浏览代码

[image] Detect image type when image is first registered

The current usage pattern of image_probe() is a legacy from the time
before commit 34b6ecb ("[image] Simplify image management") when
loading an image to its executable location in memory was a separate
action from actually executing the image.

Call image_probe() as soon as an image is registered.  This allows
"imgstat" to display image type information for all images and allows
image-consuming code to assume that image->type is already set
correctly.

Ignore failures if image_probe() does not recognise the image, since
we do expect to handle unrecognised images (initrds, modules, etc).
Unrecognised images will be left with a NULL image->type, which
image-consuming code can easily check.

Signed-off-by: Michael Brown <mcb30@ipxe.org>
tags/v1.20.1
Michael Brown 9 年前
父节点
当前提交
abfe94a90a
共有 3 个文件被更改,包括 47 次插入44 次删除
  1. 42
    41
      src/core/image.c
  2. 0
    1
      src/include/ipxe/image.h
  3. 5
    2
      src/tests/pixbuf_test.c

+ 42
- 41
src/core/image.c 查看文件

@@ -157,6 +157,32 @@ int image_set_cmdline ( struct image *image, const char *cmdline ) {
157 157
 	return 0;
158 158
 }
159 159
 
160
+/**
161
+ * Determine image type
162
+ *
163
+ * @v image		Executable image
164
+ * @ret rc		Return status code
165
+ */
166
+static int image_probe ( struct image *image ) {
167
+	struct image_type *type;
168
+	int rc;
169
+
170
+	/* Try each type in turn */
171
+	for_each_table_entry ( type, IMAGE_TYPES ) {
172
+		if ( ( rc = type->probe ( image ) ) == 0 ) {
173
+			image->type = type;
174
+			DBGC ( image, "IMAGE %s is %s\n",
175
+			       image->name, type->name );
176
+			break;
177
+		}
178
+		DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
179
+		       type->name, strerror ( rc ) );
180
+	}
181
+
182
+	DBGC ( image, "IMAGE %s format not recognised\n", image->name );
183
+	return -ENOTSUP;
184
+}
185
+
160 186
 /**
161 187
  * Register executable image
162 188
  *
@@ -189,6 +215,14 @@ int register_image ( struct image *image ) {
189 215
 	       image->name, user_to_phys ( image->data, 0 ),
190 216
 	       user_to_phys ( image->data, image->len ) );
191 217
 
218
+	/* Try to detect image type, if applicable.  Ignore failures,
219
+	 * since we expect to handle some unrecognised images
220
+	 * (e.g. kernel initrds, multiboot modules, random files
221
+	 * provided via our EFI virtual filesystem, etc).
222
+	 */
223
+	if ( ! image->type )
224
+		image_probe ( image );
225
+
192 226
 	return 0;
193 227
 }
194 228
 
@@ -226,36 +260,6 @@ struct image * find_image ( const char *name ) {
226 260
 	return NULL;
227 261
 }
228 262
 
229
-/**
230
- * Determine image type
231
- *
232
- * @v image		Executable image
233
- * @ret rc		Return status code
234
- */
235
-int image_probe ( struct image *image ) {
236
-	struct image_type *type;
237
-	int rc;
238
-
239
-	/* Succeed if we already have a type */
240
-	if ( image->type )
241
-		return 0;
242
-
243
-	/* Try each type in turn */
244
-	for_each_table_entry ( type, IMAGE_TYPES ) {
245
-		if ( ( rc = type->probe ( image ) ) == 0 ) {
246
-			image->type = type;
247
-			DBGC ( image, "IMAGE %s is %s\n",
248
-			       image->name, type->name );
249
-			return 0;
250
-		}
251
-		DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
252
-		       type->name, strerror ( rc ) );
253
-	}
254
-
255
-	DBGC ( image, "IMAGE %s format not recognised\n", image->name );
256
-	return -ENOEXEC;
257
-}
258
-
259 263
 /**
260 264
  * Execute image
261 265
  *
@@ -288,9 +292,11 @@ int image_exec ( struct image *image ) {
288 292
 	 */
