Browse Source

[ELF] Add ability to boot ELF images generated by wraplinux and mkelfImage

Delete ELF as a generic image type.  The method for invoking an
ELF-based image (as well as any tables that must be set up to allow it
to boot) will always depend on the specific architecture.  core/elf.c
now only provides the elf_load() function, to avoid duplicating
functionality between ELF-based image types.

Add arch/i386/image/elfboot.c, to handle the generic case of 32-bit
x86 ELF images.  We don't currently set up any multiboot tables, ELF
notes, etc.  This seems to be sufficient for loading kernels generated
using both wraplinux and coreboot's mkelfImage.

Note that while Etherboot 5.4 allowed ELF images to return, we don't.
There is no callback mechanism for the loaded image to shut down gPXE,
which means that we have to shut down before invoking the image.  This
means that we lose device state, protection against being trampled on,
etc.  It is not safe to continue afterwards.
tags/v0.9.4
Michael Brown 16 years ago
parent
commit
77a5cc6b13

+ 110
- 0
src/arch/i386/image/elfboot.c View 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., 675 Mass Ave, Cambridge, MA 02139, USA.
17
+ */
18
+
19
+#include <errno.h>
20
+#include <elf.h>
21
+#include <gpxe/image.h>
22
+#include <gpxe/elf.h>
23
+#include <gpxe/features.h>
24
+#include <gpxe/init.h>
25
+
26
+/**
27
+ * @file
28
+ *
29
+ * ELF bootable image
30
+ *
31
+ */
32
+
33
+FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 );
34
+
35
+struct image_type elfboot_image_type __image_type ( PROBE_NORMAL );
36
+
37
+/**
38
+ * Execute ELF image
39
+ *
40
+ * @v image		ELF image
41
+ * @ret rc		Return status code
42
+ */
43
+static int elfboot_exec ( struct image *image ) {
44
+	physaddr_t entry = image->priv.phys;
45
+
46
+	/* An ELF image has no callback interface, so we need to shut
47
+	 * down before invoking it.
48
+	 */
49
+	shutdown();
50
+
51
+	/* Jump to OS with flat physical addressing */
52
+	__asm__ __volatile__ ( PHYS_CODE ( "call *%%edi\n\t" )
53
+			       : : "D" ( entry )
54
+			       : "eax", "ebx", "ecx", "edx", "esi", "ebp",
55
+			         "memory" );
56
+
57
+	DBGC ( image, "ELF %p returned\n", image );
58
+
59
+	/* It isn't safe to continue after calling shutdown() */
60
+	while ( 1 ) {}
61
+
62
+	return -ECANCELED;  /* -EIMPOSSIBLE, anyone? */
63
+}
64
+
65
+/**
66
+ * Load ELF image into memory
67
+ *
68
+ * @v image		ELF file
69
+ * @ret rc		Return status code
70
+ */
71
+static int elfboot_load ( struct image *image ) {
72
+	Elf32_Ehdr ehdr;
73
+	static const uint8_t e_ident[] = {
74
+		[EI_MAG0]	= ELFMAG0,
75
+		[EI_MAG1]	= ELFMAG1,
76
+		[EI_MAG2]	= ELFMAG2,
77
+		[EI_MAG3]	= ELFMAG3,
78
+		[EI_CLASS]	= ELFCLASS32,
79
+		[EI_DATA]	= ELFDATA2LSB,
80
+		[EI_VERSION]	= EV_CURRENT,
81
+	};
82
+	int rc;
83
+
84
+	/* Read ELF header */
85
+	copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
86
+	if ( memcmp ( ehdr.e_ident, e_ident, sizeof ( e_ident ) ) != 0 ) {
87
+		DBG ( "Invalid ELF identifier\n" );
88
+		return -ENOEXEC;
89
+	}
90
+
91
+	/* This is an ELF image, valid or otherwise */
92
+	if ( ! image->type )
93
+		image->type = &elfboot_image_type;
94
+
95
+	/* Load the image using core ELF support */
96
+	if ( ( rc = elf_load ( image ) ) != 0 ) {
97
+		DBGC ( image, "ELF %p could not load: %s\n",
98
+		       image, strerror ( rc ) );
99
+		return rc;
100
+	}
101
+
102
+	return 0;
103
+}
104
+
105
+/** ELF image type */
106
+struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = {
107
+	.name = "ELF",
108
+	.load = elfboot_load,
109
+	.exec = elfboot_exec,
110
+};

+ 1
- 0
src/arch/i386/include/bits/errfile.h View File

20
 #define ERRFILE_multiboot      ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00030000 )
20
 #define ERRFILE_multiboot      ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00030000 )
21
 #define ERRFILE_nbi	       ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00040000 )
21
 #define ERRFILE_nbi	       ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00040000 )
22
 #define ERRFILE_pxe_image      ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00050000 )
22
 #define ERRFILE_pxe_image      ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00050000 )
23
+#define ERRFILE_elfboot	       ( ERRFILE_ARCH | ERRFILE_IMAGE | 0x00060000 )
23
 
24
 
24
 #define ERRFILE_undi		 ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
25
 #define ERRFILE_undi		 ( ERRFILE_ARCH | ERRFILE_NET | 0x00000000 )
25
 #define ERRFILE_undiload	 ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )
26
 #define ERRFILE_undiload	 ( ERRFILE_ARCH | ERRFILE_NET | 0x00010000 )

