1 // SPDX-License-Identifier: GPL-2.0+
2 /*
3 * For the code moved from cmd/bootefi.c
4 * Copyright (c) 2016 Alexander Graf
5 */
6
7 #define LOG_CATEGORY LOGC_EFI
8
9 #include <bootflow.h>
10 #include <charset.h>
11 #include <dm.h>
12 #include <efi.h>
13 #include <efi_device_path.h>
14 #include <efi_loader.h>
15 #include <env.h>
16 #include <image.h>
17 #include <log.h>
18 #include <malloc.h>
19 #include <mapmem.h>
20 #include <net.h>
21
22 static struct efi_device_path *bootefi_image_path;
23 static struct efi_device_path *bootefi_device_path;
24 static void *image_addr;
25 static size_t image_size;
26
27 /**
28 * efi_get_image_parameters() - return image parameters
29 *
30 * @img_addr: address of loaded image in memory
31 * @img_size: size of loaded image
32 */
efi_get_image_parameters(void ** img_addr,size_t * img_size)33 void efi_get_image_parameters(void **img_addr, size_t *img_size)
34 {
35 *img_addr = image_addr;
36 *img_size = image_size;
37 }
38
39 /**
40 * efi_clear_bootdev() - clear boot device
41 */
efi_clear_bootdev(void)42 void efi_clear_bootdev(void)
43 {
44 efi_free_pool(bootefi_device_path);
45 efi_free_pool(bootefi_image_path);
46 bootefi_device_path = NULL;
47 bootefi_image_path = NULL;
48 image_addr = NULL;
49 image_size = 0;
50 }
51
52 /**
53 * calculate_paths() - Calculate the device and image patch from strings
54 *
55 * @dev: device, e.g. "MMC"
56 * @devnr: number of the device, e.g. "1:2"
57 * @path: path to file loaded
58 * @device_pathp: returns EFI device path
59 * @image_pathp: returns EFI image path
60 * Return: EFI_SUCCESS on success, else error code
61 */
calculate_paths(const char * dev,const char * devnr,const char * path,struct efi_device_path ** device_pathp,struct efi_device_path ** image_pathp)62 static efi_status_t calculate_paths(const char *dev, const char *devnr,
63 const char *path,
64 struct efi_device_path **device_pathp,
65 struct efi_device_path **image_pathp)
66 {
67 struct efi_device_path *image, *device;
68 efi_status_t ret;
69
70 #if IS_ENABLED(CONFIG_NETDEVICES)
71 if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) {
72 ret = efi_net_new_dp(dev, devnr, eth_get_dev());
73 if (ret != EFI_SUCCESS)
74 return ret;
75 }
76 #endif
77
78 ret = efi_dp_from_name(dev, devnr, path, &device, &image);
79 if (ret != EFI_SUCCESS)
80 return ret;
81
82 *device_pathp = device;
83 if (image) {
84 /* FIXME: image should not contain device */
85 struct efi_device_path *image_tmp = image;
86
87 efi_dp_split_file_path(image, &device, &image);
88 efi_free_pool(image_tmp);
89 }
90 *image_pathp = image;
91 log_debug("- boot device %pD\n", device);
92 if (image)
93 log_debug("- image %pD\n", image);
94
95 return EFI_SUCCESS;
96 }
97
98 /**
99 * efi_set_bootdev() - set boot device
100 *
101 * This function is called when a file is loaded, e.g. via the 'load' command.
102 * We use the path to this file to inform the UEFI binary about the boot device.
103 *
104 * For a valid image, it sets:
105 * - image_addr to the provided buffer
106 * - image_size to the provided buffer_size
107 * - bootefi_device_path to the EFI device-path
108 * - bootefi_image_path to the EFI image-path
109 *
110 * @dev: device, e.g. "MMC"
111 * @devnr: number of the device, e.g. "1:2"
112 * @path: path to file loaded
113 * @buffer: buffer with file loaded
114 * @buffer_size: size of file loaded
115 */
efi_set_bootdev(const char * dev,const char * devnr,const char * path,void * buffer,size_t buffer_size)116 void efi_set_bootdev(const char *dev, const char *devnr, const char *path,
117 void *buffer, size_t buffer_size)
118 {
119 efi_status_t ret;
120
121 log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev,
122 devnr, path, buffer, buffer_size);
123
124 /* Forget overwritten image */
125 if (buffer + buffer_size >= image_addr &&
126 image_addr + image_size >= buffer)
127 efi_clear_bootdev();
128
129 /* Remember only PE-COFF and FIT images */
130 if (efi_check_pe(buffer, buffer_size, NULL) != EFI_SUCCESS) {
131 if (IS_ENABLED(CONFIG_FIT) &&
132 !fit_check_format(buffer, IMAGE_SIZE_INVAL)) {
133 /*
134 * FIT images of type EFI_OS are started via command
135 * bootm. We should not use their boot device with the
136 * bootefi command.
137 */
138 buffer = 0;
139 buffer_size = 0;
140 } else {
141 log_debug("- not remembering image\n");
142 return;
143 }
144 }
145
146 /* efi_set_bootdev() is typically called repeatedly, recover memory */
147 efi_clear_bootdev();
148
149 image_addr = buffer;
150 image_size = buffer_size;
151
152 ret = calculate_paths(dev, devnr, path, &bootefi_device_path,
153 &bootefi_image_path);
154 if (ret) {
155 log_debug("- efi_dp_from_name() failed, err=%lx\n", ret);
156 efi_clear_bootdev();
157 }
158 }
159
160 /**
161 * efi_run_image() - run loaded UEFI image
162 *
163 * @source_buffer: memory address of the UEFI image
164 * @source_size: size of the UEFI image
165 * @dp_dev: EFI device-path
166 * @dp_img: EFI image-path
167 * Return: status code
168 */
efi_run_image(void * source_buffer,efi_uintn_t source_size,struct efi_device_path * dp_dev,struct efi_device_path * dp_img)169 static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size,
170 struct efi_device_path *dp_dev,
171 struct efi_device_path *dp_img)
172 {
173 efi_handle_t handle;
174 struct efi_device_path *msg_path, *file_path;
175 efi_status_t ret;
176 u16 *load_options;
177
178 file_path = efi_dp_concat(dp_dev, dp_img, 0);
179 msg_path = dp_img;
180
181 log_info("Booting %pD\n", msg_path);
182
183 ret = EFI_CALL(efi_load_image(false, efi_root, file_path, source_buffer,
184 source_size, &handle));
185 if (ret != EFI_SUCCESS) {
186 log_err("Loading image failed\n");
187 goto out;
188 }
189
190 /* Transfer environment variable as load options */
191 ret = efi_env_set_load_options(handle, "bootargs", &load_options);
192 if (ret != EFI_SUCCESS)
193 goto out;
194
195 ret = do_bootefi_exec(handle, load_options);
196
197 out:
198
199 return ret;
200 }
201
202 /**
203 * efi_binary_run_dp() - run loaded UEFI image
204 *
205 * @image: memory address of the UEFI image
206 * @size: size of the UEFI image
207 * @fdt: device-tree
208 * @initrd: initrd
209 * @initrd_sz: initrd size
210 * @dp_dev: EFI device-path
211 * @dp_img: EFI image-path
212 *
213 * Execute an EFI binary image loaded at @image.
214 * @size may be zero if the binary is loaded with U-Boot load command.
215 *
216 * Return: status code
217 */
efi_binary_run_dp(void * image,size_t size,void * fdt,void * initrd,size_t initrd_sz,struct efi_device_path * dp_dev,struct efi_device_path * dp_img)218 static efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt,
219 void *initrd, size_t initrd_sz,
220 struct efi_device_path *dp_dev,
221 struct efi_device_path *dp_img)
222 {
223 efi_status_t ret;
224
225 /* Initialize EFI drivers */
226 ret = efi_init_obj_list();
227 if (ret != EFI_SUCCESS) {
228 log_err("Error: Cannot initialize UEFI sub-system, r = %lu\n",
229 ret & ~EFI_ERROR_MASK);
230 return -1;
231 }
232
233 ret = efi_install_fdt(fdt);
234 if (ret != EFI_SUCCESS)
235 return ret;
236
237 ret = efi_install_initrd(initrd, initrd_sz);
238 if (ret != EFI_SUCCESS)
239 return ret;
240
241 return efi_run_image(image, size, dp_dev, dp_img);
242 }
243
244 /**
245 * efi_binary_run() - run loaded UEFI image
246 *
247 * @image: memory address of the UEFI image
248 * @size: size of the UEFI image
249 * @fdt: device-tree
250 * @initrd: initrd
251 * @initrd_sz: initrd size
252 *
253 * Execute an EFI binary image loaded at @image.
254 * @size may be zero if the binary is loaded with U-Boot load command.
255 *
256 * Return: status code
257 */
efi_binary_run(void * image,size_t size,void * fdt,void * initrd,size_t initrd_sz)258 efi_status_t efi_binary_run(void *image, size_t size, void *fdt, void *initrd, size_t initrd_sz)
259 {
260 efi_handle_t mem_handle = NULL;
261 struct efi_device_path *file_path = NULL;
262 efi_status_t ret;
263
264 if (!bootefi_device_path || !bootefi_image_path) {
265 log_debug("Not loaded from disk\n");
266 /*
267 * Special case for efi payload not loaded from disk,
268 * such as 'bootefi hello' or for example payload
269 * loaded directly into memory via JTAG, etc:
270 */
271 file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE,
272 (uintptr_t)image, size);
273 /*
274 * Make sure that device for device_path exist
275 * in load_image(). Otherwise, shell and grub will fail.
276 */
277 ret = efi_install_multiple_protocol_interfaces(&mem_handle,
278 &efi_guid_device_path,
279 file_path, NULL);
280 if (ret != EFI_SUCCESS)
281 goto out;
282
283 bootefi_device_path = file_path;
284 bootefi_image_path = NULL;
285 } else {
286 log_debug("Loaded from disk\n");
287 }
288
289 ret = efi_binary_run_dp(image, size, fdt, initrd, initrd_sz, bootefi_device_path,
290 bootefi_image_path);
291 out:
292 if (mem_handle) {
293 efi_status_t r;
294
295 r = efi_uninstall_multiple_protocol_interfaces(mem_handle,
296 &efi_guid_device_path, file_path, NULL);
297 if (r != EFI_SUCCESS)
298 log_err("Uninstalling protocol interfaces failed\n");
299 }
300 efi_free_pool(file_path);
301
302 return ret;
303 }
304
305 /**
306 * calc_dev_name() - Calculate the device name to give to EFI
307 *
308 * If not supported, this shows an error.
309 *
310 * Return name, or NULL if not supported
311 */
calc_dev_name(struct bootflow * bflow)312 static const char *calc_dev_name(struct bootflow *bflow)
313 {
314 const struct udevice *media_dev;
315
316 media_dev = dev_get_parent(bflow->dev);
317
318 if (!bflow->blk) {
319 if (device_get_uclass_id(media_dev) == UCLASS_ETH)
320 return "Net";
321
322 log_err("Cannot boot EFI app on media '%s'\n",
323 dev_get_uclass_name(media_dev));
324
325 return NULL;
326 }
327
328 if (device_get_uclass_id(media_dev) == UCLASS_MASS_STORAGE)
329 return "usb";
330
331 return blk_get_uclass_name(device_get_uclass_id(media_dev));
332 }
333
efi_bootflow_run(struct bootflow * bflow)334 efi_status_t efi_bootflow_run(struct bootflow *bflow)
335 {
336 struct efi_device_path *device, *image;
337 const struct udevice *media_dev;
338 struct blk_desc *desc = NULL;
339 const char *dev_name;
340 char devnum_str[9];
341 efi_status_t ret;
342 void *fdt;
343
344 media_dev = dev_get_parent(bflow->dev);
345 if (bflow->blk) {
346 desc = dev_get_uclass_plat(bflow->blk);
347
348 snprintf(devnum_str, sizeof(devnum_str), "%x:%x",
349 desc ? desc->devnum : dev_seq(media_dev), bflow->part);
350 } else {
351 *devnum_str = '\0';
352 }
353
354 dev_name = calc_dev_name(bflow);
355 log_debug("dev_name '%s' devnum_str '%s' fname '%s' media_dev '%s'\n",
356 dev_name, devnum_str, bflow->fname, media_dev->name);
357 if (!dev_name)
358 return EFI_UNSUPPORTED;
359 ret = calculate_paths(dev_name, devnum_str, bflow->fname, &device,
360 &image);
361 if (ret)
362 return EFI_UNSUPPORTED;
363
364 if (bflow->flags & BOOTFLOWF_USE_BUILTIN_FDT) {
365 log_debug("Booting with built-in fdt\n");
366 fdt = EFI_FDT_USE_INTERNAL;
367 } else {
368 log_debug("Booting with external fdt\n");
369 fdt = map_sysmem(bflow->fdt_addr, 0);
370 }
371 ret = efi_binary_run_dp(bflow->buf, bflow->size, fdt, NULL, 0, device, image);
372
373 return ret;
374 }
375