176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** @file 276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Embedded image support 476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Embedded images are images built into the gPXE binary and do not require 676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * fetching over the network. 776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanFILE_LICENCE ( GPL2_OR_LATER ); 1076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <string.h> 1276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/image.h> 1376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/uaccess.h> 1476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#include <gpxe/init.h> 1576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 1676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 1776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Free embedded image 1876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * 1976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * @v refcnt Reference counter 2076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 2176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void __attribute__ (( unused )) 2276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanembedded_image_free ( struct refcnt *refcnt __unused ) { 2376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Do nothing */ 2476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 2576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 2676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Raw image data for all embedded images */ 2776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#undef EMBED 2876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EMBED( _index, _path, _name ) \ 2976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman extern char embedded_image_ ## _index ## _data[]; \ 3076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman extern char embedded_image_ ## _index ## _len[]; \ 3176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman __asm__ ( ".section \".rodata\", \"a\", @progbits\n\t" \ 3276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "\nembedded_image_" #_index "_data:\n\t" \ 3376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ".incbin \"" _path "\"\n\t" \ 3476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "\nembedded_image_" #_index "_end:\n\t" \ 3576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ".equ embedded_image_" #_index "_len, " \ 3676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "( embedded_image_" #_index "_end - " \ 3776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman " embedded_image_" #_index "_data )\n\t" \ 3876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman ".previous\n\t" ); 3976d05dc695b06c4e987bb8078f78032441e1430cGreg HartmanEMBED_ALL 4076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 4176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/* Image structures for all embedded images */ 4276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#undef EMBED 4376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman#define EMBED( _index, _path, _name ) { \ 4476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .refcnt = { .free = embedded_image_free, }, \ 4576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .name = _name, \ 4676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .data = ( userptr_t ) ( embedded_image_ ## _index ## _data ), \ 4776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .len = ( size_t ) embedded_image_ ## _index ## _len, \ 4876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}, 4976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic struct image embedded_images[] = { 5076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman EMBED_ALL 5176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 5276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 5376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** 5476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * Register all embedded images 5576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 5676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstatic void embedded_init ( void ) { 5776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int i; 5876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman struct image *image; 5976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman void *data; 6076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman int rc; 6176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Skip if we have no embedded images */ 6376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ! sizeof ( embedded_images ) ) 6476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 6576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 6676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Fix up data pointers and register images */ 6776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman for ( i = 0 ; i < ( int ) ( sizeof ( embedded_images ) / 6876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman sizeof ( embedded_images[0] ) ) ; i++ ) { 6976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman image = &embedded_images[i]; 7076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* virt_to_user() cannot be used in a static 7276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * initialiser, so we cast the pointer to a userptr_t 7376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * in the initialiser and fix it up here. (This will 7476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman * actually be a no-op on most platforms.) 7576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman */ 7676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman data = ( ( void * ) image->data ); 7776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman image->data = virt_to_user ( data ); 7876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 7976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "Embedded image \"%s\": %zd bytes at %p\n", 8076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman image->name, image->len, data ); 8176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = register_image ( image ) ) != 0 ) { 8376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "Could not register embedded image \"%s\": " 8476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman "%s\n", image->name, strerror ( rc ) ); 8576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 8676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 8876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 8976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman /* Load the first image */ 9076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman image = &embedded_images[0]; 9176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman if ( ( rc = image_autoload ( image ) ) != 0 ) { 9276d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman DBG ( "Could not load embedded image \"%s\": %s\n", 9376d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman image->name, strerror ( rc ) ); 9476d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman return; 9576d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman } 9676d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman} 9776d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman 9876d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman/** Embedded image initialisation function */ 9976d05dc695b06c4e987bb8078f78032441e1430cGreg Hartmanstruct init_fn embedded_init_fn __init_fn ( INIT_NORMAL ) = { 10076d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman .initialise = embedded_init, 10176d05dc695b06c4e987bb8078f78032441e1430cGreg Hartman}; 102