Patchwork [RFC,v4,3/3] use elf_reset to reload elf image

login
register
mail settings
Submitter Olivia Yin
Date Nov. 14, 2012, 1:28 p.m.
Message ID <1352899732-1197-4-git-send-email-hong-hua.yin@freescale.com>
Download mbox | patch
Permalink /patch/198919/
State New
Headers show

Comments

Olivia Yin - Nov. 14, 2012, 1:28 p.m.
Signed-off-by: Olivia Yin <hong-hua.yin@freescale.com>
---
 elf.h        |   10 ++++++
 hw/elf_ops.h |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 111 insertions(+), 0 deletions(-)
Blue Swirl - Nov. 17, 2012, 4:09 p.m.
On Wed, Nov 14, 2012 at 1:28 PM, Olivia Yin <hong-hua.yin@freescale.com> wrote:
> Signed-off-by: Olivia Yin <hong-hua.yin@freescale.com>
> ---
>  elf.h        |   10 ++++++
>  hw/elf_ops.h |  101 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 111 insertions(+), 0 deletions(-)
>
> diff --git a/elf.h b/elf.h
> index a21ea53..335f1af 100644
> --- a/elf.h
> +++ b/elf.h
> @@ -1078,6 +1078,16 @@ typedef struct elf64_hdr {
>    Elf64_Half e_shstrndx;
>  } Elf64_Ehdr;
>
> +typedef struct ImageElf ImageElf;
> +struct ImageElf {
> +    char *name;
> +    uint64_t (*fn)(void *, uint64_t);
> +    void *opaque;
> +    int swab;
> +    int machine;
> +    int lsb;
> +};
> +
>  /* These constants define the permissions on sections in the program
>     header, p_flags. */
>  #define PF_R           0x4
> diff --git a/hw/elf_ops.h b/hw/elf_ops.h
> index 531a425..89654bb 100644
> --- a/hw/elf_ops.h
> +++ b/hw/elf_ops.h
> @@ -187,6 +187,95 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
>      return -1;
>  }
>
> +static void glue(elf_reset, SZ)(void *opaque)
> +{
> +    ImageElf *elf = opaque;
> +    struct elfhdr ehdr;
> +    struct elf_phdr *phdr = NULL, *ph;
> +    int size, i, fd;
> +    elf_word mem_size;
> +    uint64_t addr;
> +    uint8_t *data = NULL;
> +
> +    fd = open(elf->name, O_RDONLY | O_BINARY);
> +    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))

Please add braces and check your patches with checkpatch.pl.

> +        goto fail;
> +    if (elf->swab) {
> +        glue(bswap_ehdr, SZ)(&ehdr);
> +    }
> +
> +    switch (elf->machine) {
> +        case EM_PPC64:
> +            if (EM_PPC64 != ehdr.e_machine)
> +                if (EM_PPC != ehdr.e_machine)
> +                    goto fail;
> +            break;
> +        case EM_X86_64:
> +            if (EM_X86_64 != ehdr.e_machine)
> +                if (EM_386 != ehdr.e_machine)
> +                    goto fail;
> +            break;
> +        case EM_MICROBLAZE:
> +            if (EM_MICROBLAZE != ehdr.e_machine)
> +                if (EM_MICROBLAZE_OLD != ehdr.e_machine)
> +                    goto fail;
> +            break;
> +        default:
> +            if (elf->machine != ehdr.e_machine)
> +                goto fail;
> +    }
> +
> +    glue(load_symbols, SZ)(&ehdr, fd, elf->swab, elf->lsb);
> +
> +    size = ehdr.e_phnum * sizeof(phdr[0]);
> +    lseek(fd, ehdr.e_phoff, SEEK_SET);
> +    phdr = g_malloc0(size);
> +    if (!phdr)
> +        goto fail;
> +    if (read(fd, phdr, size) != size)
> +        goto fail;
> +    if (elf->swab) {
> +        for(i = 0; i < ehdr.e_phnum; i++) {
> +            ph = &phdr[i];
> +            glue(bswap_phdr, SZ)(ph);
> +        }
> +    }
> +
> +    for(i = 0; i < ehdr.e_phnum; i++) {
> +        ph = &phdr[i];
> +        if (ph->p_type == PT_LOAD) {
> +            mem_size = ph->p_memsz;
> +            /* XXX: avoid allocating */
> +            data = g_malloc0(mem_size);
> +            if (ph->p_filesz > 0) {
> +                if (lseek(fd, ph->p_offset, SEEK_SET) < 0)
> +                    goto fail;
> +                if (read(fd, data, ph->p_filesz) != ph->p_filesz)
> +                    goto fail;
> +            }
> +            /* address_offset is hack for kernel images that are
> +               linked at the wrong physical address.  */
> +            if (elf->fn) {
> +                addr = elf->fn(elf->opaque, ph->p_paddr);
> +            } else {
> +                addr = ph->p_paddr;
> +            }
> +
> +            cpu_physical_memory_write(addr, data, mem_size);
> +
> +            g_free(data);
> +            data = NULL;
> +        }
> +    }
> +    close(fd);
> +    g_free(phdr);
> +    phdr = NULL;
> + fail:
> +    close(fd);
> +    g_free(data);
> +    g_free(phdr);
> +}
> +
>  static int glue(load_elf, SZ)(const char *name, int fd,
>                                uint64_t (*translate_fn)(void *, uint64_t),
>                                void *translate_opaque,
> @@ -293,6 +382,18 @@ static int glue(load_elf, SZ)(const char *name, int fd,
>              data = NULL;
>          }
>      }
> +
> +    ImageElf *elf;
> +    elf = g_malloc0(sizeof(*elf));
> +    elf->name = g_strdup(name);
> +    elf->fn = translate_fn;
> +    elf->opaque = translate_opaque;
> +    elf->swab = must_swab;
> +    elf->machine = elf_machine;
> +    elf->lsb = clear_lsb;
> +
> +    qemu_register_reset(glue(elf_reset, SZ), elf);
> +
>      g_free(phdr);
>      if (lowaddr)
>          *lowaddr = (uint64_t)(elf_sword)low;
> --
> 1.7.1
>
>
>

