Переглянути джерело

[image] Allow multiple embedded images

This patch extends the embedded image feature to allow multiple
embedded images instead of just one.

gPXE now always boots the first embedded image on startup instead of
doing the hardcoded DHCP boot (aka autoboot).

Based heavily upon a patch by Stefan Hajnoczi <stefanha@gmail.com>.
tags/v0.9.7
Michael Brown 16 роки тому
джерело
коміт
076154a1c6

+ 4
- 0
contrib/scripts/gpxelinux.gpxe Переглянути файл

1
+#!gpxe
2
+dhcp net0
3
+imgload img1
4
+boot img1

+ 8
- 0
contrib/scripts/static.gpxe Переглянути файл

1
+#!gpxe
2
+ifopen net0
3
+set net0/ip 10.0.2.15
4
+set net0/netmask 255.255.255.0
5
+set net0/gateway 10.0.2.2
6
+set net0/dns 10.0.2.3
7
+kernel http://etherboot.org/gtest/gtest.gpxe
8
+boot gtest.gpxe

+ 33
- 9
src/Makefile.housekeeping Переглянути файл

85
 # Check for various tool workarounds
85
 # Check for various tool workarounds
86
 #
86
 #
87
 
87
 
88
+# Make syntax does not allow use of comma or space in certain places.
89
+# This ugly workaround is suggested in the manual.
90
+#
91
+COMMA	:= ,
92
+EMPTY	:=
93
+SPACE	:= $(EMPTY) $(EMPTY)
94
+
88
 # Check for an old version of gas (binutils 2.9.1)
95
 # Check for an old version of gas (binutils 2.9.1)
89
 #
96
 #
90
 OLDGAS	:= $(shell $(AS) --version | grep -q '2\.9\.1' && $(ECHO) -DGAS291)
97
 OLDGAS	:= $(shell $(AS) --version | grep -q '2\.9\.1' && $(ECHO) -DGAS291)
280
 ASFLAGS		+= $(EXTRA_ASFLAGS)
287
 ASFLAGS		+= $(EXTRA_ASFLAGS)
281
 LDFLAGS		+= $(EXTRA_LDFLAGS)
288
 LDFLAGS		+= $(EXTRA_LDFLAGS)
282
 
289
 
283
-# Embedded image, if present
290
+# Embedded image(s), or default if not set
284
 #
291
 #
285
-EMBEDDED_IMAGE	= /dev/null
292
+EMBEDDED_IMAGE	= image/default.gpxe
286
 
293
 
287
 # Inhibit -Werror if NO_WERROR is specified on make command line
294
 # Inhibit -Werror if NO_WERROR is specified on make command line
288
 #
295
 #
406
 roms :
413
 roms :
407
 	@$(ECHO) $(ROMS)
414
 	@$(ECHO) $(ROMS)
408
 
415
 
