sparc32 merge

git-svn-id: svn://coreboot.org/openbios/openbios-devel@18 f158a5a8-5612-0410-a976-696ce0be7e32
This commit is contained in:
Stefan Reinauer
2006-05-15 08:17:51 +00:00
parent ebbc76b022
commit 1d33aa0ec0
10 changed files with 532 additions and 10 deletions

133
arch/sparc32/aoutload.c Normal file
View File

@@ -0,0 +1,133 @@
/* a.out boot loader
* As we have seek, this implementation can be straightforward.
* 2003-07 by SONE Takeshi
*/
#include "openbios/config.h"
#include "openbios/kernel.h"
#include "a.out.h"
#include "sys_info.h"
#include "loadfs.h"
#define printf printk
#define debug printk
#define addr_fixup(addr) ((addr) & 0x00ffffff)
static char *image_name, *image_version;
const char *program_name, *program_version;
static int check_mem_ranges(struct sys_info *info,
unsigned long start,
unsigned long size)
{
int j;
unsigned long end;
unsigned long prog_start, prog_end;
struct memrange *mem;
prog_start = virt_to_phys(&_start);
prog_end = virt_to_phys(&_end);
end = start + size;
if (start < prog_start && end > prog_start)
goto conflict;
if (start < prog_end && end > prog_end)
goto conflict;
mem = info->memrange;
for (j = 0; j < info->n_memranges; j++) {
if (mem[j].base <= start && mem[j].base + mem[j].size >= end)
break;
}
if (j >= info->n_memranges)
goto badseg;
return 1;
conflict:
printf("%s occupies [%#lx-%#lx]\n", program_name, prog_start, prog_end);
badseg:
printf("A.out file [%#lx-%#lx] doesn't fit into memory\n", start, end - 1);
return 0;
}
int aout_load(struct sys_info *info, const char *filename, const char *cmdline)
{
int retval = -1;
int image_retval;
struct exec ehdr;
unsigned long start, size;
image_name = image_version = 0;
if (!file_open(filename))
goto out;
if (lfile_read(&ehdr, sizeof ehdr) != sizeof ehdr) {
debug("Can't read a.out header\n");
retval = LOADER_NOT_SUPPORT;
goto out;
}
if (N_BADMAG(ehdr)) {
debug("Not a bootable a.out image\n");
retval = LOADER_NOT_SUPPORT;
goto out;
}
if (N_MAGIC(ehdr) == NMAGIC) {
size = N_DATADDR(ehdr) + ehdr.a_data;
} else {
size = ehdr.a_text + ehdr.a_data;
}
start = 0x4000; // N_TXTADDR(ehdr);
if (!check_mem_ranges(info, start, size))
goto out;
printf("Loading a.out %s...\n", image_name ? image_name : "image");
file_seek(N_TXTOFF(ehdr));
if (N_MAGIC(ehdr) == NMAGIC) {
if (lfile_read(start, ehdr.a_text) != ehdr.a_text) {
printf("Can't read program text segment (size 0x%x)\n", ehdr.a_text);
goto out;
}
if (lfile_read(start + N_DATADDR(ehdr), ehdr.a_data) != ehdr.a_data) {
printf("Can't read program data segment (size 0x%x)\n", ehdr.a_data);
goto out;
}
} else {
if (lfile_read(start, size) != size) {
printf("Can't read program (size 0x%x)\n", size);
goto out;
}
}
debug("Loaded %lu bytes\n", size);
debug("entry point is %#x\n", start);
printf("Jumping to entry point...\n");
#if 1
{
extern unsigned int qemu_mem_size;
void *init_openprom(unsigned long memsize, const char *cmdline, char boot_device);
int (*entry)(const void *romvec, int p2, int p3, int p4, int p5);
const void *romvec;
romvec = init_openprom(qemu_mem_size, cmdline, 'c');
entry = (void *) addr_fixup(start);
image_retval = entry(romvec, 0, 0, 0, 0);
}
#endif
printf("Image returned with return value %#x\n", image_retval);
retval = 0;
out:
return retval;
}

View File

