// File: /workspace/github_c_makefile_star2_O1/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 0x8aef(%rip), %xmm0     # 0x10d60
movaps %xmm0, 0x10(%rsp)
movq $0x200, 0x320(%rdi) # imm = 0x200
movl $0x200, %edi            # imm = 0x200
callq 0x32f0
movq %rax, 0x328(%rbx)
testq %rax, %rax
je 0x837a
movq $-0x1, %rax
movq %r14, %rcx
incq %rax
cmpl $0x0, (%rcx)
leaq 0x10(%rcx), %rcx
jne 0x82a5
movl %eax, 0x2e8(%rbx)
movq 0x230(%rbx), %rcx
imulq %rcx, %rax
movq %rax, 0x300(%rbx)
leaq 0x9570(%rip), %r13      # 0x11840
movl 0x28(%r13), %edx
cmpl $0x2, %edx
jne 0x82e3
addq %rax, %rax
movq %rax, 0x300(%rbx)
movslq 0x20(%r13), %rax
movl %eax, 0x33c(%rbx)
imulq 0x300(%rbx), %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 -0x625(%rip), %rcx      # 0x7cfd
cmpq %rcx, %rax
movq %r14, 0x8(%rsp)
je 0x83a0
leaq -0x524(%rip), %rcx      # 0x7e0f
cmpq %rcx, %rax
je 0x83a9
leaq -0x46d(%rip), %rcx      # 0x7ed2
cmpq %rcx, %rax
je 0x83b2
leaq -0x2ff(%rip), %rcx      # 0x804c
cmpq %rcx, %rax
je 0x83bb
leaq -0x13e(%rip), %rcx      # 0x8219
cmpq %rcx, %rax
je 0x83c4
leaq -0x124(%rip), %rcx      # 0x823f
cmpq %rcx, %rax
leaq 0x932b(%rip), %rcx      # 0x11698
leaq 0x932c(%rip), %rax      # 0x116a0
cmoveq %rcx, %rax
jmp 0x83cb
callq 0x3070
movl (%rax), %edi
leaq 0x521f(%rip), %rsi      # 0xd5a7
leaq 0x3821(%rip), %rdx      # 0xbbb0
callq 0x7c3f
leaq 0x521c(%rip), %rsi      # 0xd5b7
jmp 0x89a0
leaq 0x92c9(%rip), %rax      # 0x11670
jmp 0x83cb
leaq 0x92c8(%rip), %rax      # 0x11678
jmp 0x83cb
leaq 0x92c7(%rip), %rax      # 0x11680
jmp 0x83cb
leaq 0x92c6(%rip), %rax      # 0x11688
jmp 0x83cb
leaq 0x92c5(%rip), %rax      # 0x11690
movq (%rax), %rdx
movq 0x228(%rbx), %rcx
leaq 0x520f(%rip), %rsi      # 0xd5eb
movl $0x3, %edi
xorl %eax, %eax
callq 0x79f8
movl 0x33c(%rbx), %ecx
movl 0x360(%rbx), %edx
cmpl %ecx, %edx
jge 0x8745
leaq 0x520d(%rip), %rsi      # 0xd610
leaq 0x522e(%rip), %r12      # 0xd638
leaq 0x5350(%rip), %r15      # 0xd761
incl %edx
movl %edx, 0x360(%rbx)
movq 0x228(%rbx), %r8
movl $0x3, %edi
xorl %eax, %eax
callq 0x79f8
movl $0x0, 0x30c(%rbx)
movl 0x2e8(%rbx), %ecx
testl %ecx, %ecx
jle 0x8704
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 0x79f8
cmpl $0x0, (%r14)
je 0x88a6
jle 0x8548
movl $0x1, 0x308(%rbx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x9bc2
movl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x89b1
cmpl $0x2, 0x28(%r13)
jne 0x86b9
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 0x51c0(%rip), %rsi      # 0xd6b4
xorl %eax, %eax
callq 0x79f8
movl $0x2, 0x308(%rbx)
movq %rbx, %rdi
movq %r14, %rsi
callq 0x984a
movl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x89b1
movl 0x30c(%rbx), %edx
movl 0x2e8(%rbx), %ecx
movl 0x360(%rbx), %r8d
movl 0x33c(%rbx), %r9d
movq 0x228(%rbx), %rax
jmp 0x86a2
movl $0x1, 0x308(%rbx)
movl 0x2d8(%rbx), %edi
movq 0x328(%rbx), %rsi
movq 0x320(%rbx), %rdx
callq 0x3240
testl %eax, %eax
js 0x8975
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
cmpq 0x320(%rbx), %rax
jne 0x88b7
movq %rbx, %rdi
callq 0x9581
movl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x89b1
cmpl $0x2, 0x28(%r13)
jne 0x86b9
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 0x50d9(%rip), %rsi      # 0xd6b4
xorl %eax, %eax
callq 0x79f8
movl $0x2, 0x308(%rbx)
movq %rbx, %rdi
callq 0x9244
movl $0x0, 0x308(%rbx)
testl %eax, %eax
js 0x89b1
movq 0x10(%r13), %rax
leaq 0x905f(%rip), %rsi      # 0x11670
leaq -0x91b(%rip), %rcx      # 0x7cfd
cmpq %rcx, %rax
je 0x8685
leaq 0x9054(%rip), %rsi      # 0x11678
leaq -0x81c(%rip), %rcx      # 0x7e0f
cmpq %rcx, %rax
je 0x8685
leaq 0x9049(%rip), %rsi      # 0x11680
leaq -0x76c(%rip), %rcx      # 0x7ed2
cmpq %rcx, %rax
je 0x8685
leaq 0x903e(%rip), %rsi      # 0x11688
leaq -0x605(%rip), %rcx      # 0x804c
cmpq %rcx, %rax
je 0x8685
leaq 0x9033(%rip), %rsi      # 0x11690
leaq -0x44b(%rip), %rcx      # 0x8219
cmpq %rcx, %rax
je 0x8685
leaq -0x431(%rip), %rcx      # 0x823f
cmpq %rcx, %rax
leaq 0x9026(%rip), %rsi      # 0x116a0
leaq 0x9017(%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 0x503b(%rip), %rsi      # 0xd6ed
xorl %eax, %eax
callq 0x79f8
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 0x79f8
incq %rbp
movslq 0x2e8(%rbx), %rcx
addq $0x10, %r14
cmpq %rcx, %rbp
jl 0x844b
movl 0x360(%rbx), %edx
movl 0x33c(%rbx), %ecx
movq 0x228(%rbx), %r8
movl $0x3, %edi
leaq 0x5076(%rip), %rsi      # 0xd799
xorl %eax, %eax
callq 0x79f8
movl 0x33c(%rbx), %ecx
movl 0x360(%rbx), %edx
cmpl %ecx, %edx
leaq 0x4ed1(%rip), %rsi      # 0xd610
jl 0x8411
leaq -0x700(%rip), %rax      # 0x804c
cmpq %rax, 0x10(%r13)
je 0x87f3
movl $0x3, 0x308(%rbx)
movq 0x228(%rbx), %rdx
leaq 0x5106(%rip), %rsi      # 0xd874
movl $0x3, %edi
xorl %eax, %eax
callq 0x79f8
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x9bc2
testl %eax, %eax
js 0x89b1
movl 0x28(%r13), %eax
decl %eax
cmpl $0x1, %eax
ja 0x88c3
movq 0x228(%rbx), %rdx
leaq 0x50de(%rip), %rsi      # 0xd88a
movl $0x3, %edi
xorl %eax, %eax
callq 0x79f8
leaq 0x10(%rsp), %rsi
movq %rbx, %rdi
callq 0x984a
testl %eax, %eax
js 0x89b1
leaq 0x50f1(%rip), %r14      # 0xd8c5
leaq 0x50cd(%rip), %rsi      # 0xd8a8
movq 0x228(%rbx), %rdx
movl $0x3, %edi
xorl %eax, %eax
callq 0x79f8
jmp 0x88ca
movl $0x4, 0x308(%rbx)
movl 0x2d8(%rbx), %edi
movq 0x328(%rbx), %rsi
movq 0x320(%rbx), %rdx
callq 0x3240
testl %eax, %eax
js 0x897f
andl $0x7fffffff, %eax       # imm = 0x7FFFFFFF
cmpq 0x320(%rbx), %rax
jne 0x88b7
movq 0x228(%rbx), %rdx
leaq 0x4f83(%rip), %rsi      # 0xd7c1
movl $0x3, %edi
xorl %eax, %eax
callq 0x79f8
movq %rbx, %rdi
callq 0x9581
testl %eax, %eax
js 0x89b1
movl 0x28(%r13), %eax
decl %eax
cmpl $0x1, %eax
ja 0x89c0
movq 0x228(%rbx), %rdx
leaq 0x4f70(%rip), %rsi      # 0xd7e7
movl $0x3, %edi
xorl %eax, %eax
callq 0x79f8
movq %rbx, %rdi
callq 0x9244
testl %eax, %eax
js 0x89b1
leaq 0x4fb6(%rip), %r14      # 0xd850
leaq 0x4f7b(%rip), %rsi      # 0xd81c
jmp 0x87db
leaq 0x4dc3(%rip), %rsi      # 0xd670
movl $0x7, %edi
jmp 0x89a5
leaq 0x4e80(%rip), %rsi      # 0xd73e
jmp 0x89a0
leaq 0x4ffb(%rip), %r14      # 0xd8c5
movq 0x228(%rbx), %rdx
movl $0x3, %edi
movq %r14, %rsi
xorl %eax, %eax
callq 0x79f8
movq $0x0, 0x320(%rbx)
movq 0x328(%rbx), %rdi
callq 0x3060
movl $0x0, 0x308(%rbx)
movq 0x588(%rbx), %rdx
testq %rdx, %rdx
je 0x8927
movq 0x228(%rbx), %rcx
leaq 0x4fbf(%rip), %rsi      # 0xd8da
movl $0x5, %edi
xorl %eax, %eax
callq 0x79f8
movq 0x2f8(%rbx), %rdx
testq %rdx, %rdx
je 0x894d
movq 0x228(%rbx), %rcx
leaq 0x4fc2(%rip), %rsi      # 0xd903
movl $0x5, %edi
xorl %eax, %eax
callq 0x79f8
movl $0x1, %eax
cmpq $0x0, 0x2f8(%rbx)
jne 0x89b1
cmpq $0x0, 0x348(%rbx)
jne 0x89b1
xorl %eax, %eax
cmpq $0x0, 0x588(%rbx)
setne %al
jmp 0x89b1
movl $0x0, 0x308(%rbx)
callq 0x3070
movl (%rax), %edi
leaq 0x4c1a(%rip), %rsi      # 0xd5a7
leaq 0x4af3(%rip), %rdx      # 0xd487
callq 0x7c3f
leaq 0x4d85(%rip), %rsi      # 0xd725
movl $0x6, %edi
xorl %eax, %eax
callq 0x79f8
movl $0xffffffff, %eax       # imm = 0xFFFFFFFF
addq $0x28, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
leaq 0x4e89(%rip), %r14      # 0xd850
jmp 0x88ca