409
-# Embedded binary
416
+# List of embedded images included in the last build of embedded.o.
410
-$(BIN)/embedimg.bin: $(EMBEDDED_IMAGE)
417
+# This is needed in order to correctly rebuild embedded.o whenever the
411
-	$(QM)$(ECHO) "  [COPY] $@"
418
+# list of objects changes.
412
-	$(Q)$(CP) -f $(EMBEDDED_IMAGE) $@
419
+#
420
+EMBEDDED_LIST	:= $(BIN)/.embedded.list
421
+ifeq ($(wildcard $(EMBEDDED_LIST)),)
422
+EMBEDDED_LIST_IMAGE :=
423
+else
424
+EMBEDDED_LIST_IMAGE := $(shell cat $(EMBEDDED_LIST))
425
+endif
426
+ifneq ($(EMBEDDED_LIST_IMAGE),$(EMBEDDED_IMAGE))
427
+$(shell $(ECHO) "$(EMBEDDED_IMAGE)" > $(EMBEDDED_LIST))
428
+endif
429
+
430
+$(EMBEDDED_LIST) :
431
+
432
+VERYCLEANUP	+= $(EMBEDDED_LIST)
433
+
434
+EMBEDDED_FILES	:= $(subst $(COMMA), ,$(EMBEDDED_IMAGE))
435
+EMBED_ALL	:= $(foreach i,$(shell seq 1 $(words $(EMBEDDED_FILES))),\
436
+		     EMBED ( $(i), \"$(word $(i), $(EMBEDDED_FILES))\",\
437
+			     \"$(notdir $(word $(i),$(EMBEDDED_FILES)))\" ))
413
 
438
 
414
-$(BIN)/embed.o: $(BIN)/embedimg.bin
439
+$(BIN)/embedded.o : $(EMBEDDED_FILES) $(EMBEDDED_LIST)
415
-CFLAGS_embed = -DEMBEDIMG=\"$(BIN)/embedimg.bin\"
440
+CFLAGS_embedded = -DEMBED_ALL="$(EMBED_ALL)"
416
 
441
 
417
 # Generate the NIC file from the parsed source files.  The NIC file is
442
 # Generate the NIC file from the parsed source files.  The NIC file is
418
 # only for rom-o-matic.
443
 # only for rom-o-matic.
491
 # Calculate list of debugging versions of objects to be included in
516
 # Calculate list of debugging versions of objects to be included in
492
 # the target.
517
 # the target.
493
 #
518
 #
494
-COMMA		:= ,
495
 DEBUG_LIST	= $(subst $(COMMA), ,$(DEBUG))
519
 DEBUG_LIST	= $(subst $(COMMA), ,$(DEBUG))
496
 DEBUG_OBJ_LEVEL	= $(firstword $(word 2,$(subst :, ,$(1))) 1)
520
 DEBUG_OBJ_LEVEL	= $(firstword $(word 2,$(subst :, ,$(1))) 1)
497
 DEBUG_OBJ_BASE	= $(word 1,$(subst :, ,$(1))).dbg$(call DEBUG_OBJ_LEVEL,$(1))
521
 DEBUG_OBJ_BASE	= $(word 1,$(subst :, ,$(1))).dbg$(call DEBUG_OBJ_LEVEL,$(1))

+ 1
- 0
src/core/config.c Переглянути файл

218
  *
218
  *
219
  */
219
  */
220
 REQUIRE_OBJECT ( device );
220
 REQUIRE_OBJECT ( device );
221
+REQUIRE_OBJECT ( embedded );

+ 11
- 4
src/core/main.c Переглянути файл

19
 #include <gpxe/features.h>
19
 #include <gpxe/features.h>
20
 #include <gpxe/shell.h>
20
 #include <gpxe/shell.h>
21
 #include <gpxe/shell_banner.h>
21
 #include <gpxe/shell_banner.h>
22
+#include <gpxe/image.h>
22
 #include <usr/autoboot.h>
23
 #include <usr/autoboot.h>
23
 #include <config/general.h>
24
 #include <config/general.h>
24
 
25
 
36
  */
37
  */
37
 __asmcall int main ( void ) {
38
 __asmcall int main ( void ) {
38
 	struct feature *feature;
39
 	struct feature *feature;
40
+	struct image *image;
39
 
41
 
40
 	/* Some devices take an unreasonably long time to initialise */
42
 	/* Some devices take an unreasonably long time to initialise */
41
 	printf ( PRODUCT_SHORT_NAME " initialising devices...\n" );
43
 	printf ( PRODUCT_SHORT_NAME " initialising devices...\n" );
68
 		/* User wants shell; just give them a shell */
70
 		/* User wants shell; just give them a shell */
69
 		shell();
71
 		shell();
70
 	} else {
72
 	} else {
71
-		/* User doesn't want shell; try booting.  If booting
73
+		/* User doesn't want shell; load and execute the first
72
-		 * fails, offer a second chance to enter the shell for
74
+		 * image.  If booting fails (i.e. if the image
73
-		 * diagnostics.
75
+		 * returns, or fails to execute), offer a second
76
+		 * chance to enter the shell for diagnostics.
74
 		 */
77
 		 */
75
-		autoboot();
78
+		for_each_image ( image ) {
79
+			image_exec ( image );
80
+			break;
81
+		}
82
+
76
 		if ( shell_banner() )
83
 		if ( shell_banner() )
77
 			shell();
84
 			shell();
78
 	}
85
 	}

+ 2
- 0
src/image/default.gpxe Переглянути файл

1
+#!gpxe
2
+autoboot

+ 0
- 7
src/image/embed.S Переглянути файл

1
-	.section ".data", "aw", @progbits
2
-	.balign 4
3
-	.globl _embedded_image_start
4
-_embedded_image_start:
5
-	.incbin EMBEDIMG
6
-	.globl _embedded_image_end
7
-_embedded_image_end:

+ 77
- 32
src/image/embedded.c Переглянути файл

1
 /** @file
1
 /** @file
2
  *
2
  *
3
- * Take a possible embedded image and put it in a struct image
3
+ * Embedded image support
4
- * data structure.
4
+ *
5
+ * Embedded images are images built into the gPXE binary and do not require
6
+ * fetching over the network.
5
  */
7
  */
6
 
8
 
9
+#include <string.h>
7
 #include <gpxe/image.h>
10
 #include <gpxe/image.h>
8
-#include <gpxe/malloc.h>
9
 #include <gpxe/uaccess.h>
11
 #include <gpxe/uaccess.h>
10
-#include <gpxe/umalloc.h>
12
+#include <gpxe/init.h>
11
-#include <gpxe/embedded.h>
12
 
13
 
13
-extern char _embedded_image_start[], _embedded_image_end[];
14
+/**
15
+ * Free embedded image
16
+ *
17
+ * @v refcnt		Reference counter
18
+ */
19
+static void embedded_image_free ( struct refcnt *refcnt __unused ) {
20
+	/* Do nothing */
21
+}
14
 
22
 
15
-struct image *embedded_image(void)
23
+/* Raw image data for all embedded images */
16
-{
24
+#undef EMBED
17
-	static int reclaimed = 0;
25
+#define EMBED( _index, _path, _name )					\
18
-	struct image *image;
26
+	extern char embedded_image_ ## _index ## _data[];		\
19
-	size_t eisize = _embedded_image_end - _embedded_image_start;
27
+	extern char embedded_image_ ## _index ## _len[];		\
28
+	__asm__ ( ".section \".rodata\", \"a\", @progbits\n\t"		\
29
+		  "\nembedded_image_" #_index "_data:\n\t"		\
30
+		  ".incbin \"" _path "\"\n\t"				\
31
+		  "\nembedded_image_" #_index "_end:\n\t"		\
32
+		  ".equ embedded_image_" #_index "_len, "		\
33
+			"( embedded_image_" #_index "_end - "		\
34
+			"  embedded_image_" #_index "_data )\n\t"	\
35
+		  ".previous\n\t" );
36
+EMBED_ALL
20
 
37
 
21
-	if ( !eisize )
38
+/* Image structures for all embedded images */
22
-		return NULL;	/* No embedded image */
39
+#undef EMBED
40
+#define EMBED( _index, _path, _name ) {					\
41
+	.refcnt = { .free = embedded_image_free, },			\
42
+	.name = _name,							\
43
+	.data = ( userptr_t ) ( embedded_image_ ## _index ## _data ),	\
44
+	.len = ( size_t ) embedded_image_ ## _index ## _len,		\
45
+},
46
+static struct image embedded_images[] = {
47
+	EMBED_ALL
48
+};
23
 
49
 
24
-	if ( reclaimed )
50
+/**
25
-		return NULL;	/* Already reclaimed */
51
+ * Register all embedded images
52
+ */
53
+static void embedded_init ( void ) {
54
+	unsigned int i;
55
+	struct image *image;
56
+	void *data;
57
+	int rc;
26
 
58
 
27
-	DBG ( "Embedded image: %zd bytes at %p\n",
59
+	/* Fix up data pointers and register images */
28
-	      eisize, _embedded_image_start );
60
+	for ( i = 0 ; i < ( sizeof ( embedded_images ) /
61
+			    sizeof ( embedded_images[0] ) ) ; i++ ) {
62
+		image = &embedded_images[i];
29
 
63
 
30
-	image = alloc_image();
64
+		/* virt_to_user() cannot be used in a static
31
-	if (!image)
65
+		 * initialiser, so we cast the pointer to a userptr_t
32
-		return NULL;
66
+		 * in the initialiser and fix it up here.  (This will
67
+		 * actually be a no-op on most platforms.)
68
+		 */
69
+		data = ( ( void * ) image->data );
70
+		image->data = virt_to_user ( data );
33
 
71
 
34
-	image->len     = eisize;
72
+		DBG ( "Embedded image \"%s\": %zd bytes at %p\n",
35
-	image->data    = umalloc(eisize);
73
+		      image->name, image->len, data );
36
-	if (image->data == UNULL) {
37
-		image_put(image);
38
-		return image = NULL;
39
-	}
40
-	copy_to_user(image->data, 0, _embedded_image_start, eisize);
41
-	register_image(image);
42
 
74
 
43
-	/* Reclaim embedded image memory */
75
+		if ( ( rc = register_image ( image ) ) != 0 ) {
44
-	reclaimed = 1;
76
+			DBG ( "Could not register embedded image \"%s\": "
45
-	mpopulate(_embedded_image_start, eisize);
77
+			      "%s\n", image->name, strerror ( rc ) );
78
+			return;
79
+		}
80
+	}
46
 
81
 
47
-	return image;
82
+	/* Load the first image */
83
+	image = &embedded_images[0];
84
+	if ( ( rc = image_autoload ( image ) ) != 0 ) {
85
+		DBG ( "Could not load embedded image \"%s\": %s\n",
86
+		      image->name, strerror ( rc ) );
87
+		return;
88
+	}
48
 }
89
 }
49
 
90
 
91
+/** Embedded image initialisation function */
92
+struct init_fn embedded_init_fn __init_fn ( INIT_NORMAL ) = {
93
+	.initialise = embedded_init,
94
+};

+ 0
- 9
src/include/gpxe/embedded.h Переглянути файл

1
-#ifndef _GPXE_EMBEDDED_H
2
-#define _GPXE_EMBEDDED_H
3
-
4
-#include <gpxe/image.h>
5
-
6
-struct image *embedded_image(void);
7
-
8
-#endif
9
-

+ 1
- 0
src/include/gpxe/errfile.h Переглянути файл

145
 #define ERRFILE_script		      ( ERRFILE_IMAGE | 0x00020000 )
145
 #define ERRFILE_script		      ( ERRFILE_IMAGE | 0x00020000 )
146
 #define ERRFILE_segment		      ( ERRFILE_IMAGE | 0x00030000 )
146
 #define ERRFILE_segment		      ( ERRFILE_IMAGE | 0x00030000 )
147
 #define ERRFILE_efi_image	      ( ERRFILE_IMAGE | 0x00040000 )
147
 #define ERRFILE_efi_image	      ( ERRFILE_IMAGE | 0x00040000 )
148
+#define ERRFILE_embedded	      ( ERRFILE_IMAGE | 0x00050000 )
148
 
149
 
149
 #define ERRFILE_asn1		      ( ERRFILE_OTHER | 0x00000000 )
150
 #define ERRFILE_asn1		      ( ERRFILE_OTHER | 0x00000000 )
150
 #define ERRFILE_chap		      ( ERRFILE_OTHER | 0x00010000 )
151
 #define ERRFILE_chap		      ( ERRFILE_OTHER | 0x00010000 )

+ 1
- 0
src/include/gpxe/uri.h Переглянути файл

7
  *
7
  *
8
  */
8
  */
9
 
9
 
10
+#include <stddef.h>
10
 #include <stdlib.h>
11
 #include <stdlib.h>
11
 #include <gpxe/refcnt.h>
12
 #include <gpxe/refcnt.h>
12
 
13
 

+ 0
- 30
src/usr/autoboot.c Переглянути файл

23
 #include <gpxe/dhcp.h>
23
 #include <gpxe/dhcp.h>
24
 #include <gpxe/settings.h>
24
 #include <gpxe/settings.h>
25
 #include <gpxe/image.h>
25
 #include <gpxe/image.h>
26
-#include <gpxe/embedded.h>
27
 #include <gpxe/sanboot.h>
26
 #include <gpxe/sanboot.h>
28
 #include <gpxe/uri.h>
27
 #include <gpxe/uri.h>
29
 #include <usr/ifmgmt.h>
28
 #include <usr/ifmgmt.h>
59
 	return NULL;
58
 	return NULL;
60
 }
59
 }
