1 /* 2 * Copyright (C) 2006 Michael Brown <mbrown (at) 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 image->refcnt.free = 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 } 329