mirror of
https://gitlab.com/qemu-project/openbios.git
synced 2024-02-13 08:34:06 +08:00
Implements XCOFF loader (to be able to boot Apple BootX bootloader)
Signed-off-by: Laurent Vivier <Laurent@vivier.eu> git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@581 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
@@ -180,6 +180,7 @@ constant /Elf32_Ehdr
|
||||
;
|
||||
|
||||
variable elf-entry
|
||||
variable xcoff-entry
|
||||
|
||||
: init-program-elf
|
||||
elf file-type !
|
||||
@@ -302,9 +303,19 @@ variable elf-entry
|
||||
elf file-type @ = if
|
||||
[IFDEF] CONFIG_PPC
|
||||
elf-entry @ " (go)" evaluate
|
||||
[ELSE]
|
||||
." go is not yet implemented"
|
||||
[THEN]
|
||||
else
|
||||
." go is not yet implemented"
|
||||
xcoff file-type @ = if
|
||||
[IFDEF] CONFIG_PPC
|
||||
xcoff-entry @ " (go)" evaluate
|
||||
[ELSE]
|
||||
." go is not yet implemented"
|
||||
[THEN]
|
||||
else
|
||||
." go is not yet implemented"
|
||||
then
|
||||
then
|
||||
;
|
||||
|
||||
|
||||
98
include/openbios/xcoff.h
Normal file
98
include/openbios/xcoff.h
Normal file
@@ -0,0 +1,98 @@
|
||||
#ifndef XCOFF_H
|
||||
#define XCOFF_H
|
||||
|
||||
/* XCOFF executable loader */
|
||||
|
||||
typedef struct COFF_filehdr_t {
|
||||
uint16_t f_magic; /* magic number */
|
||||
uint16_t f_nscns; /* number of sections */
|
||||
uint32_t f_timdat; /* time & date stamp */
|
||||
uint32_t f_symptr; /* file pointer to symtab */
|
||||
uint32_t f_nsyms; /* number of symtab entries */
|
||||
uint16_t f_opthdr; /* sizeof(optional hdr) */
|
||||
uint16_t f_flags; /* flags */
|
||||
} COFF_filehdr_t;
|
||||
|
||||
/* IBM RS/6000 */
|
||||
|
||||
#define U802WRMAGIC 0x02DA /* writeable text segments **chh** */
|
||||
#define U802ROMAGIC 0x02DF /* readonly sharable text segments */
|
||||
#define U802TOCMAGIC 0x02E1 /* readonly text segments and TOC */
|
||||
#define U802TOMAGIC 0x01DF
|
||||
|
||||
/*
|
||||
* Bits for f_flags:
|
||||
*
|
||||
* F_RELFLG relocation info stripped from file
|
||||
* F_EXEC file is executable (i.e. no unresolved external
|
||||
* references)
|
||||
* F_LNNO line numbers stripped from file
|
||||
* F_LSYMS local symbols stripped from file
|
||||
* F_MINMAL this is a minimal object file (".m") output of fextract
|
||||
* F_UPDATE this is a fully bound update file, output of ogen
|
||||
* F_SWABD this file has had its bytes swabbed (in names)
|
||||
* F_AR16WR this file has the byte ordering of an AR16WR
|
||||
* (e.g. 11/70) machine
|
||||
* F_AR32WR this file has the byte ordering of an AR32WR machine
|
||||
* (e.g. vax and iNTEL 386)
|
||||
* F_AR32W this file has the byte ordering of an AR32W machine
|
||||
* (e.g. 3b,maxi)
|
||||
* F_PATCH file contains "patch" list in optional header
|
||||
* F_NODF (minimal file only) no decision functions for
|
||||
* replaced functions
|
||||
*/
|
||||
|
||||
#define COFF_F_RELFLG 0000001
|
||||
#define COFF_F_EXEC 0000002
|
||||
#define COFF_F_LNNO 0000004
|
||||
#define COFF_F_LSYMS 0000010
|
||||
#define COFF_F_MINMAL 0000020
|
||||
#define COFF_F_UPDATE 0000040
|
||||
#define COFF_F_SWABD 0000100
|
||||
#define COFF_F_AR16WR 0000200
|
||||
#define COFF_F_AR32WR 0000400
|
||||
#define COFF_F_AR32W 0001000
|
||||
#define COFF_F_PATCH 0002000
|
||||
#define COFF_F_NODF 0002000
|
||||
|
||||
typedef struct COFF_aouthdr_t {
|
||||
uint16_t magic; /* type of file */
|
||||
uint16_t vstamp; /* version stamp */
|
||||
uint32_t tsize; /* text size in bytes, padded to FW bdry */
|
||||
uint32_t dsize; /* initialized data " " */
|
||||
uint32_t bsize; /* uninitialized data " " */
|
||||
uint32_t entry; /* entry pt. */
|
||||
uint32_t text_start; /* base of text used for this file */
|
||||
uint32_t data_start; /* base of data used for this file */
|
||||
uint32_t o_toc; /* address of TOC */
|
||||
uint16_t o_snentry; /* section number of entry point */
|
||||
uint16_t o_sntext; /* section number of .text section */
|
||||
uint16_t o_sndata; /* section number of .data section */
|
||||
uint16_t o_sntoc; /* section number of TOC */
|
||||
uint16_t o_snloader; /* section number of .loader section */
|
||||
uint16_t o_snbss; /* section number of .bss section */
|
||||
uint16_t o_algntext; /* .text alignment */
|
||||
uint16_t o_algndata; /* .data alignment */
|
||||
uint16_t o_modtype; /* module type (??) */
|
||||
uint16_t o_cputype; /* cpu type */
|
||||
uint32_t o_maxstack; /* max stack size (??) */
|
||||
uint32_t o_maxdata; /* max data size (??) */
|
||||
char o_resv2[12]; /* reserved */
|
||||
} COFF_aouthdr_t;
|
||||
|
||||
#define AOUT_MAGIC 0x010b
|
||||
|
||||
typedef struct COFF_scnhdr_t {
|
||||
char s_name[8]; /* section name */
|
||||
uint32_t s_paddr; /* physical address, aliased s_nlib */
|
||||
uint32_t s_vaddr; /* virtual address */
|
||||
uint32_t s_size; /* section size */
|
||||
uint32_t s_scnptr; /* file ptr to raw data for section */
|
||||
uint32_t s_relptr; /* file ptr to relocation */
|
||||
uint32_t s_lnnoptr; /* file ptr to line numbers */
|
||||
uint16_t s_nreloc; /* number of relocation entries */
|
||||
uint16_t s_nlnno; /* number of line number entries */
|
||||
uint32_t s_flags; /* flags */
|
||||
} COFF_scnhdr_t;
|
||||
|
||||
#endif /* XCOFF_H */
|
||||
@@ -25,6 +25,7 @@
|
||||
<object source="font_8x16.c" condition="FONT_8X16"/>
|
||||
<object source="ofmem_common.c" condition="OFMEM"/>
|
||||
<object source="elf-loader.c" condition="PPC"/>
|
||||
<object source="xcoff-loader.c" condition="PPC"/>
|
||||
</library>
|
||||
|
||||
<dictionary name="openbios" target="forth">
|
||||
|
||||
@@ -44,5 +44,6 @@ modules_init( void )
|
||||
#endif
|
||||
#ifdef CONFIG_PPC
|
||||
elf_loader_init();
|
||||
xcoff_loader_init();
|
||||
#endif
|
||||
}
|
||||
|
||||
@@ -25,5 +25,6 @@ extern void pcparts_init( void );
|
||||
extern void sunparts_init( void );
|
||||
extern void cmdline_init( void );
|
||||
extern void elf_loader_init( void );
|
||||
extern void xcoff_loader_init( void );
|
||||
|
||||
#endif /* _H_MODULES */
|
||||
|
||||
140
modules/xcoff-loader.c
Normal file
140
modules/xcoff-loader.c
Normal file
@@ -0,0 +1,140 @@
|
||||
/*
|
||||
*
|
||||
* <xcoff-loader.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 "openbios/config.h"
|
||||
#include "openbios/bindings.h"
|
||||
#include "modules.h"
|
||||
#include "ofmem.h"
|
||||
|
||||
#include "openbios/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("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 !");
|
||||
}
|
||||
|
||||
NODE_METHODS( xcoff_loader ) = {
|
||||
{ "init-program", xcoff_loader_init_program },
|
||||
};
|
||||
|
||||
void xcoff_loader_init( void )
|
||||
{
|
||||
REGISTER_NODE( xcoff_loader );
|
||||
}
|
||||
Reference in New Issue
Block a user