Parcourir la source

Provide registration mechanism for loaded images, so that we can e.g.

refer to them by name from the command line, or build them into a
multiboot module list.

Use setting image->type to disambiguate between "not my image" and "bad
image"; this avoids relying on specific values of the error code.
tags/v0.9.3
Michael Brown il y a 18 ans
Parent
révision
f59ad50504
4 fichiers modifiés avec 262 ajouts et 122 suppressions
  1. 92
    38
      src/arch/i386/image/multiboot.c
  2. 115
    62
      src/core/image.c
  3. 11
    5
      src/image/elf.c
  4. 44
    17
      src/include/gpxe/image.h

+ 92
- 38
src/arch/i386/image/multiboot.c Voir le fichier

24
  */
24
  */
25
 
25
 
26
 #include <errno.h>
26
 #include <errno.h>
27
+#include <alloca.h>
27
 #include <multiboot.h>
28
 #include <multiboot.h>
28
 #include <gpxe/uaccess.h>
29
 #include <gpxe/uaccess.h>
29
 #include <gpxe/image.h>
30
 #include <gpxe/image.h>
31
 #include <gpxe/memmap.h>
32
 #include <gpxe/memmap.h>
32
 #include <gpxe/elf.h>
33
 #include <gpxe/elf.h>
33
 
34
 
35
+struct image_type multiboot_image_type __image_type;
36
+
34
 /** Multiboot flags that we support */
37
 /** Multiboot flags that we support */
35
 #define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
38
 #define MB_SUPPORTED_FLAGS ( MB_FLAG_PGALIGN | MB_FLAG_MEMMAP | \
36
 			     MB_FLAG_VIDMODE | MB_FLAG_RAW )
39
 			     MB_FLAG_VIDMODE | MB_FLAG_RAW )
58
 };
61
 };
59
 
62
 
60
 /**
63
 /**
61
- * Execute multiboot image
64
+ * Build multiboot memory map
62
  *
65
  *
63
- * @v image		ELF file
64
- * @ret rc		Return status code
66
+ * @v mbinfo		Multiboot information structure
67
+ * @v mbmemmap		Multiboot memory map
65
  */
68
  */
