Removed the Etherboot-specific ELF-image code and replaced it with a
authorMichael Brown <mcb30@etherboot.org>
Thu, 11 Jan 2007 14:44:03 +0000 (14:44 +0000)
committerMichael Brown <mcb30@etherboot.org>
Thu, 11 Jan 2007 14:44:03 +0000 (14:44 +0000)
generic ELF loader, to be used by the multiboot code.

src/arch/i386/core/elf.c [deleted file]
src/image/elf.c [new file with mode: 0644]
src/include/elf.h
src/include/elf_boot.h [deleted file]

diff --git a/src/arch/i386/core/elf.c b/src/arch/i386/core/elf.c
deleted file mode 100644 (file)
index fbb4032..0000000
+++ /dev/null
@@ -1,136 +0,0 @@
-#include "etherboot.h"
-#include "elf.h"
-#include "memsizes.h"
-
-
-#define NAME "Etherboot"
-
-#if defined(PCBIOS)
-#define FIRMWARE "PCBIOS"
-#endif
-#if defined(LINUXBIOS)
-#define FIRMWARE "LinuxBIOS"
-#endif
-#if !defined(FIRMWARE)
-#error "No BIOS selected"
-#endif
-
-#define SZ(X) ((sizeof(X)+3) & ~3)
-#define CP(D,S) (memcpy(&(D), &(S), sizeof(S)))
-
-struct elf_notes {
-       /* The note header */
-       struct Elf_Bhdr hdr;
-
-       /* First the Fixed sized entries that must be well aligned */
-
-       /* Pointer to bootp data */
-       Elf_Nhdr nf1;
-       char     nf1_name[SZ(EB_PARAM_NOTE)];
-       uint32_t nf1_bootp_data;
-
-       /* Pointer to ELF header */
-       Elf_Nhdr nf2;
-       char     nf2_name[SZ(EB_PARAM_NOTE)];
-       uint32_t nf2_header;
-
-       /* A copy of the i386 memory map */
-       Elf_Nhdr nf3;
-       char     nf3_name[SZ(EB_PARAM_NOTE)];
-       struct meminfo nf3_meminfo;
-
-       /* Then the variable sized data string data where alignment does not matter */
-
-       /* The bootloader name */
-       Elf_Nhdr nv1;
-       char     nv1_desc[SZ(NAME)];
-       /* The bootloader version */
-       Elf_Nhdr nv2;
-       char     nv2_desc[SZ(VERSION)];
-       /* The firmware type */
-       Elf_Nhdr nv3;
-       char     nv3_desc[SZ(FIRMWARE)];
-       /* Name of the loaded image */
-       Elf_Nhdr nv4;
-       char     nv4_loaded_image[128];
-       /* An empty command line */
-       Elf_Nhdr nv5;
-       char     nv5_cmdline[SZ("")];
-};
-
-#define ELF_NOTE_COUNT  (3 + 5)
-
-static struct elf_notes notes;
-struct Elf_Bhdr *prepare_boot_params(void *header)
-{
-       memset(&notes, 0, sizeof(notes));
-       notes.hdr.b_signature = ELF_BHDR_MAGIC;
-       notes.hdr.b_size      = sizeof(notes);
-       notes.hdr.b_checksum  = 0;
-       notes.hdr.b_records   = ELF_NOTE_COUNT;
-
-       /* Initialize the fixed length entries. */
-       notes.nf1.n_namesz = sizeof(EB_PARAM_NOTE);
-       notes.nf1.n_descsz = sizeof(notes.nf1_bootp_data);
-       notes.nf1.n_type   = EB_BOOTP_DATA;
-       CP(notes.nf1_name,   EB_PARAM_NOTE);
-       notes.nf1_bootp_data = virt_to_phys(&bootp_data);
-
-       notes.nf2.n_namesz = sizeof(EB_PARAM_NOTE);
-       notes.nf2.n_descsz = sizeof(notes.nf2_header);
-       notes.nf2.n_type   = EB_HEADER;
-       CP(notes.nf2_name,   EB_PARAM_NOTE);
-       notes.nf2_header   = virt_to_phys(header);
-
-       notes.nf3.n_namesz = sizeof(EB_PARAM_NOTE);
-       notes.nf3.n_descsz = sizeof(notes.nf3_meminfo);
-       notes.nf3.n_type   = EB_I386_MEMMAP;
-       CP(notes.nf3_name,   EB_PARAM_NOTE);
-       memcpy(&notes.nf3_meminfo, &meminfo, sizeof(meminfo));
-
-       /* Initialize the variable length entries */
-       notes.nv1.n_namesz = 0;
-       notes.nv1.n_descsz = sizeof(NAME);
-       notes.nv1.n_type   = EBN_BOOTLOADER_NAME;
-       CP(notes.nv1_desc,   NAME);
-
-       notes.nv2.n_namesz = 0;
-       notes.nv2.n_descsz = sizeof(VERSION);
-       notes.nv2.n_type   = EBN_BOOTLOADER_VERSION;
-       CP(notes.nv2_desc,   VERSION);
-
-       notes.nv3.n_namesz = 0;
-       notes.nv3.n_descsz = sizeof(FIRMWARE);
-       notes.nv3.n_type   = EBN_FIRMWARE_TYPE;
-       CP(notes.nv3_desc,   FIRMWARE);
-
-       /* Attempt to pass the name of the loaded image */
-       notes.nv4.n_namesz = 0;
-       notes.nv4.n_descsz = sizeof(notes.nv4_loaded_image);
-       notes.nv4.n_type   = EBN_LOADED_IMAGE;
-       memcpy(&notes.nv4_loaded_image, KERNEL_BUF, sizeof(notes.nv4_loaded_image));
-
-       /* Pass an empty command line for now */
-       notes.nv5.n_namesz = 0;
-       notes.nv5.n_descsz = sizeof("");
-       notes.nv5.n_type   = EBN_COMMAND_LINE;
-       CP(notes.nv5_cmdline,   "");
-
-
-       notes.hdr.b_checksum = ipchksum(&notes, sizeof(notes));
-       /* Like UDP invert a 0 checksum to show that a checksum is present */
-       if (notes.hdr.b_checksum == 0) {
-               notes.hdr.b_checksum = 0xffff;
-       }
-       return &notes.hdr;
-}
-
-int elf_start(unsigned long machine __unused_i386, unsigned long entry, unsigned long params)
-{
-#if defined(CONFIG_X86_64)
-       if (machine == EM_X86_64) {
-               return xstart_lm(entry, params);
-       }
-#endif
-       return xstart32(entry, params);
-}
diff --git a/src/image/elf.c b/src/image/elf.c
new file mode 100644 (file)
index 0000000..c746caa
--- /dev/null
@@ -0,0 +1,130 @@
+/*
+ * Copyright (C) 2007 Michael Brown <mbrown@fensystems.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; either version 2 of the
+ * License, or any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/**
+ * @file
+ *
+ * ELF image format
+ *
+ */
+
+#include <errno.h>
+#include <elf.h>
+#include <gpxe/uaccess.h>
+#include <gpxe/segment.h>
+
+typedef Elf32_Ehdr     Elf_Ehdr;
+typedef Elf32_Phdr     Elf_Phdr;
+typedef Elf32_Off      Elf_Off;
+
+/** An ELF file */
+struct elf {
+       /** ELF file image */
+       userptr_t image;
+       /** Length of ELF file image */
+       size_t len;
+};
+
+/**
+ * Load ELF segment into memory
+ *
+ * @v elf              ELF file
+ * @v phdr             ELF program header
+ * @ret rc             Return status code
+ */
+static int elf_load_segment ( struct elf *elf, Elf_Phdr *phdr ) {
+       physaddr_t dest;
+       userptr_t buffer;
+       int rc;
+
+       /* Do nothing for non-PT_LOAD segments */
+       if ( phdr->p_type != PT_LOAD )
+               return 0;
+
+       /* Check segment lies within image */
+       if ( ( phdr->p_offset + phdr->p_filesz ) > elf->len ) {
+               DBG ( "ELF segment outside ELF file\n" );
+               return -ENOEXEC;
+       }
+
+       /* Find start address: use physical address for preference,
+        * fall back to virtual address if no physical address
+        * supplied.
+        */
+       dest = phdr->p_paddr;
+       if ( ! dest )
+               dest = phdr->p_vaddr;
+       if ( ! dest ) {
+               DBG ( "ELF segment loads to physical address 0\n" );
+               return -ENOEXEC;
+       }
+       buffer = phys_to_user ( dest );
+
+       DBG ( "ELF loading segment [%lx,%lx) to [%lx,%lx,%lx)\n",
+             phdr->p_offset, ( phdr->p_offset + phdr->p_filesz ),
+             phdr->p_paddr, ( phdr->p_paddr + phdr->p_filesz ),
+             ( phdr->p_paddr + phdr->p_memsz ) );
+
+       /* Verify and prepare segment */
+       if ( ( rc = prep_segment ( buffer, phdr->p_filesz,
+                                  phdr->p_memsz ) ) != 0 ) {
+               DBG ( "ELF could not prepare segment: %s\n", strerror ( rc ) );
+               return rc;
+       }
+
+       /* Copy image to segment */
+       copy_user ( buffer, 0, elf->image, phdr->p_offset, phdr->p_filesz );
+
+       return 0;
+}
+
+/**
+ * Load ELF image into memory
+ *
+ * @v elf              ELF file
+ * @ret rc             Return status code
+ */
+int elf_load ( struct elf *elf ) {
+       Elf_Ehdr ehdr;
+       Elf_Phdr phdr;
+       Elf_Off phoff;
+       unsigned int phnum;
+       int rc;
+
+       /* Read ELF header */
+       copy_from_user ( &ehdr, elf->image, 0, sizeof ( ehdr ) );
+       if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) {
+               DBG ( "Invalid ELF signature\n" );
+               return -ENOEXEC;
+       }
+
+       /* Read ELF program headers */
+       for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
+             phoff += ehdr.e_phentsize, phnum-- ) {
+               if ( phoff > elf->len ) {
+                       DBG ( "ELF program header %d outside ELF image\n",
+                             phnum );
+                       return -ENOEXEC;
+               }
+               copy_from_user ( &phdr, elf->image, phoff, sizeof ( phdr ) );
+               if ( ( rc = elf_load_segment ( elf, &phdr ) ) != 0 )
+                       return rc;
+       }
+
+       return 0;
+}
index 606b419..a6eb5d9 100644 (file)
 #define ELFMAG3                'F'
 
 #define ELFMAG         "\177ELF"
