// File: /workspace/github_cpp_makefile_star2_O3/goodix[P]gdix_hid_firmware_update/gtx3/gtx3_update.cpp
// Function: GTx3Update::fw_update(unsigned int)
int GTx3Update::fw_update(unsigned int firmware_flag)
{
	int retry;
	int ret, i;
	unsigned char temp_buf[65];
	unsigned char *fw_data = NULL;
	unsigned char buf_switch_to_patch[] = {0x00, 0x10, 0x00, 0x00, 0x01, 0x01};
	unsigned char buf_start_update[] = {0x00, 0x11, 0x00, 0x00, 0x01, 0x01};
	unsigned char buf_restart[] = {0x0E, 0x13, 0x00, 0x00, 0x01, 0x01};

	int sub_fw_num = 0;
	unsigned char sub_fw_type;
	unsigned int sub_fw_len;
	unsigned int sub_fw_flash_addr;
	unsigned int sub_fw_info_pos =
		image->GetFirmwareSubFwInfoOffset(); // SUB_FW_INFO_OFFSET;
	unsigned int fw_image_offset =
		image->GetFirmwareSubFwDataOffset(); // SUB_FW_DATA_OFFSET;

	ret = dev->Write(buf_switch_to_patch, sizeof(buf_switch_to_patch));
	if (ret < 0) {
		gdix_err("Failed switch to patch\n");
		goto update_err;
	}

	usleep(250000);
	retry = GDIX_RETRY_TIMES;
	do {
		ret = dev->Read(BL_STATE_ADDR, temp_buf, 1);
		gdix_dbg("BL_STATE_ADDR:0x%x\n", BL_STATE_ADDR);
		if (ret < 0) {
			gdix_err("Failed read 0x%x, ret = %d\n", BL_STATE_ADDR, ret);
			goto update_err;
		}
		if (temp_buf[0] == 0xDD)
			break;
		gdix_info("0x%x value is 0x%x != 0xDD, retry\n", BL_STATE_ADDR,
				  temp_buf[0]);
		usleep(30000);
	} while (--retry);

	if (!retry) {
		gdix_err("Reg 0x%x != 0xDD\n", BL_STATE_ADDR);
		ret = -2;
		goto update_err;
	}

	/* Start update */
	ret = dev->Write(buf_start_update, sizeof(buf_start_update));
	if (ret < 0) {
		gdix_err("Failed start update, ret=%d\n", ret);
		goto update_err;
	}
	usleep(100000);

	/* Start load firmware */
	fw_data = image->GetFirmwareData();
	if (!fw_data) {
		gdix_err("No valid fw data \n");
		ret = -4;
		goto update_err;
	}

	sub_fw_num =
		image->GetFirmwareSubFwNum(); // fw_data[FW_IMAGE_SUB_FWNUM_OFFSET];
	// sub_fw_info_pos = image->GetFirmwareSubFwInfoOffset();//
	// SUB_FW_INFO_OFFSET; fw_image_offset = image->GetFirmwareSubFwDataOffset()
	// ; //SUB_FW_DATA_OFFSET;
	gdix_dbg("load sub firmware, sub_fw_num=%d\n", sub_fw_num);
	if (sub_fw_num == 0)
		return -5;

	/* flash HID subsystem */
	if (need_upgrade_hid_subsystem(dev, image)) {
		firmware_flag |= (0x1 << HID_SUBSYSTEM_TYPE_ID);
		gdix_dbg("hid subsystem updata flag setted\n");
	}

	/* load normal firmware package */
	for (i = 0; i < sub_fw_num; i++) {
		sub_fw_type = fw_data[sub_fw_info_pos];
		gdix_dbg("load sub firmware, sub_fw_type=0x%x\n", sub_fw_type);
		sub_fw_len = (fw_data[sub_fw_info_pos + 1] << 24) |
					 (fw_data[sub_fw_info_pos + 2] << 16) |
					 (fw_data[sub_fw_info_pos + 3] << 8) |
					 fw_data[sub_fw_info_pos + 4];

		sub_fw_flash_addr =
			(fw_data[sub_fw_info_pos + 5] << 8) | fw_data[sub_fw_info_pos + 6];
		sub_fw_flash_addr = sub_fw_flash_addr << 8;
		if (!(firmware_flag & (0x01 << sub_fw_type))) {
			gdix_info("Sub firmware type does not math:type=%d\n", sub_fw_type);
			fw_image_offset += sub_fw_len;
			sub_fw_info_pos += 8;
			continue;
		}

		/* if sub fw type is HID subsystem we need compare version before update
		 */
		// TODO update hid subsystem
		gdix_dbg("load sub firmware addr:0x%x,len:0x%x\n", sub_fw_flash_addr,
				 sub_fw_len);
		ret = load_sub_firmware(sub_fw_flash_addr, &fw_data[fw_image_offset],
								sub_fw_len);
		if (ret < 0) {
			gdix_dbg("Failed load sub firmware, ret=%d\n", ret);
			goto update_err;
		}
		fw_image_offset += sub_fw_len;
		sub_fw_info_pos += 8;
	}

	/* flash config with isp if NEED_UPDATE_CONFIG_WITH_ISP flag is setted or
	 * hid subsystem updated.
	 */
	if (image->GetUpdateFlag() & NEED_UPDATE_CONFIG_WITH_ISP ||
		firmware_flag & (0x1 << HID_SUBSYSTEM_TYPE_ID)) {
		this->is_cfg_flashed_with_isp = true;
		ret = flash_cfg_with_isp();
		if (ret < 0) {
			gdix_err("failed flash config with isp, ret %d\n", ret);
			goto update_err;
		}
	}

	/* reset IC */
	gdix_dbg("reset ic\n");
	retry = 3;
	do {
		ret = dev->Write(buf_restart, sizeof(buf_restart));
		if (ret < 0)
			gdix_dbg("Failed write restart command, ret=%d\n", ret);
		usleep(20000);
	} while (--retry);
	usleep(300000);
	return 0;

update_err:
	/* reset IC */
	gdix_dbg("reset ic\n");
	retry = 3;
	do {
		if (dev->Write(buf_restart, sizeof(buf_restart)) < 0)
			gdix_dbg("Failed write restart command\n");
		usleep(20000);
	} while (--retry);

	usleep(300000);
	return ret;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x78, %rsp
movl %esi, 0xc(%rsp)
movq %rdi, %rbx
movw $0x101, %ax             # imm = 0x101
leaq 0x28(%rsp), %r15
movw %ax, 0x4(%r15)
movl $0x1000, (%r15)         # imm = 0x1000
movw %ax, 0x24(%rsp)
movl $0x1100, 0x20(%rsp)     # imm = 0x1100
movw %ax, 0x18(%rsp)
movl $0x130e, 0x14(%rsp)     # imm = 0x130E
movq 0x10(%rdi), %rdi
movq (%rdi), %rax
callq *0x60(%rax)
movl %eax, %r14d
movq 0x10(%rbx), %rdi
movq (%rdi), %rax
callq *0x68(%rax)
movl %eax, %ebp
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movq %r15, %rsi
movl $0x6, %edx
callq *0x38(%rax)
testl %eax, %eax
js 0xc366
movl %ebp, 0x10(%rsp)
movl $0x3d090, %edi          # imm = 0x3D090
callq 0x5170
movl $0xfffffffa, %r15d      # imm = 0xFFFFFFFA
leaq 0x30(%rsp), %r13
leaq 0xcf3d(%rip), %rbp      # 0x191d6
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movl $0x5095, %esi           # imm = 0x5095
movq %r13, %rdx
movl $0x1, %ecx
callq *0x20(%rax)
movl %eax, %r12d
leaq 0x14fd7(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc2e5
movq 0x14cf2(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xaf18(%rip), %rsi      # 0x171e8
movq %rbp, %rdx
movl $0xb7, %ecx
movl $0x5095, %r8d           # imm = 0x5095
xorl %eax, %eax
callq 0x5180
testl %r12d, %r12d
js 0xc383
movzbl 0x30(%rsp), %r9d
cmpl $0xdd, %r9d
je 0xc3c5
leaq 0x14f89(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc333
movq 0x14ca4(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xaf1c(%rip), %rsi      # 0x1723a
movq %rbp, %rdx
movl $0xbf, %ecx
movl $0x5095, %r8d           # imm = 0x5095
xorl %eax, %eax
callq 0x5180
movl $0x7530, %edi           # imm = 0x7530
callq 0x5170
incl %r15d
jne 0xc299
movl $0xfffffffe, %r12d      # imm = 0xFFFFFFFE
leaq 0x14f3e(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc6ea
callq 0x58d6
jmp 0xc6ea
movl %eax, %r12d
leaq 0x14f21(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc6ea
callq 0x5930
jmp 0xc6ea
leaq 0x14f07(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc6ea
movq 0x14c3e(%rip), %rax     # 0x20fd8
movq (%rax), %rdi
leaq 0xae69(%rip), %rsi      # 0x1720d
leaq 0xce2b(%rip), %rdx      # 0x191d6
movl $0xb9, %ecx
movl $0x5095, %r8d           # imm = 0x5095
movl %r12d, %r9d
xorl %eax, %eax
callq 0x5180
jmp 0xc6ea
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
leaq 0x20(%rsp), %rsi
movl $0x6, %edx
callq *0x38(%rax)
testl %eax, %eax
js 0xc6a3
movl $0x186a0, %edi          # imm = 0x186A0
callq 0x5170
movq 0x10(%rbx), %rdi
movq (%rdi), %rax
callq *0x38(%rax)
testq %rax, %rax
je 0xc6d4
movq %rax, %r13
movq 0x10(%rbx), %rdi
movq (%rdi), %rax
callq *0x58(%rax)
movl %eax, %ebp
leaq 0x14e7d(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc440
movq 0x14b98(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xaeb9(%rip), %rsi      # 0x172e3
leaq 0xcda5(%rip), %rdx      # 0x191d6
movl $0xde, %ecx
movl %ebp, %r8d
xorl %eax, %eax
callq 0x5180
testl %ebp, %ebp
je 0xc794
movq 0x8(%rbx), %rdi
movq 0x10(%rbx), %rsi
callq 0xc0bf
testb %al, %al
je 0xc48e
orl $0x20, 0xc(%rsp)
leaq 0x14e2c(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc48e
movq 0x14b47(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xbce8(%rip), %rsi      # 0x18163
leaq 0xcd54(%rip), %rdx      # 0x191d6
movl $0xe5, %ecx
xorl %eax, %eax
callq 0x5180
testl %ebp, %ebp
jle 0xc5d4
movl %r14d, %eax
movzbl (%r13,%rax), %r12d
leaq 0x14deb(%rip), %rax     # 0x21291
cmpb $0x0, (%rax)
je 0xc4d2
movq 0x14b06(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xae5a(%rip), %rsi      # 0x17316
leaq 0xcd13(%rip), %rdx      # 0x191d6
movl $0xeb, %ecx
movl %r12d, %r8d
xorl %eax, %eax
callq 0x5180
leal 0x1(%r14), %eax
movzbl (%r13,%rax), %eax
shll $0x18, %eax
leal 0x2(%r14), %ecx
movzbl (%r13,%rcx), %ecx
shll $0x10, %ecx
orl %eax, %ecx
leal 0x3(%r14), %eax
movzbl (%r13,%rax), %eax
shll $0x8, %eax
orl %ecx, %eax
leal 0x4(%r14), %ecx
movzbl (%r13,%rcx), %r15d
orl %eax, %r15d
movl 0xc(%rsp), %eax
btl %r12d, %eax
leaq 0x14d78(%rip), %rax     # 0x21291
movb (%rax), %al
movl %ebp, 0x1c(%rsp)
jae 0xc58e
leal 0x5(%r14), %ecx
movzbl (%r13,%rcx), %ecx
leal 0x6(%r14), %edx
movzbl (%r13,%rdx), %r12d
shll $0x10, %ecx
shll $0x8, %r12d
orl %ecx, %r12d
testb %al, %al
je 0xc56d
movq 0x14a6e(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xae32(%rip), %rsi      # 0x17386
leaq 0xcc7b(%rip), %rdx      # 0x191d6
movl $0xff, %ecx
movl %r12d, %r8d
movl %r15d, %r9d
xorl %eax, %eax
callq 0x5180
movl 0x10(%rsp), %ebp
movl %ebp, %edx
addq %r13, %rdx
movq (%rbx), %rax
movq %rbx, %rdi
movl %r12d, %esi
movl %r15d, %ecx
callq *0x28(%rax)
testl %eax, %eax
jns 0xc5bd
jmp 0xc79c
testb %al, %al
movl 0x10(%rsp), %ebp
je 0xc5bd
movq 0x14a1b(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xada5(%rip), %rsi      # 0x1734c
leaq 0xcc28(%rip), %rdx      # 0x191d6
movl $0xf5, %ecx
movl %r12d, %r8d
xorl %eax, %eax
callq 0x5180
addl %r15d, %ebp
movl %ebp, 0x10(%rsp)
addl $0x8, %r14d
movl 0x1c(%rsp), %ebp
decl %ebp
jne 0xc496
movq 0x10(%rbx), %rdi
movq (%rdi), %rax
callq *0xa8(%rax)
andl $0x10, %eax
movl 0xc(%rsp), %ecx
andl $0x20, %ecx
orl %eax, %ecx
je 0xc604
movb $0x1, 0x19(%rbx)
movq (%rbx), %rax
movq %rbx, %rdi
callq *0x40(%rax)
testl %eax, %eax
js 0xc7db
leaq 0x14c86(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc634
movq 0x149a1(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xae32(%rip), %rsi      # 0x17453
leaq 0xcbae(%rip), %rdx      # 0x191d6
movl $0x118, %ecx            # imm = 0x118
xorl %eax, %eax
callq 0x5180
movl $0xfffffffd, %ebp       # imm = 0xFFFFFFFD
leaq 0x14(%rsp), %r14
leaq 0xae29(%rip), %r15      # 0x1746e
leaq 0xcb8a(%rip), %r13      # 0x191d6
xorl %r12d, %r12d
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movq %r14, %rsi
movl $0x6, %edx
callq *0x38(%rax)
testl %eax, %eax
jns 0xc690
leaq 0x14c25(%rip), %rcx     # 0x21291
cmpb $0x1, (%rcx)
jne 0xc690
movq 0x14940(%rip), %rcx     # 0x20fb8
movq (%rcx), %rdi
movq %r15, %rsi
movq %r13, %rdx
movl $0x11d, %ecx            # imm = 0x11D
movl %eax, %r8d
xorl %eax, %eax
callq 0x5180
movl $0x4e20, %edi           # imm = 0x4E20
callq 0x5170
incl %ebp
jne 0xc64f
jmp 0xc778
movl %eax, %r12d
leaq 0x14be4(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc6ea
movq 0x1491f(%rip), %rax     # 0x20fd8
movq (%rax), %rdi
leaq 0xabce(%rip), %rsi      # 0x17291
leaq 0xcb0c(%rip), %rdx      # 0x191d6
movl $0xcc, %ecx
jmp 0xc7cc
movl $0xfffffffc, %r12d      # imm = 0xFFFFFFFC
leaq 0x14bb0(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
je 0xc80d
leaq 0x14ba0(%rip), %rbp     # 0x21291
cmpb $0x1, (%rbp)
jne 0xc71b
movq 0x148ba(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xad4b(%rip), %rsi      # 0x17453
leaq 0xcac7(%rip), %rdx      # 0x191d6
movl $0x125, %ecx            # imm = 0x125
xorl %eax, %eax
callq 0x5180
movl $0xfffffffd, %r15d      # imm = 0xFFFFFFFD
leaq 0x14(%rsp), %r14
leaq 0xcaa9(%rip), %r13      # 0x191d6
movq 0x8(%rbx), %rdi
movq (%rdi), %rax
movq %r14, %rsi
movl $0x6, %edx
callq *0x38(%rax)
testl %eax, %eax
jns 0xc769
cmpb $0x1, (%rbp)
jne 0xc769
movq 0x14868(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xb63e(%rip), %rsi      # 0x17d98
movq %r13, %rdx
movl $0x129, %ecx            # imm = 0x129
xorl %eax, %eax
callq 0x5180
movl $0x4e20, %edi           # imm = 0x4E20
callq 0x5170
incl %r15d
jne 0xc72d
movl $0x493e0, %edi          # imm = 0x493E0
callq 0x5170
movl %r12d, %eax
addq $0x78, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movl $0xfffffffb, %r12d      # imm = 0xFFFFFFFB
jmp 0xc782
movl %eax, %r12d
leaq 0x14aeb(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc6ea
movq 0x14802(%rip), %rax     # 0x20fb8
movq (%rax), %rdi
leaq 0xabfd(%rip), %rsi      # 0x173bd
leaq 0xca0f(%rip), %rdx      # 0x191d6
movl $0x103, %ecx            # imm = 0x103
movl %r12d, %r8d
xorl %eax, %eax
callq 0x5180
jmp 0xc6ea
movl %eax, %r12d
leaq 0x14aac(%rip), %rax     # 0x21291
cmpb $0x1, (%rax)
jne 0xc6ea
movq 0x147e3(%rip), %rax     # 0x20fd8
movq (%rax), %rdi
leaq 0xabf1(%rip), %rsi      # 0x173f0
leaq 0xc9d0(%rip), %rdx      # 0x191d6
movl $0x112, %ecx            # imm = 0x112
jmp 0xc7cc
callq 0x5906
jmp 0xc6ea
nop