289 293
 	current_image = image_get ( image );
290 294
 
291
-	/* Check that this image can be selected for execution */
292
-	if ( ( rc = image_select ( image ) ) != 0 )
295
+	/* Check that this image can be executed */
296
+	if ( ! ( image->type && image->type->exec ) ) {
297
+		rc = -ENOEXEC;
293 298
 		goto err;
299
+	}
294 300
 
295 301
 	/* Check that image is trusted (if applicable) */
296 302
 	if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) {
@@ -382,8 +388,8 @@ int image_replace ( struct image *replacement ) {
382 388
 	}
383 389
 
384 390
 	/* Check that the replacement image can be executed */
385
-	if ( ( rc = image_probe ( replacement ) ) != 0 )
386
-		return rc;
391
+	if ( ! ( replacement->type && replacement->type->exec ) )
392
+		return -ENOEXEC;
387 393
 
388 394
 	/* Clear any existing replacement */
389 395
 	image_put ( image->replacement );
@@ -404,16 +410,13 @@ int image_replace ( struct image *replacement ) {
404 410
  */
405 411
 int image_select ( struct image *image ) {
406 412
 	struct image *tmp;
407
-	int rc;
408 413
 
409 414
 	/* Unselect all other images */
410 415
 	for_each_image ( tmp )
411 416
 		tmp->flags &= ~IMAGE_SELECTED;
412 417
 
413 418
 	/* Check that this image can be executed */
414
-	if ( ( rc = image_probe ( image ) ) != 0 )
415
-		return rc;
416
-	if ( ! image->type->exec )
419
+	if ( ! ( image->type && image->type->exec ) )
417 420
 		return -ENOEXEC;
418 421
 
419 422
 	/* Mark image as selected */
@@ -472,9 +475,7 @@ int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
472 475
 	int rc;
473 476
 
474 477
 	/* Check that this image can be used to create a pixel buffer */
475
-	if ( ( rc = image_probe ( image ) ) != 0 )
476
-		return rc;
477
-	if ( ! image->type->pixbuf )
478
+	if ( ! ( image->type && image->type->pixbuf ) )
478 479
 		return -ENOTSUP;
479 480
 
480 481
 	/* Try creating pixel buffer */

+ 0
- 1
src/include/ipxe/image.h 查看文件

@@ -163,7 +163,6 @@ extern int image_set_cmdline ( struct image *image, const char *cmdline );
163 163
 extern int register_image ( struct image *image );
164 164
 extern void unregister_image ( struct image *image );
165 165
 struct image * find_image ( const char *name );
166
-extern int image_probe ( struct image *image );
167 166
 extern int image_exec ( struct image *image );
168 167
 extern int image_replace ( struct image *replacement );
169 168
 extern int image_select ( struct image *image );

+ 5
- 2
src/tests/pixbuf_test.c 查看文件

@@ -57,8 +57,8 @@ void pixbuf_okx ( struct pixel_buffer_test *test, const char *file,
57 57
 	/* Correct image data pointer */
58 58
 	test->image->data = virt_to_user ( ( void * ) test->image->data );
59 59
 
60
-	/* Check that image is detected as PNM */
61
-	okx ( image_probe ( test->image ) == 0, file, line );
60
+	/* Check that image is detected as correct type */
61
+	okx ( register_image ( test->image ) == 0, file, line );
62 62
 	okx ( test->image->type == test->type, file, line );
63 63
 
64 64
 	/* Check that a pixel buffer can be created from the image */
@@ -77,4 +77,7 @@ void pixbuf_okx ( struct pixel_buffer_test *test, const char *file,
77 77
 
78 78
 		pixbuf_put ( pixbuf );
79 79
 	}
80
+
81
+	/* Unregister image */
82
+	unregister_image ( test->image );
80 83
 }

正在加载...
取消
保存