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