aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile.target3
-rw-r--r--hw/an5206.c4
-rw-r--r--hw/arm_boot.c4
-rw-r--r--hw/armv7m.c4
-rw-r--r--hw/axis_dev88.c7
-rw-r--r--hw/dummy_m68k.c4
-rw-r--r--hw/elf_ops.h10
-rw-r--r--hw/etraxfs.c7
-rw-r--r--hw/loader.c14
-rw-r--r--hw/loader.h7
-rw-r--r--hw/mcf5208.c4
-rw-r--r--hw/mips.h4
-rw-r--r--hw/mips_addr.c34
-rw-r--r--hw/mips_malta.c24
-rw-r--r--hw/mips_mipssim.c17
-rw-r--r--hw/mips_r4k.c17
-rw-r--r--hw/multiboot.c4
-rw-r--r--hw/petalogix_s3adsp1800_mmu.c11
-rw-r--r--hw/ppc440_bamboo.c4
-rw-r--r--hw/ppc_newworld.c19
-rw-r--r--hw/ppc_oldworld.c21
-rw-r--r--hw/ppce500_mpc8544ds.c4
-rw-r--r--hw/sun4m.c19
-rw-r--r--hw/sun4u.c14
24 files changed, 159 insertions, 101 deletions
diff --git a/Makefile.target b/Makefile.target
index eb54d7574..ab3c438fa 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -237,7 +237,8 @@ obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
obj-ppc-$(CONFIG_FDT) += device_tree.o
obj-mips-y = mips_r4k.o mips_jazz.o mips_malta.o mips_mipssim.o
-obj-mips-y += mips_timer.o mips_int.o dma.o vga.o serial.o i8254.o i8259.o rc4030.o
+obj-mips-y += mips_addr.o mips_timer.o mips_int.o
+obj-mips-y += dma.o vga.o serial.o i8254.o i8259.o rc4030.o
obj-mips-y += vga-pci.o vga-isa.o vga-isa-mm.o
obj-mips-y += g364fb.o jazz_led.o dp8393x.o
obj-mips-y += ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/piix.o
diff --git a/hw/an5206.c b/hw/an5206.c
index a4b83b0f4..f584d8816 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -68,8 +68,8 @@ static void an5206_init(ram_addr_t ram_size,
exit(1);
}
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
diff --git a/hw/arm_boot.c b/hw/arm_boot.c
index 30a76a56d..df031a595 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -225,8 +225,8 @@ 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, 0, &elf_entry, NULL, NULL,
- big_endian, ELF_MACHINE, 1);
+ kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
+ NULL, NULL, big_endian, ELF_MACHINE, 1);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
diff --git a/hw/armv7m.c b/hw/armv7m.c
index 034323d26..35f75735b 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -215,8 +215,8 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
big_endian = 0;
#endif
- image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL,
- big_endian, ELF_MACHINE, 1);
+ image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
+ NULL, big_endian, ELF_MACHINE, 1);
if (image_size < 0) {
image_size = load_image_targphys(kernel_filename, 0, flash_size);
lowaddr = 0;
diff --git a/hw/axis_dev88.c b/hw/axis_dev88.c
index 1a6664957..5516e4252 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -249,6 +249,11 @@ static void main_cpu_reset(void *opaque)
env->pc = bootstrap_pc;
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0x80000000LL;
+}
+
static
void axisdev88_init (ram_addr_t ram_size,
const char *boot_device,
@@ -345,7 +350,7 @@ void axisdev88_init (ram_addr_t ram_size,
/* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */
- kernel_size = load_elf(kernel_filename, -0x80000000LL,
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
&entry, NULL, &high, 0, ELF_MACHINE, 0);
bootstrap_pc = entry;
if (kernel_size < 0) {
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index ce45a597d..9c9e6ff00 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -43,8 +43,8 @@ static void dummy_m68k_init(ram_addr_t ram_size,
/* Load kernel. */
if (kernel_filename) {
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
diff --git a/hw/elf_ops.h b/hw/elf_ops.h
index 14b9ec044..69c07571b 100644
--- a/hw/elf_ops.h
+++ b/hw/elf_ops.h
@@ -184,7 +184,9 @@ 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, int64_t address_offset,
+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)
@@ -253,7 +255,11 @@ static int glue(load_elf, SZ)(const char *name, int fd, int64_t address_offset,
}
/* address_offset is hack for kernel images that are
linked at the wrong physical address. */
- addr = ph->p_paddr + address_offset;
+ if (translate_fn) {
+ addr = translate_fn(translate_opaque, ph->p_paddr);
+ } else {
+ addr = ph->p_paddr;
+ }
snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
rom_add_blob_fixed(label, data, mem_size, addr);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index 2f7f3695c..7405db487 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -44,6 +44,11 @@ static void main_cpu_reset(void *opaque)
env->pc = bootstrap_pc;
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0x80000000LL;
+}
+
static
void bareetraxfs_init (ram_addr_t ram_size,
const char *boot_device,
@@ -137,7 +142,7 @@ void bareetraxfs_init (ram_addr_t ram_size,
/* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */
- kernel_size = load_elf(kernel_filename, -0x80000000LL,
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
&entry, NULL, &high, 0, ELF_MACHINE, 0);
bootstrap_pc = entry;
if (kernel_size < 0) {
diff --git a/hw/loader.c b/hw/loader.c
index 1448887e5..79a6f9518 100644
--- a/hw/loader.c
+++ b/hw/loader.c
@@ -276,9 +276,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, int64_t address_offset,
- uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
- int big_endian, int elf_machine, int clear_lsb)
+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 fd, data_order, target_data_order, must_swab, ret;
uint8_t e_ident[EI_NIDENT];
@@ -312,11 +312,11 @@ int load_elf(const char *filename, int64_t address_offset,
lseek(fd, 0, SEEK_SET);
if (e_ident[EI_CLASS] == ELFCLASS64) {
- ret = load_elf64(filename, fd, address_offset, must_swab, pentry,
- lowaddr, highaddr, elf_machine, clear_lsb);
+ ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
+ pentry, lowaddr, highaddr, elf_machine, clear_lsb);
} else {
- ret = load_elf32(filename, fd, address_offset, must_swab, pentry,
- lowaddr, highaddr, elf_machine, clear_lsb);
+ ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
+ pentry, lowaddr, highaddr, elf_machine, clear_lsb);
}
close(fd);
diff --git a/hw/loader.h b/hw/loader.h
index 56676e16c..1f82fc5e9 100644
--- a/hw/loader.h
+++ b/hw/loader.h
@@ -5,9 +5,10 @@
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, int64_t address_offset,
- uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
- int big_endian, int elf_machine, int clear_lsb);
+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_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,
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 559861146..5b686c657 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -270,8 +270,8 @@ static void mcf5208evb_init(ram_addr_t ram_size,
exit(1);
}
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
diff --git a/hw/mips.h b/hw/mips.h
index 5fd72bb02..9484ea7d9 100644
--- a/hw/mips.h
+++ b/hw/mips.h
@@ -20,6 +20,10 @@ void mipsnet_init(int base, qemu_irq irq, NICInfo *nd);
/* jazz_led.c */
extern void jazz_led_init(target_phys_addr_t base);
+/* mips_addr.c */
+uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr);
+uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr);
+
/* mips_int.c */
extern void cpu_mips_irq_init_cpu(CPUState *env);
diff --git a/hw/mips_addr.c b/hw/mips_addr.c
new file mode 100644
index 000000000..b96fea031
--- /dev/null
+++ b/hw/mips_addr.c
@@ -0,0 +1,34 @@
+/*
+ * QEMU MIPS address translation support
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "hw.h"
+#include "mips.h"
+
+uint64_t cpu_mips_kseg0_to_phys(void *opaque, uint64_t addr)
+{
+ return addr & 0x7fffffffll;
+}
+
+uint64_t cpu_mips_phys_to_kseg0(void *opaque, uint64_t addr)
+{
+ return addr | ~0x7fffffffll;
+}
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 2d02a1022..91498c262 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -46,15 +46,7 @@
//#define DEBUG_BOARD_INIT
-#ifdef TARGET_MIPS64
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
-#else
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
-#endif
-
-#define ENVP_ADDR (int32_t)0x80002000
-#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
-
+#define ENVP_ADDR 0x80002000l
#define ENVP_NB_ENTRIES 16
#define ENVP_ENTRY_SIZE 256
@@ -681,7 +673,7 @@ static void prom_set(uint32_t* prom_buf, int index, const char *string, ...)
/* Kernel */
static int64_t load_kernel (void)
{
- int64_t kernel_entry, kernel_low, kernel_high;
+ int64_t kernel_entry, kernel_high;
long initrd_size;
ram_addr_t initrd_offset;
int big_endian;
@@ -695,9 +687,9 @@ static int64_t load_kernel (void)
big_endian = 0;
#endif
- if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
- (uint64_t *)&kernel_entry, (uint64_t *)&kernel_low,
- (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1) < 0) {
+ if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
+ (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
+ big_endian, ELF_MACHINE, 1) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
loaderparams.kernel_filename);
exit(1);
@@ -733,8 +725,8 @@ static int64_t load_kernel (void)
prom_set(prom_buf, prom_index++, loaderparams.kernel_filename);
if (initrd_size > 0) {
- prom_set(prom_buf, prom_index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
- PHYS_TO_VIRT(initrd_offset), initrd_size,
+ prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+ cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
loaderparams.kernel_cmdline);
} else {
prom_set(prom_buf, prom_index++, loaderparams.kernel_cmdline);
@@ -747,7 +739,7 @@ static int64_t load_kernel (void)
prom_set(prom_buf, prom_index++, NULL);
rom_add_blob_fixed("prom", prom_buf, prom_size,
- ENVP_ADDR + VIRT_TO_PHYS_ADDEND);
+ cpu_mips_kseg0_to_phys(NULL, ENVP_ADDR));
return kernel_entry;
}
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index aa9011676..9a6f50cd1 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -35,14 +35,6 @@
#include "loader.h"
#include "elf.h"
-#ifdef TARGET_MIPS64
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
-#else
-#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffU)
-#endif
-
-#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
-
static struct _loaderparams {
int ram_size;
const char *kernel_filename;
@@ -57,7 +49,7 @@ typedef struct ResetData {
static int64_t load_kernel(void)
{
- int64_t entry, kernel_low, kernel_high;
+ int64_t entry, kernel_high;
long kernel_size;
long initrd_size;
ram_addr_t initrd_offset;
@@ -69,9 +61,10 @@ static int64_t load_kernel(void)
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
- (uint64_t *)&entry, (uint64_t *)&kernel_low,
- (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1);
+ kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
+ NULL, (uint64_t *)&entry, NULL,
+ (uint64_t *)&kernel_high, big_endian,
+ ELF_MACHINE, 1);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
diff --git a/hw/mips_r4k.c b/hw/mips_r4k.c
index b69d7c3e9..3edc8d592 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -21,10 +21,6 @@
#include "loader.h"
#include "elf.h"
-#define PHYS_TO_VIRT(x) ((x) | ~(target_ulong)0x7fffffff)
-
-#define VIRT_TO_PHYS_ADDEND (-((int64_t)(int32_t)0x80000000))
-
#define MAX_IDE_BUS 2
static const int ide_iobase[2] = { 0x1f0, 0x170 };
@@ -77,7 +73,7 @@ typedef struct ResetData {
static int64_t load_kernel(void)
{
- int64_t entry, kernel_low, kernel_high;
+ int64_t entry, kernel_high;
long kernel_size, initrd_size, params_size;
ram_addr_t initrd_offset;
uint32_t *params_buf;
@@ -88,9 +84,10 @@ static int64_t load_kernel(void)
#else
big_endian = 0;
#endif
- kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND,
- (uint64_t *)&entry, (uint64_t *)&kernel_low,
- (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1);
+ kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
+ NULL, (uint64_t *)&entry, NULL,
+ (uint64_t *)&kernel_high, big_endian,
+ ELF_MACHINE, 1);
if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry;
@@ -132,8 +129,8 @@ static int64_t load_kernel(void)
params_buf[1] = tswap32(0x12345678);
if (initrd_size > 0) {
- snprintf((char *)params_buf + 8, 256, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s",
- PHYS_TO_VIRT((uint32_t)initrd_offset),
+ snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
+ cpu_mips_phys_to_kseg0(NULL, initrd_offset),
initrd_size, loaderparams.kernel_cmdline);
} else {
snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
diff --git a/hw/multiboot.c b/hw/multiboot.c
index a25fbf6f3..a1b665cd4 100644
--- a/hw/multiboot.c
+++ b/hw/multiboot.c
@@ -170,8 +170,8 @@ int load_multiboot(void *fw_cfg,
uint64_t elf_low, elf_high;
int kernel_size;
fclose(f);
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_low, &elf_high,
- 0, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ &elf_low, &elf_high, 0, ELF_MACHINE, 0);
if (kernel_size < 0) {
fprintf(stderr, "Error while loading elf kernel\n");
exit(1);
diff --git a/hw/petalogix_s3adsp1800_mmu.c b/hw/petalogix_s3adsp1800_mmu.c
index 874363630..ea91d65f6 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -104,6 +104,11 @@ static int petalogix_load_device_tree(target_phys_addr_t addr,
return fdt_size;
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0x30000000LL;
+}
+
static void
petalogix_s3adsp1800_init(ram_addr_t ram_size,
const char *boot_device,
@@ -163,13 +168,13 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
uint32_t base32;
/* Boots a kernel elf binary. */
- kernel_size = load_elf(kernel_filename, 0,
+ kernel_size = load_elf(kernel_filename, NULL, NULL,
&entry, &low, &high,
1, ELF_MACHINE, 0);
base32 = entry;
if (base32 == 0xc0000000) {
- kernel_size = load_elf(kernel_filename, -0x30000000LL,
- &entry, NULL, NULL,
+ kernel_size = load_elf(kernel_filename, translate_kernel_address,
+ NULL, &entry, NULL, NULL,
1, ELF_MACHINE, 0);
}
/* Always boot into physical ram. */
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index efe5a77ba..6ca873ee7 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -120,8 +120,8 @@ static void bamboo_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, 0, &elf_entry, &elf_lowaddr,
- NULL, 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
}
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index d4f9013fe..7c100e77a 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -115,6 +115,11 @@ static int fw_cfg_boot_set(void *opaque, const char *boot_device)
return 0;
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
+}
+
/* PowerPC Mac99 hardware initialisation */
static void ppc_core99_init (ram_addr_t ram_size,
const char *boot_device,
@@ -180,7 +185,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
/* Load OpenBIOS (ELF) */
if (filename) {
- bios_size = load_elf(filename, 0, NULL, NULL, NULL, 1, ELF_MACHINE, 0);
+ bios_size = load_elf(filename, NULL, NULL, NULL,
+ NULL, NULL, 1, ELF_MACHINE, 0);
qemu_free(filename);
} else {
@@ -232,15 +238,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
#endif
kernel_base = KERNEL_LOAD_ADDR;
- /* Now we can load the kernel. The first step tries to load the kernel
- supposing PhysAddr = 0x00000000. If that was wrong the kernel is
- loaded again, the new PhysAddr being computed from lowaddr. */
- kernel_size = load_elf(kernel_filename, kernel_base, NULL, &lowaddr, NULL,
- 1, ELF_MACHINE, 0);
- if (kernel_size > 0 && lowaddr != KERNEL_LOAD_ADDR) {
- kernel_size = load_elf(kernel_filename, (2 * kernel_base) - lowaddr,
- NULL, NULL, NULL, 1, ELF_MACHINE, 0);
- }
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed,
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 93c95ba65..bdc5bcd92 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -122,6 +122,12 @@ static int fw_cfg_boot_set(void *opaque, const char *boot_device)
return 0;
}
+
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
+}
+
static void ppc_heathrow_init (ram_addr_t ram_size,
const char *boot_device,
const char *kernel_filename,
@@ -185,8 +191,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
/* Load OpenBIOS (ELF) */
if (filename) {
- bios_size = load_elf(filename, 0, NULL, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
+ 1, ELF_MACHINE, 0);
qemu_free(filename);
} else {
bios_size = -1;
@@ -236,15 +242,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
bswap_needed = 0;
#endif
kernel_base = KERNEL_LOAD_ADDR;
- /* Now we can load the kernel. The first step tries to load the kernel
- supposing PhysAddr = 0x00000000. If that was wrong the kernel is
- loaded again, the new PhysAddr being computed from lowaddr. */
- kernel_size = load_elf(kernel_filename, kernel_base, NULL, &lowaddr, NULL,
- 1, ELF_MACHINE, 0);
- if (kernel_size > 0 && lowaddr != KERNEL_LOAD_ADDR) {
- kernel_size = load_elf(kernel_filename, (2 * kernel_base) - lowaddr,
- NULL, NULL, NULL, 1, ELF_MACHINE, 0);
- }
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed,
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 90b4c5669..a83dba4a1 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -231,8 +231,8 @@ 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, 0, &elf_entry, &elf_lowaddr,
- NULL, 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
+ &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
}
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 7e2628203..90e661d5c 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -292,6 +292,11 @@ static void cpu_halt_signal(void *opaque, int irq, int level)
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT);
}
+static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
+{
+ return addr - 0xf0000000ULL;
+}
+
static unsigned long sun4m_load_kernel(const char *kernel_filename,
const char *initrd_filename,
ram_addr_t RAM_size)
@@ -312,8 +317,8 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
#else
bswap_needed = 0;
#endif
- kernel_size = load_elf(kernel_filename, -0xf0000000ULL, NULL, NULL,
- NULL, 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
+ NULL, NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
@@ -636,6 +641,12 @@ static void afx_register_devices(void)
device_init(afx_register_devices);
/* Boot PROM (OpenBIOS) */
+static uint64_t translate_prom_address(void *opaque, uint64_t addr)
+{
+ target_phys_addr_t *base_addr = (target_phys_addr_t *)opaque;
+ return addr + *base_addr - PROM_VADDR;
+}
+
static void prom_init(target_phys_addr_t addr, const char *bios_name)
{
DeviceState *dev;
@@ -655,8 +666,8 @@ 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, addr - PROM_VADDR, NULL, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ ret = load_elf(filename, translate_prom_address, &addr, NULL,
+ NULL, NULL, 1, ELF_MACHINE, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
}
diff --git a/hw/sun4u.c b/hw/sun4u.c
index f339df38d..666383607 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -189,8 +189,8 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
#else
bswap_needed = 0;
#endif
- kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
+ NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
@@ -580,6 +580,12 @@ static void pci_ebus_register(void)
device_init(pci_ebus_register);
+static uint64_t translate_prom_address(void *opaque, uint64_t addr)
+{
+ target_phys_addr_t *base_addr = (target_phys_addr_t *)opaque;
+ return addr + *base_addr - PROM_VADDR;
+}
+
/* Boot PROM (OpenBIOS) */
static void prom_init(target_phys_addr_t addr, const char *bios_name)
{
@@ -600,8 +606,8 @@ 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, addr - PROM_VADDR, NULL, NULL, NULL,
- 1, ELF_MACHINE, 0);
+ ret = load_elf(filename, translate_prom_address, &addr,
+ NULL, NULL, NULL, 1, ELF_MACHINE, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
}