Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | // SPDX-License-Identifier: GPL-2.0+ /* * Running programs from the EFI app * * Copyright 2024 Linaro Limited * Copyright 2024 Canonical Ltd */ #define LOG_CATEGORY LOGC_EFI #include <bootm.h> #include <dm.h> #include <efi.h> #include <efi_api.h> #include <efi_device_path.h> #include <log.h> #include <malloc.h> /** * do_bootefi_exec() - execute EFI binary * * The image indicated by @handle is started. When it returns the allocated * memory for the @load_options is freed. * * @handle: handle of loaded image * @load_options: load options * Return: status code */ static efi_status_t do_bootefi_exec(efi_handle_t handle, void *load_options) { struct efi_boot_services *boot = efi_get_boot(); efi_uintn_t exit_data_size = 0; u16 *exit_data = NULL; efi_status_t ret; /* On ARM switch from EL3 or secure mode to EL2 or non-secure mode */ if (!IS_ENABLED(CONFIG_EFI_APP)) switch_to_non_secure_mode(); /* TODO(sjg@chromium.org): Set watchdog */ /* Call our payload! */ ret = boot->start_image(handle, &exit_data_size, &exit_data); if (ret != EFI_SUCCESS) { log_err("## Application failed, r = %lu\n", ret & ~EFI_ERROR_MASK); if (exit_data) { log_err("## %ls\n", exit_data); boot->free_pool(exit_data); } } free(load_options); /* TODO(sjg@chromium.org): Disable watchdog */ return ret; } efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size, struct efi_device_path *dp_dev, struct efi_device_path *dp_img) { struct efi_boot_services *boot = efi_get_boot(); efi_handle_t handle; struct efi_device_path *msg_path, *file_path; efi_status_t ret; file_path = efi_dp_concat(dp_dev, dp_img, 0); msg_path = dp_img; log_info("Booting %pD\n", msg_path); ret = boot->load_image(false, efi_get_parent_image(), file_path, source_buffer, source_size, &handle); if (ret != EFI_SUCCESS) { log_err("Loading image failed\n"); goto out; } ret = do_bootefi_exec(handle, NULL); out: return ret; } efi_status_t 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) { return efi_run_image(image, size, dp_dev, dp_img); } int efi_dp_from_bootdev(const struct udevice *dev, const struct efi_device_path **dpp) { const struct udevice *media = dev_get_parent(dev); const struct efi_media_plat *plat; log_debug("dev '%s': uclass ID %d\n", media->name, device_get_uclass_id(media)); if (device_get_uclass_id(media) != UCLASS_EFI_MEDIA) return log_msg_ret("efb", -ENOTSUPP); plat = dev_get_plat(media); *dpp = plat->device_path; return 0; } |