// File: /workspace/github_c_makefile_star2_O0/evilwombat[P]gopro-fw-tools/h4-section-patch.c
// Function: main
int main(int argc, char **argv)
{
	char *fname, *sname, *oname;
	int ret;
	int target_section;
	unsigned char *fw_buf, *replacement_buf;
	unsigned int fw_size, replacement_size;
	int num_sections;
	int old_num_sections;
	unsigned int new_section_crc, new_global_crc;
	struct section_info sections[MAX_SECTIONS];
	
	printf("evilwombat's magical firmware section patching tool.\n");
	printf("This program is incomplete, undocumented, and unfit for any purpose whatsoever.\n");
	printf("This program is provided entirely AS-IS without ANY warranty, and is unfit for ANY\n");
	printf("purpose. The author bears NO RESPONSIBILITY for ANY consequences of the use of this\n");
	printf("software, including, but not limited to, permanent to damage or destruction of\n");
	printf("your camera, someone else's camera, or any damage to anything, or any consequences\n");
	printf("whatsoever.\n");
	printf("\n");
	printf("Additionally, if you use this program, you are agreeing that your camera's warranty\n");
	printf("is VOIDED, and that you will not attempt to get any kind of warranty coverage or\n");
	printf("ask for any kind of warranty repair for your camera.\n");
	
	printf("IF YOU BRICK IT OR DAMAGE IT, IT'S YOUR FAULT. Don't try to get it replaced. We don't\n");
	printf("need the manufacturer complaining that hobby people are killing their cameras and\n");
	printf("getting mad at us for it.\n");
	printf("\nYOU HAVE BEEN WARNED\n");
	printf("\nMoreover, this program is INCOMPLETE and probably nonfunctional.\n");
	printf("DO NOT USE THIS PROGRAM!\n\n");
	
	if (argc != 5) {
		print_usage(argv[0]);
		return -1;
	}
	
	fname = argv[1];
	sname = argv[2];
	target_section = atoi(argv[3]);
	oname = argv[4];

	printf("Replacing section %d in file %s with file %s, and writing output to %s\n",
	       target_section, fname, sname, oname);

	fw_buf = read_file(fname, &fw_size);
	
	if (!fw_buf) {
		printf("Could not read in original firmware file %s. Exiting.\n", fname);
		return -1;
	}
	
	replacement_buf = read_file(sname, &replacement_size);
	
	if (!replacement_buf) {
		printf("Could not read in replacement section file %s. Exiting.\n", sname);
		return -1;
	}

	printf("\nDecoding contents of %s...\n", fname);
	num_sections = parse_firmware(fw_buf, fw_size, sections, MAX_SECTIONS);
	if (num_sections <= 0) {
		printf("This firmware looks invalid. Exiting.\n");
		return -1;
	}
	printf("\nFound %d sections in file %s:\n", num_sections, fname);
	print_sections(sections, num_sections);
	printf("\n");

	if (target_section >= num_sections) {
		printf("This firmware file (%s) only contains %d sections, and you are\n", fname, num_sections);
		printf("trying to replace section %d (and they are numbered from 0).\n", target_section);
		printf("Are you sure you know what you are doing?\n");
		return -1;
	}
	
	printf("Okay. Trying to replace section_%d with %s\n", target_section, sname);
	
	if (sections[target_section].length > replacement_size) {
		printf("\n******************************************************************************\n");
		printf("WARNING!! The replacement section is smaller than the section in the firmware.\n");
		printf("In the firmware, section_%d is %d bytes long.\n",
		       target_section, sections[target_section].length);
		printf("Your replacement file for section_%d is only %d bytes long.\n",
		       target_section, replacement_size);
		printf("Your replacement section is smaller than the target section by %d bytes.\n",
			sections[target_section].length - replacement_size);
		printf("\nThis might not necessarily be a bad thing, depending on what you are doing.\n");
		printf("If you continue, the section will be zero-padded to the expected length.\n");
		printf("******************************************************************************\n");
		printf("Would you like to proceed? (y/n)\n");
		
		if (getchar() != 'y') {
			printf("Operation aborted by user\n");
			return -1;
		}
	}
	
	if (sections[target_section].length < replacement_size) {
		printf("\n**************************************************************\n");
		printf("ERROR!! The replacement section will not fit into the firmware.\n");
		printf("Your replacement file for section_%d has length %d bytes.\n", target_section, replacement_size);
		printf("In the firmware, this section is only %d bytes long.\n", sections[target_section].length);
		printf("Your replacement section is too long by %d bytes.\n",
			replacement_size - sections[target_section].length);
		printf("This will not work.\n");
		return -1;
	}

	printf("\nReplacing target section...\n");
	/* Zero out replacement section in case we are zero-padding */
	memset(fw_buf + sections[target_section].offset, 0, sections[target_section].length);
	memcpy(fw_buf + sections[target_section].offset, replacement_buf, replacement_size);

	printf("Updating CRCs...\n");
	new_section_crc = crc32(fw_buf + sections[target_section].offset, sections[target_section].length);
	printf("New section CRC: %08x\n", new_section_crc);
	
	write_word_le(fw_buf, sections[target_section].offset - 0x100, new_section_crc);

	new_global_crc = get_global_crc(fw_buf, fw_size);
	printf("New global CRC: %08x\n", new_global_crc);
	
	write_word_le(fw_buf, 0, new_global_crc);
	
	old_num_sections = num_sections;

	printf("\nRescanning resulting firmware for sanity...\n");
	num_sections = parse_firmware(fw_buf, fw_size, sections, MAX_SECTIONS);
	if (num_sections <= 0) {
		printf("The new firmware looks invalid!!\nThis is definitely a bug in this program.\n");
		printf("Please contact evilwombat and report how this happened.\n");
		return -1;
	}
	printf("\nFound %d sections in the new firmware:\n", num_sections);
	print_sections(sections, num_sections);

	if (num_sections != old_num_sections) {
		printf("Old and new section count does not match!!\nThis is definitely a bug in this program.\n");
		printf("Please contact evilwombat and report how this happened.\n");
		return -1;
	}
	
	printf("\nSaving new firmware to file %s...\n", oname);
	ret = save_file(oname, fw_size, fw_buf);
	if (ret) {
		printf("Error saving file!\n");
		return -1;
	}
	printf("Done.\n");

	return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xce0, %rsp            # imm = 0xCE0
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq 0x18df(%rip), %rdi      # 0x328f
movb $0x0, %al
callq 0x1060
leaq 0x1907(%rip), %rdi      # 0x32c5
movb $0x0, %al
callq 0x1060
leaq 0x194a(%rip), %rdi      # 0x3316
movb $0x0, %al
callq 0x1060
leaq 0x1990(%rip), %rdi      # 0x336a
movb $0x0, %al
callq 0x1060
leaq 0x19d7(%rip), %rdi      # 0x33bf
movb $0x0, %al
callq 0x1060
leaq 0x1a19(%rip), %rdi      # 0x340f
movb $0x0, %al
callq 0x1060
leaq 0x1905(%rip), %rdi      # 0x3309
movb $0x0, %al
callq 0x1060
leaq 0x1c66(%rip), %rdi      # 0x3678
movb $0x0, %al
callq 0x1060
leaq 0x1a43(%rip), %rdi      # 0x3463
movb $0x0, %al
callq 0x1060
leaq 0x1a8a(%rip), %rdi      # 0x34b8
movb $0x0, %al
callq 0x1060
leaq 0x1ace(%rip), %rdi      # 0x350a
movb $0x0, %al
callq 0x1060
leaq 0x1af6(%rip), %rdi      # 0x3540
movb $0x0, %al
callq 0x1060
leaq 0x1b3f(%rip), %rdi      # 0x3597
movb $0x0, %al
callq 0x1060
leaq 0x1b84(%rip), %rdi      # 0x35ea
movb $0x0, %al
callq 0x1060
leaq 0x1b91(%rip), %rdi      # 0x3605
movb $0x0, %al
callq 0x1060
leaq 0x1b9a(%rip), %rdi      # 0x361c
movb $0x0, %al
callq 0x1060
leaq 0x1bcf(%rip), %rdi      # 0x365f
movb $0x0, %al
callq 0x1060
cmpl $0x5, -0x8(%rbp)
je 0x1ab5
movq -0x10(%rbp), %rax
movq (%rax), %rdi
callq 0x2030
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x10(%rbp), %rax
movq 0x10(%rax), %rax
movq %rax, -0x20(%rbp)
movq -0x10(%rbp), %rax
movq 0x18(%rax), %rdi
callq 0x10e0
movl %eax, -0x30(%rbp)
movq -0x10(%rbp), %rax
movq 0x20(%rax), %rax
movq %rax, -0x28(%rbp)
movl -0x30(%rbp), %esi
movq -0x18(%rbp), %rdx
movq -0x20(%rbp), %rcx
movq -0x28(%rbp), %r8
leaq 0x1b7b(%rip), %rdi      # 0x367a
movb $0x0, %al
callq 0x1060
movq -0x18(%rbp), %rdi
leaq -0x44(%rbp), %rsi
callq 0x1200
movq %rax, -0x38(%rbp)
cmpq $0x0, -0x38(%rbp)
jne 0x1b3c
movq -0x18(%rbp), %rsi
leaq 0x1b99(%rip), %rdi      # 0x36c2
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
movq -0x20(%rbp), %rdi
leaq -0x48(%rbp), %rsi
callq 0x1200
movq %rax, -0x40(%rbp)
cmpq $0x0, -0x40(%rbp)
jne 0x1b72
movq -0x20(%rbp), %rsi
leaq 0x1b9a(%rip), %rdi      # 0x36f9
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
movq -0x18(%rbp), %rsi
leaq 0x1bb5(%rip), %rdi      # 0x3732
movb $0x0, %al
callq 0x1060
movq -0x38(%rbp), %rdi
movl -0x44(%rbp), %esi
leaq -0xce0(%rbp), %rdx
movl $0x64, %ecx
callq 0x14e0
movl %eax, -0x4c(%rbp)
cmpl $0x0, -0x4c(%rbp)
jg 0x1bbf
leaq 0x1ba3(%rip), %rdi      # 0x374f
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
movl -0x4c(%rbp), %esi
movq -0x18(%rbp), %rdx
leaq 0x1ba9(%rip), %rdi      # 0x3776
movb $0x0, %al
callq 0x1060
leaq -0xce0(%rbp), %rdi
movl -0x4c(%rbp), %esi
callq 0x13a0
leaq 0x1a8e(%rip), %rdi      # 0x3678
movb $0x0, %al
callq 0x1060
movl -0x30(%rbp), %eax
cmpl -0x4c(%rbp), %eax
jl 0x1c39
movq -0x18(%rbp), %rsi
movl -0x4c(%rbp), %edx
leaq 0x1b8f(%rip), %rdi      # 0x3796
movb $0x0, %al
callq 0x1060
movl -0x30(%rbp), %esi
leaq 0x1bbe(%rip), %rdi      # 0x37d6
movb $0x0, %al
callq 0x1060
leaq 0x1bee(%rip), %rdi      # 0x3814
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
movl -0x30(%rbp), %esi
movq -0x20(%rbp), %rdx
leaq 0x1bf8(%rip), %rdi      # 0x383f
movb $0x0, %al
callq 0x1060
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x1c(%rax), %eax
cmpl -0x48(%rbp), %eax
jbe 0x1d46
leaq 0x1bf8(%rip), %rdi      # 0x386b
movb $0x0, %al
callq 0x1060
leaq 0x1c3b(%rip), %rdi      # 0x38bc
movb $0x0, %al
callq 0x1060
movl -0x30(%rbp), %esi
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x1c(%rax), %edx
leaq 0x1c65(%rip), %rdi      # 0x390c
movb $0x0, %al
callq 0x1060
movl -0x30(%rbp), %esi
movl -0x48(%rbp), %edx
leaq 0x1c80(%rip), %rdi      # 0x393b
movb $0x0, %al
callq 0x1060
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x1c(%rax), %esi
subl -0x48(%rbp), %esi
leaq 0x1c97(%rip), %rdi      # 0x3978
movb $0x0, %al
callq 0x1060
leaq 0x1cd3(%rip), %rdi      # 0x39c2
movb $0x0, %al
callq 0x1060
leaq 0x1d13(%rip), %rdi      # 0x3a10
movb $0x0, %al
callq 0x1060
leaq 0x1b61(%rip), %rdi      # 0x386c
movb $0x0, %al
callq 0x1060
leaq 0x1d41(%rip), %rdi      # 0x3a5a
movb $0x0, %al
callq 0x1060
callq 0x1080
cmpl $0x79, %eax
je 0x1d44
leaq 0x1d4b(%rip), %rdi      # 0x3a7c
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
jmp 0x1d46
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x1c(%rax), %eax
cmpl -0x48(%rbp), %eax
jae 0x1df7
leaq 0x1d2c(%rip), %rdi      # 0x3a97
movb $0x0, %al
callq 0x1060
leaq 0x1d5f(%rip), %rdi      # 0x3ad8
movb $0x0, %al
callq 0x1060
movl -0x30(%rbp), %esi
movl -0x48(%rbp), %edx
leaq 0x1d8c(%rip), %rdi      # 0x3b19
movb $0x0, %al
callq 0x1060
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x1c(%rax), %esi
leaq 0x1da4(%rip), %rdi      # 0x3b54
movb $0x0, %al
callq 0x1060
movl -0x48(%rbp), %esi
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
subl 0x1c(%rax), %esi
leaq 0x1db4(%rip), %rdi      # 0x3b8a
movb $0x0, %al
callq 0x1060
leaq 0x1dd9(%rip), %rdi      # 0x3bbd
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
leaq 0x1dd4(%rip), %rdi      # 0x3bd2
movb $0x0, %al
callq 0x1060
movq -0x38(%rbp), %rdi
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x18(%rax), %eax
addq %rax, %rdi
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x1c(%rax), %eax
movl %eax, %edx
xorl %esi, %esi
callq 0x1070
movq -0x38(%rbp), %rdi
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x18(%rax), %eax
addq %rax, %rdi
movq -0x40(%rbp), %rsi
movl -0x48(%rbp), %eax
movl %eax, %edx
callq 0x10b0
leaq 0x1d80(%rip), %rdi      # 0x3bf0
movb $0x0, %al
callq 0x1060
movq -0x38(%rbp), %rdi
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x18(%rax), %eax
addq %rax, %rdi
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x1c(%rax), %esi
callq 0x2190
movl %eax, -0x54(%rbp)
movl -0x54(%rbp), %esi
leaq 0x1d48(%rip), %rdi      # 0x3c02
movb $0x0, %al
callq 0x1060
movq -0x38(%rbp), %rdi
movslq -0x30(%rbp), %rcx
leaq -0xce0(%rbp), %rax
shlq $0x5, %rcx
addq %rcx, %rax
movl 0x18(%rax), %esi
subl $0x100, %esi            # imm = 0x100
movl -0x54(%rbp), %edx
callq 0x2090
movq -0x38(%rbp), %rdi
movl -0x44(%rbp), %esi
callq 0x1480
movl %eax, -0x58(%rbp)
movl -0x58(%rbp), %esi
leaq 0x1d18(%rip), %rdi      # 0x3c19
movb $0x0, %al
callq 0x1060
movq -0x38(%rbp), %rdi
movl -0x58(%rbp), %edx
xorl %esi, %esi
callq 0x2090
movl -0x4c(%rbp), %eax
movl %eax, -0x50(%rbp)
leaq 0x1d0c(%rip), %rdi      # 0x3c2f
movb $0x0, %al
callq 0x1060
movq -0x38(%rbp), %rdi
movl -0x44(%rbp), %esi
leaq -0xce0(%rbp), %rdx
movl $0x64, %ecx
callq 0x14e0
movl %eax, -0x4c(%rbp)
cmpl $0x0, -0x4c(%rbp)
jg 0x1f73
leaq 0x1d0b(%rip), %rdi      # 0x3c5d
movb $0x0, %al
callq 0x1060
leaq 0x1d49(%rip), %rdi      # 0x3ca9
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
movl -0x4c(%rbp), %esi
leaq 0x1d65(%rip), %rdi      # 0x3ce2
movb $0x0, %al
callq 0x1060
leaq -0xce0(%rbp), %rdi
movl -0x4c(%rbp), %esi
callq 0x13a0
movl -0x4c(%rbp), %eax
cmpl -0x50(%rbp), %eax
je 0x1fc0
leaq 0x1d69(%rip), %rdi      # 0x3d0b
movb $0x0, %al
callq 0x1060
leaq 0x1cf9(%rip), %rdi      # 0x3ca9
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
movq -0x28(%rbp), %rsi
leaq 0x1d96(%rip), %rdi      # 0x3d61
movb $0x0, %al
callq 0x1060
movq -0x28(%rbp), %rdi
movl -0x44(%rbp), %esi
movq -0x38(%rbp), %rdx
callq 0x2100
movl %eax, -0x2c(%rbp)
cmpl $0x0, -0x2c(%rbp)
je 0x2002
leaq 0x1d93(%rip), %rdi      # 0x3d85
movb $0x0, %al
callq 0x1060
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0x2017
leaq 0x1d90(%rip), %rdi      # 0x3d99
movb $0x0, %al
callq 0x1060
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xce0, %rsp            # imm = 0xCE0
popq %rbp
retq
nopw %cs:(%rax,%rax)