提交 409dbce5 编写于 作者: A Aurelien Jarno

load_elf: replace the address addend by a translation function

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: NAurelien Jarno <aurelien@aurel32.net>
上级 cb66ffcf
...@@ -237,7 +237,8 @@ obj-ppc-$(CONFIG_KVM) += kvm_ppc.o ...@@ -237,7 +237,8 @@ obj-ppc-$(CONFIG_KVM) += kvm_ppc.o
obj-ppc-$(CONFIG_FDT) += device_tree.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_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 += vga-pci.o vga-isa.o vga-isa-mm.o
obj-mips-y += g364fb.o jazz_led.o dp8393x.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 obj-mips-y += ide/core.o ide/qdev.o ide/isa.o ide/pci.o ide/piix.o
......
...@@ -68,8 +68,8 @@ static void an5206_init(ram_addr_t ram_size, ...@@ -68,8 +68,8 @@ static void an5206_init(ram_addr_t ram_size,
exit(1); exit(1);
} }
kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
1, ELF_MACHINE, 0); NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry; entry = elf_entry;
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL); kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
......
...@@ -225,8 +225,8 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info) ...@@ -225,8 +225,8 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
#endif #endif
/* Assume that raw images are linux kernels, and ELF images are not. */ /* Assume that raw images are linux kernels, and ELF images are not. */
kernel_size = load_elf(info->kernel_filename, 0, &elf_entry, NULL, NULL, kernel_size = load_elf(info->kernel_filename, NULL, NULL, &elf_entry,
big_endian, ELF_MACHINE, 1); NULL, NULL, big_endian, ELF_MACHINE, 1);
entry = elf_entry; entry = elf_entry;
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_uimage(info->kernel_filename, &entry, NULL, kernel_size = load_uimage(info->kernel_filename, &entry, NULL,
......
...@@ -215,8 +215,8 @@ qemu_irq *armv7m_init(int flash_size, int sram_size, ...@@ -215,8 +215,8 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
big_endian = 0; big_endian = 0;
#endif #endif
image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL, image_size = load_elf(kernel_filename, NULL, NULL, &entry, &lowaddr,
big_endian, ELF_MACHINE, 1); NULL, big_endian, ELF_MACHINE, 1);
if (image_size < 0) { if (image_size < 0) {
image_size = load_image_targphys(kernel_filename, 0, flash_size); image_size = load_image_targphys(kernel_filename, 0, flash_size);
lowaddr = 0; lowaddr = 0;
......
...@@ -249,6 +249,11 @@ static void main_cpu_reset(void *opaque) ...@@ -249,6 +249,11 @@ static void main_cpu_reset(void *opaque)
env->pc = bootstrap_pc; env->pc = bootstrap_pc;
} }
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
{
return addr - 0x80000000LL;
}
static static
void axisdev88_init (ram_addr_t ram_size, void axisdev88_init (ram_addr_t ram_size,
const char *boot_device, const char *boot_device,
...@@ -345,7 +350,7 @@ void axisdev88_init (ram_addr_t ram_size, ...@@ -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 /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */ 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); &entry, NULL, &high, 0, ELF_MACHINE, 0);
bootstrap_pc = entry; bootstrap_pc = entry;
if (kernel_size < 0) { if (kernel_size < 0) {
......
...@@ -43,8 +43,8 @@ static void dummy_m68k_init(ram_addr_t ram_size, ...@@ -43,8 +43,8 @@ static void dummy_m68k_init(ram_addr_t ram_size,
/* Load kernel. */ /* Load kernel. */
if (kernel_filename) { if (kernel_filename) {
kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
1, ELF_MACHINE, 0); NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry; entry = elf_entry;
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL); kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
......
...@@ -184,7 +184,9 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab, ...@@ -184,7 +184,9 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
return -1; 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, int must_swab, uint64_t *pentry,
uint64_t *lowaddr, uint64_t *highaddr, uint64_t *lowaddr, uint64_t *highaddr,
int elf_machine, int clear_lsb) 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, ...@@ -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 /* address_offset is hack for kernel images that are
linked at the wrong physical address. */ 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); snprintf(label, sizeof(label), "phdr #%d: %s", i, name);
rom_add_blob_fixed(label, data, mem_size, addr); rom_add_blob_fixed(label, data, mem_size, addr);
......
...@@ -44,6 +44,11 @@ static void main_cpu_reset(void *opaque) ...@@ -44,6 +44,11 @@ static void main_cpu_reset(void *opaque)
env->pc = bootstrap_pc; env->pc = bootstrap_pc;
} }
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
{
return addr - 0x80000000LL;
}
static static
void bareetraxfs_init (ram_addr_t ram_size, void bareetraxfs_init (ram_addr_t ram_size,
const char *boot_device, const char *boot_device,
...@@ -137,7 +142,7 @@ void bareetraxfs_init (ram_addr_t ram_size, ...@@ -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 /* Boots a kernel elf binary, os/linux-2.6/vmlinux from the axis
devboard SDK. */ 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); &entry, NULL, &high, 0, ELF_MACHINE, 0);
bootstrap_pc = entry; bootstrap_pc = entry;
if (kernel_size < 0) { if (kernel_size < 0) {
......
...@@ -276,9 +276,9 @@ static void *load_at(int fd, int offset, int size) ...@@ -276,9 +276,9 @@ static void *load_at(int fd, int offset, int size)
#include "elf_ops.h" #include "elf_ops.h"
/* return < 0 if error, otherwise the number of bytes loaded in memory */ /* return < 0 if error, otherwise the number of bytes loaded in memory */
int load_elf(const char *filename, int64_t address_offset, int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
int big_endian, int elf_machine, int clear_lsb) uint64_t *highaddr, int big_endian, int elf_machine, int clear_lsb)
{ {
int fd, data_order, target_data_order, must_swab, ret; int fd, data_order, target_data_order, must_swab, ret;
uint8_t e_ident[EI_NIDENT]; uint8_t e_ident[EI_NIDENT];
...@@ -312,11 +312,11 @@ int load_elf(const char *filename, int64_t address_offset, ...@@ -312,11 +312,11 @@ int load_elf(const char *filename, int64_t address_offset,
lseek(fd, 0, SEEK_SET); lseek(fd, 0, SEEK_SET);
if (e_ident[EI_CLASS] == ELFCLASS64) { if (e_ident[EI_CLASS] == ELFCLASS64) {
ret = load_elf64(filename, fd, address_offset, must_swab, pentry, ret = load_elf64(filename, fd, translate_fn, translate_opaque, must_swab,
lowaddr, highaddr, elf_machine, clear_lsb); pentry, lowaddr, highaddr, elf_machine, clear_lsb);
} else { } else {
ret = load_elf32(filename, fd, address_offset, must_swab, pentry, ret = load_elf32(filename, fd, translate_fn, translate_opaque, must_swab,
lowaddr, highaddr, elf_machine, clear_lsb); pentry, lowaddr, highaddr, elf_machine, clear_lsb);
} }
close(fd); close(fd);
......
...@@ -5,9 +5,10 @@ ...@@ -5,9 +5,10 @@
int get_image_size(const char *filename); int get_image_size(const char *filename);
int load_image(const char *filename, uint8_t *addr); /* deprecated */ 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_image_targphys(const char *filename, target_phys_addr_t, int max_sz);
int load_elf(const char *filename, int64_t address_offset, int load_elf(const char *filename, uint64_t (*translate_fn)(void *, uint64_t),
uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr, void *translate_opaque, uint64_t *pentry, uint64_t *lowaddr,
int big_endian, int elf_machine, int clear_lsb); 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 load_aout(const char *filename, target_phys_addr_t addr, int max_sz,
int bswap_needed, target_phys_addr_t target_page_size); int bswap_needed, target_phys_addr_t target_page_size);
int load_uimage(const char *filename, target_phys_addr_t *ep, int load_uimage(const char *filename, target_phys_addr_t *ep,
......
...@@ -270,8 +270,8 @@ static void mcf5208evb_init(ram_addr_t ram_size, ...@@ -270,8 +270,8 @@ static void mcf5208evb_init(ram_addr_t ram_size,
exit(1); exit(1);
} }
kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
1, ELF_MACHINE, 0); NULL, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry; entry = elf_entry;
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL); kernel_size = load_uimage(kernel_filename, &entry, NULL, NULL);
......
...@@ -20,6 +20,10 @@ void mipsnet_init(int base, qemu_irq irq, NICInfo *nd); ...@@ -20,6 +20,10 @@ void mipsnet_init(int base, qemu_irq irq, NICInfo *nd);
/* jazz_led.c */ /* jazz_led.c */
extern void jazz_led_init(target_phys_addr_t base); 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 */ /* mips_int.c */
extern void cpu_mips_irq_init_cpu(CPUState *env); extern void cpu_mips_irq_init_cpu(CPUState *env);
......
/*
* 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;
}
...@@ -46,15 +46,7 @@ ...@@ -46,15 +46,7 @@
//#define DEBUG_BOARD_INIT //#define DEBUG_BOARD_INIT
#ifdef TARGET_MIPS64 #define ENVP_ADDR 0x80002000l
#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_NB_ENTRIES 16 #define ENVP_NB_ENTRIES 16
#define ENVP_ENTRY_SIZE 256 #define ENVP_ENTRY_SIZE 256
...@@ -681,7 +673,7 @@ static void prom_set(uint32_t* prom_buf, int index, const char *string, ...) ...@@ -681,7 +673,7 @@ static void prom_set(uint32_t* prom_buf, int index, const char *string, ...)
/* Kernel */ /* Kernel */
static int64_t load_kernel (void) static int64_t load_kernel (void)
{ {
int64_t kernel_entry, kernel_low, kernel_high; int64_t kernel_entry, kernel_high;
long initrd_size; long initrd_size;
ram_addr_t initrd_offset; ram_addr_t initrd_offset;
int big_endian; int big_endian;
...@@ -695,9 +687,9 @@ static int64_t load_kernel (void) ...@@ -695,9 +687,9 @@ static int64_t load_kernel (void)
big_endian = 0; big_endian = 0;
#endif #endif
if (load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND, if (load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys, NULL,
(uint64_t *)&kernel_entry, (uint64_t *)&kernel_low, (uint64_t *)&kernel_entry, NULL, (uint64_t *)&kernel_high,
(uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1) < 0) { big_endian, ELF_MACHINE, 1) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n", fprintf(stderr, "qemu: could not load kernel '%s'\n",
loaderparams.kernel_filename); loaderparams.kernel_filename);
exit(1); exit(1);
...@@ -733,8 +725,8 @@ static int64_t load_kernel (void) ...@@ -733,8 +725,8 @@ static int64_t load_kernel (void)
prom_set(prom_buf, prom_index++, loaderparams.kernel_filename); prom_set(prom_buf, prom_index++, loaderparams.kernel_filename);
if (initrd_size > 0) { if (initrd_size > 0) {
prom_set(prom_buf, prom_index++, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s", prom_set(prom_buf, prom_index++, "rd_start=0x%" PRIx64 " rd_size=%li %s",
PHYS_TO_VIRT(initrd_offset), initrd_size, cpu_mips_phys_to_kseg0(NULL, initrd_offset), initrd_size,
loaderparams.kernel_cmdline); loaderparams.kernel_cmdline);
} else { } else {
prom_set(prom_buf, prom_index++, loaderparams.kernel_cmdline); prom_set(prom_buf, prom_index++, loaderparams.kernel_cmdline);
...@@ -747,7 +739,7 @@ static int64_t load_kernel (void) ...@@ -747,7 +739,7 @@ static int64_t load_kernel (void)
prom_set(prom_buf, prom_index++, NULL); prom_set(prom_buf, prom_index++, NULL);
rom_add_blob_fixed("prom", prom_buf, prom_size, 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; return kernel_entry;
} }
......
...@@ -35,14 +35,6 @@ ...@@ -35,14 +35,6 @@
#include "loader.h" #include "loader.h"
#include "elf.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 { static struct _loaderparams {
int ram_size; int ram_size;
const char *kernel_filename; const char *kernel_filename;
...@@ -57,7 +49,7 @@ typedef struct ResetData { ...@@ -57,7 +49,7 @@ typedef struct ResetData {
static int64_t load_kernel(void) static int64_t load_kernel(void)
{ {
int64_t entry, kernel_low, kernel_high; int64_t entry, kernel_high;
long kernel_size; long kernel_size;
long initrd_size; long initrd_size;
ram_addr_t initrd_offset; ram_addr_t initrd_offset;
...@@ -69,9 +61,10 @@ static int64_t load_kernel(void) ...@@ -69,9 +61,10 @@ static int64_t load_kernel(void)
big_endian = 0; big_endian = 0;
#endif #endif
kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND, kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
(uint64_t *)&entry, (uint64_t *)&kernel_low, NULL, (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1); (uint64_t *)&kernel_high, big_endian,
ELF_MACHINE, 1);
if (kernel_size >= 0) { if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000) if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry; entry = (int32_t)entry;
......
...@@ -21,10 +21,6 @@ ...@@ -21,10 +21,6 @@
#include "loader.h" #include "loader.h"
#include "elf.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 #define MAX_IDE_BUS 2
static const int ide_iobase[2] = { 0x1f0, 0x170 }; static const int ide_iobase[2] = { 0x1f0, 0x170 };
...@@ -77,7 +73,7 @@ typedef struct ResetData { ...@@ -77,7 +73,7 @@ typedef struct ResetData {
static int64_t load_kernel(void) 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; long kernel_size, initrd_size, params_size;
ram_addr_t initrd_offset; ram_addr_t initrd_offset;
uint32_t *params_buf; uint32_t *params_buf;
...@@ -88,9 +84,10 @@ static int64_t load_kernel(void) ...@@ -88,9 +84,10 @@ static int64_t load_kernel(void)
#else #else
big_endian = 0; big_endian = 0;
#endif #endif
kernel_size = load_elf(loaderparams.kernel_filename, VIRT_TO_PHYS_ADDEND, kernel_size = load_elf(loaderparams.kernel_filename, cpu_mips_kseg0_to_phys,
(uint64_t *)&entry, (uint64_t *)&kernel_low, NULL, (uint64_t *)&entry, NULL,
(uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1); (uint64_t *)&kernel_high, big_endian,
ELF_MACHINE, 1);
if (kernel_size >= 0) { if (kernel_size >= 0) {
if ((entry & ~0x7fffffffULL) == 0x80000000) if ((entry & ~0x7fffffffULL) == 0x80000000)
entry = (int32_t)entry; entry = (int32_t)entry;
...@@ -132,8 +129,8 @@ static int64_t load_kernel(void) ...@@ -132,8 +129,8 @@ static int64_t load_kernel(void)
params_buf[1] = tswap32(0x12345678); params_buf[1] = tswap32(0x12345678);
if (initrd_size > 0) { if (initrd_size > 0) {
snprintf((char *)params_buf + 8, 256, "rd_start=0x" TARGET_FMT_lx " rd_size=%li %s", snprintf((char *)params_buf + 8, 256, "rd_start=0x%" PRIx64 " rd_size=%li %s",
PHYS_TO_VIRT((uint32_t)initrd_offset), cpu_mips_phys_to_kseg0(NULL, initrd_offset),
initrd_size, loaderparams.kernel_cmdline); initrd_size, loaderparams.kernel_cmdline);
} else { } else {
snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline); snprintf((char *)params_buf + 8, 256, "%s", loaderparams.kernel_cmdline);
......
...@@ -170,8 +170,8 @@ int load_multiboot(void *fw_cfg, ...@@ -170,8 +170,8 @@ int load_multiboot(void *fw_cfg,
uint64_t elf_low, elf_high; uint64_t elf_low, elf_high;
int kernel_size; int kernel_size;
fclose(f); fclose(f);
kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_low, &elf_high, kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
0, ELF_MACHINE, 0); &elf_low, &elf_high, 0, ELF_MACHINE, 0);
if (kernel_size < 0) { if (kernel_size < 0) {
fprintf(stderr, "Error while loading elf kernel\n"); fprintf(stderr, "Error while loading elf kernel\n");
exit(1); exit(1);
......
...@@ -104,6 +104,11 @@ static int petalogix_load_device_tree(target_phys_addr_t addr, ...@@ -104,6 +104,11 @@ static int petalogix_load_device_tree(target_phys_addr_t addr,
return fdt_size; return fdt_size;
} }
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
{
return addr - 0x30000000LL;
}
static void static void
petalogix_s3adsp1800_init(ram_addr_t ram_size, petalogix_s3adsp1800_init(ram_addr_t ram_size,
const char *boot_device, const char *boot_device,
...@@ -163,13 +168,13 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size, ...@@ -163,13 +168,13 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
uint32_t base32; uint32_t base32;
/* Boots a kernel elf binary. */ /* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, 0, kernel_size = load_elf(kernel_filename, NULL, NULL,
&entry, &low, &high, &entry, &low, &high,
1, ELF_MACHINE, 0); 1, ELF_MACHINE, 0);
base32 = entry; base32 = entry;
if (base32 == 0xc0000000) { if (base32 == 0xc0000000) {
kernel_size = load_elf(kernel_filename, -0x30000000LL, kernel_size = load_elf(kernel_filename, translate_kernel_address,
&entry, NULL, NULL, NULL, &entry, NULL, NULL,
1, ELF_MACHINE, 0); 1, ELF_MACHINE, 0);
} }
/* Always boot into physical ram. */ /* Always boot into physical ram. */
......
...@@ -120,8 +120,8 @@ static void bamboo_init(ram_addr_t ram_size, ...@@ -120,8 +120,8 @@ static void bamboo_init(ram_addr_t ram_size,
if (kernel_filename) { if (kernel_filename) {
kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL); kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr, kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
NULL, 1, ELF_MACHINE, 0); &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry; entry = elf_entry;
loadaddr = elf_lowaddr; loadaddr = elf_lowaddr;
} }
......
...@@ -115,6 +115,11 @@ static int fw_cfg_boot_set(void *opaque, const char *boot_device) ...@@ -115,6 +115,11 @@ static int fw_cfg_boot_set(void *opaque, const char *boot_device)
return 0; return 0;
} }
static uint64_t translate_kernel_address(void *opaque, uint64_t addr)
{
return (addr & 0x0fffffff) + KERNEL_LOAD_ADDR;
}
/* PowerPC Mac99 hardware initialisation */ /* PowerPC Mac99 hardware initialisation */
static void ppc_core99_init (ram_addr_t ram_size, static void ppc_core99_init (ram_addr_t ram_size,
const char *boot_device, const char *boot_device,
...@@ -180,7 +185,8 @@ static void ppc_core99_init (ram_addr_t ram_size, ...@@ -180,7 +185,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
/* Load OpenBIOS (ELF) */ /* Load OpenBIOS (ELF) */
if (filename) { 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); qemu_free(filename);
} else { } else {
...@@ -232,15 +238,8 @@ static void ppc_core99_init (ram_addr_t ram_size, ...@@ -232,15 +238,8 @@ static void ppc_core99_init (ram_addr_t ram_size,
#endif #endif
kernel_base = KERNEL_LOAD_ADDR; kernel_base = KERNEL_LOAD_ADDR;
/* Now we can load the kernel. The first step tries to load the kernel kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
supposing PhysAddr = 0x00000000. If that was wrong the kernel is NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
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);
}
if (kernel_size < 0) if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base, kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed, ram_size - kernel_base, bswap_needed,
......
...@@ -122,6 +122,12 @@ static int fw_cfg_boot_set(void *opaque, const char *boot_device) ...@@ -122,6 +122,12 @@ static int fw_cfg_boot_set(void *opaque, const char *boot_device)
return 0; 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, static void ppc_heathrow_init (ram_addr_t ram_size,
const char *boot_device, const char *boot_device,
const char *kernel_filename, const char *kernel_filename,
...@@ -185,8 +191,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size, ...@@ -185,8 +191,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
/* Load OpenBIOS (ELF) */ /* Load OpenBIOS (ELF) */
if (filename) { if (filename) {
bios_size = load_elf(filename, 0, NULL, NULL, NULL, bios_size = load_elf(filename, 0, NULL, NULL, NULL, NULL,
1, ELF_MACHINE, 0); 1, ELF_MACHINE, 0);
qemu_free(filename); qemu_free(filename);
} else { } else {
bios_size = -1; bios_size = -1;
...@@ -236,15 +242,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size, ...@@ -236,15 +242,8 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
bswap_needed = 0; bswap_needed = 0;
#endif #endif
kernel_base = KERNEL_LOAD_ADDR; kernel_base = KERNEL_LOAD_ADDR;
/* Now we can load the kernel. The first step tries to load the kernel kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
supposing PhysAddr = 0x00000000. If that was wrong the kernel is NULL, &lowaddr, NULL, 1, ELF_MACHINE, 0);
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);
}
if (kernel_size < 0) if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base, kernel_size = load_aout(kernel_filename, kernel_base,
ram_size - kernel_base, bswap_needed, ram_size - kernel_base, bswap_needed,
......
...@@ -231,8 +231,8 @@ static void mpc8544ds_init(ram_addr_t ram_size, ...@@ -231,8 +231,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
if (kernel_filename) { if (kernel_filename) {
kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL); kernel_size = load_uimage(kernel_filename, &entry, &loadaddr, NULL);
if (kernel_size < 0) { if (kernel_size < 0) {
kernel_size = load_elf(kernel_filename, 0, &elf_entry, &elf_lowaddr, kernel_size = load_elf(kernel_filename, NULL, NULL, &elf_entry,
NULL, 1, ELF_MACHINE, 0); &elf_lowaddr, NULL, 1, ELF_MACHINE, 0);
entry = elf_entry; entry = elf_entry;
loadaddr = elf_lowaddr; loadaddr = elf_lowaddr;
} }
......
...@@ -292,6 +292,11 @@ static void cpu_halt_signal(void *opaque, int irq, int level) ...@@ -292,6 +292,11 @@ static void cpu_halt_signal(void *opaque, int irq, int level)
cpu_interrupt(cpu_single_env, CPU_INTERRUPT_HALT); 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, static unsigned long sun4m_load_kernel(const char *kernel_filename,
const char *initrd_filename, const char *initrd_filename,
ram_addr_t RAM_size) ram_addr_t RAM_size)
...@@ -312,8 +317,8 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename, ...@@ -312,8 +317,8 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
#else #else
bswap_needed = 0; bswap_needed = 0;
#endif #endif
kernel_size = load_elf(kernel_filename, -0xf0000000ULL, NULL, NULL, kernel_size = load_elf(kernel_filename, translate_kernel_address, NULL,
NULL, 1, ELF_MACHINE, 0); NULL, NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0) if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR, kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed, RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
...@@ -636,6 +641,12 @@ static void afx_register_devices(void) ...@@ -636,6 +641,12 @@ static void afx_register_devices(void)
device_init(afx_register_devices); device_init(afx_register_devices);
/* Boot PROM (OpenBIOS) */ /* 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) static void prom_init(target_phys_addr_t addr, const char *bios_name)
{ {
DeviceState *dev; DeviceState *dev;
...@@ -655,8 +666,8 @@ static void prom_init(target_phys_addr_t addr, const char *bios_name) ...@@ -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); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) { if (filename) {
ret = load_elf(filename, addr - PROM_VADDR, NULL, NULL, NULL, ret = load_elf(filename, translate_prom_address, &addr, NULL,
1, ELF_MACHINE, 0); NULL, NULL, 1, ELF_MACHINE, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) { if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX); ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
} }
......
...@@ -189,8 +189,8 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename, ...@@ -189,8 +189,8 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
#else #else
bswap_needed = 0; bswap_needed = 0;
#endif #endif
kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL, kernel_size = load_elf(kernel_filename, NULL, NULL, NULL,
1, ELF_MACHINE, 0); NULL, NULL, 1, ELF_MACHINE, 0);
if (kernel_size < 0) if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR, kernel_size = load_aout(kernel_filename, KERNEL_LOAD_ADDR,
RAM_size - KERNEL_LOAD_ADDR, bswap_needed, RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
...@@ -580,6 +580,12 @@ static void pci_ebus_register(void) ...@@ -580,6 +580,12 @@ static void pci_ebus_register(void)
device_init(pci_ebus_register); 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) */ /* Boot PROM (OpenBIOS) */
static void prom_init(target_phys_addr_t addr, const char *bios_name) 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) ...@@ -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); filename = qemu_find_file(QEMU_FILE_TYPE_BIOS, bios_name);
if (filename) { if (filename) {
ret = load_elf(filename, addr - PROM_VADDR, NULL, NULL, NULL, ret = load_elf(filename, translate_prom_address, &addr,
1, ELF_MACHINE, 0); NULL, NULL, NULL, 1, ELF_MACHINE, 0);
if (ret < 0 || ret > PROM_SIZE_MAX) { if (ret < 0 || ret > PROM_SIZE_MAX) {
ret = load_image_targphys(filename, addr, PROM_SIZE_MAX); ret = load_image_targphys(filename, addr, PROM_SIZE_MAX);
} }
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册