aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/image.c69
-rw-r--r--src/hci/commands/image_cmd.c2
-rw-r--r--src/image/script.c7
-rw-r--r--src/include/ipxe/image.h47
-rw-r--r--src/interface/efi/efi_file.c2
-rw-r--r--src/usr/imgmgmt.c8
6 files changed, 85 insertions, 50 deletions
diff --git a/src/core/image.c b/src/core/image.c
index b280eb4..3e65b5e 100644
--- a/src/core/image.c
+++ b/src/core/image.c
@@ -56,8 +56,15 @@ FILE_LICENCE ( GPL2_OR_LATER_OR_UBDL );
/** List of registered images */
struct list_head images = LIST_HEAD_INIT ( images );
+/** Image selected for execution */
+struct image_tag selected_image __image_tag = {
+ .name = "SELECTED",
+};
+
/** Currently-executing image */
-struct image *current_image;
+struct image_tag current_image __image_tag = {
+ .name = "CURRENT",
+};
/** Current image trust requirement */
static int require_trusted_images = 0;
@@ -72,8 +79,13 @@ static int require_trusted_images_permanent = 0;
*/
static void free_image ( struct refcnt *refcnt ) {
struct image *image = container_of ( refcnt, struct image, refcnt );
+ struct image_tag *tag;
DBGC ( image, "IMAGE %s freed\n", image->name );
+ for_each_table_entry ( tag, IMAGE_TAGS ) {
+ if ( tag->image == image )
+ tag->image = NULL;
+ }
free ( image->name );
free ( image->cmdline );
uri_put ( image->uri );
@@ -261,12 +273,6 @@ int register_image ( struct image *image ) {
return rc;
}
- /* Avoid ending up with multiple "selected" images on
- * re-registration
- */
- if ( image_find_selected() )
- image->flags &= ~IMAGE_SELECTED;
-
/* Add to image list */
image_get ( image );
image->flags |= IMAGE_REGISTERED;
@@ -321,6 +327,23 @@ struct image * find_image ( const char *name ) {
}
/**
+ * Find image by tag
+ *
+ * @v tag Image tag
+ * @ret image Executable image, or NULL
+ */
+struct image * find_image_tag ( struct image_tag *tag ) {
+ struct image *image;
+
+ for_each_image ( image ) {
+ if ( tag->image == image )
+ return image;
+ }
+
+ return NULL;
+}
+
+/**
* Execute image
*
* @v image Executable image
@@ -346,13 +369,13 @@ int image_exec ( struct image *image ) {
if ( image->uri )
churi ( image->uri );
- /* Preserve record of any currently-running image */
- saved_current_image = current_image;
+ /* Set as currently running image */
+ saved_current_image = image_tag ( image, &current_image );
/* Take out a temporary reference to the image, so that it
* does not get freed when temporarily unregistered.
*/
- current_image = image_get ( image );
+ image_get ( image );
/* Check that this image can be executed */
if ( ! ( image->type && image->type->exec ) ) {
@@ -419,7 +442,7 @@ int image_exec ( struct image *image ) {
image_put ( image );
/* Restore previous currently-running image */
- current_image = saved_current_image;
+ image_tag ( saved_current_image, &current_image );
/* Reset current working directory */
churi ( old_cwuri );
@@ -442,7 +465,7 @@ int image_exec ( struct image *image ) {
* registered until the currently-executing image returns.
*/
int image_replace ( struct image *replacement ) {
- struct image *image = current_image;
+ struct image *image = current_image.image;
int rc;
/* Sanity check */
@@ -478,38 +501,18 @@ int image_replace ( struct image *replacement ) {
* @ret rc Return status code
*/
int image_select ( struct image *image ) {
- struct image *tmp;
-
- /* Unselect all other images */
- for_each_image ( tmp )
- tmp->flags &= ~IMAGE_SELECTED;
/* Check that this image can be executed */
if ( ! ( image->type && image->type->exec ) )
return -ENOEXEC;
/* Mark image as selected */
- image->flags |= IMAGE_SELECTED;
+ image_tag ( image, &selected_image );
return 0;
}
/**
- * Find selected image
- *
- * @ret image Executable image, or NULL
- */
-struct image * image_find_selected ( void ) {
- struct image *image;
-
- for_each_image ( image ) {
- if ( image->flags & IMAGE_SELECTED )
- return image;
- }
- return NULL;
-}
-
-/**
* Change image trust requirement
*
* @v require_trusted Require trusted images
diff --git a/src/hci/commands/image_cmd.c b/src/hci/commands/image_cmd.c
index 4a7c500..bf97b4d 100644
--- a/src/hci/commands/image_cmd.c
+++ b/src/hci/commands/image_cmd.c
@@ -129,7 +129,7 @@ static int imgsingle_exec ( int argc, char **argv,
&image ) ) != 0 )
goto err_acquire;
} else {
- image = image_find_selected();
+ image = find_image_tag ( &selected_image );
if ( ! image ) {
printf ( "No image selected\n" );
goto err_acquire;
diff --git a/src/image/script.c b/src/image/script.c
index b34df1e..49b3564 100644
--- a/src/image/script.c
+++ b/src/image/script.c
@@ -311,6 +311,7 @@ static int terminate_on_label_found ( int rc ) {
* @ret rc Return status code
*/
static int goto_exec ( int argc, char **argv ) {
+ struct image *image = current_image.image;
struct goto_options opts;
size_t saved_offset;
int rc;
@@ -320,7 +321,7 @@ static int goto_exec ( int argc, char **argv ) {
return rc;
/* Sanity check */
- if ( ! current_image ) {
+ if ( ! image ) {
rc = -ENOTTY;
printf ( "Not in a script: %s\n", strerror ( rc ) );
return rc;
@@ -331,10 +332,10 @@ static int goto_exec ( int argc, char **argv ) {
/* Find label */
saved_offset = script_offset;
- if ( ( rc = process_script ( current_image, goto_find_label,
+ if ( ( rc = process_script ( image, goto_find_label,
terminate_on_label_found ) ) != 0 ) {
script_offset = saved_offset;
- DBGC ( current_image, "[%04zx] No such label :%s\n",
+ DBGC ( image, "[%04zx] No such label :%s\n",
script_offset, goto_label );
return rc;
}
diff --git a/src/include/ipxe/image.h b/src/include/ipxe/image.h
index e00af82..cd51188 100644
--- a/src/include/ipxe/image.h
+++ b/src/include/ipxe/image.h
@@ -61,19 +61,16 @@ struct image {
};
/** Image is registered */
-#define IMAGE_REGISTERED 0x00001
-
-/** Image is selected for execution */
-#define IMAGE_SELECTED 0x0002
+#define IMAGE_REGISTERED 0x0001
/** Image is trusted */
-#define IMAGE_TRUSTED 0x0004
+#define IMAGE_TRUSTED 0x0002
/** Image will be automatically unregistered after execution */
-#define IMAGE_AUTO_UNREGISTER 0x0008
+#define IMAGE_AUTO_UNREGISTER 0x0004
/** Image will be hidden from enumeration */
-#define IMAGE_HIDDEN 0x0010
+#define IMAGE_HIDDEN 0x0008
/** An executable image type */
struct image_type {
@@ -153,8 +150,23 @@ struct image_type {
/** An executable image type */
#define __image_type( probe_order ) __table_entry ( IMAGE_TYPES, probe_order )
+/** An image tag */
+struct image_tag {
+ /** Name */
+ const char *name;
+ /** Image (weak reference, nullified when image is freed) */
+ struct image *image;
+};
+
+/** Image tag table */
+#define IMAGE_TAGS __table ( struct image_tag, "image_tags" )
+
+/** An image tag */
+#define __image_tag __table_entry ( IMAGE_TAGS, 01 )
+
extern struct list_head images;
-extern struct image *current_image;
+extern struct image_tag current_image;
+extern struct image_tag selected_image;
/** Iterate over all registered images */
#define for_each_image( image ) \
@@ -181,11 +193,11 @@ extern int image_set_len ( struct image *image, size_t len );
extern int image_set_data ( struct image *image, userptr_t data, size_t len );
extern int register_image ( struct image *image );
extern void unregister_image ( struct image *image );
-struct image * find_image ( const char *name );
+extern struct image * find_image ( const char *name );
+extern struct image * find_image_tag ( struct image_tag *tag );
extern int image_exec ( struct image *image );
extern int image_replace ( struct image *replacement );
extern int image_select ( struct image *image );
-extern struct image * image_find_selected ( void );
extern int image_set_trust ( int require_trusted, int permanent );
extern struct image * image_memory ( const char *name, userptr_t data,
size_t len );
@@ -244,4 +256,19 @@ static inline void image_untrust ( struct image *image ) {
image->flags &= ~IMAGE_TRUSTED;
}
+/**
+ * Tag image
+ *
+ * @v image Image
+ * @v tag Image tag
+ * @ret prev Previous tagged image (if any)
+ */
+static inline struct image * image_tag ( struct image *image,
+ struct image_tag *tag ) {
+ struct image *prev = tag->image;
+
+ tag->image = image;
+ return prev;
+}
+
#endif /* _IPXE_IMAGE_H */
diff --git a/src/interface/efi/efi_file.c b/src/interface/efi/efi_file.c
index 266de4a..2ae3a0c 100644
--- a/src/interface/efi/efi_file.c
+++ b/src/interface/efi/efi_file.c
@@ -420,7 +420,7 @@ efi_file_open ( EFI_FILE_PROTOCOL *this, EFI_FILE_PROTOCOL **new,
if ( ( strncasecmp ( name, "grub", 4 ) == 0 ) &&
( ( sep = strrchr ( name, '.' ) ) != NULL ) &&
( strcasecmp ( sep, ".efi" ) == 0 ) &&
- ( ( image = image_find_selected() ) != NULL ) ) {
+ ( ( image = find_image_tag ( &selected_image ) ) != NULL ) ) {
return efi_file_open_image ( image, wname, new );
}
diff --git a/src/usr/imgmgmt.c b/src/usr/imgmgmt.c
index 94f3d2c..92bf236 100644
--- a/src/usr/imgmgmt.c
+++ b/src/usr/imgmgmt.c
@@ -156,13 +156,17 @@ int imgacquire ( const char *name_uri, unsigned long timeout,
* @v image Executable/loadable image
*/
void imgstat ( struct image *image ) {
+ struct image_tag *tag;
+
printf ( "%s : %zd bytes", image->name, image->len );
if ( image->type )
printf ( " [%s]", image->type->name );
+ for_each_table_entry ( tag, IMAGE_TAGS ) {
+ if ( tag->image == image )
+ printf ( " [%s]", tag->name );
+ }
if ( image->flags & IMAGE_TRUSTED )
printf ( " [TRUSTED]" );
- if ( image->flags & IMAGE_SELECTED )
- printf ( " [SELECTED]" );
if ( image->flags & IMAGE_AUTO_UNREGISTER )
printf ( " [AUTOFREE]" );
if ( image->flags & IMAGE_HIDDEN )