diff options
Diffstat (limited to 'src/image/embedded.c')
-rw-r--r-- | src/image/embedded.c | 109 |
1 files changed, 77 insertions, 32 deletions
diff --git a/src/image/embedded.c b/src/image/embedded.c index 0ce09783..f76ca11b 100644 --- a/src/image/embedded.c +++ b/src/image/embedded.c @@ -1,49 +1,94 @@ /** @file * - * Take a possible embedded image and put it in a struct image - * data structure. + * Embedded image support + * + * Embedded images are images built into the gPXE binary and do not require + * fetching over the network. */ +#include <string.h> #include <gpxe/image.h> -#include <gpxe/malloc.h> #include <gpxe/uaccess.h> -#include <gpxe/umalloc.h> -#include <gpxe/embedded.h> +#include <gpxe/init.h> -extern char _embedded_image_start[], _embedded_image_end[]; +/** + * Free embedded image + * + * @v refcnt Reference counter + */ +static void embedded_image_free ( struct refcnt *refcnt __unused ) { + /* Do nothing */ +} -struct image *embedded_image(void) -{ - static int reclaimed = 0; - struct image *image; - size_t eisize = _embedded_image_end - _embedded_image_start; +/* Raw image data for all embedded images */ +#undef EMBED +#define EMBED( _index, _path, _name ) \ + extern char embedded_image_ ## _index ## _data[]; \ + extern char embedded_image_ ## _index ## _len[]; \ + __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" \ + "\nembedded_image_" #_index "_data:\n\t" \ + ".incbin \"" _path "\"\n\t" \ + "\nembedded_image_" #_index "_end:\n\t" \ + ".equ embedded_image_" #_index "_len, " \ + "( embedded_image_" #_index "_end - " \ + " embedded_image_" #_index "_data )\n\t" \ + ".previous\n\t" ); +EMBED_ALL - if ( !eisize ) - return NULL; /* No embedded image */ +/* Image structures for all embedded images */ +#undef EMBED +#define EMBED( _index, _path, _name ) { \ + .refcnt = { .free = embedded_image_free, }, \ + .name = _name, \ + .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \ + .len = ( size_t ) embedded_image_ ## _index ## _len, \ +}, +static struct image embedded_images[] = { + EMBED_ALL +}; - if ( reclaimed ) - return NULL; /* Already reclaimed */ +/** + * Register all embedded images + */ +static void embedded_init ( void ) { + unsigned int i; + struct image *image; + void *data; + int rc; - DBG ( "Embedded image: %zd bytes at %p\n", - eisize, _embedded_image_start ); + /* Fix up data pointers and register images */ + for ( i = 0 ; i < ( sizeof ( embedded_images ) / + sizeof ( embedded_images[0] ) ) ; i++ ) { + image = &embedded_images[i]; - image = alloc_image(); - if (!image) - return NULL; + /* virt_to_user() cannot be used in a static + * initialiser, so we cast the pointer to a userptr_t + * in the initialiser and fix it up here. (This will + * actually be a no-op on most platforms.) + */ + data = ( ( void * ) image->data ); + image->data = virt_to_user ( data ); - image->len = eisize; - image->data = umalloc(eisize); - if (image->data == UNULL) { - image_put(image); - return image = NULL; - } - copy_to_user(image->data, 0, _embedded_image_start, eisize); - register_image(image); + DBG ( "Embedded image \"%s\": %zd bytes at %p\n", + image->name, image->len, data ); - /* Reclaim embedded image memory */ - reclaimed = 1; - mpopulate(_embedded_image_start, eisize); + if ( ( rc = register_image ( image ) ) != 0 ) { + DBG ( "Could not register embedded image \"%s\": " + "%s\n", image->name, strerror ( rc ) ); + return; + } + } - return image; + /* Load the first image */ + image = &embedded_images[0]; + if ( ( rc = image_autoload ( image ) ) != 0 ) { + DBG ( "Could not load embedded image \"%s\": %s\n", + image->name, strerror ( rc ) ); + return; + } } +/** Embedded image initialisation function */ +struct init_fn embedded_init_fn __init_fn ( INIT_NORMAL ) = { + .initialise = embedded_init, +}; |