From d4451ae21638e1c2f95051b7dbad50531f9dbaae Mon Sep 17 00:00:00 2001 From: Mark Cave-Ayland Date: Sun, 28 Mar 2010 23:47:36 +0000 Subject: [PATCH] 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 git-svn-id: svn://coreboot.org/openbios/trunk/openbios-devel@720 f158a5a8-5612-0410-a976-696ce0be7e32 --- arch/unix/build.xml | 2 +- arch/unix/unix.c | 2 + include/libopenbios/aout_load.h | 1 + include/libopenbios/elf_load.h | 1 + include/libopenbios/fcode_load.h | 1 + include/libopenbios/forth_load.h | 1 + include/libopenbios/xcoff_load.h | 27 ++++++ libopenbios/aout_load.c | 17 +++- libopenbios/build.xml | 1 + libopenbios/elf_load.c | 59 ++++++++++++- libopenbios/fcode_load.c | 21 ++++- libopenbios/forth_load.c | 7 ++ libopenbios/xcoff_load.c | 141 +++++++++++++++++++++++++++++++ packages/elf-loader.c | 72 +--------------- packages/xcoff-loader.c | 117 +------------------------ 15 files changed, 276 insertions(+), 194 deletions(-) create mode 100644 include/libopenbios/xcoff_load.h create mode 100644 libopenbios/xcoff_load.c diff --git a/arch/unix/build.xml b/arch/unix/build.xml index 9866d27..bc0cf9e 100644 --- a/arch/unix/build.xml +++ b/arch/unix/build.xml @@ -13,8 +13,8 @@ - + diff --git a/arch/unix/unix.c b/arch/unix/unix.c index 0b987cb..ec5dd52 100644 --- a/arch/unix/unix.c +++ b/arch/unix/unix.c @@ -51,6 +51,8 @@ static void exit_terminal(void); void boot(void); +unsigned long virt_offset = 0; + /* local variables */ static ucell *memory; diff --git a/include/libopenbios/aout_load.h b/include/libopenbios/aout_load.h index 6ec3950..2a948b6 100644 --- a/include/libopenbios/aout_load.h +++ b/include/libopenbios/aout_load.h @@ -22,5 +22,6 @@ extern int is_aout(struct exec *ehdr); extern int aout_load(struct sys_info *info, const char *filename); +extern void aout_init_program(void); #endif /* _H_AOUTLOAD */ diff --git a/include/libopenbios/elf_load.h b/include/libopenbios/elf_load.h index bdf57e0..f16ff2f 100644 --- a/include/libopenbios/elf_load.h +++ b/include/libopenbios/elf_load.h @@ -22,6 +22,7 @@ #include "libopenbios/sys_info.h" 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 find_elf(Elf_ehdr *ehdr); diff --git a/include/libopenbios/fcode_load.h b/include/libopenbios/fcode_load.h index c9750a6..c2c341a 100644 --- a/include/libopenbios/fcode_load.h +++ b/include/libopenbios/fcode_load.h @@ -19,5 +19,6 @@ extern int is_fcode(unsigned char *fcode); extern int fcode_load(const char *filename); +extern void fcode_init_program(void); #endif /* _H_FCODELOAD */ diff --git a/include/libopenbios/forth_load.h b/include/libopenbios/forth_load.h index 6940cfe..acb01fa 100644 --- a/include/libopenbios/forth_load.h +++ b/include/libopenbios/forth_load.h @@ -19,5 +19,6 @@ extern int is_forth(char *forth); extern int forth_load(const char *filename); +extern void forth_init_program(void); #endif /* _H_FORTHLOAD */ diff --git a/include/libopenbios/xcoff_load.h b/include/libopenbios/xcoff_load.h new file mode 100644 index 0000000..2ec693d --- /dev/null +++ b/include/libopenbios/xcoff_load.h @@ -0,0 +1,27 @@ +/* + * Creation Date: <2010/03/22 18:00:00 mcayland> + * Time-stamp: <2010/03/22 18:00:00 mcayland> + * + * + * + * 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 */ diff --git a/libopenbios/aout_load.c b/libopenbios/aout_load.c index 458850a..5efed60 100644 --- a/libopenbios/aout_load.c +++ b/libopenbios/aout_load.c @@ -23,7 +23,8 @@ static char *image_name, *image_version; 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 size) { @@ -58,16 +59,17 @@ static int check_mem_ranges(struct sys_info *info, return 0; } -int is_aout(struct exec *ehdr) +int +is_aout(struct exec *ehdr) { return ((ehdr->a_info & 0xffff) == OMAGIC || (ehdr->a_info & 0xffff) == NMAGIC || (ehdr->a_info & 0xffff) == ZMAGIC || (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; struct exec ehdr; @@ -154,3 +156,10 @@ out: close_io(fd); return retval; } + +void +aout_init_program(void) +{ + // Currently not implemented + feval("0 state-valid !"); +} diff --git a/libopenbios/build.xml b/libopenbios/build.xml index 76755f0..f466322 100644 --- a/libopenbios/build.xml +++ b/libopenbios/build.xml @@ -14,6 +14,7 @@ + diff --git a/libopenbios/elf_load.c b/libopenbios/elf_load.c index 6afd7af..c6a57f3 100644 --- a/libopenbios/elf_load.c +++ b/libopenbios/elf_load.c @@ -19,6 +19,10 @@ #define MAX_HEADERS 0x20 #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 */ #define addr_fixup(addr) ((addr) & 0x00ffffff) @@ -362,7 +366,8 @@ elf_readhdrs(int offset, Elf_ehdr *ehdr) 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_phdr *phdr = NULL; @@ -460,3 +465,55 @@ out: free(image_version); 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 !"); +} diff --git a/libopenbios/fcode_load.c b/libopenbios/fcode_load.c index 038563c..4ea6d55 100644 --- a/libopenbios/fcode_load.c +++ b/libopenbios/fcode_load.c @@ -13,16 +13,18 @@ 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] == 0xf2 // start2 || fcode[0] == 0xf3 // start4 || fcode[0] == 0xfd); // version1 } -int fcode_load(const char *filename) +int +fcode_load(const char *filename) { int retval = -1; uint8_t fcode_header[8]; @@ -84,3 +86,16 @@ out: close_io(fd); 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"); +} diff --git a/libopenbios/forth_load.c b/libopenbios/forth_load.c index b0ee295..e462e49 100644 --- a/libopenbios/forth_load.c +++ b/libopenbios/forth_load.c @@ -78,3 +78,10 @@ out: // free(forthtext); return retval; } + +void +forth_init_program(void) +{ + // Currently not implemented + feval("0 state-valid !"); +} diff --git a/libopenbios/xcoff_load.c b/libopenbios/xcoff_load.c new file mode 100644 index 0000000..d722be2 --- /dev/null +++ b/libopenbios/xcoff_load.c @@ -0,0 +1,141 @@ +/* + * + * + * + * XCOFF file loader + * + * Copyright (C) 2009 Laurent Vivier (Laurent@vivier.eu) + * + * from original XCOFF loader by Steven Noonan + * + * 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 !"); +} diff --git a/packages/elf-loader.c b/packages/elf-loader.c index 2135c85..1665f0d 100644 --- a/packages/elf-loader.c +++ b/packages/elf-loader.c @@ -16,81 +16,13 @@ #include "config.h" #include "libopenbios/bindings.h" +#include "libopenbios/elf_load.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" ); -#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 ) = { - { "init-program", elf_loader_init_program }, + { "init-program", elf_init_program }, }; void elf_loader_init( void ) diff --git a/packages/xcoff-loader.c b/packages/xcoff-loader.c index 2bcc7d3..5213cc1 100644 --- a/packages/xcoff-loader.c +++ b/packages/xcoff-loader.c @@ -16,126 +16,13 @@ #include "config.h" #include "libopenbios/bindings.h" +#include "libopenbios/xcoff_load.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" ); -#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 ) = { - { "init-program", xcoff_loader_init_program }, + { "init-program", xcoff_init_program }, }; void xcoff_loader_init( void )