Updater: Use -O0 and write flash writer and fix hex parser
This commit is contained in:
@@ -1,72 +1,74 @@
|
||||
#include "hex-parser.h"
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
static int convert_hex_char_to_value(char c, uint32_t *out)
|
||||
{
|
||||
int ret = 0;
|
||||
uint32_t value = 0;
|
||||
int ret = 0;
|
||||
uint32_t value = 0;
|
||||
|
||||
if (!out)
|
||||
return -1002;
|
||||
if (!out)
|
||||
return -1002;
|
||||
|
||||
switch (c) {
|
||||
case '0' ... '9':
|
||||
value = (uint32_t)c - (uint32_t)'0';
|
||||
break;
|
||||
case 'a' ... 'f':
|
||||
/* Convert to upper */
|
||||
c -= 0x20;
|
||||
/* FALLTHRU */
|
||||
case 'A' ... 'F':
|
||||
value = (uint32_t)c - (uint32_t)'A' + 10UL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
switch (c) {
|
||||
case '0' ... '9':
|
||||
value = (uint32_t)c - (uint32_t)'0';
|
||||
break;
|
||||
case 'a' ... 'f':
|
||||
/* Convert to upper */
|
||||
c -= 0x20;
|
||||
/* FALLTHRU */
|
||||
case 'A' ... 'F':
|
||||
value = (uint32_t)c - (uint32_t)'A' + 10UL;
|
||||
break;
|
||||
default:
|
||||
ret = -1;
|
||||
}
|
||||
|
||||
if (ret == 0)
|
||||
*out = value;
|
||||
if (ret == 0)
|
||||
*out = value;
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int convert_big_endian_hex_string_to_val(const char *string, size_t len, uint32_t *out)
|
||||
{
|
||||
int ret_val = -1;
|
||||
uint32_t converted_value = 0UL;
|
||||
uint32_t digit;
|
||||
int res;
|
||||
unsigned int i;
|
||||
int ret_val = -1;
|
||||
uint32_t converted_value = 0UL;
|
||||
uint32_t digit;
|
||||
int res;
|
||||
unsigned int i;
|
||||
|
||||
/* Return error in case of an input error */
|
||||
if (!string || !len)
|
||||
goto exit;
|
||||
/* Return error in case of an input error */
|
||||
if (!string || !len)
|
||||
goto exit;
|
||||
|
||||
if (!out)
|
||||
return -1003;
|
||||
if (!out)
|
||||
return -1003;
|
||||
|
||||
/* we don't support strings larger than 8 chars */
|
||||
if (len > 8)
|
||||
goto exit;
|
||||
/* we don't support strings larger than 8 chars */
|
||||
if (len > 8)
|
||||
goto exit;
|
||||
|
||||
|
||||
for (i = 0; i < len && string[i] != '\0'; i++) {
|
||||
/* Convert current character to number */
|
||||
res = convert_hex_char_to_value(string[i], &digit);
|
||||
if (res) {
|
||||
/* Not a hex number */
|
||||
ret_val = -2;
|
||||
goto exit;
|
||||
}
|
||||
for (i = 0; i < len && string[i] != '\0'; i++) {
|
||||
/* Convert current character to number */
|
||||
res = convert_hex_char_to_value(string[i], &digit);
|
||||
if (res) {
|
||||
/* Not a hex number */
|
||||
ret_val = -2;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
converted_value *= 0x10;
|
||||
converted_value += digit;
|
||||
}
|
||||
converted_value *= 0x10;
|
||||
converted_value += digit;
|
||||
}
|
||||
|
||||
*out = converted_value;
|
||||
*out = converted_value;
|
||||
ret_val = 0;
|
||||
|
||||
exit:
|
||||
return ret_val;
|
||||
return ret_val;
|
||||
}
|
||||
|
||||
enum hex_parser_ret hex_parser_open(struct hex_parser *parser, const char *file_name)
|
||||
@@ -85,7 +87,179 @@ enum hex_parser_ret hex_parser_open(struct hex_parser *parser, const char *file_
|
||||
return HEX_PARSER_OK;
|
||||
}
|
||||
|
||||
enum hex_parser_ret hex_parser_parse(struct hex_parser *parser, uint32_t *address, char *data, size_t data_len);
|
||||
static int read_line_from_file(FIL *file, char *data, int size)
|
||||
{
|
||||
char *ret_ptr;
|
||||
int length;
|
||||
|
||||
ret_ptr = f_gets(data, size, file);
|
||||
if (!ret_ptr)
|
||||
return -1;
|
||||
|
||||
/* To be sure */
|
||||
data[size - 1] = 0;
|
||||
length = strlen(ret_ptr);
|
||||
|
||||
return length;
|
||||
}
|
||||
|
||||
static int hex_record_check_checksum(const char *buff, int hex_byte_count)
|
||||
{
|
||||
int i;
|
||||
int res;
|
||||
uint32_t checksum = 0;
|
||||
uint32_t tmp;
|
||||
|
||||
if (!buff || !hex_byte_count)
|
||||
return -1000;
|
||||
|
||||
for (i = 0; i < hex_byte_count; i++) {
|
||||
res = convert_big_endian_hex_string_to_val(&buff[2 * i], 2, &tmp);
|
||||
if (res)
|
||||
return -1;
|
||||
checksum += tmp;
|
||||
}
|
||||
|
||||
if (checksum & 0xFF) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
enum hex_parser_ret hex_parser_parse(struct hex_parser *parser, uint32_t *address, char *data, size_t data_len,
|
||||
size_t *lenout)
|
||||
{
|
||||
static char workbuff[512];
|
||||
int count;
|
||||
int i;
|
||||
enum hex_parser_ret retval = HEX_PARSER_DATA_OK;
|
||||
uint32_t hex_addr;
|
||||
uint32_t byte_count;
|
||||
uint32_t record_type;
|
||||
uint32_t tmp;
|
||||
|
||||
if (!parser || !lenout || !data_len || !data || !address)
|
||||
return HEX_PARSER_ERROR;
|
||||
|
||||
/* Read a line from the file */
|
||||
count = read_line_from_file(&parser->file, workbuff, sizeof(workbuff));
|
||||
if (!count) {
|
||||
/* Check for error in case nothing is read */
|
||||
if (f_error(&parser->file)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
} else if (f_eof(&parser->file)) {
|
||||
retval = HEX_PARSER_FILE_END;
|
||||
goto exit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Strip out invalid characters at the end */
|
||||
for (i = count - 1; i >= 0; i--) {
|
||||
if (workbuff[i] == '\r' || workbuff[i] == '\n' ||
|
||||
workbuff[i] == '\t' || workbuff[i] == ' ')
|
||||
{
|
||||
workbuff[i] = 0;
|
||||
count--;
|
||||
}
|
||||
}
|
||||
|
||||
/* We read a valid line, check for valid marker */
|
||||
if (workbuff[0] != ':') {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Line has to be longer than 11 chars in total */
|
||||
if (count < 11) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Read in the data count */
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[1], 2, &byte_count)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Read in the address */
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[3], 4, &hex_addr)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Read in the record type */
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[7], 2, &record_type)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
if (byte_count * 2 + 9 + 2 != (unsigned int)count) {
|
||||
/* Line not the expected length */
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check the checksum. We have bytecount + 5 bytes in a record */
|
||||
if (hex_record_check_checksum(&workbuff[1], byte_count + 5)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
goto exit;
|
||||
}
|
||||
|
||||
/* Check record type */
|
||||
switch (record_type) {
|
||||
case 0x00: /* Data */
|
||||
if (byte_count > data_len) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
*lenout = 0;
|
||||
*address = hex_addr + parser->current_address_offset;
|
||||
|
||||
for (i = 0; i < (int)byte_count; i++) {
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[9 + 2*i], 2, &tmp)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
*data = (char)(tmp & 0xFF);
|
||||
data++;
|
||||
(*lenout)++;
|
||||
}
|
||||
retval = HEX_PARSER_DATA_OK;
|
||||
break;
|
||||
case 0x01: /* End of file */
|
||||
retval = HEX_PARSER_EOF_RECORD;
|
||||
break;
|
||||
case 0x04: /* extended linear address */
|
||||
if (byte_count != 2) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
/* Parse the upper 16 bit of the address */
|
||||
if (convert_big_endian_hex_string_to_val(&workbuff[9], 4, &tmp)) {
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
}
|
||||
|
||||
parser->current_address_offset = tmp << 16;
|
||||
retval = HEX_PARSER_OK;
|
||||
break;
|
||||
case 0x05:
|
||||
retval = HEX_PARSER_OK;
|
||||
break;
|
||||
default:
|
||||
retval = HEX_PARSER_ERROR;
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
exit:
|
||||
return retval;
|
||||
}
|
||||
|
||||
enum hex_parser_ret hex_parser_close(struct hex_parser *parser) {
|
||||
if (!parser)
|
||||
|
||||
Reference in New Issue
Block a user