Browse Source

[image] Simplify image management

Refactor the {load,exec} image operations as {probe,exec}.  This makes
the probe mechanism cleaner, eliminates some forward declarations,
avoids holding magic state in image->priv, eliminates the possibility
of screwing up between the "load" and "exec" stages, and makes the
documentation simpler since the concept of "loading" (as distinct from
"executing") no longer needs to be explained.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 13 years ago
parent
commit
34b6ecb2f1

+ 30
- 40
src/arch/i386/image/bzimage.c View File

41
 
41
 
42
 FEATURE ( FEATURE_IMAGE, "bzImage", DHCP_EB_FEATURE_BZIMAGE, 1 );
42
 FEATURE ( FEATURE_IMAGE, "bzImage", DHCP_EB_FEATURE_BZIMAGE, 1 );
43
 
43
 
44
-struct image_type bzimage_image_type __image_type ( PROBE_NORMAL );
45
-
46
 /**
44
 /**
47
  * bzImage context
45
  * bzImage context
48
  */
46
  */
111
 			 sizeof ( bzimg->bzhdr ) );
109
 			 sizeof ( bzimg->bzhdr ) );
112
 
110
 
113
 	/* Calculate size of real-mode portion */
111
 	/* Calculate size of real-mode portion */
114
-	bzimg->rm_filesz =
115
-		( ( bzimg->bzhdr.setup_sects ? bzimg->bzhdr.setup_sects : 4 ) + 1 ) << 9;
112
+	bzimg->rm_filesz = ( ( ( bzimg->bzhdr.setup_sects ?
113
+				 bzimg->bzhdr.setup_sects : 4 ) + 1 ) << 9 );
116
 	if ( bzimg->rm_filesz > image->len ) {
114
 	if ( bzimg->rm_filesz > image->len ) {
117
 		DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
115
 		DBGC ( image, "bzImage %p too short for %zd byte of setup\n",
118
 		       image, bzimg->rm_filesz );
116
 		       image, bzimg->rm_filesz );
455
 	const char *cmdline = ( image->cmdline ? image->cmdline : "" );
453
 	const char *cmdline = ( image->cmdline ? image->cmdline : "" );
456
 	int rc;
454
 	int rc;
457
 
455
 
458
-	/* Read and parse header from loaded kernel */
456
+	/* Read and parse header from image */
459
 	if ( ( rc = bzimage_parse_header ( image, &bzimg,
457
 	if ( ( rc = bzimage_parse_header ( image, &bzimg,
460
-					   image->priv.user ) ) != 0 )
458
+					   image->data ) ) != 0 )
459
+		return rc;
460
+
461
+	/* Prepare segments */
462
+	if ( ( rc = prep_segment ( bzimg.rm_kernel, bzimg.rm_filesz,
463
+				   bzimg.rm_memsz ) ) != 0 ) {
464
+		DBGC ( image, "bzImage %p could not prepare RM segment: %s\n",
465
+		       image, strerror ( rc ) );
466
+		return rc;
467
+	}
468
+	if ( ( rc = prep_segment ( bzimg.pm_kernel, bzimg.pm_sz,
469
+				   bzimg.pm_sz ) ) != 0 ) {
470
+		DBGC ( image, "bzImage %p could not prepare PM segment: %s\n",
471
+		       image, strerror ( rc ) );
461
 		return rc;
472
 		return rc;
462
-	assert ( bzimg.rm_kernel == image->priv.user );
473
+	}
474
+
475
+	/* Load segments */
476
+	memcpy_user ( bzimg.rm_kernel, 0, image->data,
477
+		      0, bzimg.rm_filesz );
478
+	memcpy_user ( bzimg.pm_kernel, 0, image->data,
479
+		      bzimg.rm_filesz, bzimg.pm_sz );
480
+
481
+	/* Update and write out header */
482
+	bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
463
 
483
 
464
 	/* Parse command line for bootloader parameters */
484
 	/* Parse command line for bootloader parameters */
465
 	if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
485
 	if ( ( rc = bzimage_parse_cmdline ( image, &bzimg, cmdline ) ) != 0)
506
 }
526
 }
507
 
527
 
508
 /**
528
 /**
509
- * Load bzImage image into memory
529
+ * Probe bzImage image
510
  *
530
  *
511
  * @v image		bzImage file
531
  * @v image		bzImage file
512
  * @ret rc		Return status code
532
  * @ret rc		Return status code
513
  */
533
  */
514
-int bzimage_load ( struct image *image ) {
534
+int bzimage_probe ( struct image *image ) {
515
 	struct bzimage_context bzimg;
535
 	struct bzimage_context bzimg;
516
 	int rc;
536
 	int rc;
517
 
537
 
520
 					   image->data ) ) != 0 )
540
 					   image->data ) ) != 0 )
521
 		return rc;
541
 		return rc;
522
 
542
 
523
-	/* This is a bzImage image, valid or otherwise */
524
-	if ( ! image->type )
525
-		image->type = &bzimage_image_type;
526
-
527
-	/* Prepare segments */
528
-	if ( ( rc = prep_segment ( bzimg.rm_kernel, bzimg.rm_filesz,
529
-				   bzimg.rm_memsz ) ) != 0 ) {
530
-		DBGC ( image, "bzImage %p could not prepare RM segment: %s\n",
531
-		       image, strerror ( rc ) );
532
-		return rc;
533
-	}
534
-	if ( ( rc = prep_segment ( bzimg.pm_kernel, bzimg.pm_sz,
535
-				   bzimg.pm_sz ) ) != 0 ) {
536
-		DBGC ( image, "bzImage %p could not prepare PM segment: %s\n",
537
-		       image, strerror ( rc ) );
538
-		return rc;
539
-	}
540
-
541
-	/* Load segments */
542
-	memcpy_user ( bzimg.rm_kernel, 0, image->data,
543
-		      0, bzimg.rm_filesz );
544
-	memcpy_user ( bzimg.pm_kernel, 0, image->data,
545
-		      bzimg.rm_filesz, bzimg.pm_sz );
546
-
547
-	/* Update and write out header */
548
-	bzimage_update_header ( image, &bzimg, bzimg.rm_kernel );
549
-
550
-	/* Record real-mode segment in image private data field */
551
-	image->priv.user = bzimg.rm_kernel;
552
-
553
 	return 0;
543
 	return 0;
554
 }
544
 }
555
 
545
 
556
 /** Linux bzImage image type */
546
 /** Linux bzImage image type */
557
 struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ) = {
547
 struct image_type bzimage_image_type __image_type ( PROBE_NORMAL ) = {
558
 	.name = "bzImage",
548
 	.name = "bzImage",
559
-	.load = bzimage_load,
549
+	.probe = bzimage_probe,
560
 	.exec = bzimage_exec,
550
 	.exec = bzimage_exec,
561
 };
551
 };

+ 20
- 15
src/arch/i386/image/com32.c View File

40
 #include <ipxe/init.h>
40
 #include <ipxe/init.h>
41
 #include <ipxe/io.h>
41
 #include <ipxe/io.h>
42
 
42
 
