diff options
Diffstat (limited to 'gpxe/src/image')
-rw-r--r-- | gpxe/src/image/efi_image.c | 108 | ||||
-rw-r--r-- | gpxe/src/image/elf.c | 162 | ||||
-rw-r--r-- | gpxe/src/image/embedded.c | 101 | ||||
-rw-r--r-- | gpxe/src/image/script.c | 126 | ||||
-rw-r--r-- | gpxe/src/image/segment.c | 87 |
5 files changed, 0 insertions, 584 deletions
diff --git a/gpxe/src/image/efi_image.c b/gpxe/src/image/efi_image.c deleted file mode 100644 index 60d150a9..00000000 --- a/gpxe/src/image/efi_image.c +++ /dev/null @@ -1,108 +0,0 @@ -/* - * Copyright (C) 2008 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_LICENCE ( GPL2_OR_LATER ); - -#include <errno.h> -#include <gpxe/efi/efi.h> -#include <gpxe/image.h> -#include <gpxe/features.h> - -FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 ); - -struct image_type efi_image_type __image_type ( PROBE_NORMAL ); - -/** - * Execute EFI image - * - * @v image EFI image - * @ret rc Return status code - */ -static int efi_image_exec ( struct image *image ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE handle; - UINTN exit_data_size; - CHAR16 *exit_data; - EFI_STATUS efirc; - - /* Attempt loading image */ - if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL, - user_to_virt ( image->data, 0 ), - image->len, &handle ) ) != 0 ) { - /* Not an EFI image */ - DBGC ( image, "EFIIMAGE %p could not load: %s\n", - image, efi_strerror ( efirc ) ); - return -ENOEXEC; - } - - /* Start the image */ - if ( ( efirc = bs->StartImage ( handle, &exit_data_size, - &exit_data ) ) != 0 ) { - DBGC ( image, "EFIIMAGE %p returned with status %s\n", - image, efi_strerror ( efirc ) ); - goto done; - } - - done: - /* Unload the image. We can't leave it loaded, because we - * have no "unload" operation. - */ - bs->UnloadImage ( handle ); - - return EFIRC_TO_RC ( efirc ); -} - -/** - * Load EFI image into memory - * - * @v image EFI file - * @ret rc Return status code - */ -static int efi_image_load ( struct image *image ) { - EFI_BOOT_SERVICES *bs = efi_systab->BootServices; - EFI_HANDLE handle; - EFI_STATUS efirc; - - /* Attempt loading image */ - if ( ( efirc = bs->LoadImage ( FALSE, efi_image_handle, NULL, - user_to_virt ( image->data, 0 ), - image->len, &handle ) ) != 0 ) { - /* Not an EFI image */ - DBGC ( image, "EFIIMAGE %p could not load: %s\n", - image, efi_strerror ( efirc ) ); - return -ENOEXEC; - } - - /* This is an EFI image */ - if ( ! image->type ) - image->type = &efi_image_type; - - /* Unload the image. We can't leave it loaded, because we - * have no "unload" operation. - */ - bs->UnloadImage ( handle ); - - return 0; -} - -/** EFI image type */ -struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = { - .name = "EFI", - .load = efi_image_load, - .exec = efi_image_exec, -}; diff --git a/gpxe/src/image/elf.c b/gpxe/src/image/elf.c deleted file mode 100644 index a0ec065e..00000000 --- a/gpxe/src/image/elf.c +++ /dev/null @@ -1,162 +0,0 @@ -/* - * 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_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * ELF image format - * - * A "pure" ELF image is not a bootable image. There are various - * bootable formats based upon ELF (e.g. Multiboot), which share - * common ELF-related functionality. - */ - -#include <errno.h> -#include <elf.h> -#include <gpxe/uaccess.h> -#include <gpxe/segment.h> -#include <gpxe/image.h> -#include <gpxe/elf.h> - -typedef Elf32_Ehdr Elf_Ehdr; -typedef Elf32_Phdr Elf_Phdr; -typedef Elf32_Off Elf_Off; - -/** - * Load ELF segment into memory - * - * @v image ELF file - * @v phdr ELF program header - * @v ehdr ELF executable header - * @ret rc Return status code - */ -static int elf_load_segment ( struct image *image, Elf_Phdr *phdr, - Elf_Ehdr *ehdr ) { - physaddr_t dest; - userptr_t buffer; - unsigned long e_offset; - 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 ) > image->len ) { - DBGC ( image, "ELF %p segment outside image\n", image ); - 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 ) { - DBGC ( image, "ELF %p segment loads to physical address 0\n", - image ); - return -ENOEXEC; - } - buffer = phys_to_user ( dest ); - - DBGC ( image, "ELF %p loading segment [%x,%x) to [%x,%x,%x)\n", image, - 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 ) { - DBGC ( image, "ELF %p could not prepare segment: %s\n", - image, strerror ( rc ) ); - return rc; - } - - /* Copy image to segment */ - memcpy_user ( buffer, 0, image->data, phdr->p_offset, phdr->p_filesz ); - - /* Set execution address, if it lies within this segment */ - if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) { - image->priv.phys = ehdr->e_entry; - DBGC ( image, "ELF %p found physical entry point at %lx\n", - image, image->priv.phys ); - } else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) ) - < phdr->p_filesz ) { - if ( ! image->priv.phys ) { - image->priv.phys = ( dest + e_offset ); - DBGC ( image, "ELF %p found virtual entry point at %lx" - " (virt %lx)\n", image, image->priv.phys, - ( ( unsigned long ) ehdr->e_entry ) ); - } - } - - return 0; -} - -/** - * Load ELF image into memory - * - * @v image ELF file - * @ret rc Return status code - */ -int elf_load ( struct image *image ) { - Elf_Ehdr ehdr; - Elf_Phdr phdr; - Elf_Off phoff; - unsigned int phnum; - int rc; - - /* Image type must already have been set by caller */ - assert ( image->type != NULL ); - - /* Read ELF header */ - copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); - if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) { - DBGC ( image, "ELF %p has invalid signature\n", image ); - return -ENOEXEC; - } - - /* Invalidate execution address */ - image->priv.phys = 0; - - /* Read ELF program headers */ - for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ; - phoff += ehdr.e_phentsize, phnum-- ) { - if ( phoff > image->len ) { - DBGC ( image, "ELF %p program header %d outside " - "image\n", image, phnum ); - return -ENOEXEC; - } - copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) ); - if ( ( rc = elf_load_segment ( image, &phdr, &ehdr ) ) != 0 ) - return rc; - } - - /* Check for a valid execution address */ - if ( ! image->priv.phys ) { - DBGC ( image, "ELF %p entry point %lx outside image\n", - image, ( ( unsigned long ) ehdr.e_entry ) ); - return -ENOEXEC; - } - - return 0; -} diff --git a/gpxe/src/image/embedded.c b/gpxe/src/image/embedded.c deleted file mode 100644 index 58a14ea4..00000000 --- a/gpxe/src/image/embedded.c +++ /dev/null @@ -1,101 +0,0 @@ -/** @file - * - * Embedded image support - * - * Embedded images are images built into the gPXE binary and do not require - * fetching over the network. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <string.h> -#include <gpxe/image.h> -#include <gpxe/uaccess.h> -#include <gpxe/init.h> - -/** - * Free embedded image - * - * @v refcnt Reference counter - */ -static void __attribute__ (( unused )) -embedded_image_free ( struct refcnt *refcnt __unused ) { - /* Do nothing */ -} - -/* Raw image data for all embedded images */ -#undef EMBED -#define EMBED( _index, _path, _name ) \ - extern char embedded_image_ ## _index ## _data[]; \ - extern char embedded_image_ ## _index ## _len[]; \ - __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" \ - "\nembedded_image_" #_index "_data:\n\t" \ - ".incbin \"" _path "\"\n\t" \ - "\nembedded_image_" #_index "_end:\n\t" \ - ".equ embedded_image_" #_index "_len, " \ - "( embedded_image_" #_index "_end - " \ - " embedded_image_" #_index "_data )\n\t" \ - ".previous\n\t" ); -EMBED_ALL - -/* Image structures for all embedded images */ -#undef EMBED -#define EMBED( _index, _path, _name ) { \ - .refcnt = { .free = embedded_image_free, }, \ - .name = _name, \ - .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \ - .len = ( size_t ) embedded_image_ ## _index ## _len, \ -}, -static struct image embedded_images[] = { - EMBED_ALL -}; - -/** - * Register all embedded images - */ -static void embedded_init ( void ) { - int i; - struct image *image; - void *data; - int rc; - - /* Skip if we have no embedded images */ - if ( ! sizeof ( embedded_images ) ) - return; - - /* Fix up data pointers and register images */ - for ( i = 0 ; i < ( int ) ( sizeof ( embedded_images ) / - sizeof ( embedded_images[0] ) ) ; i++ ) { - image = &embedded_images[i]; - - /* virt_to_user() cannot be used in a static - * initialiser, so we cast the pointer to a userptr_t - * in the initialiser and fix it up here. (This will - * actually be a no-op on most platforms.) - */ - data = ( ( void * ) image->data ); - image->data = virt_to_user ( data ); - - DBG ( "Embedded image \"%s\": %zd bytes at %p\n", - image->name, image->len, data ); - - if ( ( rc = register_image ( image ) ) != 0 ) { - DBG ( "Could not register embedded image \"%s\": " - "%s\n", image->name, strerror ( rc ) ); - return; - } - } - - /* Load the first image */ - image = &embedded_images[0]; - if ( ( rc = image_autoload ( image ) ) != 0 ) { - DBG ( "Could not load embedded image \"%s\": %s\n", - image->name, strerror ( rc ) ); - return; - } -} - -/** Embedded image initialisation function */ -struct init_fn embedded_init_fn __init_fn ( INIT_NORMAL ) = { - .initialise = embedded_init, -}; diff --git a/gpxe/src/image/script.c b/gpxe/src/image/script.c deleted file mode 100644 index 0835ecb5..00000000 --- a/gpxe/src/image/script.c +++ /dev/null @@ -1,126 +0,0 @@ -/* - * 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_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * gPXE scripts - * - */ - -#include <string.h> -#include <stdlib.h> -#include <ctype.h> -#include <errno.h> -#include <gpxe/image.h> - -struct image_type script_image_type __image_type ( PROBE_NORMAL ); - -/** - * Execute script - * - * @v image Script - * @ret rc Return status code - */ -static int script_exec ( struct image *image ) { - size_t offset = 0; - off_t eol; - size_t len; - int rc; - - /* Temporarily de-register image, so that a "boot" command - * doesn't throw us into an execution loop. - */ - unregister_image ( image ); - - while ( offset < image->len ) { - - /* Find length of next line, excluding any terminating '\n' */ - eol = memchr_user ( image->data, offset, '\n', - ( image->len - offset ) ); - if ( eol < 0 ) - eol = image->len; - len = ( eol - offset ); - - /* Copy line, terminate with NUL, and execute command */ - { - char cmdbuf[ len + 1 ]; - - copy_from_user ( cmdbuf, image->data, offset, len ); - cmdbuf[len] = '\0'; - DBG ( "$ %s\n", cmdbuf ); - if ( ( rc = system ( cmdbuf ) ) != 0 ) { - DBG ( "Command \"%s\" failed: %s\n", - cmdbuf, strerror ( rc ) ); - goto done; - } - } - - /* Move to next line */ - offset += ( len + 1 ); - } - - rc = 0; - done: - /* Re-register image and return */ - register_image ( image ); - return rc; -} - -/** - * Load script into memory - * - * @v image Script - * @ret rc Return status code - */ -static int script_load ( struct image *image ) { - static const char magic[] = "#!gpxe"; - char test[ sizeof ( magic ) - 1 /* NUL */ + 1 /* terminating space */]; - - /* Sanity check */ - if ( image->len < sizeof ( test ) ) { - DBG ( "Too short to be a script\n" ); - return -ENOEXEC; - } - - /* Check for magic signature */ - copy_from_user ( test, image->data, 0, sizeof ( test ) ); - if ( ( memcmp ( test, magic, ( sizeof ( test ) - 1 ) ) != 0 ) || - ! isspace ( test[ sizeof ( test ) - 1 ] ) ) { - DBG ( "Invalid magic signature\n" ); - return -ENOEXEC; - } - - /* This is a script */ - image->type = &script_image_type; - - /* We don't actually load it anywhere; we will pick the lines - * out of the image as we need them. - */ - - return 0; -} - -/** Script image type */ -struct image_type script_image_type __image_type ( PROBE_NORMAL ) = { - .name = "script", - .load = script_load, - .exec = script_exec, -}; diff --git a/gpxe/src/image/segment.c b/gpxe/src/image/segment.c deleted file mode 100644 index e2474536..00000000 --- a/gpxe/src/image/segment.c +++ /dev/null @@ -1,87 +0,0 @@ -/* - * 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_LICENCE ( GPL2_OR_LATER ); - -/** - * @file - * - * Executable image segments - * - */ - -#include <errno.h> -#include <gpxe/uaccess.h> -#include <gpxe/memmap.h> -#include <gpxe/errortab.h> -#include <gpxe/segment.h> - -/** - * Prepare segment for loading - * - * @v segment Segment start - * @v filesz Size of the "allocated bytes" portion of the segment - * @v memsz Size of the segment - * @ret rc Return status code - */ -int prep_segment ( userptr_t segment, size_t filesz, size_t memsz ) { - struct memory_map memmap; - physaddr_t start = user_to_phys ( segment, 0 ); - physaddr_t mid = user_to_phys ( segment, filesz ); - physaddr_t end = user_to_phys ( segment, memsz ); - unsigned int i; - - DBG ( "Preparing segment [%lx,%lx,%lx)\n", start, mid, end ); - - /* Sanity check */ - if ( filesz > memsz ) { - DBG ( "Insane segment [%lx,%lx,%lx)\n", start, mid, end ); - return -EINVAL; - } - - /* Get a fresh memory map. This allows us to automatically - * avoid treading on any regions that Etherboot is currently - * editing out of the memory map. - */ - get_memmap ( &memmap ); - - /* Look for a suitable memory region */ - for ( i = 0 ; i < memmap.count ; i++ ) { - if ( ( start >= memmap.regions[i].start ) && - ( end <= memmap.regions[i].end ) ) { - /* Found valid region: zero bss and return */ - memset_user ( segment, filesz, 0, ( memsz - filesz ) ); - return 0; - } - } - - /* No suitable memory region found */ - DBG ( "Segment [%lx,%lx,%lx) does not fit into available memory\n", - start, mid, end ); - return -ERANGE; -} - -/** - * Segment-specific error messages - * - * This error happens sufficiently often to merit a user-friendly - * description. - */ -struct errortab segment_errors[] __errortab = { - { ERANGE, "Requested memory not available" }, -}; |