FreeCalypso > hg > freecalypso-reveng
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; +}