1 // SPDX-License-Identifier: GPL-2.0
2
3 #include <linux/efi.h>
4 #include <linux/pe.h>
5 #include <asm/efi.h>
6 #include <asm/unaligned.h>
7
8 #include "efistub.h"
9
10 static unsigned char zboot_heap[SZ_256K] __aligned(64);
11 static unsigned long free_mem_ptr, free_mem_end_ptr;
12
13 #define STATIC static
14 #if defined(CONFIG_KERNEL_GZIP)
15 #include "../../../../lib/decompress_inflate.c"
16 #elif defined(CONFIG_KERNEL_LZ4)
17 #include "../../../../lib/decompress_unlz4.c"
18 #elif defined(CONFIG_KERNEL_LZMA)
19 #include "../../../../lib/decompress_unlzma.c"
20 #elif defined(CONFIG_KERNEL_LZO)
21 #include "../../../../lib/decompress_unlzo.c"
22 #elif defined(CONFIG_KERNEL_XZ)
23 #undef memcpy
24 #define memcpy memcpy
25 #undef memmove
26 #define memmove memmove
27 #include "../../../../lib/decompress_unxz.c"
28 #elif defined(CONFIG_KERNEL_ZSTD)
29 #include "../../../../lib/decompress_unzstd.c"
30 #endif
31
32 extern char efi_zboot_header[];
33 extern char _gzdata_start[], _gzdata_end[];
34
log(efi_char16_t str[])35 static void log(efi_char16_t str[])
36 {
37 efi_call_proto(efi_table_attr(efi_system_table, con_out),
38 output_string, L"EFI decompressor: ");
39 efi_call_proto(efi_table_attr(efi_system_table, con_out),
40 output_string, str);
41 efi_call_proto(efi_table_attr(efi_system_table, con_out),
42 output_string, L"\n");
43 }
44
error(char * x)45 static void error(char *x)
46 {
47 log(L"error() called from decompressor library\n");
48 }
49
50 // Local version to avoid pulling in memcmp()
guids_eq(const efi_guid_t * a,const efi_guid_t * b)51 static bool guids_eq(const efi_guid_t *a, const efi_guid_t *b)
52 {
53 const u32 *l = (u32 *)a;
54 const u32 *r = (u32 *)b;
55
56 return l[0] == r[0] && l[1] == r[1] && l[2] == r[2] && l[3] == r[3];
57 }
58
59 static efi_status_t __efiapi
load_file(efi_load_file_protocol_t * this,efi_device_path_protocol_t * rem,bool boot_policy,unsigned long * bufsize,void * buffer)60 load_file(efi_load_file_protocol_t *this, efi_device_path_protocol_t *rem,
61 bool boot_policy, unsigned long *bufsize, void *buffer)
62 {
63 unsigned long compressed_size = _gzdata_end - _gzdata_start;
64 struct efi_vendor_dev_path *vendor_dp;
65 bool decompress = false;
66 unsigned long size;
67 int ret;
68
69 if (rem == NULL || bufsize == NULL)
70 return EFI_INVALID_PARAMETER;
71
72 if (boot_policy)
73 return EFI_UNSUPPORTED;
74
75 // Look for our vendor media device node in the remaining file path
76 if (rem->type == EFI_DEV_MEDIA &&
77 rem->sub_type == EFI_DEV_MEDIA_VENDOR) {
78 vendor_dp = container_of(rem, struct efi_vendor_dev_path, header);
79 if (!guids_eq(&vendor_dp->vendorguid, &LINUX_EFI_ZBOOT_MEDIA_GUID))
80 return EFI_NOT_FOUND;
81
82 decompress = true;
83 rem = (void *)(vendor_dp + 1);
84 }
85
86 if (rem->type != EFI_DEV_END_PATH ||
87 rem->sub_type != EFI_DEV_END_ENTIRE)
88 return EFI_NOT_FOUND;
89
90 // The uncompressed size of the payload is appended to the raw bit
91 // stream, and may therefore appear misaligned in memory
92 size = decompress ? get_unaligned_le32(_gzdata_end - 4)
93 : compressed_size;
94 if (buffer == NULL || *bufsize < size) {
95 *bufsize = size;
96 return EFI_BUFFER_TOO_SMALL;
97 }
98
99 if (decompress) {
100 ret = __decompress(_gzdata_start, compressed_size, NULL, NULL,
101 buffer, size, NULL, error);
102 if (ret < 0) {
103 log(L"Decompression failed");
104 return EFI_DEVICE_ERROR;
105 }
106 } else {
107 memcpy(buffer, _gzdata_start, compressed_size);
108 }
109
110 return EFI_SUCCESS;
111 }
112
113 // Return the length in bytes of the device path up to the first end node.
device_path_length(const efi_device_path_protocol_t * dp)114 static int device_path_length(const efi_device_path_protocol_t *dp)
115 {
116 int len = 0;
117
118 while (dp->type != EFI_DEV_END_PATH) {
119 len += dp->length;
120 dp = (void *)((u8 *)dp + dp->length);
121 }
122 return len;
123 }
124
append_rel_offset_node(efi_device_path_protocol_t ** dp,unsigned long start,unsigned long end)125 static void append_rel_offset_node(efi_device_path_protocol_t **dp,
126 unsigned long start, unsigned long end)
127 {
128 struct efi_rel_offset_dev_path *rodp = (void *)*dp;
129
130 rodp->header.type = EFI_DEV_MEDIA;
131 rodp->header.sub_type = EFI_DEV_MEDIA_REL_OFFSET;
132 rodp->header.length = sizeof(struct efi_rel_offset_dev_path);
133 rodp->reserved = 0;
134 rodp->starting_offset = start;
135 rodp->ending_offset = end;
136
137 *dp = (void *)(rodp + 1);
138 }
139
append_ven_media_node(efi_device_path_protocol_t ** dp,efi_guid_t * guid)140 static void append_ven_media_node(efi_device_path_protocol_t **dp,
141 efi_guid_t *guid)
142 {
143 struct efi_vendor_dev_path *vmdp = (void *)*dp;
144
145 vmdp->header.type = EFI_DEV_MEDIA;
146 vmdp->header.sub_type = EFI_DEV_MEDIA_VENDOR;
147 vmdp->header.length = sizeof(struct efi_vendor_dev_path);
148 vmdp->vendorguid = *guid;
149
150 *dp = (void *)(vmdp + 1);
151 }
152
append_end_node(efi_device_path_protocol_t ** dp)153 static void append_end_node(efi_device_path_protocol_t **dp)
154 {
155 (*dp)->type = EFI_DEV_END_PATH;
156 (*dp)->sub_type = EFI_DEV_END_ENTIRE;
157 (*dp)->length = sizeof(struct efi_generic_dev_path);
158
159 ++*dp;
160 }
161
162 asmlinkage efi_status_t __efiapi
efi_zboot_entry(efi_handle_t handle,efi_system_table_t * systab)163 efi_zboot_entry(efi_handle_t handle, efi_system_table_t *systab)
164 {
165 struct efi_mem_mapped_dev_path mmdp = {
166 .header.type = EFI_DEV_HW,
167 .header.sub_type = EFI_DEV_MEM_MAPPED,
168 .header.length = sizeof(struct efi_mem_mapped_dev_path)
169 };
170 efi_device_path_protocol_t *parent_dp, *dpp, *lf2_dp, *li_dp;
171 efi_load_file2_protocol_t zboot_load_file2;
172 efi_loaded_image_t *parent, *child;
173 unsigned long exit_data_size;
174 efi_handle_t child_handle;
175 efi_handle_t zboot_handle;
176 efi_char16_t *exit_data;
177 efi_status_t status;
178 void *dp_alloc;
179 int dp_len;
180
181 WRITE_ONCE(efi_system_table, systab);
182
183 free_mem_ptr = (unsigned long)&zboot_heap;
184 free_mem_end_ptr = free_mem_ptr + sizeof(zboot_heap);
185
186 exit_data = NULL;
187 exit_data_size = 0;
188
189 status = efi_bs_call(handle_protocol, handle,
190 &LOADED_IMAGE_PROTOCOL_GUID, (void **)&parent);
191 if (status != EFI_SUCCESS) {
192 log(L"Failed to locate parent's loaded image protocol");
193 return status;
194 }
195
196 status = efi_bs_call(handle_protocol, handle,
197 &LOADED_IMAGE_DEVICE_PATH_PROTOCOL_GUID,
198 (void **)&parent_dp);
199 if (status != EFI_SUCCESS || parent_dp == NULL) {
200 // Create a MemoryMapped() device path node to describe
201 // the parent image if no device path was provided.
202 mmdp.memory_type = parent->image_code_type;
203 mmdp.starting_addr = (unsigned long)parent->image_base;
204 mmdp.ending_addr = (unsigned long)parent->image_base +
205 parent->image_size - 1;
206 parent_dp = &mmdp.header;
207 dp_len = sizeof(mmdp);
208 } else {
209 dp_len = device_path_length(parent_dp);
210 }
211
212 // Allocate some pool memory for device path protocol data
213 status = efi_bs_call(allocate_pool, EFI_LOADER_DATA,
214 2 * (dp_len + sizeof(struct efi_rel_offset_dev_path) +
215 sizeof(struct efi_generic_dev_path)) +
216 sizeof(struct efi_vendor_dev_path),
217 (void **)&dp_alloc);
218 if (status != EFI_SUCCESS) {
219 log(L"Failed to allocate device path pool memory");
220 return status;
221 }
222
223 // Create a device path describing the compressed payload in this image
224 // <...parent_dp...>/Offset(<start>, <end>)
225 lf2_dp = memcpy(dp_alloc, parent_dp, dp_len);
226 dpp = (void *)((u8 *)lf2_dp + dp_len);
227 append_rel_offset_node(&dpp,
228 (unsigned long)(_gzdata_start - efi_zboot_header),
229 (unsigned long)(_gzdata_end - efi_zboot_header - 1));
230 append_end_node(&dpp);
231
232 // Create a device path describing the decompressed payload in this image
233 // <...parent_dp...>/Offset(<start>, <end>)/VenMedia(ZBOOT_MEDIA_GUID)
234 dp_len += sizeof(struct efi_rel_offset_dev_path);
235 li_dp = memcpy(dpp, lf2_dp, dp_len);
236 dpp = (void *)((u8 *)li_dp + dp_len);
237 append_ven_media_node(&dpp, &LINUX_EFI_ZBOOT_MEDIA_GUID);
238 append_end_node(&dpp);
239
240 zboot_handle = NULL;
241 zboot_load_file2.load_file = load_file;
242 status = efi_bs_call(install_multiple_protocol_interfaces,
243 &zboot_handle,
244 &EFI_DEVICE_PATH_PROTOCOL_GUID, lf2_dp,
245 &EFI_LOAD_FILE2_PROTOCOL_GUID, &zboot_load_file2,
246 NULL);
247 if (status != EFI_SUCCESS) {
248 log(L"Failed to install LoadFile2 protocol and device path");
249 goto free_dpalloc;
250 }
251
252 status = efi_bs_call(load_image, false, handle, li_dp, NULL, 0,
253 &child_handle);
254 if (status != EFI_SUCCESS) {
255 log(L"Failed to load image");
256 goto uninstall_lf2;
257 }
258
259 status = efi_bs_call(handle_protocol, child_handle,
260 &LOADED_IMAGE_PROTOCOL_GUID, (void **)&child);
261 if (status != EFI_SUCCESS) {
262 log(L"Failed to locate child's loaded image protocol");
263 goto unload_image;
264 }
265
266 // Copy the kernel command line
267 child->load_options = parent->load_options;
268 child->load_options_size = parent->load_options_size;
269
270 status = efi_bs_call(start_image, child_handle, &exit_data_size,
271 &exit_data);
272 if (status != EFI_SUCCESS) {
273 log(L"StartImage() returned with error");
274 if (exit_data_size > 0)
275 log(exit_data);
276
277 // If StartImage() returns EFI_SECURITY_VIOLATION, the image is
278 // not unloaded so we need to do it by hand.
279 if (status == EFI_SECURITY_VIOLATION)
280 unload_image:
281 efi_bs_call(unload_image, child_handle);
282 }
283
284 uninstall_lf2:
285 efi_bs_call(uninstall_multiple_protocol_interfaces,
286 zboot_handle,
287 &EFI_DEVICE_PATH_PROTOCOL_GUID, lf2_dp,
288 &EFI_LOAD_FILE2_PROTOCOL_GUID, &zboot_load_file2,
289 NULL);
290
291 free_dpalloc:
292 efi_bs_call(free_pool, dp_alloc);
293
294 efi_bs_call(exit, handle, status, exit_data_size, exit_data);
295
296 // Free ExitData in case Exit() returned with a failure code,
297 // but return the original status code.
298 log(L"Exit() returned with failure code");
299 if (exit_data != NULL)
300 efi_bs_call(free_pool, exit_data);
301 return status;
302 }
303