// File: /workspace/github_c_makefile_star2_O3/evilwombat[P]gopro-fw-tools/h3-wifi-address.c
// Function: main
int main(int argc, char **argv)
{
	FILE *in_fd;
	char *fname, *output_name;
	struct stat st;
	int ret;
	unsigned int size, hdr_size;
	unsigned char *buf;
	uint32_t crc, hdr_crc;
	int patch_byte = 8;
	struct wifi_fw_type *wifi_fw = wifi_fw_list;

	printf("MAKE SURE YOU HAVE READ THE INSTRUCTIONS!\n");
	printf("The author makes absolutely NO GUARANTEES of the correctness of this program\n");
	printf("and takes absolutely NO RESPONSIBILITY OR LIABILITY for any consequences that\n");
	printf("arise from its use. This program could SEVERELY mess up your camera, totally\n");
	printf("destroy it, cause it to catch fire. It could also destroy your computer, burn\n");
	printf("down your house, etc. The author takes no responsibility for the consequences\n");
	printf("of using this program. Use it at your own risk! You have been warned.\n");
	printf("\n");

	if (argc != 4) {
		print_usage(argv[0]);
		return -1;
	}

	fname = argv[1];

	patch_byte = atoi(argv[2]);

	if (patch_byte < 0 || patch_byte > 255) {
		printf("Bad patching value: %d\n", patch_byte);
		return -1;
	}

	printf("Patching camera address to 10.%d.5.9\n", patch_byte);
	printf("Patching computer address to 10.%d.5.109\n", patch_byte);
	printf("\n");

	output_name = argv[3];

	ret = stat(fname, &st);
	if (ret) {
		printf("Error: Could not stat %s\n", fname);
		return -1;
	}

	size = st.st_size;
	if (size <= 0) {
		printf("Bad file size: %d\n", size);
		return -1;
	}

	buf = malloc(size);
	if (!buf) {
		printf("Could not allocate %d bytes\n", size);
		return -1;
	}

	in_fd = fopen(fname, "rb");

	ret = read_file(in_fd, buf, size);
	if (ret) {
		printf("Could not read file: %d\n", ret);
		return -1;
	}
	fclose(in_fd);

	hdr_size = read_word(buf, SIZE_OFFSET);
	hdr_crc = read_word(buf, CRC_OFFSET);

	printf("Wifi FW header reports size: %08x\n", hdr_size);
	printf("Wifi FW header reports CRC : %08x\n", hdr_crc);

	printf("Actual file size: %08x\n", size);
	if (size != hdr_size) {
		printf("File size does not match size reported in header.\n");
		goto fail;
	}

	write_word(buf, CRC_OFFSET, 0x00000000);
	crc = crc32(buf, size);

	printf("Actual file CRC : %08x\n", crc);
	if (crc != hdr_crc) {
		printf("File CRC does not match CRC reported in header.\n");
		goto fail;
	}

	/*
	 * Checking both the size and CRC is probably redundant, but we may
	 * as well be careful
	 */
	while (wifi_fw->name) {
		if (wifi_fw->size == size && wifi_fw->crc == crc)
			break;
		wifi_fw++;
	}

	if (wifi_fw->name == NULL) {
		printf("\nUnrecognized firmware file!\n");
		printf("This only works on the following firmware files:\n");

		wifi_fw = wifi_fw_list;
		while (wifi_fw->name) {
			printf("\t * %s\n", wifi_fw->name);
			wifi_fw++;
		}

		goto fail;
	}

	printf("Detected firmware type: \"%s\"\n", wifi_fw->name);

	printf("Patching firmware...\n");
	ret = patch_buffer(buf, wifi_fw->patch, patch_byte, wifi_fw->old_val);
	if (ret) {
		printf("Error patching buffer: %d\n", ret);
		goto fail;
	}

	crc = crc32(buf, size);
	printf("New CRC: %08x\n", crc);
	write_word(buf, CRC_OFFSET, crc);

	printf("Saving output file: %s\n", output_name);
	ret = save_file(output_name, size, buf);
	if (ret) {
		printf("Error saving file: %d\n", ret);
		goto fail;
	}
	printf("Done.\n");

fail:
	free(buf);
	return 0;
}

