diff options
Diffstat (limited to 'gpxe/src/core/image.c')
-rw-r--r-- | gpxe/src/core/image.c | 328 |
1 files changed, 0 insertions, 328 deletions
diff --git a/gpxe/src/core/image.c b/gpxe/src/core/image.c deleted file mode 100644 index 24fe51ab..00000000 --- a/gpxe/src/core/image.c +++ /dev/null @@ -1,328 +0,0 @@ -/* - * 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. - */ - -FILE_LICENCE ( GPL2_OR_LATER ); - -#include <stddef.h> -#include <string.h> -#include <stdlib.h> -#include <stdio.h> -#include <errno.h> -#include <assert.h> -#include <libgen.h> -#include <gpxe/list.h> -#include <gpxe/umalloc.h> -#include <gpxe/uri.h> -#include <gpxe/image.h> - -/** @file - * - * Executable/loadable images - * - */ - -/** List of registered images */ -struct list_head images = LIST_HEAD_INIT ( images ); - -/** - * Free executable/loadable image - * - * @v refcnt Reference counter - */ -static void free_image ( struct refcnt *refcnt ) { - struct image *image = container_of ( refcnt, struct image, refcnt ); - - uri_put ( image->uri ); - ufree ( image->data ); - image_put ( image->replacement ); - free ( image ); - DBGC ( image, "IMAGE %p freed\n", image ); -} - -/** - * Allocate executable/loadable image - * - * @ret image Executable/loadable image - */ -struct image * alloc_image ( void ) { - struct image *image; - - image = zalloc ( sizeof ( *image ) ); - if ( image ) { - image->refcnt.free = free_image; - } - return image; -} - -/** - * Set image URI - * - * @v image Image - * @v URI New image URI - * @ret rc Return status code - * - * If no name is set, the name will be updated to the base name of the - * URI path (if any). - */ -int image_set_uri ( struct image *image, struct uri *uri ) { - const char *path = uri->path; - - /* Replace URI reference */ - uri_put ( image->uri ); - image->uri = uri_get ( uri ); - - /* Set name if none already specified */ - if ( path && ( ! image->name[0] ) ) - image_set_name ( image, basename ( ( char * ) path ) ); - - return 0; -} - -/** - * Set image command line - * - * @v image Image - * @v cmdline New image command line - * @ret rc Return status code - */ -int image_set_cmdline ( struct image *image, const char *cmdline ) { - free ( image->cmdline ); - image->cmdline = strdup ( cmdline ); - if ( ! image->cmdline ) - return -ENOMEM; - return 0; -} - -/** - * Register executable/loadable image - * - * @v image Executable/loadable image - * @ret rc Return status code - */ -int register_image ( struct image *image ) { - static unsigned int imgindex = 0; - - /* Create image name if it doesn't already have one */ - if ( ! image->name[0] ) { - snprintf ( image->name, sizeof ( image->name ), "img%d", - imgindex++ ); - } - - /* Add to image list */ - image_get ( image ); - list_add_tail ( &image->list, &images ); - DBGC ( image, "IMAGE %p at [%lx,%lx) registered as %s\n", - image, user_to_phys ( image->data, 0 ), - user_to_phys ( image->data, image->len ), image->name ); - - return 0; -} - -/** - * Unregister executable/loadable image - * - * @v image Executable/loadable image - */ -void unregister_image ( struct image *image ) { - DBGC ( image, "IMAGE %p unregistered\n", image ); - list_del ( &image->list ); - image_put ( image ); -} - -/** - * Find image by name - * - * @v name Image name - * @ret image Executable/loadable image, or NULL - */ -struct image * find_image ( const char *name ) { - struct image *image; - - list_for_each_entry ( image, &images, list ) { - if ( strcmp ( image->name, name ) == 0 ) - return image; - } - - return NULL; -} - -/** - * Load executable/loadable image into memory - * - * @v image Executable/loadable image - * @v type Executable/loadable image type - * @ret rc Return status code - */ -static int image_load_type ( struct image *image, struct image_type *type ) { - int rc; - - /* Check image is actually loadable */ - if ( ! type->load ) - return -ENOEXEC; - - /* Try the image loader */ - if ( ( rc = type->load ( image ) ) != 0 ) { - DBGC ( image, "IMAGE %p could not load as %s: %s\n", - image, type->name, strerror ( rc ) ); - return rc; - } - - /* Flag as loaded */ - image->flags |= IMAGE_LOADED; - return 0; -} - -/** - * Load executable/loadable image into memory - * - * @v image Executable/loadable image - * @ret rc Return status code - */ -int image_load ( struct image *image ) { - - assert ( image->type != NULL ); - - return image_load_type ( image, image->type ); -} - -/** - * 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; - - /* If image already has a type, use it */ - if ( image->type ) - return image_load ( image ); - - /* Otherwise probe for a suitable type */ - for_each_table_entry ( type, IMAGE_TYPES ) { - DBGC ( image, "IMAGE %p trying type %s\n", image, type->name ); - rc = image_load_type ( image, type ); - if ( image->type == NULL ) - continue; - return rc; - } - - DBGC ( image, "IMAGE %p format not recognised\n", image ); - return -ENOEXEC; -} - -/** - * Execute loaded image - * - * @v image Loaded image - * @ret rc Return status code - */ -int image_exec ( struct image *image ) { - struct image *replacement; - struct uri *old_cwuri; - int rc; - - /* Image must be loaded first */ - if ( ! ( image->flags & IMAGE_LOADED ) ) { - DBGC ( image, "IMAGE %p could not execute: not loaded\n", - image ); - return -ENOTTY; - } - - assert ( image->type != NULL ); - - /* Check that image is actually executable */ - if ( ! image->type->exec ) - return -ENOEXEC; - - /* Switch current working directory to be that of the image itself */ - old_cwuri = uri_get ( cwuri ); - churi ( image->uri ); - - /* Take out a temporary reference to the image. This allows - * the image to unregister itself if necessary, without - * automatically freeing itself. - */ - image_get ( image ); - - /* Try executing the image */ - if ( ( rc = image->type->exec ( image ) ) != 0 ) { - DBGC ( image, "IMAGE %p could not execute: %s\n", - image, strerror ( rc ) ); - /* Do not return yet; we still have clean-up to do */ - } - - /* Pick up replacement image before we drop the original - * image's temporary reference. - */ - replacement = image->replacement; - - /* Drop temporary reference to the original image */ - image_put ( image ); - - /* Reset current working directory */ - churi ( old_cwuri ); - uri_put ( old_cwuri ); - - /* Tail-recurse into replacement image, if one exists */ - if ( replacement ) { - DBGC ( image, "IMAGE %p replacing self with IMAGE %p\n", - image, replacement ); - if ( ( rc = image_exec ( replacement ) ) != 0 ) - return rc; - } - - return rc; -} - -/** - * Register and autoload an image - * - * @v image Image - * @ret rc Return status code - */ -int register_and_autoload_image ( struct image *image ) { - int rc; - - if ( ( rc = register_image ( image ) ) != 0 ) - return rc; - - if ( ( rc = image_autoload ( image ) ) != 0 ) - return rc; - - return 0; -} - -/** - * Register and autoexec an image - * - * @v image Image - * @ret rc Return status code - */ -int register_and_autoexec_image ( struct image *image ) { - int rc; - - if ( ( rc = register_and_autoload_image ( image ) ) != 0 ) - return rc; - - if ( ( rc = image_exec ( image ) ) != 0 ) - return rc; - - return 0; -} |