Message ID | 1352899732-1197-4-git-send-email-hong-hua.yin@freescale.com |
---|---|
State | New |
Headers | show |
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 > > >
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;
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(-)