[e16e8f2] | 1 | /** @file |
---|
| 2 | * |
---|
| 3 | * Embedded image support |
---|
| 4 | * |
---|
| 5 | * Embedded images are images built into the gPXE binary and do not require |
---|
| 6 | * fetching over the network. |
---|
| 7 | */ |
---|
| 8 | |
---|
| 9 | FILE_LICENCE ( GPL2_OR_LATER ); |
---|
| 10 | |
---|
| 11 | #include <string.h> |
---|
| 12 | #include <gpxe/image.h> |
---|
| 13 | #include <gpxe/uaccess.h> |
---|
| 14 | #include <gpxe/init.h> |
---|
| 15 | |
---|
| 16 | /** |
---|
| 17 | * Free embedded image |
---|
| 18 | * |
---|
| 19 | * @v refcnt Reference counter |
---|
| 20 | */ |
---|
| 21 | static void __attribute__ (( unused )) |
---|
| 22 | embedded_image_free ( struct refcnt *refcnt __unused ) { |
---|
| 23 | /* Do nothing */ |
---|
| 24 | } |
---|
| 25 | |
---|
| 26 | /* Raw image data for all embedded images */ |
---|
| 27 | #undef EMBED |
---|
| 28 | #define EMBED( _index, _path, _name ) \ |
---|
| 29 | extern char embedded_image_ ## _index ## _data[]; \ |
---|
| 30 | extern char embedded_image_ ## _index ## _len[]; \ |
---|
| 31 | __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" \ |
---|
| 32 | "\nembedded_image_" #_index "_data:\n\t" \ |
---|
| 33 | ".incbin \"" _path "\"\n\t" \ |
---|
| 34 | "\nembedded_image_" #_index "_end:\n\t" \ |
---|
| 35 | ".equ embedded_image_" #_index "_len, " \ |
---|
| 36 | "( embedded_image_" #_index "_end - " \ |
---|
| 37 | " embedded_image_" #_index "_data )\n\t" \ |
---|
| 38 | ".previous\n\t" ); |
---|
| 39 | EMBED_ALL |
---|
| 40 | |
---|
| 41 | /* Image structures for all embedded images */ |
---|
| 42 | #undef EMBED |
---|
| 43 | #define EMBED( _index, _path, _name ) { \ |
---|
| 44 | .refcnt = { .free = embedded_image_free, }, \ |
---|
| 45 | .name = _name, \ |
---|
| 46 | .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \ |
---|
| 47 | .len = ( size_t ) embedded_image_ ## _index ## _len, \ |
---|
| 48 | }, |
---|
| 49 | static struct image embedded_images[] = { |
---|
| 50 | EMBED_ALL |
---|
| 51 | }; |
---|
| 52 | |
---|
| 53 | /** |
---|
| 54 | * Register all embedded images |
---|
| 55 | */ |
---|
| 56 | static void embedded_init ( void ) { |
---|
| 57 | int i; |
---|
| 58 | struct image *image; |
---|
| 59 | void *data; |
---|
| 60 | int rc; |
---|
| 61 | |
---|
| 62 | /* Skip if we have no embedded images */ |
---|
| 63 | if ( ! sizeof ( embedded_images ) ) |
---|
| 64 | return; |
---|
| 65 | |
---|
| 66 | /* Fix up data pointers and register images */ |
---|
| 67 | for ( i = 0 ; i < ( int ) ( sizeof ( embedded_images ) / |
---|
| 68 | sizeof ( embedded_images[0] ) ) ; i++ ) { |
---|
| 69 | image = &embedded_images[i]; |
---|
| 70 | |
---|
| 71 | /* virt_to_user() cannot be used in a static |
---|
| 72 | * initialiser, so we cast the pointer to a userptr_t |
---|
| 73 | * in the initialiser and fix it up here. (This will |
---|
| 74 | * actually be a no-op on most platforms.) |
---|
| 75 | */ |
---|
| 76 | data = ( ( void * ) image->data ); |
---|
| 77 | image->data = virt_to_user ( data ); |
---|
| 78 | |
---|
| 79 | DBG ( "Embedded image \"%s\": %zd bytes at %p\n", |
---|
| 80 | image->name, image->len, data ); |
---|
| 81 | |
---|
| 82 | if ( ( rc = register_image ( image ) ) != 0 ) { |
---|
| 83 | DBG ( "Could not register embedded image \"%s\": " |
---|
| 84 | "%s\n", image->name, strerror ( rc ) ); |
---|
| 85 | return; |
---|
| 86 | } |
---|
| 87 | } |
---|
| 88 | |
---|
| 89 | /* Load the first image */ |
---|
| 90 | image = &embedded_images[0]; |
---|
| 91 | if ( ( rc = image_autoload ( image ) ) != 0 ) { |
---|
| 92 | DBG ( "Could not load embedded image \"%s\": %s\n", |
---|
| 93 | image->name, strerror ( rc ) ); |
---|
| 94 | return; |
---|
| 95 | } |
---|
| 96 | } |
---|
| 97 | |
---|
| 98 | /** Embedded image initialisation function */ |
---|
| 99 | struct init_fn embedded_init_fn __init_fn ( INIT_NORMAL ) = { |
---|
| 100 | .initialise = embedded_init, |
---|
| 101 | }; |
---|