summaryrefslogtreecommitdiffstats
path: root/src/core/image.c
diff options
context:
space:
mode:
authorMichael Brown2011-03-09 17:55:51 +0100
committerMichael Brown2011-03-09 17:57:34 +0100
commit9fa4ac2e9a781861e36e618eb1d461d8dc53a27c (patch)
tree437a36ae53aa9361f33c3c435c7b0978a9de42f5 /src/core/image.c
parent[image] Generalise "currently-running script" to "currently-running image" (diff)
downloadipxe-9fa4ac2e9a781861e36e618eb1d461d8dc53a27c.tar.gz
ipxe-9fa4ac2e9a781861e36e618eb1d461d8dc53a27c.tar.xz
ipxe-9fa4ac2e9a781861e36e618eb1d461d8dc53a27c.zip
[image] Simplify use of imgdownload()
Allow imgdownload() to be called without first having to allocate (and so keep track of) an image. Signed-off-by: Michael Brown <mcb30@ipxe.org>
Diffstat (limited to 'src/core/image.c')
-rw-r--r--src/core/image.c51
1 files changed, 50 insertions, 1 deletions
diff --git a/src/core/image.c b/src/core/image.c
index d205768a..01091f1b 100644
--- a/src/core/image.c
+++ b/src/core/image.c
@@ -130,6 +130,7 @@ int register_image ( struct image *image ) {
/* Add to image list */
image_get ( image );
+ image->flags |= IMAGE_REGISTERED;
list_add_tail ( &image->list, &images );
DBGC ( image, "IMAGE %s at [%lx,%lx) registered\n",
image->name, user_to_phys ( image->data, 0 ),
@@ -144,8 +145,10 @@ int register_image ( struct image *image ) {
* @v image Executable image
*/
void unregister_image ( struct image *image ) {
+
DBGC ( image, "IMAGE %s unregistered\n", image->name );
list_del ( &image->list );
+ image->flags &= ~IMAGE_REGISTERED;
image_put ( image );
}
@@ -201,6 +204,10 @@ int image_probe ( struct image *image ) {
*
* @v image Executable image
* @ret rc Return status code
+ *
+ * The image must already be registered. Note that executing an image
+ * may cause it to unregister itself. The caller must therefore
+ * assume that the image pointer becomes invalid.
*/
int image_exec ( struct image *image ) {
struct image *saved_current_image;
@@ -208,6 +215,9 @@ int image_exec ( struct image *image ) {
struct uri *old_cwuri;
int rc;
+ /* Sanity check */
+ assert ( image->flags & IMAGE_REGISTERED );
+
/* Check that this image can be executed */
if ( ( rc = image_probe ( image ) ) != 0 )
return rc;
@@ -233,9 +243,13 @@ int image_exec ( struct image *image ) {
}
/* Pick up replacement image before we drop the original
- * image's temporary reference.
+ * image's temporary reference. The replacement image must
+ * already be registered, so we don't need to hold a temporary
+ * reference (which would complicate the tail-recursion).
*/
replacement = image->replacement;
+ if ( replacement )
+ assert ( replacement->flags & IMAGE_REGISTERED );
/* Drop temporary reference to the original image */
image_put ( image );
@@ -259,6 +273,41 @@ int image_exec ( struct image *image ) {
}
/**
+ * Set replacement image
+ *
+ * @v replacement Replacement image
+ * @ret rc Return status code
+ *
+ * The replacement image must already be registered, and must remain
+ * registered until the currently-executing image returns.
+ */
+int image_replace ( struct image *replacement ) {
+ struct image *image = current_image;
+ int rc;
+
+ /* Sanity check */
+ assert ( replacement->flags & IMAGE_REGISTERED );
+
+ /* Fail unless there is a currently-executing image */
+ if ( ! image ) {
+ rc = -ENOTTY;
+ DBGC ( replacement, "IMAGE %s cannot replace non-existent "
+ "image: %s\n", replacement->name, strerror ( rc ) );
+ return rc;
+ }
+
+ /* Clear any existing replacement */
+ image_put ( image->replacement );
+
+ /* Set replacement */
+ image->replacement = image_get ( replacement );
+ DBGC ( image, "IMAGE %s will replace self with IMAGE %s\n",
+ image->name, replacement->name );
+
+ return 0;
+}
+
+/**
* Select image for execution
*
* @v image Executable image