// Assembly:
pushq %rbp
pushq %r15
pushq %r14
pushq %r13
pushq %r12
pushq %rbx
subq $0x98, %rsp
movq %rsi, %rbx
movl %edi, %ebp
leaq 0x10f3(%rip), %rdi      # 0x22ec
callq 0x1050
leaq 0x1111(%rip), %rdi      # 0x2316
callq 0x1050
leaq 0x1152(%rip), %rdi      # 0x2363
callq 0x1050
leaq 0x1194(%rip), %rdi      # 0x23b1
callq 0x1050
leaq 0x11d5(%rip), %rdi      # 0x23fe
callq 0x1050
leaq 0x1217(%rip), %rdi      # 0x244c
callq 0x1050
leaq 0x1259(%rip), %rdi      # 0x249a
callq 0x1050
movl $0xa, %edi
callq 0x1040
cmpl $0x4, %ebp
jne 0x1280
movq 0x8(%rbx), %r12
movq 0x10(%rbx), %rdi
callq 0x10c0
movl %eax, %ebp
cmpl $0x100, %eax            # imm = 0x100
jb 0x12c3
leaq 0xe24(%rip), %rdi       # 0x2096
movl %ebp, %esi
xorl %eax, %eax
callq 0x1080
jmp 0x1313
movq (%rbx), %rsi
leaq 0xfcf(%rip), %rdi       # 0x2259
xorl %eax, %eax
callq 0x1080
leaq 0x1313(%rip), %rdi      # 0x25ab
callq 0x1050
leaq 0x1338(%rip), %rdi      # 0x25dc
callq 0x1050
leaq 0x1350(%rip), %rdi      # 0x2600
callq 0x1050
leaq 0x136c(%rip), %rdi      # 0x2628
callq 0x1050
jmp 0x1313
leaq 0xde4(%rip), %rdi       # 0x20ae
movl %ebp, %esi
xorl %eax, %eax
callq 0x1080
leaq 0xdfa(%rip), %rdi       # 0x20d4
movl %ebp, %esi
xorl %eax, %eax
callq 0x1080
movl $0xa, %edi
callq 0x1040
movq 0x18(%rbx), %r14
leaq 0x8(%rsp), %rsi
movq %r12, %rdi
callq 0x1090
testl %eax, %eax
je 0x132c
leaq 0xdf5(%rip), %rdi       # 0x20fe
movq %r12, %rsi
xorl %eax, %eax
callq 0x1080
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movl %ebx, %eax
addq $0x98, %rsp
popq %rbx
popq %r12
popq %r13
popq %r14
popq %r15
popq %rbp
retq
movq 0x38(%rsp), %r15
testl %r15d, %r15d
je 0x1483
movl %r15d, %r13d
movq %r13, %rdi
callq 0x10a0
testq %rax, %rax
je 0x1491
movq %rax, %rbx
leaq 0xdf0(%rip), %rsi       # 0x2148
movq %r12, %rdi
callq 0x10b0
movq %rax, %r12
movslq %r13d, %rsi
movl $0x1, %edx
movq %rbx, %rdi
movq %rax, %rcx
callq 0x1060
cmpl $0x1, %eax
jne 0x14a0
movq %r12, %rdi
callq 0x1070
movl 0x3f8(%rbx), %r13d
movl 0x3fc(%rbx), %r12d
bswapl %r13d
bswapl %r12d
leaq 0xdc2(%rip), %rdi       # 0x2164
movl %r13d, %esi
xorl %eax, %eax
callq 0x1080
leaq 0xdd4(%rip), %rdi       # 0x2187
movl %r12d, %esi
xorl %eax, %eax
callq 0x1080
leaq 0xde6(%rip), %rdi       # 0x21aa
movl %r15d, %esi
xorl %eax, %eax
callq 0x1080
cmpl %r15d, %r13d
jne 0x14bd
movl $0x0, 0x3fc(%rbx)
movq %rbx, %rdi
movl %r15d, %esi
callq 0x1648
movq %rax, %r13
leaq 0xdcc(%rip), %rdi       # 0x21c2
movl %r13d, %esi
xorl %eax, %eax
callq 0x1080
cmpl %r13d, %r12d
jne 0x14c6
movq 0x2cd0(%rip), %rsi      # 0x40e0
testq %rsi, %rsi
je 0x1439
leaq 0x2ce4(%rip), %r13      # 0x4100
cmpl %r15d, -0x18(%r13)
jne 0x142c
cmpl %r12d, -0x14(%r13)
je 0x14e1
movq (%r13), %rsi
addq $0x20, %r13
testq %rsi, %rsi
jne 0x141c
leaq 0x10bb(%rip), %rdi      # 0x24fb
callq 0x1050
leaq 0x10cc(%rip), %rdi      # 0x2518
callq 0x1050
movq 0x2c88(%rip), %rsi      # 0x40e0
testq %rsi, %rsi
je 0x14d2
leaq 0x2c9c(%rip), %r15      # 0x4100
leaq 0xd6f(%rip), %r14       # 0x21da
movq %r14, %rdi
xorl %eax, %eax
callq 0x1080
movq (%r15), %rsi
addq $0x20, %r15
testq %rsi, %rsi
jne 0x146b
jmp 0x14d2
leaq 0xc8e(%rip), %rdi       # 0x2118
xorl %esi, %esi
jmp 0x1274
leaq 0xc93(%rip), %rdi       # 0x212b
movl %r15d, %esi
jmp 0x1274
leaq 0xca4(%rip), %rdi       # 0x214b
movl $0xffffffff, %ebx       # imm = 0xFFFFFFFF
movl $0xffffffff, %esi       # imm = 0xFFFFFFFF
xorl %eax, %eax
callq 0x1080
jmp 0x1318
leaq 0x10b5(%rip), %rdi      # 0x2579
jmp 0x14cd
leaq 0x107c(%rip), %rdi      # 0x2549
callq 0x1050
movq %rbx, %rdi
callq 0x1030
xorl %ebx, %ebx
jmp 0x1318
leaq 0xcfa(%rip), %rdi       # 0x21e2
xorl %eax, %eax
callq 0x1080
leaq 0xfea(%rip), %rdi       # 0x24e0
callq 0x1050
movq -0x8(%r13), %rsi
movzbl -0x10(%r13), %ecx
movzbl %bpl, %edx
movq %rbx, %rdi
callq 0x158a
testl %eax, %eax
je 0x151d
leaq 0xce5(%rip), %rdi       # 0x2200
jmp 0x1570
movq %rbx, %rdi
movl %r15d, %esi
callq 0x1648
movq %rax, %r12
leaq 0xce9(%rip), %rdi       # 0x221b
movl %r12d, %esi
xorl %eax, %eax
callq 0x1080
bswapl %r12d
movl %r12d, 0x3fc(%rbx)
leaq 0xcdd(%rip), %rdi       # 0x222a
movq %r14, %rsi
xorl %eax, %eax
callq 0x1080
movq %r14, %rdi
movl %r15d, %esi
movq %rbx, %rdx
callq 0x15d8
testl %eax, %eax
je 0x157e
leaq 0xcd2(%rip), %rdi       # 0x2242
movl %eax, %esi
xorl %eax, %eax
callq 0x1080
jmp 0x14d2
leaq 0xf70(%rip), %rdi       # 0x24f5
jmp 0x14cd