// File: /workspace/github_c_makefile_star2_O0/jogolden[P]ps4flashtool/flashtool.c
// Function: main
int main(int argc, char **argv) {
    int i;
    char *flashfile = NULL;
    char *flashout = NULL;
    char *extractdir = NULL;
    char *rawextractdir = NULL;
    char *emcipl = NULL;
    char *eapkbl = NULL;
    char *eapkern = NULL;

    char *keyfile = FLASHTOOL_KEYFILE;
    unsigned char *flashdata = NULL;
    unsigned char *ptr = NULL, *ptr2 = NULL;
    unsigned int len, len2;

    printf("~ PlayStation 4 flash tool " FLASHTOOL_VERSION " | by " FLASHTOOL_CREDITS " ~\n");

    if(argc == 1) {
        printf("try '%s --help' for more information\n", argv[0]);
        return 0;
    }

    // make sure this is zero
    verbose = 0;
    noverify = 0;

    for(i = 1; i < argc; i++) {
        char *opt = argv[i];
        char *arg = (i == argc - 1) ? NULL : argv[i + 1];

        if(opt[0] != '-') {
            printf("error: invalid argument syntax!\n");
            return 1;
        }
        if(opt[0] == '-') { opt++; }
        if(opt[0] == '-') { opt++; }
        
        if(opt[0] == 'h' || !strcmp(opt, "help")) {
            print_usage();
            return 1;
        } else if(opt[0] == 'v' || !strcmp(opt, "verbose")) {
            verbose = 1;
        } else if(opt[0] == 'i' || !strcmp(opt, "input")) {
            if(!arg) {
                printf("error: invalid flash input argument!\n");
                return 1;
            }
            flashfile = arg;
            i++;
        } else if(opt[0] == 'o' || !strcmp(opt, "output")) {
            if(!arg) {
                printf("error: invalid flash output argument!\n");
                return 1;
            }
            flashout = arg;
            i++;
        } else if(opt[0] == 'n' || !strcmp(opt, "noverify")) {
            noverify = 1;
        } else if(opt[0] == 'k' || !strcmp(opt, "keyfile")) {
            if(!arg) {
                printf("error: invalid keyfile argument!\n");
                return 1;
            }
            keyfile = arg;
            printf("* changed keyfile to '%s'\n", keyfile);
            i++;
        } else if(!strcmp(opt, "extract")) {
            if(!arg) {
                printf("error: invalid extract directory argument!\n");
                return 1;
            }
            extractdir = arg;
            i++;
        } else if(!strcmp(opt, "rawextract")) {
            if(!arg) {
                printf("error: invalid raw extract directory argument!\n");
                return 1;
            }
            rawextractdir = arg;
            i++;
        } else if(!strcmp(opt, "emcipl")) {
            if(!arg) {
                printf("error: invalid emcipl argument!\n");
                return 1;
            }
            emcipl = arg;
            i++;
        } else if(!strcmp(opt, "eapkbl")) {
            if(!arg) {
                printf("error: invalid eapkbl argument!\n");
                return 1;
            }
            eapkbl = arg;
            i++;
        } else if(!strcmp(opt, "eapkern")) {
            if(!arg) {
                printf("error: invalid eapkern argument!\n");
                return 1;
            }
            eapkern = arg;
            i++;
        } else {
            printf("error: unknown option '%s'\n", opt);
            printf("try '%s --help' for more information\n", argv[0]);
            return 1;
        }
    }

    if(eapkern) {
        char *comma = strstr(eapkern, ",");
        if(!comma) {
            printf("error: please use a comma between the input and output for EAP kernel decryption\n");
            goto end;
        }

        comma[0] = '\0';

        char *input = eapkern;
        char *output = comma + 1;
        
        if(readbin(input, &ptr, &len)) {
            printf("error: failed to read EAP kernel from file!\n");
            goto end;
        }

        printf("attempting to decrypt EAP kernel '%s' to '%s' ...\n", input, output);
        printf("* keys may or not work on your console model/firmware version\n");

        if(decrypt_decompress_eap_kernel(ptr, len, &ptr2, &len2)) {
            printf("error: failed to decrypt EAP kernel\n");
            goto end;
        }

        dumpbin(output, ptr2, len2);

        printf("wrote decrypted EAP kernel\n");

        free(ptr);
        free(ptr2);

        goto end;
    }

    if(!flashfile) {
        printf("error: please specify a PlayStation 4 flash file!\n");
        goto end;
    }
    
    // load flash
    flashdata = load_flashdump(flashfile);
    if(!flashdata) {
        printf("error: invalid flash file!\n");
        goto end;
    }
    
    print_flashinfo(flashdata);

    if(verbose) {
        find_and_print_slb2_info(flashdata);
    }
    
    // raw extract does not require a key file so do it before
    if(rawextractdir) {
        if(rawextract_flashdump(flashdata, rawextractdir)) {
            printf("error: raw extract failed!\n");
        }

        goto end;
    }

    // load the keys
    printf("loading key file '%s' ...\n", keyfile);
    if(keymgr_loadkeys(keyfile)) {
        return 1;
    }

    if(verbose) {
        keymgr_printkeys();
    }
    
    // check flash
    if(!noverify) {
        if(check_flashdump(flashdata)) {
            printf("error: invalid flash data detected!\n");
            goto end;
        }
    }
    
    // replace emc ipl
    if(emcipl) {
        printf("replacing EMC IPL in flash dump with '%s' ...\n", emcipl);

        if(readbin(emcipl, &ptr, &len)) {
            printf("error: failed to read EMC IPL from file!\n");
            goto end;
        }

        if(replace_emc_ipl(flashdata, ptr, len)) {
            printf("warning: failed to replace EMC IPL!\n");
        }

        free(ptr);
    }
    
    // replace eap kbl
    if(eapkbl) {
        printf("replacing EAP KBL in flash dump with '%s' ...\n", eapkbl);

        if(readbin(eapkbl, &ptr, &len)) {
            printf("error: failed to read EAP KBL from file!\n");
            goto end;
        }

        if(replace_eap_kbl(flashdata, ptr, len)) {
            printf("warning: failed to replace EAP KBL!\n");
        }

        free(ptr);
    }
    
    // extract parts
    if(extractdir) {
        if(extract_flashdump(flashdata, extractdir)) {
            printf("error: failed during flash extraction!\n");
            goto end;
        }
    }

    // write flashdata out
    if(flashout) {
        // enable uart ;)
        char uart = 1;
        nvs_write(flashdata, 0, 4, NVS_VAR_BLOCK4_ENABLE_UART, 1, &uart);

        if(verbose) {
            printf("* enabled uart in NVS region\n");
        }

        dumpbin(flashout, flashdata, FLASH_SIZE);
        printf("wrote final flash to '%s'\n", flashout);
    }

end:
    if(flashdata) {
        free(flashdata);
    }

    keymgr_cleanup();

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0xb0, %rsp
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
movq $0x0, -0x20(%rbp)
movq $0x0, -0x28(%rbp)
movq $0x0, -0x30(%rbp)
movq $0x0, -0x38(%rbp)
movq $0x0, -0x40(%rbp)
movq $0x0, -0x48(%rbp)
movq $0x0, -0x50(%rbp)
leaq 0x66d3(%rip), %rax      # 0xcafb
movq %rax, -0x58(%rbp)
movq $0x0, -0x60(%rbp)
movq $0x0, -0x68(%rbp)
movq $0x0, -0x70(%rbp)
leaq 0x66bc(%rip), %rdi      # 0xcb07
movb $0x0, %al
callq 0x2080
cmpl $0x1, -0x8(%rbp)
jne 0x6479
movq -0x10(%rbp), %rax
movq (%rax), %rsi
leaq 0x66d0(%rip), %rdi      # 0xcb36
movb $0x0, %al
callq 0x2080
movl $0x0, -0x4(%rbp)
jmp 0x6c92
movl $0x0, 0x9ec1(%rip)      # 0x10344
movl $0x0, 0x9ebb(%rip)      # 0x10348
movl $0x1, -0x14(%rbp)
movl -0x14(%rbp), %eax
cmpl -0x8(%rbp), %eax
jge 0x68f0
movq -0x10(%rbp), %rax
movslq -0x14(%rbp), %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0x80(%rbp)
movl -0x14(%rbp), %eax
movl -0x8(%rbp), %ecx
subl $0x1, %ecx
cmpl %ecx, %eax
jne 0x64c8
xorl %eax, %eax
movq %rax, -0xb0(%rbp)
jmp 0x64e0
movq -0x10(%rbp), %rax
movl -0x14(%rbp), %ecx
addl $0x1, %ecx
movslq %ecx, %rcx
movq (%rax,%rcx,8), %rax
movq %rax, -0xb0(%rbp)
movq -0xb0(%rbp), %rax
movq %rax, -0x88(%rbp)
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
je 0x6514
leaq 0x665b(%rip), %rdi      # 0xcb5c
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
jne 0x652c
movq -0x80(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x2d, %eax
jne 0x6544
movq -0x80(%rbp), %rax
addq $0x1, %rax
movq %rax, -0x80(%rbp)
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x68, %eax
je 0x6565
movq -0x80(%rbp), %rdi
leaq 0x62f9(%rip), %rsi      # 0xc854
callq 0x20c0
cmpl $0x0, %eax
jne 0x6576
callq 0x5e50
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x76, %eax
je 0x6597
movq -0x80(%rbp), %rdi
leaq 0x62ed(%rip), %rsi      # 0xc87a
callq 0x20c0
cmpl $0x0, %eax
jne 0x65a6
movl $0x1, 0x9da3(%rip)      # 0x10344
jmp 0x68de
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x69, %eax
je 0x65c7
movq -0x80(%rbp), %rdi
leaq 0x62fc(%rip), %rsi      # 0xc8b9
callq 0x20c0
cmpl $0x0, %eax
jne 0x6604
cmpq $0x0, -0x88(%rbp)
jne 0x65eb
leaq 0x65a5(%rip), %rdi      # 0xcb7d
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x88(%rbp), %rax
movq %rax, -0x20(%rbp)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x68dc
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x6f, %eax
je 0x6625
movq -0x80(%rbp), %rdi
leaq 0x62b1(%rip), %rsi      # 0xc8cc
callq 0x20c0
cmpl $0x0, %eax
jne 0x6662
cmpq $0x0, -0x88(%rbp)
jne 0x6649
leaq 0x656d(%rip), %rdi      # 0xcba3
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x88(%rbp), %rax
movq %rax, -0x28(%rbp)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x68da
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x6e, %eax
je 0x6683
movq -0x80(%rbp), %rdi
leaq 0x625a(%rip), %rsi      # 0xc8d3
callq 0x20c0
cmpl $0x0, %eax
jne 0x6692
movl $0x1, 0x9cbb(%rip)      # 0x10348
jmp 0x68d8
movq -0x80(%rbp), %rax
movsbl (%rax), %eax
cmpl $0x6b, %eax
je 0x66b3
movq -0x80(%rbp), %rdi
leaq 0x6258(%rip), %rsi      # 0xc901
callq 0x20c0
cmpl $0x0, %eax
jne 0x6702
cmpq $0x0, -0x88(%rbp)
jne 0x66d7
leaq 0x6506(%rip), %rdi      # 0xcbca
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x88(%rbp), %rax
movq %rax, -0x58(%rbp)
movq -0x58(%rbp), %rsi
leaq 0x64ff(%rip), %rdi      # 0xcbec
movb $0x0, %al
callq 0x2080
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x68d6
movq -0x80(%rbp), %rdi
leaq 0x622c(%rip), %rsi      # 0xc939
callq 0x20c0
cmpl $0x0, %eax
jne 0x6754
cmpq $0x0, -0x88(%rbp)
jne 0x673b
leaq 0x64df(%rip), %rdi      # 0xcc07
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x88(%rbp), %rax
movq %rax, -0x30(%rbp)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x68d4
movq -0x80(%rbp), %rdi
leaq 0x61d7(%rip), %rsi      # 0xc936
callq 0x20c0
cmpl $0x0, %eax
jne 0x67a6
cmpq $0x0, -0x88(%rbp)
jne 0x678d
leaq 0x64b9(%rip), %rdi      # 0xcc33
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x88(%rbp), %rax
movq %rax, -0x38(%rbp)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x68d2
movq -0x80(%rbp), %rdi
leaq 0x61af(%rip), %rsi      # 0xc960
callq 0x20c0
cmpl $0x0, %eax
jne 0x67f8
cmpq $0x0, -0x88(%rbp)
jne 0x67df
leaq 0x6497(%rip), %rdi      # 0xcc63
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x88(%rbp), %rax
movq %rax, -0x40(%rbp)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x68d0
movq -0x80(%rbp), %rdi
leaq 0x618d(%rip), %rsi      # 0xc990
callq 0x20c0
cmpl $0x0, %eax
jne 0x684a
cmpq $0x0, -0x88(%rbp)
jne 0x6831
leaq 0x6466(%rip), %rdi      # 0xcc84
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x88(%rbp), %rax
movq %rax, -0x48(%rbp)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x68ce
movq -0x80(%rbp), %rdi
leaq 0x6167(%rip), %rsi      # 0xc9bc
callq 0x20c0
cmpl $0x0, %eax
jne 0x6899
cmpq $0x0, -0x88(%rbp)
jne 0x6883
leaq 0x6435(%rip), %rdi      # 0xcca5
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
movq -0x88(%rbp), %rax
movq %rax, -0x50(%rbp)
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x68cc
movq -0x80(%rbp), %rsi
leaq 0x6423(%rip), %rdi      # 0xccc7
movb $0x0, %al
callq 0x2080
movq -0x10(%rbp), %rax
movq (%rax), %rsi
leaq 0x627d(%rip), %rdi      # 0xcb36
movb $0x0, %al
callq 0x2080
movl $0x1, -0x4(%rbp)
jmp 0x6c92
jmp 0x68ce
jmp 0x68d0
jmp 0x68d2
jmp 0x68d4
jmp 0x68d6
jmp 0x68d8
jmp 0x68da
jmp 0x68dc
jmp 0x68de
jmp 0x68e0
jmp 0x68e2
movl -0x14(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x14(%rbp)
jmp 0x6494
cmpq $0x0, -0x50(%rbp)
je 0x6a10
movq -0x50(%rbp), %rdi
leaq 0x63dd(%rip), %rsi      # 0xcce3
callq 0x2150
movq %rax, -0x90(%rbp)
cmpq $0x0, -0x90(%rbp)
jne 0x692f
leaq 0x63c2(%rip), %rdi      # 0xcce5
movb $0x0, %al
callq 0x2080
jmp 0x6c74
movq -0x90(%rbp), %rax
movb $0x0, (%rax)
movq -0x50(%rbp), %rax
movq %rax, -0x98(%rbp)
movq -0x90(%rbp), %rax
addq $0x1, %rax
movq %rax, -0xa0(%rbp)
movq -0x98(%rbp), %rdi
leaq -0x68(%rbp), %rsi
leaq -0x74(%rbp), %rdx
callq 0x5750
cmpl $0x0, %eax
je 0x6982
leaq 0x63c1(%rip), %rdi      # 0xcd37
movb $0x0, %al
callq 0x2080
jmp 0x6c74
movq -0x98(%rbp), %rsi
movq -0xa0(%rbp), %rdx
leaq 0x63cd(%rip), %rdi      # 0xcd64
movb $0x0, %al
callq 0x2080
leaq 0x63f2(%rip), %rdi      # 0xcd97
movb $0x0, %al
callq 0x2080
movq -0x68(%rbp), %rdi
movl -0x74(%rbp), %esi
leaq -0x70(%rbp), %rdx
leaq -0x78(%rbp), %rcx
callq 0xaf30
cmpl $0x0, %eax
je 0x69d8
leaq 0x640a(%rip), %rdi      # 0xcdd6
movb $0x0, %al
callq 0x2080
jmp 0x6c74
movq -0xa0(%rbp), %rdi
movq -0x70(%rbp), %rsi
movl -0x78(%rbp), %edx
callq 0x56e0
leaq 0x6409(%rip), %rdi      # 0xcdfb
movb $0x0, %al
callq 0x2080
movq -0x68(%rbp), %rdi
callq 0x2030
movq -0x70(%rbp), %rdi
callq 0x2030
jmp 0x6c74
cmpq $0x0, -0x20(%rbp)
jne 0x6a2a
leaq 0x63f9(%rip), %rdi      # 0xce17
movb $0x0, %al
callq 0x2080
jmp 0x6c74
movq -0x20(%rbp), %rdi
callq 0x5850
movq %rax, -0x60(%rbp)
cmpq $0x0, -0x60(%rbp)
jne 0x6a51
leaq 0x6405(%rip), %rdi      # 0xce4a
movb $0x0, %al
callq 0x2080
jmp 0x6c74
movq -0x60(%rbp), %rdi
callq 0x5a30
cmpl $0x0, 0x98e3(%rip)      # 0x10344
je 0x6a6c
movq -0x60(%rbp), %rdi
callq 0x6ca0
cmpq $0x0, -0x38(%rbp)
je 0x6a98
movq -0x60(%rbp), %rdi
movq -0x38(%rbp), %rsi
callq 0x5d10
cmpl $0x0, %eax
je 0x6a93
leaq 0x63da(%rip), %rdi      # 0xce66
movb $0x0, %al
callq 0x2080
jmp 0x6c74
movq -0x58(%rbp), %rsi
leaq 0x63df(%rip), %rdi      # 0xce82
movb $0x0, %al
callq 0x2080
movq -0x58(%rbp), %rdi
callq 0x6f60
cmpl $0x0, %eax
je 0x6ac4
movl $0x1, -0x4(%rbp)
jmp 0x6c92
cmpl $0x0, 0x9879(%rip)      # 0x10344
je 0x6ad4
movb $0x0, %al
callq 0x7180
cmpl $0x0, 0x986d(%rip)      # 0x10348
jne 0x6b00
movq -0x60(%rbp), %rdi
callq 0x5b40
cmpl $0x0, %eax
je 0x6afe
leaq 0x63ab(%rip), %rdi      # 0xce9d
movb $0x0, %al
callq 0x2080
jmp 0x6c74
jmp 0x6b00
cmpq $0x0, -0x40(%rbp)
je 0x6b6e
movq -0x40(%rbp), %rsi
leaq 0x63b0(%rip), %rdi      # 0xcec2
movb $0x0, %al
callq 0x2080
movq -0x40(%rbp), %rdi
leaq -0x68(%rbp), %rsi
leaq -0x74(%rbp), %rdx
callq 0x5750
cmpl $0x0, %eax
je 0x6b42
leaq 0x63bb(%rip), %rdi      # 0xcef1
movb $0x0, %al
callq 0x2080
jmp 0x6c74
movq -0x60(%rbp), %rdi
movq -0x68(%rbp), %rsi
movl -0x74(%rbp), %edx
callq 0xa230
cmpl $0x0, %eax
je 0x6b65
leaq 0x63bd(%rip), %rdi      # 0xcf1b
movb $0x0, %al
callq 0x2080
movq -0x68(%rbp), %rdi
callq 0x2030
cmpq $0x0, -0x48(%rbp)
je 0x6bdc
movq -0x48(%rbp), %rsi
leaq 0x63c0(%rip), %rdi      # 0xcf40
movb $0x0, %al
callq 0x2080
movq -0x48(%rbp), %rdi
leaq -0x68(%rbp), %rsi
leaq -0x74(%rbp), %rdx
callq 0x5750
cmpl $0x0, %eax
je 0x6bb0
leaq 0x63cb(%rip), %rdi      # 0xcf6f
movb $0x0, %al
callq 0x2080
jmp 0x6c74
movq -0x60(%rbp), %rdi
movq -0x68(%rbp), %rsi
movl -0x74(%rbp), %edx
callq 0xa810
cmpl $0x0, %eax
je 0x6bd3
leaq 0x63cd(%rip), %rdi      # 0xcf99
movb $0x0, %al
callq 0x2080
movq -0x68(%rbp), %rdi
callq 0x2030
cmpq $0x0, -0x30(%rbp)
je 0x6c07
movq -0x60(%rbp), %rdi
movq -0x30(%rbp), %rsi
callq 0x5b90
cmpl $0x0, %eax
je 0x6c05
leaq 0x63c2(%rip), %rdi      # 0xcfbe
movb $0x0, %al
callq 0x2080
jmp 0x6c74
jmp 0x6c07
cmpq $0x0, -0x28(%rbp)
je 0x6c72
movb $0x1, -0xa1(%rbp)
movq -0x60(%rbp), %rdi
xorl %esi, %esi
movl $0x4, %edx
movl $0x31f, %ecx            # imm = 0x31F
movl $0x1, %r8d
leaq -0xa1(%rbp), %r9
callq 0x7360
cmpl $0x0, 0x9706(%rip)      # 0x10344
je 0x6c4e
leaq 0x639f(%rip), %rdi      # 0xcfe6
movb $0x0, %al
callq 0x2080
movq -0x28(%rbp), %rdi
movq -0x60(%rbp), %rsi
movl $0x2000000, %edx        # imm = 0x2000000
callq 0x56e0
movq -0x28(%rbp), %rsi
leaq 0x6399(%rip), %rdi      # 0xd004
movb $0x0, %al
callq 0x2080
jmp 0x6c74
cmpq $0x0, -0x60(%rbp)
je 0x6c84
movq -0x60(%rbp), %rdi
callq 0x2030
movb $0x0, %al
callq 0x7120
movl $0x0, -0x4(%rbp)
movl -0x4(%rbp), %eax
addq $0xb0, %rsp
popq %rbp
retq
nop