Scripts temporarily deregister themselves while executing. This
[people/andreif/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 <gpxe/list.h>
26 #include <gpxe/umalloc.h>
27 #include <gpxe/image.h>
28
29 /** @file
30  *
31  * Executable/loadable images
32  *
33  */
34
35 /** List of registered images */
36 struct list_head images = LIST_HEAD_INIT ( images );
37
38 /** List of image types */
39 static struct image_type image_types[0]
40         __table_start ( struct image_type, image_types );
41 static struct image_type image_types_end[0]
42         __table_end ( struct image_type, image_types );
43
44 /**
45  * Free executable/loadable image
46  *
47  * @v refcnt            Reference counter
48  */
49 static void free_image ( struct refcnt *refcnt ) {
50         struct image *image = container_of ( refcnt, struct image, refcnt );
51
52         ufree ( image->data );
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 = malloc ( sizeof ( *image ) );
66         if ( image ) {
67                 memset ( image, 0, sizeof ( *image ) );
68                 image->refcnt.free = free_image;
69         }
70         return image;
71 }
72
73 /**
74  * Register executable/loadable image
75  *
76  * @v image             Executable/loadable image
77  * @ret rc              Return status code
78  */
79 int register_image ( struct image *image ) {
80         static unsigned int imgindex = 0;
81
82         /* Create image name if it doesn't already have one */
83         if ( ! image->name[0] ) {
84                 snprintf ( image->name, sizeof ( image->name ), "img%d",
85                            imgindex++ );
86         }
87
88         /* Add to image list */
89         image_get ( image );
90         list_add_tail ( &image->list, &images );
91         DBGC ( image, "IMAGE %p at [%lx,%lx) registered as %s\n",
92                image, user_to_phys ( image->data, 0 ),
93                user_to_phys ( image->data, image->len ), image->name );
94
95         return 0;
96 }
97
98 /**
99  * Unregister executable/loadable image
100  *
101  * @v image             Executable/loadable image
102  */
103 void unregister_image ( struct image *image ) {
104         list_del ( &image->list );
105         image_put ( image );
106         DBGC ( image, "IMAGE %p unregistered\n", image );
107 }
108
109 /**
110  * Find image by name
111  *
112  * @v name              Image name
113  * @ret image           Executable/loadable image, or NULL
114  */
115 struct image * find_image ( const char *name ) {
116         struct image *image;
117
118         list_for_each_entry ( image, &images, list ) {
119                 if ( strcmp ( image->name, name ) == 0 )
120                         return image;
121         }
122
123         return NULL;
124 }
125
126 /**
127  * Load executable/loadable image into memory
128  *
129  * @v image             Executable/loadable image
130  * @v type              Executable/loadable image type
131  * @ret rc              Return status code
132  */
133 static int image_load_type ( struct image *image, struct image_type *type ) {
134         int rc;
135
136         /* Check image is actually loadable */
137         if ( ! type->load )
138                 return -ENOEXEC;
139
140         /* Try the image loader */
141         if ( ( rc = type->load ( image ) ) != 0 ) {
142                 DBGC ( image, "IMAGE %p could not load as %s: %s\n",
143                        image, type->name, strerror ( rc ) );
144                 return rc;
145         }
146
147         /* Flag as loaded */
148         image->flags |= IMAGE_LOADED;
149         return 0;
150 }
151
152 /**
153  * Load executable/loadable image into memory
154  *
155  * @v image             Executable/loadable image
156  * @ret rc              Return status code
157  */
158 int image_load ( struct image *image ) {
159
160         assert ( image->type != NULL );
161
162         return image_load_type ( image, image->type );
163 }
164
165 /**
166  * Autodetect image type and load executable/loadable image into memory
167  *
168  * @v image             Executable/loadable image
169  * @ret rc              Return status code
170  */
171 int image_autoload ( struct image *image ) {
172         struct image_type *type;
173         int rc;
174
175         /* If image already has a type, use it */
176         if ( image->type )
177                 return image_load ( image );
178
179         /* Otherwise probe for a suitable type */
180         for ( type = image_types ; type < image_types_end ; type++ ) {
181                 DBGC ( image, "IMAGE %p trying type %s\n", image, type->name );
182                 rc = image_load_type ( image, type );
183                 if ( image->type == NULL )
184                         continue;
185                 return rc;
186         }
187
188         DBGC ( image, "IMAGE %p format not recognised\n", image );
189         return -ENOEXEC;
190 }
191
192 /**
193  * Execute loaded image
194  *
195  * @v image             Loaded image
196  * @ret rc              Return status code
197  */
198 int image_exec ( struct image *image ) {
199         int rc;
200
201         /* Image must be loaded first */
202         if ( ! ( image->flags & IMAGE_LOADED ) ) {
203                 DBGC ( image, "IMAGE %p could not execute: not loaded\n",
204                        image );
205                 return -ENOTTY;
206         }
207
208         assert ( image->type != NULL );
209
210         /* Check that image is actually executable */
211         if ( ! image->type->exec )
212                 return -ENOEXEC;
213
214         /* Try executing the image */
215         if ( ( rc = image->type->exec ( image ) ) != 0 ) {
216                 DBGC ( image, "IMAGE %p could not execute: %s\n",
217                        image, strerror ( rc ) );
218                 return rc;
219         }
220
221         /* Well, some formats might return... */
222         return 0;
223 }