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., 51 Franklin Street, Fifth Floor, Boston, MA
20 FILE_LICENCE ( GPL2_OR_LATER );
30 #include <ipxe/list.h>
31 #include <ipxe/umalloc.h>
33 #include <ipxe/image.h>
41 /* Disambiguate the various error causes */
42 #define EACCES_UNTRUSTED \
43 __einfo_error ( EINFO_EACCES_UNTRUSTED )
44 #define EINFO_EACCES_UNTRUSTED \
45 __einfo_uniqify ( EINFO_EACCES, 0x01, "Untrusted image" )
46 #define EACCES_PERMANENT \
47 __einfo_error ( EINFO_EACCES_PERMANENT )
48 #define EINFO_EACCES_PERMANENT \
49 __einfo_uniqify ( EINFO_EACCES, 0x02, "Trust requirement is permanent" )
51 /** List of registered images */
52 struct list_head images = LIST_HEAD_INIT ( images );
54 /** Currently-executing image */
55 struct image *current_image;
57 /** Current image trust requirement */
58 static int require_trusted_images = 0;
60 /** Prevent changes to image trust requirement */
61 static int require_trusted_images_permanent = 0;
64 * Free executable image
66 * @v refcnt Reference counter
68 static void free_image ( struct refcnt *refcnt ) {
69 struct image *image = container_of ( refcnt, struct image, refcnt );
71 DBGC ( image, "IMAGE %s freed\n", image->name );
73 free ( image->cmdline );
74 uri_put ( image->uri );
75 ufree ( image->data );
76 image_put ( image->replacement );
81 * Allocate executable image
84 * @ret image Executable image
86 struct image * alloc_image ( struct uri *uri ) {
92 image = zalloc ( sizeof ( *image ) );
96 /* Initialise image */
97 ref_init ( &image->refcnt, free_image );
99 image->uri = uri_get ( uri );
101 name = basename ( ( char * ) uri->path );
102 if ( ( rc = image_set_name ( image, name ) ) != 0 )
119 * @v name New image name
120 * @ret rc Return status code
122 int image_set_name ( struct image *image, const char *name ) {
126 name_copy = strdup ( name );
130 /* Replace existing name */
131 free ( image->name );
132 image->name = name_copy;
138 * Set image command line
141 * @v cmdline New image command line, or NULL
142 * @ret rc Return status code
144 int image_set_cmdline ( struct image *image, const char *cmdline ) {
146 free ( image->cmdline );
147 image->cmdline = NULL;
149 image->cmdline = strdup ( cmdline );
150 if ( ! image->cmdline )
157 * Register executable image
159 * @v image Executable image
160 * @ret rc Return status code
162 int register_image ( struct image *image ) {
163 static unsigned int imgindex = 0;
164 char name[8]; /* "imgXXXX" */
167 /* Create image name if it doesn't already have one */
168 if ( ! image->name ) {
169 snprintf ( name, sizeof ( name ), "img%d", imgindex++ );
170 if ( ( rc = image_set_name ( image, name ) ) != 0 )
174 /* Avoid ending up with multiple "selected" images on
177 if ( image_find_selected() )
178 image->flags &= ~IMAGE_SELECTED;
180 /* Add to image list */
182 image->flags |= IMAGE_REGISTERED;
183 list_add_tail ( &image->list, &images );
184 DBGC ( image, "IMAGE %s at [%lx,%lx) registered\n",
185 image->name, user_to_phys ( image->data, 0 ),
186 user_to_phys ( image->data, image->len ) );
192 * Unregister executable image
194 * @v image Executable image
196 void unregister_image ( struct image *image ) {
198 /* Do nothing unless image is registered */
199 if ( ! ( image->flags & IMAGE_REGISTERED ) )
202 DBGC ( image, "IMAGE %s unregistered\n", image->name );
203 list_del ( &image->list );
204 image->flags &= ~IMAGE_REGISTERED;
212 * @ret image Executable image, or NULL
214 struct image * find_image ( const char *name ) {
217 list_for_each_entry ( image, &images, list ) {
218 if ( strcmp ( image->name, name ) == 0 )
226 * Determine image type
228 * @v image Executable image
229 * @ret rc Return status code
231 int image_probe ( struct image *image ) {
232 struct image_type *type;
235 /* Succeed if we already have a type */
239 /* Try each type in turn */
240 for_each_table_entry ( type, IMAGE_TYPES ) {
241 if ( ( rc = type->probe ( image ) ) == 0 ) {
243 DBGC ( image, "IMAGE %s is %s\n",
244 image->name, type->name );
247 DBGC ( image, "IMAGE %s is not %s: %s\n", image->name,
248 type->name, strerror ( rc ) );
251 DBGC ( image, "IMAGE %s format not recognised\n", image->name );
258 * @v image Executable image
259 * @ret rc Return status code
261 * The image must already be registered. Note that executing an image
262 * may cause it to unregister itself. The caller must therefore
263 * assume that the image pointer becomes invalid.
265 int image_exec ( struct image *image ) {
266 struct image *saved_current_image;
267 struct image *replacement = NULL;
268 struct uri *old_cwuri;
272 assert ( image->flags & IMAGE_REGISTERED );
274 /* Switch current working directory to be that of the image itself */
275 old_cwuri = uri_get ( cwuri );
276 churi ( image->uri );
278 /* Preserve record of any currently-running image */
279 saved_current_image = current_image;
281 /* Take out a temporary reference to the image. This allows
282 * the image to unregister itself if necessary, without
283 * automatically freeing itself.
285 current_image = image_get ( image );
287 /* Check that this image can be selected for execution */
288 if ( ( rc = image_select ( image ) ) != 0 )
291 /* Check that image is trusted (if applicable) */
292 if ( require_trusted_images && ! ( image->flags & IMAGE_TRUSTED ) ) {
293 DBGC ( image, "IMAGE %s is not trusted\n", image->name );
294 rc = -EACCES_UNTRUSTED;
298 /* Record boot attempt */
299 syslog ( LOG_NOTICE, "Executing \"%s\"\n", image->name );
301 /* Try executing the image */
302 if ( ( rc = image->type->exec ( image ) ) != 0 ) {
303 DBGC ( image, "IMAGE %s could not execute: %s\n",
304 image->name, strerror ( rc ) );
305 /* Do not return yet; we still have clean-up to do */
308 /* Record result of boot attempt */
310 syslog ( LOG_NOTICE, "Execution of \"%s\" completed\n",
313 syslog ( LOG_ERR, "Execution of \"%s\" failed: %s\n",
314 image->name, strerror ( rc ) );
317 /* Pick up replacement image before we drop the original
318 * image's temporary reference. The replacement image must
319 * already be registered, so we don't need to hold a temporary
320 * reference (which would complicate the tail-recursion).
322 replacement = image->replacement;
324 assert ( replacement->flags & IMAGE_REGISTERED );
327 /* Unregister image if applicable */
328 if ( image->flags & IMAGE_AUTO_UNREGISTER )
329 unregister_image ( image );
331 /* Debug message for tail-recursion. Placed here because the
332 * image_put() may end up freeing the image.
335 DBGC ( image, "IMAGE %s replacing self with IMAGE %s\n",
336 image->name, replacement->name );
339 /* Drop temporary reference to the original image */
342 /* Restore previous currently-running image */
343 current_image = saved_current_image;
345 /* Reset current working directory */
347 uri_put ( old_cwuri );
349 /* Tail-recurse into replacement image, if one exists */
351 return image_exec ( replacement );
357 * Set replacement image
359 * @v replacement Replacement image
360 * @ret rc Return status code
362 * The replacement image must already be registered, and must remain
363 * registered until the currently-executing image returns.
365 int image_replace ( struct image *replacement ) {
366 struct image *image = current_image;
370 assert ( replacement->flags & IMAGE_REGISTERED );
372 /* Fail unless there is a currently-executing image */
375 DBGC ( replacement, "IMAGE %s cannot replace non-existent "
376 "image: %s\n", replacement->name, strerror ( rc ) );
380 /* Check that the replacement image can be executed */
381 if ( ( rc = image_probe ( replacement ) ) != 0 )
384 /* Clear any existing replacement */
385 image_put ( image->replacement );
387 /* Set replacement */
388 image->replacement = image_get ( replacement );
389 DBGC ( image, "IMAGE %s will replace self with IMAGE %s\n",
390 image->name, replacement->name );
396 * Select image for execution
398 * @v image Executable image
399 * @ret rc Return status code
401 int image_select ( struct image *image ) {
405 /* Unselect all other images */
406 for_each_image ( tmp )
407 tmp->flags &= ~IMAGE_SELECTED;
409 /* Check that this image can be executed */
410 if ( ( rc = image_probe ( image ) ) != 0 )
412 if ( ! image->type->exec )
415 /* Mark image as selected */
416 image->flags |= IMAGE_SELECTED;
422 * Find selected image
424 * @ret image Executable image, or NULL
426 struct image * image_find_selected ( void ) {
429 for_each_image ( image ) {
430 if ( image->flags & IMAGE_SELECTED )
437 * Change image trust requirement
439 * @v require_trusted Require trusted images
440 * @v permanent Make trust requirement permanent
441 * @ret rc Return status code
443 int image_set_trust ( int require_trusted, int permanent ) {
445 /* Update trust requirement, if permitted to do so */
446 if ( ! require_trusted_images_permanent ) {
447 require_trusted_images = require_trusted;
448 require_trusted_images_permanent = permanent;
451 /* Fail if we attempted to change the trust requirement but
452 * were not permitted to do so.
454 if ( require_trusted_images != require_trusted )
455 return -EACCES_PERMANENT;
461 * Create pixel buffer from image
464 * @v pixbuf Pixel buffer to fill in
465 * @ret rc Return status code
467 int image_pixbuf ( struct image *image, struct pixel_buffer **pixbuf ) {
470 /* Check that this image can be used to create a pixel buffer */
471 if ( ( rc = image_probe ( image ) ) != 0 )
473 if ( ! image->type->pixbuf )
476 /* Try creating pixel buffer */
477 if ( ( rc = image->type->pixbuf ( image, pixbuf ) ) != 0 ) {
478 DBGC ( image, "IMAGE %s could not create pixel buffer: %s\n",
479 image->name, strerror ( rc ) );