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
@@ -13,8 +13,8 @@
|
|||||||
<object source="blk.c" flags="-DBOOTSTRAP"/>
|
<object source="blk.c" flags="-DBOOTSTRAP"/>
|
||||||
<object source="plugins.c" flags="-DBOOTSTRAP" condition="PLUGINS"/>
|
<object source="plugins.c" flags="-DBOOTSTRAP" condition="PLUGINS"/>
|
||||||
<external-object source="libbootstrap.a"/>
|
<external-object source="libbootstrap.a"/>
|
||||||
<external-object source="libopenbios.a"/>
|
|
||||||
<external-object source="libpackages.a"/>
|
<external-object source="libpackages.a"/>
|
||||||
|
<external-object source="libopenbios.a"/>
|
||||||
<external-object source="libdrivers.a"/>
|
<external-object source="libdrivers.a"/>
|
||||||
<external-object source="libfs.a"/>
|
<external-object source="libfs.a"/>
|
||||||
<external-object source="liblibc.a"/>
|
<external-object source="liblibc.a"/>
|
||||||
|
|||||||
@@ -51,6 +51,8 @@
|
|||||||
static void exit_terminal(void);
|
static void exit_terminal(void);
|
||||||
void boot(void);
|
void boot(void);
|
||||||
|
|
||||||
|
unsigned long virt_offset = 0;
|
||||||
|
|
||||||
/* local variables */
|
/* local variables */
|
||||||
|
|
||||||
static ucell *memory;
|
static ucell *memory;
|
||||||
|
|||||||
@@ -22,5 +22,6 @@
|
|||||||
|
|
||||||
extern int is_aout(struct exec *ehdr);
|
extern int is_aout(struct exec *ehdr);
|
||||||
extern int aout_load(struct sys_info *info, const char *filename);
|
extern int aout_load(struct sys_info *info, const char *filename);
|
||||||
|
extern void aout_init_program(void);
|
||||||
|
|
||||||
#endif /* _H_AOUTLOAD */
|
#endif /* _H_AOUTLOAD */
|
||||||
|
|||||||
@@ -22,6 +22,7 @@
|
|||||||
#include "libopenbios/sys_info.h"
|
#include "libopenbios/sys_info.h"
|
||||||
|
|
||||||
extern int elf_load(struct sys_info *info, const char *filename, const char *cmdline, void **boot_notes);
|
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 is_elf(Elf_ehdr *ehdr);
|
||||||
extern int find_elf(Elf_ehdr *ehdr);
|
extern int find_elf(Elf_ehdr *ehdr);
|
||||||
|
|
||||||
|
|||||||
@@ -19,5 +19,6 @@
|
|||||||
|
|
||||||
extern int is_fcode(unsigned char *fcode);
|
extern int is_fcode(unsigned char *fcode);
|
||||||
extern int fcode_load(const char *filename);
|
extern int fcode_load(const char *filename);
|
||||||
|
extern void fcode_init_program(void);
|
||||||
|
|
||||||
#endif /* _H_FCODELOAD */
|
#endif /* _H_FCODELOAD */
|
||||||
|
|||||||
@@ -19,5 +19,6 @@
|
|||||||
|
|
||||||
extern int is_forth(char *forth);
|
extern int is_forth(char *forth);
|
||||||
extern int forth_load(const char *filename);
|
extern int forth_load(const char *filename);
|
||||||
|
extern void forth_init_program(void);
|
||||||
|
|
||||||
#endif /* _H_FORTHLOAD */
|
#endif /* _H_FORTHLOAD */
|
||||||
|
|||||||
27
include/libopenbios/xcoff_load.h
Normal file
27
include/libopenbios/xcoff_load.h
Normal 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 */
|
||||||
@@ -23,7 +23,8 @@
|
|||||||
static char *image_name, *image_version;
|
static char *image_name, *image_version;
|
||||||
static int fd;
|
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 start,
|
||||||
unsigned long size)
|
unsigned long size)
|
||||||
{
|
{
|
||||||
@@ -58,16 +59,17 @@ static int check_mem_ranges(struct sys_info *info,
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int is_aout(struct exec *ehdr)
|
int
|
||||||
|
is_aout(struct exec *ehdr)
|
||||||
{
|
{
|
||||||
return ((ehdr->a_info & 0xffff) == OMAGIC
|
return ((ehdr->a_info & 0xffff) == OMAGIC
|
||||||
|| (ehdr->a_info & 0xffff) == NMAGIC
|
|| (ehdr->a_info & 0xffff) == NMAGIC
|
||||||
|| (ehdr->a_info & 0xffff) == ZMAGIC
|
|| (ehdr->a_info & 0xffff) == ZMAGIC
|
||||||
|| (ehdr->a_info & 0xffff) == QMAGIC);
|
|| (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;
|
int retval = -1;
|
||||||
struct exec ehdr;
|
struct exec ehdr;
|
||||||
@@ -154,3 +156,10 @@ out:
|
|||||||
close_io(fd);
|
close_io(fd);
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
aout_init_program(void)
|
||||||
|
{
|
||||||
|
// Currently not implemented
|
||||||
|
feval("0 state-valid !");
|
||||||
|
}
|
||||||
|
|||||||
@@ -14,6 +14,7 @@
|
|||||||
<object source="ipchecksum.c"/>
|
<object source="ipchecksum.c"/>
|
||||||
<object source="linuxbios_info.c" condition="LINUXBIOS"/>
|
<object source="linuxbios_info.c" condition="LINUXBIOS"/>
|
||||||
<object source="ofmem_common.c" condition="OFMEM"/>
|
<object source="ofmem_common.c" condition="OFMEM"/>
|
||||||
|
<object source="xcoff_load.c" condition="LOADER_XCOFF"/>
|
||||||
</library>
|
</library>
|
||||||
|
|
||||||
<dictionary name="openbios" target="forth">
|
<dictionary name="openbios" target="forth">
|
||||||
|
|||||||
@@ -19,6 +19,10 @@
|
|||||||
#define MAX_HEADERS 0x20
|
#define MAX_HEADERS 0x20
|
||||||
#define BS 0x100 /* smallest step used when looking for the ELF header */
|
#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 */
|
/* FreeBSD and possibly others mask the high 8 bits */
|
||||||
#define addr_fixup(addr) ((addr) & 0x00ffffff)
|
#define addr_fixup(addr) ((addr) & 0x00ffffff)
|
||||||
|
|
||||||
@@ -362,7 +366,8 @@ elf_readhdrs(int offset, Elf_ehdr *ehdr)
|
|||||||
return phdr;
|
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_ehdr ehdr;
|
||||||
Elf_phdr *phdr = NULL;
|
Elf_phdr *phdr = NULL;
|
||||||
@@ -460,3 +465,55 @@ out:
|
|||||||
free(image_version);
|
free(image_version);
|
||||||
return retval;
|
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;
|
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] == 0xf1 // start1
|
||||||
|| fcode[0] == 0xf2 // start2
|
|| fcode[0] == 0xf2 // start2
|
||||||
|| fcode[0] == 0xf3 // start4
|
|| fcode[0] == 0xf3 // start4
|
||||||
|| fcode[0] == 0xfd); // version1
|
|| fcode[0] == 0xfd); // version1
|
||||||
}
|
}
|
||||||
|
|
||||||
int fcode_load(const char *filename)
|
int
|
||||||
|
fcode_load(const char *filename)
|
||||||
{
|
{
|
||||||
int retval = -1;
|
int retval = -1;
|
||||||
uint8_t fcode_header[8];
|
uint8_t fcode_header[8];
|
||||||
@@ -84,3 +86,16 @@ out:
|
|||||||
close_io(fd);
|
close_io(fd);
|
||||||
return retval;
|
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);
|
// free(forthtext);
|
||||||
return retval;
|
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 !");
|
||||||
|
}
|
||||||
@@ -16,81 +16,13 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "libopenbios/bindings.h"
|
#include "libopenbios/bindings.h"
|
||||||
|
#include "libopenbios/elf_load.h"
|
||||||
#include "packages.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" );
|
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 ) = {
|
NODE_METHODS( elf_loader ) = {
|
||||||
{ "init-program", elf_loader_init_program },
|
{ "init-program", elf_init_program },
|
||||||
};
|
};
|
||||||
|
|
||||||
void elf_loader_init( void )
|
void elf_loader_init( void )
|
||||||
|
|||||||
@@ -16,126 +16,13 @@
|
|||||||
|
|
||||||
#include "config.h"
|
#include "config.h"
|
||||||
#include "libopenbios/bindings.h"
|
#include "libopenbios/bindings.h"
|
||||||
|
#include "libopenbios/xcoff_load.h"
|
||||||
#include "packages.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" );
|
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 ) = {
|
NODE_METHODS( xcoff_loader ) = {
|
||||||
{ "init-program", xcoff_loader_init_program },
|
{ "init-program", xcoff_init_program },
|
||||||
};
|
};
|
||||||
|
|
||||||
void xcoff_loader_init( void )
|
void xcoff_loader_init( void )
|
||||||
|
|||||||
Reference in New Issue
Block a user