Author: stepan Date: 2006-05-15 10:17:51 +0200 (Mon, 15 May 2006) New Revision: 18
Added: openbios-devel/arch/sparc32/aoutload.c openbios-devel/include/a.out.h openbios-devel/include/sparc32/a.out.h Modified: openbios-devel/arch/sparc32/boot.c openbios-devel/arch/sparc32/build.xml openbios-devel/arch/sparc32/elfload.c openbios-devel/arch/sparc32/romvec.c openbios-devel/arch/sparc32/tree.fs openbios-devel/config/examples/cross-sparc32_config.xml openbios-devel/config/examples/sparc32_config.xml Log: sparc32 merge
Added: openbios-devel/arch/sparc32/aoutload.c =================================================================== --- openbios-devel/arch/sparc32/aoutload.c (rev 0) +++ openbios-devel/arch/sparc32/aoutload.c 2006-05-15 08:17:51 UTC (rev 18) @@ -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; +}
Modified: openbios-devel/arch/sparc32/boot.c =================================================================== --- openbios-devel/arch/sparc32/boot.c 2006-05-14 11:22:41 UTC (rev 17) +++ openbios-devel/arch/sparc32/boot.c 2006-05-15 08:17:51 UTC (rev 18) @@ -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); @@ -37,8 +38,9 @@ printk("[sparc] Booting file '%s' with parameters '%s'\n",path, param);
if (elf_load(&sys_info, path, param) == LOADER_NOT_SUPPORT) - if (linux_load(&sys_info, path, param) == LOADER_NOT_SUPPORT) - printk("Unsupported image format\n"); + 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); }
Modified: openbios-devel/arch/sparc32/build.xml =================================================================== --- openbios-devel/arch/sparc32/build.xml 2006-05-14 11:22:41 UTC (rev 17) +++ openbios-devel/arch/sparc32/build.xml 2006-05-15 08:17:51 UTC (rev 18) @@ -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"/>
Modified: openbios-devel/arch/sparc32/elfload.c =================================================================== --- openbios-devel/arch/sparc32/elfload.c 2006-05-14 11:22:41 UTC (rev 17) +++ openbios-devel/arch/sparc32/elfload.c 2006-05-15 08:17:51 UTC (rev 18) @@ -378,7 +378,7 @@ 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); }
Modified: openbios-devel/arch/sparc32/romvec.c =================================================================== --- openbios-devel/arch/sparc32/romvec.c 2006-05-14 11:22:41 UTC (rev 17) +++ openbios-devel/arch/sparc32/romvec.c 2006-05-15 08:17:51 UTC (rev 18) @@ -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 int obp_nbgetchar(void) { - return 0; + return getchar(); }
static int obp_nbputchar(int ch) @@ -214,9 +212,15 @@
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_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,
Modified: openbios-devel/arch/sparc32/tree.fs =================================================================== --- openbios-devel/arch/sparc32/tree.fs 2006-05-14 11:22:41 UTC (rev 17) +++ openbios-devel/arch/sparc32/tree.fs 2006-05-15 08:17:51 UTC (rev 18) @@ -247,3 +247,7 @@ 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 +
Modified: openbios-devel/config/examples/cross-sparc32_config.xml =================================================================== --- openbios-devel/config/examples/cross-sparc32_config.xml 2006-05-14 11:22:41 UTC (rev 17) +++ openbios-devel/config/examples/cross-sparc32_config.xml 2006-05-15 08:17:51 UTC (rev 18) @@ -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"/>
Modified: openbios-devel/config/examples/sparc32_config.xml =================================================================== --- openbios-devel/config/examples/sparc32_config.xml 2006-05-14 11:22:41 UTC (rev 17) +++ openbios-devel/config/examples/sparc32_config.xml 2006-05-15 08:17:51 UTC (rev 18) @@ -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"/>
Added: openbios-devel/include/a.out.h =================================================================== --- openbios-devel/include/a.out.h (rev 0) +++ openbios-devel/include/a.out.h 2006-05-15 08:17:51 UTC (rev 18) @@ -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__ */
Added: openbios-devel/include/sparc32/a.out.h =================================================================== --- openbios-devel/include/sparc32/a.out.h (rev 0) +++ openbios-devel/include/sparc32/a.out.h 2006-05-15 08:17:51 UTC (rev 18) @@ -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__ */