66
-static int multiboot_execute ( struct image *image ) {
67
-	static const char *bootloader_name = "gPXE " VERSION;
68
-	struct multiboot_info mbinfo;
69
+static void multiboot_build_memmap ( struct multiboot_info *mbinfo,
70
+				     struct multiboot_memory_map *mbmemmap ) {
69
 	struct memory_map memmap;
71
 	struct memory_map memmap;
70
-	struct multiboot_memory_map mbmemmap[ sizeof ( memmap.regions ) /
71
-					      sizeof ( memmap.regions[0] ) ];
72
 	unsigned int i;
72
 	unsigned int i;
73
 
73
 
74
-	/* Populate multiboot information structure */
75
-	memset ( &mbinfo, 0, sizeof ( mbinfo ) );
76
-
77
-	/* Set boot loader name */
78
-	mbinfo.flags |= MBI_FLAG_LOADER;
79
-	mbinfo.boot_loader_name = virt_to_phys ( bootloader_name );
80
-	
81
 	/* Get memory map */
74
 	/* Get memory map */
82
 	get_memmap ( &memmap );
75
 	get_memmap ( &memmap );
83
-	memset ( mbmemmap, 0, sizeof ( mbmemmap ) );
76
+
77
+	/* Translate into multiboot format */
78
+	memset ( mbmemmap, 0, sizeof ( *mbmemmap ) );
84
 	for ( i = 0 ; i < memmap.count ; i++ ) {
79
 	for ( i = 0 ; i < memmap.count ; i++ ) {
85
 		mbmemmap[i].size = sizeof ( mbmemmap[i] );
80
 		mbmemmap[i].size = sizeof ( mbmemmap[i] );
86
 		mbmemmap[i].base_addr = memmap.regions[i].start;
81
 		mbmemmap[i].base_addr = memmap.regions[i].start;
87
 		mbmemmap[i].length = ( memmap.regions[i].end -
82
 		mbmemmap[i].length = ( memmap.regions[i].end -
88
 				       memmap.regions[i].start );
83
 				       memmap.regions[i].start );
89
 		mbmemmap[i].type = MBMEM_RAM;
84
 		mbmemmap[i].type = MBMEM_RAM;
90
-		mbinfo.mmap_length += sizeof ( mbmemmap[i] );
85
+		mbinfo->mmap_length += sizeof ( mbmemmap[i] );
91
 		if ( memmap.regions[i].start == 0 )
86
 		if ( memmap.regions[i].start == 0 )
92
-			mbinfo.mem_lower = memmap.regions[i].end;
87
+			mbinfo->mem_lower = memmap.regions[i].end;
93
 		if ( memmap.regions[i].start == 0x100000 )
88
 		if ( memmap.regions[i].start == 0x100000 )
94
-			mbinfo.mem_upper = ( memmap.regions[i].end - 0x100000);
89
+			mbinfo->mem_upper = ( memmap.regions[i].end -
90
+					      0x100000 );
95
 	}
91
 	}
96
-	mbinfo.flags |= ( MBI_FLAG_MEM | MBI_FLAG_MMAP );
92
+}
93
+
94
+/**
95
+ * Build multiboot module list
96
+ *
97
+ * @v image		Multiboot image
98
+ * @v modules		Module list to fill, or NULL
99
+ * @ret count		Number of modules
100
+ */
101
+static unsigned int
102
+multiboot_build_module_list ( struct image *image,
103
+			      struct multiboot_module *modules ) {
104
+	struct image *module_image;
105
+	struct multiboot_module *module;
106
+	unsigned int count = 0;
107
+
108
+	for_each_image ( module_image ) {
109
+		/* Do not include kernel image as a module */
110
+		if ( module_image == image )
111
+			continue;
112
+		module = &modules[count++];
113
+		/* Populate module data structure, if applicable */
114
+		if ( ! modules )
115
+			continue;
116
+		module->mod_start = user_to_phys ( module_image->data, 0 );
117
+		module->mod_end = user_to_phys ( module_image->data,
118
+						 module_image->len );
119
+		if ( image->cmdline )
120
+			module->string = virt_to_phys ( image->cmdline );
121
+	}
122
+
123
+	return count;
124
+}
125
+
126
+/**
127
+ * Execute multiboot image
128
+ *
129
+ * @v image		Multiboot image
130
+ * @ret rc		Return status code
131
+ */
132
+static int multiboot_exec ( struct image *image ) {
133
+	static const char *bootloader_name = "gPXE " VERSION;
134
+	struct multiboot_info mbinfo;
135
+	struct multiboot_memory_map mbmemmap[MAX_MEMORY_REGIONS];
136
+	struct multiboot_module *modules;
137
+	unsigned int num_modules;
138
+
139
+	/* Populate multiboot information structure */
140
+	memset ( &mbinfo, 0, sizeof ( mbinfo ) );
141
+
142
+	/* Set boot loader name */
143
+	mbinfo.boot_loader_name = virt_to_phys ( bootloader_name );
144
+	mbinfo.flags |= MBI_FLAG_LOADER;
145
+	
146
+	/* Build memory map */
147
+	multiboot_build_memmap ( &mbinfo, mbmemmap );
97
 	mbinfo.mmap_addr = virt_to_phys ( &mbmemmap[0].base_addr );
148
 	mbinfo.mmap_addr = virt_to_phys ( &mbmemmap[0].base_addr );
149
+	mbinfo.flags |= ( MBI_FLAG_MEM | MBI_FLAG_MMAP );
98
 
150
 
99
 	/* Set command line, if present */
151
 	/* Set command line, if present */
100
 	if ( image->cmdline ) {
152
 	if ( image->cmdline ) {
101
-		mbinfo.flags |= MBI_FLAG_CMDLINE;
102
 		mbinfo.cmdline = virt_to_phys ( image->cmdline );
153
 		mbinfo.cmdline = virt_to_phys ( image->cmdline );
154
+		mbinfo.flags |= MBI_FLAG_CMDLINE;
103
 	}
155
 	}
104
 
156
 
157
+	/* Construct module list */
158
+	num_modules = multiboot_build_module_list ( image, NULL );
159
+	modules = alloca ( num_modules * sizeof ( *modules ) );
160
+	multiboot_build_module_list ( image, modules );
161
+	mbinfo.mods_count = num_modules;
162
+	mbinfo.mods_addr = virt_to_phys ( modules );
163
+	mbinfo.flags |= MBI_FLAG_MODS;
164
+
105
 	/* Jump to OS with flat physical addressing */
165
 	/* Jump to OS with flat physical addressing */
106
-	__asm__ __volatile__ ( PHYS_CODE ( "xchgw %%bx,%%bx\n\t"
107
-					   "call *%%edi\n\t" )
166
+	__asm__ __volatile__ ( PHYS_CODE ( /* Preserve %ebp for alloca() */
167
+					   "pushl %%ebp\n\t"
168
+					   "call *%%edi\n\t"
169
+					   "popl %%ebp\n\t" )
108
 			       : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
170
 			       : : "a" ( MULTIBOOT_BOOTLOADER_MAGIC ),
109
 			           "b" ( virt_to_phys ( &mbinfo ) ),
171
 			           "b" ( virt_to_phys ( &mbinfo ) ),
110
 			           "D" ( image->entry )
172
 			           "D" ( image->entry )
111
-			       : "ecx", "edx", "esi", "ebp" );
173
+			       : "ecx", "edx", "esi", "memory" );
112
 
174
 
113
 	return -ECANCELED;
175
 	return -ECANCELED;
114
 }
176
 }
