// File: /workspace/github_c_makefile_star2_O0/orempel[P]multiboot_tool/twiboot.c
// Function: twi_open
static int twi_open(struct multiboot *mboot)
{
    struct twi_privdata *twi = (struct twi_privdata *)mboot->privdata;

    if (twi->address == 0)
    {
        fprintf(stderr, "abort: no address given\n");
        return -1;
    }

    if (twi->device == NULL)
    {
        twi->device = strdup(TWI_DEFAULT_DEVICE);
        if (twi->device == NULL)
        {
            perror("strdup()");
            return -1;
        }
    }

    if (twi_open_device(twi) != 0)
    {
        return -1;
    }

    if (twi_switch_application(twi, BOOTTYPE_BOOTLOADER))
    {
        fprintf(stderr, "failed to switch to bootloader (invalid address?): %s\n",
                strerror(errno));

        twi_close(mboot);
        return -1;
    }

    /* wait for watchdog and startup time */
    usleep(100000);

    char version[16 +1];
    if (twi_read_version(twi, version, sizeof(version) -1))
    {
        fprintf(stderr, "failed to get bootloader version: %s\n",
                strerror(errno));

        twi_close(mboot);
        return -1;
    }

    version[16] = '\0';

    uint8_t chipinfo[8];
    if (twi_read_memory(twi, chipinfo, sizeof(chipinfo), MEMTYPE_CHIPINFO, 0x0000))
    {
        fprintf(stderr, "failed to get chipinfo: %s\n", strerror(errno));
        twi_close(mboot);
        return -1;
    }

    const char *chipname = chipinfo_get_avr_name(chipinfo);

    twi->pagesize   = chipinfo[3];
    twi->flashsize  = (chipinfo[4] << 8) + chipinfo[5];
    twi->eepromsize = (chipinfo[6] << 8) + chipinfo[7];

    printf("device         : %-16s (address: 0x%02X)\n",
           twi->device, twi->address);

    printf("version        : %-16s (sig: 0x%02x 0x%02x 0x%02x => %s)\n",
           version, chipinfo[0], chipinfo[1], chipinfo[2], chipname);

    printf("flash size     : 0x%04x / %5d   (0x%02x bytes/page)\n",
           twi->flashsize, twi->flashsize, twi->pagesize);

    printf("eeprom size    : 0x%04x / %5d\n",
           twi->eepromsize, twi->eepromsize);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x60, %rsp
movq %rdi, -0x10(%rbp)
movq -0x10(%rbp), %rax
movq 0x8(%rax), %rax
movq %rax, -0x18(%rbp)
movq -0x18(%rbp), %rax
movzbl 0x8(%rax), %eax
cmpl $0x0, %eax
jne 0x9f29
movq 0x60ec(%rip), %rax      # 0xfff8
movq (%rax), %rdi
leaq 0x1e77(%rip), %rsi      # 0xbd8d
movb $0x0, %al
callq 0x2160
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa177
movq -0x18(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x9f6d
leaq 0x28f8(%rip), %rdi      # 0xc832
callq 0x2250
movq %rax, %rcx
movq -0x18(%rbp), %rax
movq %rcx, (%rax)
movq -0x18(%rbp), %rax
cmpq $0x0, (%rax)
jne 0x9f6b
leaq 0x11d4(%rip), %rdi      # 0xb12e
callq 0x2210
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa177
jmp 0x9f6d
movq -0x18(%rbp), %rdi
callq 0xa7b0
cmpl $0x0, %eax
je 0x9f87
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa177
movq -0x18(%rbp), %rdi
xorl %esi, %esi
callq 0xa940
cmpl $0x0, %eax
je 0x9fdb
movq 0x605a(%rip), %rax      # 0xfff8
movq (%rax), %rax
movq %rax, -0x48(%rbp)
callq 0x2050
movl (%rax), %edi
callq 0x2260
movq -0x48(%rbp), %rdi
movq %rax, %rdx
leaq 0x287e(%rip), %rsi      # 0xc83d
movb $0x0, %al
callq 0x2160
movq -0x10(%rbp), %rdi
callq 0xa180
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa177
movl $0x186a0, %edi          # imm = 0x186A0
callq 0x2280
movq -0x18(%rbp), %rdi
leaq -0x30(%rbp), %rsi
movl $0x10, %edx
callq 0xa990
cmpl $0x0, %eax
je 0xa040
movq 0x5ff5(%rip), %rax      # 0xfff8
movq (%rax), %rax
movq %rax, -0x50(%rbp)
callq 0x2050
movl (%rax), %edi
callq 0x2260
movq -0x50(%rbp), %rdi
movq %rax, %rdx
leaq 0x2850(%rip), %rsi      # 0xc874
movb $0x0, %al
callq 0x2160
movq -0x10(%rbp), %rdi
callq 0xa180
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa177
movb $0x0, -0x20(%rbp)
movq -0x18(%rbp), %rdi
leaq -0x38(%rbp), %rsi
movl $0x8, %edx
xorl %r8d, %r8d
movl %r8d, %ecx
callq 0xaa50
cmpl $0x0, %eax
je 0xa0a5
movq 0x5f90(%rip), %rax      # 0xfff8
movq (%rax), %rax
movq %rax, -0x58(%rbp)
callq 0x2050
movl (%rax), %edi
callq 0x2260
movq -0x58(%rbp), %rdi
movq %rax, %rdx
leaq 0x2811(%rip), %rsi      # 0xc89a
movb $0x0, %al
callq 0x2160
movq -0x10(%rbp), %rdi
callq 0xa180
movl $0xffffffff, -0x4(%rbp) # imm = 0xFFFFFFFF
jmp 0xa177
leaq -0x38(%rbp), %rdi
callq 0x3700
movq %rax, -0x40(%rbp)
movb -0x35(%rbp), %cl
movq -0x18(%rbp), %rax
movb %cl, 0x18(%rax)
movzbl -0x34(%rbp), %eax
shll $0x8, %eax
movzbl -0x33(%rbp), %ecx
addl %ecx, %eax
movw %ax, %cx
movq -0x18(%rbp), %rax
movw %cx, 0x1a(%rax)
movzbl -0x32(%rbp), %eax
shll $0x8, %eax
movzbl -0x31(%rbp), %ecx
addl %ecx, %eax
movw %ax, %cx
movq -0x18(%rbp), %rax
movw %cx, 0x1c(%rax)
movq -0x18(%rbp), %rax
movq (%rax), %rsi
movq -0x18(%rbp), %rax
movzbl 0x8(%rax), %edx
leaq 0x2281(%rip), %rdi      # 0xc383
movb $0x0, %al
callq 0x20d0
leaq -0x30(%rbp), %rsi
movzbl -0x38(%rbp), %edx
movzbl -0x37(%rbp), %ecx
movzbl -0x36(%rbp), %r8d
movq -0x40(%rbp), %r9
leaq 0x1d64(%rip), %rdi      # 0xbe89
movb $0x0, %al
callq 0x20d0
movq -0x18(%rbp), %rax
movzwl 0x1a(%rax), %esi
movq -0x18(%rbp), %rax
movzwl 0x1a(%rax), %edx
movq -0x18(%rbp), %rax
movzbl 0x18(%rax), %ecx
leaq 0x1d78(%rip), %rdi      # 0xbec3
movb $0x0, %al
callq 0x20d0
movq -0x18(%rbp), %rax
movzwl 0x1c(%rax), %esi
movq -0x18(%rbp), %rax
movzwl 0x1c(%rax), %edx
leaq 0x1347(%rip), %rdi      # 0xb4b0
movb $0x0, %al
callq 0x20d0
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0x60, %rsp
popq %rbp
retq