#define NULL ((void *)0)
typedef unsigned long size_t; // Customize by platform.
typedef long intptr_t;
typedef unsigned long uintptr_t;
typedef long scalar_t__; // Either arithmetic or pointer type.
/* By default, we understand bool (as a convenience). */
typedef int bool;
#define false 0
#define true 1

/* Forward declarations */

/* Type definitions */
typedef int ssize_t;
typedef int off_t;

/* Variables and functions */
int /*<<< orphan*/ SEEK_END;
int /*<<< orphan*/ SEEK_SET;
unsigned int checksum32(unsigned char *, int);
int checksum_page(int, int, unsigned int *);
int /*<<< orphan*/ free_aligned(unsigned char *, int);
int /*<<< orphan*/ getchar();
int lseek(int, int /*<<< orphan*/, int /*<<< orphan*/);
unsigned char *malloc_aligned(int);
int /*<<< orphan*/ printf(char *, ...);
int read(int, unsigned char *, int);
int sendcmd(int, int, int, int, int /*<<< orphan*/);
int write_data(int, unsigned char *, int);
int upload_firmware(int f, int o) {
  off_t offset;
  ssize_t gotbytes;
  int x;
  unsigned char *cksumbuf, *firmbuf;
  int res = 0;
  printf(
      "*** WARNING ***\n"
      "This performs a firmware upgrade. If done incorrectly,\n"
      "it may brick your photo frame, making it unusable.\n"
      "\n"
      "This program writes the firmware to a temporary location, overwriting\n"
      "the second photo. At the same time, it sets a flag which triggers a\n"
      "firmware upgrade after the photo frame is unplugged from USB.\n"
      "\n"
      "Ensure the photo frame is turned on, so it does not lose power when\n"
      "USB is disconnected.\n"
      "\n"
      "Once the flag is set, it cannot be cleared. However, you can try to\n"
      "upload the firmware again. Ensure you have a good upload before you\n"
      "disconnect USB. That is the final point of no return.\n"
      "\n"
      "Press Enter to proceed.\n");
  (void)getchar();
  cksumbuf = malloc_aligned(512);
  if (cksumbuf == NULL) {
    printf("ERROR: Failed to allocate buffer for checksum.\n");
    return 0;
  }
  firmbuf = malloc_aligned((0x8000 * 2));
  if (firmbuf == NULL) {
    printf("ERROR: Failed to allocate buffer for checksum.\n");
    free_aligned(cksumbuf, 512);
    return 0;
  }
  offset = lseek(o, 0, SEEK_END);
  if (offset < 0) {
    printf("ERROR: Failed to seek to end of file.\n");
    goto ulfw_safe_fail;
  } else if (offset != (0x8000 * 2)) {
    printf("ERROR: File size wrong, should be %i bytes.\n", (0x8000 * 2));
    goto ulfw_safe_fail;
  }
  offset = lseek(o, 0, SEEK_SET);
  if (offset != 0) {
    printf("ERROR: Failed to start of file.\n");
    goto ulfw_safe_fail;
  }
  gotbytes = read(o, firmbuf, (0x8000 * 2));
  if (gotbytes != (0x8000 * 2)) {
    printf("ERROR: Firmware file read failed.\n");
    goto ulfw_safe_fail;
  }
  for (x = 0; x < 2; x++) {
    unsigned int cksumhere, cksumthere;
    unsigned char *chunkp = &firmbuf[0x8000 * x];
    cksumhere = checksum32(chunkp, 0x8000);
    printf("Writing firmware block %i (0x%04x-0x%04x)\n", x,
           (int)(chunkp - firmbuf), (int)(chunkp - firmbuf + 0x8000 - 1));
    if (sendcmd(f, 3, x | 0x80000000, 0x8000, 0) != 1) {
      printf("ERROR: Failed to send upload command.");
      goto ulfw_unsafe_fail;
    }
    if (write_data(f, chunkp, 0x8000) != 0x8000) {
      printf("ERROR: Failed to send data.");
      goto ulfw_unsafe_fail;
    }
    if (checksum_page(f, x + 6, &cksumthere) != 1) {
      printf("ERROR: Failed to read checksum.");
      goto ulfw_unsafe_fail;
    }
    if (cksumhere == cksumthere) {
      printf("Checksum okay for block %i.\n", x);
    } else {
      printf("ERROR: Checksum mismatch at block %i: "
             "should be %08x, but got %08x.\n",
             x, cksumhere, cksumthere);
      goto ulfw_unsafe_fail;
    }
  }
  printf(
      "\n"
      "Firmware upload successful. Disconnect USB to begin firmware upgrade.\n"
      "Switch must be on to continue powering the device after USB is\n"
      "disconnected. Do not interrupt the process!\n");
  res = 1;
  goto ulfw_exit;
ulfw_unsafe_fail:
  printf("The photo frame may be bricked when you disconnect USB and it "
         "attempts to\n"
         "update. Try to perform a successful firmware update before "
         "disconnecting.\n");
  goto ulfw_exit;
ulfw_safe_fail:
  printf("This failure was safe. No firmware upload was performed.\n");
ulfw_exit:
  free_aligned(firmbuf, (0x8000 * 2));
  free_aligned(cksumbuf, 512);
  return res;
}


