[contrib] Allow Network Protocol header to display in rom-o-matic
[gpxe.git] / src / core / image.c
blobd7fed72cee256cfc45ba097844a7ae63801e4cbc
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 free ( image->cmdline );
51 uri_put ( image->uri );
52 ufree ( image->data );
53 image_put ( image->replacement );
54 free ( image );
55 DBGC ( image, "IMAGE %p freed\n", image );
58 /**
59 * Allocate executable/loadable image
61 * @ret image Executable/loadable image
63 struct image * alloc_image ( void ) {
64 struct image *image;
66 image = zalloc ( sizeof ( *image ) );
67 if ( image ) {
68 ref_init ( &image->refcnt, free_image );
70 return image;
73 /**
74 * Set image URI
76 * @v image Image
77 * @v URI New image URI
78 * @ret rc Return status code
80 * If no name is set, the name will be updated to the base name of the
81 * URI path (if any).
83 int image_set_uri ( struct image *image, struct uri *uri ) {
84 const char *path = uri->path;
86 /* Replace URI reference */
87 uri_put ( image->uri );
88 image->uri = uri_get ( uri );
90 /* Set name if none already specified */
91 if ( path && ( ! image->name[0] ) )
92 image_set_name ( image, basename ( ( char * ) path ) );
94 return 0;
97 /**
98 * Set image command line
100 * @v image Image
101 * @v cmdline New image command line
102 * @ret rc Return status code
104 int image_set_cmdline ( struct image *image, const char *cmdline ) {
105 free ( image->cmdline );
106 image->cmdline = strdup ( cmdline );
107 if ( ! image->cmdline )
108 return -ENOMEM;
109 return 0;
113 * Register executable/loadable image
115 * @v image Executable/loadable image
116 * @ret rc Return status code
118 int register_image ( struct image *image ) {
119 static unsigned int imgindex = 0;
121 /* Create image name if it doesn't already have one */
122 if ( ! image->name[0] ) {
123 snprintf ( image->name, sizeof ( image->name ), "img%d",
124 imgindex++ );
127 /* Add to image list */
128 image_get ( image );
129 list_add_tail ( &image->list, &images );
130 DBGC ( image, "IMAGE %p at [%lx,%lx) registered as %s\n",
131 image, user_to_phys ( image->data, 0 ),
132 user_to_phys ( image->data, image->len ), image->name );
134 return 0;
138 * Unregister executable/loadable image
140 * @v image Executable/loadable image
142 void unregister_image ( struct image *image ) {
143 DBGC ( image, "IMAGE %p unregistered\n", image );
144 list_del ( &image->list );
145 image_put ( image );
149 * Find image by name
151 * @v name Image name
152 * @ret image Executable/loadable image, or NULL
154 struct image * find_image ( const char *name ) {
155 struct image *image;
157 list_for_each_entry ( image, &images, list ) {
158 if ( strcmp ( image->name, name ) == 0 )
159 return image;
162 return NULL;
166 * Load executable/loadable image into memory
168 * @v image Executable/loadable image
169 * @v type Executable/loadable image type
170 * @ret rc Return status code
172 static int image_load_type ( struct image *image, struct image_type *type ) {
173 int rc;
175 /* Check image is actually loadable */
176 if ( ! type->load )
177 return -ENOEXEC;
179 /* Try the image loader */
180 if ( ( rc = type->load ( image ) ) != 0 ) {
181 DBGC ( image, "IMAGE %p could not load as %s: %s\n",
182 image, type->name, strerror ( rc ) );
183 return rc;
186 /* Flag as loaded */
187 image->flags |= IMAGE_LOADED;
188 return 0;
192 * Load executable/loadable image into memory
194 * @v image Executable/loadable image
195 * @ret rc Return status code
197 int image_load ( struct image *image ) {
199 assert ( image->type != NULL );
201 return image_load_type ( image, image->type );
205 * Autodetect image type and load executable/loadable image into memory
207 * @v image Executable/loadable image
208 * @ret rc Return status code
210 int image_autoload ( struct image *image ) {
211 struct image_type *type;
212 int rc;
214 /* If image already has a type, use it */
215 if ( image->type )
216 return image_load ( image );
218 /* Otherwise probe for a suitable type */
219 for_each_table_entry ( type, IMAGE_TYPES ) {
220 DBGC ( image, "IMAGE %p trying type %s\n", image, type->name );
221 rc = image_load_type ( image, type );
222 if ( image->type == NULL )
223 continue;
224 return rc;
227 DBGC ( image, "IMAGE %p format not recognised\n", image );
228 return -ENOEXEC;
232 * Execute loaded image
234 * @v image Loaded image
235 * @ret rc Return status code
237 int image_exec ( struct image *image ) {
238 struct image *replacement;
239 struct uri *old_cwuri;
240 int rc;
242 /* Image must be loaded first */
243 if ( ! ( image->flags & IMAGE_LOADED ) ) {
244 DBGC ( image, "IMAGE %p could not execute: not loaded\n",
245 image );
246 return -ENOTTY;
249 assert ( image->type != NULL );
251 /* Check that image is actually executable */
252 if ( ! image->type->exec )
253 return -ENOEXEC;
255 /* Switch current working directory to be that of the image itself */
256 old_cwuri = uri_get ( cwuri );
257 churi ( image->uri );
259 /* Take out a temporary reference to the image. This allows
260 * the image to unregister itself if necessary, without
261 * automatically freeing itself.
263 image_get ( image );
265 /* Try executing the image */
266 if ( ( rc = image->type->exec ( image ) ) != 0 ) {
267 DBGC ( image, "IMAGE %p could not execute: %s\n",
268 image, strerror ( rc ) );
269 /* Do not return yet; we still have clean-up to do */
272 /* Pick up replacement image before we drop the original
273 * image's temporary reference.
275 replacement = image->replacement;
277 /* Drop temporary reference to the original image */
278 image_put ( image );
280 /* Reset current working directory */
281 churi ( old_cwuri );
282 uri_put ( old_cwuri );
284 /* Tail-recurse into replacement image, if one exists */
285 if ( replacement ) {
286 DBGC ( image, "IMAGE %p replacing self with IMAGE %p\n",
287 image, replacement );
288 if ( ( rc = image_exec ( replacement ) ) != 0 )
289 return rc;
292 return rc;
296 * Register and autoload an image
298 * @v image Image
299 * @ret rc Return status code
301 int register_and_autoload_image ( struct image *image ) {
302 int rc;
304 if ( ( rc = register_image ( image ) ) != 0 )
305 return rc;
307 if ( ( rc = image_autoload ( image ) ) != 0 )
308 return rc;
310 return 0;
314 * Register and autoexec an image
316 * @v image Image
317 * @ret rc Return status code
319 int register_and_autoexec_image ( struct image *image ) {
320 int rc;
322 if ( ( rc = register_and_autoload_image ( image ) ) != 0 )
323 return rc;
325 if ( ( rc = image_exec ( image ) ) != 0 )
326 return rc;
328 return 0;