Patchwork [v9,3/4] use elf_reset to reload elf image

login
register
mail settings
Submitter Olivia Yin
Date Jan. 18, 2013, 9:16 a.m.
Message ID <1358500598-19518-4-git-send-email-hong-hua.yin@freescale.com>
Download mbox | patch
Permalink /patch/213560/
State New
Headers show

Comments

Olivia Yin - Jan. 18, 2013, 9:16 a.m.
Signed-off-by: Olivia Yin <hong-hua.yin@freescale.com>
---
 hw/elf_ops.h |   45 ++++++++++++++++++++++++++++++++++++++++-----
 hw/loader.c  |   11 +++++++++++
 hw/loader.h  |    9 +++++++++
 3 files changed, 60 insertions(+), 5 deletions(-)

Patch

diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index 531a425..25ee02a 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -187,12 +187,12 @@  static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
     return -1;
 }
 
-static int glue(load_elf, SZ)(const char *name, int fd,
+static int glue(elf_phy_loader, SZ)(const char *name, int fd,
                               uint64_t (*translate_fn)(void *, uint64_t),
                               void *translate_opaque,
                               int must_swab, uint64_t *pentry,
                               uint64_t *lowaddr, uint64_t *highaddr,
-                              int elf_machine, int clear_lsb)
+                              int elf_machine, int clear_lsb, int reset)
 {
     struct elfhdr ehdr;
     struct elf_phdr *phdr = NULL, *ph;
@@ -202,6 +202,9 @@  static int glue(load_elf, SZ)(const char *name, int fd,
     uint8_t *data = NULL;
     char label[128];
 
+    if (reset) {
+        fd = open(name, O_RDONLY | O_BINARY);
+    }
     if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
         goto fail;
     if (must_swab) {
@@ -232,7 +235,9 @@  static int glue(load_elf, SZ)(const char *name, int fd,
     if (pentry)
    	*pentry = (uint64_t)(elf_sword)ehdr.e_entry;
 
-    glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb);
+    if (!reset) {
+        glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb);
+    }
 
     size = ehdr.e_phnum * sizeof(phdr[0]);
     lseek(fd, ehdr.e_phoff, SEEK_SET);
@@ -280,8 +285,12 @@  static int glue(load_elf, SZ)(const char *name, int fd,
                 *pentry = ehdr.e_entry - ph->p_vaddr + ph->p_paddr;
             }
 
-            snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
-            rom_add_blob_fixed(label, data, mem_size, addr);
+            if (!reset) {
+                snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
+                rom_add_blob_fixed(label, data, mem_size, addr);
+            } else {
+                cpu_physical_memory_write(addr, data, mem_size);
+            }
 
             total_size += mem_size;
             if (addr < low)
@@ -304,3 +313,29 @@  static int glue(load_elf, SZ)(const char *name, int fd,
     g_free(phdr);
     return -1;
 }
+
+static void glue(elf_reset, SZ)(void *opaque)
+{
+    FlatImageFile *elf = opaque;
+    int fd;
+    
+    fd = open(elf->image.name, O_RDONLY | O_BINARY);
+    glue(elf_phy_loader, SZ)(elf->image.name, fd, elf->fn, elf->opaque,
+                             elf->swab, NULL, NULL, NULL,
+                             elf->machine, elf->lsb, 1);
+}
+
+static int glue(load_elf, SZ)(const char *name, int fd,
+                              uint64_t (*translate_fn)(void *, uint64_t),
+                              void *translate_opaque,
+                              int must_swab, uint64_t *pentry,
+                              uint64_t *lowaddr, uint64_t *highaddr,
+                              int elf_machine, int clear_lsb)
+{
+    int ret;
+
+    ret = glue(elf_phy_loader, SZ)(name, fd, (*translate_fn), translate_opaque,
+                                   must_swab, pentry, lowaddr, highaddr,
+                                   elf_machine, clear_lsb, 0);
+    return ret;
+}
diff --git a/hw/loader.c b/hw/loader.c
index 89ce853..5849e32 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -343,13 +343,24 @@  int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
         goto fail;
     }
 
+    FlatImageFile *elf;
+    elf = g_malloc0(sizeof(*elf));
+    elf->image.name = g_strdup(filename);
+    elf->fn = translate_fn;
+    elf->opaque = translate_opaque;
+    elf->swab = must_swab;
+    elf->machine = elf_machine;
+    elf->lsb = clear_lsb;
+
     lseek(fd, 0, SEEK_SET);
     if (e_ident[EI_CLASS] == ELFCLASS64) {
         ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
                          pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+        qemu_register_reset(elf_reset64, elf);
     } else {
         ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
                          pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+        qemu_register_reset(elf_reset32, elf);
     }
 
     close(fd);
diff --git a/hw/loader.h b/hw/loader.h
index b22d77b..69fac87 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -13,6 +13,15 @@  typedef struct UImageFile {
     int *is_linux;
 } UImageFile;
 
+typedef struct FlatImageFile {
+    ImageFile image;
+    uint64_t (*fn)(void *, uint64_t);
+    void *opaque;
+    int swab;
+    int machine;
+    int lsb;
+} FlatImageFile;
+
 /* loader.c */
 int get_image_size(const char *filename);
 int load_image(const char *filename, uint8_t *addr); /* deprecated */