diff fluid-mnf/fluid.c @ 311:9cecc930d78f

fluid-mnf: original source from TI, defenestrated line endings and rearranged directory structure, but no *.[ch] source file content changes yet
author Mychaela Falconia <falcon@freecalypso.org>
date Sat, 29 Feb 2020 05:36:07 +0000
parents
children 77c86062e253
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fluid-mnf/fluid.c	Sat Feb 29 05:36:07 2020 +0000
@@ -0,0 +1,818 @@
+/******************************************************************************
+ * FLUID (Flash Loader Utility Independent of Device)
+ *
+ * Copyright Texas Instruments, 2001.
+ * Mads Meisner-Jensen, mmj@ti.com.
+ *
+ * Main, command-line argument parsing, error handling.
+ *
+ * $Id: fluid.c 1.50 Thu, 14 Nov 2002 13:10:05 +0100 tsj $
+ *
+ ******************************************************************************/
+
+#include "fluid.h"
+#include "flash.h"
+#include "fileio.h"
+#include "trace.h"
+// Secure Calypso Plus
+#include "../inc/ram_load.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <stdarg.h>
+
+#if defined(MSC) || defined(BCC)
+  #include "getopt.h"
+  #include "windows.h"
+#else
+  #include <getopt.h>
+#endif
+
+#include <errno.h> // for ERANGE
+
+
+/******************************************************************************
+ * Prototypes and Globals
+ ******************************************************************************/
+
+extern T_RAM_LOADER d_ram_loader;   // Secure Calypso Plus
+
+char *arg_file_list[ARG_FILE_LIST_SIZE_MAX] = { (char *) 0 };
+int  arg_file_list_size = 0;
+
+char *arg_erase_override = "";
+char *arg_read = "";
+char *arg_write = "";
+int  arg_checksum = 1;
+int  arg_compress = 1;
+int  arg_dry_run = 0;
+int  arg_list_devices = 0;
+char arg_target_type = 0;
+int  arg_image_map_show = 0;
+int  arg_sector_map_show = 0;
+int  arg_sector_list_show = 0;
+int  arg_timers_show = 0;
+int  arg_timers_extended_show = 0;
+int  arg_checksum_show = 0;
+int  arg_show_hexdump = 0;
+int  arg_target_trace_enable = 0;
+int  arg_progress = 'a';
+char arg_hexfile_type = 'm';
+char arg_hexfile_memwidth = 2;
+
+int  arg_target_reset = 1;
+int  arg_rom_bootloader = 0;
+int  arg_boot_delay_rom = 15;
+int  arg_boot_delay_fluid = 15;
+int  arg_device_id0 = -1;
+int  arg_device_id1 = -1;
+
+int  arg_uart_port = 1;
+int  arg_uart_baudrate = 115200;
+char arg_uart_flowcontrol[] = "pn";
+char arg_uart_level_convert = 0;
+
+char arg_verbose = 0;
+int  arg_debug_resume = 0;
+int  arg_debug_trace_pe = 0;
+int  arg_keep_going = 0;
+int  arg_show_main_args = 0;
+int  arg_skip_erase = 0;
+
+// Secure Calypso Plus
+char *arg_die_id_file_name = "";
+char *arg_imeisv = "";
+char *arg_platform_certificate_addr = "";
+int  arg_request_certificate = 0;
+int  arg_delay_for_changing_cs5 = 0;
+int  arg_uart_baudrate_during_cmd_download = 115200;
+int  arg_uart_timeout_configuration = 0;
+int  arg_block_size = 8 * 1024;   // Must be a modulus of 64 bytes, except for the last command.
+
+int arg_usage = 0;
+
+char *argv_0;
+
+int  arg_tr_mask = 0;
+int  arg_tr_spaces = 2;
+char *arg_tr_file = NULL;
+
+int arg_errorfd = 2;
+
+static void main_usage(void);
+static void main_args(int argc, char *argv[]);
+static long arg_long_get(void);
+
+extern int fluid_machine(void);
+extern int fluid_compress(void);
+extern int fluid_decompress(void);
+
+extern int serial_is_baudrate(int bps);
+
+
+/******************************************************************************
+ * Error handling
+ ******************************************************************************/
+
+extern char *main_strerror(int error);
+
+char *win32_strerror(void)
+{
+    static char buf[220];
+    int error;
+    char *p = buf;
+
+    error = GetLastError();
+    p += sprintf(buf, "%d: ", error);
+
+    if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, error,
+                      MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
+                      p, sizeof(buf) - 20, NULL) == 0)
+        sprintf(p, "(Unknown Win32 error)");
+
+    return buf;
+}
+
+void main_msg(char *format, ...)
+{
+    va_list args;
+    char buf[1024];
+
+    va_start(args, format);
+    vsprintf(buf, format, args);
+    va_end(args);
+
+    if (arg_errorfd == 2) {
+        fprintf(stderr, "%s", buf);
+        fflush(stderr);
+    }
+    else {
+        fprintf(stdout, "%s", buf);
+        fflush(stdout);
+    }
+}
+
+void main_error_str(char type, int error, char *string)
+{
+    // If it was an OS error...
+    if (error < E_OS) {
+        error -= E_OS;
+        main_msg("OS-ERROR: %s", win32_strerror());
+    }
+
+    main_msg(" %s(%d): %s%s\n", (type == 'w' ? "WARNING" : "ERROR"),
+             -error, main_strerror(error), string);
+}
+
+void main_warning(int error)
+{
+    main_error_str('w', error, "");
+}
+
+void main_error(int error)
+{
+    main_error_str('e', error, "");
+
+    if (arg_keep_going == 0)
+        exit(-error);
+}
+
+void main_fatal(int error)
+{
+    main_error(error);
+    exit(-error);
+}
+
+
+/******************************************************************************
+ * Command line parsing
+ ******************************************************************************/
+
+static void main_help(void)
+{
+    printf(
+        "\n"
+        "You have started fluid with no command line arguments\n"
+        "\n"
+        "To see all the available command line arguments, start fluid\n"
+        "from a command line prompt (cmd.exe or similar) with:\n"
+        "\n"
+        "    fluid -h\n"
+        "\n"
+        "To see some basic and common examples of usage, start fluid with:\n"
+        "\n"
+        "    fluid -ic\n"
+        "\n"
+        "You can get an overview of all the available examples with:\n"
+        "\n"
+        "    fluid -ii\n"
+        "\n"
+//        "Please read the README file for notes and other info and read the\n"
+//        "HISTORY file to see what has happened with fluid since last release.\n"
+//        "\n"
+        "Press RETURN to exit...\n"
+        );
+    getchar();
+}
+
+static void main_example(int type)
+{
+    switch (type) {
+    case 'c':
+        printf(
+            "Download into board:\n"
+            "  fluid -f gsm.m0\n"
+            "\n"
+            "Simulate a download into board (dry-run):\n"
+            "  fluid -n -f gsm.m0\n"
+            "\n"
+            "Check if file has already been downloaded into board:\n"
+            "  fluid -n -f gsm.m0\n"
+            "\n"
+            "Download into board without erasing boot sector:\n"
+            "  fluid -e-0 -f gsm.m0\n"
+            "\n"
+            "Download into board with another progress indication:\n"
+            "  fluid -gc -f gsm.m0\n"
+            "\n"
+            );
+        break;
+    case 'a':
+        printf(
+            "Download into board with more output verbosity:\n"
+            "  fluid -v -v -f gsm.m0\n"
+            "\n"
+            "Show the image map (which parts of the flash are used, which are not):\n"
+            "  fluid -si -n -f gsm.m0\n"
+            "\n"
+            "Show both the image and the erase maps:\n"
+            "  fluid -sis -n -f gsm.m0\n"
+            "\n"
+            "Download into board without delta download:\n"
+            "  fluid -C -f gsm.m0\n"
+            "\n"
+            );
+        break;
+    case 'e':
+        printf(
+            "Erase all flash (including boot sector!):\n"
+            "  fluid -e+*\n"
+            "\n"
+            "Erase all flash except the boot sector:\n"
+            "  fluid -e+*,-0\n"
+            "\n"
+            "Erase the last megabyte of a 4MB flash device:\n"
+            "  fluid -e+3M..4M\n"
+            "\n"
+            "Erase all flash except sectors 1..7 and addresses 1984k..2048k:\n"
+            "  fluid -e+*,-1..8,-1984k..2048k\n"
+            "\n"
+            );
+        break;
+    case 'r':
+        printf(
+            "Read whole FFS system from a B-Sample:\n"
+            "  fluid -r3M..4M -f bsffs.m0\n"
+            "\n"
+            "Then copy/download it (e.g., to another B-Sample):\n"
+            "  fluid -f bsffs.m0\n"
+            "\n"
+            "Read serial switch config from a B- or C-Sample:\n"
+            "(serial switch config is in sector 2 on TI releases earlier than SSA-5.3.1)\n"
+            "  fluid -r0x11ffe..0x12000 -f usxx.m0 -sx\n"
+            "\n"
+            "Copy it to a(nother) B- or C-sample:\n"
+            "  fluid -f usxx.m0\n"
+            "\n");
+        break;
+    case 'w':
+        printf(
+            "Over-write image with a byte string at a specific address:\n"
+            "  fluid -f gsm.m0 -w7800=0x11,0x22,0x33,0x44,0x55,0x66\n"
+            "\n"
+            "Write zeroes into top-most 2MB of C-Sample flash memory:\n"
+            "  fluid -w2M..4M=0\n"
+            "\n"
+            "Write a string to a specific address:\n"
+            "  fluid -w0x1800=\"\"\"Mads\"\"\",0\n"
+            "\n");
+            break;
+    case 's':
+        printf(
+            "Reset target, doing nothing else (requires special cable):\n"
+            "  fluid -n -or\n"
+            "\n"
+            );
+        break;
+    default:
+        printf(
+            "Avaliable examples:\n"
+            "  a = Advanced, common usage\n"
+            "  c = Common usage\n"
+            "  e = Erase override\n"
+            "  r = Read target memory\n"
+            "  w = Write target memory\n"
+            "  s = Special usage\n"
+            );
+        break;
+    }
+    exit(0);
+}
+
+static void main_debug_usage(void)
+{
+    printf("Debug usage: fluid [OPTIONS...]\n"
+           "\n"
+           "  -d r       Display target (remote) tracing.\n"
+           "  -d c       Resume fluid state machine in command interpreter.\n"
+           "  -d o       Display final command line option values.\n"
+           "  -d t<char> Trace mask in human format:\n"
+           "               a = All, except ?\n"
+           "               * = All\n"
+           "               g = getchar()\n"
+           "               p = putchar()\n"
+           "               G = target driver receive\n"
+           "               P = target driver transmit\n"
+           "               w = target wait\n"
+           "               t = target/transport layer driver\n"
+           "               h = hexfile read/decode\n"
+           "               H = hexfile write/encode\n"
+           "               r = device file parser\n"
+           "               c = Command line argument parser\n"
+           "               u = utility functions\n"
+           "               m = state machine functions\n"
+           "               \n"
+           "  -d v       Display info on compiler used.\n"
+           "  -d f<file> Trace to file.\n"
+           "  -d i<n>    Trace indentation multiplier. Default is 2.\n"
+           "  -d m<n>    Trace mask. Default is 0.\n"
+           "  -t <char>  Trace mask in human format. Same as '-d t<char>'.\n"
+           "\n"
+           "B-/C-/D-Sample LEDs layout:\n"
+           "\n"
+           "+---0---+---1---+---2---+---3---+---4---+---5---+---6---+---7---+\n"
+           "| Recv  | Erase | Prog  | Overhd| Idle  |       |       | Busy  |\n"
+           "+-------+-------+-------+-------+-------+-------+-------+-------+\n"
+        );
+    exit(0);
+}
+
+static void main_args_debug_trace(void)
+{
+    while (*optarg) {
+        switch(*optarg++) {
+        case 'a': arg_tr_mask |= TrAll & ~(0); break;
+        case '*': arg_tr_mask |= TrAll; break;
+        case 'm': arg_tr_mask |= TrMachines; break;
+        case 'g': arg_tr_mask |= TrGetChar; break;
+        case 'p': arg_tr_mask |= TrPutChar; break;
+        case 'G': arg_tr_mask |= TrDriverGet; break;
+        case 'P': arg_tr_mask |= TrDriverPut; break;
+        case 'w': arg_tr_mask |= TrTargetWait; break;
+        case 't': arg_tr_mask |= TrTargetDrv; break;
+        case 'h': arg_tr_mask |= TrHexRead; break;
+        case 'H': arg_tr_mask |= TrHexWrite; break;
+        case 'r': arg_tr_mask |= TrParser; break;
+        case 'c': arg_tr_mask |= TrArgParser; break;
+        case 'C': arg_tr_mask |= TrCmdLineParser; break;
+        case 'u': arg_tr_mask |= TrUtility; break;
+        }
+    }
+}
+
+static void fluid_welcome(void)
+{
+    flowf(NORMAL,
+        "FLUID Revision 2.27, (23 Aug 2004). Copyright Texas Instruments, 2001-2004.\n");
+}
+
+static void fluid_compile_info(void)
+{
+    flowf(
+        NORMAL,
+        "Compiled " __DATE__ " " __TIME__ " with "
+#if defined(MSC)
+        "Microsoft cl.exe"
+#elif defined(BCC)
+        "Borland bcc"
+#else
+        "GNU gcc"
+#endif
+        "\n");
+}
+
+static void main_usage(void)
+{
+    printf(
+        "Usage: fluid [OPTIONS...]\n"
+        "\n");
+    if (!arg_usage)
+        fluid_welcome();
+    printf(
+        "FLUID is a Flash Loader Utility Independent of Device\n"
+        "This version supports:\n"
+        "  TI GSM Boot Loader V6.x.x (with fluid patch)\n"
+        "  TI ROM Boot Loader (Calypso devices only)\n"
+        "\n"
+        "  -f <file>  Flash image file (input or output file).\n"
+        "  -p <num>   Serial port number. Default is 1.\n"
+        "  -b <num>   Serial baudrate. Default is 115200.\n"
+        "  -t <char>  Target type (Default is auto-detect):\n"
+        "               h = Hercules\n"
+        "               u = Ulysses\n"
+        "               c = Calypso\n"
+        "               l = Calypso Lite\n"
+        "               p = Calypso Plus\n"
+        "  -l         List all known flash devices.\n"
+        "  -c, -C     Do or do not checksum target memory thus enabling delta\n"
+        "             download (only program changed sectors). Default is on.\n"
+        "  -z, -Z     Do or do not compress data on download. Default is on.\n"
+        "  -g <char>  Progress indication type:\n"
+        "               a = asterisks (default), c = chars, d = dots,\n"
+        "               x = address+size, n = none\n"
+        "  -e [+|-]<addr0>..<addr1>,... or [+|-]<n>,...<\n"
+        "             Erase/program override. Erase or don't erase flash\n"
+        "             memory in the range [addr0..addr1[. Use '-ie' to see\n"
+        "             examples of usage\n"
+        "             -<...> = do *not* erase and program\n"
+        "             +<...> = force erase\n"
+        "             Giving <n> as an asterisk, '*', means all sectors\n"
+        "  -r <addr0>..<addr1>,...\n"
+        "             Read target memory range [addr0..addr1[ and write the\n"
+        "             bytes to output file specified.\n"
+        "  -w <addr0>..<addr1>=<b0,b1,...,bN>:...\n"
+        "             Write bytes to image. The bytes b0..bN are replicated\n"
+        "             through the whole memory range [addr0..addr1[\n"
+        "  -o <char>  Extra options:\n"
+        "               o = Only bootstrap using ROM boot loader (Calypso devices only)\n"
+        "               O = Do NOT use ROM boot loader\n"
+        "               e = Skip erase (Require empty flash)\n"
+        "               r = Reset target after download (default)\n"
+        "               R = Do NOT reset target after download\n"
+        "               l = Activate (old-fashioned) UART level conversion\n"
+        "               m = Select Motorola hexfile output format (default)\n"
+        "               b = Select binary/raw file output format\n"
+        "               i<n1>,<n2> = Disable device auto-detection and set manufacturer\n"
+        "                   id and device id\n"
+        "               d<n1>,<n2> = Set detection delay (in ms) for ROM and fluid boot\n"
+        "                   loader, respectively\n"
+        "               1, 2, 4 = Select hexfile memory width 1, 2 or 4. Default is 2\n"
+        "  -s <char>  Show additional info:\n"
+        "               i = image map\n"
+        "               s = sector erase map\n"
+        "               l = sector erase list\n"
+        "               t = target timers, T = extended target timer info\n"
+        "               x = hexdump of target memory (together with '-r')\n"
+        "               c = checksums\n"
+        "  -n         Dry run. Do not program the flash device.\n"
+        "  -v         Be verbose. Multiple '-v's means more verbosity.\n"
+        "  -q         Be quiet.\n"
+//        "  -y         Use stdout for error messages.\n"
+        "  -dh        Display help on debug and trace options.\n"
+        "  -h         Display this help.\n"
+        "  -i <char>  Display examples (i = index/overview of examples).\n"
+        // Secure Calypso Plus
+        "\n  Secure Calypso Plus options:\n"
+        "  -I <char>  IMEI protection options:\n"
+        "               d <file> = Retrieve die id from target and write to <file>.\n"
+        "               n <num>  = 16 digits representing the IMEI-SV, [8 TAC]+[6 SNR]+\n"
+        "                          [2 SVN], which is used for non-secure E-samples or\n"
+        "                          secure E-samples when the die id is not added to the\n"
+        "                          DIE_ID field of the manufacturer certificate.\n"
+        "               a <addr> = Address of the platform certificate stored in flash.\n"
+        "  -R         Request firmware certificate.\n"
+        "  -D <num>   Insert a delay before detection of flash type. This delay is used\n"
+        "             for changing the memory mapping on CS5 due to a bug in ROM code\n"
+        "             0x0410 (see SECURITY.txt) or for connecting to target via JTAG.\n"
+        "  -U <num>   UART baudrate during flash programmer download. Default is 115200.\n"
+        "  -u <num>   UART timeout configuration. Default is 0.\n"
+        "  -B <num>   Block size. Must be a modulus of 64 bytes. Default is %d bytes.\n", arg_block_size
+        // End Secure Calypso Plus
+        );
+}
+
+static void main_args(int argc, char *argv[])
+{
+    char ch;
+    int i;
+    // IMEI Protection
+    char d_i, d_digit;
+    char a_imeisv_format[] = "The IMEI-SV must consist of 16 digits in compliance with the following format:\n[8 TAC]+[6 SNR]+[2 SVN]\n";
+
+    if (argc == 1) {
+        fluid_welcome();
+        main_help();
+        exit(0);
+    }
+
+    for (i = argc - 1; i >= 0; i--) {
+        // TODO?: scan for filenames.
+    }
+
+    while ((ch = getopt(argc, argv,
+                        "f:p:b:cCzZjJt:e:s:r:w:nlqg:o:vkd:i:hVyI:RD:U:u:B:")) != -1)
+    {
+        switch (ch)
+        {
+        case 'f':
+            if (arg_file_list_size < ARG_FILE_LIST_SIZE_MAX - 1)
+                arg_file_list[arg_file_list_size++] = optarg;
+            arg_file_list[arg_file_list_size] = NULL;
+            break;
+        case 'p':
+            arg_uart_port = arg_long_get();
+            if (arg_uart_port < 1 || 24 < arg_uart_port)
+                main_error(E_BADARG);
+            break;
+        case 'b':
+            arg_uart_baudrate = arg_long_get();
+            arg_uart_baudrate = serial_is_baudrate(arg_uart_baudrate);
+            if (arg_uart_baudrate == 0)
+                main_error(E_BADARG);
+            break;
+        case 't':
+            arg_target_type = *optarg;
+            break;
+        case 'c': arg_checksum = 1; break;
+        case 'C': arg_checksum = 0; break;
+        case 'z': arg_compress = 1; break;
+        case 'Z': arg_compress = 0; break;
+        case 'e':
+            if (*arg_erase_override != 0)
+                main_error(E_ARG_MULTI);
+            arg_erase_override = optarg;
+            break;
+        case 's':
+            while (*optarg) {
+                switch(*optarg++) {
+                case 'i': arg_image_map_show++; break;
+                case 's': arg_sector_map_show++; break;
+                case 'l': arg_sector_list_show++; break;
+                case 't': arg_timers_show++; break;
+                case 'T': arg_timers_extended_show++; break;
+                case 'c': arg_checksum_show++; break;
+                case 'x': arg_show_hexdump++; break;
+                }
+            }
+            break;
+        case 'r':
+            if (*arg_read != 0)
+                main_error(E_ARG_MULTI);
+            arg_read = optarg;
+            break;
+        case 'w':
+            if (*arg_write != 0)
+                main_error(E_ARG_MULTI);
+            arg_write = optarg;
+            break;
+        case 'l': arg_list_devices = 1; break;
+        case 'n': arg_dry_run++; break;
+        case 'k': arg_keep_going = 1; break;
+        case 'v': arg_verbose++; break;
+        case 'q': arg_verbose--; break;
+        case 'g':
+            if (*optarg != 'a' &&
+                *optarg != 'c' &&
+                *optarg != 'd' &&
+                *optarg != 'x' &&
+                *optarg != 'n')
+                main_error(E_BADARG);
+            arg_progress = *optarg;
+            break;
+        case 'o':
+            while (*optarg) {
+                tr(TrCmdLineParser, "main_args(): -o%s", optarg);
+                switch (*optarg) {
+                case 'e': arg_skip_erase = 1; break;
+                case 'R': arg_target_reset = 0; break;
+                case 'r': arg_target_reset = 2; break;
+                case 'o': arg_rom_bootloader = 1; break;
+                case 'O': arg_rom_bootloader = -1; break;
+                case 'l': arg_uart_level_convert = 1; break;
+                case 'b':
+                case 'm': arg_hexfile_type = *optarg; break;
+                case 'i':
+                    optarg++;
+                    arg_device_id0 = arg_long_get();
+                    if (*optarg == ',') {
+                        optarg++;
+                        arg_device_id1 = arg_long_get();
+                    }
+                    else {
+                        fprintf(stderr, "arg: '%s'", optarg);
+                        main_error(E_BADARG);
+                    }
+                    optarg--;
+                    break;
+                case 'd':
+                    optarg++;
+                    arg_boot_delay_rom = arg_long_get();
+                    if (*optarg == ',') {
+                        optarg++;
+                        arg_boot_delay_fluid = arg_long_get();
+                    }
+                    else if (*optarg == 0)
+                        arg_boot_delay_fluid = arg_boot_delay_rom;
+                    else {
+                        fprintf(stderr, "arg: '%s'", optarg);
+                        main_error(E_BADARG);
+                    }
+                    optarg--;
+                    break;
+                case '1':
+                case '2':
+                case '4':
+                    arg_hexfile_memwidth = *optarg - '0';
+                    break;
+                default:
+                    main_error(E_BADARG);
+                }
+                tr(TrCmdLineParser, "\n");
+                optarg++;
+            }
+            break;
+        case 'd':
+            while (*optarg) {
+                switch (*optarg++) {
+                case 'h': main_debug_usage(); break;
+                case 'c': arg_debug_resume = 1; break;
+                case 'p': arg_debug_trace_pe = 1; break;
+                case 'r': arg_target_trace_enable = 1; break;
+                case 'o': arg_show_main_args = 1; break;
+                case 't': main_args_debug_trace(); break;
+                case 'v': fluid_compile_info(); exit(0); break;
+                case 'f': arg_tr_file = optarg; optarg += strlen(optarg); break;
+                case 'm': arg_tr_mask = arg_long_get(); break;
+                case 'i': arg_tr_spaces = arg_long_get(); break;
+                default:
+                    main_error(E_BADARG);
+                }
+            }
+            optarg++;
+            break;
+        case 'i': main_example(*optarg); break;
+        case 'h': arg_usage = 1; break;
+        case 'V': fluid_welcome(); exit(0);
+        case 'y': arg_errorfd = 1; break;
+        // IMEI Protection
+        case 'I':
+            switch (*optarg++) {
+            case 'd':
+                if (*arg_die_id_file_name != 0)
+                    main_error(E_ARG_MULTI);
+                if (*optarg == 0)
+                    optarg++;
+                arg_die_id_file_name = optarg;
+                break;
+            case 'n':
+                if (*arg_imeisv != 0)
+                    main_error(E_ARG_MULTI);
+                if (*optarg == 0)
+                    optarg++;
+                arg_imeisv = optarg;
+                if (strlen(arg_imeisv) != C_IMEISV_DIGITS) {
+                    fprintf(stderr, a_imeisv_format);
+                    main_error(E_BADARG);
+                }
+                for (d_i = 0; d_i < C_IMEISV_DIGITS; d_i++) {
+                    sscanf(arg_imeisv++, "%1c", &d_digit);
+                    if (d_digit < '0' ||d_digit > '9') {
+                        fprintf(stderr, a_imeisv_format);
+                        main_error(E_BADARG);
+                    }
+                }
+                arg_imeisv = optarg;   // Re-assign arg_imeisv after error check
+                break;
+            case 'a':
+                if (*arg_platform_certificate_addr != 0)
+                    main_error(E_ARG_MULTI);
+                if (*optarg == 0)
+                    optarg++;
+                arg_platform_certificate_addr = optarg;
+                if ((strlen(arg_platform_certificate_addr) == C_PLATFORM_CERT_ADDR_DIGITS + 2) &&
+                   (arg_platform_certificate_addr[0] == '0') &&
+                   (arg_platform_certificate_addr[1] == 'x'))
+                    arg_platform_certificate_addr += 2;
+                else if (strlen(arg_platform_certificate_addr) != C_PLATFORM_CERT_ADDR_DIGITS) {
+                    fprintf(stderr, "The platform certificate address must comply with the following format, e.g.,\n0x04650000\n");
+                    main_error(E_BADARG);
+                }
+                break;
+            default:
+                main_error(E_BADARG);
+            }
+            break;
+        // Secure Calypso Plus
+        case 'R':
+            arg_request_certificate = 1;
+            d_ram_loader.b_certificate_request = C_TRUE;
+            break;
+        case 'D':
+            arg_delay_for_changing_cs5 = arg_long_get();
+            if (arg_delay_for_changing_cs5 < 0)
+                main_error(E_BADARG);
+            break;
+        case 'U':
+            arg_uart_baudrate_during_cmd_download = arg_long_get();
+            if (arg_uart_baudrate_during_cmd_download < 0)
+                main_error(E_BADARG);
+            break;
+        case 'u':
+            arg_uart_timeout_configuration = arg_long_get();
+            d_ram_loader.d_uart_timeout = (UWORD32) arg_uart_timeout_configuration;
+            if (d_ram_loader.d_uart_timeout < 0)
+                main_error(E_BADARG);
+            break;
+        case 'B':
+            arg_block_size = arg_long_get();
+            d_ram_loader.d_nb_byte_in_block = (UWORD32) arg_block_size;
+            if (d_ram_loader.d_nb_byte_in_block < 1)
+                main_error(E_BADARG);
+            break;
+        // End Secure Calypso Plus
+        default:
+            main_usage();
+            exit(-E_BADARG);
+        }
+    }
+
+    if (arg_usage) {
+        main_usage();
+        exit(0);
+    }
+
+    if (arg_show_main_args) {
+        printf("Command line option values:\n");
+        printf("argv[0] = '%s'\n", argv[0]);
+        printf("\n");
+        printf("port = %d\n", arg_uart_port);
+        printf("baudrate = %d\n", arg_uart_baudrate);
+
+        printf("target_trace_enable = %d\n", arg_target_trace_enable);
+        printf("\n");
+    }
+
+}
+
+static long arg_long_get(void)
+{
+    long value;
+    char *endp;
+
+    errno = 0;
+    value = strtol(optarg, &endp, 0);
+
+    if (errno == ERANGE || endp == optarg) {
+        fprintf(stderr, "Invalid command line number argument: '%s'", optarg);
+        exit(1);
+    }
+    optarg = endp;
+    return value;
+}
+
+
+/******************************************************************************
+ * Globals and Main
+ ******************************************************************************/
+
+int flowf(int level, char *format, ...)
+{
+    int n = 0;
+    va_list args;
+    char buf[1024];
+
+    if (level <= arg_verbose) {
+        va_start(args, format);
+        vsprintf(buf, format, args);
+
+        n = fprintf(stdout, "%s", buf);
+    }
+    fflush(stdout);
+
+    return n;
+}
+
+int main(int argc, char *argv[])
+{
+    int error;
+
+    file_read_rc(".fluidrc");
+
+    main_args(argc, argv);
+    argv_0 = argv[0];
+
+    if (arg_verbose >= NORMAL)
+        fluid_welcome();
+
+    // Init tracing library
+    tr_init(arg_tr_spaces, arg_tr_file);
+    tr_mask(TrMAIN | arg_tr_mask);
+
+    error = fluid_machine();
+
+    if (error < 0)
+        main_error(error);
+
+    exit(-error);
+}