summaryrefslogtreecommitdiffstats
path: root/src/image/embedded.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/image/embedded.c')
-rw-r--r--src/image/embedded.c109
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,
+};