]> git.ipfire.org Git - thirdparty/ipxe.git/commitdiff
[image] Detect image type when image is first registered
authorMichael Brown <mcb30@ipxe.org>
Fri, 21 Aug 2015 15:15:24 +0000 (16:15 +0100)
committerMichael Brown <mcb30@ipxe.org>
Fri, 21 Aug 2015 15:25:11 +0000 (16:25 +0100)
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>
src/core/image.c
src/include/ipxe/image.h
src/tests/pixbuf_test.c

index 365e4d8017b2a33ce5daa9c12c56e05da18e4cbf..529e3d72cd4ce7a7629f700d23ccf0d3b57fcc17 100644 (file)
@@ -157,6 +157,32 @@ int image_set_cmdline ( struct image *image, const char *cmdline ) {
        return 0;
 }
 
+/**
+ * Determine image type
+ *
+ * @v image            Executable image
+ * @ret rc             Return status code
+ */
+static int image_probe ( struct image *image ) {
+       struct image_type *type;
+       int rc;
+
+       /* Try each type in turn */
+       for_each_table_entry ( type, IMAGE_TYPES ) {
+               if ( ( rc = type->probe ( image ) ) == 0 ) {
+                       image->type = type;
+                       DBGC ( image, "IMAGE %s is %s\n",
+                              image->name, type->name );
+                       break;
+               }
+               DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
+                      type->name, strerror ( rc ) );
+       }
+
+       DBGC ( image, "IMAGE %s format not recognised\n", image->name );
+       return -ENOTSUP;
+}
+
 /**
  * Register executable image
  *
@@ -189,6 +215,14 @@ int register_image ( struct image *image ) {
               image->name, user_to_phys ( image->data, 0 ),
               user_to_phys ( image->data, image->len ) );
 
+       /* Try to detect image type, if applicable.  Ignore failures,
+        * since we expect to handle some unrecognised images
+        * (e.g. kernel initrds, multiboot modules, random files
+        * provided via our EFI virtual filesystem, etc).
+        */
+       if ( ! image->type )
+               image_probe ( image );
+
        return 0;
 }
 
@@ -226,36 +260,6 @@ struct image * find_image ( const char *name ) {
        return NULL;
 }
 
-/**
- * Determine image type
- *
- * @v image            Executable image
- * @ret rc             Return status code
- */
-int image_probe ( struct image *image ) {
-       struct image_type *type;
-       int rc;
-
-       /* Succeed if we already have a type */
-       if ( image->type )
-               return 0;
-
-       /* Try each type in turn */
-       for_each_table_entry ( type, IMAGE_TYPES ) {
-               if ( ( rc = type->probe ( image ) ) == 0 ) {
-                       image->type = type;
-                       DBGC ( image, "IMAGE %s is %s\n",
-                              image->name, type->name );
-                       return 0;
-               }
-               DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
-                      type->name, strerror ( rc ) );
-       }
-
-       DBGC ( image, "IMAGE %s format not recognised\n", image->name );
-       return -ENOEXEC;
-}
-
 /**
  * Execute image
  *
@@ -288,9 +292,11 @@ int image_exec ( struct image *image ) {
         */
        current_image = image_get ( image );
 
-       /* Check that this image can be selected for execution */
-       if ( ( rc = image_select ( image ) ) != 0 )
+       /* Check that this image can be executed */
+       if ( ! ( image->type && image->type->exec ) ) {
+               rc = -ENOEXEC;
                goto err;
+       }
 
        /* Check that image is trusted (if applicable) */
        if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) {
@@ -382,8 +388,8 @@ int image_replace ( struct image *replacement ) {
        }
 
        /* Check that the replacement image can be executed */
-       if ( ( rc = image_probe ( replacement ) ) != 0 )
-               return rc;
+       if ( ! ( replacement->type && replacement->type->exec ) )
+               return -ENOEXEC;
 
        /* Clear any existing replacement */
        image_put ( image->replacement );
@@ -404,16 +410,13 @@ int image_replace ( struct image *replacement ) {
  */
 int image_select ( struct image *image ) {
        struct image *tmp;
-       int rc;
 
        /* Unselect all other images */
        for_each_image ( tmp )
                tmp->flags &= ~IMAGE_SELECTED;
 
        /* Check that this image can be executed */
-       if ( ( rc = image_probe ( image ) ) != 0 )
-               return rc;
-       if ( ! image->type->exec )
+       if ( ! ( image->type && image->type->exec ) )
                return -ENOEXEC;
 
        /* Mark image as selected */
@@ -472,9 +475,7 @@ int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
        int rc;
 
        /* Check that this image can be used to create a pixel buffer */
-       if ( ( rc = image_probe ( image ) ) != 0 )
-               return rc;
-       if ( ! image->type->pixbuf )
+       if ( ! ( image->type && image->type->pixbuf ) )
                return -ENOTSUP;
 
        /* Try creating pixel buffer */
index 5d003842a9af28eaeaa28bf457c5f342e0cdf919..6abd7a2d2f226d192e7a770c9bf70de7bf633a99 100644 (file)
@@ -163,7 +163,6 @@ extern int image_set_cmdline ( struct image *image, const char *cmdline );
 extern int register_image ( struct image *image );
 extern void unregister_image ( struct image *image );
 struct image * find_image ( const char *name );
-extern int image_probe ( struct image *image );
 extern int image_exec ( struct image *image );
 extern int image_replace ( struct image *replacement );
 extern int image_select ( struct image *image );
index 28c502b43878a9942c8d28e05f61ea18017283ac..aaa516bb293c3e48a304eee8dd356b7fd413e436 100644 (file)
@@ -57,8 +57,8 @@ void pixbuf_okx ( struct pixel_buffer_test *test, const char *file,
        /* Correct image data pointer */
        test->image->data = virt_to_user ( ( void * ) test->image->data );
 
-       /* Check that image is detected as PNM */
-       okx ( image_probe ( test->image ) == 0, file, line );
+       /* Check that image is detected as correct type */
+       okx ( register_image ( test->image ) == 0, file, line );
        okx ( test->image->type == test->type, file, line );
 
        /* 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,
 
                pixbuf_put ( pixbuf );
        }
+
+       /* Unregister image */
+       unregister_image ( test->image );
 }