// File: FFY00[P]uicc/src/program_uicc.c
// Function: main
int main(int argc, char **argv) {
    char portName[FILENAME_MAX+1] = "/dev/ttyUSB0";
    struct uicc_vals new_vals;
    static struct option long_options[] = {
        {"port",  required_argument, 0, 0},
        {"adm",   required_argument, 0, 1},
        {"iccid", required_argument, 0, 2},
        {"imsi",  required_argument, 0, 3},
        {"opc",   required_argument, 0, 4},
        {"isdn",  required_argument, 0, 5},
        {"acc",   required_argument, 0, 6},
        {"key",   required_argument, 0, 7},
        {"MNCsize", required_argument, 0, 8},
        {"xx",    required_argument, 0, 9},
        {"authenticate",  no_argument, 0, 10},
        {"spn", required_argument, 0, 11},
        {0,       0,                 0, 0}
    };
    static map<string,string> help_text= {
        {"port",  "Linux port to access the card reader (/dev/ttyUSB0)"},
        {"adm",   "The ADM code of the card (the master password)"},
        {"iccid", "the UICC id to set"},
        {"imsi",  "The imsi to set, we automatically set complementary files such as \"home PLMN\""},
        {"opc",   "OPc field: OPerator code: must be also set in HSS (exlusive with OP)"},
        {"isdn",  "The mobile phone number (not used in simple 4G)"},
        {"acc",   "One of the defined security codes"},
        {"key",   "The authentication key (called Ki in 3G/4G, Kc in GSM), must be the same in HSS"},
        {"MNCsize","Mobile network code size in digits (default to 2)"},
        {"xx",    "OP  field: OPerator code: must be also set in HSS (exclusive with OPc)"},
        {"spn",   "service provider name: the name that the UE will show as 'network'"},
        {"authenticate",  "Test the milenage authentication and discover the current sequence number"},
    };
    int c;
    bool correctOpt=true;

    while (correctOpt) {
        int option_index = 0;
        c = getopt_long_only(argc, argv, "",
                             long_options, &option_index);

        if (c == -1)
            break;

        new_vals.setIt= c > 0;

        switch (c) {
        case 0:
            strncpy(portName, optarg, FILENAME_MAX);
            break;

        case 1:
            new_vals.adm=optarg;
            break;

        case 2:
            new_vals.iccid=optarg;
            break;

        case 3:
            new_vals.imsi=optarg;
            break;

        case 4:
            new_vals.opc=optarg;
            break;

        case 5:
            new_vals.isdn=optarg;
            break;

        case 6:
            new_vals.acc=optarg;
            break;

        case 7:
            new_vals.key=optarg;
            break;

        case 8:
            new_vals.mncLen=atoi(optarg);
            break;

        case 9:
            new_vals.op=optarg;
            break;

        case 10:
            new_vals.authenticate=true;
            break;

        case 11:
            new_vals.spn=optarg;
            break;

        default:
            printf("unrecognized option: %d \n", c);
            correctOpt=false;
        };
    }

    if (optind < argc ||  correctOpt==false) {
        printf("non-option ARGV-elements: ");

        while (optind < argc)
            printf("%s ", argv[optind++]);

        printf("Possible options are:\n");

        for (int i=0; long_options[i].name!=NULL; i++)
            printf("  --%-10s %s\n",long_options[i].name, help_text[long_options[i].name].c_str());

        printf("\n");
        exit(1);
    }

    printf ("Existing values in USIM\n");
    //Assert(readUSIMvalues(portName), "failed to read UICC");

    if ( new_vals.op != "") {
        setOPc(new_vals);
        printf("Computed OPc from OP and Ki as: %s\n", new_vals.opc.c_str());
    }

    if (new_vals.setIt) {
        if ( new_vals.adm.size() != 8 )
            printf ("No ADM code of 8 figures, can't program the UICC\n");
        else {
            printf("Setting new values\n");
            writeSIMvalues(portName, new_vals);
            writeUSIMvalues(portName, new_vals);
            printf ("Read new values in UICC\n");
            readUSIMvalues(portName);
        }
    }

    if ( new_vals.authenticate)
        authenticate(portName, new_vals);

    return 0;
}

