e29d4cc77739f9bb2f9849c542a9bc06b12aab7e
[people/meteger/gpxe.git] / src / core / image.c
1 /*
2  * Copyright (C) 2006 Michael Brown <mbrown@fensystems.co.uk>.
3  *
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.
8  *
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.
13  *
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.
17  */
18
19 FILE_LICENCE ( GPL2_OR_LATER );
20
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>
32
33 /** @file
34  *
35  * Executable/loadable images
36  *
37  */
38
39 /** List of registered images */
40 struct list_head images = LIST_HEAD_INIT ( images );
41
42 /**
43  * Free executable/loadable image
44  *
45  * @v refcnt            Reference counter
46  */
47 static void free_image ( struct refcnt *refcnt ) {
48         struct image *image = container_of ( refcnt, struct image, refcnt );
49
50         uri_put ( image->uri );
51         ufree ( image->data );
52         image_put ( image->replacement );
53         free ( image );
54         DBGC ( image, "IMAGE %p freed\n", image );
55 }
56
57 /**
58  * Allocate executable/loadable image
59  *
60  * @ret image           Executable/loadable image
61  */
62 struct image * alloc_image ( void ) {
63         struct image *image;
64
65         image = zalloc ( sizeof ( *image ) );
66         if ( image ) {
67                 ref_init ( &image->refcnt, free_image );
68         }
69         return image;
70 }
71
72 /**
73  * Set image URI
74  *
75  * @v image             Image
76  * @v URI               New image URI
77  * @ret rc              Return status code
78  *
79  * If no name is set, the name will be updated to the base name of the
80  * URI path (if any).
81  */
82 int image_set_uri ( struct image *image, struct uri *uri ) {
83         const char *path = uri->path;
84
85         /* Replace URI reference */
86         uri_put ( image->uri );
87         image->uri = uri_get ( uri );
88
89         /* Set name if none already specified */
90         if ( path && ( ! image->name[0] ) )
91                 image_set_name ( image, basename ( ( char * ) path ) );
92
93         return 0;
94 }
95
96 /**
97  * Set image command line
98  *
99  * @v image             Image
100  * @v cmdline           New image command line
101  * @ret rc              Return status code
102  */
103 int image_set_cmdline ( struct image *image, const char *cmdline ) {
104         free ( image->cmdline );
105         image->cmdline = strdup ( cmdline );
106         if ( ! image->cmdline )
107                 return -ENOMEM;
108         return 0;
109 }
110
111 /**
112  * Register executable/loadable image
113  *
114  * @v image             Executable/loadable image
115  * @ret rc              Return status code
116  */
117 int register_image ( struct image *image ) {
118         static unsigned int imgindex = 0;
119
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",
123                            imgindex++ );
124         }
125
126         /* Add to image list */
127         image_get ( image );
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 );
132
133         return 0;
134 }
135
136 /**
137  * Unregister executable/loadable image
138  *
139  * @v image             Executable/loadable image
140  */
141 void unregister_image ( struct image *image ) {
142         DBGC ( image, "IMAGE %p unregistered\n", image );
143         list_del ( &image->list );
144         image_put ( image );
145 }
146
147 /**
148  * Find image by name
149  *
150  * @v name              Image name
151  * @ret image           Executable/loadable image, or NULL
152  */
153 struct image * find_image ( const char *name ) {
154         struct image *image;
155
156         list_for_each_entry ( image, &images, list ) {
157                 if ( strcmp ( image->name, name ) == 0 )
158                         return image;
159         }
160
161         return NULL;
162 }
163
164 /**
165  * Load executable/loadable image into memory
166  *
167  * @v image             Executable/loadable image
168  * @v type              Executable/loadable image type
169  * @ret rc              Return status code
170  */
171 static int image_load_type ( struct image *image, struct image_type *type ) {
172         int rc;
173
174         /* Check image is actually loadable */
175         if ( ! type->load )
176                 return -ENOEXEC;
177
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 ) );
182                 return rc;
183         }
184
185         /* Flag as loaded */
186         image->flags |= IMAGE_LOADED;
187         return 0;
188 }
189
190 /**
191  * Load executable/loadable image into memory
192  *
193  * @v image             Executable/loadable image
194  * @ret rc              Return status code
195  */
196 int image_load ( struct image *image ) {
197
198         assert ( image->type != NULL );
199
200         return image_load_type ( image, image->type );
201 }
202
203 /**
204  * Autodetect image type and load executable/loadable image into memory
205  *
206  * @v image             Executable/loadable image
207  * @ret rc              Return status code
208  */
209 int image_autoload ( struct image *image ) {
210         struct image_type *type;
211         int rc;
212
213         /* If image already has a type, use it */
214         if ( image->type )
215                 return image_load ( image );
216
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 )
222                         continue;
223                 return rc;
224         }
225
226         DBGC ( image, "IMAGE %p format not recognised\n", image );
227         return -ENOEXEC;
228 }
229
230 /**
231  * Execute loaded image
232  *
233  * @v image             Loaded image
234  * @ret rc              Return status code
235  */
236 int image_exec ( struct image *image ) {
237         struct image *replacement;
238         struct uri *old_cwuri;
239         int rc;
240
241         /* Image must be loaded first */
242         if ( ! ( image->flags & IMAGE_LOADED ) ) {
243                 DBGC ( image, "IMAGE %p could not execute: not loaded\n",
244                        image );
245                 return -ENOTTY;
246         }
247
248         assert ( image->type != NULL );
249
250         /* Check that image is actually executable */
251         if ( ! image->type->exec )
252                 return -ENOEXEC;
253
254         /* Switch current working directory to be that of the image itself */
255         old_cwuri = uri_get ( cwuri );
256         churi ( image->uri );
257
258         /* Take out a temporary reference to the image.  This allows
259          * the image to unregister itself if necessary, without
260          * automatically freeing itself.
261          */
262         image_get ( image );
263
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 */
269         }
270
271         /* Pick up replacement image before we drop the original
272          * image's temporary reference.
273          */
274         replacement = image->replacement;
275
276         /* Drop temporary reference to the original image */
277         image_put ( image );
278
279         /* Reset current working directory */
280         churi ( old_cwuri );
281         uri_put ( old_cwuri );
282
283         /* Tail-recurse into replacement image, if one exists */
284         if ( replacement ) {
285                 DBGC ( image, "IMAGE %p replacing self with IMAGE %p\n",
286                        image, replacement );
287                 if ( ( rc = image_exec ( replacement ) ) != 0 )
288                         return rc;
289         }
290
291         return rc;
292 }
293
294 /**
295  * Register and autoload an image
296  *
297  * @v image             Image
298  * @ret rc              Return status code
299  */
300 int register_and_autoload_image ( struct image *image ) {
301         int rc;
302
303         if ( ( rc = register_image ( image ) ) != 0 )
304                 return rc;
305
306         if ( ( rc = image_autoload ( image ) ) != 0 )
307                 return rc;
308
309         return 0;
310 }
311
312 /**
313  * Register and autoexec an image
314  *
315  * @v image             Image
316  * @ret rc              Return status code
317  */
318 int register_and_autoexec_image ( struct image *image ) {
319         int rc;
320
321         if ( ( rc = register_and_autoload_image ( image ) ) != 0 )
322                 return rc;
323
324         if ( ( rc = image_exec ( image ) ) != 0 )
325                 return rc;
326
327         return 0;
328 }