load_elf: replace the address addend by a translation function
authorAurelien Jarno <aurelien@aurel32.net>
Sun, 14 Mar 2010 20:20:59 +0000 (21:20 +0100)
committerAurelien Jarno <aurelien@aurel32.net>
Tue, 16 Mar 2010 07:38:05 +0000 (08:38 +0100)
A few machines need to translate the ELF header addresses into physical
addresses. Currently the only possibility is to add a value to the
addresses.

This patch replaces the addend argument by and a translation function
and an opaque passed to the function. A NULL function does not translate
the address.

The patch also convert all machines that have an addend, simplify the
PowerPC kernel loading and fix the MIPS kernel loading using this new
feature. Other machines may benefit from this feature.

Signed-off-by: Aurelien Jarno <aurelien@aurel32.net>
24 files changed:
Makefile.target
hw/an5206.c
hw/arm_boot.c
hw/armv7m.c
hw/axis_dev88.c
hw/dummy_m68k.c
hw/elf_ops.h
hw/etraxfs.c
hw/loader.c
hw/loader.h
hw/mcf5208.c
hw/mips.h
hw/mips_addr.c [new file with mode: 0644]
hw/mips_malta.c
hw/mips_mipssim.c
hw/mips_r4k.c
hw/multiboot.c
hw/petalogix_s3adsp1800_mmu.c
hw/ppc440_bamboo.c
hw/ppc_newworld.c
hw/ppc_oldworld.c
hw/ppce500_mpc8544ds.c
hw/sun4m.c
hw/sun4u.c

index eb54d7574f3528078670ecbd1eade3a14c4370e2..ab3c438fad4ad5e1f4f0e83dac27108e35750b62 100644 (file)
@@ -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
index a4b83b0f44571cdd4287d6e21916e91c78dbead7..f584d8816fd4721ded5e37d5009a38aeffce8f52 100644 (file)
@@ -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);
index 30a76a56d14a87729b2a499c44335c2ee8fc2b06..df031a5952c5941a626fdb667bef670ebfd25b79 100644 (file)
@@ -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,
index 034323d26e8de90c2978f74fb9dd229c5fd026ed..35f75735b91d755d03b6f160b8172755ba961381 100644 (file)
@@ -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;
index 1a6664957a098f6977880e4f035f3b5435d90236..5516e4252869abd3412caf35629019624dad7921 100644 (file)
@@ -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) {
index ce45a597db38243d8dffbe334d679de5dddda88b..9c9e6ff00938333483c153a6ba700cf786a5b043 100644 (file)
@@ -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);
index 14b9ec04446268c92020b94c5ce12fd340a1a897..69c07571b6077f829410adf41a7a2d9194330434 100644 (file)
@@ -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);
index 2f7f3695c5ee4f8fa777e0ba4dfdb1c42ffc60e3..7405db487e3395ddab52dc91eb1e96e3126fa15a 100644 (file)
@@ -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) {
index 1448887e5e0d8b33c19620d384fbf7b8bdec27ea..79a6f95186ed2dd597c465eff2b5e201340ead0d 100644 (file)
@@ -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);
index 56676e16c7a87d89fd4f29eee2f7a6afcf24fbff..1f82fc5e982b87c6747a8e502b37342e029ec037 100644 (file)
@@ -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,
index 559861146272e21669502434748f2eddbd398fb3..5b686c657a62ffe3b5f5c3b42638f2f249504bcd 100644 (file)
@@ -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);
index 5fd72bb0260d434af9244b5057ec83fdec45c69c..9484ea7d9610b31a63ed69f3418c0365f56e527d 100644 (file)
--- 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 (file)
index 0000000..b96fea0
--- /dev/null
@@ -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;
+}
index 2d02a10227809e37aac05317589d85f6d0105806..91498c262cc82415b5307464623f4997fe1f0628 100644 (file)
 
 //#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;
 }
index aa90116760899438d913dceeecefdf891c23daa4..9a6f50cd15152f2ac714e2836a6f6cc96a77fb62 100644 (file)
 #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;
index b69d7c3e99af297670599b2c77cd5df2b08c7fe1..3edc8d5921a9df6df2050aa631d647e4128863cf 100644 (file)
 #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);
index a25fbf6f358988e0ba1b6b7a9cc5e9c1e5fbfc8d..a1b665cd41285b8e23859d1c1eeaa09e92640182 100644 (file)
@@ -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);
index 874363630295e40553c1a11005b363e13646b4cb..ea91d65f622b9cfc7cc25719759fc037244d7c40 100644 (file)
@@ -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.  */
index efe5a77bab1651ac1d98c364c2b61996f60afd98..6ca873ee7eeb179eccaccb786800fb1da172fc1f 100644 (file)
@@ -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;
         }
index d4f9013fe521e73fe39c5cead400117e9f64f997..7c100e77a4848c89f96acc163329d21a8d28c2dd 100644 (file)
@@ -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,
index 93c95ba6593d01998551625e1b01dc7ca6afd07c..bdc5bcd92ef93dbc4ac35f87f4171fc2c4b067de 100644 (file)
@@ -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,
index 90b4c56698943cc4251c3c9e3d8598e064862075..a83dba4a18c2feca9f1e43ec56c5b8116de15e4f 100644 (file)
@@ -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;
         }
index 7e262820349d84c4143b33d16f63157fdb50b4be..90e661d5c269355d1344003f28cbf628093269c1 100644 (file)
@@ -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);
         }
index f339df38d191fe38aa940d6c4805ec4e145a8222..666383607f3d16592473ec1ebf87e5e56eceebd8 100644 (file)
@@ -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);
         }