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
9FILE_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 */
21static void __attribute__ (( unused ))
22embedded_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" );
39EMBED_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},
49static struct image embedded_images[] = {
50	EMBED_ALL
51};
52
53/**
54 * Register all embedded images
55 */
56static 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 */
99struct init_fn embedded_init_fn __init_fn ( INIT_NORMAL ) = {
100	.initialise = embedded_init,
101};
102