// File: /workspace/github_cpp_makefile_star2_O1/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 $0x78, %rsp
movl %ecx, %ebx
movl %esi, 0xc(%rsp)
xorps %xmm0, %xmm0
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x30(%rsp)
xorl %eax, %eax
movb %al, 0x70(%rsp)
movabsq $0x60000120e, %rcx      # imm = 0x60000120E
movq %rcx, 0x20(%rsp)
movq $0x0, 0x27(%rsp)
movb %al, 0xb(%rsp)
testl %ebx, %ebx
je 0xb035
movq %rdx, %r14
movq %rdi, %r15
leaq 0x30(%rsp), %r13
xorl %eax, %eax
xorl %ebp, %ebp
movl %ebx, 0x14(%rsp)
movl %eax, 0x18(%rsp)
movl %ebx, %ecx
subl %ebp, %ecx
movl $0x1000, %eax           # imm = 0x1000
cmpl %eax, %ecx
cmovael %eax, %ecx
movq 0x8(%r15), %rdi
movl %ebp, %edx
addq %r14, %rdx
movq (%rdi), %rax
movl $0xc000, %esi           # imm = 0xC000
movl %ecx, 0x10(%rsp)
callq *0x30(%rax)
testl %eax, %eax
js 0xb03d
cmpl %ebp, %ebx
movl %ebp, 0x1c(%rsp)
jne 0xae6c
xorl %eax, %eax
jmp 0xae9b
movl 0x10(%rsp), %ecx
xorl %edx, %edx
movl %ebp, %esi
xorl %eax, %eax
movl %esi, %edi
movzbl (%r14,%rdi), %edi
shll $0x8, %edi
leal 0x1(%rsi), %r8d
movzbl (%r14,%r8), %r8d
orl %edi, %r8d
addl %r8d, %eax
addq $0x2, %rdx
addl $0x2, %esi
cmpq %rcx, %rdx
jb 0xae76
movl 0x10(%rsp), %ecx
movb %ch, 0x25(%rsp)
movb %cl, 0x26(%rsp)
movl 0xc(%rsp), %edx
movl %edx, %ecx
shrl $0x10, %ecx
movb %cl, 0x27(%rsp)
movb %dh, 0x28(%rsp)
movb %ah, 0x29(%rsp)
movb %al, 0x2a(%rsp)
movq 0x8(%r15), %rdi
movq (%rdi), %rax
leaq 0x20(%rsp), %rsi
movl $0xb, %edx
callq *0x38(%rax)
testl %eax, %eax
leaq 0x163b4(%rip), %rbx     # 0x21291
js 0xb080
movl $0x13880, %edi          # imm = 0x13880
callq 0x5170
movl $0xffffff9c, %r12d      # imm = 0xFFFFFF9C
xorps %xmm0, %xmm0
movaps %xmm0, 0x60(%rsp)
movaps %xmm0, 0x50(%rsp)
movaps %xmm0, 0x40(%rsp)
movaps %xmm0, 0x30(%rsp)
movb $0x0, 0x70(%rsp)
movq 0x8(%r15), %rdi
movq (%rdi), %rax
movl $0x5096, %esi           # imm = 0x5096
movq %r13, %rdx
movl $0x1, %ecx
callq *0x20(%rax)
testl %eax, %eax
jns 0xaf5c
cmpb $0x1, (%rbx)
jne 0xaf5c
movq 0x16082(%rip), %rcx     # 0x20fb8
movq (%rcx), %rdi
leaq 0xce12(%rip), %rsi      # 0x17d52
leaq 0xcdbe(%rip), %rdx      # 0x17d05
movl $0xbc, %ecx
movl $0x5096, %r8d           # imm = 0x5096
movl %eax, %r9d
xorl %eax, %eax
callq 0x5180
cmpb $-0x56, 0x30(%rsp)
je 0xaff4
movl $0x7d0, %edi            # imm = 0x7D0
callq 0x5170
incl %r12d
jne 0xaef3
cmpb $0x1, (%rbx)
jne 0xafaf
movq 0x16032(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
movzbl 0x30(%rsp), %r9d
leaq 0xcde7(%rip), %rsi      # 0x17d7d
leaq 0xcd68(%rip), %rdx      # 0x17d05
movl $0xc5, %ecx
movl $0x5096, %r8d           # imm = 0x5096
xorl %eax, %eax
callq 0x5180
cmpb $0x1, (%rbx)
movl 0x14(%rsp), %ebx
jne 0xafe6
movq 0x15ff9(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xcde3(%rip), %rsi      # 0x17dac
leaq 0xcd35(%rip), %rdx      # 0x17d05
movl $0xc6, %ecx
movl 0x18(%rsp), %r8d
movl 0xc(%rsp), %r9d
xorl %eax, %eax
callq 0x5180
movl 0x18(%rsp), %eax
incl %eax
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
jmp 0xb022
movl 0x10(%rsp), %ebp
addl %ebp, 0x1c(%rsp)
addl %ebp, 0xc(%rsp)
movq 0x8(%r15), %rdi
movq (%rdi), %rax
movl $0x5096, %esi           # imm = 0x5096
leaq 0xb(%rsp), %rdx
movl $0x1, %ecx
callq *0x30(%rax)
xorl %r12d, %r12d
xorl %eax, %eax
movl 0x14(%rsp), %ebx
cmpl $0x5, %eax
jg 0xb088
movl 0x1c(%rsp), %ebp
cmpl %ebx, %ebp
jne 0xae2e
jmp 0xb088
movl $0xffffffff, %r12d      # imm = 0xFFFFFFFF
jmp 0xb088
movl %eax, %r12d
leaq 0x1624a(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xb088
movq 0x15f85(%rip), %rax     # 0x20fd8
movq (%rax), %rdi
movl %r12d, (%rsp)
leaq 0xcc67(%rip), %rsi      # 0x17cc8
leaq 0xcc9d(%rip), %rdx      # 0x17d05
movl 0x10(%rsp), %r8d
movl 0xc(%rsp), %r9d
movl $0xa0, %ecx
xorl %eax, %eax
callq 0x5180
jmp 0xb088
movl %eax, %r12d
cmpb $0x1, (%rbx)
je 0xb09a
movl %r12d, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x15f37(%rip), %rax     # 0x20fd8
movq (%rax), %rdi
leaq 0xcc6c(%rip), %rsi      # 0x17d17
leaq 0xcc53(%rip), %rdx      # 0x17d05
movl $0xb2, %ecx
movl %r12d, %r8d
xorl %eax, %eax
callq 0x5180
jmp 0xb088
nop