// Assembly:
pushq %rbp
movq %rsp, %rbp
subq $0x1520, %rsp           # imm = 0x1520
movl $0x0, -0x4(%rbp)
movl %edi, -0x8(%rbp)
movq %rsi, -0x10(%rbp)
leaq -0x1020(%rbp), %rdi
leaq 0x14de9(%rip), %rsi     # 0x22050
movl $0x1001, %edx           # imm = 0x1001
callq 0x3230
leaq -0x1150(%rbp), %rdi
callq 0x12e70
cmpb $0x0, 0x22214(%rip)     # 0x2f498
jne 0xd517
leaq 0x22207(%rip), %rdi     # 0x2f498
callq 0x34e0
cmpl $0x0, %eax
je 0xd517
leaq -0x1460(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x1812b(%rip), %rsi     # 0x253df
leaq 0x18158(%rip), %rdx     # 0x25413
callq 0x13210
jmp 0xd2c2
leaq -0x1420(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x1810d(%rip), %rsi     # 0x253e4
leaq 0x18169(%rip), %rdx     # 0x25447
callq 0x132f0
jmp 0xd2e5
leaq -0x13e0(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x180ee(%rip), %rsi     # 0x253e8
leaq 0x18175(%rip), %rdx     # 0x25476
callq 0x133d0
jmp 0xd308
leaq -0x13a0(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x180d1(%rip), %rsi     # 0x253ee
leaq 0x18165(%rip), %rdx     # 0x25489
callq 0x134b0
jmp 0xd32b
leaq -0x1360(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x180b3(%rip), %rsi     # 0x253f3
leaq 0x18190(%rip), %rdx     # 0x254d7
callq 0x13590
jmp 0xd34e
leaq -0x1320(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x18094(%rip), %rsi     # 0x253f7
leaq 0x181b2(%rip), %rdx     # 0x2551c
callq 0x13670
jmp 0xd371
leaq -0x12e0(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x18076(%rip), %rsi     # 0x253fc
leaq 0x181bf(%rip), %rdx     # 0x2554c
callq 0x13750
jmp 0xd394
leaq -0x12a0(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x18057(%rip), %rsi     # 0x25400
leaq 0x181be(%rip), %rdx     # 0x2556e
callq 0x13830
jmp 0xd3b7
leaq -0x1260(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x18038(%rip), %rsi     # 0x25404
leaq 0x181eb(%rip), %rdx     # 0x255be
callq 0x13910
jmp 0xd3da
leaq -0x1220(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x1801d(%rip), %rsi     # 0x2540c
leaq 0x181fa(%rip), %rdx     # 0x255f0
callq 0x139f0
jmp 0xd3fd
leaq -0x11e0(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x17ffd(%rip), %rsi     # 0x2540f
leaq 0x1821e(%rip), %rdx     # 0x25637
callq 0x13ad0
jmp 0xd420
leaq -0x11a0(%rbp), %rdi
movq %rdi, -0x1468(%rbp)
leaq 0x17be0(%rip), %rsi     # 0x25015
leaq 0x1823e(%rip), %rdx     # 0x2567a
callq 0x13bb0
jmp 0xd443
leaq -0x1460(%rbp), %rax
movq %rax, -0x1160(%rbp)
movq $0xc, -0x1158(%rbp)
leaq -0x1476(%rbp), %rdi
movq %rdi, -0x14b8(%rbp)
callq 0x13cc0
movq -0x14b8(%rbp), %r8
movq -0x1160(%rbp), %rsi
movq -0x1158(%rbp), %rdx
leaq 0x21fdd(%rip), %rdi     # 0x2f468
leaq -0x1475(%rbp), %rcx
callq 0x13ce0
jmp 0xd499
leaq -0x1476(%rbp), %rdi
callq 0x13db0
leaq -0x1460(%rbp), %rax
movq %rax, -0x14c8(%rbp)
addq $0x300, %rax            # imm = 0x300
movq %rax, -0x14c0(%rbp)
movq -0x14c0(%rbp), %rdi
addq $-0x40, %rdi
movq %rdi, -0x14d0(%rbp)
callq 0x13c90
movq -0x14c8(%rbp), %rcx
movq -0x14d0(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x14c0(%rbp)
jne 0xd4c0
leaq 0x68d8(%rip), %rdi      # 0x13dd0
leaq 0x21f69(%rip), %rsi     # 0x2f468
leaq 0x21da2(%rip), %rdx     # 0x2f2a8
callq 0x3250
leaq 0x21f86(%rip), %rdi     # 0x2f498
callq 0x31d0
movb $0x1, -0x147d(%rbp)
testb $0x1, -0x147d(%rbp)
je 0xd7fc
movl $0x0, -0x1484(%rbp)
movl -0x8(%rbp), %edi
movq -0x10(%rbp), %rsi
leaq 0x18721(%rip), %rdx     # 0x25c64
leaq 0x21d66(%rip), %rcx     # 0x2f2b0
leaq -0x1484(%rbp), %r8
callq 0x3080
movl %eax, -0x147c(%rbp)
cmpl $-0x1, -0x147c(%rbp)
jne 0xd64a
jmp 0xd7fc
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1470(%rbp)
movl %eax, -0x1474(%rbp)
movq -0x1468(%rbp), %rax
leaq -0x1460(%rbp), %rcx
cmpq %rax, %rcx
movq %rax, -0x14d8(%rbp)
je 0xd5cb
movq -0x14d8(%rbp), %rdi
addq $-0x40, %rdi
movq %rdi, -0x14e0(%rbp)
callq 0x13c90
movq -0x14e0(%rbp), %rax
leaq -0x1460(%rbp), %rcx
cmpq %rcx, %rax
movq %rax, -0x14d8(%rbp)
jne 0xd59a
jmp 0xd639
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1470(%rbp)
movl %eax, -0x1474(%rbp)
leaq -0x1476(%rbp), %rdi
callq 0x13db0
leaq -0x1460(%rbp), %rax
movq %rax, -0x14f0(%rbp)
addq $0x300, %rax            # imm = 0x300
movq %rax, -0x14e8(%rbp)
movq -0x14e8(%rbp), %rdi
addq $-0x40, %rdi
movq %rdi, -0x14f8(%rbp)
callq 0x13c90
movq -0x14f0(%rbp), %rcx
movq -0x14f8(%rbp), %rax
cmpq %rcx, %rax
movq %rax, -0x14e8(%rbp)
jne 0xd606
jmp 0xd639
leaq 0x21e58(%rip), %rdi     # 0x2f498
callq 0x31c0
jmp 0xdaee
movl -0x147c(%rbp), %eax
testl %eax, %eax
setg -0x1150(%rbp)
movl -0x147c(%rbp), %eax
movq %rax, -0x1500(%rbp)
subq $0xb, %rax
ja 0xd7da
movq -0x1500(%rbp), %rax
leaq 0x14992(%rip), %rcx     # 0x22010
movslq (%rcx,%rax,4), %rax
addq %rcx, %rax
jmpq *%rax
leaq -0x1020(%rbp), %rdi
movq 0x21923(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
movl $0x1000, %edx           # imm = 0x1000
callq 0x3140
jmp 0xd7f7
movq 0x2190a(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x1148(%rbp), %rdi
callq 0x33d0
jmp 0xd6bf
jmp 0xd7f7
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1470(%rbp)
movl %eax, -0x1474(%rbp)
jmp 0xdaee
movq 0x218d6(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x1128(%rbp), %rdi
callq 0x33d0
jmp 0xd6f3
jmp 0xd7f7
movq 0x218b9(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x1108(%rbp), %rdi
callq 0x33d0
jmp 0xd710
jmp 0xd7f7
movq 0x2189c(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x10e8(%rbp), %rdi
callq 0x33d0
jmp 0xd72d
jmp 0xd7f7
movq 0x2187f(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x10a8(%rbp), %rdi
callq 0x33d0
jmp 0xd74a
jmp 0xd7f7
movq 0x21862(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x1088(%rbp), %rdi
callq 0x33d0
jmp 0xd767
jmp 0xd7f7
movq 0x21845(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x1068(%rbp), %rdi
callq 0x33d0
jmp 0xd784
jmp 0xd7f7
movq 0x2182b(%rip), %rax     # 0x2efb8
movq (%rax), %rdi
callq 0x3480
movl %eax, -0x1028(%rbp)
jmp 0xd7f7
movq 0x21814(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x10c8(%rbp), %rdi
callq 0x33d0
jmp 0xd7b5
jmp 0xd7f7
movb $0x1, -0x1024(%rbp)
jmp 0xd7f7
movq 0x217f1(%rip), %rax     # 0x2efb8
movq (%rax), %rsi
leaq -0x1048(%rbp), %rdi
callq 0x33d0
jmp 0xd7d8
jmp 0xd7f7
movl -0x147c(%rbp), %esi
leaq 0x17edd(%rip), %rdi     # 0x256c4
xorl %eax, %eax
callq 0x3050
jmp 0xd7f0
movb $0x0, -0x147d(%rbp)
jmp 0xd51e
movq 0x217d5(%rip), %rax     # 0x2efd8
movl (%rax), %eax
cmpl -0x8(%rbp), %eax
jl 0xd81e
movb -0x147d(%rbp), %al
andb $0x1, %al
movzbl %al, %eax
cmpl $0x0, %eax
jne 0xd9b8
leaq 0x17eb9(%rip), %rdi     # 0x256de
xorl %eax, %eax
callq 0x3050
jmp 0xd82e
jmp 0xd830
movq 0x217a1(%rip), %rax     # 0x2efd8
movl (%rax), %eax
cmpl -0x8(%rbp), %eax
jge 0xd868
movq -0x10(%rbp), %rax
movq 0x2178f(%rip), %rdx     # 0x2efd8
movslq (%rdx), %rcx
movl %ecx, %esi
incl %esi
movl %esi, (%rdx)
movq (%rax,%rcx,8), %rsi
leaq 0x184f9(%rip), %rdi     # 0x25d56
xorl %eax, %eax
callq 0x3050
jmp 0xd866
jmp 0xd830
leaq 0x17e8a(%rip), %rdi     # 0x256f9
xorl %eax, %eax
callq 0x3050
jmp 0xd878
movl $0x0, -0x1488(%rbp)
movslq -0x1488(%rbp), %rcx
leaq 0x21a20(%rip), %rax     # 0x2f2b0
shlq $0x5, %rcx
addq %rcx, %rax
cmpq $0x0, (%rax)
je 0xd99e
movslq -0x1488(%rbp), %rax
shlq $0x5, %rax
leaq 0x219fd(%rip), %rcx     # 0x2f2b0
movq (%rax,%rcx), %rax
movq %rax, -0x1510(%rbp)
leaq -0x14a9(%rbp), %rdi
movq %rdi, -0x1508(%rbp)
callq 0x34d0
movq -0x1510(%rbp), %rsi
movq -0x1508(%rbp), %rdx
leaq -0x14a8(%rbp), %rdi
callq 0x33e0
jmp 0xd8ed
leaq 0x21b74(%rip), %rdi     # 0x2f468
leaq -0x14a8(%rbp), %rsi
callq 0x13df0
movq %rax, -0x1518(%rbp)
jmp 0xd909
movq -0x1518(%rbp), %rdi
callq 0x3110
movq -0x1510(%rbp), %rsi
movq %rax, %rdx
leaq 0x17dea(%rip), %rdi     # 0x25710
xorl %eax, %eax
callq 0x3050
jmp 0xd92f
leaq -0x14a8(%rbp), %rdi
callq 0x31a0
leaq -0x14a9(%rbp), %rdi
callq 0x3300
movl -0x1488(%rbp), %eax
addl $0x1, %eax
movl %eax, -0x1488(%rbp)
jmp 0xd882
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1470(%rbp)
movl %eax, -0x1474(%rbp)
jmp 0xd98d
movq %rax, %rcx
movl %edx, %eax
movq %rcx, -0x1470(%rbp)
movl %eax, -0x1474(%rbp)
leaq -0x14a8(%rbp), %rdi
callq 0x31a0
leaq -0x14a9(%rbp), %rdi
callq 0x3300
jmp 0xdaee
leaq 0x17d37(%rip), %rdi     # 0x256dc
xorl %eax, %eax
callq 0x3050
jmp 0xd9ae
movl $0x1, %edi
callq 0x3370
leaq 0x17d5f(%rip), %rdi     # 0x2571e
xorl %eax, %eax
callq 0x3050
jmp 0xd9c8
leaq -0x10c8(%rbp), %rdi
leaq 0x1828e(%rip), %rsi     # 0x25c64
callq 0xe980
movb %al, -0x1519(%rbp)
jmp 0xd9e3
movb -0x1519(%rbp), %al
testb $0x1, %al
jne 0xd9ef
jmp 0xda1e
leaq -0x1150(%rbp), %rdi
callq 0xbc90
jmp 0xd9fd
leaq -0x10e8(%rbp), %rdi
callq 0x3110
movq %rax, %rsi
leaq 0x17d24(%rip), %rdi     # 0x25737
xorl %eax, %eax
callq 0x3050
jmp 0xda1c
jmp 0xda1e
testb $0x1, -0x1150(%rbp)
je 0xdaaf
leaq -0x1150(%rbp), %rdi
addq $0x8, %rdi
callq 0x31f0
cmpq $0x8, %rax
je 0xda53
leaq 0x17d13(%rip), %rdi     # 0x2575b
xorl %eax, %eax
callq 0x3050
jmp 0xda51
jmp 0xdaad
leaq 0x17d33(%rip), %rdi     # 0x2578d
xorl %eax, %eax
callq 0x3050
jmp 0xda63
leaq -0x1020(%rbp), %rdi
leaq -0x1150(%rbp), %rsi
callq 0x52b0
jmp 0xda78
leaq -0x1020(%rbp), %rdi
leaq -0x1150(%rbp), %rsi
callq 0x7f50
jmp 0xda8d
leaq 0x17d0d(%rip), %rdi     # 0x257a1
xorl %eax, %eax
callq 0x3050
jmp 0xda9d
leaq -0x1020(%rbp), %rdi
callq 0x45f0
jmp 0xdaab
jmp 0xdaad
jmp 0xdaaf
testb $0x1, -0x1024(%rbp)
je 0xdacf
leaq -0x1020(%rbp), %rdi
leaq -0x1150(%rbp), %rsi
callq 0xc220
jmp 0xdacd
jmp 0xdacf
movl $0x0, -0x4(%rbp)
leaq -0x1150(%rbp), %rdi
callq 0x13ed0
movl -0x4(%rbp), %eax
addq $0x1520, %rsp           # imm = 0x1520
popq %rbp
retq
leaq -0x1150(%rbp), %rdi
callq 0x13ed0
movq -0x1470(%rbp), %rdi
callq 0x34b0
nopw %cs:(%rax,%rax)