diff options
Diffstat (limited to 'lib/efi_loader')
-rw-r--r-- | lib/efi_loader/Kconfig | 215 | ||||
-rw-r--r-- | lib/efi_loader/efi_bootmgr.c | 28 | ||||
-rw-r--r-- | lib/efi_loader/efi_capsule.c | 1 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_dt_fixup.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_firmware.c | 55 | ||||
-rw-r--r-- | lib/efi_loader/efi_helper.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/helloworld.c | 3 |
10 files changed, 206 insertions, 106 deletions
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index 6ffefa9103f..e58b8825605 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -1,3 +1,5 @@ +menu "UEFI Support" + config EFI_LOADER bool "Support running UEFI applications" depends on OF_LIBFDT && ( \ @@ -41,13 +43,58 @@ config EFI_BINARY_EXEC You may enable CMD_BOOTEFI_BINARY so that you can use bootefi command to do that. -config EFI_BOOTMGR - bool "UEFI Boot Manager" +config EFI_SECURE_BOOT + bool "Enable EFI secure boot support" + depends on EFI_LOADER && FIT_SIGNATURE + select HASH + select SHA256 + select RSA + select RSA_VERIFY_WITH_PKEY + select IMAGE_SIGN_INFO + select ASYMMETRIC_KEY_TYPE + select ASYMMETRIC_PUBLIC_KEY_SUBTYPE + select X509_CERTIFICATE_PARSER + select PKCS7_MESSAGE_PARSER + select PKCS7_VERIFY + select MSCODE_PARSER + select EFI_SIGNATURE_SUPPORT + help + Select this option to enable EFI secure boot support. + Once SecureBoot mode is enforced, any EFI binary can run only if + it is signed with a trusted key. To do that, you need to install, + at least, PK, KEK and db. + +config EFI_SIGNATURE_SUPPORT + bool + +menu "UEFI services" + +config EFI_GET_TIME + bool "GetTime() runtime service" + depends on DM_RTC default y help - Select this option if you want to select the UEFI binary to be booted - via UEFI variables Boot####, BootOrder, and BootNext. You should also - normally enable CMD_BOOTEFI_BOOTMGR so that the command is available. + Provide the GetTime() runtime service at boottime. This service + can be used by an EFI application to read the real time clock. + +config EFI_SET_TIME + bool "SetTime() runtime service" + depends on EFI_GET_TIME + default y if ARCH_QEMU || SANDBOX + help + Provide the SetTime() runtime service at boottime. This service + can be used by an EFI application to adjust the real time clock. + +config EFI_HAVE_RUNTIME_RESET + # bool "Reset runtime service is available" + bool + default y + depends on ARCH_BCM283X || FSL_LAYERSCAPE || PSCI_RESET || \ + SANDBOX || SYSRESET_SBI || SYSRESET_X86 + +endmenu + +menu "UEFI Variables" choice prompt "Store for non-volatile UEFI variables" @@ -172,30 +219,18 @@ config EFI_VAR_BUF_SIZE Minimum 4096, default 131072 -config EFI_GET_TIME - bool "GetTime() runtime service" - depends on DM_RTC - default y +config EFI_PLATFORM_LANG_CODES + string "Language codes supported by firmware" + default "en-US" help - Provide the GetTime() runtime service at boottime. This service - can be used by an EFI application to read the real time clock. + This value is used to initialize the PlatformLangCodes variable. Its + value is a semicolon (;) separated list of language codes in native + RFC 4646 format, e.g. "en-US;de-DE". The first language code is used + to initialize the PlatformLang variable. -config EFI_SET_TIME - bool "SetTime() runtime service" - depends on EFI_GET_TIME - default y if ARCH_QEMU || SANDBOX - help - Provide the SetTime() runtime service at boottime. This service - can be used by an EFI application to adjust the real time clock. +endmenu -config EFI_SCROLL_ON_CLEAR_SCREEN - bool "Avoid overwriting previous output on clear screen" - help - Instead of erasing the screen content when the console screen should - be cleared, emit blank new lines so that previous output is scrolled - out of sight rather than overwritten. On serial consoles this allows - to capture complete boot logs (except for interactive menus etc.) - and can ease debugging related issues. +menu "Capsule support" config EFI_HAVE_CAPSULE_SUPPORT bool @@ -237,6 +272,18 @@ config EFI_CAPSULE_ON_DISK_EARLY executed as part of U-Boot initialisation so that they will surely take place whatever is set to distro_bootcmd. +config EFI_CAPSULE_NAMESPACE_GUID + string "Namespace for dynamic capsule GUIDs" + # v4 UUID as a default for upstream U-Boot boards + default "8c9f137e-91dc-427b-b2d6-b420faebaf2a" + depends on EFI_HAVE_CAPSULE_SUPPORT + help + Define the namespace or "salt" GUID used to generate the per-image + GUIDs. This should be a GUID in the standard 8-4-4-4-12 format. + + Device vendors are expected to generate their own namespace GUID + to avoid conflicts with upstream/community images. + config EFI_CAPSULE_FIRMWARE bool @@ -309,6 +356,10 @@ config EFI_CAPSULE_CRT_FILE embedded in the platform's device tree and used for capsule authentication at the time of capsule update. +endmenu + +menu "UEFI protocol support" + config EFI_DEVICE_PATH_TO_TEXT bool "Device path to text protocol" default y @@ -362,39 +413,6 @@ config EFI_UNICODE_CAPITALIZATION endif -config EFI_LOADER_BOUNCE_BUFFER - bool "EFI Applications use bounce buffers for DMA operations" - help - Some hardware does not support DMA to full 64bit addresses. For this - hardware we can create a bounce buffer so that payloads don't have to - worry about platform details. - -config EFI_PLATFORM_LANG_CODES - string "Language codes supported by firmware" - default "en-US" - help - This value is used to initialize the PlatformLangCodes variable. Its - value is a semicolon (;) separated list of language codes in native - RFC 4646 format, e.g. "en-US;de-DE". The first language code is used - to initialize the PlatformLang variable. - -config EFI_HAVE_RUNTIME_RESET - # bool "Reset runtime service is available" - bool - default y - depends on ARCH_BCM283X || FSL_LAYERSCAPE || PSCI_RESET || \ - SANDBOX || SYSRESET_SBI || SYSRESET_X86 - -config EFI_GRUB_ARM32_WORKAROUND - bool "Workaround for GRUB on 32bit ARM" - default n if ARCH_BCM283X || ARCH_SUNXI || ARCH_QEMU - default y - depends on ARM && !ARM64 - help - GRUB prior to version 2.04 requires U-Boot to disable caches. This - workaround currently is also needed on systems with caches that - cannot be managed via CP15. - config EFI_RNG_PROTOCOL bool "EFI_RNG_PROTOCOL support" depends on DM_RNG @@ -447,29 +465,36 @@ config EFI_LOAD_FILE2_INITRD installed and Linux 5.7+ will ignore any initrd=<ramdisk> command line argument. -config EFI_SECURE_BOOT - bool "Enable EFI secure boot support" - depends on EFI_LOADER && FIT_SIGNATURE - select HASH - select SHA256 - select RSA - select RSA_VERIFY_WITH_PKEY - select IMAGE_SIGN_INFO - select ASYMMETRIC_KEY_TYPE - select ASYMMETRIC_PUBLIC_KEY_SUBTYPE - select X509_CERTIFICATE_PARSER - select PKCS7_MESSAGE_PARSER - select PKCS7_VERIFY - select MSCODE_PARSER - select EFI_SIGNATURE_SUPPORT +config EFI_RISCV_BOOT_PROTOCOL + bool "RISCV_EFI_BOOT_PROTOCOL support" + default y + depends on RISCV help - Select this option to enable EFI secure boot support. - Once SecureBoot mode is enforced, any EFI binary can run only if - it is signed with a trusted key. To do that, you need to install, - at least, PK, KEK and db. + The EFI_RISCV_BOOT_PROTOCOL is used to transfer the boot hart ID + to the next boot stage. It should be enabled as it is meant to + replace the transfer via the device-tree. The latter is not + possible on systems using ACPI. -config EFI_SIGNATURE_SUPPORT - bool +endmenu + +menu "Misc options" +config EFI_LOADER_BOUNCE_BUFFER + bool "EFI Applications use bounce buffers for DMA operations" + depends on ARM64 + help + Some hardware does not support DMA to full 64bit addresses. For this + hardware we can create a bounce buffer so that payloads don't have to + worry about platform details. + +config EFI_GRUB_ARM32_WORKAROUND + bool "Workaround for GRUB on 32bit ARM" + default n if ARCH_BCM283X || ARCH_SUNXI || ARCH_QEMU + default y + depends on ARM && !ARM64 + help + GRUB prior to version 2.04 requires U-Boot to disable caches. This + workaround currently is also needed on systems with caches that + cannot be managed via CP15. config EFI_ESRT bool "Enable the UEFI ESRT generation" @@ -496,15 +521,26 @@ config EFI_EBBR_2_1_CONFORMANCE help Enabling this option adds the EBBRv2.1 conformance entry to the ECPT UEFI table. -config EFI_RISCV_BOOT_PROTOCOL - bool "RISCV_EFI_BOOT_PROTOCOL support" +config EFI_SCROLL_ON_CLEAR_SCREEN + bool "Avoid overwriting previous output on clear screen" + help + Instead of erasing the screen content when the console screen should + be cleared, emit blank new lines so that previous output is scrolled + out of sight rather than overwritten. On serial consoles this allows + to capture complete boot logs (except for interactive menus etc.) + and can ease debugging related issues. + +endmenu + +menu "EFI bootmanager" + +config EFI_BOOTMGR + bool "UEFI Boot Manager" default y - depends on RISCV help - The EFI_RISCV_BOOT_PROTOCOL is used to transfer the boot hart ID - to the next boot stage. It should be enabled as it is meant to - replace the transfer via the device-tree. The latter is not - possible on systems using ACPI. + Select this option if you want to select the UEFI binary to be booted + via UEFI variables Boot####, BootOrder, and BootNext. You should also + normally enable CMD_BOOTEFI_BOOTMGR so that the command is available. config EFI_HTTP_BOOT bool "EFI HTTP Boot support" @@ -514,5 +550,10 @@ config EFI_HTTP_BOOT help Enabling this option adds EFI HTTP Boot support. It allows to directly boot from network. +endmenu endif + +source "lib/efi/Kconfig" + +endmenu diff --git a/lib/efi_loader/efi_bootmgr.c b/lib/efi_loader/efi_bootmgr.c index 589d3996b68..a3aa2b8d1b9 100644 --- a/lib/efi_loader/efi_bootmgr.c +++ b/lib/efi_loader/efi_bootmgr.c @@ -380,14 +380,15 @@ err: } /** - * efi_bootmgr_release_uridp_resource() - cleanup uri device path resource + * efi_bootmgr_release_uridp() - cleanup uri device path resource * * @ctx: event context * Return: status code */ -efi_status_t efi_bootmgr_release_uridp_resource(struct uridp_context *ctx) +efi_status_t efi_bootmgr_release_uridp(struct uridp_context *ctx) { efi_status_t ret = EFI_SUCCESS; + efi_status_t ret2 = EFI_SUCCESS; if (!ctx) return ret; @@ -407,32 +408,33 @@ efi_status_t efi_bootmgr_release_uridp_resource(struct uridp_context *ctx) /* cleanup for PE-COFF image */ if (ctx->mem_handle) { - ret = efi_uninstall_multiple_protocol_interfaces( - ctx->mem_handle, &efi_guid_device_path, ctx->loaded_dp, - NULL); - if (ret != EFI_SUCCESS) + ret2 = efi_uninstall_multiple_protocol_interfaces(ctx->mem_handle, + &efi_guid_device_path, + ctx->loaded_dp, + NULL); + if (ret2 != EFI_SUCCESS) log_err("Uninstall device_path protocol failed\n"); } efi_free_pool(ctx->loaded_dp); free(ctx); - return ret; + return ret == EFI_SUCCESS ? ret2 : ret; } /** - * efi_bootmgr_image_return_notify() - return to efibootmgr callback + * efi_bootmgr_http_return() - return to efibootmgr callback * * @event: the event for which this notification function is registered * @context: event context */ -static void EFIAPI efi_bootmgr_image_return_notify(struct efi_event *event, - void *context) +static void EFIAPI efi_bootmgr_http_return(struct efi_event *event, + void *context) { efi_status_t ret; EFI_ENTRY("%p, %p", event, context); - ret = efi_bootmgr_release_uridp_resource(context); + ret = efi_bootmgr_release_uridp(context); EFI_EXIT(ret); } @@ -533,7 +535,7 @@ static efi_status_t try_load_from_uri_path(struct efi_device_path_uri *uridp, /* create event for cleanup when the image returns or error occurs */ ret = efi_create_event(EVT_NOTIFY_SIGNAL, TPL_CALLBACK, - efi_bootmgr_image_return_notify, ctx, + efi_bootmgr_http_return, ctx, &efi_guid_event_group_return_to_efibootmgr, &event); if (ret != EFI_SUCCESS) { @@ -544,7 +546,7 @@ static efi_status_t try_load_from_uri_path(struct efi_device_path_uri *uridp, return ret; err: - efi_bootmgr_release_uridp_resource(ctx); + efi_bootmgr_release_uridp(ctx); return ret; } diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c index 635088f25a1..a4ea2873038 100644 --- a/lib/efi_loader/efi_capsule.c +++ b/lib/efi_loader/efi_capsule.c @@ -20,6 +20,7 @@ #include <sort.h> #include <sysreset.h> #include <asm/global_data.h> +#include <u-boot/uuid.h> #include <crypto/pkcs7.h> #include <crypto/pkcs7_parser.h> diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index c944c10b216..cea50c748aa 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -181,7 +181,7 @@ static efi_status_t EFIAPI efi_cout_output_string( } pos = buf; utf16_utf8_strcpy(&pos, string); - fputs(stdout, buf); + puts(buf); free(buf); /* diff --git a/lib/efi_loader/efi_device_path.c b/lib/efi_loader/efi_device_path.c index 0f684590f22..9de3b95d073 100644 --- a/lib/efi_loader/efi_device_path.c +++ b/lib/efi_loader/efi_device_path.c @@ -17,7 +17,7 @@ #include <nvme.h> #include <efi_loader.h> #include <part.h> -#include <uuid.h> +#include <u-boot/uuid.h> #include <asm-generic/unaligned.h> #include <linux/compat.h> /* U16_MAX */ diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c index 9886e6897cd..9d017804eea 100644 --- a/lib/efi_loader/efi_dt_fixup.c +++ b/lib/efi_loader/efi_dt_fixup.c @@ -172,7 +172,7 @@ efi_dt_fixup(struct efi_dt_fixup_protocol *this, void *dtb, } fdt_set_totalsize(dtb, *buffer_size); - if (image_setup_libfdt(&img, dtb, NULL)) { + if (image_setup_libfdt(&img, dtb, false)) { log_err("failed to process device tree\n"); ret = EFI_INVALID_PARAMETER; goto out; diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index ba5aba098c0..6650c2b8071 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -246,6 +246,55 @@ void efi_firmware_fill_version_info(struct efi_firmware_image_descriptor *image_ } /** + * efi_gen_capsule_guids - generate GUIDs for the images + * + * Generate the image_type_id for each image in the update_info.images array + * using the first compatible from the device tree and a salt + * UUID defined at build time. + * + * Returns: status code + */ +static efi_status_t efi_gen_capsule_guids(void) +{ + int ret, i; + struct uuid namespace; + const char *compatible; /* Full array including null bytes */ + struct efi_fw_image *fw_array; + + fw_array = update_info.images; + /* Check if we need to run (there are images and we didn't already generate their IDs) */ + if (!update_info.num_images || + memchr_inv(&fw_array[0].image_type_id, 0, sizeof(fw_array[0].image_type_id))) + return EFI_SUCCESS; + + ret = uuid_str_to_bin(CONFIG_EFI_CAPSULE_NAMESPACE_GUID, + (unsigned char *)&namespace, UUID_STR_FORMAT_GUID); + if (ret) { + log_debug("%s: EFI_CAPSULE_NAMESPACE_GUID is invalid: %d\n", __func__, ret); + return EFI_INVALID_PARAMETER; + } + + compatible = ofnode_read_string(ofnode_root(), "compatible"); + if (!compatible) { + log_debug("%s: model or compatible not defined\n", __func__); + return EFI_INVALID_PARAMETER; + } + + for (i = 0; i < update_info.num_images; i++) { + gen_v5_guid(&namespace, + &fw_array[i].image_type_id, + compatible, strlen(compatible), + fw_array[i].fw_name, u16_strlen(fw_array[i].fw_name) * sizeof(uint16_t), + NULL); + + log_debug("Image %ls UUID %pUl\n", fw_array[i].fw_name, + &fw_array[i].image_type_id); + } + + return EFI_SUCCESS; +} + +/** * efi_fill_image_desc_array - populate image descriptor array * @image_info_size: Size of @image_info * @image_info: Image information @@ -272,7 +321,7 @@ static efi_status_t efi_fill_image_desc_array( { size_t total_size; struct efi_fw_image *fw_array; - int i; + int i, ret; total_size = sizeof(*image_info) * update_info.num_images; @@ -283,6 +332,10 @@ static efi_status_t efi_fill_image_desc_array( } *image_info_size = total_size; + ret = efi_gen_capsule_guids(); + if (ret != EFI_SUCCESS) + return ret; + fw_array = update_info.images; *descriptor_count = update_info.num_images; *descriptor_version = EFI_FIRMWARE_IMAGE_DESCRIPTOR_VERSION; diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index 916f43da26c..96f847652ec 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -514,7 +514,7 @@ efi_status_t efi_install_fdt(void *fdt) return EFI_OUT_OF_RESOURCES; } - if (image_setup_libfdt(&img, fdt, NULL)) { + if (image_setup_libfdt(&img, fdt, false)) { log_err("ERROR: failed to process device tree\n"); return EFI_LOAD_ERROR; } diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c index e888c52efe3..f3533f4def3 100644 --- a/lib/efi_loader/efi_variable.c +++ b/lib/efi_loader/efi_variable.c @@ -16,7 +16,7 @@ #include <malloc.h> #include <rtc.h> #include <search.h> -#include <uuid.h> +#include <u-boot/uuid.h> #include <crypto/pkcs7_parser.h> #include <linux/compat.h> #include <u-boot/crc.h> diff --git a/lib/efi_loader/helloworld.c b/lib/efi_loader/helloworld.c index bd72822c0b7..586177de0c8 100644 --- a/lib/efi_loader/helloworld.c +++ b/lib/efi_loader/helloworld.c @@ -2,6 +2,9 @@ /* * Hello world EFI application * + * Copyright (c) 2016 Google, Inc + * Written by Simon Glass <sjg@chromium.org> + * * Copyright 2020, Heinrich Schuchardt <xypron.glpk@gmx.de> * * This test program is used to test the invocation of an EFI application. |