diff fluid-mnf/fileio.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 (2020-02-29)
parents
children b730c7844233
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fluid-mnf/fileio.c	Sat Feb 29 05:36:07 2020 +0000
@@ -0,0 +1,592 @@
+/******************************************************************************
+ * FLUID (Flash Loader Utility Independent of Device)
+ *
+ * Copyright Texas Instruments, 2001.
+ * Mads Meisner-Jensen, mmj@ti.com.
+ *
+ * File reading/loading
+ *
+ * $Id: fileio.c 1.24 Mon, 28 Apr 2003 08:49:16 +0200 tsj $
+ *
+ ******************************************************************************/
+
+#include "fluid.h"
+#include "flash.h"
+#include "fileio.h"
+#include "misc.h"
+#include "trace.h"
+#include "../target/target.h"
+#include "../inc/secure_types.h"   // Secure Calypso Plus
+
+#include <stdio.h>
+#include <malloc.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+/******************************************************************************
+ * Globals
+ ******************************************************************************/
+
+// Secure Calypso Plus
+extern int bootloader_is_secure_rom;
+extern int a_certified_cmd_file_name;
+
+#define HEX_MOTOROLA_LINE_SIZE 32 // number of bytes in each line
+#define HEX_MOTOROLA_ADDR_SIZE 32 // number of bits in addresses (16, 24 or 32)
+
+
+struct {
+    char   type;
+    char   size;
+    uint32 addr;
+    uint8  data[128];
+    uint8  dummy; // required - don't remove!
+} mhex;
+
+
+int hexfile_read(char *name, char *buf, int buf_size,
+                 char *usage_map, int usage_map_chunk_size);
+int hexline_motorola_read(char* line);
+int hextoint(char *src, int digits);
+void hextobytes(uint8 *dst, char *src, int bytes);
+
+int hexblock_write(char *buf, int size, unsigned long addr, int addr_size,
+                   char hexfile_type);
+int hexline_motorola_write(char *buf, int size,
+                           unsigned long addr, int addr_size);
+int hexfile_write_open(char *name, char hexfile_type, char *buf, int size);
+int hexfile_write_close(char hexfile_type, int addr_size);
+
+/******************************************************************************
+ * File Reading
+ ******************************************************************************/
+
+// Convert image from one endian type to another. The memory width is
+// specified with <width>.
+void buffer_endian_convert(unsigned char *buf, int buf_size, int width)
+{
+    unsigned char tmp1, tmp2;
+    int i;
+
+    tr(TrHexWrite, "buffer_endian_convert(*, %d, %d)\n", buf_size, width);
+
+    for (i = 0; i < buf_size; i += width) {
+        if (width == 16 || width == 2) {
+            tmp1     = buf[i+0];
+            buf[i+0] = buf[i+1];
+            buf[i+1] = tmp1;
+        }
+        else if (width == 32 || width == 4) {
+            tmp1     = buf[i+0];
+            tmp2     = buf[i+1];
+            buf[i+0] = buf[i+3];
+            buf[i+1] = buf[i+2];
+            buf[i+2] = tmp2;
+            buf[i+3] = tmp1;
+        }
+    }
+}
+
+int file_read_rc(char *filename)
+{
+    // TODO: Read the .fluidrc file. It can contain the following
+    // directives:
+    //
+    // path = <path>  /* semi-colon? separated list of directories in which
+    //                   to look for m0 files etc. */
+    // target = [h]|[c]
+    // baudrate = <baudrate>
+    // port = <port>
+    // more?
+
+    return 0;
+}
+
+extern void tr_image_usage_map(void);
+
+int file_read_image(char *image, int image_size,
+                    char *usage_map, int usage_map_chunk_size)
+{
+    int size, size_total = 0, i = 0;
+    int time_load;
+
+    flowf(NORMAL, "Reading image file:");
+
+    memset(image,     0xFF, image_size);
+    memset(usage_map, 0,    image_size / usage_map_chunk_size);
+
+    if (arg_file_list[0] == NULL)
+        main_warning(E_FILE_INPUT);
+
+    time_load = stopwatch_start();
+
+    while (arg_file_list[i] != NULL)
+    {
+        flowf(NORMAL, " '%s'", arg_file_list[i]);
+        if ((size = hexfile_read(arg_file_list[i], image, image_size,
+                                 usage_map, usage_map_chunk_size)) < 0) {
+            flowf(ALWAYS, " MESSAGE: File '%s' not found\n", arg_file_list[i]);
+            main_error(size);
+        }
+
+        size_total += size;
+        flowf(NORMAL, " (%dkB)", (size + 512) / 1024);
+
+        i++;
+        if (arg_file_list[i] != NULL)
+            flowf(NORMAL, ",");
+    }
+    time_load = (stopwatch_stop(time_load) + 50) /100;
+    flowf(BLABBER, " (%d.%ds)", time_load / 10, time_load % 10);
+    flowf(NORMAL, " ok\n");
+
+    // Now convert image from big endian to little endian format
+    buffer_endian_convert(image, image_size, arg_hexfile_memwidth);
+
+    return size_total;
+}
+
+int file_read_cmd(char *image, int image_size, char *filename)
+{
+    //char filename[20] = "cmd.m0";
+
+    memset(image, 0, image_size);
+
+    flowf(BLABBER, "Reading cmd file '%s': ", filename);
+    if ((image_size = hexfile_read(filename, image, image_size, 0, 0)) < 0) {
+        flowf(ALWAYS, "MESSAGE: File '%s' not found\n", filename);
+        main_error(image_size);
+    }
+    flowf(BLABBER, "(%dB) ok\n", image_size);
+
+    return image_size;
+}
+
+int file_read_method(char *image, int image_size, struct device_s *device)
+{
+    char filename[20];
+
+    strncpy(filename,
+            algorithm_name_lookup_by_id(device->algorithm_id),
+            20 - sizeof(".m0"));
+    strcat(filename, ".m0");
+
+    memset(image, 0, image_size);
+
+    flowf(BLABBER, "Reading method file '%s': ", filename);
+    if ((image_size = hexfile_read(filename, image, image_size, 0, 0)) < 0) {
+        flowf(ALWAYS, "MESSAGE: File '%s' not found\n", filename);
+        main_error(image_size);
+    }
+    flowf(BLABBER, "(%dB) ok\n", image_size);
+
+    return image_size;
+}
+
+
+/******************************************************************************
+ * Hex File Read Functions
+ ******************************************************************************/
+
+// Read an input file in Motorola (or Intel) hex format. On success, return
+// the number of raw data bytes read.
+int hexfile_read(char *filename, char *buf, int buf_size,
+                 char *usage_map, int usage_map_chunk_size)
+{
+    FILE* stream;
+    char line[100];
+    uint32 addr;
+    int type, mysize = 0;
+
+    // First look for file in current directory. Then look for it in the
+    // directory where the fluid executable was found.
+    flowf(DEBUG, "(looking for '%s') ", filename);
+
+    if ((stream = fopen(filename, "rt")) == NULL)
+    {
+        char buf[256];
+
+        flowf(DEBUG, "(oops) ");
+
+        if (pathname_make(buf, sizeof(buf), argv_0, filename) < 0)
+            return E_BUFFER;
+
+        flowf(DEBUG, "(looking for '%s') ", buf);
+
+        if ((stream = fopen(buf, "rt")) == NULL)
+            return E_FILE_OPEN;
+    }
+    flowf(DEBUG, "(ok) ");
+
+    // TODO?: Read the first character of the file and determine the file
+    // type this way (Motorola format, Intel format or .out format)
+    type = 'S';
+
+    while (fgets(line, 100, stream) != NULL) {
+        switch (type) {
+        case 'S':
+            if (hexline_motorola_read(line)) {
+                mysize += (int) mhex.size;
+
+                // Secure Calypso Plus
+                if (bootloader_is_secure_rom &&
+                   strcmp(filename, (char *)&a_certified_cmd_file_name) == 0 &&
+                    mhex.addr >= CMD_SECURE_CALP_OFFSET) {
+                    // The flash programmer is linked to 0x08020000 in internal
+                    // SRAM.
+                    addr = mhex.addr - CMD_SECURE_CALP_OFFSET;
+                }
+                else if (mhex.addr >= CALP_OFFSET)
+                    // Assume linked to Calypso Plus (0x04000000 Flash Base)
+                    addr = mhex.addr - CALP_OFFSET;
+                else
+                    addr = mhex.addr;
+
+                if (addr > (uint32) buf_size) {
+                    fprintf(stderr, "Address too big: 0x%08X\n", (int) addr);
+                    return E_FILE_BUF_SMALL;
+                }
+                memcpy(&buf[addr], &mhex.data[0], mhex.size);
+                // Update the image usage map
+                if (usage_map != NULL) {
+                    usage_map[(addr) / usage_map_chunk_size] = 'x';
+                    usage_map[(addr + mhex.size - 1) / usage_map_chunk_size] = 'x';
+                }
+            }
+            break;
+        case '?':
+            // Intel format
+            break;
+        case 'O':
+            // .out format
+            break;
+        default:
+            return E_FILE_FORMAT;
+        }
+    }
+    fclose(stream);
+
+    return mysize;
+}
+
+// Read and decode one line of a Motorola hex file.
+// Original design and code by Delta Technologies, 2001.
+int hexline_motorola_read(char* line)
+{
+    mhex.type = (uint8) line[1] - '0';
+    mhex.size = hextoint(&line[2], 2);
+
+    tr(TrHexRead, "S%d%02X", mhex.type, mhex.size);
+
+    switch (mhex.type) {
+    case 0:
+        // First record in file - no action required
+        mhex.size = 0;
+        break;
+    case 1:
+        // Data record 16-bit address: S1nnAAAAxxxxxxxxxxxxxxxCC
+        mhex.size -= 3;
+        mhex.addr = hextoint(&line[4], 4);
+        tr(TrCont|TrHexRead, "%04X", mhex.addr);
+        hextobytes(&mhex.data[0], &line[8], mhex.size);
+        break;
+    case 2:
+        // Data record 24-bit address: S2nnAAAAAAxxxxxxxxxxxxxxxCC
+        mhex.size -= 4;
+        mhex.addr = hextoint(&line[4], 6);
+        tr(TrCont|TrHexRead, "%06X", mhex.addr);
+        hextobytes(&mhex.data[0], &line[10], mhex.size);
+        break;
+    case 3:
+        // Data record 32-bit address: S3nnAAAAAAAAxxxxxxxxxxxxxxxCC
+        mhex.size -= 5;
+        mhex.addr = hextoint(&line[4], 8);
+        tr(TrCont|TrHexRead, "%08X", mhex.addr);
+        hextobytes(&mhex.data[0], &line[12], mhex.size);
+        break;
+    case 7:
+        // End of file record 32-bit address
+        mhex.size = 0;
+        break;
+    case 8:
+        // End of file record 24-bit address
+        mhex.size = 0;
+        break;
+    case 9:
+        // End of file record 16-bit address
+        mhex.size = 0;
+        break;
+    default:
+        fprintf(stderr, "WARNING: Illegal hex line: %s\n", line);
+        main_error(E_FILE_FORMAT);
+    }
+    tr(TrCont|TrHexRead, "\n");
+
+    return mhex.size;
+}
+
+int hextoint(char *src, int digits)
+{
+    int number = 0;
+    char ch;
+
+    while (digits-- && *src) {
+        ch = *src++;
+        if (ch >= '0' && ch <= '9')
+            ch = ch - '0';
+        else if (ch >= 'A' && ch <= 'F')
+            ch = ch - 'A' + 10;
+        else if (ch >= 'a' && ch <= 'f')
+            ch = ch - 'a' + 10;
+        else
+            break;
+        number = (number << 4) + ch;
+    }
+    return number;
+}
+
+void hextobytes(uint8 *dst, char *src, int bytes)
+{
+    while (bytes-- && *src) {
+        *dst++ =
+            (src[0] - (src[0] <= '9' ? '0' : 'A' - 10)) * 16 +
+            (src[1] - (src[1] <= '9' ? '0' : 'A' - 10));
+        src += 2;
+        tr(TrCont|TrHexRead, "%02X", dst[-1]);
+    }
+}
+
+
+/******************************************************************************
+ * File Writing
+ ******************************************************************************/
+
+static FILE* ostream;
+
+int file_write_image(char *image, int image_size,
+                     struct image_part_s *image_list)
+{
+    int size, size_total = 0;
+    struct image_part_s *image_list_start = image_list;
+
+    if (arg_show_hexdump == 0 && arg_file_list[0] == NULL)
+        main_fatal(E_FILE_OUTPUT);
+
+    if (arg_file_list[1] != NULL)
+        main_fatal(E_ARG_MULTI);
+
+    if (arg_file_list[0] != NULL)
+    {
+        flowf(NORMAL, "Writing flash image file: '%s' ", arg_file_list[0]);
+
+        if ((size = hexfile_write_open(arg_file_list[0], arg_hexfile_type,
+                                       image, image_size)) < 0)
+            main_error(size);
+
+        while (image_list->size != 0)
+        {
+            // Note that we wrap/mirror memory each 'image_size' bytes
+            if ((size =
+                 hexblock_write(&image[image_list->addr & (image_size - 1)],
+                                image_list->size,
+                                image_list->addr, 32,
+                                arg_hexfile_type)) < 0)
+                main_error(E_FILE_BUF_SMALL);
+
+            size_total += size;
+            flowf(NORMAL, "(%dkB) ", (size + 512) / 1024);
+            image_list++;
+        }
+        if (hexfile_write_close(arg_hexfile_type, 32) < 0)
+            main_error(E_FILE_CLOSE);
+
+        flowf(NORMAL, " ok\n");
+    }
+
+    if (arg_show_hexdump) {
+        image_list = image_list_start;
+        while (image_list->size != 0)
+        {
+            hexdump(&image[image_list->addr & (image_size - 1)],
+                    image_list->size,
+                    image_list->addr, 1);
+            putchar('\n');
+            image_list++;
+        }
+    }
+
+    return size_total;
+}
+
+int file_write_die_id(unsigned char *die_id, char *filename) {
+    int i;
+
+    if (arg_hexfile_type == 'b') {
+        // Binary write
+        if ((ostream = fopen(filename, "wb")) == NULL)
+            return E_FILE_OPEN;
+
+        if (fwrite(die_id, C_WORD32LGB * C_DIE_ID_SIZE, 1, ostream) < 0)
+            return E_FILE_WRITE;
+    }
+    else {
+        // Text write
+        if ((ostream = fopen(filename, "wt")) == NULL)
+            return E_FILE_OPEN;
+
+        for (i = 0 ; i < (C_WORD32LGB * C_DIE_ID_SIZE) ; i++)
+            fprintf(ostream, "0x%2.2x ", die_id[i]);
+    }
+
+    fclose(ostream);
+
+    return 0;
+}
+
+/******************************************************************************
+ * Hex File Write Functions
+ ******************************************************************************/
+
+int hexblock_write(char *buf, int size, unsigned long addr, int addr_size,
+                   char hexfile_type)
+{
+    int size_start = size;
+    int line_size;
+
+    tr(TrHexWrite, "hexblock_write(*, %d, 0x%x, %d, '%c')\n",
+       size, addr, addr_size, hexfile_type);
+
+    while (size > 0) {
+        switch (hexfile_type) {
+        case 'b':
+            line_size = fwrite(buf, 1, size, ostream);
+            if (line_size < size_start)
+                return E_FILE_WRITE;
+            break;
+        case 'm':
+        case 'S':
+            line_size = (size > HEX_MOTOROLA_LINE_SIZE ?
+                         HEX_MOTOROLA_LINE_SIZE : size);
+            hexline_motorola_write(buf, line_size, addr, addr_size);
+            break;
+        case '?':
+            // Intel format
+            break;
+        default:
+            main_fatal(E_FILE_FORMAT);
+        }
+        buf  += line_size;
+        size -= line_size;
+        addr += line_size;
+    }
+
+    return size_start;
+}
+
+int hexfile_write_open(char *name, char hexfile_type, char *buf, int size)
+{
+    if ((ostream = fopen(name, "wt")) == NULL)
+        return E_FILE_OPEN;
+
+    // Write file header
+    switch (hexfile_type) {
+    case 'b':
+        // Binary format --- close file, then reopen it for binary writing
+        if (fclose(ostream) == EOF)
+            return E_FILE_OPEN;
+        if ((ostream = fopen(name, "wb")) == NULL)
+            return E_FILE_OPEN;
+        flowf(VERBOSE, "(binary) ");
+        break;
+    case 'm':
+    case 'S':
+        // Motorola hex files are always in big endian format.
+        flowf(VERBOSE, "(motorola) ");
+        buffer_endian_convert(buf, size, arg_hexfile_memwidth);
+        fprintf(ostream,"S0030000FC\n");
+        break;
+    case '?':
+        flowf(VERBOSE, "(intel) ");
+        // Intel format
+        break;
+    default:
+        return E_FILE_FORMAT;
+    }
+
+    return 0;
+}
+
+int hexfile_write_close(char hexfile_type, int addr_size)
+{
+    switch (hexfile_type) {
+    case 'b':
+        // Binary format --- do nothing
+        break;
+    case 'm':
+    case 'S':
+        switch (addr_size) {
+        case 16: fprintf(ostream, "S9030000FC\n"); break;
+        case 24: fprintf(ostream, "S804000000FB\n"); break;
+        case 32: fprintf(ostream, "S70500000000FA\n"); break;
+        }
+        break;
+    case '?':
+        // Intel format
+        break;
+    default:
+        return E_FILE_FORMAT;
+    }
+
+    fclose(ostream);
+
+    return 0;
+}
+
+int hexline_motorola_write(char *buf, int size,
+                           unsigned long addr, int addr_size)
+{
+    uint8 cksum;
+    int	i;
+
+    tr(TrHexWrite, "hexline_motorola_write(*, %d, 0x%x, %d)\n",
+       size, addr, addr_size);
+
+    if (addr_size == 0) {
+        if ((addr + (unsigned long)(size - 1)) < 0x10000L)
+            addr_size = 16;
+        else if ((addr + (unsigned long)(size - 1)) < 0x1000000L)
+            addr_size = 24;
+        else
+            addr_size = 32;
+    }
+    switch (addr_size) {
+    case 16:
+        fprintf(ostream, "S1%02X%04lX", size + 3, addr);
+        cksum = size + 3;
+        break;
+    case 24:
+        fprintf(ostream, "S2%02X%06lX", size + 4, addr);
+        cksum = size + 4;
+        break;
+    case 32:
+        fprintf(ostream, "S3%02X%08lX", size + 5, addr);
+        cksum = size + 5;
+        break;
+    }
+    cksum +=
+        (uint8) ((addr >> 24) & 0xFF) +
+        (uint8) ((addr >> 16) & 0xFF) +
+        (uint8) ((addr >>  8) & 0xFF) +
+        (uint8) ((addr >>  0) & 0xFF);
+    
+    for (i = 0; i < size; i++) {
+        fprintf(ostream,"%02X", buf[i] & 0xFF);
+        cksum += buf[i];
+    }
+    cksum = ~cksum;
+    fprintf(ostream,"%02X\n", cksum);
+
+    return 0;
+}
+