// File: 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
movq %rsp, %rbp
subq $0xb0, %rsp
movq %rdi, -0x8(%rbp)
movl %esi, -0xc(%rbp)
movq %rdx, -0x18(%rbp)
movl %ecx, -0x1c(%rbp)
movq -0x8(%rbp), %rax
movq %rax, -0x98(%rbp)
movl $0xffffffff, -0x20(%rbp) # imm = 0xFFFFFFFF
movl $0x0, -0x2c(%rbp)
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
movl $0x41, %edx
callq 0x50a0
movl $0x0, -0x74(%rbp)
movq 0x12860(%rip), %rax     # 0x1df40
movq %rax, -0x83(%rbp)
movl 0x1285b(%rip), %eax     # 0x1df48
movl %eax, -0x7b(%rbp)
movw 0x12855(%rip), %ax      # 0x1df4c
movw %ax, -0x77(%rbp)
movb 0x1284d(%rip), %al      # 0x1df4e
movb %al, -0x75(%rbp)
movw $0x0, -0x86(%rbp)
movb $0x0, -0x87(%rbp)
movl $0x0, -0x8c(%rbp)
xorl %eax, %eax
cmpl $0x6, -0x8c(%rbp)
movb %al, -0x99(%rbp)
jge 0xb73e
movl -0x74(%rbp), %eax
cmpl -0x1c(%rbp), %eax
setne %al
movb %al, -0x99(%rbp)
movb -0x99(%rbp), %al
testb $0x1, %al
jne 0xb74d
jmp 0xbaa5
movl -0x1c(%rbp), %eax
subl -0x74(%rbp), %eax
cmpl $0x1000, %eax           # imm = 0x1000
jbe 0xb767
movl $0x1000, %eax           # imm = 0x1000
movl %eax, -0xa0(%rbp)
jmp 0xb773
movl -0x1c(%rbp), %eax
subl -0x74(%rbp), %eax
movl %eax, -0xa0(%rbp)
movq -0x98(%rbp), %rax
movl -0xa0(%rbp), %ecx
movl %ecx, -0x2c(%rbp)
movq 0x8(%rax), %rdi
movq -0x18(%rbp), %rdx
movl -0x74(%rbp), %eax
addq %rax, %rdx
movl -0x2c(%rbp), %ecx
movq (%rdi), %rax
movl $0xc000, %esi           # imm = 0xC000
callq *0x30(%rax)
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jge 0xb7ef
jmp 0xb7aa
leaq 0x1aae8(%rip), %rax     # 0x26299
testb $0x1, (%rax)
je 0xb7e8
movq 0x1a81b(%rip), %rax     # 0x25fd8
movq (%rax), %rdi
movl -0x2c(%rbp), %r8d
movl -0xc(%rbp), %r9d
movl -0x20(%rbp), %eax
leaq 0x124fa(%rip), %rsi     # 0x1dccc
leaq 0x12530(%rip), %rdx     # 0x1dd09
movl $0xa0, %ecx
movl %eax, (%rsp)
movb $0x0, %al
callq 0x5190
jmp 0xb7ea
jmp 0xbaa7
movw $0x0, -0x86(%rbp)
movl $0x0, -0x28(%rbp)
movl -0x28(%rbp), %eax
cmpl -0x2c(%rbp), %eax
jae 0xb84a
movq -0x18(%rbp), %rax
movl -0x74(%rbp), %ecx
addl -0x28(%rbp), %ecx
movl %ecx, %ecx
movzbl (%rax,%rcx), %ecx
shll $0x8, %ecx
movq -0x18(%rbp), %rax
movl -0x74(%rbp), %edx
addl -0x28(%rbp), %edx
addl $0x1, %edx
movl %edx, %edx
movzbl (%rax,%rdx), %eax
addl %eax, %ecx
movzwl -0x86(%rbp), %eax
addl %ecx, %eax
movw %ax, -0x86(%rbp)
movl -0x28(%rbp), %eax
addl $0x2, %eax
movl %eax, -0x28(%rbp)
jmp 0xb7ff
movq -0x98(%rbp), %rax
movl -0x2c(%rbp), %ecx
shrl $0x8, %ecx
andl $0xff, %ecx
movb %cl, -0x7e(%rbp)
movl -0x2c(%rbp), %ecx
andl $0xff, %ecx
movb %cl, -0x7d(%rbp)
movl -0xc(%rbp), %ecx
shrl $0x10, %ecx
andl $0xff, %ecx
movb %cl, -0x7c(%rbp)
movl -0xc(%rbp), %ecx
shrl $0x8, %ecx
andl $0xff, %ecx
movb %cl, -0x7b(%rbp)
movzwl -0x86(%rbp), %ecx
sarl $0x8, %ecx
andl $0xff, %ecx
movb %cl, -0x7a(%rbp)
movzwl -0x86(%rbp), %ecx
andl $0xff, %ecx
movb %cl, -0x79(%rbp)
movq 0x8(%rax), %rdi
leaq -0x83(%rbp), %rsi
movq (%rdi), %rax
movl $0xb, %edx
callq *0x38(%rax)
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jge 0xb909
jmp 0xb8ce
leaq 0x1a9c4(%rip), %rax     # 0x26299
testb $0x1, (%rax)
je 0xb902
movq 0x1a6f7(%rip), %rax     # 0x25fd8
movq (%rax), %rdi
movl -0x20(%rbp), %r8d
leaq 0x1242c(%rip), %rsi     # 0x1dd1b
leaq 0x12413(%rip), %rdx     # 0x1dd09
movl $0xb2, %ecx
movb $0x0, %al
callq 0x5190
jmp 0xb904
jmp 0xbaa7
movl $0x13880, %edi          # imm = 0x13880
callq 0x5180
movl $0x64, -0x24(%rbp)
leaq -0x70(%rbp), %rdi
xorl %esi, %esi
movl $0x41, %edx
callq 0x50a0
movq -0x98(%rbp), %rax
movq 0x8(%rax), %rdi
leaq -0x70(%rbp), %rdx
movq (%rdi), %rax
movl $0x5096, %esi           # imm = 0x5096
movl $0x1, %ecx
callq *0x20(%rax)
movl %eax, -0x20(%rbp)
cmpl $0x0, -0x20(%rbp)
jge 0xb992
jmp 0xb954
leaq 0x1a93e(%rip), %rax     # 0x26299
testb $0x1, (%rax)
je 0xb98e
movq 0x1a651(%rip), %rax     # 0x25fb8
movq (%rax), %rdi
movl -0x20(%rbp), %r9d
leaq 0x123e1(%rip), %rsi     # 0x1dd56
leaq 0x1238d(%rip), %rdx     # 0x1dd09
movl $0xbc, %ecx
movl $0x5096, %r8d           # imm = 0x5096
movb $0x0, %al
callq 0x5190
jmp 0xb990
jmp 0xb992
movzbl -0x70(%rbp), %eax
cmpl $0xaa, %eax
jne 0xb99f
jmp 0xb9bb
movl $0x7d0, %edi            # imm = 0x7D0
callq 0x5180
movl -0x24(%rbp), %eax
addl $-0x1, %eax
movl %eax, -0x24(%rbp)
cmpl $0x0, %eax
jne 0xb91a
cmpl $0x0, -0x24(%rbp)
jne 0xba5b
jmp 0xb9c7
leaq 0x1a8cb(%rip), %rax     # 0x26299
testb $0x1, (%rax)
je 0xba02
movq 0x1a5de(%rip), %rax     # 0x25fb8
movq (%rax), %rdi
movzbl -0x70(%rbp), %r9d
leaq 0x12398(%rip), %rsi     # 0x1dd81
leaq 0x12319(%rip), %rdx     # 0x1dd09
movl $0xc5, %ecx
movl $0x5096, %r8d           # imm = 0x5096
movb $0x0, %al
callq 0x5190
jmp 0xba04
jmp 0xba06
leaq 0x1a88c(%rip), %rax     # 0x26299
testb $0x1, (%rax)
je 0xba41
movq 0x1a59f(%rip), %rax     # 0x25fb8
movq (%rax), %rdi
movl -0x8c(%rbp), %r8d
movl -0xc(%rbp), %r9d
leaq 0x12382(%rip), %rsi     # 0x1ddb0
leaq 0x122d4(%rip), %rdx     # 0x1dd09
movl $0xc6, %ecx
movb $0x0, %al
callq 0x5190
jmp 0xba43
movl -0x8c(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x8c(%rbp)
movl $0xffffffff, -0x20(%rbp) # imm = 0xFFFFFFFF
jmp 0xbaa0
movq -0x98(%rbp), %rax
movl -0x2c(%rbp), %ecx
addl -0x74(%rbp), %ecx
movl %ecx, -0x74(%rbp)
movl -0x2c(%rbp), %ecx
addl -0xc(%rbp), %ecx
movl %ecx, -0xc(%rbp)
movl $0x0, -0x8c(%rbp)
movq 0x8(%rax), %rdi
movq (%rdi), %rax
movl $0x5096, %esi           # imm = 0x5096
leaq -0x87(%rbp), %rdx
movl $0x1, %ecx
callq *0x30(%rax)
movl $0x0, -0x20(%rbp)
jmp 0xb71e
jmp 0xbaa7
movl -0x20(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
nopw %cs:(%rax,%rax)