43
-struct image_type com32_image_type __image_type ( PROBE_NORMAL );
44
-
45
 struct idt_register com32_external_idtr = {
43
 struct idt_register com32_external_idtr = {
46
 	.limit = COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) - 1,
44
 	.limit = COM32_NUM_IDT_ENTRIES * sizeof ( struct idt_descriptor ) - 1,
47
 	.base = COM32_IDT
45
 	.base = COM32_IDT
55
  * @v image		COM32 image
53
  * @v image		COM32 image
56
  * @ret rc		Return status code
54
  * @ret rc		Return status code
57
  */
55
  */
58
-static int com32_exec ( struct image *image ) {
56
+static int com32_exec_loop ( struct image *image ) {
59
 	struct memory_map memmap;
57
 	struct memory_map memmap;
60
 	unsigned int i;
58
 	unsigned int i;
61
 	int state;
59
 	int state;
137
 		       image, comboot_replacement_image );
135
 		       image, comboot_replacement_image );
138
 		image->replacement = comboot_replacement_image;
136
 		image->replacement = comboot_replacement_image;
139
 		comboot_replacement_image = NULL;
137
 		comboot_replacement_image = NULL;
140
-		image_autoload ( image->replacement );
141
 		break;
138
 		break;
142
 
139
 
143
 	case COMBOOT_EXIT_COMMAND:
140
 	case COMBOOT_EXIT_COMMAND:
207
  * @v image		COM32 image
204
  * @v image		COM32 image
208
  * @ret rc		Return status code
205
  * @ret rc		Return status code
209
  */
206
  */
210
-static int comboot_load_image ( struct image *image ) {
207
+static int com32_load_image ( struct image *image ) {
211
 	physaddr_t com32_irq_wrapper_phys;
208
 	physaddr_t com32_irq_wrapper_phys;
212
 	struct idt_descriptor *idt;
209
 	struct idt_descriptor *idt;
213
 	struct ijb_entry *ijb;
210
 	struct ijb_entry *ijb;
262
  * @v image		COM32 image
259
  * @v image		COM32 image
263
  * @ret rc		Return status code
260
  * @ret rc		Return status code
264
  */
261
  */
265
-static int comboot_prepare_bounce_buffer ( struct image * image ) {
262
+static int com32_prepare_bounce_buffer ( struct image * image ) {
266
 	unsigned int seg;
263
 	unsigned int seg;
267
 	userptr_t seg_userptr;
264
 	userptr_t seg_userptr;
268
 	size_t filesz, memsz;
265
 	size_t filesz, memsz;
286
 }
283
 }
287
 
284
 
288
 /**
285
 /**
289
- * Load COM32 image into memory
286
+ * Probe COM32 image
290
  *
287
  *
291
  * @v image		COM32 image
288
  * @v image		COM32 image
292
  * @ret rc		Return status code
289
  * @ret rc		Return status code
293
  */
290
  */
294
-static int com32_load ( struct image *image ) {
291
+static int com32_probe ( struct image *image ) {
295
 	int rc;
292
 	int rc;
296
 
293
 
297
 	DBGC ( image, "COM32 %p: name '%s', cmdline '%s'\n",
294
 	DBGC ( image, "COM32 %p: name '%s', cmdline '%s'\n",
302
 		return rc;
299
 		return rc;
303
 	}
300
 	}
304
 
301
 
305
-	/* This is a COM32 image, valid or otherwise */
306
-	if ( ! image->type )
307
-		image->type = &com32_image_type;
302
+	return 0;
303
+}
304
+
305
+/**
306
+ * Execute COMBOOT image
307
+ *
308
+ * @v image		COM32 image
309
+ * @ret rc		Return status code
310
+ */
311
+static int com32_exec ( struct image *image ) {
312
+	int rc;
308
 
313
 
309
 	/* Load image */
314
 	/* Load image */
310
-	if ( ( rc = comboot_load_image ( image ) ) != 0 ) {
315
+	if ( ( rc = com32_load_image ( image ) ) != 0 ) {
311
 		return rc;
316
 		return rc;
312
 	}
317
 	}
313
 
318
 
314
 	/* Prepare bounce buffer segment */
319
 	/* Prepare bounce buffer segment */
315
-	if ( ( rc = comboot_prepare_bounce_buffer ( image ) ) != 0 ) {
320
+	if ( ( rc = com32_prepare_bounce_buffer ( image ) ) != 0 ) {
316
 		return rc;
321
 		return rc;
317
 	}
322
 	}
318
 
323
 
319
-	return 0;
324
+	return com32_exec_loop ( image );
320
 }
325
 }
321
 
326
 
322
 /** SYSLINUX COM32 image type */
327
 /** SYSLINUX COM32 image type */
323
 struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = {
328
 struct image_type com32_image_type __image_type ( PROBE_NORMAL ) = {
324
 	.name = "COM32",
329
 	.name = "COM32",
325
-	.load = com32_load,
330
+	.probe = com32_probe,
326
 	.exec = com32_exec,
331
 	.exec = com32_exec,
327
 };
332
 };

+ 16
- 11
src/arch/i386/image/comboot.c View File

42
 
42
 
43
 FEATURE ( FEATURE_IMAGE, "COMBOOT", DHCP_EB_FEATURE_COMBOOT, 1 );
43
 FEATURE ( FEATURE_IMAGE, "COMBOOT", DHCP_EB_FEATURE_COMBOOT, 1 );
44
 
44
 
45
-struct image_type comboot_image_type __image_type ( PROBE_NORMAL );
46
-
47
 /**
45
 /**
48
  * COMBOOT PSP, copied to offset 0 of code segment
46
  * COMBOOT PSP, copied to offset 0 of code segment
49
  */
47
  */
131
  * @v image		COMBOOT image
129
  * @v image		COMBOOT image
132
  * @ret rc		Return status code
130
  * @ret rc		Return status code
133
  */
131
  */
134
-static int comboot_exec ( struct image *image ) {
132
+static int comboot_exec_loop ( struct image *image ) {
135
 	userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
133
 	userptr_t seg_userptr = real_to_user ( COMBOOT_PSP_SEG, 0 );
136
 	int state;
134
 	int state;
137
 
135
 
194
 		       image, comboot_replacement_image );
192
 		       image, comboot_replacement_image );
195
 		image->replacement = comboot_replacement_image;
193
 		image->replacement = comboot_replacement_image;
196
 		comboot_replacement_image = NULL;
194
 		comboot_replacement_image = NULL;
197
-		image_autoload ( image->replacement );
198
 		break;
195
 		break;
199
 
196
 
200
 	case COMBOOT_EXIT_COMMAND:
197
 	case COMBOOT_EXIT_COMMAND:
278
 }
275
 }
279
 
276
 
280
 /**
277
 /**
281
- * Load COMBOOT image into memory
278
+ * Probe COMBOOT image
282
  *
279
  *
283
  * @v image		COMBOOT image
280
  * @v image		COMBOOT image
284
  * @ret rc		Return status code
281
  * @ret rc		Return status code
285
  */
282
  */
286
-static int comboot_load ( struct image *image ) {
283
+static int comboot_probe ( struct image *image ) {
287
 	int rc;
284
 	int rc;
288
 
285
 
289
 	DBGC ( image, "COMBOOT %p: name '%s'\n",
286
 	DBGC ( image, "COMBOOT %p: name '%s'\n",
295
 		return rc;
292
 		return rc;
296
 	}
293
 	}
297
 
294
 
298
-	/* This is a 16-bit COMBOOT image, valid or otherwise */
299
-	if ( ! image->type )
300
-		image->type = &comboot_image_type;
295
+	return 0;
296
+}
297
+
298
+/**
299
+ * Execute COMBOOT image
300
+ *
301
+ * @v image		COMBOOT image
302
+ * @ret rc		Return status code
303
+ */
304
+static int comboot_exec ( struct image *image ) {
305
+	int rc;
301
 	
306
 	
302
 	/* Sanity check for filesize */
307
 	/* Sanity check for filesize */
303
 	if( image->len >= 0xFF00 ) {
308
 	if( image->len >= 0xFF00 ) {
311
 		return rc;
316
 		return rc;
312
 	}
317
 	}
313
 
318
 
314
-	return 0;
319
+	return comboot_exec_loop ( image );
315
 }
320
 }
316
 
321
 
317
 /** SYSLINUX COMBOOT (16-bit) image type */
322
 /** SYSLINUX COMBOOT (16-bit) image type */
318
 struct image_type comboot_image_type __image_type ( PROBE_NORMAL ) = {
323
 struct image_type comboot_image_type __image_type ( PROBE_NORMAL ) = {
319
 	.name = "COMBOOT",
324
 	.name = "COMBOOT",
320
-	.load = comboot_load,
325
+	.probe = comboot_probe,
321
 	.exec = comboot_exec,
326
 	.exec = comboot_exec,
322
 };
327
 };

+ 12
- 18
src/arch/i386/image/elfboot.c View File

34
 
34
 
35
 FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 );
35
 FEATURE ( FEATURE_IMAGE, "ELF", DHCP_EB_FEATURE_ELF, 1 );
36
 
36
 
37
-struct image_type elfboot_image_type __image_type ( PROBE_NORMAL );
38
-
39
 /**
37
 /**
40
  * Execute ELF image
38
  * Execute ELF image
41
  *
39
  *
43
  * @ret rc		Return status code
41
  * @ret rc		Return status code
44
  */
42
  */
45
 static int elfboot_exec ( struct image *image ) {
43
 static int elfboot_exec ( struct image *image ) {
46
-	physaddr_t entry = image->priv.phys;
44
+	physaddr_t entry;
45
+	int rc;
46
+
47
+	/* Load the image using core ELF support */
48
+	if ( ( rc = elf_load ( image, &entry ) ) != 0 ) {
49
+		DBGC ( image, "ELF %p could not load: %s\n",
50
+		       image, strerror ( rc ) );
51
+		return rc;
52
+	}
47
 
53
 
48
 	/* An ELF image has no callback interface, so we need to shut
54
 	/* An ELF image has no callback interface, so we need to shut
49
 	 * down before invoking it.
55
 	 * down before invoking it.
66
 }
72
 }
67
 
73
 
68
 /**
74
 /**
69
- * Load ELF image into memory
75
+ * Probe ELF image
70
  *
76
  *
71
  * @v image		ELF file
77
  * @v image		ELF file
72
  * @ret rc		Return status code
78
  * @ret rc		Return status code
73
  */
79
  */
74
-static int elfboot_load ( struct image *image ) {
80
+static int elfboot_probe ( struct image *image ) {
75
 	Elf32_Ehdr ehdr;
81
 	Elf32_Ehdr ehdr;
76
 	static const uint8_t e_ident[] = {
82
 	static const uint8_t e_ident[] = {
77
 		[EI_MAG0]	= ELFMAG0,
83
 		[EI_MAG0]	= ELFMAG0,
82
 		[EI_DATA]	= ELFDATA2LSB,
88
 		[EI_DATA]	= ELFDATA2LSB,
83
 		[EI_VERSION]	= EV_CURRENT,
89
 		[EI_VERSION]	= EV_CURRENT,
84
 	};
90
 	};
85
-	int rc;
86
 
91
 
87
 	/* Read ELF header */
92
 	/* Read ELF header */
88
 	copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
93
 	copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
91
 		return -ENOEXEC;
96
 		return -ENOEXEC;
92
 	}
97
 	}
93
 
98
 
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;
99
 	return 0;
106
 }
100
 }
107
 
101
 
108
 /** ELF image type */
102
 /** ELF image type */
109
 struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = {
103
 struct image_type elfboot_image_type __image_type ( PROBE_NORMAL ) = {
110
 	.name = "ELF",
104
 	.name = "ELF",
111
-	.load = elfboot_load,
105
+	.probe = elfboot_probe,
112
 	.exec = elfboot_exec,
106
 	.exec = elfboot_exec,
113
 };
107
 };

+ 76
- 70
src/arch/i386/image/multiboot.c View File

40
 
40
 
41
 FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
41
 FEATURE ( FEATURE_IMAGE, "MBOOT", DHCP_EB_FEATURE_MULTIBOOT, 1 );
42
 
42
 
43
-struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT );
44
-
45
 /**
43
 /**
46
  * Maximum number of modules we will allow for
44
  * Maximum number of modules we will allow for
47
  *
45
  *
254
 static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] );
252
 static struct multiboot_module __bss16_array ( mbmodules, [MAX_MODULES] );
255
 #define mbmodules __use_data16 ( mbmodules )
253
 #define mbmodules __use_data16 ( mbmodules )
256
 
254
 
257
-/**
258
- * Execute multiboot image
259
- *
260
- * @v image		Multiboot image
261
- * @ret rc		Return status code
262
- */
263
-static int multiboot_exec ( struct image *image ) {
264
-	physaddr_t entry = image->priv.phys;
265
-
266
-	/* Populate multiboot information structure */
267
-	memset ( &mbinfo, 0, sizeof ( mbinfo ) );
268
-	mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP |
269
-			 MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
270
-	mb_cmdline_offset = 0;
271
-	mbinfo.cmdline = multiboot_add_cmdline ( image->name, image->cmdline );
272
-	mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules,
273
-				( sizeof(mbmodules) / sizeof(mbmodules[0]) ) );
274
-	mbinfo.mods_addr = virt_to_phys ( mbmodules );
275
-	mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
276
-	mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
277
-
278
-	/* Multiboot images may not return and have no callback
279
-	 * interface, so shut everything down prior to booting the OS.
280
-	 */
281
-	shutdown_boot();
282
-
283
-	/* Build memory map after unhiding bootloader memory regions as part of
284
-	 * shutting everything down.
285
-	 */
286
-	multiboot_build_memmap ( image, &mbinfo, mbmemmap,
287
-				 ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
288
-
289
-	/* Jump to OS with flat physical addressing */
290
-	DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
291
-	       image, entry );
292
-	__asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t"
293
-					   "call *%%edi\n\t"
294
-					   "popl %%ebp\n\t" )
295
-			       : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
296
-			           "b" ( virt_to_phys ( &mbinfo ) ),
297
-			           "D" ( entry )
298
-			       : "ecx", "edx", "esi", "memory" );
299
-
300
-	DBGC ( image, "MULTIBOOT %p returned\n", image );
301
-
302
-	/* It isn't safe to continue after calling shutdown() */
303
-	while ( 1 ) {}
304
-
305
-	return -ECANCELED;  /* -EIMPOSSIBLE, anyone? */
306
-}
307
-
308
 /**
255
 /**
309
  * Find multiboot header
256
  * Find multiboot header
310
  *
257
  *
357
  *
304
  *
358
  * @v image		Multiboot file
305
  * @v image		Multiboot file
359
  * @v hdr		Multiboot header descriptor
306
  * @v hdr		Multiboot header descriptor
307
+ * @ret entry		Entry point
360
  * @ret rc		Return status code
308
  * @ret rc		Return status code
361
  */
