diff options
author | Michael Brown | 2007-01-12 00:43:29 +0100 |
---|---|---|
committer | Michael Brown | 2007-01-12 00:43:29 +0100 |
commit | f59ad50504ae8b12f32f528f1d39a7b638b75501 (patch) | |
tree | b69a1755ac5fdbdd765ba1bc8a899e97c4cdd865 /src/core/image.c | |
parent | alloca() can be useful in some (limited) circumstances. (diff) | |
download | ipxe-f59ad50504ae8b12f32f528f1d39a7b638b75501.tar.gz ipxe-f59ad50504ae8b12f32f528f1d39a7b638b75501.tar.xz ipxe-f59ad50504ae8b12f32f528f1d39a7b638b75501.zip |
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.
Diffstat (limited to 'src/core/image.c')
-rw-r--r-- | src/core/image.c | 177 |
1 files changed, 115 insertions, 62 deletions
diff --git a/src/core/image.c b/src/core/image.c index 80d3d5c5..bfa91df3 100644 --- a/src/core/image.c +++ b/src/core/image.c @@ -1,85 +1,138 @@ -#include "dev.h" -#include <gpxe/buffer.h> -#include <console.h> +/* + * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License as + * published by the Free Software Foundation; either version 2 of the + * License, or any later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + */ + +#include <stddef.h> +#include <string.h> +#include <stdlib.h> +#include <errno.h> +#include <assert.h> +#include <vsprintf.h> +#include <gpxe/list.h> +#include <gpxe/image.h> + +/** @file + * + * Executable/loadable images + * + */ -#if 0 +/** List of registered images */ +struct list_head images = LIST_HEAD_INIT ( images ); -static struct image images[0] __image_start; -static struct image images_end[0] __image_end; +/** List of image types */ +static struct image_type image_types[0] + __table_start ( struct image_type, image_types ); +static struct image_type image_types_end[0] + __table_end ( struct image_type, image_types ); -/* - * Print all images +/** + * Register executable/loadable image * + * @v image Executable/loadable image + * @ret rc Return status code */ -void print_images ( void ) { - struct image *image; +int register_image ( struct image *image ) { + static unsigned int imgindex = 0; - for ( image = images ; image < images_end ; image++ ) { - printf ( "%s ", image->name ); - } + /* Create image name */ + snprintf ( image->name, sizeof ( image->name ), "img%d", + imgindex++ ); + + /* Add to image list */ + list_add_tail ( &image->list, &images ); + DBGC ( image, "IMAGE %p registered as %s\n", image, image->name ); + + return 0; } -/* - * Identify the image format +/** + * Unregister executable/loadable image * + * @v image Executable/loadable image */ -static struct image * identify_image ( physaddr_t start, physaddr_t len, - void **context ) { - struct image *image; - - for ( image = images ; image < images_end ; image++ ) { - if ( image->probe ( start, len, context ) ) - return image; - } - - return NULL; +void unregister_image ( struct image *image ) { + list_del ( &image->list ); + DBGC ( image, "IMAGE %p unregistered\n", image ); } -/* - * Load an image into memory at a location determined by the image - * format +/** + * Load executable/loadable image into memory * + * @v image Executable/loadable image + * @ret rc Return status code */ -int autoload ( struct dev *dev, struct image **image, void **context ) { - struct buffer buffer; - int rc = 0; - - /* Prepare the load buffer */ - if ( ! init_load_buffer ( &buffer ) ) { - DBG ( "IMAGE could not initialise load buffer\n" ); - goto out; - } +int image_load ( struct image *image ) { + int rc; - /* Load the image into the load buffer */ - if ( ! load ( dev, &buffer ) ) { - DBG ( "IMAGE could not load image\n" ); - goto out_free; + assert ( image->type != NULL ); + + if ( ( rc = image->type->load ( image ) ) != 0 ) { + DBGC ( image, "IMAGE %p could not load: %s\n", + image, strerror ( rc ) ); + return rc; } - /* Shrink the load buffer */ - trim_load_buffer ( &buffer ); + return 0; +} - /* Identify the image type */ - *image = identify_image ( buffer.start, buffer.fill, context ); - if ( ! *image ) { - DBG ( "IMAGE could not identify image type\n" ); - goto out_free; - } +/** + * Autodetect image type and load executable/loadable image into memory + * + * @v image Executable/loadable image + * @ret rc Return status code + */ +int image_autoload ( struct image *image ) { + struct image_type *type; + int rc; - /* Move the image into the target location */ - if ( ! (*image)->load ( buffer.start, buffer.fill, *context ) ) { - DBG ( "IMAGE could not move to target location\n" ); - goto out_free; + for ( type = image_types ; type < image_types_end ; type++ ) { + rc = type->load ( image ); + if ( image->type == NULL ) + continue; + if ( rc != 0 ) { + DBGC ( image, "IMAGE %p (%s) could not load: %s\n", + image, image->type->name, strerror ( rc ) ); + return rc; + } + return 0; } - /* Return success */ - rc = 1; - - out_free: - /* Free the load buffer */ - done_load_buffer ( &buffer ); - out: - return rc; + DBGC ( image, "IMAGE %p format not recognised\n", image ); + return -ENOEXEC; } -#endif +/** + * Execute loaded image + * + * @v image Loaded image + * @ret rc Return status code + */ +int image_exec ( struct image *image ) { + int rc; + + assert ( image->type != NULL ); + + if ( ( rc = image->type->exec ( image ) ) != 0 ) { + DBGC ( image, "IMAGE %p could not execute: %s\n", + image, strerror ( rc ) ); + return rc; + } + + /* Well, some formats might return... */ + return 0; +} |