191
 
253
 
192
 	/* Record execution entry point */
254
 	/* Record execution entry point */
193
 	image->entry = hdr->mb.entry_addr;
255
 	image->entry = hdr->mb.entry_addr;
194
-	image->execute = multiboot_execute;
195
 
256
 
196
 	return 0;
257
 	return 0;
197
 }
258
 }
209
 	if ( ( rc = elf_load ( image ) ) != 0 ) {
270
 	if ( ( rc = elf_load ( image ) ) != 0 ) {
210
 		DBG ( "Multiboot ELF image failed to load: %s\n",
271
 		DBG ( "Multiboot ELF image failed to load: %s\n",
211
 		      strerror ( rc ) );
272
 		      strerror ( rc ) );
212
-		/* We must translate "not an ELF image" (i.e. ENOEXEC)
213
-		 * into "invalid multiboot image", to avoid screwing
214
-		 * up the image probing logic.
215
-		 */
216
-		if ( rc == -ENOEXEC ) {
217
-			return -ENOTSUP;
218
-		} else {
219
-			return rc;
220
-		}
273
+		return rc;
221
 	}
274
 	}
222
 
275
 
223
-	/* Capture execution method */
224
-	if ( image->execute )
225
-		image->execute = multiboot_execute;
226
-
227
 	return 0;
276
 	return 0;
228
 }
277
 }
229
 
278
 
244
 	}
293
 	}
245
 	DBG ( "Found multiboot header with flags %08lx\n", hdr.mb.flags );
294
 	DBG ( "Found multiboot header with flags %08lx\n", hdr.mb.flags );
246
 
295
 
296
+	/* This is a multiboot image, valid or otherwise */
297
+	if ( ! image->type )
298
+		image->type = &multiboot_image_type;
299
+
247
 	/* Abort if we detect flags that we cannot support */
300
 	/* Abort if we detect flags that we cannot support */
248
 	if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
