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