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
);
28 #include <gpxe/list.h>
29 #include <gpxe/umalloc.h>
31 #include <gpxe/image.h>
35 * Executable/loadable images
39 /** List of registered images */
40 struct list_head images
= LIST_HEAD_INIT ( images
);
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
);
55 DBGC ( image
, "IMAGE %p freed\n", image
);
59 * Allocate executable/loadable image
61 * @ret image Executable/loadable image
63 struct image
* alloc_image ( void ) {
66 image
= zalloc ( sizeof ( *image
) );
68 ref_init ( &image
->refcnt
, free_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
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
) );
98 * Set image command line
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
)
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",
127 /* Add to image list */
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
);
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
);
152 * @ret image Executable/loadable image, or NULL
154 struct image
* find_image ( const char *name
) {
157 list_for_each_entry ( image
, &images
, list
) {
158 if ( strcmp ( image
->name
, name
) == 0 )
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
) {
175 /* Check image is actually loadable */
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
) );
187 image
->flags
|= IMAGE_LOADED
;
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
;
214 /* If image already has a type, use it */
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
)
227 DBGC ( image
, "IMAGE %p format not recognised\n", image
);
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
;
242 /* Image must be loaded first */
243 if ( ! ( image
->flags
& IMAGE_LOADED
) ) {
244 DBGC ( image
, "IMAGE %p could not execute: not loaded\n",
249 assert ( image
->type
!= NULL
);
251 /* Check that image is actually executable */
252 if ( ! image
->type
->exec
)
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.
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 */
280 /* Reset current working directory */
282 uri_put ( old_cwuri
);
284 /* Tail-recurse into replacement image, if one exists */
286 DBGC ( image
, "IMAGE %p replacing self with IMAGE %p\n",
287 image
, replacement
);
288 if ( ( rc
= image_exec ( replacement
) ) != 0 )
296 * Register and autoload an image
299 * @ret rc Return status code
301 int register_and_autoload_image ( struct image
*image
) {
304 if ( ( rc
= register_image ( image
) ) != 0 )
307 if ( ( rc
= image_autoload ( image
) ) != 0 )
314 * Register and autoexec an image
317 * @ret rc Return status code
319 int register_and_autoexec_image ( struct image
*image
) {
322 if ( ( rc
= register_and_autoload_image ( image
) ) != 0 )
325 if ( ( rc
= image_exec ( image
) ) != 0 )