2 * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License as
6 * published by the Free Software Foundation; either version 2 of the
7 * License, or any later version.
9 * This program is distributed in the hope that it will be useful, but
10 * WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * General Public License for more details.
14 * You should have received a copy of the GNU General Public License
15 * along with this program; if not, write to the Free Software
16 * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
25 #include <gpxe/list.h>
26 #include <gpxe/umalloc.h>
27 #include <gpxe/image.h>
31 * Executable/loadable images
35 /** List of registered images */
36 struct list_head images = LIST_HEAD_INIT ( images );
38 /** List of image types */
39 static struct image_type image_types[0]
40 __table_start ( struct image_type, image_types );
41 static struct image_type image_types_end[0]
42 __table_end ( struct image_type, image_types );
45 * Free executable/loadable image
47 * @v refcnt Reference counter
49 static void free_image ( struct refcnt *refcnt ) {
50 struct image *image = container_of ( refcnt, struct image, refcnt );
52 ufree ( image->data );
54 DBGC ( image, "IMAGE %p freed\n", image );
58 * Allocate executable/loadable image
60 * @ret image Executable/loadable image
62 struct image * alloc_image ( void ) {
65 image = malloc ( sizeof ( *image ) );
67 memset ( image, 0, sizeof ( *image ) );
68 image->refcnt.free = free_image;
74 * Register executable/loadable image
76 * @v image Executable/loadable image
77 * @ret rc Return status code
79 int register_image ( struct image *image ) {
80 static unsigned int imgindex = 0;
82 /* Create image name if it doesn't already have one */
83 if ( ! image->name[0] ) {
84 snprintf ( image->name, sizeof ( image->name ), "img%d",
88 /* Add to image list */
90 list_add_tail ( &image->list, &images );
91 DBGC ( image, "IMAGE %p at [%lx,%lx) registered as %s\n",
92 image, user_to_phys ( image->data, 0 ),
93 user_to_phys ( image->data, image->len ), image->name );
99 * Unregister executable/loadable image
101 * @v image Executable/loadable image
103 void unregister_image ( struct image *image ) {
104 list_del ( &image->list );
106 DBGC ( image, "IMAGE %p unregistered\n", image );
110 * Move image to start of list of registered images
112 * @v image Executable/loadable image
114 * Move the image to the start of the image list. This makes it
115 * easier to keep track of which of the images marked as loaded is
116 * likely to still be valid.
118 void promote_image ( struct image *image ) {
119 list_del ( &image->list );
120 list_add ( &image->list, &images );
127 * @ret image Executable/loadable image, or NULL
129 struct image * find_image ( const char *name ) {
132 list_for_each_entry ( image, &images, list ) {
133 if ( strcmp ( image->name, name ) == 0 )
141 * Load executable/loadable image into memory
143 * @v image Executable/loadable image
144 * @v type Executable/loadable image type
145 * @ret rc Return status code
147 static int image_load_type ( struct image *image, struct image_type *type ) {
150 /* Check image is actually loadable */
154 /* Try the image loader */
155 if ( ( rc = type->load ( image ) ) != 0 ) {
156 DBGC ( image, "IMAGE %p could not load as %s: %s\n",
157 image, type->name, strerror ( rc ) );
162 image->flags |= IMAGE_LOADED;
167 * Load executable/loadable image into memory
169 * @v image Executable/loadable image
170 * @ret rc Return status code
172 int image_load ( struct image *image ) {
174 assert ( image->type != NULL );
176 return image_load_type ( image, image->type );
180 * Autodetect image type and load executable/loadable image into memory
182 * @v image Executable/loadable image
183 * @ret rc Return status code
185 int image_autoload ( struct image *image ) {
186 struct image_type *type;
189 /* If image already has a type, use it */
191 return image_load ( image );
193 /* Otherwise probe for a suitable type */
194 for ( type = image_types ; type < image_types_end ; type++ ) {
195 DBGC ( image, "IMAGE %p trying type %s\n", image, type->name );
196 rc = image_load_type ( image, type );
197 if ( image->type == NULL )
202 DBGC ( image, "IMAGE %p format not recognised\n", image );
207 * Execute loaded image
209 * @v image Loaded image
210 * @ret rc Return status code
212 int image_exec ( struct image *image ) {
215 /* Image must be loaded first */
216 if ( ! ( image->flags & IMAGE_LOADED ) ) {
217 DBGC ( image, "IMAGE %p could not execute: not loaded\n",
222 assert ( image->type != NULL );
224 /* Check that image is actually executable */
225 if ( ! image->type->exec )
228 /* Try executing the image */
229 if ( ( rc = image->type->exec ( image ) ) != 0 ) {
230 DBGC ( image, "IMAGE %p could not execute: %s\n",
231 image, strerror ( rc ) );
235 /* Well, some formats might return... */