From: Serge Vakulenko <serge.vakulenko@gmail.com>
To: qemu-devel@nongnu.org
Cc: Serge Vakulenko <serge.vakulenko@gmail.com>,
Leon Alrae <leon.alrae@imgtec.com>,
Aurelien Jarno <aurelien@aurel32.net>
Subject: [Qemu-devel] [PATCH pic32 v3 10/16] pic32: add file pic32_load_hex.c
Date: Sun, 5 Jul 2015 23:14:58 -0700 [thread overview]
Message-ID: <1436163304-6167-11-git-send-email-serge.vakulenko@gmail.com> (raw)
In-Reply-To: <1436163304-6167-1-git-send-email-serge.vakulenko@gmail.com>
It allows to load executables in Intel .hex or Motorola .srec format.
Signed-off-by: Serge Vakulenko <serge.vakulenko@gmail.com>
---
hw/mips/pic32_load_hex.c | 238 +++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 238 insertions(+)
create mode 100644 hw/mips/pic32_load_hex.c
diff --git a/hw/mips/pic32_load_hex.c b/hw/mips/pic32_load_hex.c
new file mode 100644
index 0000000..720c9ee
--- /dev/null
+++ b/hw/mips/pic32_load_hex.c
@@ -0,0 +1,238 @@
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <ctype.h>
+
+#include "pic32_peripherals.h"
+
+/* Macros for converting between hex and binary. */
+#define NIBBLE(x) (isdigit(x) ? (x)-'0' : tolower(x)+10-'a')
+#define HEX(buffer) ((NIBBLE((buffer)[0])<<4) + NIBBLE((buffer)[1]))
+
+static unsigned virt_to_phys(unsigned address)
+{
+ if (address >= 0xa0000000 && address <= 0xbfffffff) {
+ return address - 0xa0000000;
+ }
+ if (address >= 0x80000000 && address <= 0x9fffffff) {
+ return address - 0x80000000;
+ }
+ return address;
+}
+
+/*
+ * Read the S record file.
+ */
+static int load_srec(const char *filename,
+ void (*store_byte)(unsigned address, unsigned char byte))
+{
+ FILE *fd;
+ unsigned char buf[256];
+ unsigned char *data;
+ unsigned address;
+ int bytes, output_len;
+
+ fd = fopen(filename, "r");
+ if (!fd) {
+ perror(filename);
+ exit(1);
+ }
+ output_len = 0;
+ while (fgets((char *) buf, sizeof(buf), fd)) {
+ if (buf[0] == '\n') {
+ continue;
+ }
+ if (buf[0] != 'S') {
+ if (output_len == 0) {
+ break;
+ }
+ printf("%s: bad file format\n", filename);
+ exit(1);
+ }
+
+ /* Starting an S-record. */
+ if (!isxdigit(buf[2]) || !isxdigit(buf[3])) {
+ printf("%s: bad record: %s\n", filename, buf);
+ exit(1);
+ }
+ bytes = HEX(buf + 2);
+
+ /* Ignore the checksum byte. */
+ --bytes;
+
+ address = 0;
+ data = buf + 4;
+ switch (buf[1]) {
+ case '7':
+ address = HEX(data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '8':
+ address = (address << 8) | HEX(data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '9':
+ address = (address << 8) | HEX(data);
+ data += 2;
+ address = (address << 8) | HEX(data);
+ data += 2;
+ bytes -= 2;
+ if (bytes == 0) {
+ /*printf("%s: start address = %08x\n", filename, address);*/
+ /* TODO: set start address. */
+ }
+ goto done;
+
+ case '3':
+ address = HEX(data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '2':
+ address = (address << 8) | HEX(data);
+ data += 2;
+ --bytes;
+ /* Fall through. */
+ case '1':
+ address = (address << 8) | HEX(data);
+ data += 2;
+ address = (address << 8) | HEX(data);
+ data += 2;
+ bytes -= 2;
+
+ address = virt_to_phys(address);
+ output_len += bytes;
+ while (bytes-- > 0) {
+ store_byte(address++, HEX(data));
+ data += 2;
+ }
+ break;
+ }
+ }
+done:
+ fclose(fd);
+ return output_len;
+}
+
+/*
+ * Read HEX file.
+ */
+static int load_hex(const char *filename,
+ void (*store_byte)(unsigned address, unsigned char byte))
+{
+ FILE *fd;
+ unsigned char buf[256], data[16], record_type, sum;
+ unsigned address, high;
+ int bytes, output_len, i;
+
+ fd = fopen(filename, "r");
+ if (!fd) {
+ perror(filename);
+ exit(1);
+ }
+ output_len = 0;
+ high = 0;
+ while (fgets((char *) buf, sizeof(buf), fd)) {
+ if (buf[0] == '\n') {
+ continue;
+ }
+ if (buf[0] != ':') {
+ if (output_len == 0) {
+ break;
+ }
+ printf("%s: bad HEX file format\n", filename);
+ exit(1);
+ }
+ if (!isxdigit(buf[1]) || !isxdigit(buf[2]) ||
+ !isxdigit(buf[3]) || !isxdigit(buf[4]) ||
+ !isxdigit(buf[5]) || !isxdigit(buf[6]) ||
+ !isxdigit(buf[7]) || !isxdigit(buf[8])) {
+ printf("%s: bad record: %s\n", filename, buf);
+ exit(1);
+ }
+ record_type = HEX(buf+7);
+ if (record_type == 1) {
+ /* End of file. */
+ break;
+ }
+ bytes = HEX(buf+1);
+ if (strlen((char *) buf) < bytes * 2 + 11) {
+ printf("%s: too short hex line\n", filename);
+ exit(1);
+ }
+ address = high << 16 | HEX(buf+3) << 8 | HEX(buf+5);
+ if (address & 3) {
+ printf("%s: odd address\n", filename);
+ exit(1);
+ }
+
+ sum = 0;
+ for (i = 0; i < bytes; ++i) {
+ data[i] = HEX(buf+9 + i + i);
+ sum += data[i];
+ }
+ sum += record_type + bytes + (address & 0xff) + (address >> 8 & 0xff);
+ if (sum != (unsigned char) -HEX(buf+9 + bytes + bytes)) {
+ printf("%s: bad hex checksum\n", filename);
+ printf("Line %s", buf);
+ exit(1);
+ }
+
+ if (record_type == 5) {
+ /* Start address. */
+ if (bytes != 4) {
+ printf("%s: invalid length of hex start address record: "
+ "%d bytes\n", filename, bytes);
+ exit(1);
+ }
+ address = data[0] << 24 | data[1] << 16 | data[2] << 8 | data[3];
+ /*printf("%s: start address = %08x\n", filename, address);*/
+ /* TODO: set start address. */
+ continue;
+ }
+ if (record_type == 4) {
+ /* Extended address. */
+ if (bytes != 2) {
+ printf("%s: invalid length of hex linear address record: "
+ "%d bytes\n", filename, bytes);
+ exit(1);
+ }
+ high = data[0] << 8 | data[1];
+ continue;
+ }
+ if (record_type != 0) {
+ printf("%s: unknown hex record type: %d\n",
+ filename, record_type);
+ exit(1);
+ }
+
+ /* Data record found. */
+ address = virt_to_phys(address);
+ output_len += bytes;
+ for (i = 0; i < bytes; i++) {
+ store_byte(address++, data[i]);
+ }
+ }
+ fclose(fd);
+ return output_len;
+}
+
+int pic32_load_hex_file(const char *filename,
+ void (*store_byte)(unsigned address, unsigned char byte))
+{
+ int memory_len = load_srec(filename, store_byte);
+ if (memory_len == 0) {
+ memory_len = load_hex(filename, store_byte);
+ if (memory_len == 0) {
+ return 0;
+ }
+ }
+ printf("Load file: '%s', %d bytes\n", filename, memory_len);
+ if (qemu_logfile) {
+ fprintf(qemu_logfile, "Load file: '%s', %d bytes\n",
+ filename, memory_len);
+ }
+ return 1;
+}
--
2.2.2
next prev parent reply other threads:[~2015-07-06 6:17 UTC|newest]
Thread overview: 30+ messages / expand[flat|nested] mbox.gz Atom feed top
2015-07-06 6:14 [Qemu-devel] [PATCH pic32 v3 00/16] add support for pic32 microcontrollers Serge Vakulenko
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 01/16] pic32: make the CPU clock frequency configurable per platform Serge Vakulenko
2015-07-06 8:42 ` Aurelien Jarno
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 02/16] pic32: use LCG algorithm for generated random index of TLBWR instruction Serge Vakulenko
2015-07-06 8:43 ` Aurelien Jarno
2015-09-15 9:46 ` Leon Alrae
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 03/16] pic32: add support for external interrupt controller mode (EIC) Serge Vakulenko
2015-07-06 9:34 ` Aurelien Jarno
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 04/16] pic32: add two MIPS processor variants: M4K and microAptivUP Serge Vakulenko
2015-07-06 9:35 ` Aurelien Jarno
2015-10-02 10:37 ` Leon Alrae
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 05/16] pic32: add file pic32_peripherals.h Serge Vakulenko
2015-07-06 8:02 ` Peter Crosthwaite
2015-07-06 9:01 ` Aurelien Jarno
2015-07-06 17:04 ` Peter Crosthwaite
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 06/16] pic32: add file pic32mx.h Serge Vakulenko
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 07/16] pic32: add file pic32mz.h Serge Vakulenko
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 08/16] pic32: add file mips_pic32mx7.c Serge Vakulenko
2015-07-06 11:18 ` Antony Pavlov
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 09/16] pic32: add file mips_pic32mz.c Serge Vakulenko
2015-07-06 6:14 ` Serge Vakulenko [this message]
2015-07-06 6:14 ` [Qemu-devel] [PATCH pic32 v3 11/16] pic32: add file pic32_uart.c Serge Vakulenko
2015-07-06 8:08 ` Peter Crosthwaite
2015-07-06 6:15 ` [Qemu-devel] [PATCH pic32 v3 12/16] pic32: add file pic32_gpio.c Serge Vakulenko
2015-07-06 6:15 ` [Qemu-devel] [PATCH pic32 v3 13/16] pic32: add file pic32_spi.c Serge Vakulenko
2015-07-06 7:58 ` Peter Crosthwaite
2015-07-06 6:15 ` [Qemu-devel] [PATCH pic32 v3 14/16] pic32: add file pic32_sdcard.c Serge Vakulenko
2015-07-06 8:05 ` Peter Crosthwaite
2015-07-06 6:15 ` [Qemu-devel] [PATCH pic32 v3 15/16] pic32: add file pic32_ethernet.c Serge Vakulenko
2015-07-06 6:15 ` [Qemu-devel] [PATCH pic32 v3 16/16] pic32: update makefiles to cover pic32 support Serge Vakulenko
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1436163304-6167-11-git-send-email-serge.vakulenko@gmail.com \
--to=serge.vakulenko@gmail.com \
--cc=aurelien@aurel32.net \
--cc=leon.alrae@imgtec.com \
--cc=qemu-devel@nongnu.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).