301
 	if ( hdr.mb.flags & MB_UNSUPPORTED_FLAGS ) {
249
 		DBG ( "Multiboot flags %08lx not supported\n",
302
 		DBG ( "Multiboot flags %08lx not supported\n",
267
 struct image_type multiboot_image_type __image_type = {
320
 struct image_type multiboot_image_type __image_type = {
268
 	.name = "Multiboot",
321
 	.name = "Multiboot",
269
 	.load = multiboot_load,
322
 	.load = multiboot_load,
323
+	.exec = multiboot_exec,
270
 };
324
 };

+ 115
- 62
src/core/image.c Voir le fichier

1
-#include "dev.h"
2
-#include <gpxe/buffer.h>
3
-#include <console.h>
1
+/*
2
+ * Copyright (C) 2006 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 <stddef.h>
20
+#include <string.h>
21
+#include <stdlib.h>
22
+#include <errno.h>
23
+#include <assert.h>
24
+#include <vsprintf.h>
25
+#include <gpxe/list.h>
26
+#include <gpxe/image.h>
27
+
28
+/** @file
29
+ *
30
+ * Executable/loadable images
31
+ *
32
+ */
4
 
33
 
5
-#if 0
34
+/** List of registered images */
35
+struct list_head images = LIST_HEAD_INIT ( images );
6
 
36
 
7
-static struct image images[0] __image_start;
8
-static struct image images_end[0] __image_end;
37
+/** List of image types */
38
+static struct image_type image_types[0]
39
+	__table_start ( struct image_type, image_types );
40
+static struct image_type image_types_end[0]
41
+	__table_end ( struct image_type, image_types );
9
 
42
 
10
-/*
11
- * Print all images
43
+/**
44
+ * Register executable/loadable image
12
  *
45
  *
46
+ * @v image		Executable/loadable image
47
+ * @ret rc		Return status code
13
  */
48
  */
14
-void print_images ( void ) {
15
-	struct image *image;
49
+int register_image ( struct image *image ) {
50
+	static unsigned int imgindex = 0;
16
 
51
 
17
-	for ( image = images ; image < images_end ; image++ ) {
18
-		printf ( "%s ", image->name );
19
-	}
52
+	/* Create image name */
53
+	snprintf ( image->name, sizeof ( image->name ), "img%d",
54
+		   imgindex++ );
55
+
56
+	/* Add to image list */
57
+	list_add_tail ( &image->list, &images );
58
+	DBGC ( image, "IMAGE %p registered as %s\n", image, image->name );
59
+
60
+	return 0;
20
 }
61
 }
21
 
62
 
22
-/*
23
- * Identify the image format
63
+/**
64
+ * Unregister executable/loadable image
24
  *
65
  *
66
+ * @v image		Executable/loadable image
25
  */
67
  */
26
-static struct image * identify_image ( physaddr_t start, physaddr_t len,
27
-				       void **context ) {
28
-	struct image *image;
29
-	
30
-	for ( image = images ; image < images_end ; image++ ) {
31
-		if ( image->probe ( start, len, context ) )
32
-			return image;
33
-	}
34
-	
35
-	return NULL;
68
+void unregister_image ( struct image *image ) {
69
+	list_del ( &image->list );
70
+	DBGC ( image, "IMAGE %p unregistered\n", image );
36
 }
71
 }
37
 
72
 
38
-/*
39
- * Load an image into memory at a location determined by the image
40
- * format
73
+/**
74
+ * Load executable/loadable image into memory
41
  *
75
  *
76
+ * @v image		Executable/loadable image
77
+ * @ret rc		Return status code
42
  */
78
  */
43
-int autoload ( struct dev *dev, struct image **image, void **context ) {
44
-	struct buffer buffer;
45
-	int rc = 0;
46
-
47
-	/* Prepare the load buffer */
48
-	if ( ! init_load_buffer ( &buffer ) ) {
49
-		DBG ( "IMAGE could not initialise load buffer\n" );
50
-		goto out;
51
-	}
79
+int image_load ( struct image *image ) {
80
+	int rc;
52
 
81
 
53
-	/* Load the image into the load buffer */
54
-	if ( ! load ( dev, &buffer ) ) {
55
-		DBG ( "IMAGE could not load image\n" );
56
-		goto out_free;
82
+	assert ( image->type != NULL );
83
+
84
+	if ( ( rc = image->type->load ( image ) ) != 0 ) {
85
+		DBGC ( image, "IMAGE %p could not load: %s\n",
86
+		       image, strerror ( rc ) );
87
+		return rc;
57
 	}
88
 	}
58
 
89
 
59
-	/* Shrink the load buffer */
60
-	trim_load_buffer ( &buffer );
90
+	return 0;
91
+}
61
 
92
 
62
-	/* Identify the image type */
63
-	*image = identify_image ( buffer.start, buffer.fill, context );
64
-	if ( ! *image ) {
65
-		DBG ( "IMAGE could not identify image type\n" );
66
-		goto out_free;
67
-	}
93
+/**
94
+ * Autodetect image type and load executable/loadable image into memory
95
+ *
96
+ * @v image		Executable/loadable image
97
+ * @ret rc		Return status code
98
+ */
99
+int image_autoload ( struct image *image ) {
100
+	struct image_type *type;
101
+	int rc;
68
 
102
 
69
-	/* Move the image into the target location */
70
-	if ( ! (*image)->load ( buffer.start, buffer.fill, *context ) ) {
71
-		DBG ( "IMAGE could not move to target location\n" );
72
-		goto out_free;
103
+	for ( type = image_types ; type < image_types_end ; type++ ) {
104
+		rc = type->load ( image );
105
+		if ( image->type == NULL )
106
+			continue;
107
+		if ( rc != 0 ) {
108
+			DBGC ( image, "IMAGE %p (%s) could not load: %s\n",
109
+			       image, image->type->name, strerror ( rc ) );
110
+			return rc;
111
+		}
112
+		return 0;
73
 	}
113
 	}
74
 
114
 
75
-	/* Return success */
76
-	rc = 1;
77
-
78
- out_free:
79
-	/* Free the load buffer */
80
-	done_load_buffer ( &buffer );
81
- out:
82
-	return rc;
115
+	DBGC ( image, "IMAGE %p format not recognised\n", image );
116
+	return -ENOEXEC;
83
 }
117
 }
84
 
118
 
85
-#endif
119
+/**
120
+ * Execute loaded image
121
+ *
122
+ * @v image		Loaded image
123
+ * @ret rc		Return status code
124
+ */
125
+int image_exec ( struct image *image ) {
126
+	int rc;
127
+
128
+	assert ( image->type != NULL );
129
+
130
+	if ( ( rc = image->type->exec ( image ) ) != 0 ) {
131
+		DBGC ( image, "IMAGE %p could not execute: %s\n",
132
+		       image, strerror ( rc ) );
133
+		return rc;
134
+	}
135
+
136
+	/* Well, some formats might return... */
137
+	return 0;
138
+}

+ 11
- 5
src/image/elf.c Voir le fichier

30
 #include <gpxe/image.h>
30
 #include <gpxe/image.h>
31
 #include <gpxe/elf.h>
31
 #include <gpxe/elf.h>
32
 
32
 
33
+struct image_type elf_image_type __image_type;
34
+
33
 typedef Elf32_Ehdr	Elf_Ehdr;
35
 typedef Elf32_Ehdr	Elf_Ehdr;
34
 typedef Elf32_Phdr	Elf_Phdr;
36
 typedef Elf32_Phdr	Elf_Phdr;
35
 typedef Elf32_Off	Elf_Off;
37
 typedef Elf32_Off	Elf_Off;
40
  * @v image		ELF file
42
  * @v image		ELF file
41
  * @ret rc		Return status code
43
  * @ret rc		Return status code
42
  */
44
  */
43
-static int elf_execute ( struct image *image __unused ) {
45
+static int elf_exec ( struct image *image __unused ) {
44
 	return -ENOTSUP;
46
 	return -ENOTSUP;
45
 }
47
 }
46
 
48
 
63
 	/* Check segment lies within image */
65
 	/* Check segment lies within image */
64
 	if ( ( phdr->p_offset + phdr->p_filesz ) > image->len ) {
66
 	if ( ( phdr->p_offset + phdr->p_filesz ) > image->len ) {
65
 		DBG ( "ELF segment outside ELF file\n" );
67
 		DBG ( "ELF segment outside ELF file\n" );
66
-		return -ERANGE;
68
+		return -ENOEXEC;
67
 	}
69
 	}
68
 
70
 
69
 	/* Find start address: use physical address for preference,
71
 	/* Find start address: use physical address for preference,
75
 		dest = phdr->p_vaddr;
77
 		dest = phdr->p_vaddr;
76
 	if ( ! dest ) {
78
 	if ( ! dest ) {
77
 		DBG ( "ELF segment loads to physical address 0\n" );
79
 		DBG ( "ELF segment loads to physical address 0\n" );
78
-		return -ERANGE;
80
+		return -ENOEXEC;
79
 	}
81
 	}
80
 	buffer = phys_to_user ( dest );
82
 	buffer = phys_to_user ( dest );
81
 
83
 
117
 		return -ENOEXEC;
119
 		return -ENOEXEC;
118
 	}
120
 	}
119
 
121
 
122
+	/* This is an ELF image, valid or otherwise */
123
+	if ( ! image->type )
124
+		image->type = &elf_image_type;
125
+
120
 	/* Read ELF program headers */
126
 	/* Read ELF program headers */
121
 	for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
127
 	for ( phoff = ehdr.e_phoff , phnum = ehdr.e_phnum ; phnum ;
122
 	      phoff += ehdr.e_phentsize, phnum-- ) {
128
 	      phoff += ehdr.e_phentsize, phnum-- ) {
123
 		if ( phoff > image->len ) {
129
 		if ( phoff > image->len ) {
124
 			DBG ( "ELF program header %d outside ELF image\n",
130
 			DBG ( "ELF program header %d outside ELF image\n",
125
 			      phnum );
131
 			      phnum );
126
-			return -ERANGE;
132
+			return -ENOEXEC;
127
 		}
133
 		}
128
 		copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
134
 		copy_from_user ( &phdr, image->data, phoff, sizeof ( phdr ) );
129
 		if ( ( rc = elf_load_segment ( image, &phdr ) ) != 0 )
135
 		if ( ( rc = elf_load_segment ( image, &phdr ) ) != 0 )
132
 
138
 
133
 	/* Fill in entry point address */
139
 	/* Fill in entry point address */
134
 	image->entry = ehdr.e_entry;
140
 	image->entry = ehdr.e_entry;
135
-	image->execute = elf_execute;
136
 
141
 
137
 	return 0;
142
 	return 0;
138
 }
143
 }
141
 struct image_type elf_image_type __image_type = {
146
 struct image_type elf_image_type __image_type = {
142
 	.name = "ELF",
147
 	.name = "ELF",
143
 	.load = elf_load,
148
 	.load = elf_load,
149
+	.exec = elf_exec,
144
 };
150
 };

+ 44
- 17
src/include/gpxe/image.h Voir le fichier

4
 /**
4
 /**
5
  * @file
5
  * @file
6
  *
6
  *
7
- * Executable/loadable image formats
7
+ * Executable/loadable images
8
  *
8
  *
9
  */
9
  */
10
 
10
 
11
 #include <gpxe/tables.h>
11
 #include <gpxe/tables.h>
12
+#include <gpxe/list.h>
13
+#include <gpxe/uaccess.h>
14
+
15
+struct image_type;
12
 
16
 
13
 /** An executable or loadable image */
17
 /** An executable or loadable image */
14
 struct image {
18
 struct image {
19
+	/** Name */
20
+	char name[16];
21
+	/** List of registered images */
22
+	struct list_head list;
23
+
24
+	/** Command line to pass to image */
25
+	const char *cmdline;
26
+
15
 	/** Raw file image */
27
 	/** Raw file image */
16
 	userptr_t data;
28
 	userptr_t data;
17
 	/** Length of raw file image */
29
 	/** Length of raw file image */
18
 	size_t len;
30
 	size_t len;
19
 
31
 
20
-	/** Execute method
21
-	 *
22
-	 * Filled in by the image loader.  If NULL, then the image
23
-	 * cannot be executed.
24
-	 */
25
-	int ( * execute ) ( struct image *image );
26
 	/** Entry point */
32
 	/** Entry point */
27
 	physaddr_t entry;
33
 	physaddr_t entry;
28
 
34
 
29
-	/** Command line to pass to image */
30
-	const char *cmdline;
35
+	/** Image type, if known */
36
+	struct image_type *type;
31
 };
37
 };
32
 
38
 
33
 /** An executable or loadable image type */
39
 /** An executable or loadable image type */
34
 struct image_type {
40
 struct image_type {
35
 	/** Name of this image type */
41
 	/** Name of this image type */
36
 	char *name;
42
 	char *name;
37
-	/** Load image into memory
43
+	/**
44
+	 * Load image into memory
38
 	 *
45
 	 *
39
 	 * @v image		Executable/loadable image
46
 	 * @v image		Executable/loadable image
40
 	 * @ret rc		Return status code
47
 	 * @ret rc		Return status code
44
 	 * information it may require later (e.g. the execution
51
 	 * information it may require later (e.g. the execution
45
 	 * address) within the @c image structure.
52
 	 * address) within the @c image structure.
46
 	 *
53
 	 *
47
-	 * The method should return -ENOEXEC if and only if the image
48
-	 * is not in the correct format.  Other errors will be
49
-	 * interpreted as "I claim this image format, but there's
50
-	 * something wrong with it that makes it unloadable".  In
51
-	 * particular, returning -ENOEXEC will cause the image probing
52
-	 * code to try the next available image type, while returning
53
-	 * any other error will terminate image probing.
54
+	 * If the file image is in the correct format, the method must
55
+	 * update @c image->type to point to its own type (unless @c
56
+	 * image->type is already set).  This allows the autoloading
57
+	 * code to disambiguate between "this is not my image format"
58
+	 * and "there is something wrong with this image".  In
59
+	 * particular, setting @c image->type and then returning an
60
+	 * error will cause image_autoload() to abort and return an
61
+	 * error, rather than continuing to the next image type.
54
 	 */
62
 	 */
55
 	int ( * load ) ( struct image *image );
63
 	int ( * load ) ( struct image *image );
64
+	/**
65
+	 * Execute loaded image
66
+	 *
67
+	 * @v image		Loaded image
68
+	 * @ret rc		Return status code
69
+	 */
70
+	int ( * exec ) ( struct image *image );
56
 };
71
 };
57
 
72
 
58
 /** An executable or loadable image type */
73
 /** An executable or loadable image type */
68
  */
83
  */
69
 #define __default_image_type __table ( struct image_type, image_types, 02 )
84
 #define __default_image_type __table ( struct image_type, image_types, 02 )
70
 
85
 
86
+extern struct list_head images;
87
+
88
+/** Iterate over all registered images */
89
+#define for_each_image( image ) \
90
+	list_for_each_entry ( (image), &images, list )
91
+
92
+extern int register_image ( struct image *image );
93
+extern void unregister_image ( struct image *image );
94
+extern int image_load ( struct image *image );
95
+extern int image_autoload ( struct image *image );
96
+extern int image_exec ( struct image *image );
97
+
71
 #endif /* _GPXE_IMAGE_H */
98
 #endif /* _GPXE_IMAGE_H */

Chargement…
Annuler
Enregistrer