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:
Mark Cave-Ayland
2010-03-28 23:47:36 +00:00
committed by Mark Cave-Ayland
parent c60fad9646
commit d4451ae216
15 changed files with 276 additions and 194 deletions

View File

@@ -13,8 +13,8 @@
<object source="blk.c" flags="-DBOOTSTRAP"/>
<object source="plugins.c" flags="-DBOOTSTRAP" condition="PLUGINS"/>
<external-object source="libbootstrap.a"/>
<external-object source="libopenbios.a"/>
<external-object source="libpackages.a"/>
<external-object source="libopenbios.a"/>
<external-object source="libdrivers.a"/>
<external-object source="libfs.a"/>
<external-object source="liblibc.a"/>

View File

@@ -51,6 +51,8 @@
static void exit_terminal(void);
void boot(void);
unsigned long virt_offset = 0;
/* local variables */
static ucell *memory;

View File

@@ -22,5 +22,6 @@
extern int is_aout(struct exec *ehdr);
extern int aout_load(struct sys_info *info, const char *filename);
extern void aout_init_program(void);
#endif /* _H_AOUTLOAD */

View File

@@ -22,6 +22,7 @@
#include "libopenbios/sys_info.h"
extern int elf_load(struct sys_info *info, const char *filename, const char *cmdline, void **boot_notes);
extern void elf_init_program(void);
extern int is_elf(Elf_ehdr *ehdr);
extern int find_elf(Elf_ehdr *ehdr);

View File

@@ -19,5 +19,6 @@
extern int is_fcode(unsigned char *fcode);
extern int fcode_load(const char *filename);
extern void fcode_init_program(void);
#endif /* _H_FCODELOAD */

View File

@@ -19,5 +19,6 @@
extern int is_forth(char *forth);
extern int forth_load(const char *filename);
extern void forth_init_program(void);
#endif /* _H_FORTHLOAD */

View File

@@ -0,0 +1,27 @@
/*
* Creation Date: <2010/03/22 18:00:00 mcayland>
* Time-stamp: <2010/03/22 18:00:00 mcayland>
*
* <xcoff_load.h>
*
* XCOFF loader
*
* Copyright (C) 2010 Mark Cave-Ayland (mark.cave-ayland@siriusit.co.uk)
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation
*
*/
#ifndef _H_XCOFFLOAD
#define _H_XCOFFLOAD
#include "arch/common/xcoff.h"
#include "libopenbios/sys_info.h"
extern int is_xcoff(COFF_filehdr_t *fhdr);
extern int xcoff_load(struct sys_info *info, const char *filename);
extern void xcoff_init_program(void);
#endif /* _H_XCOFFLOAD */

View File

@@ -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 !");
}

View File

@@ -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">

View File

@@ -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 !");
}

View File

@@ -13,7 +13,8 @@
static int fd;
int is_fcode(unsigned char *fcode)
int
is_fcode(unsigned char *fcode)
{
return (fcode[0] == 0xf0 // start0
|| fcode[0] == 0xf1 // start1
@@ -22,7 +23,8 @@ int is_fcode(unsigned char *fcode)
|| 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");
}

View File

@@ -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
View 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 !");
}

View File

@@ -16,81 +16,13 @@
#include "config.h"
#include "libopenbios/bindings.h"
#include "libopenbios/elf_load.h"
#include "packages.h"
#include "libopenbios/ofmem.h"
#include "arch/common/elf.h"
#include "asm/elf.h"
/* TODO: manage ELF notes section */
//#define DEBUG_ELF
#ifdef DEBUG_ELF
#define DPRINTF(fmt, args...) \
do { printk("%s: " fmt, __func__ , ##args); } while (0)
#else
#define DPRINTF(fmt, args...) \
do { } while (0)
#endif
DECLARE_NODE(elf_loader, INSTALL_OPEN, 0, "+/packages/elf-loader" );
#ifdef CONFIG_PPC
extern void flush_icache_range( char *start, char *stop );
#endif
static void
elf_loader_init_program( void *dummy )
{
char *base;
int i;
Elf_ehdr *ehdr;
Elf_phdr *phdr;
size_t size;
char *addr;
cell tmp;
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++) {
DPRINTF("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 );
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 !");
}
NODE_METHODS( elf_loader ) = {
{ "init-program", elf_loader_init_program },
{ "init-program", elf_init_program },
};
void elf_loader_init( void )

View File

@@ -16,126 +16,13 @@
#include "config.h"
#include "libopenbios/bindings.h"
#include "libopenbios/xcoff_load.h"
#include "packages.h"
#include "libopenbios/ofmem.h"
#include "arch/common/xcoff.h"
//#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
DECLARE_NODE(xcoff_loader, INSTALL_OPEN, 0, "+/packages/xcoff-loader" );
#ifdef CONFIG_PPC
extern void flush_icache_range( char *start, char *stop );
#endif
static void
xcoff_loader_init_program( void *dummy )
{
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 (fhdr->f_magic != U802WRMAGIC &&
fhdr->f_magic != U802ROMAGIC &&
fhdr->f_magic != U802TOCMAGIC &&
fhdr->f_magic != U802TOMAGIC) {
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 !");
}
NODE_METHODS( xcoff_loader ) = {
{ "init-program", xcoff_loader_init_program },
{ "init-program", xcoff_init_program },
};
void xcoff_loader_init( void )