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