// File: /workspace/github_c_makefile_star2_O2/sTeeLM[P]dwipe/method.c
// Function: dwipe_runmethod
int dwipe_runmethod( DWIPE_METHOD_SIGNATURE, dwipe_pattern_t* patterns )
{
/**
 * Writes patterns to the device.
 *
 */

	/* The result holder. */
	int r;

	/* An index variable. */
	int i = 0;

	/* The zero-fill pattern for the final pass of most methods. */
	dwipe_pattern_t pattern_zero = { 1, "\x00" };


	/* Create the PRNG state buffer. */
	c->prng_seed.length = DWIPE_KNOB_PRNG_STATE_LENGTH;
	c->prng_seed.s = malloc( c->prng_seed.length );

	/* Check the memory allocation. */
	if( ! c->prng_seed.s )
	{
		dwipe_perror( errno, __FUNCTION__, "malloc" );
		dwipe_log( DWIPE_LOG_FATAL, "Unable to allocate memory for the prng seed buffer." );
		return -1;
	}

	/* Count the number of patterns in the array. */
	while( patterns[i].length ) { i += 1; }
 

	/* Tell the parent the number of device passes that will be run in one round. */
	c->pass_count = i;

	/* Set the number of bytes that will be written across all passes in one round. */
	c->pass_size = c->pass_count * c->device_size;

	if( dwipe_options.verify == DWIPE_VERIFY_ALL )
	{
		/* We must read back all passes, so double the byte count. */
		c->pass_size *= 2;
	}


	/* Tell the parent the number of rounds that will be run. */
	c->round_count = dwipe_options.rounds;

	/* Set the number of bytes that will be written across all rounds. */
	c->round_size = c->round_count * c->pass_size;

	/* The final pass is always a zero fill, except ops2 which is random. */
	c->round_size += c->device_size;

	if( dwipe_options.verify == DWIPE_VERIFY_LAST || dwipe_options.verify == DWIPE_VERIFY_ALL )
	{
		/* We must read back the last pass to verify it. */
		c->round_size += c->device_size;
	}


	/* Initialize the working round counter. */
	c->round_working = 0;

	dwipe_log( DWIPE_LOG_NOTICE, "Invoking method '%s' on device '%s'.", \
	  dwipe_method_label( dwipe_options.method ), c->device_name );

	while( c->round_working < c->round_count )
	{
		/* Increment the round counter. */
		c->round_working += 1;

		dwipe_log( DWIPE_LOG_NOTICE, "Starting round %i of %i on device '%s'.", \
		  c->round_working, c->round_count, c->device_name );

		/* Initialize the working pass counter. */
		c->pass_working = 0;

		for( i = 0 ; i < c->pass_count ; i++ )
		{
			/* Increment the working pass. */
			c->pass_working += 1;

			dwipe_log( DWIPE_LOG_NOTICE, "Starting pass %i of %i, round %i of %i, on device '%s'.", \
			  c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name );

			if( patterns[i].length == 0 )
			{
				/* Caught insanity. */
				dwipe_log( DWIPE_LOG_SANITY, "dwipe_runmethod: A non-terminating pattern element has zero length." );
				return -1;
			}
	
			if( patterns[i].length > 0 )
			{

				/* Write a static pass. */
				c->pass_type = DWIPE_PASS_WRITE;
				r = dwipe_static_pass( c, &patterns[i] );
				c->pass_type = DWIPE_PASS_NONE;
	
				/* Check for a fatal error. */
				if( r < 0 ) { return r; }
	
				if( dwipe_options.verify == DWIPE_VERIFY_ALL )
				{

					dwipe_log( DWIPE_LOG_NOTICE, "Verifying pass %i of %i, round %i of %i, on device '%s'.", \
			  		  c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name );

					/* Verify this pass. */
					c->pass_type = DWIPE_PASS_VERIFY;
					r = dwipe_static_verify( c, &patterns[i] );
					c->pass_type = DWIPE_PASS_NONE;
	
					/* Check for a fatal error. */
					if( r < 0 ) { return r; }

					dwipe_log( DWIPE_LOG_NOTICE, "Verified pass %i of %i, round %i of %i, on device '%s'.", \
			  		  c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name );
				}
		
			} /* static pass */
	
			else
			{
				c->pass_type = DWIPE_PASS_WRITE;

				/* Seed the PRNG. */
				r = read( c->entropy_fd, c->prng_seed.s, c->prng_seed.length );
	
				/* Check the result. */
				if( r < 0 )
				{
					c->pass_type = DWIPE_PASS_NONE;
					dwipe_perror( errno, __FUNCTION__, "read" );
					dwipe_log( DWIPE_LOG_FATAL, "Unable to seed the PRNG." );
					return -1;
				}
	
				/* Check for a partial read. */
				if( r != c->prng_seed.length )
				{
					/* TODO: Handle partial reads. */
					dwipe_log( DWIPE_LOG_FATAL, "Insufficient entropy is available." );
					return -1;
				}
	
				/* Write the random pass. */
				r = dwipe_random_pass( c );
				c->pass_type = DWIPE_PASS_NONE;
	
				/* Check for a fatal error. */
				if( r < 0 ) { return r; }
	
				if( dwipe_options.verify == DWIPE_VERIFY_ALL )
				{
					dwipe_log( DWIPE_LOG_NOTICE, "Verifying pass %i of %i, round %i of %i, on device '%s'.", \
			  		  c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name );

					/* Verify this pass. */
					c->pass_type = DWIPE_PASS_VERIFY;
					r = dwipe_random_verify( c );
					c->pass_type = DWIPE_PASS_NONE;
	
					/* Check for a fatal error. */
					if( r < 0 ) { return r; }

					dwipe_log( DWIPE_LOG_NOTICE, "Verified pass %i of %i, round %i of %i, on device '%s'.", \
			  		  c->pass_working, c->pass_count, c->round_working, c->round_count, dwipe_method_label( dwipe_options.method ) );
				}
	
			} /* random pass */
	
			dwipe_log( DWIPE_LOG_NOTICE, "Finished pass %i of %i, round %i of %i, on device '%s'.", \
			  c->pass_working, c->pass_count, c->round_working, c->round_count, c->device_name );

		} /* for passes */

		dwipe_log( DWIPE_LOG_NOTICE, "Finished round %i of %i on device '%s'.", \
		  c->round_working, c->round_count, c->device_name );
	
	} /* while rounds */


	if( dwipe_options.method == &dwipe_ops2 )
	{
		/* NOTE: The OPS-II method specifically requires that a random pattern be left on the device. */

		/* Tell the parent that we are running the final pass. */
		c->pass_type = DWIPE_PASS_FINAL_OPS2;

		/* Seed the PRNG. */
		r = read( c->entropy_fd, c->prng_seed.s, c->prng_seed.length );
	
		/* Check the result. */
		if( r < 0 )
		{
			dwipe_perror( errno, __FUNCTION__, "read" );
			dwipe_log( DWIPE_LOG_FATAL, "Unable to seed the PRNG." );
			return -1;
		}
	
		/* Check for a partial read. */
		if( r != c->prng_seed.length )
		{
			/* TODO: Handle partial reads. */
			dwipe_log( DWIPE_LOG_FATAL, "Insufficient entropy is available." );
			return -1;
		}
	
		dwipe_log( DWIPE_LOG_NOTICE, "Writing final random pattern to '%s'.", c->device_name );

		/* The final ops2 pass. */
		r = dwipe_random_pass( c );

		/* Check for a fatal error. */
		if( r < 0 ) { return r; }

		if( dwipe_options.verify == DWIPE_VERIFY_LAST || dwipe_options.verify == DWIPE_VERIFY_ALL )
		{
			dwipe_log( DWIPE_LOG_NOTICE, "Verifying the final random pattern on '%s' is empty.", c->device_name );

			/* Verify the final zero pass. */
			r = dwipe_random_verify( c );

			/* Check for a fatal error. */
			if( r < 0 ) { return r; }

			dwipe_log( DWIPE_LOG_NOTICE, "Verified the final random pattern on '%s' is empty.", c->device_name );
		}

		dwipe_log( DWIPE_LOG_NOTICE, "Wrote final random pattern to '%s'.", c->device_name );

	} /* final ops2 */


	else
	{
		/* Tell the user that we are on the final pass. */
		c->pass_type = DWIPE_PASS_FINAL_BLANK;

		dwipe_log( DWIPE_LOG_NOTICE, "Blanking device '%s'.", c->device_name );

		/* The final zero pass. */
		r = dwipe_static_pass( c, &pattern_zero );
	
		/* Check for a fatal error. */
		if( r < 0 ) { return r; }
	
	
		if( dwipe_options.verify == DWIPE_VERIFY_LAST || dwipe_options.verify == DWIPE_VERIFY_ALL )
		{
			dwipe_log( DWIPE_LOG_NOTICE, "Verifying that '%s' is empty.", c->device_name );
	
			/* Verify the final zero pass. */
			r = dwipe_static_verify( c, &pattern_zero );
	
			/* Check for a fatal error. */
			if( r < 0 ) { return r; }
	
			dwipe_log( DWIPE_LOG_NOTICE, "Verified that '%s' is empty.", c->device_name );
		}

		dwipe_log( DWIPE_LOG_NOTICE, "Blanked device '%s'.", c->device_name );

	} /* final blank */
	
	/* Release the state buffer. */
	c->prng_seed.length = 0;
	free( c->prng_seed.s );
	
	/* Tell the parent that we have fininshed the final pass. */
	c->pass_type = DWIPE_PASS_NONE;

	if( c->verify_errors > 0 )
	{
		/* We finished, but with non-fatal verification errors. */
		dwipe_log( DWIPE_LOG_ERROR, "%llu verification errors on device '%s'.", c->verify_errors, c->device_name );
	}

	if( c->pass_errors > 0 )
	{
		/* We finished, but with non-fatal wipe errors. */
		dwipe_log( DWIPE_LOG_ERROR, "%llu wipe errors on device '%s'.", c->pass_errors, c->device_name );
	}

	/* FIXME: The 'round_errors' context member is not being used. */

	if( c->pass_errors > 0 || c->round_errors > 0 || c->verify_errors > 0 )
	{
		/* We finished, but with non-fatal errors. */
		return 1;
	}
	
	/* We finished successfully. */
	return 0;	
	
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x38, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movups 0x8190(%rip), %xmm0     # 0xfd60
movaps %xmm0, 0x20(%rsp)
movq $0x200, 0x320(%rdi) # imm = 0x200
movl $0x200, %edi            # imm = 0x200
callq 0x3300
movq %rax, 0x328(%rbx)
testq %rax, %rax
je 0x7f58
pushq $-0x1
popq %rax
movq %r14, %rcx
incq %rax
cmpl $0x0, (%rcx)
leaq 0x10(%rcx), %rcx
jne 0x7c00
movl %eax, 0x2e8(%rbx)
movq 0x230(%rbx), %rcx
imulq %rcx, %rax
movq %rax, 0x300(%rbx)
leaq 0x8c15(%rip), %r15      # 0x10840
movl 0x28(%r15), %edx
cmpl $0x2, %edx
jne 0x7c3e
addq %rax, %rax
movq %rax, 0x300(%rbx)
movslq 0x20(%r15), %rsi
movl %esi, 0x33c(%rbx)
imulq %rsi, %rax
addq %rcx, %rax
decl %edx
xorl %esi, %esi
cmpl $0x2, %edx
cmovaeq %rsi, %rcx
addq %rax, %rcx
movq %rcx, 0x350(%rbx)
andl $0x0, 0x360(%rbx)
movq 0x10(%r15), %rdi
callq 0x7630
movq 0x228(%rbx), %rcx
leaq 0x4969(%rip), %rsi      # 0xc5eb
pushq $0x3
popq %rbp
movl %ebp, %edi
movq %rax, %rdx
xorl %eax, %eax
callq 0x73a8
leaq 0x4978(%rip), %rsi      # 0xc610
movq %r14, 0x18(%rsp)
movl 0x33c(%rbx), %ecx
movl 0x360(%rbx), %edx
cmpl %ecx, %edx
jge 0x7fc1
incl %edx
movl %edx, 0x360(%rbx)
movq 0x228(%rbx), %r8
movl %ebp, %edi
xorl %eax, %eax
callq 0x73a8
andl $0x0, 0x30c(%rbx)
xorl %r12d, %r12d
movslq 0x2e8(%rbx), %rcx
cmpq %rcx, %r12
jge 0x7f24
movl 0x30c(%rbx), %edx
incl %edx
movl %edx, 0x30c(%rbx)
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
movq %rax, (%rsp)
movl %ebp, %edi
leaq 0x4925(%rip), %rsi      # 0xc638
xorl %eax, %eax
callq 0x73a8
cmpl $0x0, (%r14)
je 0x7f7d
movl $0x1, 0x308(%rbx)
jle 0x7de5
movq %rbx, %rdi
movq %r14, %rsi
callq 0x94c7
andl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x81c3
cmpl $0x2, 0x28(%r15)
jne 0x7ee3
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
movq %rax, (%rsp)
movl %ebp, %edi
leaq 0x492d(%rip), %rsi      # 0xc6b4
xorl %eax, %eax
callq 0x73a8
movl $0x2, 0x308(%rbx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x9196
andl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x81c3
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
movq %rax, (%rsp)
movl %ebp, %edi
leaq 0x490d(%rip), %rsi      # 0xc6ed
jmp 0x7edc
movl 0x2d8(%rbx), %edi
movq 0x328(%rbx), %rsi
movq 0x320(%rbx), %rdx
callq 0x3240
testl %eax, %eax
js 0x7f97
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
cmpq 0x320(%rbx), %rax
jne 0x81d8
movq %rbx, %rdi
callq 0x8ee2
andl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x81c3
cmpl $0x2, 0x28(%r15)
jne 0x7ee3
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
movq %rax, (%rsp)
movl %ebp, %edi
leaq 0x484c(%rip), %rsi      # 0xc6b4
xorl %eax, %eax
callq 0x73a8
movl $0x2, 0x308(%rbx)
movq %rbx, %rdi
callq 0x8bc8
andl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x81c3
movl 0x2e8(%rbx), %eax
movl %eax, 0x14(%rsp)
movl 0x30c(%rbx), %r13d
movl 0x360(%rbx), %eax
movl %eax, 0x10(%rsp)
movl 0x33c(%rbx), %eax
movl %eax, 0xc(%rsp)
movq 0x10(%r15), %rdi
callq 0x7630
movq %rax, (%rsp)
movl %ebp, %edi
leaq 0x4822(%rip), %rsi      # 0xc6ed
movl %r13d, %edx
movl 0x14(%rsp), %ecx
movl 0x10(%rsp), %r8d
movl 0xc(%rsp), %r9d
xorl %eax, %eax
callq 0x73a8
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
movq %rax, (%rsp)
movl %ebp, %edi
leaq 0x4850(%rip), %rsi      # 0xc761
xorl %eax, %eax
callq 0x73a8
incq %r12
addq $0x10, %r14
jmp 0x7cd3
movl 0x360(%rbx), %edx
movl 0x33c(%rbx), %ecx
movq 0x228(%rbx), %r8
movl %ebp, %edi
leaq 0x4859(%rip), %rsi      # 0xc799
xorl %eax, %eax
callq 0x73a8
movq 0x18(%rsp), %r14
leaq 0x46bd(%rip), %rsi      # 0xc610
jmp 0x7c9d
callq 0x3070
movl (%rax), %edi
leaq 0x4641(%rip), %rsi      # 0xc5a7
leaq 0x2c43(%rip), %rdx      # 0xabb0
callq 0x7600
leaq 0x463e(%rip), %rsi      # 0xc5b7
pushq $0x6
jmp 0x7f86
leaq 0x46ec(%rip), %rsi      # 0xc670
pushq $0x7
popq %rdi
xorl %eax, %eax
callq 0x73a8
pushq $-0x1
popq %r13
jmp 0x81c6
andl $0x0, 0x308(%rbx)
callq 0x3070
movl (%rax), %edi
leaq 0x45fb(%rip), %rsi      # 0xc5a7
leaq 0x44d4(%rip), %rdx      # 0xc487
callq 0x7600
leaq 0x4766(%rip), %rsi      # 0xc725
jmp 0x7f79
leaq -0x604(%rip), %rax      # 0x79c4
cmpq %rax, 0x10(%r15)
je 0x8108
movl $0x3, 0x308(%rbx)
movq 0x228(%rbx), %rdx
leaq 0x488a(%rip), %rsi      # 0xc874
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x73a8
leaq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0x94c7
testl %eax, %eax
js 0x81c3
movl 0x28(%r15), %eax
decl %eax
cmpl $0x1, %eax
ja 0x8059
movq 0x228(%rbx), %rdx
leaq 0x4868(%rip), %rsi      # 0xc88a
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x73a8
leaq 0x20(%rsp), %rsi
movq %rbx, %rdi
callq 0x9196
testl %eax, %eax
js 0x81c3
movq 0x228(%rbx), %rdx
leaq 0x4859(%rip), %rsi      # 0xc8a8
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x73a8
movq 0x228(%rbx), %rdx
leaq 0x485e(%rip), %rsi      # 0xc8c5
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x73a8
andq $0x0, 0x320(%rbx)
movq 0x328(%rbx), %rdi
callq 0x3060
andl $0x0, 0x308(%rbx)
movq 0x588(%rbx), %rdx
testq %rdx, %rdx
je 0x80b0
movq 0x228(%rbx), %rcx
leaq 0x4834(%rip), %rsi      # 0xc8da
pushq $0x5
popq %rdi
xorl %eax, %eax
callq 0x73a8
movq 0x2f8(%rbx), %rdx
pushq $0x1
popq %r13
testq %rdx, %rdx
je 0x80e6
movq 0x228(%rbx), %rcx
leaq 0x4835(%rip), %rsi      # 0xc903
pushq $0x5
popq %rdi
xorl %eax, %eax
callq 0x73a8
cmpq $0x0, 0x2f8(%rbx)
jne 0x81c6
cmpq $0x0, 0x348(%rbx)
jne 0x81c6
xorl %r13d, %r13d
cmpq $0x0, 0x588(%rbx)
setne %r13b
jmp 0x81c6
movl $0x4, 0x308(%rbx)
movl 0x2d8(%rbx), %edi
movq 0x328(%rbx), %rsi
movq 0x320(%rbx), %rdx
callq 0x3240
testl %eax, %eax
js 0x7f9e
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
cmpq 0x320(%rbx), %rax
jne 0x81d8
movq 0x228(%rbx), %rdx
leaq 0x466e(%rip), %rsi      # 0xc7c1
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x73a8
movq %rbx, %rdi
callq 0x8ee2
testl %eax, %eax
js 0x81c3
movl 0x28(%r15), %eax
decl %eax
cmpl $0x1, %eax
ja 0x81b0
movq 0x228(%rbx), %rdx
leaq 0x4665(%rip), %rsi      # 0xc7e7
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x73a8
movq %rbx, %rdi
callq 0x8bc8
testl %eax, %eax
js 0x81c3
movq 0x228(%rbx), %rdx
leaq 0x4676(%rip), %rsi      # 0xc81c
pushq $0x3
popq %rdi
xorl %eax, %eax
callq 0x73a8
movq 0x228(%rbx), %rdx
leaq 0x4692(%rip), %rsi      # 0xc850
jmp 0x8067
movl %eax, %r13d
movl %r13d, %eax
addq $0x38, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x455f(%rip), %rsi      # 0xc73e
jmp 0x7f79