@@ -10,6 +10,7 @@
#include "sys_info.h"
int elf_load(struct sys_info *, const char *filename, const char *cmdline);
int aout_load(struct sys_info *, const char *filename, const char *cmdline);
int linux_load(struct sys_info *, const char *filename, const char *cmdline);
void boot(void);
@@ -38,6 +39,7 @@ void boot(void)
if (elf_load(&sys_info, path, param) == LOADER_NOT_SUPPORT)
if (linux_load(&sys_info, path, param) == LOADER_NOT_SUPPORT)
if (aout_load(&sys_info, path, param) == LOADER_NOT_SUPPORT)
printk("Unsupported image format\n");
free(path);

View File

@@ -18,6 +18,7 @@
<object source="linux_load.c"/>
<object source="sys_info.c"/>
<object source="elfload.c"/>
<object source="aoutload.c"/>
<object source="forthload.c"/>
<object source="loadfs.c"/>
<object source="romvec.c"/>

View File

@@ -378,7 +378,7 @@ int elf_load(struct sys_info *info, const char *filename, const char *cmdline)
int (*entry)(const void *romvec, int p2, int p3, int p4, int p5);
const void *romvec;
romvec = init_openprom(qemu_mem_size, NULL, 'c');
romvec = init_openprom(qemu_mem_size, cmdline, 'c');
entry = (void *) addr_fixup(ehdr.e_entry);
image_retval = entry(romvec, 0, 0, 0, 0);
}

View File