61
 
60
 
62
-/**
63
- * Boot embedded image
64
- *
65
- * @ret rc		Return status code
66
- */
67
-static int boot_embedded_image ( void ) {
68
-	struct image *image;
69
-	int rc;
70
-
71
-	image = embedded_image();
72
-	if ( !image )
73
-		return ENOENT;
74
-
75
-	if ( ( rc = imgload ( image ) ) != 0 ) {
76
-		printf ( "Could not load embedded image: %s\n",
77
-			 strerror ( rc ) );
78
-	} else if ( ( rc = imgexec ( image ) ) != 0 ) {
79
-		printf ( "Could not boot embedded image: %s\n",
80
-			 strerror ( rc ) );
81
-	}
82
-	image_put ( image );
83
-	return rc;
84
-}
85
-
86
 /**
61
 /**
87
  * Boot using next-server and filename
62
  * Boot using next-server and filename
88
  *
63
  *
196
 		return rc;
171
 		return rc;
197
 	route();
172
 	route();
198
 
173
 
199
-	/* Try to boot an embedded image if we have one */
200
-	rc = boot_embedded_image ();
201
-	if ( rc != ENOENT )
202
-		return rc;
203
-
204
 	/* Try PXE menu boot, if applicable */
174
 	/* Try PXE menu boot, if applicable */
205
 	fetch_string_setting ( NULL, &vendor_class_id_setting,
175
 	fetch_string_setting ( NULL, &vendor_class_id_setting,
206
 			       buf, sizeof ( buf ) );
176
 			       buf, sizeof ( buf ) );

Завантаження…
Відмінити
Зберегти