309
  */
362
 static int multiboot_load_raw ( struct image *image,
310
 static int multiboot_load_raw ( struct image *image,
363
-				struct multiboot_header_info *hdr ) {
311
+				struct multiboot_header_info *hdr,
312
+				physaddr_t *entry ) {
364
 	size_t offset;
313
 	size_t offset;
365
 	size_t filesz;
314
 	size_t filesz;
366
 	size_t memsz;
315
 	size_t memsz;
391
 	/* Copy image to segment */
340
 	/* Copy image to segment */
392
 	memcpy_user ( buffer, 0, image->data, offset, filesz );
341
 	memcpy_user ( buffer, 0, image->data, offset, filesz );
393
 
342
 
394
-	/* Record execution entry point in image private data field */
395
-	image->priv.phys = hdr->mb.entry_addr;
343
+	/* Record execution entry point */
344
+	*entry = hdr->mb.entry_addr;
396
 
345
 
397
 	return 0;
346
 	return 0;
398
 }
347
 }
401
  * Load ELF multiboot image into memory
350
  * Load ELF multiboot image into memory
402
  *
351
  *
403
  * @v image		Multiboot file
352
  * @v image		Multiboot file
353
+ * @ret entry		Entry point
404
  * @ret rc		Return status code
354
  * @ret rc		Return status code
405
  */
355
  */
406
-static int multiboot_load_elf ( struct image *image ) {
356
+static int multiboot_load_elf ( struct image *image, physaddr_t *entry ) {
407
 	int rc;
357
 	int rc;
408
 
358
 
409
 	/* Load ELF image*/
359
 	/* Load ELF image*/
410
-	if ( ( rc = elf_load ( image ) ) != 0 ) {
360
+	if ( ( rc = elf_load ( image, entry ) ) != 0 ) {
411
 		DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n",
361
 		DBGC ( image, "MULTIBOOT %p ELF image failed to load: %s\n",
412
 		       image, strerror ( rc ) );
362
 		       image, strerror ( rc ) );
413
 		return rc;
363
 		return rc;
417
 }
367
 }
418
 
368
 
419
 /**
369
 /**
420
- * Load multiboot image into memory
370
+ * Execute multiboot image
421
  *
371
  *
422
- * @v image		Multiboot file
372
+ * @v image		Multiboot image
423
  * @ret rc		Return status code
373
  * @ret rc		Return status code
424
  */
374
  */
425
-static int multiboot_load ( struct image *image ) {
375
+static int multiboot_exec ( struct image *image ) {
426
 	struct multiboot_header_info hdr;
376
 	struct multiboot_header_info hdr;
377
+	physaddr_t entry;
427
 	int rc;
378
 	int rc;
428
 
379
 
429
 	/* Locate multiboot header, if present */
380
 	/* Locate multiboot header, if present */
432
 		       image );
383
 		       image );
433
 		return rc;
384
 		return rc;
434
 	}
385
 	}
435
-	DBGC ( image, "MULTIBOOT %p found header with flags %08x\n",
436
-	       image, hdr.mb.flags );
437
-
438
-	/* This is a multiboot image, valid or otherwise */
439
-	if ( ! image->type )
440
-		image->type = &multiboot_image_type;
441
 
386
 
442
 	/* Abort if we detect flags that we cannot support */
387
 	/* Abort if we detect flags that we cannot support */
443
 	if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
388
 	if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
451
 	 * the ELF header if present, and Solaris relies on this
396
 	 * the ELF header if present, and Solaris relies on this
452
 	 * behaviour.
397
 	 * behaviour.
453
 	 */
398
 	 */
454
-	if ( ( ( rc = multiboot_load_elf ( image ) ) != 0 ) &&
455
-	     ( ( rc = multiboot_load_raw ( image, &hdr ) ) != 0 ) )
399
+	if ( ( ( rc = multiboot_load_elf ( image, &entry ) ) != 0 ) &&
400
+	     ( ( rc = multiboot_load_raw ( image, &hdr, &entry ) ) != 0 ) )
456
 		return rc;
401
 		return rc;
457
 
402
 
403
+	/* Populate multiboot information structure */
404
+	memset ( &mbinfo, 0, sizeof ( mbinfo ) );
405
+	mbinfo.flags = ( MBI_FLAG_LOADER | MBI_FLAG_MEM | MBI_FLAG_MMAP |
406
+			 MBI_FLAG_CMDLINE | MBI_FLAG_MODS );
407
+	mb_cmdline_offset = 0;
408
+	mbinfo.cmdline = multiboot_add_cmdline ( image->name, image->cmdline );
409
+	mbinfo.mods_count = multiboot_build_module_list ( image, mbmodules,
410
+				( sizeof(mbmodules) / sizeof(mbmodules[0]) ) );
411
+	mbinfo.mods_addr = virt_to_phys ( mbmodules );
412
+	mbinfo.mmap_addr = virt_to_phys ( mbmemmap );
413
+	mbinfo.boot_loader_name = virt_to_phys ( mb_bootloader_name );
414
+
415
+	/* Multiboot images may not return and have no callback
416
+	 * interface, so shut everything down prior to booting the OS.
417
+	 */
418
+	shutdown_boot();
419
+
420
+	/* Build memory map after unhiding bootloader memory regions as part of
421
+	 * shutting everything down.
422
+	 */
423
+	multiboot_build_memmap ( image, &mbinfo, mbmemmap,
424
+				 ( sizeof(mbmemmap) / sizeof(mbmemmap[0]) ) );
425
+
426
+	/* Jump to OS with flat physical addressing */
427
+	DBGC ( image, "MULTIBOOT %p starting execution at %lx\n",
428
+	       image, entry );
429
+	__asm__ __volatile__ ( PHYS_CODE ( "pushl %%ebp\n\t"
430
+					   "call *%%edi\n\t"
431
+					   "popl %%ebp\n\t" )
432
+			       : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
433
+			           "b" ( virt_to_phys ( &mbinfo ) ),
434
+			           "D" ( entry )
435
+			       : "ecx", "edx", "esi", "memory" );
436
+
437
+	DBGC ( image, "MULTIBOOT %p returned\n", image );
438
+
439
+	/* It isn't safe to continue after calling shutdown() */
440
+	while ( 1 ) {}
441
+
442
+	return -ECANCELED;  /* -EIMPOSSIBLE, anyone? */
443
+}
444
+
445
+/**
446
+ * Probe multiboot image
447
+ *
448
+ * @v image		Multiboot file
449
+ * @ret rc		Return status code
450
+ */
451
+static int multiboot_probe ( struct image *image ) {
452
+	struct multiboot_header_info hdr;
453
+	int rc;
454
+
455
+	/* Locate multiboot header, if present */
456
+	if ( ( rc = multiboot_find_header ( image, &hdr ) ) != 0 ) {
457
+		DBGC ( image, "MULTIBOOT %p has no multiboot header\n",
458
+		       image );
459
+		return rc;
460
+	}
461
+	DBGC ( image, "MULTIBOOT %p found header with flags %08x\n",
462
+	       image, hdr.mb.flags );
463
+
458
 	return 0;
464
 	return 0;
459
 }
465
 }
460
 
466
 
461
 /** Multiboot image type */
467
 /** Multiboot image type */
462
 struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ) = {
468
 struct image_type multiboot_image_type __image_type ( PROBE_MULTIBOOT ) = {
463
 	.name = "Multiboot",
469
 	.name = "Multiboot",
464
-	.load = multiboot_load,
470
+	.probe = multiboot_probe,
465
 	.exec = multiboot_exec,
471
 	.exec = multiboot_exec,
466
 };
472
 };

+ 45
- 56
src/arch/i386/image/nbi.c View File

28
 
28
 
29
 FEATURE ( FEATURE_IMAGE, "NBI", DHCP_EB_FEATURE_NBI, 1 );
29
 FEATURE ( FEATURE_IMAGE, "NBI", DHCP_EB_FEATURE_NBI, 1 );
30
 
30
 
