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 <string.h>
27 #include <errno.h>
28 #include <elf.h>
29 #include <librm.h>
30 #include <ipxe/image.h>
31 #include <ipxe/elf.h>
32 #include <ipxe/features.h>
33 #include <ipxe/init.h>
34 
35 /**
36  * @file
37  *
38  * ELF bootable image
39  *
40  */
41 
43 
44 /**
45  * Execute ELF image
46  *
47  * @v image ELF image
48  * @ret rc Return status code
49  */
50 static int elfboot_exec ( struct image *image ) {
51  physaddr_t entry;
53  int rc;
54 
55  /* Load the image using core ELF support */
56  if ( ( rc = elf_load ( image, &entry, &max ) ) != 0 ) {
57  DBGC ( image, "ELF %s could not load: %s\n",
58  image->name, strerror ( rc ) );
59  return rc;
60  }
61 
62  /* An ELF image has no callback interface, so we need to shut
63  * down before invoking it.
64  */
65  shutdown_boot();
66 
67  /* Jump to OS with flat physical addressing */
68  DBGC ( image, "ELF %s starting execution at %lx\n",
69  image->name, entry );
70  __asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t" /* gcc bug */
71  "call *%%edi\n\t"
72  "popl %%ebp\n\t" /* gcc bug */ )
73  : : "D" ( entry )
74  : "eax", "ebx", "ecx", "edx", "esi", "memory" );
75 
76  DBGC ( image, "ELF %s returned\n", image->name );
77 
78  /* It isn't safe to continue after calling shutdown() */
79  while ( 1 ) {}
80 
81  return -ECANCELED; /* -EIMPOSSIBLE, anyone? */
82 }
83 
84 /**
85  * Check that ELF segment uses flat physical addressing
86  *
87  * @v image ELF file
88  * @v phdr ELF program header
89  * @v dest Destination address
90  * @ret rc Return status code
91  */
92 static int elfboot_check_segment ( struct image *image, const Elf_Phdr *phdr,
93  physaddr_t dest ) {
94 
95  /* Check that ELF segment uses flat physical addressing */
96  if ( phdr->p_vaddr != dest ) {
97  DBGC ( image, "ELF %s uses virtual addressing (phys %x, virt "
98  "%x)\n", image->name, phdr->p_paddr, phdr->p_vaddr );
99  return -ENOEXEC;
100  }
101 
102  return 0;
103 }
104 
105 /**
106  * Probe ELF image
107  *
108  * @v image ELF file
109  * @ret rc Return status code
110  */
111 static int elfboot_probe ( struct image *image ) {
112  const Elf32_Ehdr *ehdr;
113  static const uint8_t e_ident[] = {
114  [EI_MAG0] = ELFMAG0,
115  [EI_MAG1] = ELFMAG1,
116  [EI_MAG2] = ELFMAG2,
117  [EI_MAG3] = ELFMAG3,
118  [EI_CLASS] = ELFCLASS32,
119  [EI_DATA] = ELFDATA2LSB,
121  };
122  physaddr_t entry;
123  physaddr_t max;
124  int rc;
125 
126  /* Read ELF header */
127  if ( image->len < sizeof ( *ehdr ) ) {
128  DBGC ( image, "ELF %s too short for ELF header\n",
129  image->name );
130  return -ENOEXEC;
131  }
132  ehdr = image->data;
133  if ( memcmp ( ehdr->e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) {
134  DBGC ( image, "ELF %s invalid identifier\n", image->name );
135  return -ENOEXEC;
136  }
137 
138  /* Check that this image uses flat physical addressing */
139  if ( ( rc = elf_segments ( image, ehdr, elfboot_check_segment,
140  &entry, &max ) ) != 0 ) {
141  DBGC ( image, "ELF %s is not loadable: %s\n",
142  image->name, strerror ( rc ) );
143  return rc;
144  }
145 
146  return 0;
147 }
148 
149 /** ELF image type */
150 struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = {
151  .name = "ELF",
152  .probe = elfboot_probe,
153  .exec = elfboot_exec,
154 };
#define EI_DATA
Definition: elf.h:48
static int elfboot_check_segment(struct image *image, const Elf_Phdr *phdr, physaddr_t dest)
Check that ELF segment uses flat physical addressing.
Definition: elfboot.c:92
FILE_LICENCE(GPL2_OR_LATER_OR_UBDL)
Elf32_Addr p_paddr
Definition: elf.h:71
#define PHYS_CODE(asm_code_str)
Definition: librm.h:167
struct arbelprm_rc_send_wqe rc
Definition: arbel.h:14
ELF header.
Definition: elf.h:25
#define max(x, y)
Definition: ath.h:40
#define EI_VERSION
Definition: elf.h:49
Error codes.
const void * data
Read-only data.
Definition: image.h:50
#define ELFMAG1
Definition: elf.h:53
#define ENOEXEC
Exec format error.
Definition: errno.h:519
#define DBGC(...)
Definition: compiler.h:505
An executable image type.
Definition: image.h:94
#define PROBE_NORMAL
Normal image probe priority.
Definition: image.h:155
An executable image.
Definition: image.h:23
#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:96
ELF image format.
int elf_segments(struct image *image, const Elf_Ehdr *ehdr, int(*process)(struct image *image, const Elf_Phdr *phdr, physaddr_t dest), physaddr_t *entry, physaddr_t *max)
Process ELF segments.
Definition: elf.c:157
#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:206
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.
#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
size_t len
Length of raw file image.
Definition: image.h:55
FEATURE(FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1)
__asm__ __volatile__("call *%9" :"=a"(result), "=c"(discard_ecx), "=d"(discard_edx) :"d"(0), "a"(code), "b"(0), "c"(in_phys), "D"(0), "S"(out_phys), "m"(hypercall))
unsigned char uint8_t
Definition: stdint.h:10
#define EI_CLASS
Definition: elf.h:47
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:50
__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
if(len >=6 *4) __asm__ __volatile__("movsl" if(len >=5 *4) __asm__ __volatile__("movsl" if(len >=4 *4) __asm__ __volatile__("movsl" if(len >=3 *4) __asm__ __volatile__("movsl" if(len >=2 *4) __asm__ __volatile__("movsl" if(len >=1 *4) __asm__ __volatile__("movsl" if((len % 4) >=2) __asm__ __volatile__("movsw" if((len % 2) >=1) __asm__ __volatile__("movsb" return dest
Definition: string.h:150
#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:111
#define ELFMAG0
Definition: elf.h:52
static void shutdown_boot(void)
Shut down system for OS boot.
Definition: init.h:77
int memcmp(const void *first, const void *second, size_t len)
Compare memory regions.
Definition: string.c:114
char * name
Name.
Definition: image.h:37
ELF program header.
Definition: elf.h:67
String functions.
#define EI_MAG1
Definition: elf.h:44
#define EI_MAG0
Definition: elf.h:43