Author: blueswirl Date: 2008-07-08 18:02:43 +0200 (Tue, 08 Jul 2008) New Revision: 196
Added: openbios-devel/arch/sparc64/aoutload.c Modified: openbios-devel/arch/sparc64/boot.c openbios-devel/arch/sparc64/boot.h openbios-devel/arch/sparc64/build.xml Log: Add a.out support for SILO
Added: openbios-devel/arch/sparc64/aoutload.c =================================================================== --- openbios-devel/arch/sparc64/aoutload.c (rev 0) +++ openbios-devel/arch/sparc64/aoutload.c 2008-07-08 16:02:43 UTC (rev 196) @@ -0,0 +1,146 @@ +/* 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" +#define CONFIG_SPARC64_PAGE_SIZE_8KB +#include "a.out.h" +#include "sys_info.h" +#include "loadfs.h" +#include "boot.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; + unsigned int offset; + + image_name = image_version = 0; + + if (!file_open(filename)) + goto out; + + for (offset = 0; offset < 16 * 512; offset += 512) { + file_seek(offset); + 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)) + break; + } + + if (N_BADMAG(ehdr)) { + debug("Not a bootable a.out image\n"); + retval = LOADER_NOT_SUPPORT; + goto out; + } + + if (ehdr.a_text == 0x30800007) + ehdr.a_text=64*1024; + + if (N_MAGIC(ehdr) == NMAGIC) { + size = addr_fixup(N_DATADDR(ehdr)) + addr_fixup(ehdr.a_data); + } else { + size = addr_fixup(ehdr.a_text) + addr_fixup(ehdr.a_data); + } + + if (size < 7680) + size = 7680; + + + 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(offset + N_TXTOFF(ehdr)); + + if (N_MAGIC(ehdr) == NMAGIC) { + if ((unsigned long)lfile_read((void *)start, ehdr.a_text) != ehdr.a_text) { + printf("Can't read program text segment (size 0x%lx)\n", ehdr.a_text); + goto out; + } + if ((unsigned long)lfile_read((void *)(start + N_DATADDR(ehdr)), ehdr.a_data) != ehdr.a_data) { + printf("Can't read program data segment (size 0x%lx)\n", ehdr.a_data); + goto out; + } + } else { + if ((unsigned long)lfile_read((void *)start, size) != size) { + printf("Can't read program (size 0x%lx)\n", size); + goto out; + } + } + + debug("Loaded %lu bytes\n", size); + + debug("entry point is %#lx\n", start); + printf("Jumping to entry point...\n"); + +#if 1 + { + int (*entry)(unsigned long p1, unsigned long p2, unsigned long p3, + unsigned long p4, unsigned long p5); + extern int of_client_interface( int *params ); + + entry = (void *) addr_fixup(start); + image_retval = entry(0, 0, 0, 0, (unsigned long)&of_client_interface); + } +#endif + + printf("Image returned with return value %#x\n", image_retval); + retval = 0; + +out: + file_close(); + return retval; +}
Modified: openbios-devel/arch/sparc64/boot.c =================================================================== --- openbios-devel/arch/sparc64/boot.c 2008-07-08 15:59:40 UTC (rev 195) +++ openbios-devel/arch/sparc64/boot.c 2008-07-08 16:02:43 UTC (rev 196) @@ -67,13 +67,15 @@
if (elf_load(&sys_info, path, param) == LOADER_NOT_SUPPORT) - if (linux_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) {
sprintf(altpath, "%s:d", path);
if (elf_load(&sys_info, altpath, param) == LOADER_NOT_SUPPORT) if (linux_load(&sys_info, altpath, param) == LOADER_NOT_SUPPORT) - printk("Unsupported image format\n"); + if (aout_load(&sys_info, altpath, param) == LOADER_NOT_SUPPORT) + printk("Unsupported image format\n"); }
free(path);
Modified: openbios-devel/arch/sparc64/boot.h =================================================================== --- openbios-devel/arch/sparc64/boot.h 2008-07-08 15:59:40 UTC (rev 195) +++ openbios-devel/arch/sparc64/boot.h 2008-07-08 16:02:43 UTC (rev 196) @@ -9,6 +9,7 @@ int forth_load(struct sys_info *info, const char *filename, const char *cmdline); int elf_load(struct sys_info *info, const char *filename, const char *cmdline); int linux_load(struct sys_info *info, const char *file, const char *cmdline); +int aout_load(struct sys_info *info, const char *filename, const char *cmdline);
uint64_t start_elf(uint64_t entry_point, uint64_t param);
Modified: openbios-devel/arch/sparc64/build.xml =================================================================== --- openbios-devel/arch/sparc64/build.xml 2008-07-08 15:59:40 UTC (rev 195) +++ openbios-devel/arch/sparc64/build.xml 2008-07-08 16:02:43 UTC (rev 196) @@ -15,6 +15,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"/> </library>