summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2006-04-23 17:14:05 +0000
committerbellard <bellard@c046a42c-6fe2-441c-8c8c-71466251a162>2006-04-23 17:14:05 +0000
commitb37837317fb3177755c592591d7f53826c6afae5 (patch)
tree19be2c8087a98430ea8e5edfd012a11c44e4939f
parent5fe141fd30d35516eac3674f7b62be51ba34543f (diff)
use generic ELF loader
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1832 c046a42c-6fe2-441c-8c8c-71466251a162
-rw-r--r--hw/elf_ops.h218
-rw-r--r--hw/magic-load.c201
-rw-r--r--hw/sun4m.c10
-rw-r--r--hw/sun4u.c11
4 files changed, 13 insertions, 427 deletions
diff --git a/hw/elf_ops.h b/hw/elf_ops.h
deleted file mode 100644
index 1f3232d47..000000000
--- a/hw/elf_ops.h
+++ /dev/null
@@ -1,218 +0,0 @@
-#ifdef BSWAP_NEEDED
-static void glue(bswap_ehdr, SZ)(struct elfhdr *ehdr)
-{
- bswap16s(&ehdr->e_type); /* Object file type */
- bswap16s(&ehdr->e_machine); /* Architecture */
- bswap32s(&ehdr->e_version); /* Object file version */
- bswapSZs(&ehdr->e_entry); /* Entry point virtual address */
- bswapSZs(&ehdr->e_phoff); /* Program header table file offset */
- bswapSZs(&ehdr->e_shoff); /* Section header table file offset */
- bswap32s(&ehdr->e_flags); /* Processor-specific flags */
- bswap16s(&ehdr->e_ehsize); /* ELF header size in bytes */
- bswap16s(&ehdr->e_phentsize); /* Program header table entry size */
- bswap16s(&ehdr->e_phnum); /* Program header table entry count */
- bswap16s(&ehdr->e_shentsize); /* Section header table entry size */
- bswap16s(&ehdr->e_shnum); /* Section header table entry count */
- bswap16s(&ehdr->e_shstrndx); /* Section header string table index */
-}
-
-static void glue(bswap_phdr, SZ)(struct elf_phdr *phdr)
-{
- bswap32s(&phdr->p_type); /* Segment type */
- bswapSZs(&phdr->p_offset); /* Segment file offset */
- bswapSZs(&phdr->p_vaddr); /* Segment virtual address */
- bswapSZs(&phdr->p_paddr); /* Segment physical address */
- bswapSZs(&phdr->p_filesz); /* Segment size in file */
- bswapSZs(&phdr->p_memsz); /* Segment size in memory */
- bswap32s(&phdr->p_flags); /* Segment flags */
- bswapSZs(&phdr->p_align); /* Segment alignment */
-}
-
-static void glue(bswap_shdr, SZ)(struct elf_shdr *shdr)
-{
- bswap32s(&shdr->sh_name);
- bswap32s(&shdr->sh_type);
- bswapSZs(&shdr->sh_flags);
- bswapSZs(&shdr->sh_addr);
- bswapSZs(&shdr->sh_offset);
- bswapSZs(&shdr->sh_size);
- bswap32s(&shdr->sh_link);
- bswap32s(&shdr->sh_info);
- bswapSZs(&shdr->sh_addralign);
- bswapSZs(&shdr->sh_entsize);
-}
-
-static void glue(bswap_sym, SZ)(struct elf_sym *sym)
-{
- bswap32s(&sym->st_name);
- bswapSZs(&sym->st_value);
- bswapSZs(&sym->st_size);
- bswap16s(&sym->st_shndx);
-}
-#endif
-
-static int glue(find_phdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_phdr *phdr, elf_word type)
-{
- int i, retval;
-
- retval = lseek(fd, ehdr->e_phoff, SEEK_SET);
- if (retval < 0)
- return -1;
-
- for (i = 0; i < ehdr->e_phnum; i++) {
- retval = read(fd, phdr, sizeof(*phdr));
- if (retval < 0)
- return -1;
- glue(bswap_phdr, SZ)(phdr);
- if (phdr->p_type == type)
- return 0;
- }
- return -1;
-}
-
-static void * glue(find_shdr, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
-{
- int i, retval;
-
- retval = lseek(fd, ehdr->e_shoff, SEEK_SET);
- if (retval < 0)
- return NULL;
-
- for (i = 0; i < ehdr->e_shnum; i++) {
- retval = read(fd, shdr, sizeof(*shdr));
- if (retval < 0)
- return NULL;
- glue(bswap_shdr, SZ)(shdr);
- if (shdr->sh_type == type)
- return qemu_malloc(shdr->sh_size);
- }
- return NULL;
-}
-
-static void * glue(find_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
-{
- int retval;
-
- retval = lseek(fd, ehdr->e_shoff + sizeof(struct elf_shdr) * symtab->sh_link, SEEK_SET);
- if (retval < 0)
- return NULL;
-
- retval = read(fd, shdr, sizeof(*shdr));
- if (retval < 0)
- return NULL;
- glue(bswap_shdr, SZ)(shdr);
- if (shdr->sh_type == SHT_STRTAB)
- return qemu_malloc(shdr->sh_size);;
- return NULL;
-}
-
-static int glue(read_program, SZ)(int fd, struct elf_phdr *phdr, void *dst, elf_word entry)
-{
- int retval;
- retval = lseek(fd, phdr->p_offset + entry - phdr->p_vaddr, SEEK_SET);
- if (retval < 0)
- return -1;
- return read(fd, dst, phdr->p_filesz);
-}
-
-static int glue(read_section, SZ)(int fd, struct elf_shdr *s, void *dst)
-{
- int retval;
-
- retval = lseek(fd, s->sh_offset, SEEK_SET);
- if (retval < 0)
- return -1;
- retval = read(fd, dst, s->sh_size);
- if (retval < 0)
- return -1;
- return 0;
-}
-
-static void * glue(process_section, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, elf_word type)
-{
- void *dst;
-
- dst = glue(find_shdr, SZ)(ehdr, fd, shdr, type);
- if (!dst)
- goto error;
-
- if (glue(read_section, SZ)(fd, shdr, dst))
- goto error;
- return dst;
- error:
- qemu_free(dst);
- return NULL;
-}
-
-static void * glue(process_strtab, SZ)(struct elfhdr *ehdr, int fd, struct elf_shdr *shdr, struct elf_shdr *symtab)
-{
- void *dst;
-
- dst = glue(find_strtab, SZ)(ehdr, fd, shdr, symtab);
- if (!dst)
- goto error;
-
- if (glue(read_section, SZ)(fd, shdr, dst))
- goto error;
- return dst;
- error:
- qemu_free(dst);
- return NULL;
-}
-
-static void glue(load_symbols, SZ)(struct elfhdr *ehdr, int fd)
-{
- struct elf_shdr symtab, strtab;
- struct elf_sym *syms;
-#if (SZ == 64)
- struct elf32_sym *syms32;
-#endif
- struct syminfo *s;
- int nsyms, i;
- char *str;
-
- /* Symbol table */
- syms = glue(process_section, SZ)(ehdr, fd, &symtab, SHT_SYMTAB);
- if (!syms)
- return;
-
- nsyms = symtab.sh_size / sizeof(struct elf_sym);
-#if (SZ == 64)
- syms32 = qemu_mallocz(nsyms * sizeof(struct elf32_sym));
-#endif
- for (i = 0; i < nsyms; i++) {
- glue(bswap_sym, SZ)(&syms[i]);
-#if (SZ == 64)
- syms32[i].st_name = syms[i].st_name;
- syms32[i].st_info = syms[i].st_info;
- syms32[i].st_other = syms[i].st_other;
- syms32[i].st_shndx = syms[i].st_shndx;
- syms32[i].st_value = syms[i].st_value & 0xffffffff;
- syms32[i].st_size = syms[i].st_size & 0xffffffff;
-#endif
- }
- /* String table */
- str = glue(process_strtab, SZ)(ehdr, fd, &strtab, &symtab);
- if (!str)
- goto error_freesyms;
-
- /* Commit */
- s = qemu_mallocz(sizeof(*s));
-#if (SZ == 64)
- s->disas_symtab = syms32;
- qemu_free(syms);
-#else
- s->disas_symtab = syms;
-#endif
- s->disas_num_syms = nsyms;
- s->disas_strtab = str;
- s->next = syminfos;
- syminfos = s;
- return;
- error_freesyms:
-#if (SZ == 64)
- qemu_free(syms32);
-#endif
- qemu_free(syms);
- return;
-}
diff --git a/hw/magic-load.c b/hw/magic-load.c
deleted file mode 100644
index d5c098fb4..000000000
--- a/hw/magic-load.c
+++ /dev/null
@@ -1,201 +0,0 @@
-#include "vl.h"
-#include "disas.h"
-#include "exec-all.h"
-
-struct exec
-{
- uint32_t a_info; /* Use macros N_MAGIC, etc for access */
- uint32_t a_text; /* length of text, in bytes */
- uint32_t a_data; /* length of data, in bytes */
- uint32_t a_bss; /* length of uninitialized data area, in bytes */
- uint32_t a_syms; /* length of symbol table data in file, in bytes */
- uint32_t a_entry; /* start address */
- uint32_t a_trsize; /* length of relocation info for text, in bytes */
- 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);
- bswap32s(&e->a_text);
- bswap32s(&e->a_data);
- bswap32s(&e->a_bss);
- bswap32s(&e->a_syms);
- bswap32s(&e->a_entry);
- 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
-#define NMAGIC 0410
-#define ZMAGIC 0413
-#define QMAGIC 0314
-#define _N_HDROFF(x) (1024 - sizeof (struct exec))
-#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_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
-#define _N_SEGMENT_ROUND(x) (((x) + TARGET_PAGE_SIZE - 1) & ~(TARGET_PAGE_SIZE - 1))
-
-#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
-
-#define N_DATADDR(x) \
- (N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
- : (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
-
-
-#define ELF_CLASS ELFCLASS32
-#define ELF_DATA ELFDATA2MSB
-#define ELF_ARCH EM_SPARC
-
-#include "elf.h"
-
-#ifndef BSWAP_NEEDED
-#define bswap_ehdr32(e) do { } while (0)
-#define bswap_phdr32(e) do { } while (0)
-#define bswap_shdr32(e) do { } while (0)
-#define bswap_sym32(e) do { } while (0)
-#ifdef TARGET_SPARC64
-#define bswap_ehdr64(e) do { } while (0)
-#define bswap_phdr64(e) do { } while (0)
-#define bswap_shdr64(e) do { } while (0)
-#define bswap_sym64(e) do { } while (0)
-#endif
-#endif
-
-#define SZ 32
-#define elf_word uint32_t
-#define bswapSZs bswap32s
-#include "elf_ops.h"
-
-#ifdef TARGET_SPARC64
-#undef elfhdr
-#undef elf_phdr
-#undef elf_shdr
-#undef elf_sym
-#undef elf_note
-#undef elf_word
-#undef bswapSZs
-#undef SZ
-#define elfhdr elf64_hdr
-#define elf_phdr elf64_phdr
-#define elf_note elf64_note
-#define elf_shdr elf64_shdr
-#define elf_sym elf64_sym
-#define elf_word uint64_t
-#define bswapSZs bswap64s
-#define SZ 64
-#include "elf_ops.h"
-#endif
-
-int load_elf(const char *filename, uint8_t *addr)
-{
- struct elf32_hdr ehdr;
- int retval, fd;
- Elf32_Half machine;
-
- fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0)
- goto error;
-
- retval = read(fd, &ehdr, sizeof(ehdr));
- if (retval < 0)
- goto error;
-
- if (ehdr.e_ident[0] != 0x7f || ehdr.e_ident[1] != 'E'
- || ehdr.e_ident[2] != 'L' || ehdr.e_ident[3] != 'F')
- goto error;
- machine = tswap16(ehdr.e_machine);
- if (machine == EM_SPARC || machine == EM_SPARC32PLUS) {
- struct elf32_phdr phdr;
-
- bswap_ehdr32(&ehdr);
-
- if (find_phdr32(&ehdr, fd, &phdr, PT_LOAD))
- goto error;
- retval = read_program32(fd, &phdr, addr, ehdr.e_entry);
- if (retval < 0)
- goto error;
- load_symbols32(&ehdr, fd);
- }
-#ifdef TARGET_SPARC64
- else if (machine == EM_SPARCV9) {
- struct elf64_hdr ehdr64;
- struct elf64_phdr phdr;
-
- lseek(fd, 0, SEEK_SET);
-
- retval = read(fd, &ehdr64, sizeof(ehdr64));
- if (retval < 0)
- goto error;
-
- bswap_ehdr64(&ehdr64);
-
- if (find_phdr64(&ehdr64, fd, &phdr, PT_LOAD))
- goto error;
- retval = read_program64(fd, &phdr, phys_ram_base + ehdr64.e_entry, ehdr64.e_entry);
- if (retval < 0)
- goto error;
- load_symbols64(&ehdr64, fd);
- }
-#endif
-
- close(fd);
- return retval;
- error:
- close(fd);
- return -1;
-}
-
-int load_aout(const char *filename, uint8_t *addr)
-{
- int fd, size, ret;
- struct exec e;
- uint32_t magic;
-
- fd = open(filename, O_RDONLY | O_BINARY);
- if (fd < 0)
- return -1;
-
- size = read(fd, &e, sizeof(e));
- if (size < 0)
- goto fail;
-
- bswap_ahdr(&e);
-
- magic = N_MAGIC(e);
- switch (magic) {
- case ZMAGIC:
- case QMAGIC:
- case OMAGIC:
- lseek(fd, N_TXTOFF(e), SEEK_SET);
- size = read(fd, addr, e.a_text + e.a_data);
- if (size < 0)
- goto fail;
- break;
- case NMAGIC:
- lseek(fd, N_TXTOFF(e), SEEK_SET);
- size = read(fd, addr, e.a_text);
- if (size < 0)
- goto fail;
- ret = read(fd, addr + N_DATADDR(e), e.a_data);
- if (ret < 0)
- goto fail;
- size += ret;
- break;
- default:
- goto fail;
- }
- close(fd);
- return size;
- fail:
- close(fd);
- return -1;
-}
-
diff --git a/hw/sun4m.c b/hw/sun4m.c
index 435ac02bd..014ed0926 100644
--- a/hw/sun4m.c
+++ b/hw/sun4m.c
@@ -26,6 +26,7 @@
#define KERNEL_LOAD_ADDR 0x00004000
#define CMDLINE_ADDR 0x007ff000
#define INITRD_LOAD_ADDR 0x00800000
+#define PROM_SIZE_MAX (256 * 1024)
#define PROM_ADDR 0xffd00000
#define PROM_FILENAMEB "proll.bin"
#define PROM_FILENAMEE "proll.elf"
@@ -263,9 +264,12 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
slavio_misc = slavio_misc_init(PHYS_JJ_SLAVIO, PHYS_JJ_ME_IRQ);
prom_offset = ram_size + vram_size;
+ cpu_register_physical_memory(PROM_ADDR,
+ (PROM_SIZE_MAX + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK,
+ prom_offset | IO_MEM_ROM);
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
- ret = load_elf(buf, phys_ram_base + prom_offset);
+ ret = load_elf(buf, 0);
if (ret < 0) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
ret = load_image(buf, phys_ram_base + prom_offset);
@@ -275,12 +279,10 @@ static void sun4m_init(int ram_size, int vga_ram_size, int boot_device,
buf);
exit(1);
}
- cpu_register_physical_memory(PROM_ADDR, (ret + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
- prom_offset | IO_MEM_ROM);
kernel_size = 0;
if (linux_boot) {
- kernel_size = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+ kernel_size = load_elf(kernel_filename, -0xf0000000);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0)
diff --git a/hw/sun4u.c b/hw/sun4u.c
index 0cf538179..bb40697c4 100644
--- a/hw/sun4u.c
+++ b/hw/sun4u.c
@@ -27,6 +27,7 @@
#define KERNEL_LOAD_ADDR 0x00404000
#define CMDLINE_ADDR 0x003ff000
#define INITRD_LOAD_ADDR 0x00300000
+#define PROM_SIZE_MAX (256 * 1024)
#define PROM_ADDR 0x1fff0000000ULL
#define APB_SPECIAL_BASE 0x1fe00000000ULL
#define APB_MEM_BASE 0x1ff00000000ULL
@@ -277,9 +278,12 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
cpu_register_physical_memory(0, ram_size, 0);
prom_offset = ram_size + vga_ram_size;
+ cpu_register_physical_memory(PROM_ADDR,
+ (PROM_SIZE_MAX + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
+ prom_offset | IO_MEM_ROM);
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEE);
- ret = load_elf(buf, phys_ram_base + prom_offset);
+ ret = load_elf(buf, 0);
if (ret < 0) {
snprintf(buf, sizeof(buf), "%s/%s", bios_dir, PROM_FILENAMEB);
ret = load_image(buf, phys_ram_base + prom_offset);
@@ -289,13 +293,12 @@ static void sun4u_init(int ram_size, int vga_ram_size, int boot_device,
buf);
exit(1);
}
- cpu_register_physical_memory(PROM_ADDR, (ret + TARGET_PAGE_SIZE) & TARGET_PAGE_MASK,
- prom_offset | IO_MEM_ROM);
kernel_size = 0;
initrd_size = 0;
if (linux_boot) {
- kernel_size = load_elf(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
+ /* XXX: put correct offset */
+ kernel_size = load_elf(kernel_filename, 0);
if (kernel_size < 0)
kernel_size = load_aout(kernel_filename, phys_ram_base + KERNEL_LOAD_ADDR);
if (kernel_size < 0)