// File: goodix[P]gdix_hid_firmware_update/gtx9/gtx9_i2c_update.cpp
// Function: gdix_flash_subsystem(fw_subsys_info*)
static int gdix_flash_subsystem(struct fw_subsys_info *subsys)
{
	uint32_t data_size, offset;
	uint32_t total_size;
	// TODO: confirm flash addr ,<< 8??
	uint32_t subsys_base_addr = subsys->flash_addr;
	uint8_t *fw_packet = NULL;
	int r = 0;

	/*
	 * if bus(i2c/spi) error occued, then exit, we will do
	 * hardware reset and re-prepare ISP and then retry
	 * flashing
	 */
	total_size = subsys->size;
	fw_packet = (uint8_t *)malloc(ISP_MAX_BUFFERSIZE + 4);
	if (!fw_packet) {
		gdix_dbg("Failed alloc memory\n");
		return -1;
	}

	offset = 0;
	while (total_size > 0) {
		data_size =
			total_size > ISP_MAX_BUFFERSIZE ? ISP_MAX_BUFFERSIZE : total_size;
		gdix_dbg("Flash firmware to %08x,size:%u bytes\n",
				 subsys_base_addr + offset, data_size);

		memcpy(fw_packet, &subsys->data[offset], data_size);
		/* set checksum for package data */
		gdix_append_checksum(fw_packet, data_size, CHECKSUM_MODE_U16_LE);

		r = gdix_flash_package(subsys->type, fw_packet,
							   subsys_base_addr + offset, data_size + 4);
		if (r) {
			gdix_err("failed flash to %08x,size:%u bytes\n",
					 subsys_base_addr + offset, data_size);
			break;
		}
		offset += data_size;
		total_size -= data_size;
	} /* end while */

	free(fw_packet);
	return r;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x30, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movl 0x8(%rax), %eax
movl %eax, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movl $0x0, -0x2c(%rbp)
movq -0x10(%rbp), %rax
movl 0x4(%rax), %eax
movl %eax, -0x1c(%rbp)
movl $0x1004, %edi           # imm = 0x1004
callq 0x5150
movq %rax, -0x28(%rbp)
cmpq $0x0, -0x28(%rbp)
jne 0x16f54
jmp 0x16f16
leaq 0xf37c(%rip), %rax      # 0x26299
testb $0x1, (%rax)
je 0x16f46
movq 0xf08f(%rip), %rax      # 0x25fb8
movq (%rax), %rdi
leaq 0x8c92(%rip), %rsi      # 0x1fbc5
leaq 0x8cb1(%rip), %rdx      # 0x1fbeb
movl $0x2c4, %ecx            # imm = 0x2C4
movb $0x0, %al
callq 0x5190
jmp 0x16f48
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x17083
movl $0x0, -0x18(%rbp)
cmpl $0x0, -0x1c(%rbp)
jbe 0x17074
cmpl $0x1000, -0x1c(%rbp)    # imm = 0x1000
jbe 0x16f78
movl $0x1000, %eax           # imm = 0x1000
movl %eax, -0x30(%rbp)
jmp 0x16f7e
movl -0x1c(%rbp), %eax
movl %eax, -0x30(%rbp)
movl -0x30(%rbp), %eax
movl %eax, -0x14(%rbp)
leaq 0xf30e(%rip), %rax      # 0x26299
testb $0x1, (%rax)
je 0x16fc0
movq 0xf021(%rip), %rax      # 0x25fb8
movq (%rax), %rdi
movl -0x20(%rbp), %r8d
addl -0x18(%rbp), %r8d
movl -0x14(%rbp), %r9d
leaq 0x8c53(%rip), %rsi      # 0x1fc00
leaq 0x8c37(%rip), %rdx      # 0x1fbeb
movl $0x2cd, %ecx            # imm = 0x2CD
movb $0x0, %al
callq 0x5190
jmp 0x16fc2
movq -0x28(%rbp), %rdi
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rsi
movl -0x18(%rbp), %eax
addq %rax, %rsi
movl -0x14(%rbp), %eax
movl %eax, %edx
callq 0x50b0
movq -0x28(%rbp), %rdi
movl -0x14(%rbp), %esi
movl $0x1, %edx
callq 0x14fc0
movq -0x10(%rbp), %rax
movb (%rax), %cl
movq -0x28(%rbp), %rsi
movl -0x20(%rbp), %edx
addl -0x18(%rbp), %edx
movl -0x14(%rbp), %eax
addl $0x4, %eax
movzbl %cl, %edi
movzwl %ax, %ecx
callq 0x17090
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x1705b
jmp 0x1701b
leaq 0xf277(%rip), %rax      # 0x26299
testb $0x1, (%rax)
je 0x17057
movq 0xefaa(%rip), %rax      # 0x25fd8
movq (%rax), %rdi
movl -0x20(%rbp), %r8d
addl -0x18(%rbp), %r8d
movl -0x14(%rbp), %r9d
leaq 0x8bf3(%rip), %rsi      # 0x1fc37
leaq 0x8ba0(%rip), %rdx      # 0x1fbeb
movl $0x2d7, %ecx            # imm = 0x2D7
movb $0x0, %al
callq 0x5190
jmp 0x17059
jmp 0x17074
movl -0x14(%rbp), %eax
addl -0x18(%rbp), %eax
movl %eax, -0x18(%rbp)
movl -0x14(%rbp), %ecx
movl -0x1c(%rbp), %eax
subl %ecx, %eax
movl %eax, -0x1c(%rbp)
jmp 0x16f5b
movq -0x28(%rbp), %rdi
callq 0x5120
movl -0x2c(%rbp), %eax
movl %eax, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x30, %rsp
popq %rbp
retq
nopl (%rax)