31
-struct image_type nbi_image_type __image_type ( PROBE_NORMAL );
32
-
33
 /**
31
 /**
34
  * An NBI image header
32
  * An NBI image header
35
  *
33
  *
240
 	return 0;
238
 	return 0;
241
 }
239
 }
242
 
240
 
243
-/**
244
- * Load an NBI image into memory
245
- *
246
- * @v image		NBI image
247
- * @ret rc		Return status code
248
- */
249
-static int nbi_load ( struct image *image ) {
250
-	struct imgheader imgheader;
251
-	int rc;
252
-
253
-	/* If we don't have enough data give up */
254
-	if ( image->len < NBI_HEADER_LENGTH ) {
255
-		DBGC ( image, "NBI %p too short for an NBI image\n", image );
256
-		return -ENOEXEC;
257
-	}
258
-
259
-	/* Check image header */
260
-	copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
261
-	if ( imgheader.magic != NBI_MAGIC ) {
262
-		DBGC ( image, "NBI %p has no NBI signature\n", image );
263
-		return -ENOEXEC;
264
-	}
265
-
266
-	/* This is an NBI image, valid or otherwise */
267
-	if ( ! image->type )
268
-		image->type = &nbi_image_type;
269
-
270
-	DBGC ( image, "NBI %p placing header at %hx:%hx\n", image,
271
-	       imgheader.location.segment, imgheader.location.offset );
272
-
273
-	/* NBI files can have overlaps between segments; the bss of
274
-	 * one segment may overlap the initialised data of another.  I
275
-	 * assume this is a design flaw, but there are images out
276
-	 * there that we need to work with.  We therefore do two
277
-	 * passes: first to initialise the segments, then to copy the
278
-	 * data.  This avoids zeroing out already-copied data.
279
-	 */
280
-	if ( ( rc = nbi_process_segments ( image, &imgheader,
281
-					   nbi_prepare_segment ) ) != 0 )
282
-		return rc;
283
-	if ( ( rc = nbi_process_segments ( image, &imgheader,
284
-					   nbi_load_segment ) ) != 0 )
285
-		return rc;
286
-
287
-	/* Record header address in image private data field */
288
-	image->priv.user = real_to_user ( imgheader.location.segment,
289
-					  imgheader.location.offset );
290
-
291
-	return 0;
292
-}
293
-
294
 /**
241
 /**
295
  * Boot a 16-bit NBI image
242
  * Boot a 16-bit NBI image
296
  *
243
  *
396
 	int may_return;
343
 	int may_return;
397
 	int rc;
344
 	int rc;
398
 
345
 
399
-	copy_from_user ( &imgheader, image->priv.user, 0,
400
-			 sizeof ( imgheader ) );
346
+	/* Retrieve image header */
347
+	copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
348
+
349
+	DBGC ( image, "NBI %p placing header at %hx:%hx\n", image,
350
+	       imgheader.location.segment, imgheader.location.offset );
351
+
352
+	/* NBI files can have overlaps between segments; the bss of
353
+	 * one segment may overlap the initialised data of another.  I
354
+	 * assume this is a design flaw, but there are images out
355
+	 * there that we need to work with.  We therefore do two
356
+	 * passes: first to initialise the segments, then to copy the
357
+	 * data.  This avoids zeroing out already-copied data.
358
+	 */
359
+	if ( ( rc = nbi_process_segments ( image, &imgheader,
360
+					   nbi_prepare_segment ) ) != 0 )
361
+		return rc;
362
+	if ( ( rc = nbi_process_segments ( image, &imgheader,
363
+					   nbi_load_segment ) ) != 0 )
364
+		return rc;
401
 
365
 
402
 	/* Prepare DHCP option block */
366
 	/* Prepare DHCP option block */
403
 	if ( ( rc = nbi_prepare_dhcp ( image ) ) != 0 )
367
 	if ( ( rc = nbi_prepare_dhcp ( image ) ) != 0 )
427
 	return rc;
391
 	return rc;
428
 }
392
 }
429
 
393
 
394
+/**
395
+ * Probe NBI image
396
+ *
397
+ * @v image		NBI image
398
+ * @ret rc		Return status code
399
+ */
400
+static int nbi_probe ( struct image *image ) {
401
+	struct imgheader imgheader;
402
+
403
+	/* If we don't have enough data give up */
404
+	if ( image->len < NBI_HEADER_LENGTH ) {
405
+		DBGC ( image, "NBI %p too short for an NBI image\n", image );
406
+		return -ENOEXEC;
407
+	}
408
+
409
+	/* Check image header */
410
+	copy_from_user ( &imgheader, image->data, 0, sizeof ( imgheader ) );
411
+	if ( imgheader.magic != NBI_MAGIC ) {
412
+		DBGC ( image, "NBI %p has no NBI signature\n", image );
413
+		return -ENOEXEC;
414
+	}
415
+
416
+	return 0;
417
+}
418
+
430
 /** NBI image type */
419
 /** NBI image type */
431
 struct image_type nbi_image_type __image_type ( PROBE_NORMAL ) = {
420
 struct image_type nbi_image_type __image_type ( PROBE_NORMAL ) = {
432
 	.name = "NBI",
421
 	.name = "NBI",
433
-	.load = nbi_load,
422
+	.probe = nbi_probe,
434
 	.exec = nbi_exec,
423
 	.exec = nbi_exec,
435
 };
424
 };

+ 16
- 25
src/arch/i386/image/pxe_image.c View File

35
 
35
 
36
 FEATURE ( FEATURE_IMAGE, "PXE", DHCP_EB_FEATURE_PXE, 1 );
36
 FEATURE ( FEATURE_IMAGE, "PXE", DHCP_EB_FEATURE_PXE, 1 );
37
 
37
 
38
-struct image_type pxe_image_type __image_type ( PROBE_PXE );
39
-
40
 /**
38
 /**
41
  * Execute PXE image
39
  * Execute PXE image
42
  *
40
  *
44
  * @ret rc		Return status code
42
  * @ret rc		Return status code
45
  */
43
  */
