1 /* 2 * Copyright (C) 2008 Michael Brown <mbrown (at) fensystems.co.uk>. 3 * 4 * This program is free software; you can redistribute it and/or 5 * modify it under the terms of the GNU General Public License as 6 * published by the Free Software Foundation; either version 2 of the 7 * License, or any later version. 8 * 9 * This program is distributed in the hope that it will be useful, but 10 * WITHOUT ANY WARRANTY; without even the implied warranty of 11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 12 * General Public License for more details. 13 * 14 * You should have received a copy of the GNU General Public License 15 * along with this program; if not, write to the Free Software 16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. 17 */ 18 19 FILE_LICENCE ( GPL2_OR_LATER ); 20 21 #include <errno.h> 22 #include <elf.h> 23 #include <gpxe/image.h> 24 #include <gpxe/elf.h> 25 #include <gpxe/features.h> 26 #include <gpxe/init.h> 27 28 /** 29 * @file 30 * 31 * ELF bootable image 32 * 33 */ 34 35 FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 ); 36 37 struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ); 38 39 /** 40 * Execute ELF image 41 * 42 * @v image ELF image 43 * @ret rc Return status code 44 */ 45 static int elfboot_exec ( struct image *image ) { 46 physaddr_t entry = image->priv.phys; 47 48 /* An ELF image has no callback interface, so we need to shut 49 * down before invoking it. 50 */ 51 shutdown ( SHUTDOWN_BOOT ); 52 53 /* Jump to OS with flat physical addressing */ 54 DBGC ( image, "ELF %p starting execution at %lx\n", image, entry ); 55 __asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" ) 56 : : "D" ( entry ) 57 : "eax", "ebx", "ecx", "edx", "esi", "ebp", 58 "memory" ); 59 60 DBGC ( image, "ELF %p returned\n", image ); 61 62 /* It isn't safe to continue after calling shutdown() */ 63 while ( 1 ) {} 64 65 return -ECANCELED; /* -EIMPOSSIBLE, anyone? */ 66 } 67 68 /** 69 * Load ELF image into memory 70 * 71 * @v image ELF file 72 * @ret rc Return status code 73 */ 74 static int elfboot_load ( struct image *image ) { 75 Elf32_Ehdr ehdr; 76 static const uint8_t e_ident[] = { 77 [EI_MAG0] = ELFMAG0, 78 [EI_MAG1] = ELFMAG1, 79 [EI_MAG2] = ELFMAG2, 80 [EI_MAG3] = ELFMAG3, 81 [EI_CLASS] = ELFCLASS32, 82 [EI_DATA] = ELFDATA2LSB, 83 [EI_VERSION] = EV_CURRENT, 84 }; 85 int rc; 86 87 /* Read ELF header */ 88 copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) ); 89 if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) { 90 DBG ( "Invalid ELF identifier\n" ); 91 return -ENOEXEC; 92 } 93 94 /* This is an ELF image, valid or otherwise */ 95 if ( ! image->type ) 96 image->type = &elfboot_image_type; 97 98 /* Load the image using core ELF support */ 99 if ( ( rc = elf_load ( image ) ) != 0 ) { 100 DBGC ( image, "ELF %p could not load: %s\n", 101 image, strerror ( rc ) ); 102 return rc; 103 } 104 105 return 0; 106 } 107 108 /** ELF image type */ 109 struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = { 110 .name = "ELF", 111 .load = elfboot_load, 112 .exec = elfboot_exec, 113 }; 114