mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
Move the *_init_program() functions into the main loader source files so that everything is in one place. Part of this
involves taking the existing parts of the XCOFF loader and putting them into a new loader file xcoff_load.c. Also fix a dependency order change these changes introduce when building openbios-unix. Signed-off-by: Mark Cave-Ayland <mark.cave-ayland@siriusit.co.uk> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@720 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
committed by
Mark Cave-Ayland
parent
c60fad9646
commit
d4451ae216
@@ -23,7 +23,8 @@
|
||||
static char *image_name, *image_version;
|
||||
static int fd;
|
||||
|
||||
static int check_mem_ranges(struct sys_info *info,
|
||||
static int
|
||||
check_mem_ranges(struct sys_info *info,
|
||||
unsigned long start,
|
||||
unsigned long size)
|
||||
{
|
||||
@@ -58,16 +59,17 @@ static int check_mem_ranges(struct sys_info *info,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int is_aout(struct exec *ehdr)
|
||||
int
|
||||
is_aout(struct exec *ehdr)
|
||||
{
|
||||
return ((ehdr->a_info & 0xffff) == OMAGIC
|
||||
|| (ehdr->a_info & 0xffff) == NMAGIC
|
||||
|| (ehdr->a_info & 0xffff) == ZMAGIC
|
||||
|| (ehdr->a_info & 0xffff) == QMAGIC);
|
||||
|
||||
}
|
||||
|
||||
int aout_load(struct sys_info *info, const char *filename)
|
||||
int
|
||||
aout_load(struct sys_info *info, const char *filename)
|
||||
{
|
||||
int retval = -1;
|
||||
struct exec ehdr;
|
||||
@@ -154,3 +156,10 @@ out:
|
||||
close_io(fd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
aout_init_program(void)
|
||||
{
|
||||
// Currently not implemented
|
||||
feval("0 state-valid !");
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
<object source="ipchecksum.c"/>
|
||||
<object source="linuxbios_info.c" condition="LINUXBIOS"/>
|
||||
<object source="ofmem_common.c" condition="OFMEM"/>
|
||||
<object source="xcoff_load.c" condition="LOADER_XCOFF"/>
|
||||
</library>
|
||||
|
||||
<dictionary name="openbios" target="forth">
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
#define MAX_HEADERS 0x20
|
||||
#define BS 0x100 /* smallest step used when looking for the ELF header */
|
||||
|
||||
#ifdef CONFIG_PPC
|
||||
extern void flush_icache_range( char *start, char *stop );
|
||||
#endif
|
||||
|
||||
/* FreeBSD and possibly others mask the high 8 bits */
|
||||
#define addr_fixup(addr) ((addr) & 0x00ffffff)
|
||||
|
||||
@@ -362,7 +366,8 @@ elf_readhdrs(int offset, Elf_ehdr *ehdr)
|
||||
return phdr;
|
||||
}
|
||||
|
||||
int elf_load(struct sys_info *info, const char *filename, const char *cmdline, void **boot_notes)
|
||||
int
|
||||
elf_load(struct sys_info *info, const char *filename, const char *cmdline, void **boot_notes)
|
||||
{
|
||||
Elf_ehdr ehdr;
|
||||
Elf_phdr *phdr = NULL;
|
||||
@@ -460,3 +465,55 @@ out:
|
||||
free(image_version);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
elf_init_program(void)
|
||||
{
|
||||
char *base;
|
||||
int i;
|
||||
Elf_ehdr *ehdr;
|
||||
Elf_phdr *phdr;
|
||||
size_t size;
|
||||
char *addr;
|
||||
cell tmp;
|
||||
|
||||
/* TODO: manage ELF notes section */
|
||||
feval("0 state-valid !");
|
||||
feval("load-base");
|
||||
base = (char*)POP();
|
||||
|
||||
ehdr = (Elf_ehdr *)base;
|
||||
phdr = (Elf_phdr *)(base + ehdr->e_phoff);
|
||||
|
||||
for (i = 0; i < ehdr->e_phnum; i++) {
|
||||
|
||||
#if DEBUG
|
||||
debug("filesz: %08lX memsz: %08lX p_offset: %08lX "
|
||||
"p_vaddr %08lX\n",
|
||||
(ulong)phdr[i].p_filesz, (ulong)phdr[i].p_memsz,
|
||||
(ulong)phdr[i].p_offset, (ulong)phdr[i].p_vaddr );
|
||||
#endif
|
||||
|
||||
size = MIN(phdr[i].p_filesz, phdr[i].p_memsz);
|
||||
if (!size)
|
||||
continue;
|
||||
#if 0
|
||||
if( ofmem_claim( phdr[i].p_vaddr, phdr[i].p_memsz, 0 ) == -1 ) {
|
||||
printk("Claim failed!\n");
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
/* Workaround for archs where sizeof(int) != pointer size */
|
||||
tmp = phdr[i].p_vaddr;
|
||||
addr = (char *)tmp;
|
||||
|
||||
memcpy(addr, base + phdr[i].p_offset, size);
|
||||
#ifdef CONFIG_PPC
|
||||
flush_icache_range( addr, addr + size );
|
||||
#endif
|
||||
}
|
||||
/* FIXME: should initialize saved-program-state. */
|
||||
PUSH(ehdr->e_entry);
|
||||
feval("elf-entry !");
|
||||
feval("-1 state-valid !");
|
||||
}
|
||||
|
||||
@@ -13,16 +13,18 @@
|
||||
|
||||
static int fd;
|
||||
|
||||
int is_fcode(unsigned char *fcode)
|
||||
int
|
||||
is_fcode(unsigned char *fcode)
|
||||
{
|
||||
return (fcode[0] == 0xf0 // start0
|
||||
return (fcode[0] == 0xf0 // start0
|
||||
|| fcode[0] == 0xf1 // start1
|
||||
|| fcode[0] == 0xf2 // start2
|
||||
|| fcode[0] == 0xf3 // start4
|
||||
|| fcode[0] == 0xfd); // version1
|
||||
}
|
||||
|
||||
int fcode_load(const char *filename)
|
||||
int
|
||||
fcode_load(const char *filename)
|
||||
{
|
||||
int retval = -1;
|
||||
uint8_t fcode_header[8];
|
||||
@@ -84,3 +86,16 @@ out:
|
||||
close_io(fd);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
fcode_init_program(void)
|
||||
{
|
||||
/* If the payload is Fcode then we execute it immediately */
|
||||
ucell address;
|
||||
|
||||
fword("load-base");
|
||||
address = POP();
|
||||
PUSH(address);
|
||||
PUSH(1);
|
||||
fword("byte-load");
|
||||
}
|
||||
|
||||
@@ -78,3 +78,10 @@ out:
|
||||
// free(forthtext);
|
||||
return retval;
|
||||
}
|
||||
|
||||
void
|
||||
forth_init_program(void)
|
||||
{
|
||||
// Currently not implemented
|
||||
feval("0 state-valid !");
|
||||
}
|
||||
|
||||
141
libopenbios/xcoff_load.c
Normal file
141
libopenbios/xcoff_load.c
Normal file
@@ -0,0 +1,141 @@
|
||||
/*
|
||||
*
|
||||
* <xcoff_load.c>
|
||||
*
|
||||
* XCOFF file loader
|
||||
*
|
||||
* Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu)
|
||||
*
|
||||
* from original XCOFF loader by Steven Noonan <steven@uplinklabs.net>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or
|
||||
* modify it under the terms of the GNU General Public License
|
||||
* version 2
|
||||
*
|
||||
*/
|
||||
|
||||
#include "config.h"
|
||||
#include "libopenbios/bindings.h"
|
||||
#include "libopenbios/xcoff_load.h"
|
||||
|
||||
#include "arch/common/xcoff.h"
|
||||
|
||||
#ifdef CONFIG_PPC
|
||||
extern void flush_icache_range( char *start, char *stop );
|
||||
#endif
|
||||
|
||||
//#define DEBUG_XCOFF
|
||||
|
||||
#ifdef DEBUG_XCOFF
|
||||
#define DPRINTF(fmt, args...) \
|
||||
do { printk("%s: " fmt, __func__ , ##args); } while (0)
|
||||
#else
|
||||
#define DPRINTF(fmt, args...) \
|
||||
do { } while (0)
|
||||
#endif
|
||||
|
||||
int
|
||||
is_xcoff(COFF_filehdr_t *fhdr)
|
||||
{
|
||||
return (fhdr->f_magic == U802WRMAGIC
|
||||
|| fhdr->f_magic == U802ROMAGIC
|
||||
|| fhdr->f_magic == U802TOCMAGIC
|
||||
|| fhdr->f_magic == U802TOMAGIC);
|
||||
}
|
||||
|
||||
int
|
||||
xcoff_load(struct sys_info *info, const char *filename)
|
||||
{
|
||||
// Currently not implemented
|
||||
return LOADER_NOT_SUPPORT;
|
||||
}
|
||||
|
||||
void
|
||||
xcoff_init_program(void)
|
||||
{
|
||||
char *base;
|
||||
COFF_filehdr_t *fhdr;
|
||||
COFF_aouthdr_t *ahdr;
|
||||
COFF_scnhdr_t *shdr;
|
||||
uint32_t offset;
|
||||
int i;
|
||||
|
||||
feval("0 state-valid !");
|
||||
|
||||
feval("load-base");
|
||||
base = (char*)POP();
|
||||
|
||||
fhdr = (COFF_filehdr_t*)base;
|
||||
|
||||
/* Is it an XCOFF file ? */
|
||||
if (!is_xcoff(fhdr)) {
|
||||
DPRINTF("Not a XCOFF file %02x\n", fhdr->f_magic);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Is it executable ? */
|
||||
if (fhdr->f_magic != 0x01DF &&
|
||||
(fhdr->f_flags & COFF_F_EXEC) == 0) {
|
||||
DPRINTF("Not an executable XCOFF file %02x\n", fhdr->f_flags);
|
||||
return;
|
||||
}
|
||||
|
||||
/* Optional header is a.out ? */
|
||||
if (fhdr->f_opthdr != sizeof(COFF_aouthdr_t)) {
|
||||
DPRINTF("AOUT optional error size mismatch in XCOFF file\n");
|
||||
return;
|
||||
}
|
||||
|
||||
ahdr = (COFF_aouthdr_t*)(base + sizeof(COFF_filehdr_t));
|
||||
|
||||
/* check a.out magic number */
|
||||
if (ahdr->magic != AOUT_MAGIC) {
|
||||
DPRINTF("Invalid AOUT optional header\n");
|
||||
return;
|
||||
}
|
||||
|
||||
offset = sizeof(COFF_filehdr_t) + sizeof(COFF_aouthdr_t);
|
||||
|
||||
DPRINTF("XCOFF file with %d sections\n", fhdr->f_nscns);
|
||||
|
||||
for (i = 0; i < fhdr->f_nscns; i++) {
|
||||
|
||||
DPRINTF("Read header at offset %0x\n", offset);
|
||||
|
||||
shdr = (COFF_scnhdr_t*)(base + offset);
|
||||
|
||||
DPRINTF("Initializing '%s' section from %0x %0x to %0x (%0x)\n",
|
||||
shdr->s_name, offset, shdr->s_scnptr,
|
||||
shdr->s_vaddr, shdr->s_size);
|
||||
|
||||
if (strcmp(shdr->s_name, ".text") == 0) {
|
||||
|
||||
memcpy((char*)shdr->s_vaddr, base + shdr->s_scnptr,
|
||||
shdr->s_size);
|
||||
#ifdef CONFIG_PPC
|
||||
flush_icache_range((char*)shdr->s_vaddr,
|
||||
(char*)(shdr->s_vaddr + shdr->s_size));
|
||||
#endif
|
||||
} else if (strcmp(shdr->s_name, ".data") == 0) {
|
||||
|
||||
memcpy((char*)shdr->s_vaddr, base + shdr->s_scnptr,
|
||||
shdr->s_size);
|
||||
|
||||
} else if (strcmp(shdr->s_name, ".bss") == 0) {
|
||||
|
||||
memset((void *)shdr->s_vaddr, 0, shdr->s_size);
|
||||
|
||||
} else {
|
||||
DPRINTF(" Skip '%s' section\n", shdr->s_name);
|
||||
}
|
||||
offset += sizeof(COFF_scnhdr_t);
|
||||
}
|
||||
|
||||
/* FIXME: should initialize saved-program-state. */
|
||||
|
||||
DPRINTF("XCOFF entry point: %x\n", *(uint32_t*)ahdr->entry);
|
||||
PUSH(*(uint32_t*)ahdr->entry);
|
||||
feval("xcoff-entry !");
|
||||
|
||||
feval("-1 state-valid !");
|
||||
}
|
||||
Reference in New Issue
Block a user