xref: /linux/drivers/firmware/efi/libstub/zboot.c (revision b92dd11725a7c57f55e148c7d3ce58a86f480575)
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 
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 
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()
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
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.
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 
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 
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 
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
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