Skip to content

Commit

Permalink
Compile loader only once
Browse files Browse the repository at this point in the history
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>
  • Loading branch information
blueswirl committed Sep 20, 2009
1 parent a333cd7 commit ca20cf3
Show file tree
Hide file tree
Showing 36 changed files with 234 additions and 96 deletions.
1 change: 1 addition & 0 deletions Makefile.hw
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion Makefile.target
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
4 changes: 3 additions & 1 deletion disas.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand All @@ -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;
Expand Down
7 changes: 5 additions & 2 deletions hw/an5206.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand All @@ -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";
Expand Down Expand Up @@ -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);
Expand Down
14 changes: 12 additions & 2 deletions hw/arm_boot.c
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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) {
Expand All @@ -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,
Expand Down
12 changes: 11 additions & 1 deletion hw/armv7m.c
Original file line number Diff line number Diff line change
Expand Up @@ -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. */

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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;
Expand Down
4 changes: 3 additions & 1 deletion hw/axis_dev88.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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. */
Expand Down
7 changes: 5 additions & 2 deletions hw/dummy_m68k.c
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,8 @@
#include "hw.h"
#include "sysemu.h"
#include "boards.h"
#include "loader.h"
#include "elf.h"

#define KERNEL_LOAD_ADDR 0x10000

Expand All @@ -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";
Expand All @@ -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);
Expand Down
23 changes: 13 additions & 10 deletions elf_ops.h → hw/elf_ops.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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;
Expand All @@ -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)
Expand All @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion hw/etraxfs.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down Expand Up @@ -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. */
Expand Down
Loading

0 comments on commit ca20cf3

Please sign in to comment.