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 similarity index 93% rename from elf_ops.h rename to 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 similarity index 90% rename from loader.c rename to hw/loader.c index 0cbcf9c6a3..5d83a66041 100644 --- a/loader.c +++ b/hw/loader.c @@ -42,10 +42,11 @@ * with this program; if not, see . */ -#include "qemu-common.h" +#include "hw.h" #include "disas.h" #include "sysemu.h" #include "uboot_image.h" +#include "loader.h" #include @@ -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;