46
 static int pxe_exec ( struct image *image ) {
44
 static int pxe_exec ( struct image *image ) {
45
+	userptr_t buffer = real_to_user ( 0, 0x7c00 );
47
 	struct net_device *netdev;
46
 	struct net_device *netdev;
48
 	int rc;
47
 	int rc;
49
 
48
 
49
+	/* Verify and prepare segment */
50
+	if ( ( rc = prep_segment ( buffer, image->len, image->len ) ) != 0 ) {
51
+		DBGC ( image, "IMAGE %p could not prepare segment: %s\n",
52
+		       image, strerror ( rc ) );
53
+		return rc;
54
+	}
55
+
56
+	/* Copy image to segment */
57
+	memcpy_user ( buffer, 0, image->data, 0, image->len );
58
+
50
 	/* Arbitrarily pick the most recently opened network device */
59
 	/* Arbitrarily pick the most recently opened network device */
51
 	if ( ( netdev = last_opened_netdev() ) == NULL ) {
60
 	if ( ( netdev = last_opened_netdev() ) == NULL ) {
52
 		DBGC ( image, "IMAGE %p could not locate PXE net device\n",
61
 		DBGC ( image, "IMAGE %p could not locate PXE net device\n",
67
 }
76
 }
68
 
77
 
69
 /**
78
 /**
70
- * Load PXE image into memory
79
+ * Probe PXE image
71
  *
80
  *
72
  * @v image		PXE file
81
  * @v image		PXE file
73
  * @ret rc		Return status code
82
  * @ret rc		Return status code
74
  */
83
  */
75
-int pxe_load ( struct image *image ) {
76
-	userptr_t buffer = real_to_user ( 0, 0x7c00 );
77
-	size_t filesz = image->len;
78
-	size_t memsz = image->len;
79
-	int rc;
84
+int pxe_probe ( struct image *image ) {
80
 
85
 
81
 	/* Images too large to fit in base memory cannot be PXE
86
 	/* Images too large to fit in base memory cannot be PXE
82
 	 * images.  We include this check to help prevent unrecognised
87
 	 * images.  We include this check to help prevent unrecognised
83
 	 * images from being marked as PXE images, since PXE images
88
 	 * images from being marked as PXE images, since PXE images
84
 	 * have no signature we can check against.
89
 	 * have no signature we can check against.
85
 	 */
90
 	 */
86
-	if ( filesz > ( 0xa0000 - 0x7c00 ) )
91
+	if ( image->len > ( 0xa0000 - 0x7c00 ) )
87
 		return -ENOEXEC;
92
 		return -ENOEXEC;
88
 
93
 
89
 	/* Rejecting zero-length images is also useful, since these
94
 	/* Rejecting zero-length images is also useful, since these
90
 	 * end up looking to the user like bugs in iPXE.
95
 	 * end up looking to the user like bugs in iPXE.
91
 	 */
96
 	 */
92
-	if ( ! filesz )
97
+	if ( ! image->len )
93
 		return -ENOEXEC;
98
 		return -ENOEXEC;
94
 
99
 
95
-	/* There are no signature checks for PXE; we will accept anything */
96
-	if ( ! image->type )
97
-		image->type = &pxe_image_type;
98
-
99
-	/* Verify and prepare segment */
100
-	if ( ( rc = prep_segment ( buffer, filesz, memsz ) ) != 0 ) {
101
-		DBGC ( image, "IMAGE %p could not prepare segment: %s\n",
102
-		       image, strerror ( rc ) );
103
-		return rc;
104
-	}
105
-
106
-	/* Copy image to segment */
107
-	memcpy_user ( buffer, 0, image->data, 0, filesz );
108
-
109
 	return 0;
100
 	return 0;
110
 }
101
 }
111
 
102
 
112
 /** PXE image type */
103
 /** PXE image type */
113
 struct image_type pxe_image_type __image_type ( PROBE_PXE ) = {
104
 struct image_type pxe_image_type __image_type ( PROBE_PXE ) = {
114
 	.name = "PXE",
105
 	.name = "PXE",
115
-	.load = pxe_load,
106
+	.probe = pxe_probe,
116
 	.exec = pxe_exec,
107
 	.exec = pxe_exec,
117
 };
108
 };

+ 1
- 1
src/arch/i386/interface/syslinux/comboot_call.c View File

217
 		goto out;
217
 		goto out;
218
 	}
218
 	}
219
 	if ( ( rc = imgfetch ( kernel, kernel_file,
219
 	if ( ( rc = imgfetch ( kernel, kernel_file,
220
-			       register_image ) ) != 0 ) {
220
+			       register_and_select_image ) ) != 0 ) {
221
 		DBG ( "COMBOOT: could not fetch kernel: %s\n",
221
 		DBG ( "COMBOOT: could not fetch kernel: %s\n",
222
 		      strerror ( rc ) );
222
 		      strerror ( rc ) );
223
 		goto out;
223
 		goto out;

+ 1
- 2
src/core/downloader.c View File

218
  * @ret rc		Return status code
218
  * @ret rc		Return status code
219
  *
219
  *
220
  * Instantiates a downloader object to download the specified URI into
220
  * Instantiates a downloader object to download the specified URI into
221
- * the specified image object.  If the download is successful, the
222
- * image registration routine @c register_image() will be called.
221
+ * the specified image object.
223
  */
222
  */
224
 int create_downloader ( struct interface *job, struct image *image,
223
 int create_downloader ( struct interface *job, struct image *image,
225
 			int type, ... ) {
224
 			int type, ... ) {

+ 88
- 94
src/core/image.c View File

32
 
32
 
33
 /** @file
33
 /** @file
34
  *
34
  *
35
- * Executable/loadable images
35
+ * Executable images
36
  *
36
  *
37
  */
37
  */
38
 
38
 
40
 struct list_head images = LIST_HEAD_INIT ( images );
40
 struct list_head images = LIST_HEAD_INIT ( images );
41
 
41
 
42
 /**
42
 /**
43
- * Free executable/loadable image
43
+ * Free executable image
44
  *
44
  *
45
  * @v refcnt		Reference counter
45
  * @v refcnt		Reference counter
46
  */
46
  */
52
 	ufree ( image->data );
52
 	ufree ( image->data );
53
 	image_put ( image->replacement );
53
 	image_put ( image->replacement );
54
 	free ( image );
54
 	free ( image );
55
-	DBGC ( image, "IMAGE %p freed\n", image );
55
+	DBGC ( image, "IMAGE %s freed\n", image->name );
56
 }
56
 }
57
 
57
 
58
 /**
58
 /**
59
- * Allocate executable/loadable image
59
+ * Allocate executable image
60
  *
60
  *
61
- * @ret image		Executable/loadable image
61
+ * @ret image		Executable image
62
  */
62
  */
63
 struct image * alloc_image ( void ) {
63
 struct image * alloc_image ( void ) {
64
 	struct image *image;
64
 	struct image *image;
75
  *
75
  *
76
  * @v image		Image
76
  * @v image		Image
77
  * @v URI		New image URI
77
  * @v URI		New image URI
78
- * @ret rc		Return status code
79
  *
78
  *
80
  * If no name is set, the name will be updated to the base name of the
79
  * If no name is set, the name will be updated to the base name of the
81
  * URI path (if any).
80
  * URI path (if any).
82
  */
81
  */
83
-int image_set_uri ( struct image *image, struct uri *uri ) {
82
+void image_set_uri ( struct image *image, struct uri *uri ) {
84
 	const char *path = uri->path;
83
 	const char *path = uri->path;
85
 
84
 
86
 	/* Replace URI reference */
85
 	/* Replace URI reference */
90
 	/* Set name if none already specified */
89
 	/* Set name if none already specified */
91
 	if ( path && ( ! image->name[0] ) )
90
 	if ( path && ( ! image->name[0] ) )
92
 		image_set_name ( image, basename ( ( char * ) path ) );
91
 		image_set_name ( image, basename ( ( char * ) path ) );
93
-
94
-	return 0;
95
 }
92
 }
96
 
93
 
97
 /**
94
 /**
110
 }
107
 }
111
 
108
 
112
 /**
109
 /**
113
- * Register executable/loadable image
110
+ * Register executable image
114
  *
111
  *
115
- * @v image		Executable/loadable image
112
+ * @v image		Executable image
116
  * @ret rc		Return status code
113
  * @ret rc		Return status code
117
  */
114
  */
118
 int register_image ( struct image *image ) {
115
 int register_image ( struct image *image ) {
127
 	/* Add to image list */
124
 	/* Add to image list */
128
 	image_get ( image );
125
 	image_get ( image );
129
 	list_add_tail ( &image->list, &images );
126
 	list_add_tail ( &image->list, &images );
130
-	DBGC ( image, "IMAGE %p at [%lx,%lx) registered as %s\n",
131
-	       image, user_to_phys ( image->data, 0 ),
132
-	       user_to_phys ( image->data, image->len ), image->name );
127
+	DBGC ( image, "IMAGE %s at [%lx,%lx) registered\n",
128
+	       image->name, user_to_phys ( image->data, 0 ),
129
+	       user_to_phys ( image->data, image->len ) );
133
 
130
 
134
 	return 0;
131
 	return 0;
135
 }
132
 }
136
 
133
 
137
 /**
134
 /**
138
- * Unregister executable/loadable image
135
+ * Unregister executable image
139
  *
136
  *
140
- * @v image		Executable/loadable image
137
+ * @v image		Executable image
141
  */
138
  */
142
 void unregister_image ( struct image *image ) {
139
 void unregister_image ( struct image *image ) {
143
-	DBGC ( image, "IMAGE %p unregistered\n", image );
140
+	DBGC ( image, "IMAGE %s unregistered\n", image->name );
144
 	list_del ( &image->list );
141
 	list_del ( &image->list );
145
 	image_put ( image );
142
 	image_put ( image );
146
 }
143
 }
149
  * Find image by name
146
  * Find image by name
150
  *
147
  *
151
  * @v name		Image name
148
  * @v name		Image name
152
- * @ret image		Executable/loadable image, or NULL
149
+ * @ret image		Executable image, or NULL
153
  */
150
  */
154
 struct image * find_image ( const char *name ) {
151
 struct image * find_image ( const char *name ) {
155
 	struct image *image;
152
 	struct image *image;
163
 }
160
 }
164
 
161
 
165
 /**
162
 /**
166
- * Load executable/loadable image into memory
167
- *
168
- * @v image		Executable/loadable image
169
- * @v type		Executable/loadable image type
170
- * @ret rc		Return status code
171
- */
172
-static int image_load_type ( struct image *image, struct image_type *type ) {
173
-	int rc;
174
-
175
-	/* Check image is actually loadable */
176
-	if ( ! type->load )
177
-		return -ENOEXEC;
178
-
179
-	/* Try the image loader */
180
-	if ( ( rc = type->load ( image ) ) != 0 ) {
181
-		DBGC ( image, "IMAGE %p could not load as %s: %s\n",
182
-		       image, type->name, strerror ( rc ) );
183
-		return rc;
184
-	}
185
-
186
-	/* Flag as loaded */
187
-	image->flags |= IMAGE_LOADED;
188
-	return 0;
189
-}
190
-
191
-/**
192
- * Load executable/loadable image into memory
193
- *
194
- * @v image		Executable/loadable image
195
- * @ret rc		Return status code
196
- */
197
-int image_load ( struct image *image ) {
198
-
199
-	assert ( image->type != NULL );
200
-
201
-	return image_load_type ( image, image->type );
202
-}
203
-
204
-/**
205
- * Autodetect image type and load executable/loadable image into memory
163
+ * Determine image type
206
  *
164
  *
207
- * @v image		Executable/loadable image
165
+ * @v image		Executable image
208
  * @ret rc		Return status code
166
  * @ret rc		Return status code
209
  */
167
  */
210
-int image_autoload ( struct image *image ) {
168
+int image_probe ( struct image *image ) {
211
 	struct image_type *type;
169
 	struct image_type *type;
212
 	int rc;
170
 	int rc;
213
 
171
 
214
-	/* If image already has a type, use it */
172
+	/* Succeed if we already have a type */
215
 	if ( image->type )
173
 	if ( image->type )
216
-		return image_load ( image );
174
+		return 0;
217
 
175
 
218
-	/* Otherwise probe for a suitable type */
176
+	/* Try each type in turn */
219
 	for_each_table_entry ( type, IMAGE_TYPES ) {
177
 	for_each_table_entry ( type, IMAGE_TYPES ) {
220
-		DBGC ( image, "IMAGE %p trying type %s\n", image, type->name );
221
-		rc = image_load_type ( image, type );
222
-		if ( image->type == NULL )
223
-			continue;
224
-		return rc;
178
+		if ( ( rc = type->probe ( image ) ) == 0 ) {
179
+			image->type = type;
180
+			DBGC ( image, "IMAGE %s is %s\n",
181
+			       image->name, type->name );
182
+			return 0;
183
+		}
184
+		DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
185
+		       type->name, strerror ( rc ) );
225
 	}
186
 	}
226
 
187
 
227
-	DBGC ( image, "IMAGE %p format not recognised\n", image );
188
+	DBGC ( image, "IMAGE %s format not recognised\n", image->name );
228
 	return -ENOEXEC;
189
 	return -ENOEXEC;
229
 }
190
 }
230
 
191
 
231
 /**
192
 /**
232
- * Execute loaded image
193
+ * Execute image
233
  *
194
  *
234
- * @v image		Loaded image
195
+ * @v image		Executable image
235
  * @ret rc		Return status code
196
  * @ret rc		Return status code
236
  */
197
  */
237
 int image_exec ( struct image *image ) {
198
 int image_exec ( struct image *image ) {
239
 	struct uri *old_cwuri;
200
 	struct uri *old_cwuri;
240
 	int rc;
201
 	int rc;
241
 
202
 
242
-	/* Image must be loaded first */
243
-	if ( ! ( image->flags & IMAGE_LOADED ) ) {
244
-		DBGC ( image, "IMAGE %p could not execute: not loaded\n",
245
-		       image );
246
-		return -ENOTTY;
247
-	}
248
-
249
-	assert ( image->type != NULL );
250
-
251
-	/* Check that image is actually executable */
252
-	if ( ! image->type->exec )
253
-		return -ENOEXEC;
203
+	/* Check that this image can be executed */
204
+	if ( ( rc = image_probe ( image ) ) != 0 )
205
+		return rc;
254
 
206
 
255
 	/* Switch current working directory to be that of the image itself */
207
 	/* Switch current working directory to be that of the image itself */
256
 	old_cwuri = uri_get ( cwuri );
208
 	old_cwuri = uri_get ( cwuri );
264
 
216
 
265
 	/* Try executing the image */
217
 	/* Try executing the image */
266
 	if ( ( rc = image->type->exec ( image ) ) != 0 ) {
218
 	if ( ( rc = image->type->exec ( image ) ) != 0 ) {
267
-		DBGC ( image, "IMAGE %p could not execute: %s\n",
268
-		       image, strerror ( rc ) );
219
+		DBGC ( image, "IMAGE %s could not execute: %s\n",
220
+		       image->name, strerror ( rc ) );
269
 		/* Do not return yet; we still have clean-up to do */
221
 		/* Do not return yet; we still have clean-up to do */
270
 	}
222
 	}
271
 
223
 
283
 
235
 
284
 	/* Tail-recurse into replacement image, if one exists */
236
 	/* Tail-recurse into replacement image, if one exists */
285
 	if ( replacement ) {
237
 	if ( replacement ) {
286
-		DBGC ( image, "IMAGE %p replacing self with IMAGE %p\n",
287
-		       image, replacement );
238
+		DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n",
239
+		       image->name, replacement->name );
288
 		if ( ( rc = image_exec ( replacement ) ) != 0 )
240
 		if ( ( rc = image_exec ( replacement ) ) != 0 )
289
 			return rc;
241
 			return rc;
290
 	}
242
 	}
293
 }
245
 }
294
 
246
 
295
 /**
247
 /**
296
- * Register and autoload an image
248
+ * Select image for execution
297
  *
249
  *
298
- * @v image		Image
250
+ * @v image		Executable image
299
  * @ret rc		Return status code
251
  * @ret rc		Return status code
300
  */
252
  */
301
-int register_and_autoload_image ( struct image *image ) {
253
+int image_select ( struct image *image ) {
254
+	struct image *tmp;
255
+	int rc;
256
+
257
+	/* Unselect all other images */
258
+	for_each_image ( tmp )
259
+		tmp->flags &= ~IMAGE_SELECTED;
260
+
261
+	/* Check that this image can be executed */
262
+	if ( ( rc = image_probe ( image ) ) != 0 )
263
+		return rc;
264
+
265
+	/* Mark image as selected */
266
+	image->flags |= IMAGE_SELECTED;
267
+
268
+	return 0;
269
+}
270
+
271
+/**
272
+ * Find selected image
273
+ *
274
+ * @ret image		Executable image, or NULL
275
+ */
276
+struct image * image_find_selected ( void ) {
277
+	struct image *image;
278
+
279
+	for_each_image ( image ) {
280
+		if ( image->flags & IMAGE_SELECTED )
281
+			return image;
282
+	}
283
+	return NULL;
284
+}
285
+
286
+/**
287
+ * Register and select an image
288
+ *
289
+ * @v image		Executable image
290
+ * @ret rc		Return status code
291
+ */
292
+int register_and_select_image ( struct image *image ) {
302
 	int rc;
293
 	int rc;
303
 
294
 
304
 	if ( ( rc = register_image ( image ) ) != 0 )
295
 	if ( ( rc = register_image ( image ) ) != 0 )
305
 		return rc;
296
 		return rc;
306
 
297
 
307
-	if ( ( rc = image_autoload ( image ) ) != 0 )
298
+	if ( ( rc = image_probe ( image ) ) != 0 )
299
+		return rc;
300
+
301
+	if ( ( rc = image_select ( image ) ) != 0 )
308
 		return rc;
302
 		return rc;
309
 
303
 
310
 	return 0;
304
 	return 0;
311
 }
305
 }
312
 
306
 
313
 /**
307
 /**
314
- * Register and autoexec an image
308
+ * Register and boot an image
315
  *
309
  *
316
  * @v image		Image
310
  * @v image		Image
317
  * @ret rc		Return status code
311
  * @ret rc		Return status code
318
  */
312
  */
319
-int register_and_autoexec_image ( struct image *image ) {
313
+int register_and_boot_image ( struct image *image ) {
320
 	int rc;
314
 	int rc;
321
 
315
 
322
-	if ( ( rc = register_and_autoload_image ( image ) ) != 0 )
316
+	if ( ( rc = register_and_select_image ( image ) ) != 0 )
323
 		return rc;
317
 		return rc;
324
 
318
 
325
 	if ( ( rc = image_exec ( image ) ) != 0 )
319
 	if ( ( rc = image_exec ( image ) ) != 0 )

+ 30
- 34
src/hci/commands/image_cmd.c View File

86
 	COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS,
86
 	COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS,
87
 		       "[--name <name>] <uri> [<arguments>...]" );
87
 		       "[--name <name>] <uri> [<arguments>...]" );
88
 
88
 
89
-/** "kernel" command descriptor */
90
-static struct command_descriptor kernel_cmd =
91
-	COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS,
92
-		       "[--name <name>] <uri> [<arguments>...]" );
93
-
94
-/** "chain" command descriptor */
95
-static struct command_descriptor chain_cmd =
96
-	COMMAND_DESC ( struct imgfetch_options, imgfetch_opts, 1, MAX_ARGUMENTS,
97
-		       "[--name <name>] <uri> [<arguments>...]" );
98
-
99
 /**
89
 /**
100
  * The "imgfetch" and friends command body
90
  * The "imgfetch" and friends command body
101
  *
91
  *
102
  * @v argc		Argument count
92
  * @v argc		Argument count
103
  * @v argv		Argument list
93
  * @v argv		Argument list
104
  * @v cmd		Command descriptor
94
  * @v cmd		Command descriptor
105
- * @v image_register	Image registration action
95
+ * @v action		Action to take upon a successful download
106
  * @ret rc		Return status code
96
  * @ret rc		Return status code
107
  */
97
  */
108
 static int imgfetch_core_exec ( int argc, char **argv,
98
 static int imgfetch_core_exec ( int argc, char **argv,
109
 				struct command_descriptor *cmd,
99
 				struct command_descriptor *cmd,
110
-				int ( * image_register ) ( struct image * ) ) {
100
+				int ( * action ) ( struct image *image ) ) {
111
 	struct imgfetch_options opts;
101
 	struct imgfetch_options opts;
112
 	struct image *image;
102
 	struct image *image;
113
 	char *uri_string;
103
 	char *uri_string;
139
 		return rc;
129
 		return rc;
140
 
130
 
141
 	/* Fetch the image */
131
 	/* Fetch the image */
142
-	if ( ( rc = imgfetch ( image, uri_string, image_register ) ) != 0 ) {
132
+	if ( ( rc = imgfetch ( image, uri_string, action ) ) != 0 ) {
143
 		printf ( "Could not fetch %s: %s\n",
133
 		printf ( "Could not fetch %s: %s\n",
144
 			 uri_string, strerror ( rc ) );
134
 			 uri_string, strerror ( rc ) );
145
 		image_put ( image );
135
 		image_put ( image );
172
  */
162
  */
173
 static int kernel_exec ( int argc, char **argv ) {
163
 static int kernel_exec ( int argc, char **argv ) {
174
 
164
 
175
-	return imgfetch_core_exec ( argc, argv, &kernel_cmd,
176
-				    register_and_autoload_image );
165
+	return imgfetch_core_exec ( argc, argv, &imgfetch_cmd,
166
+				    register_and_select_image );
177
 }
167
 }
178
 
168
 
179
 /**
169
 /**
185
  */
175
  */
186
 static int chain_exec ( int argc, char **argv) {
176
 static int chain_exec ( int argc, char **argv) {
187
 
177
 
188
-	return imgfetch_core_exec ( argc, argv, &chain_cmd,
189
-				    register_and_autoexec_image );
178
+	return imgfetch_core_exec ( argc, argv, &imgfetch_cmd,
179
+				    register_and_boot_image );
190
 }
180
 }
191
 
181
 
192
-/** "imgload" options */
193
-struct imgload_options {};
182
+/** "imgselect" options */
183
+struct imgselect_options {};
194
 
184
 
195
-/** "imgload" option list */
196
-static struct option_descriptor imgload_opts[] = {};
185
+/** "imgselect" option list */
186
+static struct option_descriptor imgselect_opts[] = {};
197
 
187
 
198
-/** "imgload" command descriptor */
199
-static struct command_descriptor imgload_cmd =
200
-	COMMAND_DESC ( struct imgload_options, imgload_opts, 1, 1, "<image>" );
188
+/** "imgselect" command descriptor */
189
+static struct command_descriptor imgselect_cmd =
190
+	COMMAND_DESC ( struct imgselect_options, imgselect_opts, 1, 1,
191
+		       "<image>" );
201
 
192
 
202
 /**
193
 /**
203
- * The "imgload" command
194
+ * The "imgselect" command
204
  *
195
  *
205
  * @v argc		Argument count
196
  * @v argc		Argument count
206
  * @v argv		Argument list
197
  * @v argv		Argument list
207
  * @ret rc		Return status code
198
  * @ret rc		Return status code
208
  */
199
  */
209
-static int imgload_exec ( int argc, char **argv ) {
210
-	struct imgload_options opts;
200
+static int imgselect_exec ( int argc, char **argv ) {
201
+	struct imgselect_options opts;
211
 	struct image *image;
202
 	struct image *image;
212
 	int rc;
203
 	int rc;
213
 
204
 
214
 	/* Parse options */
205
 	/* Parse options */
215
-	if ( ( rc = parse_options ( argc, argv, &imgload_cmd, &opts ) ) != 0 )
206
+	if ( ( rc = parse_options ( argc, argv, &imgselect_cmd, &opts ) ) != 0 )
216
 		return rc;
207
 		return rc;
217
 
208
 
218
 	/* Parse image name */
209
 	/* Parse image name */
220
 		return rc;
211
 		return rc;
221
 
212
 
222
 	/* Load image */
213
 	/* Load image */
223
-	if ( ( rc = imgload ( image ) ) != 0 ) {
224
-		printf ( "Could not load %s: %s\n",
214
+	if ( ( rc = imgselect ( image ) ) != 0 ) {
215
+		printf ( "Could not select %s: %s\n",
225
 			 image->name, strerror ( rc ) );
216
 			 image->name, strerror ( rc ) );
226
 		return rc;
217
 		return rc;
227
 	}
218
 	}
302
 	} else {
293
 	} else {
303
 		image = imgautoselect();
294
 		image = imgautoselect();
304
 		if ( ! image ) {
295
 		if ( ! image ) {
305
-			printf ( "No (unique) loaded image\n" );
306
-			return -ENOTTY;
296
+			rc = -ENOTTY;
297
+			printf ( "No image selected: %s\n", strerror ( rc ) );
298
+			return rc;
307
 		}
299
 		}
308
 	}
300
 	}
309
 
301
 
417
 		.exec = chain_exec,
409
 		.exec = chain_exec,
418
 	},
410
 	},
419
 	{
411
 	{
420
-		.name = "imgload",
421
-		.exec = imgload_exec,
412
+		.name = "imgselect",
413
+		.exec = imgselect_exec,
414
+	},
415
+	{
416
+		.name = "imgload", /* synonym for "imgselect" */
417
+		.exec = imgselect_exec,
422
 	},
418
 	},
423
 	{
419
 	{
424
 		.name = "imgargs",
420
 		.name = "imgargs",

+ 3
- 9
src/image/efi_image.c View File

26
 
26
 
27
 FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
27
 FEATURE ( FEATURE_IMAGE, "EFI", DHCP_EB_FEATURE_EFI, 1 );
28
 
28
 
29
-struct image_type efi_image_type __image_type ( PROBE_NORMAL );
30
-
31
 /** Event used to signal shutdown */
29
 /** Event used to signal shutdown */
32
 static EFI_EVENT efi_shutdown_event;
30
 static EFI_EVENT efi_shutdown_event;
33
 
31
 
99
 }
97
 }
100
 
98
 
101
 /**
99
 /**
102
- * Load EFI image into memory
100
+ * Probe EFI image
103
  *
101
  *
104
  * @v image		EFI file
102
  * @v image		EFI file
105
  * @ret rc		Return status code
103
  * @ret rc		Return status code
106
  */
104
  */
107
-static int efi_image_load ( struct image *image ) {
105
+static int efi_image_probe ( struct image *image ) {
108
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
106
 	EFI_BOOT_SERVICES *bs = efi_systab->BootServices;
109
 	EFI_HANDLE handle;
107
 	EFI_HANDLE handle;
110
 	EFI_STATUS efirc;
108
 	EFI_STATUS efirc;
119
 		return -ENOEXEC;
117
 		return -ENOEXEC;
120
 	}
118
 	}
121
 
119
 
122
-	/* This is an EFI image */
123
-	if ( ! image->type )
124
-		image->type = &efi_image_type;
125
-
126
 	/* Unload the image.  We can't leave it loaded, because we
120
 	/* Unload the image.  We can't leave it loaded, because we
127
 	 * have no "unload" operation.
121
 	 * have no "unload" operation.
128
 	 */
122
 	 */
134
 /** EFI image type */
128
 /** EFI image type */
135
 struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
129
 struct image_type efi_image_type __image_type ( PROBE_NORMAL ) = {
136
 	.name = "EFI",
130
 	.name = "EFI",
137
-	.load = efi_image_load,
131
+	.probe = efi_image_probe,
138
 	.exec = efi_image_exec,
132
 	.exec = efi_image_exec,
139
 };
133
 };

+ 15
- 14
src/image/elf.c View File

45
  * @v image		ELF file
45
  * @v image		ELF file
46
  * @v phdr		ELF program header
46
  * @v phdr		ELF program header
47
  * @v ehdr		ELF executable header
47
  * @v ehdr		ELF executable header
48
+ * @ret entry		Entry point, if found
48
  * @ret rc		Return status code
49
  * @ret rc		Return status code
49
  */
50
  */
50
 static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
51
 static int elf_load_segment ( struct image *image, Elf_Phdr *phdr,
51
-			      Elf_Ehdr *ehdr ) {
52
+			      Elf_Ehdr *ehdr, physaddr_t *entry ) {
52
 	physaddr_t dest;
53
 	physaddr_t dest;
53
 	userptr_t buffer;
54
 	userptr_t buffer;
54
 	unsigned long e_offset;
55
 	unsigned long e_offset;
96
 
97
 
97
 	/* Set execution address, if it lies within this segment */
98
 	/* Set execution address, if it lies within this segment */
98
 	if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) {
99
 	if ( ( e_offset = ( ehdr->e_entry - dest ) ) < phdr->p_filesz ) {
99
-		image->priv.phys = ehdr->e_entry;
100
+		*entry = ehdr->e_entry;
100
 		DBGC ( image, "ELF %p found physical entry point at %lx\n",
101
 		DBGC ( image, "ELF %p found physical entry point at %lx\n",
101
-		       image, image->priv.phys );
102
+		       image, *entry );
102
 	} else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) )
103
 	} else if ( ( e_offset = ( ehdr->e_entry - phdr->p_vaddr ) )
103
 		    < phdr->p_filesz ) {
104
 		    < phdr->p_filesz ) {
104
-		if ( ! image->priv.phys ) {
105
-			image->priv.phys = ( dest + e_offset );
105
+		if ( ! *entry ) {
106
+			*entry = ( dest + e_offset );
106
 			DBGC ( image, "ELF %p found virtual entry point at %lx"
107
 			DBGC ( image, "ELF %p found virtual entry point at %lx"
107
-			       " (virt %lx)\n", image, image->priv.phys,
108
+			       " (virt %lx)\n", image, *entry,
108
 			       ( ( unsigned long ) ehdr->e_entry ) );
109
 			       ( ( unsigned long ) ehdr->e_entry ) );
109
 		}
110
 		}
110
 	}
111
 	}
116
  * Load ELF image into memory
117
  * Load ELF image into memory
117
  *
118
  *
118
  * @v image		ELF file
119
  * @v image		ELF file
120
+ * @ret entry		Entry point
119
  * @ret rc		Return status code
121
  * @ret rc		Return status code
120
  */
122
  */
121
-int elf_load ( struct image *image ) {
123
+int elf_load ( struct image *image, physaddr_t *entry ) {
122
 	Elf_Ehdr ehdr;
124
 	Elf_Ehdr ehdr;
123
 	Elf_Phdr phdr;
125
 	Elf_Phdr phdr;
124
 	Elf_Off phoff;
126
 	Elf_Off phoff;
125
 	unsigned int phnum;
127
 	unsigned int phnum;
126
 	int rc;
128
 	int rc;
127
 
129
 
128
-	/* Image type must already have been set by caller */
129
-	assert ( image->type != NULL );
130
-
131
 	/* Read ELF header */
130
 	/* Read ELF header */
132
 	copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
131
 	copy_from_user ( &ehdr, image->data, 0, sizeof ( ehdr ) );
133
 	if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) {
132
 	if ( memcmp ( &ehdr.e_ident[EI_MAG0], ELFMAG, SELFMAG ) != 0 ) {
135
 		return -ENOEXEC;
134
 		return -ENOEXEC;
136
 	}
135
 	}
137
 
136
 
138
-	/* Invalidate execution address */
139
-	image->priv.phys = 0;
137
+	/* Invalidate entry point */
138
+	*entry = 0;
140
 
139
 
141
 	/* Read ELF program headers */
140
 	/* Read ELF program headers */
142
 	for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
141
 	for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
147
 			return -ENOEXEC;
146
 			return -ENOEXEC;
148
 		}
147
 		}