Patch

diff --git a/elf.h b/elf.h
index a21ea53..335f1af 100644
--- a/elf.h
+++ b/elf.h
@@ -1078,6 +1078,16 @@  typedef struct elf64_hdr {
   Elf64_Half e_shstrndx;
 } Elf64_Ehdr;
 
+typedef struct ImageElf ImageElf;
+struct ImageElf {
+    char *name;
+    uint64_t (*fn)(void *, uint64_t);
+    void *opaque;
+    int swab;
+    int machine;
+    int lsb;
+};
+
 /* These constants define the permissions on sections in the program
    header, p_flags. */
 #define PF_R		0x4
diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index 531a425..89654bb 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -187,6 +187,95 @@  static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
     return -1;
 }
 
+static void glue(elf_reset, SZ)(void *opaque)
+{
+    ImageElf *elf = opaque;
+    struct elfhdr ehdr;
+    struct elf_phdr *phdr = NULL, *ph;
+    int size, i, fd;
+    elf_word mem_size;
+    uint64_t addr;
+    uint8_t *data = NULL;
+
+    fd = open(elf->name, O_RDONLY | O_BINARY);
+    if (read(fd, &ehdr, sizeof(ehdr)) != sizeof(ehdr))
+        goto fail;
+    if (elf->swab) {
+        glue(bswap_ehdr, SZ)(&ehdr);
+    }
+
+    switch (elf->machine) {
+        case EM_PPC64:
+            if (EM_PPC64 != ehdr.e_machine)
+                if (EM_PPC != ehdr.e_machine)
+                    goto fail;
+            break;
+        case EM_X86_64:
+            if (EM_X86_64 != ehdr.e_machine)
+                if (EM_386 != ehdr.e_machine)
+                    goto fail;
+            break;
+        case EM_MICROBLAZE:
+            if (EM_MICROBLAZE != ehdr.e_machine)
+                if (EM_MICROBLAZE_OLD != ehdr.e_machine)
+                    goto fail;
+            break;
+        default:
+            if (elf->machine != ehdr.e_machine)
+                goto fail;
+    }
+
+    glue(load_symbols, SZ)(&ehdr, fd, elf->swab, elf->lsb);
+
+    size = ehdr.e_phnum * sizeof(phdr[0]);
+    lseek(fd, ehdr.e_phoff, SEEK_SET);
+    phdr = g_malloc0(size);
+    if (!phdr)
+        goto fail;
+    if (read(fd, phdr, size) != size)
+        goto fail;
+    if (elf->swab) {
+        for(i = 0; i < ehdr.e_phnum; i++) {
+            ph = &phdr[i];
+            glue(bswap_phdr, SZ)(ph);
+        }
+    }
+
+    for(i = 0; i < ehdr.e_phnum; i++) {
+        ph = &phdr[i];
+        if (ph->p_type == PT_LOAD) {
+            mem_size = ph->p_memsz;
+            /* XXX: avoid allocating */
+            data = g_malloc0(mem_size);
+            if (ph->p_filesz > 0) {
+                if (lseek(fd, ph->p_offset, SEEK_SET) < 0)
+                    goto fail;
+                if (read(fd, data, ph->p_filesz) != ph->p_filesz)
+                    goto fail;
+            }
+            /* address_offset is hack for kernel images that are
+               linked at the wrong physical address.  */
+            if (elf->fn) {
+                addr = elf->fn(elf->opaque, ph->p_paddr);
+            } else {
+                addr = ph->p_paddr;
+            }
+
+            cpu_physical_memory_write(addr, data, mem_size);
+
+            g_free(data);
+            data = NULL;
+        }
+    }
+    close(fd);
+    g_free(phdr);
+    phdr = NULL;
+ fail:
+    close(fd);
+    g_free(data);
+    g_free(phdr);
+}
+
 static int glue(load_elf, SZ)(const char *name, int fd,
                               uint64_t (*translate_fn)(void *, uint64_t),
                               void *translate_opaque,
@@ -293,6 +382,18 @@  static int glue(load_elf, SZ)(const char *name, int fd,
             data = NULL;
         }
     }
+
+    ImageElf *elf;
+    elf = g_malloc0(sizeof(*elf));
+    elf->name = g_strdup(name);
+    elf->fn = translate_fn;
+    elf->opaque = translate_opaque;
+    elf->swab = must_swab;
+    elf->machine = elf_machine;
+    elf->lsb = clear_lsb;
+
+    qemu_register_reset(glue(elf_reset, SZ), elf);
+
     g_free(phdr);
     if (lowaddr)
         *lowaddr = (uint64_t)(elf_sword)low;