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