Signed-off-by: Olivia Yin <hong-hua....@freescale.com> --- elf.h | 10 ++++++++++ hw/elf_ops.h | 44 +++++++++++++++++++++++++++++++++++++++----- hw/loader.c | 11 +++++++++++ 3 files changed, 60 insertions(+), 5 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..3ff8ffd 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,28 @@ static int glue(load_elf, SZ)(const char *name, int fd, g_free(phdr); return -1; } + +static void glue(elf_reset, SZ)(void *opaque) +{ + ImageElf *elf = opaque; + int fd; + + fd = open(elf->name, O_RDONLY | O_BINARY); + glue(elf_phy_loader, SZ)(elf->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 151ef20..10e5726 100644 --- a/hw/loader.c +++ b/hw/loader.c @@ -342,13 +342,24 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t), goto fail; } + ImageElf *elf; + elf = g_malloc0(sizeof(*elf)); + elf->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); -- 1.7.1