149
 		copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
148
 		copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
150
-		if ( ( rc = elf_load_segment ( image, &phdr, &ehdr ) ) != 0 )
149
+		if ( ( rc = elf_load_segment ( image, &phdr, &ehdr,
150
+					       entry ) ) != 0 ) {
151
 			return rc;
151
 			return rc;
152
+		}
152
 	}
153
 	}
153
 
154
 
154
 	/* Check for a valid execution address */
155
 	/* Check for a valid execution address */
155
-	if ( ! image->priv.phys ) {
156
+	if ( ! *entry ) {
156
 		DBGC ( image, "ELF %p entry point %lx outside image\n",
157
 		DBGC ( image, "ELF %p entry point %lx outside image\n",
157
 		       image, ( ( unsigned long ) ehdr.e_entry ) );
158
 		       image, ( ( unsigned long ) ehdr.e_entry ) );
158
 		return -ENOEXEC;
159
 		return -ENOEXEC;

+ 3
- 3
src/image/embedded.c View File

76
 		}
76
 		}
77
 	}
77
 	}
78
 
78
 
79
-	/* Load the first image */
79
+	/* Select the first image */
80
 	image = &embedded_images[0];
80
 	image = &embedded_images[0];
81
-	if ( ( rc = image_autoload ( image ) ) != 0 ) {
82
-		DBG ( "Could not load embedded image \"%s\": %s\n",
81
+	if ( ( rc = image_select ( image ) ) != 0 ) {
82
+		DBG ( "Could not select embedded image \"%s\": %s\n",
83
 		      image->name, strerror ( rc ) );
83
 		      image->name, strerror ( rc ) );
84
 		return;
84
 		return;
85
 	}
85
 	}