+#define        SELFMAG         4
 
 #define EI_CLASS       4       /* File class byte index */
 #define ELFCLASSNONE   0       /* Invalid class */
 #define ELF32_PHDR_SIZE (8*4)  /* Size of an elf program header */
 
 #ifndef ASSEMBLY
+
+#include <stdint.h>
+
 /*
  * ELF definitions common to all 32-bit architectures.
  */
@@ -229,6 +233,4 @@ typedef struct {
 
 #endif /* ASSEMBLY */
 
-#include "elf_boot.h"
-
 #endif /* ELF_H */
diff --git a/src/include/elf_boot.h b/src/include/elf_boot.h
deleted file mode 100644 (file)
index 878a870..0000000
+++ /dev/null
@@ -1,84 +0,0 @@
-#ifndef ELF_BOOT_H 
-#define ELF_BOOT_H 
-
-
-/* This defines the structure of a table of parameters useful for ELF
- * bootable images.  These parameters are all passed and generated
- * by the bootloader to the booted image.  For simplicity and
- * consistency the Elf Note format is reused.
- *
- * All of the information must be Position Independent Data.
- * That is it must be safe to relocate the whole ELF boot parameter
- * block without changing the meaning or correctnes of the data.
- * Additionally it must be safe to permute the order of the ELF notes
- * to any possible permutation without changing the meaning or correctness
- * of the data.
- *
- */
-
-#define ELF_BHDR_MAGIC         0x0E1FB007
-
-#ifndef ASSEMBLY
-#include <stdint.h>
-typedef uint16_t Elf_Half;
-typedef uint32_t Elf_Word;
-
-typedef struct Elf_Bhdr
-{
-       Elf_Word b_signature; /* "0x0E1FB007" */
-       Elf_Word b_size;
-       Elf_Half b_checksum;
-       Elf_Half b_records;
-} Elf_Bhdr;
-
-typedef struct Elf_Nhdr
-{
-       Elf_Word n_namesz;              /* Length of the note's name.  */
-       Elf_Word n_descsz;              /* Length of the note's descriptor.  */
-       Elf_Word n_type;                /* Type of the note.  */
-} Elf_Nhdr;
-
-#endif /* ASSEMBLY */
-
-/* Standardized Elf image notes for booting... The name for all of these is ELFBoot */
-#define ELF_NOTE_BOOT          "ELFBoot"
-
-#define EIN_PROGRAM_NAME       0x00000001
-/* The program in this ELF file */
-#define EIN_PROGRAM_VERSION    0x00000002
-/* The version of the program in this ELF file */
-#define EIN_PROGRAM_CHECKSUM   0x00000003
-/* ip style checksum of the memory image. */
-
-
-/* Notes that are passed to a loaded image */
-/* For standard notes n_namesz must be zero */
-#define EBN_FIRMWARE_TYPE      0x00000001
-/* ASCIZ name of the platform firmware. */
-#define EBN_BOOTLOADER_NAME    0x00000002
-/* This specifies just the ASCIZ name of the bootloader */
-#define EBN_BOOTLOADER_VERSION 0x00000003
-/* This specifies the version of the bootloader as an ASCIZ string */
-#define EBN_COMMAND_LINE       0x00000004
-/* This specifies a command line that can be set by user interaction,
- * and is provided as a free form ASCIZ string to the loaded image.
- */
-#define EBN_NOP                        0x00000005
-/* A note nop note has no meaning, useful for inserting explicit padding */
-#define EBN_LOADED_IMAGE       0x00000006
-/* An ASCIZ string naming the loaded image */
-
-
-/* Etherboot specific notes */
-#define EB_PARAM_NOTE          "Etherboot"
-#define EB_IA64_SYSTAB         0x00000001
-#define EB_IA64_MEMMAP         0x00000002
-#define EB_IA64_FPSWA          0x00000003
-#define EB_IA64_CONINFO                0x00000004
-#define EB_BOOTP_DATA          0x00000005
-#define EB_HEADER              0x00000006
-#define EB_IA64_IMAGE_HANDLE   0x00000007
-#define EB_I386_MEMMAP         0x00000008
-
-
-#endif /* ELF_BOOT_H */