diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 3 | ||||
-rw-r--r-- | lib/acpi/acpi_dp.c | 2 | ||||
-rw-r--r-- | lib/acpi/acpigen.c | 2 | ||||
-rw-r--r-- | lib/ecdsa/ecdsa-libcrypto.c | 2 | ||||
-rw-r--r-- | lib/efi/Kconfig | 5 | ||||
-rw-r--r-- | lib/efi/efi_app.c | 2 | ||||
-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 | 12 | ||||
-rw-r--r-- | lib/efi_loader/efi_console.c | 4 | ||||
-rw-r--r-- | lib/efi_loader/efi_device_path.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_file.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_firmware.c | 55 | ||||
-rw-r--r-- | lib/efi_loader/efi_rng.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_unicode_collation.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/efi_variable.c | 2 | ||||
-rw-r--r-- | lib/efi_loader/helloworld.c | 3 | ||||
-rw-r--r-- | lib/fwu_updates/Kconfig | 1 | ||||
-rw-r--r-- | lib/fwu_updates/fwu.c | 31 | ||||
-rw-r--r-- | lib/fwu_updates/fwu_mtd.c | 2 | ||||
-rw-r--r-- | lib/fwu_updates/fwu_v1.c | 18 | ||||
-rw-r--r-- | lib/fwu_updates/fwu_v2.c | 81 | ||||
-rw-r--r-- | lib/uuid.c | 103 | ||||
-rw-r--r-- | lib/vsprintf.c | 2 |
24 files changed, 399 insertions, 182 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 5f282ecb543..1dd4f271595 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -73,6 +73,7 @@ config HAVE_PRIVATE_LIBGCC config LIB_UUID bool + select SHA1 config RANDOM_UUID bool "GPT Random UUID generation" @@ -1081,8 +1082,6 @@ config SMBIOS_PARSER help A simple parser for SMBIOS data. -source "lib/efi/Kconfig" -source "lib/efi_loader/Kconfig" source "lib/optee/Kconfig" config TEST_FDTDEC diff --git a/lib/acpi/acpi_dp.c b/lib/acpi/acpi_dp.c index 6733809986a..5714acce088 100644 --- a/lib/acpi/acpi_dp.c +++ b/lib/acpi/acpi_dp.c @@ -9,7 +9,7 @@ #include <dm.h> #include <log.h> #include <malloc.h> -#include <uuid.h> +#include <u-boot/uuid.h> #include <acpi/acpigen.h> #include <acpi/acpi_dp.h> #include <dm/acpi.h> diff --git a/lib/acpi/acpigen.c b/lib/acpi/acpigen.c index b95cabb9149..ecff5a50d50 100644 --- a/lib/acpi/acpigen.c +++ b/lib/acpi/acpigen.c @@ -10,7 +10,7 @@ #include <dm.h> #include <log.h> -#include <uuid.h> +#include <u-boot/uuid.h> #include <acpi/acpigen.h> #include <acpi/acpi_device.h> #include <acpi/acpi_table.h> diff --git a/lib/ecdsa/ecdsa-libcrypto.c b/lib/ecdsa/ecdsa-libcrypto.c index 5fa9be10b4b..403dfe0b97c 100644 --- a/lib/ecdsa/ecdsa-libcrypto.c +++ b/lib/ecdsa/ecdsa-libcrypto.c @@ -108,7 +108,7 @@ static size_t ecdsa_key_size_bytes(const EC_KEY *key) const EC_GROUP *group; group = EC_KEY_get0_group(key); - return EC_GROUP_order_bits(group) / 8; + return (EC_GROUP_order_bits(group) + 7) / 8; } static int default_password(char *buf, int size, int rwflag, void *u) diff --git a/lib/efi/Kconfig b/lib/efi/Kconfig index c2b9bb73f71..81ed3e66b34 100644 --- a/lib/efi/Kconfig +++ b/lib/efi/Kconfig @@ -1,3 +1,6 @@ +menu "U-Boot as UEFI application" + depends on X86 + config EFI bool "Support running U-Boot from EFI" depends on X86 @@ -72,3 +75,5 @@ config EFI_RAM_SIZE use. U-Boot allocates this from EFI on start-up (along with a few other smaller amounts) and it can never be increased after that. It is used as the RAM size in with U-Boot. + +endmenu diff --git a/lib/efi/efi_app.c b/lib/efi/efi_app.c index 88332c3c910..9b94a93ee4f 100644 --- a/lib/efi/efi_app.c +++ b/lib/efi/efi_app.c @@ -17,7 +17,7 @@ #include <init.h> #include <malloc.h> #include <sysreset.h> -#include <uuid.h> +#include <u-boot/uuid.h> #include <asm/global_data.h> #include <linux/err.h> #include <linux/types.h> 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..f8a4a7c6ef4 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> @@ -563,9 +564,14 @@ static efi_status_t efi_capsule_update_firmware( bool fw_accept_os; if (IS_ENABLED(CONFIG_FWU_MULTI_BANK_UPDATE)) { - if (fwu_empty_capsule_checks_pass() && - fwu_empty_capsule(capsule_data)) - return fwu_empty_capsule_process(capsule_data); + if (fwu_empty_capsule(capsule_data)) { + if (fwu_empty_capsule_checks_pass()) { + return fwu_empty_capsule_process(capsule_data); + } else { + log_err("FWU empty capsule checks failed. Cannot start update\n"); + return EFI_INVALID_PARAMETER; + } + } if (!fwu_update_checks_pass()) { log_err("FWU checks failed. Cannot start update\n"); diff --git a/lib/efi_loader/efi_console.c b/lib/efi_loader/efi_console.c index c944c10b216..9d9f786a6db 100644 --- a/lib/efi_loader/efi_console.c +++ b/lib/efi_loader/efi_console.c @@ -100,7 +100,7 @@ static int term_get_char(s32 *c) } /** - * Receive and parse a reply from the terminal. + * term_read_reply() - receive and parse a reply from the terminal * * @n: array of return values * @num: number of return values expected @@ -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_file.c b/lib/efi_loader/efi_file.c index 222001d6a3b..c92d8ccf004 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -295,7 +295,7 @@ out: } /** - * efi_file_open_() + * efi_file_open() - open file synchronously * * This function implements the Open service of the File Protocol. * See the UEFI spec for details. 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_rng.c b/lib/efi_loader/efi_rng.c index 9bad7ed6931..4734f95eee1 100644 --- a/lib/efi_loader/efi_rng.c +++ b/lib/efi_loader/efi_rng.c @@ -91,7 +91,7 @@ back: } /** - * rng_getrng() - get random value + * getrng() - get random value * * This function implement the GetRng() service of the EFI random number * generator protocol. See the UEFI spec for details. diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index 627bb9123cf..d48700a352b 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -266,7 +266,7 @@ static void EFIAPI efi_fat_to_str(struct efi_unicode_collation_protocol *this, } /** - * efi_fat_to_str() - convert a utf-16 string to legal characters for a FAT + * efi_str_to_fat() - convert a utf-16 string to legal characters for a FAT * file name in an OEM code page * * @this: unicode collation protocol instance 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. diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig index 51b7fbbefd3..a722107c129 100644 --- a/lib/fwu_updates/Kconfig +++ b/lib/fwu_updates/Kconfig @@ -40,6 +40,7 @@ config FWU_MDATA_V1 config FWU_MDATA_V2 bool "Enable support FWU Metadata version 2" + depends on !FWU_MDATA_V1 help The FWU specification supports two versions of the metadata structure. This option enables support for FWU diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c index c7fc8987beb..7f085a0211f 100644 --- a/lib/fwu_updates/fwu.c +++ b/lib/fwu_updates/fwu.c @@ -28,6 +28,31 @@ enum { IMAGE_ACCEPT_CLEAR, }; +/** + * fwu_bank_accepted() - Has the bank been accepted + * @data: Version agnostic FWU metadata information + * @bank: Update bank to check + * + * Check in the given bank if all the images have been accepted. + * + * Return: true if all images accepted, false otherwise + */ +bool fwu_bank_accepted(struct fwu_data *data, uint32_t bank) +{ + u32 i; + struct fwu_image_entry *img_entry; + struct fwu_image_bank_info *img_bank_info; + + img_entry = &data->fwu_images[0]; + for (i = 0; i < CONFIG_FWU_NUM_IMAGES_PER_BANK; i++) { + img_bank_info = &img_entry[i].img_bank_info[bank]; + if (!img_bank_info->accepted) + return false; + } + + return true; +} + static int trial_counter_update(u16 *trial_state_ctr) { bool delete; @@ -88,6 +113,8 @@ static int fwu_trial_count_update(void) ret = fwu_revert_boot_index(); if (ret) log_err("Unable to revert active_index\n"); + + trial_counter_update(NULL); ret = 1; } else { log_info("Trial State count: attempt %d out of %d\n", @@ -737,8 +764,8 @@ static int fwu_boottime_checks(void) return 0; in_trial = in_trial_state(); - if (!in_trial || (ret = fwu_trial_count_update()) > 0) - ret = trial_counter_update(NULL); + + ret = in_trial ? fwu_trial_count_update() : trial_counter_update(NULL); if (!ret) boottime_check = 1; diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index c14203b9dd3..554723046f6 100644 --- a/lib/fwu_updates/fwu_mtd.c +++ b/lib/fwu_updates/fwu_mtd.c @@ -10,7 +10,7 @@ #include <log.h> #include <malloc.h> #include <mtd.h> -#include <uuid.h> +#include <u-boot/uuid.h> #include <stdio.h> #include <dm/ofnode.h> diff --git a/lib/fwu_updates/fwu_v1.c b/lib/fwu_updates/fwu_v1.c index efb8d515008..c311a8857a6 100644 --- a/lib/fwu_updates/fwu_v1.c +++ b/lib/fwu_updates/fwu_v1.c @@ -52,11 +52,14 @@ static void fwu_data_init(void) memcpy(dst_img_info, src_img_info, image_info_size); } -static int fwu_trial_state_update(bool trial_state) +static int fwu_trial_state_update(bool trial_state, uint32_t bank) { int ret; struct fwu_data *data = fwu_get_data(); + if (!trial_state && !fwu_bank_accepted(data, bank)) + return 0; + if (trial_state) { ret = fwu_trial_state_ctr_start(); if (ret) @@ -112,9 +115,9 @@ void fwu_populate_mdata_image_info(struct fwu_data *data) * Return: 0 if OK, -ve on error */ int fwu_state_machine_updates(bool trial_state, - __maybe_unused uint32_t update_index) + uint32_t update_index) { - return fwu_trial_state_update(trial_state); + return fwu_trial_state_update(trial_state, update_index); } /** @@ -146,6 +149,7 @@ int fwu_init(void) { int ret; uint32_t mdata_size; + struct fwu_mdata mdata = {0}; fwu_get_mdata_size(&mdata_size); @@ -157,10 +161,16 @@ int fwu_init(void) * Now read the entire structure, both copies, and * validate that the copies. */ - ret = fwu_get_mdata(NULL); + ret = fwu_get_mdata(&mdata); if (ret) return ret; + if (mdata.version != 0x1) { + log_err("FWU metadata version %u. Expected value of %u\n", + mdata.version, FWU_MDATA_VERSION); + return -EINVAL; + } + fwu_data_init(); return 0; diff --git a/lib/fwu_updates/fwu_v2.c b/lib/fwu_updates/fwu_v2.c index 108bc9bb4ac..ce46904ff2e 100644 --- a/lib/fwu_updates/fwu_v2.c +++ b/lib/fwu_updates/fwu_v2.c @@ -10,6 +10,9 @@ #include <linux/types.h> #define FWU_MDATA_VERSION 0x2U +#define FWU_IMG_DESC_OFFSET 0x20U + +static struct fwu_mdata g_mdata; static inline struct fwu_fw_store_desc *fwu_get_fw_desc(struct fwu_mdata *mdata) { @@ -58,24 +61,6 @@ static int fwu_mdata_sanity_checks(void) struct fwu_data *data = fwu_get_data(); struct fwu_mdata *mdata = data->fwu_mdata; - if (mdata->version != FWU_MDATA_VERSION) { - log_err("FWU metadata version %u. Expected value of %u\n", - mdata->version, FWU_MDATA_VERSION); - return -EINVAL; - } - - if (!mdata->desc_offset) { - log_err("No image information provided with the Metadata. "); - log_err("Image information expected in the metadata\n"); - return -EINVAL; - } - - if (mdata->desc_offset != 0x20) { - log_err("Descriptor Offset(0x%x) in the FWU Metadata not equal to 0x20\n", - mdata->desc_offset); - return -EINVAL; - } - num_banks = fwu_get_fw_desc(mdata)->num_banks; num_images = fwu_get_fw_desc(mdata)->num_images; @@ -100,6 +85,9 @@ static int fwu_bank_state_update(bool trial_state, uint32_t bank) struct fwu_data *data = fwu_get_data(); struct fwu_mdata *mdata = data->fwu_mdata; + if (!trial_state && !fwu_bank_accepted(data, bank)) + return 0; + mdata->bank_state[bank] = data->bank_state[bank] = trial_state ? FWU_BANK_VALID : FWU_BANK_ACCEPTED; @@ -127,6 +115,35 @@ static int fwu_trial_state_start(uint update_index) return 0; } +static bool fwu_get_mdata_mandatory(uint part) +{ + int ret = 0; + struct udevice *fwu_dev = fwu_get_dev(); + + memset(&g_mdata, 0, sizeof(struct fwu_mdata)); + + ret = fwu_read_mdata(fwu_dev, &g_mdata, + part == PRIMARY_PART ? true : false, + sizeof(struct fwu_mdata)); + if (ret) + return false; + + if (g_mdata.version != FWU_MDATA_VERSION) { + log_err("FWU partition %u has metadata version %u. Expected value of %u\n", + part, g_mdata.version, FWU_MDATA_VERSION); + return false; + } + + if (g_mdata.desc_offset != FWU_IMG_DESC_OFFSET) { + log_err("Descriptor Offset(0x%x) in the FWU Metadata partition %u not equal to 0x20\n", + g_mdata.desc_offset, part); + log_err("Image information expected in the metadata\n"); + return false; + } + + return true; +} + /** * fwu_populate_mdata_image_info() - Populate the image information * of the metadata @@ -187,24 +204,14 @@ int fwu_state_machine_updates(bool trial_state, uint32_t update_index) */ int fwu_get_mdata_size(uint32_t *mdata_size) { - int ret = 0; - struct fwu_mdata mdata = { 0 }; struct fwu_data *data = fwu_get_data(); - struct udevice *fwu_dev = fwu_get_dev(); if (data->metadata_size) { *mdata_size = data->metadata_size; return 0; } - ret = fwu_read_mdata(fwu_dev, &mdata, 1, - sizeof(struct fwu_mdata)); - if (ret) { - log_err("FWU metadata read failed\n"); - return ret; - } - - *mdata_size = mdata.metadata_size; + *mdata_size = g_mdata.metadata_size; if (!*mdata_size) return -EINVAL; @@ -224,21 +231,23 @@ int fwu_get_mdata_size(uint32_t *mdata_size) int fwu_init(void) { int ret; - struct fwu_mdata mdata = { 0 }; - struct udevice *fwu_dev = fwu_get_dev(); /* * First we read only the top level structure * and get the size of the complete structure. + * Try reading the first partition first, if + * that does not work, try the secondary + * partition. The idea is, if one of the + * partitions is corrupted, it should be restored + * from the intact partition. */ - ret = fwu_read_mdata(fwu_dev, &mdata, 1, - sizeof(struct fwu_mdata)); - if (ret) { + if (!fwu_get_mdata_mandatory(PRIMARY_PART) && + !fwu_get_mdata_mandatory(SECONDARY_PART)) { log_err("FWU metadata read failed\n"); - return ret; + return -1; } - ret = fwu_mdata_copies_allocate(mdata.metadata_size); + ret = fwu_mdata_copies_allocate(g_mdata.metadata_size); if (ret) return ret; diff --git a/lib/uuid.c b/lib/uuid.c index dfa2320ba26..11b86ffb02e 100644 --- a/lib/uuid.c +++ b/lib/uuid.c @@ -7,21 +7,35 @@ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> */ -#define LOG_CATEGOT LOGC_CORE - +#ifndef USE_HOSTCC #include <command.h> #include <efi_api.h> #include <env.h> #include <rand.h> #include <time.h> -#include <uuid.h> -#include <linux/ctype.h> -#include <errno.h> #include <asm/io.h> #include <part_efi.h> #include <malloc.h> #include <dm/uclass.h> #include <rng.h> +#include <linux/ctype.h> +#include <hexdump.h> +#else +#include <stdarg.h> +#include <stdint.h> +#include <eficapsule.h> +#include <ctype.h> +#endif +#include <linux/types.h> +#include <errno.h> +#include <linux/kconfig.h> +#include <u-boot/uuid.h> +#include <u-boot/sha1.h> + +#ifdef USE_HOSTCC +/* polyfill hextoul to avoid pulling in strto.c */ +#define hextoul(cp, endp) strtoul(cp, endp, 16) +#endif int uuid_str_valid(const char *uuid) { @@ -51,6 +65,7 @@ static const struct { const char *string; efi_guid_t guid; } list_guid[] = { +#ifndef USE_HOSTCC #ifdef CONFIG_PARTITION_TYPE_GUID {"system", PARTITION_SYSTEM_GUID}, {"mbr", LEGACY_MBR_PARTITION_GUID}, @@ -231,6 +246,7 @@ static const struct { { "EFI_MEM_STATUS_CODE_REC", EFI_MEM_STATUS_CODE_REC }, { "EFI_GUID_EFI_ACPI1", EFI_GUID_EFI_ACPI1 }, #endif +#endif /* !USE_HOSTCC */ }; int uuid_guid_get_bin(const char *guid_str, unsigned char *guid_bin) @@ -266,7 +282,6 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, uint64_t tmp64; if (!uuid_str_valid(uuid_str)) { - log_debug("not valid\n"); #ifdef CONFIG_PARTITION_TYPE_GUID if (!uuid_guid_get_bin(uuid_str, uuid_bin)) return 0; @@ -297,7 +312,7 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, tmp16 = cpu_to_be16(hextoul(uuid_str + 19, NULL)); memcpy(uuid_bin + 8, &tmp16, 2); - tmp64 = cpu_to_be64(simple_strtoull(uuid_str + 24, NULL, 16)); + tmp64 = cpu_to_be64(hextoul(uuid_str + 24, NULL)); memcpy(uuid_bin + 10, (char *)&tmp64 + 2, 6); return 0; @@ -305,9 +320,9 @@ int uuid_str_to_bin(const char *uuid_str, unsigned char *uuid_bin, int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin) { - u16 tmp16; - u32 tmp32; - u64 tmp64; + uint16_t tmp16; + uint32_t tmp32; + uint64_t tmp64; if (!uuid_str_valid(uuid_str) || !uuid_bin) return -EINVAL; @@ -324,7 +339,7 @@ int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin) tmp16 = cpu_to_le16(hextoul(uuid_str + 19, NULL)); memcpy(uuid_bin + 8, &tmp16, 2); - tmp64 = cpu_to_le64(simple_strtoull(uuid_str + 24, NULL, 16)); + tmp64 = cpu_to_le64(hextoul(uuid_str + 24, NULL)); memcpy(uuid_bin + 10, &tmp64, 6); return 0; @@ -333,11 +348,11 @@ int uuid_str_to_le_bin(const char *uuid_str, unsigned char *uuid_bin) void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str, int str_format) { - const u8 uuid_char_order[UUID_BIN_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8, + const uint8_t uuid_char_order[UUID_BIN_LEN] = {0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15}; - const u8 guid_char_order[UUID_BIN_LEN] = {3, 2, 1, 0, 5, 4, 7, 6, 8, + const uint8_t guid_char_order[UUID_BIN_LEN] = {3, 2, 1, 0, 5, 4, 7, 6, 8, 9, 10, 11, 12, 13, 14, 15}; - const u8 *char_order; + const uint8_t *char_order; const char *format; int i; @@ -369,6 +384,57 @@ void uuid_bin_to_str(const unsigned char *uuid_bin, char *uuid_str, } } +static void configure_uuid(struct uuid *uuid, unsigned char version) +{ + uint16_t tmp; + + /* Configure variant/version bits */ + tmp = be16_to_cpu(uuid->time_hi_and_version); + tmp = (tmp & ~UUID_VERSION_MASK) | (version << UUID_VERSION_SHIFT); + uuid->time_hi_and_version = cpu_to_be16(tmp); + + uuid->clock_seq_hi_and_reserved &= ~UUID_VARIANT_MASK; + uuid->clock_seq_hi_and_reserved |= (UUID_VARIANT << UUID_VARIANT_SHIFT); +} + +void gen_v5_guid(const struct uuid *namespace, struct efi_guid *guid, ...) +{ + sha1_context ctx; + va_list args; + const uint8_t *data; + uint32_t *tmp32; + uint16_t *tmp16; + uint8_t hash[SHA1_SUM_LEN]; + + sha1_starts(&ctx); + /* Hash the namespace UUID as salt */ + sha1_update(&ctx, (unsigned char *)namespace, UUID_BIN_LEN); + va_start(args, guid); + + while ((data = va_arg(args, const uint8_t *))) { + unsigned int len = va_arg(args, size_t); + + sha1_update(&ctx, data, len); + } + + va_end(args); + sha1_finish(&ctx, hash); + + /* Truncate the hash into output UUID, it is already big endian */ + memcpy(guid, hash, sizeof(*guid)); + + configure_uuid((struct uuid *)guid, 5); + + /* Make little endian */ + tmp32 = (uint32_t *)&guid->b[0]; + *tmp32 = cpu_to_le32(be32_to_cpu(*tmp32)); + tmp16 = (uint16_t *)&guid->b[4]; + *tmp16 = cpu_to_le16(be16_to_cpu(*tmp16)); + tmp16 = (uint16_t *)&guid->b[6]; + *tmp16 = cpu_to_le16(be16_to_cpu(*tmp16)); +} + +#ifndef USE_HOSTCC #if defined(CONFIG_RANDOM_UUID) || defined(CONFIG_CMD_UUID) void gen_rand_uuid(unsigned char *uuid_bin) { @@ -395,13 +461,7 @@ void gen_rand_uuid(unsigned char *uuid_bin) for (i = 0; i < 4; i++) ptr[i] = rand(); - clrsetbits_be16(&uuid->time_hi_and_version, - UUID_VERSION_MASK, - UUID_VERSION << UUID_VERSION_SHIFT); - - clrsetbits_8(&uuid->clock_seq_hi_and_reserved, - UUID_VARIANT_MASK, - UUID_VARIANT << UUID_VARIANT_SHIFT); + configure_uuid(uuid, UUID_VERSION); memcpy(uuid_bin, uuid, 16); } @@ -458,3 +518,4 @@ U_BOOT_CMD(guid, CONFIG_SYS_MAXARGS, 1, do_uuid, ); #endif /* CONFIG_CMD_UUID */ #endif /* CONFIG_RANDOM_UUID || CONFIG_CMD_UUID */ +#endif /* !USE_HOSTCC */ diff --git a/lib/vsprintf.c b/lib/vsprintf.c index cfd1f1914ed..e5802866632 100644 --- a/lib/vsprintf.c +++ b/lib/vsprintf.c @@ -18,7 +18,7 @@ #include <div64.h> #include <hexdump.h> #include <stdarg.h> -#include <uuid.h> +#include <u-boot/uuid.h> #include <stdio.h> #include <vsprintf.h> #include <linux/ctype.h> |