+ 3
- 12
src/image/script.c View File

36
 #include <ipxe/image.h>
36
 #include <ipxe/image.h>
37
 #include <ipxe/shell.h>
37
 #include <ipxe/shell.h>
38
 
38
 
39
-struct image_type script_image_type __image_type ( PROBE_NORMAL );
40
-
41
 /** Currently running script
39
 /** Currently running script
42
  *
40
  *
43
  * This is a global in order to allow goto_exec() to update the
41
  * This is a global in order to allow goto_exec() to update the
165
 }
163
 }
166
 
164
 
167
 /**
165
 /**
168
- * Load script into memory
166
+ * Probe script image
169
  *
167
  *
170
  * @v image		Script
168
  * @v image		Script
171
  * @ret rc		Return status code
169
  * @ret rc		Return status code
172
  */
170
  */
173
-static int script_load ( struct image *image ) {
171
+static int script_probe ( struct image *image ) {
174
 	static const char ipxe_magic[] = "#!ipxe";
172
 	static const char ipxe_magic[] = "#!ipxe";
175
 	static const char gpxe_magic[] = "#!gpxe";
173
 	static const char gpxe_magic[] = "#!gpxe";
176
 	linker_assert ( sizeof ( ipxe_magic ) == sizeof ( gpxe_magic ),
174
 	linker_assert ( sizeof ( ipxe_magic ) == sizeof ( gpxe_magic ),
193
 		return -ENOEXEC;
191
 		return -ENOEXEC;
194
 	}
192
 	}
195
 
193
 
196
-	/* This is a script */
197
-	image->type = &script_image_type;
198
-
199
-	/* We don't actually load it anywhere; we will pick the lines
200
-	 * out of the image as we need them.
201
-	 */
202
-
203
 	return 0;
194
 	return 0;
204
 }
195
 }
205
 
196
 
206
 /** Script image type */
197
 /** Script image type */
207
 struct image_type script_image_type __image_type ( PROBE_NORMAL ) = {
198
 struct image_type script_image_type __image_type ( PROBE_NORMAL ) = {
208
 	.name = "script",
199
 	.name = "script",
209
-	.load = script_load,
200
+	.probe = script_probe,
210
 	.exec = script_exec,
201
 	.exec = script_exec,
211
 };
202
 };
212
 
203
 

+ 1
- 1
src/include/ipxe/elf.h View File

12
 
12
 
13
 #include <elf.h>
13
 #include <elf.h>
14
 
14
 
15
-extern int elf_load ( struct image *image );
15
+extern int elf_load ( struct image *image, physaddr_t *entry );
16
 
16
 
17
 #endif /* _IPXE_ELF_H */
17
 #endif /* _IPXE_ELF_H */

+ 20
- 42
src/include/ipxe/image.h View File

4
 /**
4
 /**
5
  * @file
5
  * @file
6
  *
6
  *
7
- * Executable/loadable images
7
+ * Executable images
8
  *
8
  *
9
  */
9
  */
10
 
10
 
18
 struct uri;
18
 struct uri;
19
 struct image_type;
19
 struct image_type;
20
 
20
 