+ 1
- 2
src/config.h View File

121
  *
121
  *
122
  */
122
  */
123
 #undef	IMAGE_NBI		/* NBI image support */
123
 #undef	IMAGE_NBI		/* NBI image support */
124
-#undef	IMAGE_ELF64		/* ELF64 image support */
125
-#undef	IMAGE_ELF		/* ELF image support */
124
+#define	IMAGE_ELF		/* ELF image support */
126
 #undef	IMAGE_FREEBSD		/* FreeBSD kernel image support */
125
 #undef	IMAGE_FREEBSD		/* FreeBSD kernel image support */
127
 #define	IMAGE_MULTIBOOT		/* MultiBoot image support */
126
 #define	IMAGE_MULTIBOOT		/* MultiBoot image support */
128
 #undef	IMAGE_AOUT		/* a.out image support */
127
 #undef	IMAGE_AOUT		/* a.out image support */

+ 1
- 4
src/core/config.c View File

131
 #ifdef IMAGE_NBI
131
 #ifdef IMAGE_NBI
132
 REQUIRE_OBJECT ( nbi );
132
 REQUIRE_OBJECT ( nbi );
133
 #endif
133
 #endif
134
-#ifdef IMAGE_ELF64
135
-REQUIRE_OBJECT ( elf64 );
136
-#endif
137
 #ifdef IMAGE_ELF
134
 #ifdef IMAGE_ELF
138
-REQUIRE_OBJECT ( elf );
135
+REQUIRE_OBJECT ( elfboot );
139
 #endif
136
 #endif
140
 #ifdef IMAGE_FREEBSD
137
 #ifdef IMAGE_FREEBSD
141
 REQUIRE_OBJECT ( freebsd );
138
 REQUIRE_OBJECT ( freebsd );

+ 6
- 23
src/image/elf.c View File

21
  *
21
  *
22
  * ELF image format
22
  * ELF image format
23
  *
23
  *
24
+ * A "pure" ELF image is not a bootable image.  There are various
25
+ * bootable formats based upon ELF (e.g. Multiboot), which share
26
+ * common ELF-related functionality.
24
  */
27
  */
25
 
28
 
26
 #include <errno.h>
29
 #include <errno.h>
30
 #include <gpxe/image.h>
33
 #include <gpxe/image.h>
31
 #include <gpxe/elf.h>
34
 #include <gpxe/elf.h>
32
 
35
 
33
-struct image_type elf_image_type __image_type ( PROBE_NORMAL );
34
-
35
 typedef Elf32_Ehdr	Elf_Ehdr;
36
 typedef Elf32_Ehdr	Elf_Ehdr;
36
 typedef Elf32_Phdr	Elf_Phdr;
37
 typedef Elf32_Phdr	Elf_Phdr;
37
 typedef Elf32_Off	Elf_Off;
38
 typedef Elf32_Off	Elf_Off;
38
 
39
 
39
-/**
40
- * Execute ELF image
41
- *
42
- * @v image		ELF file
43
- * @ret rc		Return status code
44
- */
45
-static int elf_exec ( struct image *image __unused ) {
46
-	return -ENOTSUP;
47
-}
48
-
49
 /**
40
 /**
50
  * Load ELF segment into memory
41
  * Load ELF segment into memory
51
  *
42
  *
112
 	unsigned int phnum;
103
 	unsigned int phnum;
113
 	int rc;
104
 	int rc;
114
 
105
 
106
+	/* Image type must already have been set by caller */
107
+	assert ( image->type != NULL );
108
+
115
 	/* Read ELF header */
109
 	/* Read ELF header */
116
 	copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
110
 	copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
117
 	if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) {
111
 	if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) {
119
 		return -ENOEXEC;
113
 		return -ENOEXEC;
120
 	}
114
 	}
121
 
115
 
122
-	/* This is an ELF image, valid or otherwise */
123
-	if ( ! image->type )
124
-		image->type = &elf_image_type;
125
-
126
 	/* Read ELF program headers */
116
 	/* Read ELF program headers */
127
 	for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
117
 	for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
128
 	      phoff += ehdr.e_phentsize, phnum-- ) {
118
 	      phoff += ehdr.e_phentsize, phnum-- ) {
141
 
131
 
142
 	return 0;
132
 	return 0;
143
 }
133
 }
144
-
145
-/** ELF image type */
146
-struct image_type elf_image_type __image_type ( PROBE_NORMAL ) = {
147
-	.name = "ELF",
148
-	.load = elf_load,
149
-	.exec = elf_exec,
150
-};

+ 1
- 0
src/include/gpxe/features.h View File

43
 #define DHCP_EB_FEATURE_MULTIBOOT	0x19 /**< Multiboot format */
43
 #define DHCP_EB_FEATURE_MULTIBOOT	0x19 /**< Multiboot format */
44
 #define DHCP_EB_FEATURE_NBI		0x20 /**< NBI format */
44
 #define DHCP_EB_FEATURE_NBI		0x20 /**< NBI format */
45
 #define DHCP_EB_FEATURE_PXE		0x21 /**< PXE format */
45
 #define DHCP_EB_FEATURE_PXE		0x21 /**< PXE format */
46
+#define DHCP_EB_FEATURE_ELF		0x22 /**< ELF format */
46
 
47
 
47
 /** @} */
48
 /** @} */
48
 
49
 

Loading…
Cancel
Save