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 uri_put ( image
->uri
);
51 ufree ( image
->data
);
52 image_put ( image
->replacement
);
54 DBGC ( image
, "IMAGE %p freed\n", image
);
58 * Allocate executable/loadable image
60 * @ret image Executable/loadable image
62 struct image
* alloc_image ( void ) {
65 image
= zalloc ( sizeof ( *image
) );
67 image
->refcnt
.free
= free_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
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
) );
97 * Set image command line
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
)
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",
126 /* Add to image list */
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
);
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
);
151 * @ret image Executable/loadable image, or NULL
153 struct image
* find_image ( const char *name
) {
156 list_for_each_entry ( image
, &images
, list
) {
157 if ( strcmp ( image
->name
, name
) == 0 )
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
) {
174 /* Check image is actually loadable */
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
) );
186 image
->flags
|= IMAGE_LOADED
;
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
;
213 /* If image already has a type, use it */
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
)
226 DBGC ( image
, "IMAGE %p format not recognised\n", image
);
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
;
241 /* Image must be loaded first */
242 if ( ! ( image
->flags
& IMAGE_LOADED
) ) {
243 DBGC ( image
, "IMAGE %p could not execute: not loaded\n",
248 assert ( image
->type
!= NULL
);
250 /* Check that image is actually executable */
251 if ( ! image
->type
->exec
)
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.
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 */
279 /* Reset current working directory */
281 uri_put ( old_cwuri
);
283 /* Tail-recurse into replacement image, if one exists */
285 DBGC ( image
, "IMAGE %p replacing self with IMAGE %p\n",
286 image
, replacement
);
287 if ( ( rc
= image_exec ( replacement
) ) != 0 )
295 * Register and autoload an image
298 * @ret rc Return status code
300 int register_and_autoload_image ( struct image
*image
) {
303 if ( ( rc
= register_image ( image
) ) != 0 )
306 if ( ( rc
= image_autoload ( image
) ) != 0 )
313 * Register and autoexec an image
316 * @ret rc Return status code
318 int register_and_autoexec_image ( struct image
*image
) {
321 if ( ( rc
= register_and_autoload_image ( image
) ) != 0 )
324 if ( ( rc
= image_exec ( image
) ) != 0 )