21
-/** An executable or loadable image */
21
+/** An executable image */
22
 struct image {
22
 struct image {
23
 	/** Reference count */
23
 	/** Reference count */
24
 	struct refcnt refcnt;
24
 	struct refcnt refcnt;
42
 
42
 
43
 	/** Image type, if known */
43
 	/** Image type, if known */
44
 	struct image_type *type;
44
 	struct image_type *type;
45
-	/** Image type private data */
46
-	union {
47
-		physaddr_t phys;
48
-		userptr_t user;
49
-		unsigned long ul;
50
-	} priv;
51
 
45
 
52
 	/** Replacement image
46
 	/** Replacement image
53
 	 *
47
 	 *
54
 	 * An image wishing to replace itself with another image (in a
48
 	 * An image wishing to replace itself with another image (in a
55
 	 * style similar to a Unix exec() call) should return from its
49
 	 * style similar to a Unix exec() call) should return from its
56
 	 * exec() method with the replacement image set to point to
50
 	 * exec() method with the replacement image set to point to
57
-	 * the new image.  The new image must already be in a suitable
58
-	 * state for execution (i.e. loaded).
51
+	 * the new image.
59
 	 *
52
 	 *
60
 	 * If an image unregisters itself as a result of being
53
 	 * If an image unregisters itself as a result of being
61
 	 * executed, it must make sure that its replacement image (if
54
 	 * executed, it must make sure that its replacement image (if
65
 	struct image *replacement;
58
 	struct image *replacement;
66
 };
59
 };
67
 
60
 
68
-/** Image is loaded */
69
-#define IMAGE_LOADED 0x0001
61
+/** Image is selected for execution */
62
+#define IMAGE_SELECTED 0x0001
70
 
63
 
71
-/** An executable or loadable image type */
64
+/** An executable image type */
72
 struct image_type {
65
 struct image_type {
73
 	/** Name of this image type */
66
 	/** Name of this image type */
74
 	char *name;
67
 	char *name;
75
-	/**
76
-	 * Load image into memory
68
+	/** Probe image
77
 	 *
69
 	 *
78
-	 * @v image		Executable/loadable image
70
+	 * @v image		Executable image
79
 	 * @ret rc		Return status code
71
 	 * @ret rc		Return status code
80
 	 *
72
 	 *
81
-	 * Load the image into memory at the correct location as
82
-	 * determined by the file format.
83
-	 *
84
-	 * If the file image is in the correct format, the method must
85
-	 * update @c image->type to point to its own type (unless @c
86
-	 * image->type is already set).  This allows the autoloading
87
-	 * code to disambiguate between "this is not my image format"
88
-	 * and "there is something wrong with this image".  In
89
-	 * particular, setting @c image->type and then returning an
90
-	 * error will cause image_autoload() to abort and return an
91
-	 * error, rather than continuing to the next image type.
73
+	 * Return success if the image is of this image type.
92
 	 */
74
 	 */
93
-	int ( * load ) ( struct image *image );
75
+	int ( * probe ) ( struct image *image );
94
 	/**
76
 	/**
95
-	 * Execute loaded image
77
+	 * Execute image
96
 	 *
78
 	 *
97
-	 * @v image		Loaded image
79
+	 * @v image		Executable image
98
 	 * @ret rc		Return status code
80
 	 * @ret rc		Return status code
99
-	 *
100
-	 * Note that the image may be invalidated by the act of
101
-	 * execution, i.e. an image is allowed to choose to unregister
102
-	 * (and so potentially free) itself.
103
 	 */
81
 	 */
104
 	int ( * exec ) ( struct image *image );
82
 	int ( * exec ) ( struct image *image );
105
 };
83
 };
125
  */
103
  */
126
 #define PROBE_PXE 03
104
 #define PROBE_PXE 03
127
 
105
 
128
-/** Executable or loadable image type table */
106
+/** Executable image type table */
129
 #define IMAGE_TYPES __table ( struct image_type, "image_types" )
107
 #define IMAGE_TYPES __table ( struct image_type, "image_types" )
130
 
108
 
131
-/** An executable or loadable image type */
109
+/** An executable image type */
132
 #define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
110
 #define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
133
 
111
 
134
 extern struct list_head images;
112
 extern struct list_head images;
147
 }
125
 }
148
 
126
 
149
 extern struct image * alloc_image ( void );
127
 extern struct image * alloc_image ( void );
150
-extern int image_set_uri ( struct image *image, struct uri *uri );
128
+extern void image_set_uri ( struct image *image, struct uri *uri );
151
 extern int image_set_cmdline ( struct image *image, const char *cmdline );
129
 extern int image_set_cmdline ( struct image *image, const char *cmdline );
152
 extern int register_image ( struct image *image );
130
 extern int register_image ( struct image *image );
153
 extern void unregister_image ( struct image *image );
131
 extern void unregister_image ( struct image *image );
154
-extern void promote_image ( struct image *image );
155
 struct image * find_image ( const char *name );
132
 struct image * find_image ( const char *name );
156
-extern int image_load ( struct image *image );
157
-extern int image_autoload ( struct image *image );
133
+extern int image_probe ( struct image *image );
158
 extern int image_exec ( struct image *image );
134
 extern int image_exec ( struct image *image );
159
-extern int register_and_autoload_image ( struct image *image );
160
-extern int register_and_autoexec_image ( struct image *image );
135
+extern int image_select ( struct image *image );
136
+extern struct image * image_find_selected ( void );
137
+extern int register_and_select_image ( struct image *image );
138
+extern int register_and_boot_image ( struct image *image );
161
 
139
 
162
 /**
140
 /**
163
  * Increment reference count on an image
141
  * Increment reference count on an image

+ 30
- 4
src/include/usr/imgmgmt.h View File

9
 
9
 
10
 FILE_LICENCE ( GPL2_OR_LATER );
10
 FILE_LICENCE ( GPL2_OR_LATER );
11
 
11
 
12
-struct image;
12
+#include <ipxe/image.h>
13
 
13
 
14
 extern int imgdownload ( struct image *image, struct uri *uri,
14
 extern int imgdownload ( struct image *image, struct uri *uri,
15
 			 int ( * action ) ( struct image *image ) );
15
 			 int ( * action ) ( struct image *image ) );
16
 extern int imgfetch ( struct image *image, const char *uri_string,
16
 extern int imgfetch ( struct image *image, const char *uri_string,
17
 		      int ( * action ) ( struct image *image ) );
17
 		      int ( * action ) ( struct image *image ) );
18
-extern int imgload ( struct image *image );
19
-extern int imgexec ( struct image *image );
20
-extern struct image * imgautoselect ( void );
21
 extern void imgstat ( struct image *image );
18
 extern void imgstat ( struct image *image );
22
 extern void imgfree ( struct image *image );
19
 extern void imgfree ( struct image *image );
23
 
20
 
21
+/**
22
+ * Select an image for execution
23
+ *
24
+ * @v image		Image
25
+ * @ret rc		Return status code
26
+ */
27
+static inline int imgselect ( struct image *image ) {
28
+	return image_select ( image );
29
+}
30
+
31
+/**
32
+ * Find the previously-selected image
33
+ *
34
+ * @ret image		Image, or NULL
35
+ */
36
+static inline struct image * imgautoselect ( void ) {
37
+	return image_find_selected();
38
+}
39
+
40
+/**
41
+ * Execute an image
42
+ *
43
+ * @v image		Image
44
+ * @ret rc		Return status code
45
+ */
46
+static inline int imgexec ( struct image *image ) {
47
+	return image_exec ( image );
48
+}
49
+
24
 #endif /* _USR_IMGMGMT_H */
50
 #endif /* _USR_IMGMGMT_H */

+ 1
- 1
src/usr/autoboot.c View File

184
 	/* Attempt filename boot if applicable */
184
 	/* Attempt filename boot if applicable */
185
 	if ( filename ) {
185
 	if ( filename ) {
186
 		if ( ( rc = imgdownload ( image, filename,
186
 		if ( ( rc = imgdownload ( image, filename,
187
-					  register_and_autoexec_image ) ) !=0){
187
+					  register_and_boot_image ) ) != 0 ) {
188
 			printf ( "\nCould not chain image: %s\n",
188
 			printf ( "\nCould not chain image: %s\n",
189
 				 strerror ( rc ) );
189
 				 strerror ( rc ) );
190
 			/* Fall through to (possibly) attempt a SAN boot
190
 			/* Fall through to (possibly) attempt a SAN boot

+ 3
- 49
src/usr/imgmgmt.c View File

99
 	return rc;
99
 	return rc;
100
 }
100
 }
101
 
101
 
102
-/**
103
- * Load an image
104
- *
105
- * @v image		Image
106
- * @ret rc		Return status code
107
- */
108
-int imgload ( struct image *image ) {
109
-	int rc;
110
-
111
-	/* Try to load image */
112
-	if ( ( rc = image_autoload ( image ) ) != 0 )
113
-		return rc;
114
-
115
-	return 0;
116
-}
117
-
118
-/**
119
- * Execute an image
120
- *
121
- * @v image		Image
122
- * @ret rc		Return status code
123
- */
124
-int imgexec ( struct image *image ) {
125
-	return image_exec ( image );
126
-}
127
-
128
-/**
129
- * Identify the only loaded image
130
- *
131
- * @ret image		Image, or NULL if 0 or >1 images are loaded
132
- */
133
-struct image * imgautoselect ( void ) {
134
-	struct image *image;
135
-	struct image *selected_image = NULL;
136
-	int flagged_images = 0;
137
-
138
-	for_each_image ( image ) {
139
-		if ( image->flags & IMAGE_LOADED ) {
140
-			selected_image = image;
141
-			flagged_images++;
142
-		}
143
-	}
144
-
145
-	return ( ( flagged_images == 1 ) ? selected_image : NULL );
146
-}
147
-
148
 /**
102
 /**
149
  * Display status of an image
103
  * Display status of an image
150
  *
104
  *
151
  * @v image		Executable/loadable image
105
  * @v image		Executable/loadable image
152
  */
106
  */
153
 void imgstat ( struct image *image ) {
107
 void imgstat ( struct image *image ) {
154
-	printf ( "%s: %zd bytes", image->name, image->len );
108
+	printf ( "%s : %zd bytes", image->name, image->len );
155
 	if ( image->type )
109
 	if ( image->type )
156
 		printf ( " [%s]", image->type->name );
110
 		printf ( " [%s]", image->type->name );
157
-	if ( image->flags & IMAGE_LOADED )
158
-		printf ( " [LOADED]" );
111
+	if ( image->flags & IMAGE_SELECTED )
112
+		printf ( " [SELECTED]" );
159
 	if ( image->cmdline )
113
 	if ( image->cmdline )
160
 		printf ( " \"%s\"", image->cmdline );
114
 		printf ( " \"%s\"", image->cmdline );
161
 	printf ( "\n" );
115
 	printf ( "\n" );

Loading…
Cancel
Save