[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Qemu-ppc] [RFC PATCH v4 3/3] use elf_reset to reload elf image
From: |
Olivia Yin |
Subject: |
[Qemu-ppc] [RFC PATCH v4 3/3] use elf_reset to reload elf image |
Date: |
Wed, 14 Nov 2012 21:28:52 +0800 |
Signed-off-by: Olivia Yin <address@hidden>
---
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))
+ 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
Re: [Qemu-ppc] [Qemu-devel] [RFC PATCH v4 1/3] use image_file_reset to reload initrd image, Stuart Yoder, 2012/11/15
Re: [Qemu-ppc] [RFC PATCH v4 0/3] reload kernel/initrd/elf images when reset, Yin Olivia-R63875, 2012/11/15