[release] Update version to 1.0.0 for release
[gpxe.git] / src / core / image.c
blob24fe51ab9daf4566a66e90cdd67ece5f379ce5b1
1 /*
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.
19 FILE_LICENCE ( GPL2_OR_LATER );
21 #include <stddef.h>
22 #include <string.h>
23 #include <stdlib.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <assert.h>
27 #include <libgen.h>
28 #include <gpxe/list.h>
29 #include <gpxe/umalloc.h>
30 #include <gpxe/uri.h>
31 #include <gpxe/image.h>
33 /** @file
35 * Executable/loadable images
39 /** List of registered images */
40 struct list_head images = LIST_HEAD_INIT ( images );
42 /**
43 * Free executable/loadable image
45 * @v refcnt Reference counter
47 static void free_image ( struct refcnt *refcnt ) {
48 struct image *image = container_of ( refcnt, struct image, refcnt );
50 uri_put ( image->uri );
51 ufree ( image->data );
52 image_put ( image->replacement );
53 free ( image );
54 DBGC ( image, "IMAGE %p freed\n", image );
57 /**
58 * Allocate executable/loadable image
60 * @ret image Executable/loadable image
62 struct image * alloc_image ( void ) {
63 struct image *image;
65 image = zalloc ( sizeof ( *image ) );
66 if ( image ) {
67 image->refcnt.free = free_image;
69 return image;
72 /**
73 * Set image URI
75 * @v image Image
76 * @v URI New image URI
77 * @ret rc Return status code
79 * If no name is set, the name will be updated to the base name of the
80 * URI path (if any).
82 int image_set_uri ( struct image *image, struct uri *uri ) {
83 const char *path = uri->path;
85 /* Replace URI reference */
86 uri_put ( image->uri );
87 image->uri = uri_get ( uri );
89 /* Set name if none already specified */
90 if ( path && ( ! image->name[0] ) )
91 image_set_name ( image, basename ( ( char * ) path ) );
93 return 0;
96 /**
97 * Set image command line
99 * @v image Image
100 * @v cmdline New image command line
101 * @ret rc Return status code
103 int image_set_cmdline ( struct image *image, const char *cmdline ) {
104 free ( image->cmdline );
105 image->cmdline = strdup ( cmdline );
106 if ( ! image->cmdline )
107 return -ENOMEM;
108 return 0;
112 * Register executable/loadable image
114 * @v image Executable/loadable image
115 * @ret rc Return status code
117 int register_image ( struct image *image ) {
118 static unsigned int imgindex = 0;
120 /* Create image name if it doesn't already have one */
121 if ( ! image->name[0] ) {
122 snprintf ( image->name, sizeof ( image->name ), "img%d",
123 imgindex++ );
126 /* Add to image list */
127 image_get ( image );
128 list_add_tail ( &image->list, &images );
129 DBGC ( image, "IMAGE %p at [%lx,%lx) registered as %s\n",
130 image, user_to_phys ( image->data, 0 ),
131 user_to_phys ( image->data, image->len ), image->name );
133 return 0;
137 * Unregister executable/loadable image
139 * @v image Executable/loadable image
141 void unregister_image ( struct image *image ) {
142 DBGC ( image, "IMAGE %p unregistered\n", image );
143 list_del ( &image->list );
144 image_put ( image );
148 * Find image by name
150 * @v name Image name
151 * @ret image Executable/loadable image, or NULL
153 struct image * find_image ( const char *name ) {
154 struct image *image;
156 list_for_each_entry ( image, &images, list ) {
157 if ( strcmp ( image->name, name ) == 0 )
158 return image;
161 return NULL;
165 * Load executable/loadable image into memory
167 * @v image Executable/loadable image
168 * @v type Executable/loadable image type
169 * @ret rc Return status code
171 static int image_load_type ( struct image *image, struct image_type *type ) {
172 int rc;
174 /* Check image is actually loadable */
175 if ( ! type->load )
176 return -ENOEXEC;
178 /* Try the image loader */
179 if ( ( rc = type->load ( image ) ) != 0 ) {
180 DBGC ( image, "IMAGE %p could not load as %s: %s\n",
181 image, type->name, strerror ( rc ) );
182 return rc;
185 /* Flag as loaded */
186 image->flags |= IMAGE_LOADED;
187 return 0;
191 * Load executable/loadable image into memory
193 * @v image Executable/loadable image
194 * @ret rc Return status code
196 int image_load ( struct image *image ) {
198 assert ( image->type != NULL );
200 return image_load_type ( image, image->type );
204 * Autodetect image type and load executable/loadable image into memory
206 * @v image Executable/loadable image
207 * @ret rc Return status code
209 int image_autoload ( struct image *image ) {
210 struct image_type *type;
211 int rc;
213 /* If image already has a type, use it */
214 if ( image->type )
215 return image_load ( image );
217 /* Otherwise probe for a suitable type */
218 for_each_table_entry ( type, IMAGE_TYPES ) {
219 DBGC ( image, "IMAGE %p trying type %s\n", image, type->name );
220 rc = image_load_type ( image, type );
221 if ( image->type == NULL )
222 continue;
223 return rc;
226 DBGC ( image, "IMAGE %p format not recognised\n", image );
227 return -ENOEXEC;
231 * Execute loaded image
233 * @v image Loaded image
234 * @ret rc Return status code
236 int image_exec ( struct image *image ) {
237 struct image *replacement;
238 struct uri *old_cwuri;
239 int rc;
241 /* Image must be loaded first */
242 if ( ! ( image->flags & IMAGE_LOADED ) ) {
243 DBGC ( image, "IMAGE %p could not execute: not loaded\n",
244 image );
245 return -ENOTTY;
248 assert ( image->type != NULL );
250 /* Check that image is actually executable */
251 if ( ! image->type->exec )
252 return -ENOEXEC;
254 /* Switch current working directory to be that of the image itself */
255 old_cwuri = uri_get ( cwuri );
256 churi ( image->uri );
258 /* Take out a temporary reference to the image. This allows
259 * the image to unregister itself if necessary, without
260 * automatically freeing itself.
262 image_get ( image );
264 /* Try executing the image */
265 if ( ( rc = image->type->exec ( image ) ) != 0 ) {
266 DBGC ( image, "IMAGE %p could not execute: %s\n",
267 image, strerror ( rc ) );
268 /* Do not return yet; we still have clean-up to do */
271 /* Pick up replacement image before we drop the original
272 * image's temporary reference.
274 replacement = image->replacement;
276 /* Drop temporary reference to the original image */
277 image_put ( image );
279 /* Reset current working directory */
280 churi ( old_cwuri );
281 uri_put ( old_cwuri );
283 /* Tail-recurse into replacement image, if one exists */
284 if ( replacement ) {
285 DBGC ( image, "IMAGE %p replacing self with IMAGE %p\n",
286 image, replacement );
287 if ( ( rc = image_exec ( replacement ) ) != 0 )
288 return rc;
291 return rc;
295 * Register and autoload an image
297 * @v image Image
298 * @ret rc Return status code
300 int register_and_autoload_image ( struct image *image ) {
301 int rc;
303 if ( ( rc = register_image ( image ) ) != 0 )
304 return rc;
306 if ( ( rc = image_autoload ( image ) ) != 0 )
307 return rc;
309 return 0;
313 * Register and autoexec an image
315 * @v image Image
316 * @ret rc Return status code
318 int register_and_autoexec_image ( struct image *image ) {
319 int rc;
321 if ( ( rc = register_and_autoload_image ( image ) ) != 0 )
322 return rc;
324 if ( ( rc = image_exec ( image ) ) != 0 )
325 return rc;
327 return 0;