x86 assembly (clang, -O0):
<upload_firmware>:
push   %rbp
mov    %rsp,%rbp
sub    $0x40,%rsp
mov    %edi,-0x8(%rbp)
mov    %esi,-0xc(%rbp)
movl   $0x0,-0x2c(%rbp)
lea    0xe44(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    $0x0,%al
call   1080 <getchar@plt>
mov    $0x200,%edi
call   1030 <malloc_aligned@plt>
mov    %rax,-0x20(%rbp)
cmpq   $0x0,-0x20(%rbp)
jne    11fd <upload_firmware+0x5d>
lea    0x108c(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
movl   $0x0,-0x4(%rbp)
jmp    14b2 <upload_firmware+0x312>
mov    $0x10000,%edi
call   1030 <malloc_aligned@plt>
mov    %rax,-0x28(%rbp)
cmpq   $0x0,-0x28(%rbp)
jne    123e <upload_firmware+0x9e>
lea    0x1059(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x20(%rbp),%rdi
mov    $0x200,%esi
call   1090 <free_aligned@plt>
movl   $0x0,-0x4(%rbp)
jmp    14b2 <upload_firmware+0x312>
mov    -0xc(%rbp),%edi
mov    0x2da0(%rip),%rax
mov    (%rax),%edx
xor    %esi,%esi
call   1050 <lseek@plt>
mov    %eax,-0x10(%rbp)
cmpl   $0x0,-0x10(%rbp)
jge    1271 <upload_firmware+0xd1>
lea    0x1041(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1482 <upload_firmware+0x2e2>
cmpl   $0x10000,-0x10(%rbp)
je     1296 <upload_firmware+0xf6>
lea    0x1048(%rip),%rdi
mov    $0x10000,%esi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1482 <upload_firmware+0x2e2>
jmp    129b <upload_firmware+0xfb>
mov    -0xc(%rbp),%edi
mov    0x2d33(%rip),%rax
mov    (%rax),%edx
xor    %esi,%esi
call   1050 <lseek@plt>
mov    %eax,-0x10(%rbp)
cmpl   $0x0,-0x10(%rbp)
je     12ce <upload_firmware+0x12e>
lea    0x1038(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1482 <upload_firmware+0x2e2>
mov    -0xc(%rbp),%edi
mov    -0x28(%rbp),%rsi
mov    $0x10000,%edx
call   1060 <read@plt>
mov    %eax,-0x14(%rbp)
cmpl   $0x10000,-0x14(%rbp)
je     1302 <upload_firmware+0x162>
lea    0x1025(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1482 <upload_firmware+0x2e2>
movl   $0x0,-0x18(%rbp)
cmpl   $0x2,-0x18(%rbp)
jge    1455 <upload_firmware+0x2b5>
mov    -0x28(%rbp),%rax
mov    -0x18(%rbp),%ecx
shl    $0xf,%ecx
movslq %ecx,%rcx
add    %rcx,%rax
mov    %rax,-0x40(%rbp)
mov    -0x40(%rbp),%rdi
mov    $0x8000,%esi
call   10a0 <checksum32@plt>
mov    %eax,-0x30(%rbp)
mov    -0x18(%rbp),%esi
mov    -0x40(%rbp),%rax
mov    -0x28(%rbp),%rcx
sub    %rcx,%rax
mov    %eax,%edx
mov    -0x40(%rbp),%rax
mov    -0x28(%rbp),%rcx
sub    %rcx,%rax
add    $0x8000,%rax
sub    $0x1,%rax
mov    %eax,%ecx
lea    0xfd8(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x8(%rbp),%edi
mov    -0x18(%rbp),%edx
or     $0x80000000,%edx
mov    $0x3,%esi
mov    $0x8000,%ecx
xor    %r8d,%r8d
call   10b0 <sendcmd@plt>
cmp    $0x1,%eax
je     13a7 <upload_firmware+0x207>
lea    0xfce(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    146f <upload_firmware+0x2cf>
mov    -0x8(%rbp),%edi
mov    -0x40(%rbp),%rsi
mov    $0x8000,%edx
call   1070 <write_data@plt>
cmp    $0x8000,%eax
je     13d6 <upload_firmware+0x236>
lea    0xfc5(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    146f <upload_firmware+0x2cf>
mov    -0x8(%rbp),%edi
mov    -0x18(%rbp),%esi
add    $0x6,%esi
lea    -0x34(%rbp),%rdx
call   10c0 <checksum_page@plt>
cmp    $0x1,%eax
je     1404 <upload_firmware+0x264>
lea    0xfb3(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    146f <upload_firmware+0x2cf>
mov    -0x30(%rbp),%eax
cmp    -0x34(%rbp),%eax
jne    1426 <upload_firmware+0x286>
mov    -0x18(%rbp),%esi
lea    0xfb1(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1442 <upload_firmware+0x2a2>
mov    -0x18(%rbp),%esi
mov    -0x30(%rbp),%edx
mov    -0x34(%rbp),%ecx
lea    0xfb2(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    146f <upload_firmware+0x2cf>
jmp    1447 <upload_firmware+0x2a7>
mov    -0x18(%rbp),%eax
add    $0x1,%eax
mov    %eax,-0x18(%rbp)
jmp    1309 <upload_firmware+0x169>
lea    0xfd1(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
movl   $0x1,-0x2c(%rbp)
jmp    1490 <upload_firmware+0x2f0>
lea    0x106a(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
jmp    1490 <upload_firmware+0x2f0>
lea    0x10ec(%rip),%rdi
mov    $0x0,%al
call   1040 <printf@plt>
mov    -0x28(%rbp),%rdi
mov    $0x10000,%esi
call   1090 <free_aligned@plt>
mov    -0x20(%rbp),%rdi
mov    $0x200,%esi
call   1090 <free_aligned@plt>
mov    -0x2c(%rbp),%eax
mov    %eax,-0x4(%rbp)
mov    -0x4(%rbp),%eax
add    $0x40,%rsp
pop    %rbp
ret

x86 assembly (clang, -O2):
<upload_firmware>:
push   %rbp
push   %r15
push   %r14
push   %r13
push   %r12
push   %rbx
push   %rax
mov    %esi,%ebp
mov    %edi,%r12d
lea    0xf55(%rip),%rdi
call   1030 <puts@plt>
xor    %ebx,%ebx
xor    %eax,%eax
call   1090 <getchar@plt>
mov    $0x200,%edi
call   1040 <malloc_aligned@plt>
test   %rax,%rax
je     1239 <upload_firmware+0x89>
mov    %rax,%r13
mov    $0x10000,%edi
call   1040 <malloc_aligned@plt>
test   %rax,%rax
je     1247 <upload_firmware+0x97>
mov    %rax,%r14
mov    0x2de8(%rip),%rax
mov    (%rax),%edx
mov    %ebp,%edi
xor    %esi,%esi
call   1060 <lseek@plt>
test   %eax,%eax
js     1264 <upload_firmware+0xb4>
cmp    $0x10000,%eax
jne    1272 <upload_firmware+0xc2>
mov    0x2dbb(%rip),%rax
mov    (%rax),%edx
mov    %ebp,%edi
xor    %esi,%esi
call   1060 <lseek@plt>
test   %eax,%eax
je     12be <upload_firmware+0x10e>
lea    0x12fb(%rip),%rdi
jmp    126b <upload_firmware+0xbb>
lea    0x1338(%rip),%rdi
call   1030 <puts@plt>
jmp    12ad <upload_firmware+0xfd>
lea    0x132a(%rip),%rdi
call   1030 <puts@plt>
mov    %r13,%rdi
mov    $0x200,%esi
call   10a0 <free_aligned@plt>
xor    %ebx,%ebx
jmp    12ad <upload_firmware+0xfd>
lea    0x12e7(%rip),%rdi
call   1030 <puts@plt>
jmp    1285 <upload_firmware+0xd5>
lea    0xd87(%rip),%rdi
mov    $0x10000,%esi
xor    %eax,%eax
call   1050 <printf@plt>
lea    0x126d(%rip),%rdi
call   1030 <puts@plt>
xor    %ebx,%ebx
mov    %r14,%rdi
mov    $0x10000,%esi
call   10a0 <free_aligned@plt>
mov    %r13,%rdi
mov    $0x200,%esi
call   10a0 <free_aligned@plt>
mov    %ebx,%eax
add    $0x8,%rsp
pop    %rbx
pop    %r12
pop    %r13
pop    %r14
pop    %r15
pop    %rbp
ret
mov    %ebp,%edi
mov    %r14,%rsi
mov    $0x10000,%edx
call   1070 <read@plt>
cmp    $0x10000,%eax
jne    142f <upload_firmware+0x27f>
mov    %r14,%rdi
mov    $0x8000,%esi
call   10b0 <checksum32@plt>
mov    %eax,%r15d
lea    0xd3e(%rip),%rdi
xor    %esi,%esi
xor    %edx,%edx
mov    $0x7fff,%ecx
xor    %eax,%eax
call   1050 <printf@plt>
mov    %r12d,%edi
mov    $0x3,%esi
mov    $0x80000000,%edx
mov    $0x8000,%ecx
xor    %r8d,%r8d
call   10c0 <sendcmd@plt>
cmp    $0x1,%eax
jne    143b <upload_firmware+0x28b>
mov    %r12d,%edi
mov    %r14,%rsi
mov    $0x8000,%edx
call   1080 <write_data@plt>
cmp    $0x8000,%eax
jne    1444 <upload_firmware+0x294>
lea    0x4(%rsp),%rdx
mov    %r12d,%edi
mov    $0x6,%esi
call   10d0 <checksum_page@plt>
cmp    $0x1,%eax
jne    144d <upload_firmware+0x29d>
mov    0x4(%rsp),%ecx
cmp    %ecx,%r15d
jne    1467 <upload_firmware+0x2b7>
lea    0xd4e(%rip),%rdi
xor    %esi,%esi
xor    %eax,%eax
call   1050 <printf@plt>
mov    %r14,%rbx
add    $0x8000,%rbx
mov    %rbx,%rdi
mov    $0x8000,%esi
call   10b0 <checksum32@plt>
mov    %eax,%r15d
lea    0xc97(%rip),%rdi
mov    $0x1,%esi
mov    $0x8000,%edx
mov    $0xffff,%ecx
xor    %eax,%eax
call   1050 <printf@plt>
mov    %r12d,%edi
mov    $0x3,%esi
mov    $0x80000001,%edx
mov    $0x8000,%ecx
xor    %r8d,%r8d
call   10c0 <sendcmd@plt>
cmp    $0x1,%eax
jne    143b <upload_firmware+0x28b>
mov    %r12d,%edi
mov    %rbx,%rsi
mov    $0x8000,%edx
call   1080 <write_data@plt>
cmp    $0x8000,%eax
jne    1444 <upload_firmware+0x294>
lea    0x4(%rsp),%rdx
mov    %r12d,%edi
mov    $0x7,%esi
call   10d0 <checksum_page@plt>
cmp    $0x1,%eax
jne    144d <upload_firmware+0x29d>
mov    0x4(%rsp),%ecx
cmp    %ecx,%r15d
jne    1486 <upload_firmware+0x2d6>
lea    0xcad(%rip),%rdi
mov    $0x1,%ebx
mov    $0x1,%esi
xor    %eax,%eax
call   1050 <printf@plt>
lea    0xf6c(%rip),%rdi
call   1030 <puts@plt>
jmp    1293 <upload_firmware+0xe3>
lea    0x10a1(%rip),%rdi
jmp    126b <upload_firmware+0xbb>
lea    0xc16(%rip),%rdi
jmp    1454 <upload_firmware+0x2a4>
lea    0xc33(%rip),%rdi
jmp    1454 <upload_firmware+0x2a4>
lea    0xc46(%rip),%rdi
xor    %eax,%eax
call   1050 <printf@plt>
lea    0xfe1(%rip),%rdi
jmp    128c <upload_firmware+0xdc>
xor    %esi,%esi
lea    0xc67(%rip),%rdi
mov    %r15d,%edx
xor    %eax,%eax
call   1050 <printf@plt>
lea    0xfc2(%rip),%rdi
jmp    128c <upload_firmware+0xdc>
mov    $0x1,%esi
jmp    1469 <upload_firmware+0x2b9>

LLVM IR (-O0):
@.str = [630 x i8] c"*** WARNING ***\0AThis performs a firmware upgrade. If done incorrectly,\0Ait may brick your photo frame, making it unusable.\0A\0AThis program writes the firmware to a temporary location, overwriting\0Athe second photo. At the same time, it sets a flag which triggers a\0Afirmware upgrade after the photo frame is unplugged from USB.\0A\0AEnsure the photo frame is turned on, so it does not lose power when\0AUSB is disconnected.\0A\0AOnce the flag is set, it cannot be cleared. However, you can try to\0Aupload the firmware again. Ensure you have a good upload before you\0Adisconnect USB. That is the final point of no return.\0A\0APress Enter to proceed.\0A\00"
@.str.1 = [48 x i8] c"ERROR: Failed to allocate buffer for checksum.\0A\00"
@SEEK_END = global i32 0
@.str.2 = [39 x i8] c"ERROR: Failed to seek to end of file.\0A\00"
@.str.3 = [45 x i8] c"ERROR: File size wrong, should be %i bytes.\0A\00"
@SEEK_SET = global i32 0
@.str.4 = [33 x i8] c"ERROR: Failed to start of file.\0A\00"
@.str.5 = [35 x i8] c"ERROR: Firmware file read failed.\0A\00"
@.str.6 = [43 x i8] c"Writing firmware block %i (0x%04x-0x%04x)\0A\00"
@.str.7 = [38 x i8] c"ERROR: Failed to send upload command.\00"
@.str.8 = [28 x i8] c"ERROR: Failed to send data.\00"
@.str.9 = [32 x i8] c"ERROR: Failed to read checksum.\00"
@.str.10 = [29 x i8] c"Checksum okay for block %i.\0A\00"
@.str.11 = [69 x i8] c"ERROR: Checksum mismatch at block %i: should be %08x, but got %08x.\0A\00"
@.str.12 = [179 x i8] c"\0AFirmware upload successful. Disconnect USB to begin firmware upgrade.\0ASwitch must be on to continue powering the device after USB is\0Adisconnected. Do not interrupt the process!\0A\00"
@.str.13 = [149 x i8] c"The photo frame may be bricked when you disconnect USB and it attempts to\0Aupdate. Try to perform a successful firmware update before disconnecting.\0A\00"
@.str.14 = [58 x i8] c"This failure was safe. No firmware upload was performed.\0A\00"
define i32 @upload_firmware(i32 %0, i32 %1) {
%3 = alloca i32
%4 = alloca i32
%5 = alloca i32
%6 = alloca i32
%7 = alloca i32
%8 = alloca i32
%9 = alloca i8*
%10 = alloca i8*
%11 = alloca i32
%12 = alloca i32
%13 = alloca i32
%14 = alloca i8*
store i32 %0, i32* %4
store i32 %1, i32* %5
store i32 0, i32* %11
%15 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([630 x i8], [630 x i8]* @.str, i64 0, i64 0))
%16 = call i32 (...) @getchar()
%17 = call i8* @malloc_aligned(i32 512)
store i8* %17, i8** %9
%18 = load i8*, i8** %9
%19 = icmp eq i8* %18, null
br i1 %19, label %20, label %22
20: ; preds = %2
%21 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([48 x i8], [48 x i8]* @.str.1, i64 0, i64 0))
store i32 0, i32* %3
br label %138
22: ; preds = %2
%23 = call i8* @malloc_aligned(i32 65536)
store i8* %23, i8** %10
%24 = load i8*, i8** %10
%25 = icmp eq i8* %24, null
br i1 %25, label %26, label %30
26: ; preds = %22
%27 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([48 x i8], [48 x i8]* @.str.1, i64 0, i64 0))
%28 = load i8*, i8** %9
%29 = call i32 @free_aligned(i8* %28, i32 512)
store i32 0, i32* %3
br label %138
30: ; preds = %22
%31 = load i32, i32* %5
%32 = load i32, i32* @SEEK_END
%33 = call i32 @lseek(i32 %31, i32 0, i32 %32)
store i32 %33, i32* %6
%34 = load i32, i32* %6
%35 = icmp slt i32 %34, 0
br i1 %35, label %36, label %38
36: ; preds = %30
%37 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([39 x i8], [39 x i8]* @.str.2, i64 0, i64 0))
br label %130
38: ; preds = %30
%39 = load i32, i32* %6
%40 = icmp ne i32 %39, 65536
br i1 %40, label %41, label %43
41: ; preds = %38
%42 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([45 x i8], [45 x i8]* @.str.3, i64 0, i64 0), i32 65536)
br label %130
43: ; preds = %38
br label %44
44: ; preds = %43
%45 = load i32, i32* %5
%46 = load i32, i32* @SEEK_SET
%47 = call i32 @lseek(i32 %45, i32 0, i32 %46)
store i32 %47, i32* %6
%48 = load i32, i32* %6
%49 = icmp ne i32 %48, 0
br i1 %49, label %50, label %52
50: ; preds = %44
%51 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([33 x i8], [33 x i8]* @.str.4, i64 0, i64 0))
br label %130
52: ; preds = %44
%53 = load i32, i32* %5
%54 = load i8*, i8** %10
%55 = call i32 @read(i32 %53, i8* %54, i32 65536)
store i32 %55, i32* %7
%56 = load i32, i32* %7
%57 = icmp ne i32 %56, 65536
br i1 %57, label %58, label %60
58: ; preds = %52
%59 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([35 x i8], [35 x i8]* @.str.5, i64 0, i64 0))
br label %130
60: ; preds = %52
store i32 0, i32* %8
br label %61
61: ; preds = %123, %60
%62 = load i32, i32* %8
%63 = icmp slt i32 %62, 2
br i1 %63, label %64, label %126
64: ; preds = %61
%65 = load i8*, i8** %10
%66 = load i32, i32* %8
%67 = mul nsw i32 32768, %66
%68 = sext i32 %67 to i64
%69 = getelementptr inbounds i8, i8* %65, i64 %68
store i8* %69, i8** %14
%70 = load i8*, i8** %14
%71 = call i32 @checksum32(i8* %70, i32 32768)
store i32 %71, i32* %12
%72 = load i32, i32* %8
%73 = load i8*, i8** %14
%74 = load i8*, i8** %10
%75 = ptrtoint i8* %73 to i64
%76 = ptrtoint i8* %74 to i64
%77 = sub i64 %75, %76
%78 = trunc i64 %77 to i32
%79 = load i8*, i8** %14
%80 = load i8*, i8** %10
%81 = ptrtoint i8* %79 to i64
%82 = ptrtoint i8* %80 to i64
%83 = sub i64 %81, %82
%84 = add nsw i64 %83, 32768
%85 = sub nsw i64 %84, 1
%86 = trunc i64 %85 to i32
%87 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([43 x i8], [43 x i8]* @.str.6, i64 0, i64 0), i32 %72, i32 %78, i32 %86)
%88 = load i32, i32* %4
%89 = load i32, i32* %8
%90 = or i32 %89, -2147483648
%91 = call i32 @sendcmd(i32 %88, i32 3, i32 %90, i32 32768, i32 0)
%92 = icmp ne i32 %91, 1
br i1 %92, label %93, label %95
93: ; preds = %64
%94 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([38 x i8], [38 x i8]* @.str.7, i64 0, i64 0))
br label %128
95: ; preds = %64
%96 = load i32, i32* %4
%97 = load i8*, i8** %14
%98 = call i32 @write_data(i32 %96, i8* %97, i32 32768)
%99 = icmp ne i32 %98, 32768
br i1 %99, label %100, label %102
100: ; preds = %95
%101 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([28 x i8], [28 x i8]* @.str.8, i64 0, i64 0))
br label %128
102: ; preds = %95
%103 = load i32, i32* %4
%104 = load i32, i32* %8
%105 = add nsw i32 %104, 6
%106 = call i32 @checksum_page(i32 %103, i32 %105, i32* %13)
%107 = icmp ne i32 %106, 1
br i1 %107, label %108, label %110
108: ; preds = %102
%109 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([32 x i8], [32 x i8]* @.str.9, i64 0, i64 0))
br label %128
110: ; preds = %102
%111 = load i32, i32* %12
%112 = load i32, i32* %13
%113 = icmp eq i32 %111, %112
br i1 %113, label %114, label %117
114: ; preds = %110
%115 = load i32, i32* %8
%116 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([29 x i8], [29 x i8]* @.str.10, i64 0, i64 0), i32 %115)
br label %122
117: ; preds = %110
%118 = load i32, i32* %8
%119 = load i32, i32* %12
%120 = load i32, i32* %13
%121 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([69 x i8], [69 x i8]* @.str.11, i64 0, i64 0), i32 %118, i32 %119, i32 %120)
br label %128
122: ; preds = %114
br label %123
123: ; preds = %122
%124 = load i32, i32* %8
%125 = add nsw i32 %124, 1
store i32 %125, i32* %8
br label %61
126: ; preds = %61
%127 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([179 x i8], [179 x i8]* @.str.12, i64 0, i64 0))
store i32 1, i32* %11
br label %132
128: ; preds = %117, %108, %100, %93
%129 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([149 x i8], [149 x i8]* @.str.13, i64 0, i64 0))
br label %132
130: ; preds = %58, %50, %41, %36
%131 = call i32 (i8*, ...) @printf(i8* getelementptr inbounds ([58 x i8], [58 x i8]* @.str.14, i64 0, i64 0))
br label %132
132: ; preds = %130, %128, %126
%133 = load i8*, i8** %10
%134 = call i32 @free_aligned(i8* %133, i32 65536)
%135 = load i8*, i8** %9
%136 = call i32 @free_aligned(i8* %135, i32 512)
%137 = load i32, i32* %11
store i32 %137, i32* %3
br label %138
138: ; preds = %132, %26, %20
%139 = load i32, i32* %3
ret i32 %139
}

