aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBlue Swirl <blauwirbel@gmail.com>2009-09-20 14:58:02 +0000
committerBlue Swirl <blauwirbel@gmail.com>2009-09-20 14:58:02 +0000
commitca20cf32ab3d945155141ef737f5d08ebb373e1d (patch)
tree45515350fdf7b5322658095beec591565a78506d
parenta333cd7166d12397635e16dcade28da5ba8ec7b3 (diff)
Compile loader only once
Callers must pass ELF machine, byte swapping and symbol LSB clearing information to ELF loader. A.out loader needs page size information, pass that too as a parameter. Extract prototypes to a separate file. Move loader.[ch] and elf_ops.h under hw. Adjust callers. Also use target_phys_addr_t instead of target_ulong for addresses: loader addresses aren't virtual. Signed-off-by: Blue Swirl <blauwirbel@gmail.com>
-rw-r--r--Makefile.hw1
-rw-r--r--Makefile.target2
-rw-r--r--disas.h4
-rw-r--r--hw/an5206.c7
-rw-r--r--hw/arm_boot.c14
-rw-r--r--hw/armv7m.c12
-rw-r--r--hw/axis_dev88.c4
-rw-r--r--hw/dummy_m68k.c7
-rw-r--r--hw/elf_ops.h (renamed from elf_ops.h)23
-rw-r--r--hw/etraxfs.c4
-rw-r--r--hw/loader.c (renamed from loader.c)56
-rw-r--r--hw/loader.h21
-rw-r--r--hw/mcf5208.c7
-rw-r--r--hw/mips_jazz.c1
-rw-r--r--hw/mips_malta.c11
-rw-r--r--hw/mips_mipssim.c11
-rw-r--r--hw/mips_r4k.c10
-rw-r--r--hw/nseries.c1
-rw-r--r--hw/palm.c1
-rw-r--r--hw/pc.c5
-rw-r--r--hw/petalogix_s3adsp1800_mmu.c8
-rw-r--r--hw/ppc.c1
-rw-r--r--hw/ppc405_boards.c1
-rw-r--r--hw/ppc440_bamboo.c8
-rw-r--r--hw/ppc_newworld.c20
-rw-r--r--hw/ppc_oldworld.c20
-rw-r--r--hw/ppc_prep.c1
-rw-r--r--hw/ppce500_mpc8544ds.c8
-rw-r--r--hw/r2d.c1
-rw-r--r--hw/shix.c1
-rw-r--r--hw/smbios.c1
-rw-r--r--hw/sun4m.c17
-rw-r--r--hw/sun4u.c18
-rw-r--r--hw/tc58128.c1
-rw-r--r--linux-user/elfload.c4
-rw-r--r--sysemu.h18
36 files changed, 234 insertions, 96 deletions
diff --git a/Makefile.hw b/Makefile.hw
index 11227bf873..cb9c9a4a85 100644
--- a/Makefile.hw
+++ b/Makefile.hw
@@ -11,6 +11,7 @@ VPATH=$(SRC_PATH):$(SRC_PATH)/hw
QEMU_CFLAGS+=-I.. -I$(SRC_PATH)/fpu
obj-y =
+obj-y += loader.o
obj-y += virtio.o
obj-y += fw_cfg.o
obj-y += watchdog.o
diff --git a/Makefile.target b/Makefile.target
index d9e98fe3c5..bc3998a1de 100644
--- a/Makefile.target
+++ b/Makefile.target
@@ -155,7 +155,7 @@ endif
# System emulator target
ifdef CONFIG_SOFTMMU
-obj-y = vl.o monitor.o pci.o loader.o isa_mmio.o machine.o \
+obj-y = vl.o monitor.o pci.o isa_mmio.o machine.o \
gdbstub.o gdbstub-xml.o msix.o ioport.o
# virtio has to be here due to weird dependency between PCI and virtio-net.
# need to fix this properly
diff --git a/disas.h b/disas.h
index 0789b57218..06abab21eb 100644
--- a/disas.h
+++ b/disas.h
@@ -3,6 +3,7 @@
#include "qemu-common.h"
+#ifdef NEED_CPU_H
/* Disassemble this for me please... (debugging). */
void disas(FILE *out, void *code, unsigned long size);
void target_disas(FILE *out, target_ulong code, target_ulong size, int flags);
@@ -15,12 +16,13 @@ void monitor_disas(Monitor *mon, CPUState *env,
/* Look up symbol for debugging purpose. Returns "" if unknown. */
const char *lookup_symbol(target_ulong orig_addr);
+#endif
struct syminfo;
struct elf32_sym;
struct elf64_sym;
-typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_ulong orig_addr);
+typedef const char *(*lookup_symbol_t)(struct syminfo *s, target_phys_addr_t orig_addr);
struct syminfo {
lookup_symbol_t lookup_symbol;
diff --git a/hw/an5206.c b/hw/an5206.c
index d417d923b9..a4b83b0f44 100644
--- a/hw/an5206.c
+++ b/hw/an5206.c
@@ -11,6 +11,8 @@
#include "mcf.h"
#include "sysemu.h"
#include "boards.h"
+#include "loader.h"
+#include "elf.h"
#define KERNEL_LOAD_ADDR 0x10000
#define AN5206_MBAR_ADDR 0x10000000
@@ -35,7 +37,7 @@ static void an5206_init(ram_addr_t ram_size,
CPUState *env;
int kernel_size;
uint64_t elf_entry;
- target_ulong entry;
+ target_phys_addr_t entry;
if (!cpu_model)
cpu_model = "m5206";
@@ -66,7 +68,8 @@ static void an5206_init(ram_addr_t ram_size,
exit(1);
}
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
+ kernel_size = load_elf(kernel_filename, 0, &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 35f0130db1..a8a38c5a36 100644
--- a/hw/arm_boot.c
+++ b/hw/arm_boot.c
@@ -10,6 +10,8 @@
#include "hw.h"
#include "arm-misc.h"
#include "sysemu.h"
+#include "loader.h"
+#include "elf.h"
#define KERNEL_ARGS_ADDR 0x100
#define KERNEL_LOAD_ADDR 0x00010000
@@ -191,7 +193,8 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
int n;
int is_linux = 0;
uint64_t elf_entry;
- target_ulong entry;
+ target_phys_addr_t entry;
+ int big_endian;
/* Load the kernel. */
if (!info->kernel_filename) {
@@ -206,8 +209,15 @@ void arm_load_kernel(CPUState *env, struct arm_boot_info *info)
qemu_register_reset(main_cpu_reset, env);
}
+#ifdef TARGET_WORDS_BIGENDIAN
+ big_endian = 1;
+#else
+ big_endian = 0;
+#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);
+ kernel_size = load_elf(info->kernel_filename, 0, &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 059a356e21..a96288d0dd 100644
--- a/hw/armv7m.c
+++ b/hw/armv7m.c
@@ -10,6 +10,8 @@
#include "sysbus.h"
#include "arm-misc.h"
#include "sysemu.h"
+#include "loader.h"
+#include "elf.h"
/* Bitbanded IO. Each word corresponds to a single bit. */
@@ -166,6 +168,7 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
uint64_t entry;
uint64_t lowaddr;
int i;
+ int big_endian;
flash_size *= 1024;
sram_size *= 1024;
@@ -206,7 +209,14 @@ qemu_irq *armv7m_init(int flash_size, int sram_size,
pic[i] = qdev_get_gpio_in(nvic, i);
}
- image_size = load_elf(kernel_filename, 0, &entry, &lowaddr, NULL);
+#ifdef TARGET_WORDS_BIGENDIAN
+ big_endian = 1;
+#else
+ big_endian = 0;
+#endif
+
+ image_size = load_elf(kernel_filename, 0, &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 b5163b655f..81a41c9446 100644
--- a/hw/axis_dev88.c
+++ b/hw/axis_dev88.c
@@ -28,6 +28,8 @@
#include "boards.h"
#include "sysemu.h"
#include "etraxfs.h"
+#include "loader.h"
+#include "elf.h"
#define D(x)
#define DNAND(x)
@@ -344,7 +346,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,
- &entry, NULL, &high);
+ &entry, NULL, &high, 0, ELF_MACHINE, 0);
bootstrap_pc = entry;
if (kernel_size < 0) {
/* Takes a kimage from the axis devboard SDK. */
diff --git a/hw/dummy_m68k.c b/hw/dummy_m68k.c
index 5718ab64e1..ce45a597db 100644
--- a/hw/dummy_m68k.c
+++ b/hw/dummy_m68k.c
@@ -9,6 +9,8 @@
#include "hw.h"
#include "sysemu.h"
#include "boards.h"
+#include "loader.h"
+#include "elf.h"
#define KERNEL_LOAD_ADDR 0x10000
@@ -22,7 +24,7 @@ static void dummy_m68k_init(ram_addr_t ram_size,
CPUState *env;
int kernel_size;
uint64_t elf_entry;
- target_ulong entry;
+ target_phys_addr_t entry;
if (!cpu_model)
cpu_model = "cfv4e";
@@ -41,7 +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);
+ kernel_size = load_elf(kernel_filename, 0, &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/elf_ops.h b/hw/elf_ops.h
index 15928cbb5b..8376465a10 100644
--- a/elf_ops.h
+++ b/hw/elf_ops.h
@@ -73,7 +73,8 @@ static int glue(symfind, SZ)(const void *s0, const void *s1)
return result;
}
-static const char *glue(lookup_symbol, SZ)(struct syminfo *s, target_ulong orig_addr)
+static const char *glue(lookup_symbol, SZ)(struct syminfo *s,
+ target_phys_addr_t orig_addr)
{
struct elf_sym *syms = glue(s->disas_symtab.elf, SZ);
struct elf_sym key;
@@ -98,7 +99,8 @@ static int glue(symcmp, SZ)(const void *s0, const void *s1)
: ((sym0->st_value > sym1->st_value) ? 1 : 0);
}
-static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
+static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab,
+ int clear_lsb)
{
struct elf_shdr *symtab, *strtab, *shdr_table = NULL;
struct elf_sym *syms = NULL;
@@ -141,10 +143,10 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
}
continue;
}
-#if defined(TARGET_ARM) || defined (TARGET_MIPS)
- /* The bottom address bit marks a Thumb or MIPS16 symbol. */
- syms[i].st_value &= ~(target_ulong)1;
-#endif
+ if (clear_lsb) {
+ /* The bottom address bit marks a Thumb or MIPS16 symbol. */
+ syms[i].st_value &= ~(glue(glue(Elf, SZ), _Addr))1;
+ }
i++;
}
syms = qemu_realloc(syms, nsyms * sizeof(*syms));
@@ -179,7 +181,8 @@ static int glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd, int must_swab)
static int glue(load_elf, SZ)(int fd, int64_t address_offset,
int must_swab, uint64_t *pentry,
- uint64_t *lowaddr, uint64_t *highaddr)
+ uint64_t *lowaddr, uint64_t *highaddr,
+ int elf_machine, int clear_lsb)
{
struct elfhdr ehdr;
struct elf_phdr *phdr = NULL, *ph;
@@ -194,7 +197,7 @@ static int glue(load_elf, SZ)(int fd, int64_t address_offset,
glue(bswap_ehdr, SZ)(&ehdr);
}
- switch (ELF_MACHINE) {
+ switch (elf_machine) {
case EM_PPC64:
if (EM_PPC64 != ehdr.e_machine)
if (EM_PPC != ehdr.e_machine)
@@ -206,14 +209,14 @@ static int glue(load_elf, SZ)(int fd, int64_t address_offset,
goto fail;
break;
default:
- if (ELF_MACHINE != ehdr.e_machine)
+ if (elf_machine != ehdr.e_machine)
goto fail;
}
if (pentry)
*pentry = (uint64_t)(elf_sword)ehdr.e_entry;
- glue(load_symbols, SZ)(&ehdr, fd, must_swab);
+ glue(load_symbols, SZ)(&ehdr, fd, must_swab, clear_lsb);
size = ehdr.e_phnum * sizeof(phdr[0]);
lseek(fd, ehdr.e_phoff, SEEK_SET);
diff --git a/hw/etraxfs.c b/hw/etraxfs.c
index ab6a3a302f..4f451c54c9 100644
--- a/hw/etraxfs.c
+++ b/hw/etraxfs.c
@@ -28,6 +28,8 @@
#include "net.h"
#include "flash.h"
#include "etraxfs.h"
+#include "loader.h"
+#include "elf.h"
#define FLASH_SIZE 0x2000000
#define INTMEM_SIZE (128 * 1024)
@@ -136,7 +138,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,
- &entry, NULL, &high);
+ &entry, NULL, &high, 0, ELF_MACHINE, 0);
bootstrap_pc = entry;
if (kernel_size < 0) {
/* Takes a kimage from the axis devboard SDK. */
diff --git a/loader.c b/hw/loader.c
index 0cbcf9c6a3..5d83a66041 100644
--- a/loader.c
+++ b/hw/loader.c
@@ -42,10 +42,11 @@
* with this program; if not, see <http://www.gnu.org/licenses/>.
*/
-#include "qemu-common.h"
+#include "hw.h"
#include "disas.h"
#include "sysemu.h"
#include "uboot_image.h"
+#include "loader.h"
#include <zlib.h>
@@ -172,7 +173,6 @@ struct exec
uint32_t a_drsize; /* length of relocation info for data, in bytes */
};
-#ifdef BSWAP_NEEDED
static void bswap_ahdr(struct exec *e)
{
bswap32s(&e->a_info);
@@ -184,9 +184,6 @@ static void bswap_ahdr(struct exec *e)
bswap32s(&e->a_trsize);
bswap32s(&e->a_drsize);
}
-#else
-#define bswap_ahdr(x) do { } while (0)
-#endif
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
#define OMAGIC 0407
@@ -197,17 +194,18 @@ static void bswap_ahdr(struct exec *e)
#define N_TXTOFF(x) \
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
(N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
-#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? TARGET_PAGE_SIZE : 0)
-#define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
+#define N_TXTADDR(x, target_page_size) (N_MAGIC(x) == QMAGIC ? target_page_size : 0)
+#define _N_SEGMENT_ROUND(x, target_page_size) (((x) + target_page_size - 1) & ~(target_page_size - 1))
-#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
+#define _N_TXTENDADDR(x, target_page_size) (N_TXTADDR(x, target_page_size)+(x).a_text)
-#define N_DATADDR(x) \
- (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
- : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
+#define N_DATADDR(x, target_page_size) \
+ (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x, target_page_size)) \
+ : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x, target_page_size), target_page_size)))
-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 fd, size, ret;
struct exec e;
@@ -221,7 +219,9 @@ int load_aout(const char *filename, target_phys_addr_t addr, int max_sz)
if (size < 0)
goto fail;
- bswap_ahdr(&e);
+ if (bswap_needed) {
+ bswap_ahdr(&e);
+ }
magic = N_MAGIC(e);
switch (magic) {
@@ -236,13 +236,14 @@ int load_aout(const char *filename, target_phys_addr_t addr, int max_sz)
goto fail;
break;
case NMAGIC:
- if (N_DATADDR(e) + e.a_data > max_sz)
+ if (N_DATADDR(e, target_page_size) + e.a_data > max_sz)
goto fail;
lseek(fd, N_TXTOFF(e), SEEK_SET);
size = read_targphys(fd, addr, e.a_text);
if (size < 0)
goto fail;
- ret = read_targphys(fd, addr + N_DATADDR(e), e.a_data);
+ ret = read_targphys(fd, addr + N_DATADDR(e, target_page_size),
+ e.a_data);
if (ret < 0)
goto fail;
size += ret;
@@ -307,9 +308,10 @@ static void *load_at(int fd, int offset, int size)
/* 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)
+ uint64_t *pentry, uint64_t *lowaddr, uint64_t *highaddr,
+ int big_endian, int elf_machine, int clear_lsb)
{
- int fd, data_order, host_data_order, must_swab, ret;
+ int fd, data_order, target_data_order, must_swab, ret;
uint8_t e_ident[EI_NIDENT];
fd = open(filename, O_RDONLY | O_BINARY);
@@ -330,22 +332,22 @@ int load_elf(const char *filename, int64_t address_offset,
data_order = ELFDATA2LSB;
#endif
must_swab = data_order != e_ident[EI_DATA];
+ if (big_endian) {
+ target_data_order = ELFDATA2MSB;
+ } else {
+ target_data_order = ELFDATA2LSB;
+ }
-#ifdef TARGET_WORDS_BIGENDIAN
- host_data_order = ELFDATA2MSB;
-#else
- host_data_order = ELFDATA2LSB;
-#endif
- if (host_data_order != e_ident[EI_DATA])
+ if (target_data_order != e_ident[EI_DATA])
return -1;
lseek(fd, 0, SEEK_SET);
if (e_ident[EI_CLASS] == ELFCLASS64) {
ret = load_elf64(fd, address_offset, must_swab, pentry,
- lowaddr, highaddr);
+ lowaddr, highaddr, elf_machine, clear_lsb);
} else {
ret = load_elf32(fd, address_offset, must_swab, pentry,
- lowaddr, highaddr);
+ lowaddr, highaddr, elf_machine, clear_lsb);
}
close(fd);
@@ -455,8 +457,8 @@ static ssize_t gunzip(void *dst, size_t dstlen, uint8_t *src,
}
/* Load a U-Boot image. */
-int load_uimage(const char *filename, target_ulong *ep, target_ulong *loadaddr,
- int *is_linux)
+int load_uimage(const char *filename, target_phys_addr_t *ep,
+ target_phys_addr_t *loadaddr, int *is_linux)
{
int fd;
int size;
diff --git a/hw/loader.h b/hw/loader.h
new file mode 100644
index 0000000000..3632008928
--- /dev/null
+++ b/hw/loader.h
@@ -0,0 +1,21 @@
+#ifndef LOADER_H
+#define LOADER_H
+
+/* loader.c */
+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_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,
+ target_phys_addr_t *loadaddr, int *is_linux);
+
+int fread_targphys(target_phys_addr_t dst_addr, size_t nbytes, FILE *f);
+int fread_targphys_ok(target_phys_addr_t dst_addr, size_t nbytes, FILE *f);
+int read_targphys(int fd, target_phys_addr_t dst_addr, size_t nbytes);
+void pstrcpy_targphys(target_phys_addr_t dest, int buf_size,
+ const char *source);
+#endif
diff --git a/hw/mcf5208.c b/hw/mcf5208.c
index 95a03fc0e6..5598611462 100644
--- a/hw/mcf5208.c
+++ b/hw/mcf5208.c
@@ -11,6 +11,8 @@
#include "sysemu.h"
#include "net.h"
#include "boards.h"
+#include "loader.h"
+#include "elf.h"
#define SYS_FREQ 66000000
@@ -201,7 +203,7 @@ static void mcf5208evb_init(ram_addr_t ram_size,
CPUState *env;
int kernel_size;
uint64_t elf_entry;
- target_ulong entry;
+ target_phys_addr_t entry;
qemu_irq *pic;
if (!cpu_model)
@@ -268,7 +270,8 @@ static void mcf5208evb_init(ram_addr_t ram_size,
exit(1);
}
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
+ kernel_size = load_elf(kernel_filename, 0, &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_jazz.c b/hw/mips_jazz.c
index d62a584a9a..1a499fa397 100644
--- a/hw/mips_jazz.c
+++ b/hw/mips_jazz.c
@@ -33,6 +33,7 @@
#include "net.h"
#include "scsi.h"
#include "mips-bios.h"
+#include "loader.h"
enum jazz_model_e
{
diff --git a/hw/mips_malta.c b/hw/mips_malta.c
index 0a6eaa479a..4d72da8716 100644
--- a/hw/mips_malta.c
+++ b/hw/mips_malta.c
@@ -39,6 +39,8 @@
#include "qemu-log.h"
#include "mips-bios.h"
#include "ide.h"
+#include "loader.h"
+#include "elf.h"
//#define DEBUG_BOARD_INIT
@@ -687,10 +689,17 @@ static int64_t load_kernel (CPUState *env)
int index = 0;
long initrd_size;
ram_addr_t initrd_offset;
+ int big_endian;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ big_endian = 1;
+#else
+ 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) < 0) {
+ (uint64_t *)&kernel_high, big_endian, ELF_MACHINE, 1) < 0) {
fprintf(stderr, "qemu: could not load kernel '%s'\n",
loaderparams.kernel_filename);
exit(1);
diff --git a/hw/mips_mipssim.c b/hw/mips_mipssim.c
index 6080dc825e..9aed40e1bd 100644
--- a/hw/mips_mipssim.c
+++ b/hw/mips_mipssim.c
@@ -32,6 +32,8 @@
#include "sysemu.h"
#include "boards.h"
#include "mips-bios.h"
+#include "loader.h"
+#include "elf.h"
#ifdef TARGET_MIPS64
#define PHYS_TO_VIRT(x) ((x) | ~0x7fffffffULL)
@@ -54,10 +56,17 @@ static void load_kernel (CPUState *env)
long kernel_size;
long initrd_size;
ram_addr_t initrd_offset;
+ int big_endian;
+
+#ifdef TARGET_WORDS_BIGENDIAN
+ big_endian = 1;
+#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);
+ (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 fcc7fed5f1..b3abc61551 100644
--- a/hw/mips_r4k.c
+++ b/hw/mips_r4k.c
@@ -18,6 +18,8 @@
#include "qemu-log.h"
#include "mips-bios.h"
#include "ide.h"
+#include "loader.h"
+#include "elf.h"
#define PHYS_TO_VIRT(x) ((x) | ~(target_ulong)0x7fffffff)
@@ -77,10 +79,16 @@ static void load_kernel (CPUState *env)
long kernel_size, initrd_size;
ram_addr_t initrd_offset;
int ret;
+ int big_endian;
+#ifdef TARGET_WORDS_BIGENDIAN
+ big_endian = 1;
+#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);
+ (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/nseries.c b/hw/nseries.c
index e9b68a7f10..066a0f980f 100644
--- a/hw/nseries.c
+++ b/hw/nseries.c
@@ -30,6 +30,7 @@
#include "flash.h"
#include "hw.h"
#include "bt.h"
+#include "loader.h"
/* Nokia N8x0 support */
struct n800_s {
diff --git a/hw/palm.c b/hw/palm.c
index bba972276e..6d19167512 100644
--- a/hw/palm.c
+++ b/hw/palm.c
@@ -24,6 +24,7 @@
#include "boards.h"
#include "arm-misc.h"
#include "devices.h"
+#include "loader.h"
static uint32_t static_readb(void *opaque, target_phys_addr_t offset)
{
diff --git a/hw/pc.c b/hw/pc.c
index 58de372da6..bc2875e36d 100644
--- a/hw/pc.c
+++ b/hw/pc.c
@@ -37,6 +37,8 @@
#include "watchdog.h"
#include "smbios.h"
#include "ide.h"
+#include "loader.h"
+#include "elf.h"
/* output Bochs bios info messages */
//#define DEBUG_BIOS
@@ -657,7 +659,8 @@ static int load_multiboot(void *fw_cfg,
uint64_t elf_entry;
int kernel_size;
fclose(f);
- kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL);
+ kernel_size = load_elf(kernel_filename, 0, &elf_entry, NULL, NULL,
+ 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 a04794d7f3..f343dbf7b8 100644
--- a/hw/petalogix_s3adsp1800_mmu.c
+++ b/hw/petalogix_s3adsp1800_mmu.c
@@ -32,6 +32,8 @@
#include "boards.h"
#include "device_tree.h"
#include "xilinx.h"
+#include "loader.h"
+#include "elf.h"
#define LMB_BRAM_SIZE (128 * 1024)
#define FLASH_SIZE (16 * 1024 * 1024)
@@ -155,11 +157,13 @@ petalogix_s3adsp1800_init(ram_addr_t ram_size,
/* Boots a kernel elf binary. */
kernel_size = load_elf(kernel_filename, 0,
- &entry, &low, &high);
+ &entry, &low, &high,
+ 1, ELF_MACHINE, 0);
base32 = entry;
if (base32 == 0xc0000000) {
kernel_size = load_elf(kernel_filename, -0x30000000LL,
- &entry, NULL, NULL);
+ &entry, NULL, NULL,
+ 1, ELF_MACHINE, 0);
}
/* Always boot into physical ram. */
bootstrap_pc = ddr_base + (entry & 0x0fffffff);
diff --git a/hw/ppc.c b/hw/ppc.c
index 2d66b9dc59..09ee2e46dd 100644
--- a/hw/ppc.c
+++ b/hw/ppc.c
@@ -27,6 +27,7 @@
#include "sysemu.h"
#include "nvram.h"
#include "qemu-log.h"
+#include "loader.h"
//#define PPC_DEBUG_IRQ
//#define PPC_DEBUG_TB
diff --git a/hw/ppc405_boards.c b/hw/ppc405_boards.c
index 0d7860edd6..9aa99c1781 100644
--- a/hw/ppc405_boards.c
+++ b/hw/ppc405_boards.c
@@ -30,6 +30,7 @@
#include "block.h"
#include "boards.h"
#include "qemu-log.h"
+#include "loader.h"
#define BIOS_FILENAME "ppc405_rom.bin"
#define BIOS_SIZE (2048 * 1024)
diff --git a/hw/ppc440_bamboo.c b/hw/ppc440_bamboo.c
index 3c59f33099..8a6b7ced92 100644
--- a/hw/ppc440_bamboo.c
+++ b/hw/ppc440_bamboo.c
@@ -22,6 +22,8 @@
#include "kvm.h"
#include "kvm_ppc.h"
#include "device_tree.h"
+#include "loader.h"
+#include "elf.h"
#define BINARY_DEVICE_TREE_FILE "bamboo.dtb"
@@ -93,8 +95,8 @@ static void bamboo_init(ram_addr_t ram_size,
CPUState *env;
uint64_t elf_entry;
uint64_t elf_lowaddr;
- target_ulong entry = 0;
- target_ulong loadaddr = 0;
+ target_phys_addr_t entry = 0;
+ target_phys_addr_t loadaddr = 0;
target_long kernel_size = 0;
target_ulong initrd_base = 0;
target_long initrd_size = 0;
@@ -126,7 +128,7 @@ static void bamboo_init(ram_addr_t ram_size,
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);
+ NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
}
diff --git a/hw/ppc_newworld.c b/hw/ppc_newworld.c
index 9a491eb7c6..6bd5234d8f 100644
--- a/hw/ppc_newworld.c
+++ b/hw/ppc_newworld.c
@@ -36,6 +36,8 @@
#include "escc.h"
#include "openpic.h"
#include "ide.h"
+#include "loader.h"
+#include "elf.h"
#define MAX_IDE_BUS 2
#define VGA_BIOS_SIZE 65536
@@ -145,7 +147,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);
+ bios_size = load_elf(filename, 0, NULL, NULL, NULL, 1, ELF_MACHINE, 0);
+
qemu_free(filename);
} else {
bios_size = -1;
@@ -187,19 +190,28 @@ static void ppc_core99_init (ram_addr_t ram_size,
if (linux_boot) {
uint64_t lowaddr = 0;
+ int bswap_needed;
+
+#ifdef BSWAP_NEEDED
+ bswap_needed = 1;
+#else
+ 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);
+ 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);
+ NULL, NULL, NULL, 1, ELF_MACHINE, 0);
}
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
- ram_size - kernel_base);
+ ram_size - kernel_base, bswap_needed,
+ TARGET_PAGE_SIZE);
if (kernel_size < 0)
kernel_size = load_image_targphys(kernel_filename,
kernel_base,
diff --git a/hw/ppc_oldworld.c b/hw/ppc_oldworld.c
index 6933650711..bb8c969ca2 100644
--- a/hw/ppc_oldworld.c
+++ b/hw/ppc_oldworld.c
@@ -36,6 +36,8 @@
#include "fw_cfg.h"
#include "escc.h"
#include "ide.h"
+#include "loader.h"
+#include "elf.h"
#define MAX_IDE_BUS 2
#define VGA_BIOS_SIZE 65536
@@ -180,7 +182,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);
+ bios_size = load_elf(filename, 0, NULL, NULL, NULL,
+ 1, ELF_MACHINE, 0);
qemu_free(filename);
} else {
bios_size = -1;
@@ -222,18 +225,27 @@ static void ppc_heathrow_init (ram_addr_t ram_size,
if (linux_boot) {
uint64_t lowaddr = 0;
+ int bswap_needed;
+
+#ifdef BSWAP_NEEDED
+ bswap_needed = 1;
+#else
+ 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);
+ 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);
+ NULL, NULL, NULL, 1, ELF_MACHINE, 0);
}
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, kernel_base,
- ram_size - kernel_base);
+ ram_size - kernel_base, bswap_needed,
+ TARGET_PAGE_SIZE);
if (kernel_size < 0)
kernel_size = load_image_targphys(kernel_filename,
kernel_base,
diff --git a/hw/ppc_prep.c b/hw/ppc_prep.c
index 5392072982..eb281f85f7 100644
--- a/hw/ppc_prep.c
+++ b/hw/ppc_prep.c
@@ -33,6 +33,7 @@
#include "boards.h"
#include "qemu-log.h"
#include "ide.h"
+#include "loader.h"
//#define HARD_DEBUG_PPC_IO
//#define DEBUG_PPC_IO
diff --git a/hw/ppce500_mpc8544ds.c b/hw/ppce500_mpc8544ds.c
index 51208215f1..504419458b 100644
--- a/hw/ppce500_mpc8544ds.c
+++ b/hw/ppce500_mpc8544ds.c
@@ -29,6 +29,8 @@
#include "device_tree.h"
#include "openpic.h"
#include "ppce500.h"
+#include "loader.h"
+#include "elf.h"
#define BINARY_DEVICE_TREE_FILE "mpc8544ds.dtb"
#define UIMAGE_LOAD_BASE 0
@@ -160,8 +162,8 @@ static void mpc8544ds_init(ram_addr_t ram_size,
CPUState *env;
uint64_t elf_entry;
uint64_t elf_lowaddr;
- target_ulong entry=0;
- target_ulong loadaddr=UIMAGE_LOAD_BASE;
+ target_phys_addr_t entry=0;
+ target_phys_addr_t loadaddr=UIMAGE_LOAD_BASE;
target_long kernel_size=0;
target_ulong dt_base=DTB_LOAD_BASE;
target_ulong initrd_base=INITRD_LOAD_BASE;
@@ -226,7 +228,7 @@ static void mpc8544ds_init(ram_addr_t ram_size,
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);
+ NULL, 1, ELF_MACHINE, 0);
entry = elf_entry;
loadaddr = elf_lowaddr;
}
diff --git a/hw/r2d.c b/hw/r2d.c
index ff514a482f..ea19ff623d 100644
--- a/hw/r2d.c
+++ b/hw/r2d.c
@@ -32,6 +32,7 @@
#include "net.h"
#include "sh7750_regs.h"
#include "ide.h"
+#include "loader.h"
#define SDRAM_BASE 0x0c000000 /* Physical location of SDRAM: Area 3 */
#define SDRAM_SIZE 0x04000000
diff --git a/hw/shix.c b/hw/shix.c
index 19b0155a49..638bf16e34 100644
--- a/hw/shix.c
+++ b/hw/shix.c
@@ -32,6 +32,7 @@
#include "sh.h"
#include "sysemu.h"
#include "boards.h"
+#include "loader.h"
#define BIOS_FILENAME "shix_bios.bin"
#define BIOS_ADDRESS 0xA0000000
diff --git a/hw/smbios.c b/hw/smbios.c
index e28beba2c8..a3ae1de824 100644
--- a/hw/smbios.c
+++ b/hw/smbios.c
@@ -13,6 +13,7 @@
#include "sysemu.h"
#include "smbios.h"
+#include "loader.h"
/*
* Structures shared with the BIOS
diff --git a/hw/sun4m.c b/hw/sun4m.c
index d97072393b..a869d15a81 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -37,6 +37,8 @@
#include "fw_cfg.h"
#include "escc.h"
#include "qdev-addr.h"
+#include "loader.h"
+#include "elf.h"
//#define DEBUG_IRQ
@@ -302,11 +304,19 @@ static unsigned long sun4m_load_kernel(const char *kernel_filename,
kernel_size = 0;
if (linux_boot) {
+ int bswap_needed;
+
+#ifdef BSWAP_NEEDED
+ bswap_needed = 1;
+#else
+ bswap_needed = 0;
+#endif
kernel_size = load_elf(kernel_filename, -0xf0000000ULL, 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);
+ RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
+ TARGET_PAGE_SIZE);
if (kernel_size < 0)
kernel_size = load_image_targphys(kernel_filename,
KERNEL_LOAD_ADDR,
@@ -608,7 +618,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);
+ ret = load_elf(filename, addr - PROM_VADDR, 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 427ee764ce..2c97d9d702 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -34,6 +34,8 @@
#include "fw_cfg.h"
#include "sysbus.h"
#include "ide.h"
+#include "loader.h"
+#include "elf.h"
//#define DEBUG_IRQ
@@ -164,10 +166,19 @@ static unsigned long sun4u_load_kernel(const char *kernel_filename,
kernel_size = 0;
if (linux_boot) {
- kernel_size = load_elf(kernel_filename, 0, NULL, NULL, NULL);
+ int bswap_needed;
+
+#ifdef BSWAP_NEEDED
+ bswap_needed = 1;
+#else
+ bswap_needed = 0;
+#endif
+ kernel_size = load_elf(kernel_filename, 0, 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);
+ RAM_size - KERNEL_LOAD_ADDR, bswap_needed,
+ TARGET_PAGE_SIZE);
if (kernel_size < 0)
kernel_size = load_image_targphys(kernel_filename,
KERNEL_LOAD_ADDR,
@@ -418,7 +429,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);
+ ret = load_elf(filename, addr - PROM_VADDR, 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/tc58128.c b/hw/tc58128.c
index 21e808547e..264aa028da 100644
--- a/hw/tc58128.c
+++ b/hw/tc58128.c
@@ -1,6 +1,7 @@
#include "hw.h"
#include "sh.h"
#include "sysemu.h"
+#include "loader.h"
#define CE1 0x0100
#define CE2 0x0200
diff --git a/linux-user/elfload.c b/linux-user/elfload.c
index 10d4781da8..7c8e771df1 100644
--- a/linux-user/elfload.c
+++ b/linux-user/elfload.c
@@ -1315,10 +1315,10 @@ static void load_symbols(struct elfhdr *hdr, int fd)
s->disas_num_syms = nsyms;
#if ELF_CLASS == ELFCLASS32
s->disas_symtab.elf32 = syms;
- s->lookup_symbol = lookup_symbolxx;
+ s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
#else
s->disas_symtab.elf64 = syms;
- s->lookup_symbol = lookup_symbolxx;
+ s->lookup_symbol = (lookup_symbol_t)lookup_symbolxx;
#endif
s->next = syminfos;
syminfos = s;
diff --git a/sysemu.h b/sysemu.h
index 644a97d624..8bf90ee357 100644
--- a/sysemu.h
+++ b/sysemu.h
@@ -237,24 +237,6 @@ extern CharDriverState *virtcon_hds[MAX_VIRTIO_CONSOLES];
#define TFR(expr) do { if ((expr) != -1) break; } while (errno == EINTR)
-#ifdef NEED_CPU_H
-/* loader.c */
-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 load_aout(const char *filename, target_phys_addr_t addr, int max_sz);
-int load_uimage(const char *filename, target_ulong *ep, target_ulong *loadaddr,
- int *is_linux);
-
-int fread_targphys(target_phys_addr_t dst_addr, size_t nbytes, FILE *f);
-int fread_targphys_ok(target_phys_addr_t dst_addr, size_t nbytes, FILE *f);
-int read_targphys(int fd, target_phys_addr_t dst_addr, size_t nbytes);
-void pstrcpy_targphys(target_phys_addr_t dest, int buf_size,
- const char *source);
-#endif
-
#ifdef HAS_AUDIO
struct soundhw {
const char *name;