@@ -17,9 +17,7 @@
#include "openbios/kernel.h"
#include "openbios/sysinclude.h"
//#define DEBUG_OBP
#ifdef DEBUG_OBP
#ifdef CONFIG_DEBUG_OBP
#define DPRINTF(fmt, args...) \
do { printk(fmt , ##args); } while (0)
#else
@@ -181,7 +179,7 @@ static const char *obp_nextprop(int node, char *name)
static int obp_nbgetchar(void)
{
return 0;
return getchar();
}
static int obp_nbputchar(int ch)
@@ -214,9 +212,15 @@ static void obp_halt()
static int obp_devopen(char *str)
{
int ret;
DPRINTF("obp_devopen(%s)\n", str);
return 0;
push_str(str);
fword("open-dev");
ret = POP();
return ret;
}
static int obp_devclose(__attribute__((unused)) int dev_desc)
@@ -228,9 +232,19 @@ static int obp_devclose(__attribute__((unused)) int dev_desc)
static int obp_rdblkdev(int dev_desc, int num_blks, int offset, char *buf)
{
DPRINTF("obp_rdblkdev: fd %x, num_blks %d, offset %d, buf 0x%x\n", dev_desc, num_blks, offset, buf);
int ret;
return 0;
DPRINTF("obp_rdblkdev: fd %x, num_blks %d, offset %d, buf 0x%x\n", dev_desc, num_blks, offset, (int)buf);
PUSH((int)buf);
PUSH(offset);
PUSH(num_blks);
push_str("read-blocks");
PUSH(dev_desc);
fword("$call-method");
ret = POP();
return ret;
}
static char *obp_dumb_mmap(char *va, __attribute__((unused)) int which_io,

View File

@@ -247,3 +247,7 @@ new-device
0 encode-int " slave" property
h# 2c encode-int 0 encode-int encode+ " intr" property
finish-device
" /options" find-device
" disk" encode-string " boot-from" property

View File

@@ -28,6 +28,7 @@
<option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
<option name="CONFIG_DEBUG_ESP" type="boolean" value="false"/>
<option name="CONFIG_DEBUG_SUN_PARTS" type="boolean" value="false"/>
<option name="CONFIG_DEBUG_OBP" type="boolean" value="false"/>
<option name="CONFIG_SERIAL_PORT" type="integer" value="0"/>
<option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>

View File

@@ -28,6 +28,7 @@
<option name="CONFIG_DEBUG_CONSOLE_SERIAL" type="boolean" value="true"/>
<option name="CONFIG_DEBUG_ESP" type="boolean" value="false"/>
<option name="CONFIG_DEBUG_SUN_PARTS" type="boolean" value="false"/>
<option name="CONFIG_DEBUG_OBP" type="boolean" value="false"/>
<option name="CONFIG_SERIAL_PORT" type="integer" value="0"/>
<option name="CONFIG_SERIAL_SPEED" type="integer" value="115200"/>

268
include/a.out.h Normal file
View File

@@ -0,0 +1,268 @@
#ifndef __A_OUT_GNU_H__
#define __A_OUT_GNU_H__
#define __GNU_EXEC_MACROS__
#ifndef __STRUCT_EXEC_OVERRIDE__
#include "asm/a.out.h"
#endif /* __STRUCT_EXEC_OVERRIDE__ */
/* these go in the N_MACHTYPE field */
enum machine_type {
#if defined (M_OLDSUN2)
M__OLDSUN2 = M_OLDSUN2,
#else
M_OLDSUN2 = 0,
#endif
#if defined (M_68010)
M__68010 = M_68010,
#else
M_68010 = 1,
#endif
#if defined (M_68020)
M__68020 = M_68020,
#else
M_68020 = 2,
#endif
#if defined (M_SPARC)
M__SPARC = M_SPARC,
#else
M_SPARC = 3,
#endif
/* skip a bunch so we don't run into any of sun's numbers */
M_386 = 100,
M_MIPS1 = 151, /* MIPS R3000/R3000 binary */
M_MIPS2 = 152 /* MIPS R6000/R4000 binary */
};
#if !defined (N_MAGIC)
#define N_MAGIC(exec) ((exec).a_info & 0xffff)
#endif
#define N_MACHTYPE(exec) ((enum machine_type)(((exec).a_info >> 16) & 0xff))
#define N_FLAGS(exec) (((exec).a_info >> 24) & 0xff)
#define N_SET_INFO(exec, magic, type, flags) \
((exec).a_info = ((magic) & 0xffff) \
| (((int)(type) & 0xff) << 16) \
| (((flags) & 0xff) << 24))
#define N_SET_MAGIC(exec, magic) \
((exec).a_info = (((exec).a_info & 0xffff0000) | ((magic) & 0xffff)))
#define N_SET_MACHTYPE(exec, machtype) \
((exec).a_info = \
((exec).a_info&0xff00ffff) | ((((int)(machtype))&0xff) << 16))
#define N_SET_FLAGS(exec, flags) \
((exec).a_info = \
((exec).a_info&0x00ffffff) | (((flags) & 0xff) << 24))
/* Code indicating object file or impure executable. */
#define OMAGIC 0407
/* Code indicating pure executable. */
#define NMAGIC 0410
/* Code indicating demand-paged executable. */
#define ZMAGIC 0413
/* This indicates a demand-paged executable with the header in the text.
The first page is unmapped to help trap NULL pointer references */
#define QMAGIC 0314
/* Code indicating core file. */
#define CMAGIC 0421
#if !defined (N_BADMAG)
#define N_BADMAG(x) (N_MAGIC(x) != OMAGIC \
&& N_MAGIC(x) != NMAGIC \
&& N_MAGIC(x) != ZMAGIC \
&& N_MAGIC(x) != QMAGIC)
#endif
#define _N_HDROFF(x) (1024 - sizeof (struct exec))
#if !defined (N_TXTOFF)
#define N_TXTOFF(x) \
(N_MAGIC(x) == ZMAGIC ? _N_HDROFF((x)) + sizeof (struct exec) : \
(N_MAGIC(x) == QMAGIC ? 0 : sizeof (struct exec)))
#endif
#if !defined (N_DATOFF)
#define N_DATOFF(x) (N_TXTOFF(x) + (x).a_text)
#endif
#if !defined (N_TRELOFF)
#define N_TRELOFF(x) (N_DATOFF(x) + (x).a_data)
#endif
#if !defined (N_DRELOFF)
#define N_DRELOFF(x) (N_TRELOFF(x) + N_TRSIZE(x))
#endif
#if !defined (N_SYMOFF)
#define N_SYMOFF(x) (N_DRELOFF(x) + N_DRSIZE(x))
#endif
#if !defined (N_STROFF)
#define N_STROFF(x) (N_SYMOFF(x) + N_SYMSIZE(x))
#endif
/* Address of text segment in memory after it is loaded. */
#if !defined (N_TXTADDR)
#define N_TXTADDR(x) (N_MAGIC(x) == QMAGIC ? PAGE_SIZE : 0)
#endif
/* Address of data segment in memory after it is loaded.
Note that it is up to you to define SEGMENT_SIZE
on machines not listed here. */
#if defined(vax) || defined(hp300) || defined(pyr)
#define SEGMENT_SIZE page_size
#endif
#ifdef sony
#define SEGMENT_SIZE 0x2000
#endif /* Sony. */
#ifdef is68k
#define SEGMENT_SIZE 0x20000
#endif
#if defined(m68k) && defined(PORTAR)
#define PAGE_SIZE 0x400
#define SEGMENT_SIZE PAGE_SIZE
#endif
#ifdef linux
#include <asm/page.h>
#if defined(__i386__) || defined(__mc68000__)
#define SEGMENT_SIZE 1024
#else
#ifndef SEGMENT_SIZE
#define SEGMENT_SIZE PAGE_SIZE
#endif
#endif
#endif
#define _N_SEGMENT_ROUND(x) (((x) + SEGMENT_SIZE - 1) & ~(SEGMENT_SIZE - 1))
#define _N_TXTENDADDR(x) (N_TXTADDR(x)+(x).a_text)
#ifndef N_DATADDR
#define N_DATADDR(x) \
(N_MAGIC(x)==OMAGIC? (_N_TXTENDADDR(x)) \
: (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
#endif
/* Address of bss segment in memory after it is loaded. */
#if !defined (N_BSSADDR)
#define N_BSSADDR(x) (N_DATADDR(x) + (x).a_data)
#endif
#if !defined (N_NLIST_DECLARED)
struct nlist {
union {
char *n_name;
struct nlist *n_next;
long n_strx;
} n_un;
unsigned char n_type;
char n_other;
short n_desc;
unsigned long n_value;
};
#endif /* no N_NLIST_DECLARED. */
#if !defined (N_UNDF)
#define N_UNDF 0
#endif
#if !defined (N_ABS)
#define N_ABS 2
#endif
#if !defined (N_TEXT)
#define N_TEXT 4
#endif
#if !defined (N_DATA)
#define N_DATA 6
#endif
#if !defined (N_BSS)
#define N_BSS 8
#endif
#if !defined (N_FN)
#define N_FN 15
#endif
#if !defined (N_EXT)
#define N_EXT 1
#endif
#if !defined (N_TYPE)
#define N_TYPE 036
#endif
#if !defined (N_STAB)
#define N_STAB 0340
#endif
/* The following type indicates the definition of a symbol as being
an indirect reference to another symbol. The other symbol
appears as an undefined reference, immediately following this symbol.
Indirection is asymmetrical. The other symbol's value will be used
to satisfy requests for the indirect symbol, but not vice versa.
If the other symbol does not have a definition, libraries will
be searched to find a definition. */
#define N_INDR 0xa
/* The following symbols refer to set elements.
All the N_SET[ATDB] symbols with the same name form one set.
Space is allocated for the set in the text section, and each set
element's value is stored into one word of the space.
The first word of the space is the length of the set (number of elements).
The address of the set is made into an N_SETV symbol
whose name is the same as the name of the set.
This symbol acts like a N_DATA global symbol
in that it can satisfy undefined external references. */
/* These appear as input to LD, in a .o file. */
#define N_SETA 0x14 /* Absolute set element symbol */
#define N_SETT 0x16 /* Text set element symbol */
#define N_SETD 0x18 /* Data set element symbol */
#define N_SETB 0x1A /* Bss set element symbol */
/* This is output from LD. */
#define N_SETV 0x1C /* Pointer to set vector in data area. */
#if !defined (N_RELOCATION_INFO_DECLARED)
/* This structure describes a single relocation to be performed.
The text-relocation section of the file is a vector of these structures,
all of which apply to the text section.
Likewise, the data-relocation section applies to the data section. */
struct relocation_info
{
/* Address (within segment) to be relocated. */
int r_address;
/* The meaning of r_symbolnum depends on r_extern. */
unsigned int r_symbolnum:24;
/* Nonzero means value is a pc-relative offset
and it should be relocated for changes in its own address
as well as for changes in the symbol or section specified. */
unsigned int r_pcrel:1;
/* Length (as exponent of 2) of the field to be relocated.
Thus, a value of 2 indicates 1<<2 bytes. */
unsigned int r_length:2;
/* 1 => relocate with value of symbol.
r_symbolnum is the index of the symbol
in file's the symbol table.
0 => relocate with the address of a segment.
r_symbolnum is N_TEXT, N_DATA, N_BSS or N_ABS
(the N_EXT bit may be set also, but signifies nothing). */
unsigned int r_extern:1;
/* Four bits that aren't used, but when writing an object file
it is desirable to clear them. */
#ifdef NS32K
unsigned r_bsr:1;
unsigned r_disp:1;
unsigned r_pad:2;
#else
unsigned int r_pad:4;
#endif
};
#endif /* no N_RELOCATION_INFO_DECLARED. */
#endif /* __A_OUT_GNU_H__ */

98
include/sparc32/a.out.h Normal file
View File

@@ -0,0 +1,98 @@
/* $Id: a.out.h,v 1.13 2000/01/09 10:46:53 anton Exp $ */
#ifndef __SPARC_A_OUT_H__
#define __SPARC_A_OUT_H__
#define SPARC_PGSIZE 0x2000 /* Thanks to the sun4 architecture... */
#define SEGMENT_SIZE SPARC_PGSIZE /* whee... */
struct exec {
unsigned char a_dynamic:1; /* A __DYNAMIC is in this image */
unsigned char a_toolversion:7;
unsigned char a_machtype;
unsigned short a_info;
unsigned long a_text; /* length of text, in bytes */
unsigned long a_data; /* length of data, in bytes */
unsigned long a_bss; /* length of bss, in bytes */
unsigned long a_syms; /* length of symbol table, in bytes */
unsigned long a_entry; /* where program begins */
unsigned long a_trsize;
unsigned long a_drsize;
};
/* Where in the file does the text information begin? */
#define N_TXTOFF(x) (N_MAGIC(x) == ZMAGIC ? 0 : sizeof (struct exec))
/* Where do the Symbols start? */
#define N_SYMOFF(x) (N_TXTOFF(x) + (x).a_text + \
(x).a_data + (x).a_trsize + \
(x).a_drsize)
/* Where does text segment go in memory after being loaded? */
#define N_TXTADDR(x) (((N_MAGIC(x) == ZMAGIC) && \
((x).a_entry < SPARC_PGSIZE)) ? \
0 : SPARC_PGSIZE)
/* And same for the data segment.. */
#define N_DATADDR(x) (N_MAGIC(x)==OMAGIC ? \
(N_TXTADDR(x) + (x).a_text) \
: (_N_SEGMENT_ROUND (_N_TXTENDADDR(x))))
#define N_TRSIZE(a) ((a).a_trsize)
#define N_DRSIZE(a) ((a).a_drsize)
#define N_SYMSIZE(a) ((a).a_syms)
/*
* Sparc relocation types
*/
enum reloc_type
{
RELOC_8,
RELOC_16,
RELOC_32, /* simplest relocs */
RELOC_DISP8,
RELOC_DISP16,
RELOC_DISP32, /* Disp's (pc-rel) */
RELOC_WDISP30,
RELOC_WDISP22, /* SR word disp's */
RELOC_HI22,
RELOC_22, /* SR 22-bit relocs */
RELOC_13,
RELOC_LO10, /* SR 13&10-bit relocs */
RELOC_SFA_BASE,
RELOC_SFA_OFF13, /* SR S.F.A. relocs */
RELOC_BASE10,
RELOC_BASE13,
RELOC_BASE22, /* base_relative pic */
RELOC_PC10,
RELOC_PC22, /* special pc-rel pic */
RELOC_JMP_TBL, /* jmp_tbl_rel in pic */
RELOC_SEGOFF16, /* ShLib offset-in-seg */
RELOC_GLOB_DAT,
RELOC_JMP_SLOT,
RELOC_RELATIVE /* rtld relocs */
};
/*
* Format of a relocation datum.
*/
struct relocation_info /* used when header.a_machtype == M_SPARC */
{
unsigned long r_address; /* relocation addr */
unsigned int r_index:24; /* segment index or symbol index */
unsigned int r_extern:1; /* if F, r_index==SEG#; if T, SYM idx */
int r_pad:2; /* <unused> */
enum reloc_type r_type:5; /* type of relocation to perform */
long r_addend; /* addend for relocation value */
};
#define N_RELOCATION_INFO_DECLARED 1
#ifdef __KERNEL__
#include <asm/page.h>
#define STACK_TOP (PAGE_OFFSET - PAGE_SIZE)
#endif /* __KERNEL__ */
#endif /* __SPARC_A_OUT_H__ */