From 3cb7c05906b8eb8e884013b441f352256fded011 Mon Sep 17 00:00:00 2001 From: Tobias Klauser Date: Wed, 10 Nov 2010 17:10:07 +0100 Subject: First bunch of rework, stil work in progress --- srec.c | 169 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 169 insertions(+) create mode 100644 srec.c (limited to 'srec.c') diff --git a/srec.c b/srec.c new file mode 100644 index 0000000..dde118c --- /dev/null +++ b/srec.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2010 Tobias Klauser + * + * This file is part of nios2sim-ng. + * + * This file is subject to the terms and conditions of the GNU General Public + * License. See the file "COPYING" in the main directory of this archive + * for more details. + */ + +#include +#include +#include +#include + +#include "nios2sim-ng.h" +#include "image.h" + +#define SREC_CRC_COUNT 1 + +#define SREC_LINE_LENGTH 515 +static char data_buf[SREC_LINE_LENGTH]; + +/** + * @return length of the line + */ +static ssize_t srec_read_line(FILE *fp, char *buf, size_t count) +{ + char c; + ssize_t len = 0; + + while (count > 0 && !feof(fp)) { + if (ferror(fp)) { + err("ferror\n"); + goto err_out; + } + + /* Read byte by byte */ + if (fread(&c, 1, 1, fp) == 1) { + if (c == '\n' || c == '\r') + break; /* end of line */ + + buf[len++] = c; + count--; + } else { + if (feof(fp) && !ferror(fp)) + break; + else + goto err_out; + } + } + + return len; +err_out: + return -1; +} + +static int srec_load_S3(char *buf, size_t data_count, + uint32_t start_addr, uint8_t *mem_base, size_t mem_size) +{ + size_t i; + uint32_t *base = (uint32_t *) mem_base; + off_t offset = 0; + + for (i = 0; i < data_count; i += 4) { + uint32_t tmp; + + if (sscanf(buf + i * 2, "%8x", &tmp) != 1) { + err("sscanf() failed on S3 record\n"); + return -1; + } + /* SREC is Big Endian, NiosII is Little Endian */ + tmp = bswap_32(tmp); + + if (offset + i > mem_size - 1) { + err("Image file too large for allocated memory of %zu bytes\n", mem_size); + return -1; + } + /* Store in memory */ + base[offset + i] = tmp; + } + + return 0; +} + +static int srec_handle_line(char *buf, size_t len, uint8_t *mem_base, size_t mem_size) +{ + unsigned int data_count = 0; + unsigned int start_addr; + + /* Minimum valid record size */ + if (len < 2) { + err("Invalid line in SREC file\n"); + return -1; + } + + if (buf[0] != 'S') { + err("Invalid line in SREC file\n"); + return -1; + } + + switch (buf[1]) { + case '0': + dbg("handling S0\n"); + break; + case '1': + dbg("handling S1\n"); + break; + case '2': + dbg("handling S2\n"); + break; + case '3': + if (sscanf(buf, "S3%2x%8x", &data_count, &start_addr) != 2) { + err("Invalid S3 record\n"); + return -1; + } + + if (srec_load_S3(buf + 12, data_count - 4, start_addr, mem_base, mem_size) != 0) + return -1; + break; + case '4': + dbg("handling S4\n"); + break; + case '5': + dbg("handling S5\n"); + break; + case '6': + dbg("handling S6\n"); + break; + case '7': + dbg("handling S7\n"); + break; + case '8': + dbg("handling S8\n"); + break; + case '9': + dbg("handling S9\n"); + break; + default: + err("Invalid SREC type: %c\n", buf[1]); + return -1; + } + + return 0; +} + +int srec_load(FILE *fp, const char *name, uint8_t *mem_base, size_t mem_size) +{ + ssize_t len; + int ret = 0; + + while (1) { + memset(data_buf, 0x00, SREC_LINE_LENGTH); + len = srec_read_line(fp, data_buf, SREC_LINE_LENGTH); + if (len < 0) { + ret = -1; + break; + } else if (len == 0) { + ret = 0; + break; + } else { + ret = srec_handle_line(data_buf, len, mem_base, mem_size); + if (ret < 0) + break; + } + } + + return ret; +} -- cgit v1.2.3-54-g00ecf