@@ -68,7 +68,7 @@ static void an5206_init(ram_addr_t ram_size,
exit(1);
}
- kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
@@ -226,7 +226,7 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
#endif
/* Assume that raw images are linux kernels, and ELF images are not. */
- kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(info->kernel_filename, NULL, &elf_entry,
NULL, NULL, big_endian, ELF_MACHINE, 1);
entry = elf_entry;
if (kernel_size < 0) {
@@ -222,7 +222,7 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
big_endian = 0;
#endif
- image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
+ image_size = load_elf(kernel_filename, NULL, &entry, &lowaddr,
NULL, big_endian, ELF_MACHINE, 1);
if (image_size < 0) {
image_size = load_image_targphys(kernel_filename, 0, flash_size);
@@ -66,11 +66,13 @@ void cris_load_image(CPUState *env, struct cris_load_info *li)
uint64_t entry, high;
int kcmdline_len;
int image_size;
+ ElfHandlers handlers = elf_default_handlers;
env->load_info = li;
/* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */
- image_size = load_elf(li->image_filename, translate_kernel_address, NULL,
+ handlers.translate_fn = translate_kernel_address;
+ image_size = load_elf(li->image_filename, &handlers,
&entry, NULL, &high, 0, ELF_MACHINE, 0);
li->entry = entry;
if (image_size < 0) {
@@ -43,7 +43,7 @@ static void dummy_m68k_init(ram_addr_t ram_size,
/* Load kernel. */
if (kernel_filename) {
- kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
@@ -190,8 +190,7 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
}
static int glue(load_elf, SZ)(const char *name, int fd,
- uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque,
+ ElfHandlers *handlers,
int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, int clear_lsb)
@@ -265,11 +264,8 @@ static int glue(load_elf, SZ)(const char *name, int fd,
}
/* address_offset is hack for kernel images that are
linked at the wrong physical address. */
- if (translate_fn) {
- addr = translate_fn(translate_opaque, ph->p_paddr);
- } else {
- addr = ph->p_paddr;
- }
+ addr = handlers->translate_fn(handlers->translate_opaque,
+ ph->p_paddr);
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
rom_add_blob_fixed(label, data, mem_size, addr);
@@ -229,6 +229,17 @@ int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
/* ELF loader */
+static uint64_t elf_default_translate(void *opaque, uint64_t addr)
+{
+ return addr;
+}
+
+ElfHandlers elf_default_handlers = {
+ .translate_fn = elf_default_translate,
+ .translate_opaque = NULL,
+};
+
+
static void *load_at(int fd, int offset, int size)
{
void *ptr;
@@ -276,9 +287,9 @@ static void *load_at(int fd, int offset, int size)
#include "elf_ops.h"
/* return < 0 if error, otherwise the number of bytes loaded in memory */
-int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
- uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
+int load_elf(const char *filename, ElfHandlers *handlers,
+ uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
+ int big_endian, int elf_machine, int clear_lsb)
{
int fd, data_order, target_data_order, must_swab, ret;
uint8_t e_ident[EI_NIDENT];
@@ -310,13 +321,17 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
if (target_data_order != e_ident[EI_DATA])
return -1;
+ if (!handlers) {
+ handlers = &elf_default_handlers;
+ }
+
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);
+ ret = load_elf64(filename, fd, handlers, must_swab, pentry, lowaddr,
+ highaddr, elf_machine, clear_lsb);
} else {
- ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
- pentry, lowaddr, highaddr, elf_machine, clear_lsb);
+ ret = load_elf32(filename, fd, handlers, must_swab, pentry, lowaddr,
+ highaddr, elf_machine, clear_lsb);
}
close(fd);
@@ -5,10 +5,18 @@
int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */
int load_image_targphys(const char *filename, target_phys_addr_t, int max_sz);
-int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
- void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
- uint64_t *highaddr, int big_endian, int elf_machine,
- int clear_lsb);
+
+typedef struct ElfHandlers {
+ uint64_t (*translate_fn)(void *opaque, uint64_t address);
+ void *translate_opaque;
+} ElfHandlers;
+
+extern ElfHandlers elf_default_handlers;
+
+int load_elf(const char *filename, ElfHandlers *handlers,
+ uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
+ int big_endian, int elf_machine, int clear_lsb);
+
int load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
int bswap_needed, target_phys_addr_t target_page_size);
int load_uimage(const char *filename, target_phys_addr_t *ep,
@@ -270,7 +270,7 @@ static void mcf5208evb_init(ram_addr_t ram_size,
exit(1);
}
- kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
@@ -106,8 +106,10 @@ static int64_t load_kernel (CPUState *env)
ram_addr_t initrd_offset;
uint32_t *prom_buf;
long prom_size;
+ ElfHandlers handlers = elf_default_handlers;
- if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+ handlers.translate_fn = cpu_mips_kseg0_to_phys;
+ if (load_elf(loaderparams.kernel_filename, &handlers,
(uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
(uint64_t *)&kernel_high, 0, ELF_MACHINE, 1) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
@@ -686,6 +686,7 @@ static int64_t load_kernel (void)
uint32_t *prom_buf;
long prom_size;
int prom_index = 0;
+ ElfHandlers handlers = elf_default_handlers;
#ifdef TARGET_WORDS_BIGENDIAN
big_endian = 1;
@@ -693,7 +694,8 @@ static int64_t load_kernel (void)
big_endian = 0;
#endif
- if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+ handlers.translate_fn = cpu_mips_kseg0_to_phys;
+ if (load_elf(loaderparams.kernel_filename, &handlers,
(uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
big_endian, ELF_MACHINE, 1) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
@@ -55,6 +55,7 @@ static int64_t load_kernel(void)
long initrd_size;
ram_addr_t initrd_offset;
int big_endian;
+ ElfHandlers handlers = elf_default_handlers;
#ifdef TARGET_WORDS_BIGENDIAN
big_endian = 1;
@@ -62,8 +63,9 @@ static int64_t load_kernel(void)
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
- NULL, (uint64_t *)&entry, NULL,
+ handlers.translate_fn = cpu_mips_kseg0_to_phys;
+ kernel_size = load_elf(loaderparams.kernel_filename, &handlers,
+ (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian,
ELF_MACHINE, 1);
if (kernel_size >= 0) {
@@ -81,14 +81,16 @@ static int64_t load_kernel(void)
ram_addr_t initrd_offset;
uint32_t *params_buf;
int big_endian;
+ ElfHandlers handlers = elf_default_handlers;
#ifdef TARGET_WORDS_BIGENDIAN
big_endian = 1;
#else
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
- NULL, (uint64_t *)&entry, NULL,
+ handlers.translate_fn = cpu_mips_kseg0_to_phys;
+ kernel_size = load_elf(loaderparams.kernel_filename, &handlers,
+ (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian,
ELF_MACHINE, 1);
if (kernel_size >= 0) {
@@ -171,7 +171,7 @@ int load_multiboot(void *fw_cfg,
uint64_t elf_low, elf_high;
int kernel_size;
fclose(f);
- kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
&elf_low, &elf_high, 0, ELF_MACHINE, 0);
if (kernel_size < 0) {
fprintf(stderr, "Error while loading elf kernel\n");
@@ -167,15 +167,17 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
if (kernel_filename) {
uint64_t entry, low, high;
uint32_t base32;
+ ElfHandlers handlers = elf_default_handlers;
/* Boots a kernel elf binary. */
- kernel_size = load_elf(kernel_filename, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL,
&entry, &low, &high,
1, ELF_MACHINE, 0);
base32 = entry;
if (base32 == 0xc0000000) {
- kernel_size = load_elf(kernel_filename, translate_kernel_address,
- NULL, &entry, NULL, NULL,
+ handlers.translate_fn = translate_kernel_address;
+ kernel_size = load_elf(kernel_filename, &handlers,
+ &entry, NULL, NULL,
1, ELF_MACHINE, 0);
}
/* Always boot into physical ram. */
@@ -123,7 +123,7 @@ static void bamboo_init(ram_addr_t ram_size,
if (kernel_filename) {
success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
if (success < 0) {
- success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ success = load_elf(kernel_filename, NULL, &elf_entry,
&elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
@@ -181,7 +181,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
/* Load OpenBIOS (ELF) */
if (filename) {
- bios_size = load_elf(filename, NULL, NULL, NULL,
+ bios_size = load_elf(filename, NULL, NULL,
NULL, NULL, 1, ELF_MACHINE, 0);
qemu_free(filename);
@@ -196,6 +196,7 @@ static void ppc_core99_init (ram_addr_t ram_size,
if (linux_boot) {
uint64_t lowaddr = 0;
int bswap_needed;
+ ElfHandlers handlers = elf_default_handlers;
#ifdef BSWAP_NEEDED
bswap_needed = 1;
@@ -204,7 +205,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
#endif
kernel_base = KERNEL_LOAD_ADDR;
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ handlers.translate_fn = translate_kernel_address;
+ kernel_size = load_elf(kernel_filename, &handlers,
NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
@@ -119,7 +119,7 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
/* Load OpenBIOS (ELF) */
if (filename) {
- bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
+ bios_size = load_elf(filename, NULL, NULL, NULL, NULL,
1, ELF_MACHINE, 0);
qemu_free(filename);
} else {
@@ -133,14 +133,16 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
if (linux_boot) {
uint64_t lowaddr = 0;
int bswap_needed;
+ ElfHandlers handlers = elf_default_handlers;
#ifdef BSWAP_NEEDED
bswap_needed = 1;
#else
bswap_needed = 0;
#endif
+ handlers.translate_fn = translate_kernel_address;
kernel_base = KERNEL_LOAD_ADDR;
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ kernel_size = load_elf(kernel_filename, &handlers,
NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
@@ -233,7 +233,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
if (kernel_filename) {
kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
if (kernel_size < 0) {
- kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ kernel_size = load_elf(kernel_filename, NULL, &elf_entry,
&elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
@@ -322,13 +322,15 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
kernel_size = 0;
if (linux_boot) {
int bswap_needed;
+ ElfHandlers handlers = elf_default_handlers;
#ifdef BSWAP_NEEDED
bswap_needed = 1;
#else
bswap_needed = 0;
#endif
- kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ handlers.translate_fn = translate_kernel_address;
+ kernel_size = load_elf(kernel_filename, &handlers,
NULL, NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
@@ -677,7 +679,11 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- ret = load_elf(filename, translate_prom_address, &addr, NULL,
+ ElfHandlers handlers = elf_default_handlers;
+
+ handlers.translate_fn = translate_prom_address;
+ handlers.translate_opaque = &addr;
+ ret = load_elf(filename, &handlers, NULL,
NULL, NULL, 1, ELF_MACHINE, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
@@ -194,7 +194,7 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
#else
bswap_needed = 0;
#endif
- kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL, NULL,
NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
@@ -597,6 +597,7 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
SysBusDevice *s;
char *filename;
int ret;
+ ElfHandlers handlers = elf_default_handlers;
dev = qdev_create(NULL, "openprom");
qdev_init_nofail(dev);
@@ -610,7 +611,9 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name)
}
filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) {
- ret = load_elf(filename, translate_prom_address, &addr,
+ handlers.translate_fn = translate_prom_address;
+ handlers.translate_opaque = &addr;
+ ret = load_elf(filename, &handlers,
NULL, NULL, NULL, 1, ELF_MACHINE, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
@@ -238,7 +238,7 @@ static void virtex_init(ram_addr_t ram_size,
target_phys_addr_t boot_offset;
/* Boots a kernel elf binary. */
- kernel_size = load_elf(kernel_filename, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, NULL,
&entry, &low, &high, 1, ELF_MACHINE, 0);
boot_info.bootstrap_pc = entry & 0x00ffffff;
The elf loader takes a direct parameter for a callback that enabled users of load_elf to translate addresses on the fly. While this is nice to have, it's really unflexible. We need to add some more callbacks to elf and listing every single one in the function call just doesn't scale. So let's move that one over to a struct that can easily be extended. This way we can add more callbacks later on and don't have to worry about compatibility. Signed-off-by: Alexander Graf <agraf@suse.de> --- hw/an5206.c | 2 +- hw/arm_boot.c | 2 +- hw/armv7m.c | 2 +- hw/cris-boot.c | 4 +++- hw/dummy_m68k.c | 2 +- hw/elf_ops.h | 10 +++------- hw/loader.c | 29 ++++++++++++++++++++++------- hw/loader.h | 16 ++++++++++++---- hw/mcf5208.c | 2 +- hw/mips_fulong2e.c | 4 +++- hw/mips_malta.c | 4 +++- hw/mips_mipssim.c | 6 ++++-- hw/mips_r4k.c | 6 ++++-- hw/multiboot.c | 2 +- hw/petalogix_s3adsp1800_mmu.c | 8 +++++--- hw/ppc440_bamboo.c | 2 +- hw/ppc_newworld.c | 6 ++++-- hw/ppc_oldworld.c | 6 ++++-- hw/ppce500_mpc8544ds.c | 2 +- hw/sun4m.c | 10 ++++++++-- hw/sun4u.c | 7 +++++-- hw/virtex_ml507.c | 2 +- 22 files changed, 89 insertions(+), 45 deletions(-)