iPXE
elfboot.c
Go to the documentation of this file.
1 /*
2  * Copyright (C) 2008 Michael Brown <mbrown@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., 51 Franklin Street, Fifth Floor, Boston, MA
17  * 02110-1301, USA.
18  *
19  * You can also choose to distribute this program under the terms of
20  * the Unmodified Binary Distribution Licence (as given in the file
21  * COPYING.UBDL), provided that you have satisfied its requirements.
22  */
23 
24 FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
25 
26 #include <errno.h>
27 #include <elf.h>
28 #include <ipxe/image.h>
29 #include <ipxe/elf.h>
30 #include <ipxe/features.h>
31 #include <ipxe/init.h>
32 
33 /**
34  * @file
35  *
36  * ELF bootable image
37  *
38  */
39 
41 
42 /**
43  * Execute ELF image
44  *
45  * @v image ELF image
46  * @ret rc Return status code
47  */
48 static int elfboot_exec ( struct image *image ) {
51  int rc;
52 
53  /* Load the image using core ELF support */
54  if ( ( rc = elf_load ( image, &entry, &max ) ) != 0 ) {
55  DBGC ( image, "ELF %p could not load: %s\n",
56  image, strerror ( rc ) );
57  return rc;
58  }
59 
60  /* An ELF image has no callback interface, so we need to shut
61  * down before invoking it.
62  */
63  shutdown_boot();
64 
65  /* Jump to OS with flat physical addressing */
66  DBGC ( image, "ELF %p starting execution at %lx\n", image, entry );
67  __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t" /* gcc bug */
68  "call *%%edi\n\t"
69  "popl %%ebp\n\t" /* gcc bug */ )
70  : : "D" ( entry )
71  : "eax", "ebx", "ecx", "edx", "esi", "memory" );
72 
73  DBGC ( image, "ELF %p returned\n", image );
74 
75  /* It isn't safe to continue after calling shutdown() */
76  while ( 1 ) {}
77 
78  return -ECANCELED; /* -EIMPOSSIBLE, anyone? */
79 }
80 
81 /**
82  * Check that ELF segment uses flat physical addressing
83  *
84  * @v image ELF file
85  * @v phdr ELF program header
86  * @v dest Destination address
87  * @ret rc Return status code
88  */
89 static int elfboot_check_segment ( struct image *image, Elf_Phdr *phdr,
90  physaddr_t dest ) {
91 
92  /* Check that ELF segment uses flat physical addressing */
93  if ( phdr->p_vaddr != dest ) {
94  DBGC ( image, "ELF %p uses virtual addressing (phys %x, "
95  "virt %x)\n", image, phdr->p_paddr, phdr->p_vaddr );
96  return -ENOEXEC;
97  }
98 
99  return 0;
100 }
101 
102 /**
103  * Probe ELF image
104  *
105  * @v image ELF file
106  * @ret rc Return status code
107  */
108 static int elfboot_probe ( struct image *image ) {
109  Elf32_Ehdr ehdr;
110  static const uint8_t e_ident[] = {
111  [EI_MAG0] = ELFMAG0,
112  [EI_MAG1] = ELFMAG1,
113  [EI_MAG2] = ELFMAG2,
114  [EI_MAG3] = ELFMAG3,
115  [EI_CLASS] = ELFCLASS32,
116  [EI_DATA] = ELFDATA2LSB,
118  };
120  physaddr_t max;
121  int rc;
122 
123  /* Read ELF header */
124  copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
125  if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) {
126  DBGC ( image, "Invalid ELF identifier\n" );
127  return -ENOEXEC;
128  }
129 
130  /* Check that this image uses flat physical addressing */
131  if ( ( rc = elf_segments ( image, &ehdr, elfboot_check_segment,
132  &entry, &max ) ) != 0 ) {
133  DBGC ( image, "Unloadable ELF image\n" );
134  return rc;
135  }
136 
137  return 0;
138 }
139 
140 /** ELF image type */
141 struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = {
142  .name = "ELF",
143  .probe = elfboot_probe,
144  .exec = elfboot_exec,
145 };
#define EI_DATA
Definition: elf.h:48
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
Elf32_Addr p_paddr
Definition: elf.h:71
#define PHYS_CODE(asm_code_str)
Definition: librm.h:279
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
ELF header.
Definition: elf.h:25
userptr_t data
Raw file image.
Definition: image.h:41
#define max(x, y)
Definition: ath.h:39
#define EI_VERSION
Definition: elf.h:49
Error codes.
#define ELFMAG1
Definition: elf.h:53
#define ENOEXEC
Exec format error.
Definition: errno.h:519
static __always_inline void copy_from_user(void *dest, userptr_t src, off_t src_off, size_t len)
Copy data from user buffer.
Definition: uaccess.h:337
#define DBGC(...)
Definition: compiler.h:505
An executable image type.
Definition: image.h:76
#define PROBE_NORMAL
Normal image probe priority.
Definition: image.h:129
An executable image.
Definition: image.h:24
#define FEATURE_IMAGE
Image formats.
Definition: features.h:22
#define ELFCLASS32
Definition: elf.h:58
#define ECANCELED
Operation canceled.
Definition: errno.h:343
char * name
Name of this image type.
Definition: image.h:78
ELF image format.
#define ELFMAG2
Definition: elf.h:54
int elf_load(struct image *image, physaddr_t *entry, physaddr_t *max)
Load ELF image into memory.
Definition: elf.c:201
Executable images.
Elf32_Addr p_vaddr
Definition: elf.h:70
Feature list.
struct image_type elfboot_image_type __image_type(PROBE_NORMAL)
ELF image type.
static void * dest
Definition: strings.h:176
#define DHCP_EB_FEATURE_ELF
ELF format.
Definition: features.h:50
unsigned char e_ident[EI_NIDENT]
Definition: elf.h:26
ELF headers.
#define EI_MAG2
Definition: elf.h:45
char * strerror(int errno)
Retrieve string representation of error number.
Definition: strerror.c:78
union aes_table_entry entry[256]
Table entries, indexed by S(N)
Definition: aes.c:26
FEATURE(FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1)
unsigned char uint8_t
Definition: stdint.h:10
int elf_segments(struct image *image, Elf_Ehdr *ehdr, int(*process)(struct image *image, Elf_Phdr *phdr, physaddr_t dest), physaddr_t *entry, physaddr_t *max)
Process ELF segments.
Definition: elf.c:154
static int elfboot_check_segment(struct image *image, Elf_Phdr *phdr, physaddr_t dest)
Check that ELF segment uses flat physical addressing.
Definition: elfboot.c:89
#define EI_CLASS
Definition: elf.h:47
__asm__ __volatile__("\n1:\n\t" "movb -1(%2,%1), %%al\n\t" "stosb\n\t" "loop 1b\n\t" "xorl %%eax, %%eax\n\t" "mov %3, %1\n\t" "rep stosb\n\t" :"=&D"(discard_D), "=&c"(discard_c) :"r"(data), "g"(pad_len), "0"(value0), "1"(len) :"eax")
unsigned long physaddr_t
Definition: stdint.h:20
#define ELFMAG3
Definition: elf.h:55
static int elfboot_exec(struct image *image)
Execute ELF image.
Definition: elfboot.c:48
__asm__(".section \".rodata\", \"a\", " PROGBITS "\n\t" "\nprivate_key_data:\n\t" ".size private_key_data, ( . - private_key_data )\n\t" ".equ private_key_len, ( . - private_key_data )\n\t" ".previous\n\t")
#define EV_CURRENT
Definition: elf.h:64
#define ELFDATA2LSB
Definition: elf.h:61
#define EI_MAG3
Definition: elf.h:46
static int elfboot_probe(struct image *image)
Probe ELF image.
Definition: elfboot.c:108
#define ELFMAG0
Definition: elf.h:52
static void shutdown_boot(void)
Shut down system for OS boot.
Definition: init.h:76
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:98
ELF program header.
Definition: elf.h:67
#define EI_MAG1
Definition: elf.h:44
#define EI_MAG0
Definition: elf.h:43