diff fluid-mnf/flash.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 f89a20e7adc7
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/fluid-mnf/flash.c	Sat Feb 29 05:36:07 2020 +0000
@@ -0,0 +1,614 @@
+/******************************************************************************
+ * FLUID (Flash Loader Utility Independent of Device)
+ * Idea, design and coding by Mads Meisner-Jensen, mmj@ti.com
+ *
+ * Copyright Texas Instruments, 2001.
+ * Mads Meisner-Jensen, mmj@ti.com.
+ *
+ * Flash device database and lookup
+ *
+ * $Id: flash.c 1.26 Wed, 30 Oct 2002 12:09:08 +0100 tsj $
+ *
+ ******************************************************************************/
+
+#include "fluid.h"
+#include "misc.h"
+#include "flash.h"
+#include "trace.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <ctype.h>
+#include <stdlib.h>
+
+
+/******************************************************************************
+ * Global, Static definitions
+ ******************************************************************************/
+
+const struct algorithm_s algorithms[] = {
+    { ALGORITHM_AMD,        "amd" },
+    { ALGORITHM_INTEL,      "intel" },
+    { ALGORITHM_INTEL_BW,   "intel_bw" },
+    { ALGORITHM_MITSUBISHI, "mitsubishi" },
+    { ALGORITHM_SST,        "sst" },
+    { 0,                    "unknown" }
+};
+
+struct manufact_s manufacturers[] = {
+    { MANUFACT_AMD,        "AMD" },
+    { MANUFACT_ATMEL,      "Atmel" },
+    { MANUFACT_FUJITSU,    "Fujitsu" },
+    { MANUFACT_INTEL,      "Intel" },
+    { MANUFACT_MXIC,       "MXIC" },
+    { MANUFACT_MITSUBISHI, "Mitsubishi" },
+    { MANUFACT_SAMSUNG,    "Samsung" },
+    { MANUFACT_SHARP,      "Sharp" },
+    { MANUFACT_STM,        "STM" },
+    { MANUFACT_SST,        "SST" },
+    { MANUFACT_TOSHIBA,    "Toshiba" },
+    { 0x00,                "Unknown" }
+};
+
+
+/******************************************************************************
+ * Default Device Database
+ ******************************************************************************/
+
+struct memmap_s map_63x64_8x8 = {
+    0,
+    "63x64_8x8kB",
+    63 + 8,
+    {
+        { 0x000000, 0x10000 }, { 0x010000, 0x10000 },
+        { 0x020000, 0x10000 }, { 0x030000, 0x10000 },
+        { 0x040000, 0x10000 }, { 0x050000, 0x10000 },
+        { 0x060000, 0x10000 }, { 0x070000, 0x10000 },
+        { 0x080000, 0x10000 }, { 0x090000, 0x10000 },
+        { 0x0A0000, 0x10000 }, { 0x0B0000, 0x10000 },
+        { 0x0C0000, 0x10000 }, { 0x0D0000, 0x10000 },
+        { 0x0E0000, 0x10000 }, { 0x0F0000, 0x10000 },
+
+        { 0x100000, 0x10000 }, { 0x110000, 0x10000 },
+        { 0x120000, 0x10000 }, { 0x130000, 0x10000 },
+        { 0x140000, 0x10000 }, { 0x150000, 0x10000 },
+        { 0x160000, 0x10000 }, { 0x170000, 0x10000 },
+        { 0x180000, 0x10000 }, { 0x190000, 0x10000 },
+        { 0x1A0000, 0x10000 }, { 0x1B0000, 0x10000 },
+        { 0x1C0000, 0x10000 }, { 0x1D0000, 0x10000 },
+        { 0x1E0000, 0x10000 }, { 0x1F0000, 0x10000 },
+
+        { 0x200000, 0x10000 }, { 0x210000, 0x10000 },
+        { 0x220000, 0x10000 }, { 0x230000, 0x10000 },
+        { 0x240000, 0x10000 }, { 0x250000, 0x10000 },
+        { 0x260000, 0x10000 }, { 0x270000, 0x10000 },
+        { 0x280000, 0x10000 }, { 0x290000, 0x10000 },
+        { 0x2A0000, 0x10000 }, { 0x2B0000, 0x10000 },
+        { 0x2C0000, 0x10000 }, { 0x2D0000, 0x10000 },
+        { 0x2E0000, 0x10000 }, { 0x2F0000, 0x10000 },
+
+        { 0x300000, 0x10000 }, { 0x310000, 0x10000 },
+        { 0x320000, 0x10000 }, { 0x330000, 0x10000 },
+        { 0x340000, 0x10000 }, { 0x350000, 0x10000 },
+        { 0x360000, 0x10000 }, { 0x370000, 0x10000 },
+        { 0x380000, 0x10000 }, { 0x390000, 0x10000 },
+        { 0x3A0000, 0x10000 }, { 0x3B0000, 0x10000 },
+        { 0x3C0000, 0x10000 }, { 0x3D0000, 0x10000 },
+        { 0x3E0000, 0x10000 },
+
+        { 0x3F0000, 0x02000 }, { 0x3F2000, 0x02000 },
+        { 0x3F4000, 0x02000 }, { 0x3F6000, 0x02000 },
+        { 0x3F8000, 0x02000 }, { 0x3FA000, 0x02000 },
+        { 0x3FC000, 0x02000 }, { 0x3FE000, 0x02000 },
+    }
+};
+
+struct memmap_s *memmaps = &map_63x64_8x8;
+
+// Default B-Sample device
+struct device_s device_fujitsu_dl323t = {
+    0,
+    ALGORITHM_AMD,
+    MANUFACT_FUJITSU,
+    0x2250,
+    "MBM29DL323DT",
+    0,
+    0,
+    &map_63x64_8x8
+};
+
+// Default C-Sample device
+struct device_s device_amd_dl322t = {
+    &device_fujitsu_dl323t, // link to next (previous) device defintion
+    ALGORITHM_AMD,
+    MANUFACT_AMD,
+    0x2255,
+    "Am29DL322DT",
+    0,
+    0,
+    &map_63x64_8x8
+};
+
+struct device_s *devices = &device_amd_dl322t;
+
+
+/******************************************************************************
+ * Device file reading and parsing
+ ******************************************************************************/
+
+#define INBUF_SIZE 1024
+
+static char inbuf[INBUF_SIZE];
+static char *pin;
+static FILE *fp;
+static int  linenum;
+
+static char string[1024];
+static int  length;
+static int  number;
+
+enum ParserTokens {
+    TOKEN_EOF,
+    TOKEN_STRING,
+    TOKEN_NUMBER,
+    TOKEN_KEYWORD
+};
+
+enum ParserKeywords {
+    KEYWORD_NONE,
+    KEYWORD_DEVICE,
+    KEYWORD_MEMMAP
+};
+
+void parser_error(int error)
+{
+    fprintf(stderr, "At line %d, ", linenum);
+    main_fatal(error);
+}
+
+void file_read_devices(char *filename)
+{
+    int token, i, n = 0;
+    struct device_s *device;
+    struct memmap_s *memmap;
+
+    flowf(BLABBER, "Reading '%s': ", filename);
+
+    // First look for file in current directory. Then look for it in the
+    // directory where the fluid executable was found.
+    if ((fp = fopen(filename, "rt")) == NULL)
+    {
+        char buf[256];
+
+        if (pathname_make(buf, sizeof(buf), argv_0, filename) < 0)
+            main_fatal(E_BUFFER);
+
+        flowf(DEBUG, "(looking for '%s') ", buf);
+
+        if ((fp = fopen(buf, "rt")) == NULL) {
+            fprintf(stderr, "WARNING: file '%s' not found. Using default device database.\n", filename);
+            return;
+        }
+    }
+
+    devices = (struct device_s *) 0;
+    memmaps = (struct memmap_s *) 0;
+
+    pin = inbuf;
+    inbuf[0] = '\n';
+    linenum = 0;
+
+    // Each loop represents one block/statement of the file
+    while ((token = get_keyword()) != E_PARSER_EOF) {
+        switch (token) {
+        case KEYWORD_MEMMAP:
+            tr(TrBegin|TrParser, "keyword: memmap {\n");
+            if ((token = get_string()) < 0)
+                parser_error(token);
+
+            if ((memmap = malloc(sizeof(struct memmap_s) + length + 1)) == NULL)
+                parser_error(E_MEMORY);
+            memmap->name = (char *) memmap + sizeof(struct memmap_s);
+            strcpy(memmap->name, string);
+
+            if ((token = get_token()) != '{')
+                parser_error(E_PARSER_SYNTAX);
+
+            i = 0;
+            while ((token = get_token()) == TOKEN_NUMBER)
+            {
+                memmap->sectors[i].addr = number;
+
+                if ((token = get_number()) < 0)
+                    parser_error(token);
+                memmap->sectors[i].size = number;
+
+                i++;
+            }
+            if (token != '}')
+                parser_error(E_PARSER_END_BRACE);
+
+            memmap->size = i;
+
+            // Append to linked list
+            memmap->next = memmaps;
+            memmaps = memmap;
+
+            tr(TrEnd|TrParser, "}\n");
+            break;
+
+        case KEYWORD_DEVICE:
+            tr(TrBegin|TrParser, "keyword: device {\n");
+            if ((token = get_string()) < 0)
+                parser_error(token);
+            if ((device = malloc(sizeof(struct device_s) + length + 1)) == NULL)
+                parser_error(E_MEMORY);
+            device->name = (char *) device + sizeof(struct device_s);
+            strcpy(device->name, string);
+
+            if ((token = get_number()) < 0)
+                parser_error(token);
+            device->manufacturer_id = number;
+
+            if ((token = get_number()) < 0)
+                parser_error(token);
+            device->device_id = number;
+
+            if ((token = get_string()) < 0)
+                parser_error(token);
+            device->algorithm_id = algorithm_id_lookup_by_name(string);
+            if (device->algorithm_id == 0)
+                parser_error(E_PARSER_ALGORITHM);
+
+            if ((token = get_string()) < 0)
+                parser_error(token);
+            device->memmap = memmap_lookup_by_name(string);
+            if (device->memmap == 0)
+                parser_error(E_PARSER_MEMMAP);
+
+            // Append to linked list
+            device->next = devices;
+            devices = device;
+
+            tr(TrEnd|TrParser, "}\n");
+            break;
+        default:
+            parser_error(E_PARSER_KEYWORD);
+        }
+        n++;
+    }
+
+    flowf(BLABBER, "(%d blocks read) ok.\n", n);
+}
+
+int get_next_line(void)
+{
+    int result;
+
+    result = (fgets(inbuf, INBUF_SIZE, fp) != NULL);
+
+    pin = inbuf;
+    linenum++;
+
+    tr(TrParser, "get_next_line() (%d) %d ", result);
+
+    return result;
+}
+
+int get_token(void)
+{
+    char *pin_start, *pin_end;
+    int whitespace;
+
+    {
+        char tmp[8];
+        for (whitespace = 0; whitespace < 7; whitespace++)
+            tmp[whitespace] = (pin[whitespace] < ' ' ? '.' : pin[whitespace]);
+        tmp[7] = 0;
+        tr(TrParser, "get_token() ('%s...')", tmp);
+    }
+
+    whitespace = 1;
+
+    while (whitespace)
+    {
+        if (*pin == ' ' || *pin == '\t' || *pin == '\n') {
+            // Skip white-space
+            tr(TrParser, " skip white-space {");
+            while (*pin == ' ' || *pin == '\t' || *pin == '\n')
+            {
+                while (*pin == ' ' || *pin == '\t')
+                    pin++;
+
+                // If end of line, read the next line
+                if (*pin == '\n') {
+                    if (get_next_line() == 0)
+                        return TOKEN_EOF;
+                }
+            }
+            tr(TrCont|TrParser, "}");
+        }
+        else if (pin[0] == '/' && pin[1] == '*') {
+            // Skip comment
+            tr(TrParser, " skip comment {");
+            while (pin[0] != '*' || pin[1] != '/')
+            {
+                while ((pin[0] != '*' || pin[1] != '/') && *pin != '\n')
+                    pin++;
+
+                // If end of line, read the next line
+                if (*pin == '\n') {
+                    if (get_next_line() == 0)
+                        return TOKEN_EOF;
+                }
+                else {
+                    pin += 2;
+                    break;
+                }
+            }
+            tr(TrCont|TrParser, "}");
+        }
+        else {
+            whitespace = 0;
+        }
+    }
+
+    {
+        char tmp[8];
+        for (whitespace = 0; whitespace < 7; whitespace++)
+            tmp[whitespace] = (pin[whitespace] < ' ' ? '.' : pin[whitespace]);
+        tmp[7] = 0;
+        tr(TrCont|TrParser, " ('%s...')\n", tmp);
+    }
+
+    // See if token is a string
+    if (isalpha(*pin) || *pin == '_') {
+        pin_start = pin;
+        while (isalnum(*pin) || *pin == '_')
+            pin++;
+        length = pin - pin_start;
+        strncpy(string, pin_start, length);
+        string[length] = 0;
+        return TOKEN_STRING;
+    }
+
+    // See if token is a number
+    if (isdigit(*pin)) {
+        number = (int) strtol(pin, &pin_end, 0);
+        pin = pin_end;
+        if (*pin_end == 'k') {
+            number *= 1024;
+            pin++;
+        }
+        return TOKEN_NUMBER;
+    }
+
+    // Token is a character
+    return *pin++;
+}
+
+int get_keyword(void)
+{
+    int token;
+
+    token = get_token();
+    tr(TrParser, "get_keyword() (%d) ", token);
+
+    if (token == TOKEN_EOF)
+        return E_PARSER_EOF;
+
+    if (token != TOKEN_STRING)
+        return E_PARSER_KEYWORD;
+
+    if (strcmp("memmap", string) == 0)
+        token = KEYWORD_MEMMAP;
+    else if (strcmp("device", string) == 0)
+        token = KEYWORD_DEVICE;
+    else
+        token = E_PARSER_KEYWORD;
+
+    tr(TrCont|TrParser, "%d\n", token);
+    return token;
+}
+
+int get_string(void)
+{
+    int token;
+
+    token = get_token();
+    tr(TrParser, "get_string() (%d) ", token);
+
+    if (token == TOKEN_EOF)
+        return E_PARSER_EOF;
+
+    if (token != TOKEN_STRING)
+        return E_PARSER_STRING;
+
+    tr(TrCont|TrParser, "'%s'\n", string);
+    return 0;
+}
+
+int get_number(void)
+{
+    int token;
+
+    token = get_token();
+    tr(TrParser, "get_number() (%d) ", token);
+
+    if (token == TOKEN_EOF)
+        return E_PARSER_EOF;
+
+    if (token != TOKEN_NUMBER)
+        return E_PARSER_NUMBER;
+
+    tr(TrCont|TrParser, "0x%X\n", number);
+    return 0;
+}
+
+
+/******************************************************************************
+ * Functions
+ ******************************************************************************/
+
+// Estimate the time taken for erasure and programming of the flash
+// device. <bytes> is the number of bytes to program.
+int time_compute(struct device_s *device,
+                 int sectors, int bytes, int chunks,
+                 int *time_erase, int *time_program, int *time_transfer)
+{
+    int te =  0; // sector erase time in milli seconds
+    int tp = 16; // 16-bit word program time in micro seconds
+    int tdt, tco, trp;
+
+    switch (device->algorithm_id) {
+    case ALGORITHM_AMD:        te =  700; break;
+    case ALGORITHM_INTEL:      te =  800; break;
+    case ALGORITHM_INTEL_BW:   te = 1300; break;
+    case ALGORITHM_MITSUBISHI: te =   40; break;
+    case ALGORITHM_SST:        te =   20; break;
+    }
+    *time_erase   = te * sectors;
+
+    // Data transmission time: with 12 bytes per chunk
+    tdt = (bytes + 12 * chunks) / (arg_uart_baudrate / 10) * 1000;
+
+    // Communication overhead time: 2 waits of 10ms per chunk.
+    tco = chunks * 2 * 10;
+
+    *time_transfer = tdt + tco;
+
+    // Raw programming time:
+    *time_program = trp = (bytes / 2) * tp / 1000;
+
+    tr(TrUtility, "tdt = %d\n", tdt);
+    tr(TrUtility, "tco = %d\n", tco);
+    tr(TrUtility, "trp = %d\n", trp);
+
+    return *time_erase + *time_transfer;
+}
+
+void device_print(struct device_s *device, char format)
+{
+    int device_size =
+        (device->memmap->sectors[device->memmap->size - 1].addr +
+         device->memmap->sectors[device->memmap->size - 1].size) /
+        (1024 * 1024 / 8);
+
+    if (format == 'l') {
+        printf("%s %s (0x%02X, 0x%04X). %dMb in %d sectors, %s algorithm",
+               manufacturer_name_lookup_by_id(device->manufacturer_id),
+               device->name,
+               device->manufacturer_id,
+               device->device_id,
+               device_size,
+               device->memmap->size,
+               algorithm_name_lookup_by_id(device->algorithm_id));
+    }
+    else if (format == 's') {
+        printf("(0x%02X, 0x%04X) %s %s",
+               device->manufacturer_id,
+               device->device_id,
+               manufacturer_name_lookup_by_id(device->manufacturer_id),
+               device->name);
+    }
+}
+
+void devices_list(void)
+{
+    struct device_s *device = devices;
+
+    while (device != NULL) {
+        device_print(device, 'l');
+        putchar('\n');
+        device = device->next;
+    }
+}
+
+struct device_s *device_lookup_by_id(int m, int d)
+{
+    struct device_s *device = devices;
+
+    while (device != NULL) {
+        if ((m & 0xFF) == device->manufacturer_id && d == device->device_id)
+            return device;
+        device = device->next;
+    }
+    return (struct device_s *) 0;
+}
+
+struct device_s *device_lookup_by_name(char *name)
+{
+    struct device_s *device = devices;
+
+    while (device != NULL) {
+        if (strcmp(name, device->name) == 0)
+            return device;
+        device = device->next;
+    }
+    return (struct device_s *) 0;
+
+}
+
+struct memmap_s *memmap_lookup_by_name(char *name)
+{
+    struct memmap_s *memmap = memmaps;
+
+    while (memmap != NULL) {
+        if (strcmp(name, memmap->name) == 0)
+            return memmap;
+        memmap = memmap->next;
+    }
+    return (struct memmap_s *) 0;
+}
+
+char *manufacturer_name_lookup_by_id(int id)
+{
+    int i = 0;
+
+    while (manufacturers[i].id != 0) {
+        if (manufacturers[i].id == id)
+            return manufacturers[i].name;
+        i++;
+    }
+
+    return manufacturers[i].name;
+}
+
+int manufacturer_id_lookup_by_name(char *name)
+{
+    int i = 0;
+
+    while (manufacturers[i].id != 0) {
+        if (strcmp(manufacturers[i].name, name) == 0)
+            return manufacturers[i].id;
+        i++;
+    }
+
+    return 0;
+}
+
+char *algorithm_name_lookup_by_id(int id)
+{
+    int i = 0;
+
+    while (algorithms[i].id != 0) {
+        if (algorithms[i].id == id)
+            return algorithms[i].name;
+        i++;
+    }
+
+    return algorithms[i].name;
+}
+
+int algorithm_id_lookup_by_name(char *name)
+{
+    int i = 0;
+
+    while (algorithms[i].id != 0) {
+        if (strcmp(algorithms[i].name, name) == 0)
+            return algorithms[i].id;
+        i++;
+    }
+
+    return 0;
+}