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.
26 #include <gpxe/list.h>
27 #include <gpxe/umalloc.h>
29 #include <gpxe/image.h>
33 * Executable/loadable images
37 /** List of registered images */
38 struct list_head images
= LIST_HEAD_INIT ( images
);
40 /** List of image types */
41 static struct image_type image_types
[0]
42 __table_start ( struct image_type
, image_types
);
43 static struct image_type image_types_end
[0]
44 __table_end ( struct image_type
, image_types
);
47 * Free executable/loadable image
49 * @v refcnt Reference counter
51 static void free_image ( struct refcnt
*refcnt
) {
52 struct image
*image
= container_of ( refcnt
, struct image
, refcnt
);
54 uri_put ( image
->uri
);
55 ufree ( image
->data
);
56 image_put ( image
->replacement
);
58 DBGC ( image
, "IMAGE %p freed\n", image
);
62 * Allocate executable/loadable image
64 * @ret image Executable/loadable image
66 struct image
* alloc_image ( void ) {
69 image
= zalloc ( sizeof ( *image
) );
71 image
->refcnt
.free
= free_image
;
80 * @v URI New image URI
81 * @ret rc Return status code
83 * If no name is set, the name will be updated to the base name of the
86 int image_set_uri ( struct image
*image
, struct uri
*uri
) {
87 const char *path
= uri
->path
;
89 /* Replace URI reference */
90 uri_put ( image
->uri
);
91 image
->uri
= uri_get ( uri
);
93 /* Set name if none already specified */
94 if ( path
&& ( ! image
->name
[0] ) )
95 image_set_name ( image
, basename ( ( char * ) path
) );
101 * Set image command line
104 * @v cmdline New image command line
105 * @ret rc Return status code
107 int image_set_cmdline ( struct image
*image
, const char *cmdline
) {
108 free ( image
->cmdline
);
109 image
->cmdline
= strdup ( cmdline
);
110 if ( ! image
->cmdline
)
116 * Register executable/loadable image
118 * @v image Executable/loadable image
119 * @ret rc Return status code
121 int register_image ( struct image
*image
) {
122 static unsigned int imgindex
= 0;
124 /* Create image name if it doesn't already have one */
125 if ( ! image
->name
[0] ) {
126 snprintf ( image
->name
, sizeof ( image
->name
), "img%d",
130 /* Add to image list */
132 list_add_tail ( &image
->list
, &images
);
133 DBGC ( image
, "IMAGE %p at [%lx,%lx) registered as %s\n",
134 image
, user_to_phys ( image
->data
, 0 ),
135 user_to_phys ( image
->data
, image
->len
), image
->name
);
141 * Unregister executable/loadable image
143 * @v image Executable/loadable image
145 void unregister_image ( struct image
*image
) {
146 DBGC ( image
, "IMAGE %p unregistered\n", image
);
147 list_del ( &image
->list
);
155 * @ret image Executable/loadable image, or NULL
157 struct image
* find_image ( const char *name
) {
160 list_for_each_entry ( image
, &images
, list
) {
161 if ( strcmp ( image
->name
, name
) == 0 )
169 * Load executable/loadable image into memory
171 * @v image Executable/loadable image
172 * @v type Executable/loadable image type
173 * @ret rc Return status code
175 static int image_load_type ( struct image
*image
, struct image_type
*type
) {
178 /* Check image is actually loadable */
182 /* Try the image loader */
183 if ( ( rc
= type
->load ( image
) ) != 0 ) {
184 DBGC ( image
, "IMAGE %p could not load as %s: %s\n",
185 image
, type
->name
, strerror ( rc
) );
190 image
->flags
|= IMAGE_LOADED
;
195 * Load executable/loadable image into memory
197 * @v image Executable/loadable image
198 * @ret rc Return status code
200 int image_load ( struct image
*image
) {
202 assert ( image
->type
!= NULL
);
204 return image_load_type ( image
, image
->type
);
208 * Autodetect image type and load executable/loadable image into memory
210 * @v image Executable/loadable image
211 * @ret rc Return status code
213 int image_autoload ( struct image
*image
) {
214 struct image_type
*type
;
217 /* If image already has a type, use it */
219 return image_load ( image
);
221 /* Otherwise probe for a suitable type */
222 for ( type
= image_types
; type
< image_types_end
; type
++ ) {
223 DBGC ( image
, "IMAGE %p trying type %s\n", image
, type
->name
);
224 rc
= image_load_type ( image
, type
);
225 if ( image
->type
== NULL
)
230 DBGC ( image
, "IMAGE %p format not recognised\n", image
);
235 * Execute loaded image
237 * @v image Loaded image
238 * @ret rc Return status code
240 int image_exec ( struct image
*image
) {
241 struct image
*replacement
;
242 struct uri
*old_cwuri
;
245 /* Image must be loaded first */
246 if ( ! ( image
->flags
& IMAGE_LOADED
) ) {
247 DBGC ( image
, "IMAGE %p could not execute: not loaded\n",
252 assert ( image
->type
!= NULL
);
254 /* Check that image is actually executable */
255 if ( ! image
->type
->exec
)
258 /* Switch current working directory to be that of the image itself */
259 old_cwuri
= uri_get ( cwuri
);
260 churi ( image
->uri
);
262 /* Take out a temporary reference to the image. This allows
263 * the image to unregister itself if necessary, without
264 * automatically freeing itself.
268 /* Try executing the image */
269 if ( ( rc
= image
->type
->exec ( image
) ) != 0 ) {
270 DBGC ( image
, "IMAGE %p could not execute: %s\n",
271 image
, strerror ( rc
) );
272 /* Do not return yet; we still have clean-up to do */
275 /* Pick up replacement image before we drop the original
276 * image's temporary reference.
278 replacement
= image
->replacement
;
280 /* Drop temporary reference to the original image */
283 /* Reset current working directory */
285 uri_put ( old_cwuri
);
287 /* Tail-recurse into replacement image, if one exists */
289 DBGC ( image
, "IMAGE %p replacing self with IMAGE %p\n",
290 image
, replacement
);
291 if ( ( rc
= image_exec ( replacement
) ) != 0 )
299 * Register and autoload an image
302 * @ret rc Return status code
304 int register_and_autoload_image ( struct image
*image
) {
307 if ( ( rc
= register_image ( image
) ) != 0 )
310 if ( ( rc
= image_autoload ( image
) ) != 0 )
317 * Register and autoexec an image
320 * @ret rc Return status code
322 int register_and_autoexec_image ( struct image
*image
) {
325 if ( ( rc
= register_and_autoload_image ( image
) ) != 0 )
328 if ( ( rc
= image_exec ( image
) ) != 0 )