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