LLVM IR (-O2):
@SEEK_END = global i32 0
@.str.3 = [45 x i8] c"ERROR: File size wrong, should be %i bytes.\0A\00"
@SEEK_SET = global i32 0
@.str.6 = [43 x i8] c"Writing firmware block %i (0x%04x-0x%04x)\0A\00"
@.str.7 = [38 x i8] c"ERROR: Failed to send upload command.\00"
@.str.8 = [28 x i8] c"ERROR: Failed to send data.\00"
@.str.9 = [32 x i8] c"ERROR: Failed to read checksum.\00"
@.str.10 = [29 x i8] c"Checksum okay for block %i.\0A\00"
@.str.11 = [69 x i8] c"ERROR: Checksum mismatch at block %i: should be %08x, but got %08x.\0A\00"
@str = [629 x i8] c"*** WARNING ***\0AThis performs a firmware upgrade. If done incorrectly,\0Ait may brick your photo frame, making it unusable.\0A\0AThis program writes the firmware to a temporary location, overwriting\0Athe second photo. At the same time, it sets a flag which triggers a\0Afirmware upgrade after the photo frame is unplugged from USB.\0A\0AEnsure the photo frame is turned on, so it does not lose power when\0AUSB is disconnected.\0A\0AOnce the flag is set, it cannot be cleared. However, you can try to\0Aupload the firmware again. Ensure you have a good upload before you\0Adisconnect USB. That is the final point of no return.\0A\0APress Enter to proceed.\00"
@str.15 = [178 x i8] c"\0AFirmware upload successful. Disconnect USB to begin firmware upgrade.\0ASwitch must be on to continue powering the device after USB is\0Adisconnected. Do not interrupt the process!\00"
@str.16 = [148 x i8] c"The photo frame may be bricked when you disconnect USB and it attempts to\0Aupdate. Try to perform a successful firmware update before disconnecting.\00"
@str.17 = [34 x i8] c"ERROR: Firmware file read failed.\00"
@str.18 = [57 x i8] c"This failure was safe. No firmware upload was performed.\00"
@str.19 = [32 x i8] c"ERROR: Failed to start of file.\00"
@str.20 = [38 x i8] c"ERROR: Failed to seek to end of file.\00"
@str.22 = [47 x i8] c"ERROR: Failed to allocate buffer for checksum.\00"
define i32 @upload_firmware(i32 %0, i32 %1) {
%3 = alloca i32
%4 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([629 x i8], [629 x i8]* @str, i64 0, i64 0))
%5 = tail call i32 (...) @getchar()
%6 = tail call i8* @malloc_aligned(i32 512)
%7 = icmp eq i8* %6, null
br i1 %7, label %8, label %10
8: ; preds = %2
%9 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([47 x i8], [47 x i8]* @str.22, i64 0, i64 0))
br label %90
10: ; preds = %2
%11 = tail call i8* @malloc_aligned(i32 65536)
%12 = icmp eq i8* %11, null
br i1 %12, label %13, label %16
13: ; preds = %10
%14 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([47 x i8], [47 x i8]* @str.22, i64 0, i64 0))
%15 = tail call i32 @free_aligned(i8* %6, i32 512)
br label %90
16: ; preds = %10
%17 = load i32, i32* @SEEK_END
%18 = tail call i32 @lseek(i32 %1, i32 0, i32 %17)
%19 = icmp slt i32 %18, 0
br i1 %19, label %20, label %22
20: ; preds = %16
%21 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([38 x i8], [38 x i8]* @str.20, i64 0, i64 0))
br label %84
22: ; preds = %16
%23 = icmp eq i32 %18, 65536
br i1 %23, label %26, label %24
24: ; preds = %22
%25 = tail call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([45 x i8], [45 x i8]* @.str.3, i64 0, i64 0), i32 65536)
br label %84
26: ; preds = %22
%27 = load i32, i32* @SEEK_SET
%28 = tail call i32 @lseek(i32 %1, i32 0, i32 %27)
%29 = icmp eq i32 %28, 0
br i1 %29, label %32, label %30
30: ; preds = %26
%31 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @str.19, i64 0, i64 0))
br label %84
32: ; preds = %26
%33 = tail call i32 @read(i32 %1, i8* %11, i32 65536)
%34 = icmp eq i32 %33, 65536
br i1 %34, label %35, label %41
35: ; preds = %32
%36 = bitcast i32* %3 to i8*
%37 = call i32 @checksum32(i8* %11, i32 32768)
%38 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([43 x i8], [43 x i8]* @.str.6, i64 0, i64 0), i32 0, i32 0, i32 32767)
%39 = call i32 @sendcmd(i32 %0, i32 3, i32 -2147483648, i32 32768, i32 0)
%40 = icmp eq i32 %39, 1
br i1 %40, label %45, label %43
41: ; preds = %32
%42 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([34 x i8], [34 x i8]* @str.17, i64 0, i64 0))
br label %84
43: ; preds = %63, %35
%44 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([38 x i8], [38 x i8]* @.str.7, i64 0, i64 0))
br label %82
45: ; preds = %35
%46 = call i32 @write_data(i32 %0, i8* %11, i32 32768)
%47 = icmp eq i32 %46, 32768
br i1 %47, label %50, label %48
48: ; preds = %70, %45
%49 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([28 x i8], [28 x i8]* @.str.8, i64 0, i64 0))
br label %82
50: ; preds = %45
%51 = call i32 @checksum_page(i32 %0, i32 6, i32* %3)
%52 = icmp eq i32 %51, 1
br i1 %52, label %55, label %53
53: ; preds = %73, %50
%54 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([32 x i8], [32 x i8]* @.str.9, i64 0, i64 0))
br label %82
55: ; preds = %50
%56 = load i32, i32* %3
%57 = icmp eq i32 %37, %56
br i1 %57, label %63, label %58
58: ; preds = %76, %55
%59 = phi i32 [ %56, %55 ], [ %77, %76 ]
%60 = phi i32 [ 0, %55 ], [ 1, %76 ]
%61 = phi i32 [ %37, %55 ], [ %66, %76 ]
%62 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([69 x i8], [69 x i8]* @.str.11, i64 0, i64 0), i32 %60, i32 %61, i32 %59)
br label %82
63: ; preds = %55
%64 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([29 x i8], [29 x i8]* @.str.10, i64 0, i64 0), i32 0)
%65 = getelementptr inbounds i8, i8* %11, i64 32768
%66 = call i32 @checksum32(i8* %65, i32 32768)
%67 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([43 x i8], [43 x i8]* @.str.6, i64 0, i64 0), i32 1, i32 32768, i32 65535)
%68 = call i32 @sendcmd(i32 %0, i32 3, i32 -2147483647, i32 32768, i32 0)
%69 = icmp eq i32 %68, 1
br i1 %69, label %70, label %43
70: ; preds = %63
%71 = call i32 @write_data(i32 %0, i8* %65, i32 32768)
%72 = icmp eq i32 %71, 32768
br i1 %72, label %73, label %48
73: ; preds = %70
%74 = call i32 @checksum_page(i32 %0, i32 7, i32* %3)
%75 = icmp eq i32 %74, 1
br i1 %75, label %76, label %53
76: ; preds = %73
%77 = load i32, i32* %3
%78 = icmp eq i32 %66, %77
br i1 %78, label %79, label %58
79: ; preds = %76
%80 = call i32 (i8*, ...) @printf(i8* dereferenceable(1) getelementptr inbounds ([29 x i8], [29 x i8]* @.str.10, i64 0, i64 0), i32 1)
%81 = call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([178 x i8], [178 x i8]* @str.15, i64 0, i64 0))
br label %86
82: ; preds = %43, %48, %53, %58
%83 = call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([148 x i8], [148 x i8]* @str.16, i64 0, i64 0))
br label %86
84: ; preds = %41, %30, %24, %20
%85 = tail call i32 @puts(i8* dereferenceable(1) getelementptr inbounds ([57 x i8], [57 x i8]* @str.18, i64 0, i64 0))
br label %86
86: ; preds = %84, %82, %79
%87 = phi i32 [ 0, %84 ], [ 0, %82 ], [ 1, %79 ]
%88 = call i32 @free_aligned(i8* %11, i32 65536)
%89 = call i32 @free_aligned(i8* %6, i32 512)
br label %90
90: ; preds = %86, %13, %8
%91 = phi i32 [ 0, %8 ], [ 0, %13 ], [ %87, %86 ]
ret i32 %91
}