2008-01-08 15:51:36 +00:00
|
|
|
/** @file
|
|
|
|
*
|
2009-02-16 00:28:30 +00:00
|
|
|
* Embedded image support
|
|
|
|
*
|
|
|
|
* Embedded images are images built into the gPXE binary and do not require
|
|
|
|
* fetching over the network.
|
2008-01-08 15:51:36 +00:00
|
|
|
*/
|
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
#include <string.h>
|
2008-01-08 15:51:36 +00:00
|
|
|
#include <gpxe/image.h>
|
|
|
|
#include <gpxe/uaccess.h>
|
2009-02-16 00:28:30 +00:00
|
|
|
#include <gpxe/init.h>
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
/**
|
|
|
|
* Free embedded image
|
|
|
|
*
|
|
|
|
* @v refcnt Reference counter
|
|
|
|
*/
|
2009-02-24 05:51:21 +00:00
|
|
|
static void __attribute__ (( unused ))
|
|
|
|
embedded_image_free ( struct refcnt *refcnt __unused ) {
|
2009-02-16 00:28:30 +00:00
|
|
|
/* Do nothing */
|
|
|
|
}
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
/* 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
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
/* 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
|
|
|
|
};
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
/**
|
|
|
|
* Register all embedded images
|
|
|
|
*/
|
|
|
|
static void embedded_init ( void ) {
|
2009-02-24 05:51:21 +00:00
|
|
|
int i;
|
2009-02-16 00:28:30 +00:00
|
|
|
struct image *image;
|
|
|
|
void *data;
|
|
|
|
int rc;
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-24 05:51:21 +00:00
|
|
|
/* Skip if we have no embedded images */
|
|
|
|
if ( ! sizeof ( embedded_images ) )
|
|
|
|
return;
|
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
/* Fix up data pointers and register images */
|
2009-02-24 05:51:21 +00:00
|
|
|
for ( i = 0 ; i < ( int ) ( sizeof ( embedded_images ) /
|
|
|
|
sizeof ( embedded_images[0] ) ) ; i++ ) {
|
2009-02-16 00:28:30 +00:00
|
|
|
image = &embedded_images[i];
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
/* 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 );
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
DBG ( "Embedded image \"%s\": %zd bytes at %p\n",
|
|
|
|
image->name, image->len, data );
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
if ( ( rc = register_image ( image ) ) != 0 ) {
|
|
|
|
DBG ( "Could not register embedded image \"%s\": "
|
|
|
|
"%s\n", image->name, strerror ( rc ) );
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
2008-01-08 15:51:36 +00:00
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
/* 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;
|
|
|
|
}
|
2008-01-08 15:51:36 +00:00
|
|
|
}
|
|
|
|
|
2009-02-16 00:28:30 +00:00
|
|
|
/** Embedded image initialisation function */
|
|
|
|
struct init_fn embedded_init_fn __init_fn ( INIT_NORMAL ) = {
|
|
|
|
.initialise = embedded_init,
|
|
|
|
};
|