summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMax Filippov <jcmvbkbc@gmail.com>2014-10-19 07:42:22 +0400
committerMichael Roth <mdroth@linux.vnet.ibm.com>2015-01-06 18:39:10 -0600
commitc448fb76516c2397e9d6f65ef8aa13c2236e56eb (patch)
tree86b88d46043aedfb0d0a31d3ef0a7ff01e5633a9
parent8239a583c15df4bf929429e7e3a856accc643c4e (diff)
downloadqemu-c448fb76516c2397e9d6f65ef8aa13c2236e56eb.tar.gz
hw/core/loader: implement address translation in uimage loader
Such address translation is needed when load address recorded in uImage is a virtual address. When the actual load address is requested, return untranslated address: user that needs the translated address can always apply translation function to it and those that need it untranslated don't need to do the inverse translation. Add translation function pointer and its parameter to uimage_load prototype. Update all existing users. No user-visible functional changes. Cc: qemu-stable@nongnu.org Signed-off-by: Max Filippov <jcmvbkbc@gmail.com> Reviewed-by: Alexander Graf <agraf@suse.de> (cherry picked from commit 25bda50a0c7241dcb247483af2b7f961632020cc) Signed-off-by: Michael Roth <mdroth@linux.vnet.ibm.com>
-rw-r--r--hw/arm/boot.c2
-rw-r--r--hw/core/loader.c17
-rw-r--r--hw/m68k/an5206.c3
-rw-r--r--hw/m68k/dummy_m68k.c3
-rw-r--r--hw/m68k/mcf5208.c3
-rw-r--r--hw/microblaze/boot.c3
-rw-r--r--hw/openrisc/openrisc_sim.c2
-rw-r--r--hw/ppc/e500.c3
-rw-r--r--hw/ppc/ppc440_bamboo.c3
-rw-r--r--hw/xtensa/xtfpga.c3
-rw-r--r--include/hw/loader.h4
11 files changed, 32 insertions, 14 deletions
diff --git a/hw/arm/boot.c b/hw/arm/boot.c
index 3d1f4a255b..50b6c5c0ee 100644
--- a/hw/arm/boot.c
+++ b/hw/arm/boot.c
@@ -508,7 +508,7 @@ void arm_load_kernel(ARMCPU *cpu, struct arm_boot_info *info)
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
- &is_linux);
+ &is_linux, NULL, NULL);
}
if (kernel_size < 0) {
entry = info->loader_start + kernel_load_offset;
diff --git a/hw/core/loader.c b/hw/core/loader.c
index 2bf6b8ff85..8b84c12dd1 100644
--- a/hw/core/loader.c
+++ b/hw/core/loader.c
@@ -456,7 +456,9 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
/* Load a U-Boot image. */
static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
- int *is_linux, uint8_t image_type)
+ int *is_linux, uint8_t image_type,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque)
{
int fd;
int size;
@@ -490,6 +492,9 @@ static int load_uboot_image(const char *filename, hwaddr *ep, hwaddr *loadaddr,
switch (hdr->ih_type) {
case IH_TYPE_KERNEL:
address = hdr->ih_load;
+ if (translate_fn) {
+ address = translate_fn(translate_opaque, address);
+ }
if (loadaddr) {
*loadaddr = hdr->ih_load;
}
@@ -566,15 +571,19 @@ out:
}
int load_uimage(const char *filename, hwaddr *ep, hwaddr *loadaddr,
- int *is_linux)
+ int *is_linux,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque)
{
- return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL);
+ return load_uboot_image(filename, ep, loadaddr, is_linux, IH_TYPE_KERNEL,
+ translate_fn, translate_opaque);
}
/* Load a ramdisk. */
int load_ramdisk(const char *filename, hwaddr addr, uint64_t max_sz)
{
- return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK);
+ return load_uboot_image(filename, NULL, &addr, NULL, IH_TYPE_RAMDISK,
+ NULL, NULL);
}
/*
diff --git a/hw/m68k/an5206.c b/hw/m68k/an5206.c
index 684496a946..388420edb7 100644
--- a/hw/m68k/an5206.c
+++ b/hw/m68k/an5206.c
@@ -74,7 +74,8 @@ static void an5206_init(MachineState *machine)
NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
- kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+ kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
+ NULL, NULL);
}
if (kernel_size < 0) {
kernel_size = load_image_targphys(kernel_filename, KERNEL_LOAD_ADDR,
diff --git a/hw/m68k/dummy_m68k.c b/hw/m68k/dummy_m68k.c
index 6db1b7164e..fb9ca0ed3a 100644
--- a/hw/m68k/dummy_m68k.c
+++ b/hw/m68k/dummy_m68k.c
@@ -50,7 +50,8 @@ static void dummy_m68k_init(MachineState *machine)
NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
- kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+ kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
+ NULL, NULL);
}
if (kernel_size < 0) {
kernel_size = load_image_targphys(kernel_filename,
diff --git a/hw/m68k/mcf5208.c b/hw/m68k/mcf5208.c
index 2ef617f2b7..07683dbf21 100644
--- a/hw/m68k/mcf5208.c
+++ b/hw/m68k/mcf5208.c
@@ -279,7 +279,8 @@ static void mcf5208evb_init(MachineState *machine)
NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
- kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
+ kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL,
+ NULL, NULL);
}
if (kernel_size < 0) {
kernel_size = load_image_targphys(kernel_filename, 0x40000000,
diff --git a/hw/microblaze/boot.c b/hw/microblaze/boot.c
index 6bf36d046f..a2843cdf99 100644
--- a/hw/microblaze/boot.c
+++ b/hw/microblaze/boot.c
@@ -154,7 +154,8 @@ void microblaze_load_kernel(MicroBlazeCPU *cpu, hwaddr ddr_base,
if (kernel_size < 0) {
hwaddr uentry, loadaddr;
- kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0);
+ kernel_size = load_uimage(kernel_filename, &uentry, &loadaddr, 0,
+ NULL, NULL);
boot_info.bootstrap_pc = uentry;
high = (loadaddr + kernel_size + 3) & ~3;
}
diff --git a/hw/openrisc/openrisc_sim.c b/hw/openrisc/openrisc_sim.c
index b2b4f9b860..123cf4d5e7 100644
--- a/hw/openrisc/openrisc_sim.c
+++ b/hw/openrisc/openrisc_sim.c
@@ -72,7 +72,7 @@ static void cpu_openrisc_load_kernel(ram_addr_t ram_size,
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename,
- &entry, NULL, NULL);
+ &entry, NULL, NULL, NULL, NULL);
}
if (kernel_size < 0) {
kernel_size = load_image_targphys(kernel_filename,
diff --git a/hw/ppc/e500.c b/hw/ppc/e500.c
index 1a5b30d3ce..c268b91252 100644
--- a/hw/ppc/e500.c
+++ b/hw/ppc/e500.c
@@ -830,7 +830,8 @@ void ppce500_init(MachineState *machine, PPCE500Params *params)
* Hrm. No ELF image? Try a uImage, maybe someone is giving us an
* ePAPR compliant kernel
*/
- kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL);
+ kernel_size = load_uimage(filename, &bios_entry, &loadaddr, NULL,
+ NULL, NULL);
if (kernel_size < 0) {
fprintf(stderr, "qemu: could not load firmware '%s'\n", filename);
exit(1);
diff --git a/hw/ppc/ppc440_bamboo.c b/hw/ppc/ppc440_bamboo.c
index 81a06d310d..778970aa9b 100644
--- a/hw/ppc/ppc440_bamboo.c
+++ b/hw/ppc/ppc440_bamboo.c
@@ -253,7 +253,8 @@ static void bamboo_init(MachineState *machine)
/* Load kernel. */
if (kernel_filename) {
- success = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
+ success = load_uimage(kernel_filename, &entry, &loadaddr, NULL,
+ NULL, NULL);
if (success < 0) {
success = load_elf(kernel_filename, NULL, NULL, &elf_entry,
&elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
diff --git a/hw/xtensa/xtfpga.c b/hw/xtensa/xtfpga.c
index a2dff5a13e..937d01edfd 100644
--- a/hw/xtensa/xtfpga.c
+++ b/hw/xtensa/xtfpga.c
@@ -325,7 +325,8 @@ static void lx_init(const LxBoardDesc *board, MachineState *machine)
} else {
hwaddr ep;
int is_linux;
- success = load_uimage(kernel_filename, &ep, NULL, &is_linux);
+ success = load_uimage(kernel_filename, &ep, NULL, &is_linux,
+ NULL, NULL);
if (success > 0 && is_linux) {
entry_point = ep;
} else {
diff --git a/include/hw/loader.h b/include/hw/loader.h
index 796cbf9b39..11b6b5ac7c 100644
--- a/include/hw/loader.h
+++ b/include/hw/loader.h
@@ -28,7 +28,9 @@ int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
int load_aout(const char *filename, hwaddr addr, int max_sz,
int bswap_needed, hwaddr target_page_size);
int load_uimage(const char *filename, hwaddr *ep,
- hwaddr *loadaddr, int *is_linux);
+ hwaddr *loadaddr, int *is_linux,
+ uint64_t (*translate_fn)(void *, uint64_t),
+ void *translate_opaque);
/**
* load_ramdisk: