// File: /workspace/github_c_makefile_star2_O3/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 $0x28, %rsp
movq %rsi, %r14
movq %rdi, %rbx
movups 0x8a63(%rip), %xmm0     # 0x10d60
movaps %xmm0, 0x10(%rsp)
movq $0x200, 0x320(%rdi) # imm = 0x200
movl $0x200, %edi            # imm = 0x200
callq 0x3300
movq %rax, 0x328(%rbx)
testq %rax, %rax
je 0x8402
movq $-0x1, %rax
movq %r14, %rcx
incq %rax
cmpl $0x0, (%rcx)
leaq 0x10(%rcx), %rcx
jne 0x8331
movl %eax, 0x2e8(%rbx)
movq 0x230(%rbx), %rcx
imulq %rcx, %rax
movq %rax, 0x300(%rbx)
leaq 0x94e4(%rip), %r13      # 0x11840
movl 0x28(%r13), %edx
cmpl $0x2, %edx
jne 0x836f
addq %rax, %rax
movq %rax, 0x300(%rbx)
movslq 0x20(%r13), %rsi
movl %esi, 0x33c(%rbx)
imulq %rsi, %rax
addq %rcx, %rax
decl %edx
xorl %esi, %esi
cmpl $0x2, %edx
cmovbq %rcx, %rsi
addq %rax, %rsi
movq %rsi, 0x350(%rbx)
movl $0x0, 0x360(%rbx)
movq 0x10(%r13), %rax
leaq -0x629(%rip), %rcx      # 0x7d81
cmpq %rcx, %rax
movq %r14, 0x8(%rsp)
je 0x8428
leaq -0x528(%rip), %rcx      # 0x7e93
cmpq %rcx, %rax
je 0x8431
leaq -0x471(%rip), %rcx      # 0x7f56
cmpq %rcx, %rax
je 0x843a
leaq -0x303(%rip), %rcx      # 0x80d0
cmpq %rcx, %rax
je 0x8443
leaq -0x13a(%rip), %rcx      # 0x82a5
cmpq %rcx, %rax
je 0x844c
leaq -0x120(%rip), %rcx      # 0x82cb
cmpq %rcx, %rax
leaq 0x92a3(%rip), %rcx      # 0x11698
leaq 0x92a4(%rip), %rax      # 0x116a0
cmoveq %rcx, %rax
jmp 0x8453
callq 0x3070
movl (%rax), %edi
leaq 0x5197(%rip), %rsi      # 0xd5a7
leaq 0x3799(%rip), %rdx      # 0xbbb0
callq 0x7cc3
leaq 0x5194(%rip), %rsi      # 0xd5b7
jmp 0x8a2b
leaq 0x9241(%rip), %rax      # 0x11670
jmp 0x8453
leaq 0x9240(%rip), %rax      # 0x11678
jmp 0x8453
leaq 0x923f(%rip), %rax      # 0x11680
jmp 0x8453
leaq 0x923e(%rip), %rax      # 0x11688
jmp 0x8453
leaq 0x923d(%rip), %rax      # 0x11690
movq (%rax), %rdx
movq 0x228(%rbx), %rcx
leaq 0x5187(%rip), %rsi      # 0xd5eb
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
movl 0x33c(%rbx), %ecx
movl 0x360(%rbx), %edx
cmpl %ecx, %edx
jge 0x87c3
leaq 0x5185(%rip), %rsi      # 0xd610
leaq 0x51a6(%rip), %r12      # 0xd638
leaq 0x52c8(%rip), %r15      # 0xd761
incl %edx
movl %edx, 0x360(%rbx)
movq 0x228(%rbx), %r8
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
movl $0x0, 0x30c(%rbx)
movl 0x2e8(%rbx), %ecx
testl %ecx, %ecx
jle 0x8782
movq 0x8(%rsp), %r14
xorl %ebp, %ebp
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 $0x3, %edi
movq %r12, %rsi
xorl %eax, %eax
callq 0x7a7c
cmpl $0x0, (%r14)
je 0x89e9
movl $0x1, 0x308(%rbx)
jle 0x85d0
movq %rbx, %rdi
movq %r14, %rsi
callq 0x9c49
movl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x8a3c
cmpl $0x2, 0x28(%r13)
jne 0x8737
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
movq %rax, (%rsp)
movl $0x3, %edi
leaq 0x5138(%rip), %rsi      # 0xd6b4
xorl %eax, %eax
callq 0x7a7c
movl $0x2, 0x308(%rbx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x98ca
movl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x8a3c
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
jmp 0x8720
movl 0x2d8(%rbx), %edi
movq 0x328(%rbx), %rsi
movq 0x320(%rbx), %rdx
callq 0x3240
testl %eax, %eax
js 0x8a00
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
cmpq 0x320(%rbx), %rax
jne 0x89f7
movq %rbx, %rdi
callq 0x9601
movl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x8a3c
cmpl $0x2, 0x28(%r13)
jne 0x8737
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
movq %rax, (%rsp)
movl $0x3, %edi
leaq 0x505b(%rip), %rsi      # 0xd6b4
xorl %eax, %eax
callq 0x7a7c
movl $0x2, 0x308(%rbx)
movq %rbx, %rdi
callq 0x92c4
movl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x8a3c
movq 0x10(%r13), %rax
leaq 0x8fe1(%rip), %rsi      # 0x11670
leaq -0x915(%rip), %rcx      # 0x7d81
cmpq %rcx, %rax
je 0x8703
leaq 0x8fd6(%rip), %rsi      # 0x11678
leaq -0x816(%rip), %rcx      # 0x7e93
cmpq %rcx, %rax
je 0x8703
leaq 0x8fcb(%rip), %rsi      # 0x11680
leaq -0x766(%rip), %rcx      # 0x7f56
cmpq %rcx, %rax
je 0x8703
leaq 0x8fc0(%rip), %rsi      # 0x11688
leaq -0x5ff(%rip), %rcx      # 0x80d0
cmpq %rcx, %rax
je 0x8703
leaq 0x8fb5(%rip), %rsi      # 0x11690
leaq -0x43d(%rip), %rcx      # 0x82a5
cmpq %rcx, %rax
je 0x8703
leaq -0x423(%rip), %rcx      # 0x82cb
cmpq %rcx, %rax
leaq 0x8fa8(%rip), %rsi      # 0x116a0
leaq 0x8f99(%rip), %rax      # 0x11698
cmoveq %rax, %rsi
movl 0x2e8(%rbx), %ecx
movl 0x30c(%rbx), %edx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq (%rsi), %rax
movq %rax, (%rsp)
movl $0x3, %edi
leaq 0x4fbd(%rip), %rsi      # 0xd6ed
xorl %eax, %eax
callq 0x7a7c
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
movq %rax, (%rsp)
movl $0x3, %edi
movq %r15, %rsi
xorl %eax, %eax
callq 0x7a7c
incq %rbp
movslq 0x2e8(%rbx), %rcx
addq $0x10, %r14
cmpq %rcx, %rbp
jl 0x84d3
movl 0x360(%rbx), %edx
movl 0x33c(%rbx), %ecx
movq 0x228(%rbx), %r8
movl $0x3, %edi
leaq 0x4ff8(%rip), %rsi      # 0xd799
xorl %eax, %eax
callq 0x7a7c
movl 0x33c(%rbx), %ecx
movl 0x360(%rbx), %edx
cmpl %ecx, %edx
leaq 0x4e53(%rip), %rsi      # 0xd610
jl 0x8499
leaq -0x6fa(%rip), %rax      # 0x80d0
cmpq %rax, 0x10(%r13)
je 0x8920
movl $0x3, 0x308(%rbx)
movq 0x228(%rbx), %rdx
leaq 0x5088(%rip), %rsi      # 0xd874
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x9c49
testl %eax, %eax
js 0x8a3c
movl 0x28(%r13), %eax
decl %eax
cmpl $0x1, %eax
ja 0x8861
movq 0x228(%rbx), %rdx
leaq 0x5064(%rip), %rsi      # 0xd88a
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x98ca
testl %eax, %eax
js 0x8a3c
movq 0x228(%rbx), %rdx
leaq 0x5053(%rip), %rsi      # 0xd8a8
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
movq 0x228(%rbx), %rdx
leaq 0x5056(%rip), %rsi      # 0xd8c5
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
movq $0x0, 0x320(%rbx)
movq 0x328(%rbx), %rdi
callq 0x3060
movl $0x0, 0x308(%rbx)
movq 0x588(%rbx), %rdx
testq %rdx, %rdx
je 0x88c2
movq 0x228(%rbx), %rcx
leaq 0x5024(%rip), %rsi      # 0xd8da
movl $0x5, %edi
xorl %eax, %eax
callq 0x7a7c
movq 0x2f8(%rbx), %rdx
testq %rdx, %rdx
je 0x88fb
movq 0x228(%rbx), %rcx
leaq 0x5027(%rip), %rsi      # 0xd903
movl $0x5, %edi
xorl %eax, %eax
callq 0x7a7c
movl $0x1, %eax
cmpq $0x0, 0x2f8(%rbx)
jne 0x8a3c
movl $0x1, %eax
cmpq $0x0, 0x348(%rbx)
jne 0x8a3c
xorl %eax, %eax
cmpq $0x0, 0x588(%rbx)
setne %al
jmp 0x8a3c
movl $0x4, 0x308(%rbx)
movl 0x2d8(%rbx), %edi
movq 0x328(%rbx), %rsi
movq 0x320(%rbx), %rdx
callq 0x3240
testl %eax, %eax
js 0x8a0a
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
cmpq 0x320(%rbx), %rax
jne 0x89f7
movq 0x228(%rbx), %rdx
leaq 0x4e56(%rip), %rsi      # 0xd7c1
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
movq %rbx, %rdi
callq 0x9601
testl %eax, %eax
js 0x8a3c
movl 0x28(%r13), %eax
decl %eax
cmpl $0x1, %eax
ja 0x89d6
movq 0x228(%rbx), %rdx
leaq 0x4e47(%rip), %rsi      # 0xd7e7
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
movq %rbx, %rdi
callq 0x92c4
testl %eax, %eax
js 0x8a3c
movq 0x228(%rbx), %rdx
leaq 0x4e52(%rip), %rsi      # 0xd81c
movl $0x3, %edi
xorl %eax, %eax
callq 0x7a7c
movq 0x228(%rbx), %rdx
leaq 0x4e6c(%rip), %rsi      # 0xd850
jmp 0x886f
leaq 0x4c80(%rip), %rsi      # 0xd670
movl $0x7, %edi
jmp 0x8a30
leaq 0x4d40(%rip), %rsi      # 0xd73e
jmp 0x8a2b
movl $0x0, 0x308(%rbx)
callq 0x3070
movl (%rax), %edi
leaq 0x4b8f(%rip), %rsi      # 0xd5a7
leaq 0x4a68(%rip), %rdx      # 0xd487
callq 0x7cc3
leaq 0x4cfa(%rip), %rsi      # 0xd725
movl $0x6, %edi
xorl %eax, %eax
callq 0x7a7c
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
nop