// File: /workspace/github_cpp_makefile_star2_O2/goodix[P]gdix_hid_firmware_update/gtx2/gtx2_update.cpp
// Function: GTx2Update::load_sub_firmware(unsigned int, unsigned char*, unsigned int)
int GTx2Update::load_sub_firmware(unsigned int flash_addr,
								  unsigned char *fw_data, unsigned int len)
{
	int ret = -1;
	int retry;
	unsigned int i;
	unsigned int unitlen = 0;
	unsigned char temp_buf[65] = {0};
	unsigned int load_data_len = 0;
	unsigned char buf_load_flash[15] = {0x0e, 0x12, 0x00, 0x00, 0x06};
	unsigned short check_sum = 0;
	unsigned char dummy = 0;
	int retry_load = 0;

	while (retry_load < GDIX_RETRY_TIMES && load_data_len != len) {
		unitlen = (len - load_data_len > RAM_BUFFER_SIZE)
					  ? RAM_BUFFER_SIZE
					  : (len - load_data_len);
		ret = dev->Write(FLASH_BUFFER_ADDR, &fw_data[load_data_len], unitlen);
		if (ret < 0) {
			gdix_err("Failed load fw, len %d : addr 0x%x, ret=%d\n", unitlen,
					 flash_addr, ret);
			goto load_fail;
		}

		/* inform IC to load 4K data to flash */
		for (check_sum = 0, i = 0; i < unitlen; i += 2) {
			check_sum += (fw_data[load_data_len + i] << 8) +
						 fw_data[load_data_len + i + 1];
		}
		buf_load_flash[5] = (unitlen >> 8) & 0xFF;
		buf_load_flash[6] = unitlen & 0xFF;
		buf_load_flash[7] = (flash_addr >> 16) & 0xFF;
		buf_load_flash[8] = (flash_addr >> 8) & 0xFF;
		buf_load_flash[9] = (check_sum >> 8) & 0xFF;
		buf_load_flash[10] = check_sum & 0xFF;

		ret = dev->Write(buf_load_flash, 11);
		if (ret < 0) {
			gdix_err("Failed write load flash command, ret =%d\n", ret);
			goto load_fail;
		}

		usleep(80000);
		retry = 100;
		do {
			memset(temp_buf, 0, sizeof(temp_buf));
			ret = dev->Read(FLASH_RESULT_ADDR, temp_buf, 1);
			if (ret < 0)
				gdix_dbg("Failed read 0x%x, ret=%d\n", FLASH_RESULT_ADDR, ret);
			if (temp_buf[0] == 0xAA)
				break;

			usleep(2000);
		} while (--retry);

		if (!retry) {
			gdix_dbg("Read back 0x%x(0x%x) != 0xAA\n", FLASH_RESULT_ADDR,
					 temp_buf[0]);
			gdix_dbg("Reload(%d) subFW:addr:0x%x\n", retry_load, flash_addr);
			/* firmware chechsum err */
			retry_load++;
			ret = -1;
		} else {
			load_data_len += unitlen;
			flash_addr += unitlen;
			retry_load = 0;
			dev->Write(0x5096, &dummy, 1);
			ret = 0;
		}
	}

load_fail:
	return ret;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movl %ecx, 0x20(%rsp)
movq %rdx, %r14
movq %rdi, %r15
xorps %xmm0, %xmm0
leaq 0x50(%rsp), %r12
movaps %xmm0, 0x30(%r12)
movaps %xmm0, 0x20(%r12)
movaps %xmm0, 0x10(%r12)
movaps %xmm0, (%r12)
xorl %eax, %eax
movabsq $0x60000120e, %rcx      # imm = 0x60000120E
leaq 0x28(%rsp), %rdx
movq %rcx, (%rdx)
andq $0x0, 0x7(%rdx)
movb %al, 0x40(%r12)
leaq 0x17(%rsp), %rcx
movb %al, (%rcx)
pushq $-0x1
popq %rbx
pushq $0x1
popq %r13
xorl %ecx, %ecx
movl 0x20(%rsp), %eax
movl %eax, %ebp
subl %ecx, %ebp
movl $0x1000, %eax           # imm = 0x1000
cmpl %eax, %ebp
cmovael %eax, %ebp
movl %ecx, %edx
addq %r14, %rdx
movl %ebp, %eax
shrl $0x8, %eax
movl %eax, 0x44(%rsp)
movl %esi, %eax
shrl $0x10, %eax
movl %eax, 0x40(%rsp)
movl %esi, %eax
shrl $0x8, %eax
movl %eax, 0x3c(%rsp)
xorl %eax, %eax
movl %esi, 0x18(%rsp)
movl %ecx, 0x1c(%rsp)
movq %rdx, 0x48(%rsp)
cmpl $0x5, %eax
ja 0x97b6
cmpl %ecx, 0x20(%rsp)
je 0x97b6
movl %eax, 0x24(%rsp)
movq 0x8(%r15), %rdi
movq (%rdi), %rax
movl $0xc000, %esi           # imm = 0xC000
movl %ebp, %ecx
callq *0x30(%rax)
testl %eax, %eax
js 0x9769
xorl %ecx, %ecx
movl 0x1c(%rsp), %eax
movl %eax, %edx
xorl %eax, %eax
cmpq %rbp, %rcx
jae 0x95c7
movl %edx, %esi
movzbl (%r14,%rsi), %esi
shll $0x8, %esi
leal 0x1(%rdx), %edi
movzbl (%r14,%rdi), %edi
orl %esi, %edi
addl %edi, %eax
addq $0x2, %rcx
addl $0x2, %edx
jmp 0x95a3
movl 0x44(%rsp), %ecx
movb %cl, 0x2d(%rsp)
movb %bpl, 0x2e(%rsp)
movl 0x40(%rsp), %ecx
movb %cl, 0x2f(%rsp)
movl 0x3c(%rsp), %ecx
movb %cl, 0x30(%rsp)
movb %ah, 0x31(%rsp)
movb %al, 0x32(%rsp)
movq 0x8(%r15), %rdi
movq (%rdi), %rax
leaq 0x28(%rsp), %rsi
pushq $0xb
popq %rdx
callq *0x38(%rax)
testl %eax, %eax
js 0x97a8
movl $0x13880, %edi          # imm = 0x13880
callq 0x5170
pushq $-0x64
popq %rbx
xorps %xmm0, %xmm0
movaps %xmm0, 0x80(%rsp)
movaps %xmm0, 0x70(%rsp)
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movb $0x0, 0x90(%rsp)
movq 0x8(%r15), %rdi
movq (%rdi), %rax
movl $0x5096, %esi           # imm = 0x5096
movq %r12, %rdx
movl %r13d, %ecx
callq *0x20(%rax)
testl %eax, %eax
jns 0x9687
leaq 0x16c3c(%rip), %rcx     # 0x20291
cmpb $0x1, (%rcx)
jne 0x9687
movq 0x16957(%rip), %rcx     # 0x1ffb8
movq (%rcx), %rdi
leaq 0xd686(%rip), %rsi      # 0x16cf1
leaq 0xd632(%rip), %rdx      # 0x16ca4
movl $0xbc, %ecx
movl $0x5096, %r8d           # imm = 0x5096
movl %eax, %r9d
xorl %eax, %eax
callq 0x5180
cmpb $-0x56, 0x50(%rsp)
je 0x9733
movl $0x7d0, %edi            # imm = 0x7D0
callq 0x5170
incl %ebx
jne 0x9613
leaq 0x16be6(%rip), %rax     # 0x20291
movb (%rax), %al
cmpb $0x1, %al
jne 0x96ea
movq 0x16900(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
movzbl 0x50(%rsp), %r9d
leaq 0xd654(%rip), %rsi      # 0x16d1c
leaq 0xd5d5(%rip), %rdx      # 0x16ca4
movl $0xc5, %ecx
movl $0x5096, %r8d           # imm = 0x5096
xorl %eax, %eax
callq 0x5180
leaq 0x16ba9(%rip), %rax     # 0x20291
movb (%rax), %al
testb $0x1, %al
je 0x971c
movq 0x168c3(%rip), %rax     # 0x1ffb8
movq (%rax), %rdi
leaq 0xd64c(%rip), %rsi      # 0x16d4b
leaq 0xd59e(%rip), %rdx      # 0x16ca4
movl $0xc6, %ecx
movl 0x24(%rsp), %r8d
movl 0x18(%rsp), %r9d
xorl %eax, %eax
callq 0x5180
movl 0x24(%rsp), %eax
incl %eax
pushq $-0x1
popq %rbx
movl 0x1c(%rsp), %ecx
movq 0x48(%rsp), %rdx
jmp 0x9569
movl 0x1c(%rsp), %r12d
addl %ebp, %r12d
movl 0x18(%rsp), %ebx
addl %ebp, %ebx
movq 0x8(%r15), %rdi
movq (%rdi), %rax
movl $0x5096, %esi           # imm = 0x5096
leaq 0x17(%rsp), %rdx
movl %r13d, %ecx
callq *0x30(%rax)
movl %r12d, %ecx
leaq 0x50(%rsp), %r12
movl %ebx, %esi
xorl %ebx, %ebx
jmp 0x9528
movl %eax, %ebx
leaq 0x16b1f(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
jne 0x97b6
movq 0x1685a(%rip), %rax     # 0x1ffd8
movq (%rax), %rdi
movl %ebx, (%rsp)
leaq 0xd4dc(%rip), %rsi      # 0x16c67
leaq 0xd512(%rip), %rdx      # 0x16ca4
movl $0xa0, %ecx
movl %ebp, %r8d
movl 0x18(%rsp), %r9d
xorl %eax, %eax
callq 0x5180
jmp 0x97b6
movl %eax, %ebx
leaq 0x16ae0(%rip), %rax     # 0x20291
cmpb $0x1, (%rax)
je 0x97ca
movl %ebx, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x16807(%rip), %rax     # 0x1ffd8
movq (%rax), %rdi
leaq 0xd4db(%rip), %rsi      # 0x16cb6
leaq 0xd4c2(%rip), %rdx      # 0x16ca4
movl $0xb2, %ecx
movl %ebx, %r8d
xorl %eax, %eax
callq 0x5180
jmp 0x97b6
nop