summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c')
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c388
1 files changed, 388 insertions, 0 deletions
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c
new file mode 100755
index 0000000..fb3f122
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_ram/src/bcm63xx_ldr_elf.c
@@ -0,0 +1,388 @@
+
+//********** for boot -elf thing from cfe_ldr_elf.c
+/* *********************************************************************
+ * Broadcom Common Firmware Environment (CFE)
+ *
+ * ELF Program Loader File: cfe_ldr_elf.c
+ *
+ * This program parses ELF executables and loads them into memory.
+ *
+ * Author: Mitch Lichtenberg (mpl@broadcom.com)
+ *
+ *********************************************************************
+ *
+ * Copyright 2000,2001,2002,2003
+ * Broadcom Corporation. All rights reserved.
+ *
+ * This software is furnished under license and may be used and
+ * copied only in accordance with the following terms and
+ * conditions. Subject to these conditions, you may download,
+ * copy, install, use, modify and distribute modified or unmodified
+ * copies of this software in source and/or binary form. No title
+ * or ownership is transferred hereby.
+ *
+ * 1) Any source code used, modified or distributed must reproduce
+ * and retain this copyright notice and list of conditions
+ * as they appear in the source file.
+ *
+ * 2) No right is granted to use any trade name, trademark, or
+ * logo of Broadcom Corporation. The "Broadcom Corporation"
+ * name may not be used to endorse or promote products derived
+ * from this software without the prior written permission of
+ * Broadcom Corporation.
+ *
+ * 3) THIS SOFTWARE IS PROVIDED "AS-IS" AND ANY EXPRESS OR
+ * IMPLIED WARRANTIES, INCLUDING BUT NOT LIMITED TO, ANY IMPLIED
+ * WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
+ * PURPOSE, OR NON-INFRINGEMENT ARE DISCLAIMED. IN NO EVENT
+ * SHALL BROADCOM BE LIABLE FOR ANY DAMAGES WHATSOEVER, AND IN
+ * PARTICULAR, BROADCOM SHALL NOT BE LIABLE FOR DIRECT, INDIRECT,
+ * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE
+ * GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR
+ * TORT (INCLUDING NEGLIGENCE OR OTHERWISE), EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ ********************************************************************* */
+
+
+#include "lib_types.h"
+#include "lib_string.h"
+#include "lib_queue.h"
+#include "lib_malloc.h"
+#include "lib_printf.h"
+
+#include "cfe_iocb.h"
+#include "cfe_device.h"
+#include "cfe_console.h"
+#include "cfe_error.h"
+#include "cfe_devfuncs.h"
+#include "cfe_timer.h"
+#include "cfe_mem.h"
+
+#include "cfe.h"
+#include "cfe_loader.h"
+#include "cfe_fileops.h"
+#include "elf.h"
+
+#include "cfe_boot.h"
+
+/* *********************************************************************
+ * Externs
+ ********************************************************************* */
+
+int bcm63xx_cfe_elfload(cfe_loadargs_t *la);
+
+const cfe_loader_t elfloader = {
+ "elf",
+ bcm63xx_cfe_elfload,
+ 0};
+
+/* *********************************************************************
+ * readprogsegment(fsctx,ref,addr,size)
+ *
+ * Read a program segment, generally corresponding to one
+ * section of the file.
+ *
+ * Input parameters:
+ * fsctx - file I/O dispatch
+ * ref - reference data for open file handle
+ * addr - target virtual address
+ * size - size of region to read
+ *
+ * Return value:
+ * Number of bytes copied or <0 if error occured
+ ********************************************************************* */
+
+static int readprogsegment(fileio_ctx_t *fsctx,void *ref,
+ void *addr,int size,int flags)
+{
+ int res;
+
+#ifdef __long64
+ if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size);
+#else
+ if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size);
+#endif
+
+ res = fs_read(fsctx,ref,addr,size);
+
+ if (res < 0) return CFE_ERR_IOERR;
+ if (res != size) return CFE_ERR_BADELFFMT;
+
+ return size;
+}
+
+
+/* *********************************************************************
+ * readclearbss(addr,size)
+ *
+ * Process a BSS section, zeroing memory corresponding to
+ * the BSS.
+ *
+ * Input parameters:
+ * addr - address to zero
+ * size - length of area to zero
+ *
+ * Return value:
+ * number of zeroed bytes or <0 if error occured
+ ********************************************************************* */
+
+static int readclearbss(void *addr,int size,int flags)
+{
+
+#ifdef __long64
+ if (flags & LOADFLG_NOISY) xprintf("0x%016llx/%d ",addr,size);
+#else
+ if (flags & LOADFLG_NOISY) xprintf("0x%x/%d ",addr,size);
+#endif
+
+ if (size > 0) memset(addr,0,size);
+ return size;
+}
+
+
+/* *********************************************************************
+ * elfgetshdr(ops,ref,ep)
+ *
+ * Get a section header from the ELF file
+ *
+ * Input parameters:
+ * ops - file I/O dispatch
+ * ref - reference data for open file
+ * ep - extended header info
+ *
+ * Return value:
+ * copy of section header (malloc'd) or NULL if no memory
+ ********************************************************************* */
+
+static Elf32_Shdr *elfgetshdr(fileio_ctx_t *fsctx,void *ref,Elf32_Ehdr *ep)
+{
+ Elf32_Shdr *shtab;
+ unsigned size = ep->e_shnum * sizeof(Elf32_Shdr);
+
+ shtab = (Elf32_Shdr *) KMALLOC(size,0);
+ if (!shtab) {
+ return NULL;
+ }
+
+ if (fs_seek(fsctx,ref,ep->e_shoff,FILE_SEEK_BEGINNING) != ep->e_shoff ||
+ fs_read(fsctx,ref,(uint8_t *)shtab,size) != size) {
+ KFREE(shtab);
+ return NULL;
+ }
+
+ return (shtab);
+}
+
+/* *********************************************************************
+ * elfload_internal(ops,ref,entrypt,flags)
+ *
+ * Read an ELF file (main routine)
+ *
+ * Input parameters:
+ * ops - file I/O dispatch
+ * ref - open file handle
+ * entrypt - filled in with entry vector
+ * flags - generic boot flags
+ *
+ * Return value:
+ * 0 if ok
+ * else error code
+ ********************************************************************* */
+
+static int elfload_internal(fileio_ctx_t *fsctx,void *ref,
+ long *entrypt,int flags)
+{
+ Elf32_Ehdr *ep;
+ Elf32_Phdr *phtab = 0;
+ Elf32_Shdr *shtab = 0;
+ unsigned int nbytes;
+ int i;
+ int res;
+ Elf32_Ehdr ehdr;
+
+ ep = &ehdr;
+ if (fs_read(fsctx,ref,(uint8_t *) ep,sizeof(*ep)) != sizeof(*ep)) {
+ return CFE_ERR_IOERR;
+ }
+
+ /* check header validity */
+ if (ep->e_ident[EI_MAG0] != ELFMAG0 ||
+ ep->e_ident[EI_MAG1] != ELFMAG1 ||
+ ep->e_ident[EI_MAG2] != ELFMAG2 ||
+ ep->e_ident[EI_MAG3] != ELFMAG3) {
+ return CFE_ERR_NOTELF;
+ }
+
+ if (ep->e_ident[EI_CLASS] != ELFCLASS32) return CFE_ERR_NOT32BIT;
+
+#ifdef __MIPSEB
+ if (ep->e_ident[EI_DATA] != ELFDATA2MSB) return CFE_ERR_WRONGENDIAN; /* big endian */
+#endif
+#ifdef __MIPSEL
+ if (ep->e_ident[EI_DATA] != ELFDATA2LSB) return CFE_ERR_WRONGENDIAN; /* little endian */
+#endif
+
+ if (ep->e_ident[EI_VERSION] != EV_CURRENT) return CFE_ERR_BADELFVERS;
+ if (ep->e_machine != EM_MIPS) return CFE_ERR_NOTMIPS;
+
+ /* Is there a program header? */
+ if (ep->e_phoff == 0 || ep->e_phnum == 0 ||
+ ep->e_phentsize != sizeof(Elf32_Phdr)) {
+ return CFE_ERR_BADELFFMT;
+ }
+
+ /* Load program header */
+ nbytes = ep->e_phnum * sizeof(Elf32_Phdr);
+ phtab = (Elf32_Phdr *) KMALLOC(nbytes,0);
+ if (!phtab) {
+ return CFE_ERR_NOMEM;
+ }
+
+ if (fs_seek(fsctx,ref,ep->e_phoff,FILE_SEEK_BEGINNING) != ep->e_phoff ||
+ fs_read(fsctx,ref,(uint8_t *)phtab,nbytes) != nbytes) {
+ KFREE(phtab);
+ return CFE_ERR_IOERR;
+ }
+
+ /*
+ * From now on we've got no guarantee about the file order,
+ * even where the section header is. Hopefully most linkers
+ * will put the section header after the program header, when
+ * they know that the executable is not demand paged. We assume
+ * that the symbol and string tables always follow the program
+ * segments.
+ */
+
+ /* read section table (if before first program segment) */
+ if (ep->e_shoff < phtab[0].p_offset) {
+ shtab = elfgetshdr(fsctx,ref,ep);
+ }
+
+ /* load program segments */
+ /* We cope with a badly sorted program header, as produced by
+ * older versions of the GNU linker, by loading the segments
+ * in file offset order, not in program header order. */
+
+ while (1) {
+ Elf32_Off lowest_offset = ~0;
+ Elf32_Phdr *ph = 0;
+
+ /* find nearest loadable segment */
+ for (i = 0; i < ep->e_phnum; i++)
+ if ((phtab[i].p_type == PT_LOAD) && (phtab[i].p_offset < lowest_offset)) {
+ ph = &phtab[i];
+ lowest_offset = ph->p_offset;
+ }
+ if (!ph) {
+ break; /* none found, finished */
+ }
+ /* load the segment */
+ if (ph->p_filesz) {
+ if (fs_seek(fsctx,ref,ph->p_offset,FILE_SEEK_BEGINNING) != ph->p_offset) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return CFE_ERR_BADELFFMT;
+ }
+ res = readprogsegment(fsctx,ref,
+ (void *)(intptr_t)(signed)ph->p_vaddr,
+ ph->p_filesz,flags);
+ if (res != ph->p_filesz) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return res;
+ }
+ }
+ if (ph->p_filesz < ph->p_memsz) {
+ res = readclearbss((void *)(intptr_t)(signed)ph->p_vaddr + ph->p_filesz,
+ ph->p_memsz - ph->p_filesz,flags);
+ if (res < 0) {
+ if (shtab) KFREE(shtab);
+ KFREE(phtab);
+ return res;
+ }
+ }
+
+ ph->p_type = PT_NULL; /* remove from consideration */
+ }
+
+ KFREE(phtab);
+
+ *entrypt = (intptr_t)ep->e_entry; /* return entry point */
+ return 0;
+}
+
+
+
+/* *********************************************************************
+ * cfe_elfload(ops,file,flags)
+ *
+ * Read an ELF file (main entry point)
+ *
+ * Input parameters:
+ * ops - fileio dispatch
+ * file - name of file to read
+ * ept - where to put entry point
+ * flags - load flags
+ *
+ * Return value:
+ * 0 if ok, else error code
+ ********************************************************************* */
+
+int bcm63xx_cfe_elfload(cfe_loadargs_t *la)
+{
+ fileio_ctx_t *fsctx;
+ void *ref;
+ int res;
+
+ /*
+ * Look up the file system type and get a context
+ */
+
+
+ res = fs_init(la->la_filesys,&fsctx,la->la_device);
+ if (res != 0) {
+ return res;
+ }
+
+ /*
+ * Turn on compression if we're doing that.
+ */
+
+ if (la->la_flags & LOADFLG_COMPRESSED) {
+ res = fs_hook(fsctx,"z");
+ if (res != 0) {
+ return res;
+ }
+ }
+
+ /*
+ * Open the remote file
+ */
+
+ res = fs_open(fsctx,&ref,la->la_filename,FILE_MODE_READ);
+ if (res != 0) {
+ fs_uninit(fsctx);
+ return CFE_ERR_FILENOTFOUND;
+ }
+
+ /*
+ * Load the image.
+ */
+
+ la->la_entrypt = 0;
+ res = elfload_internal(fsctx,ref,&(la->la_entrypt),la->la_flags);
+
+ /*
+ * All done, release resources
+ */
+
+ fs_close(fsctx,ref);
+ fs_uninit(fsctx);
+
+ return res;
+}
+
+