X-Git-Url: http://gitweb.hugovil.com/?a=blobdiff_plain;f=src%2Fcommon%2Fhexfile.c;h=b9aff06117733fb044e4de7bf2e1bd2852e307b8;hb=121bcb38f29409f10de63a68d86620c4beb75c97;hp=80a0aac9c17a719c0b5686e4d226f35d6ff69742;hpb=c2ac9fc48f2772a87164e0e432fc773debe47e89;p=emu8051.git diff --git a/src/common/hexfile.c b/src/common/hexfile.c index 80a0aac..b9aff06 100644 --- a/src/common/hexfile.c +++ b/src/common/hexfile.c @@ -4,28 +4,16 @@ * Copyright (C) 1999 Jonathan St-André * Copyright (C) 1999 Hugo Villeneuve * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; either version 2 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA. + * This file is released under the GPLv2 */ #if HAVE_CONFIG_H # include "config.h" #endif -#include #include #include +#include #if STDC_HEADERS # include @@ -39,48 +27,51 @@ /* Maximum of 75 digits with 32-bytes data records. */ #define HEXFILE_LINE_BUFFER_LEN 128 +static int asciihex2int_error; + +int +asciihex2int_get_error(void) +{ + return asciihex2int_error; +} + /* Convert integer to ASCII hex string. */ void int2asciihex(int val, char *str, int width) { if (width == 1) - sprintf(str , "%.1X", (u_int8_t) val); + sprintf(str , "%.1X", (uint8_t) val); else if (width == 2) - sprintf(str , "%.2X", (u_int8_t) val); + sprintf(str , "%.2X", (uint8_t) val); else if (width == 4) - sprintf(str , "%.4X", (u_int16_t) val); + sprintf(str , "%.4X", (uint16_t) val); else sprintf(str , "Err"); } -/* Convert ASCII hex string to integer. */ -int -asciihex2int(char *str) -{ - int val; - - sscanf(str, "%X", &val); - - return val; -} - -/* Convert an ascii string to an hexadecimal number. */ -unsigned int -Ascii2Hex(char *istring, int length) +/* + * Convert ASCII string in hexadecimal notation to integer, up to length + * characters. + * The string contains only [0-9] and [a-f] characters (no "0x" prefix). + */ +static unsigned int +asciihex2int_len(char *str, int length) { unsigned int result = 0; int i, ascii_code; - if (!length || (length > (int) strlen(istring))) - length = strlen(istring); + asciihex2int_error = false; + + if (!length || (length > (int) strlen(str))) + length = strlen(str); for (i = 0; i < length; i++) { - ascii_code = istring[i]; + ascii_code = str[i]; if (ascii_code > 0x39) ascii_code &= 0xDF; if ((ascii_code >= 0x30 && ascii_code <= 0x39) || - (ascii_code >= 0x41 && ascii_code <= 0x46)) { + (ascii_code >= 0x41 && ascii_code <= 0x46)) { ascii_code -= 0x30; if (ascii_code > 9) ascii_code -= 7; @@ -88,29 +79,54 @@ Ascii2Hex(char *istring, int length) result <<= 4; result += ascii_code; } else { - log_fail("Error converting ASCII string <%s> to hex" - " (len=%d)", istring, length); + log_err("ASCII to hex conversion failure"); + asciihex2int_error = true; + return 0; } } return result; } -void -LoadHexFile(const char *filename) +/* + * Convert ASCII string in hexadecimal notation to integer, up to \0 end character. + * The string must not contain prefix "0x", only [0-9] and [a-f] characters. + */ +unsigned int +asciihex2int(char *str) { - int i, j, RecLength, LoadOffset, RecType, Data, Checksum; + /* Set length to zero to use full length of string. */ + return asciihex2int_len(str, 0); +} + +/* + * Return value: + * true: success + * false: failure + */ +int +hexfile_load(const char *filename) +{ + int i, j, rec_len, load_offset, rec_type, data, checksum; FILE *fp; int status; char line[HEXFILE_LINE_BUFFER_LEN]; + int valid = false; + int line_num = 1; - if (filename == NULL) - log_fail("No file specified"); + log_debug("LoadHexFile"); + + if (filename == NULL) { + log_err("No file specified"); + return false; + } /* Trying to open the file. */ fp = fopen(filename, "r"); - if (fp == NULL) - log_fail("Error opening hex file <%s>: %s", filename, - strerror(errno)); + if (fp == NULL) { + log_err("Error opening hex file <%s>: %s", filename, + strerror(errno)); + return false; + } /* Reading one line of data from the hex file. */ /* char *fgets(char *s, int size, FILE *stream); @@ -120,60 +136,70 @@ LoadHexFile(const char *filename) */ while (fgets(line, HEXFILE_LINE_BUFFER_LEN, fp) != NULL) { i = 0; - Checksum = 0; + checksum = 0; if (line[i++] != ':') { log_err("hexfile line not beginning with \":\""); goto close_file; } - RecLength = Ascii2Hex(&line[i], 2); + rec_len = asciihex2int_len(&line[i], 2); i += 2; - Checksum += RecLength; + checksum += rec_len; - LoadOffset = Ascii2Hex(&line[i], 4); - Checksum += LoadOffset / 256; - Checksum += LoadOffset % 256; + load_offset = asciihex2int_len(&line[i], 4); + checksum += load_offset / 256; + checksum += load_offset % 256; i += 4; - RecType = Ascii2Hex(&line[i], 2); + rec_type = asciihex2int_len(&line[i], 2); i += 2; - Checksum += RecType; - - if (RecType == 1) { - Checksum += Ascii2Hex(&line[i], 2); - Checksum &= 0x000000FF; - - if (Checksum) { - log_err("hexfile invalid format"); - goto close_file; - } else { - /* OK */ - goto close_file; + checksum += rec_type; + + if (rec_type == 0) { + for (j = 0; j < rec_len; j++) { + data = asciihex2int_len(&line[i], 2); + mem_write8(PGM_MEM_ID, + (unsigned int) (load_offset + j), + (unsigned char) data); + i += 2; + checksum += data; } } - for (j = 0; j < RecLength; j++) { - Data = Ascii2Hex(&line[i], 2); - memory_write8(PGM_MEM_ID, - (unsigned int)(LoadOffset + j), - (unsigned char)Data); - i += 2; - Checksum += Data; - } - - RecType = Ascii2Hex(&line[i], 2); - Checksum += RecType; - Checksum &= 0x000000FF; + /* Read and add checksum value */ + checksum += asciihex2int_len(&line[i], 2); + checksum &= 0x000000FF; - if (Checksum) { + if (asciihex2int_error) { + log_err("hexfile parse error at line %d", line_num); + goto close_file; + } else if (checksum) { log_err("hexfile checksum mismatch"); goto close_file; } + + if (rec_type == 0) { + log_debug("hex record: data"); + } else if (rec_type == 1) { + log_debug("hex record: End Of File"); + valid = true; + goto close_file; + } else { + log_warn("hex record: Unsupported ($%02X)", rec_type); + } + + line_num++; } close_file: status = fclose(fp); - if (status != EXIT_SUCCESS) - log_fail("Error closing hex file"); + if (status != EXIT_SUCCESS) { + log_err("Error closing hex file"); + valid = false; + } else if (!valid) { + log_err("Error parsing hex file"); + } + + return valid; }