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