FreeCalypso > hg > freecalypso-reveng
view fluid-mnf/fileio.c @ 343:917e05f03ad2
fluid-mnf/serial.c: <assert.h> no longer needed
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 13 Mar 2020 05:40:23 +0000 |
parents | b730c7844233 |
children | f89a20e7adc7 |
line wrap: on
line source
/****************************************************************************** * 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" #if 0 #include "../target/target.h" #endif #include "calplus/secure_types.h" // Secure Calypso Plus #include <stdio.h> #include <malloc.h> #include <stdlib.h> #include <string.h> /* definitions from ../target/target.h */ // ESample #define CALP_OFFSET 0x4000000 // CS_MODE 0: Flash at 0x04000000 @ CS5 // Secure Calypso Plus #define CMD_SECURE_CALP_OFFSET 0x08020000 // Flash programmer offset in internal SRAM. /****************************************************************************** * 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; }