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>
This commit is contained in:
Blue Swirl
2009-09-20 14:58:02 +00:00
parent a333cd7166
commit ca20cf32ab
36 changed files with 234 additions and 96 deletions
+1
View File
@@ -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
+1 -1
View File
@@ -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
+3 -1
View File
@@ -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;
+5 -2
View File
@@ -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);
+12 -2
View File
@@ -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,
+11 -1
View File
@@ -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;
+3 -1
View File
@@ -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. */
+5 -2
View File
@@ -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);
+13 -10
View File
@@ -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);
+3 -1
View File
@@ -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. */
+29 -27
View File
@@ -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;
+21
View File
@@ -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
+5 -2
View File
@@ -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);
+1
View File
@@ -33,6 +33,7 @@
#include "net.h"
#include "scsi.h"
#include "mips-bios.h"
#include "loader.h"
enum jazz_model_e
{
+10 -1
View File
@@ -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);
+10 -1
View File
@@ -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;
+9 -1
View File
@@ -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;
+1
View File
@@ -30,6 +30,7 @@
#include "flash.h"
#include "hw.h"
#include "bt.h"
#include "loader.h"
/* Nokia N8x0 support */
struct n800_s {
+1
View File
@@ -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)
{
+4 -1
View File
@@ -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);

Some files were not shown because too many files have changed in this diff Show More