qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
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

  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).