diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/Kconfig | 48 | ||||
-rw-r--r-- | lib/Makefile | 3 | ||||
-rw-r--r-- | lib/acpi/acpi_dp.c | 2 | ||||
-rw-r--r-- | lib/acpi/acpigen.c | 2 | ||||
-rw-r--r-- | lib/alist.c | 158 | ||||
-rw-r--r-- | lib/asm-offsets.c | 2 | ||||
-rw-r--r-- | lib/crypto/Kconfig | 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 | 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 | ||||
-rw-r--r-- | lib/elf.c | 14 | ||||
-rw-r--r-- | lib/fdtdec.c | 1 | ||||
-rw-r--r-- | lib/fwu_updates/fwu_mtd.c | 7 | ||||
-rw-r--r-- | lib/lmb.c | 693 | ||||
-rw-r--r-- | lib/strto.c | 4 | ||||
-rw-r--r-- | lib/uuid.c | 103 | ||||
-rw-r--r-- | lib/vsprintf.c | 2 |
26 files changed, 936 insertions, 424 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 2059219a120..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" @@ -403,7 +404,7 @@ config TRACE_EARLY_CALL_DEPTH_LIMIT config TRACE_EARLY_ADDR hex "Address of early trace buffer in U-Boot" depends on TRACE_EARLY - default 0x00100000 + default 0x00200000 help Sets the address of the early trace buffer in U-Boot. This memory must be accessible before relocation. @@ -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 @@ -1102,42 +1101,19 @@ config LMB bool "Enable the logical memory blocks library (lmb)" default y if ARC || ARM || M68K || MICROBLAZE || MIPS || \ NIOS2 || PPC || RISCV || SANDBOX || SH || X86 || XTENSA + select ARCH_MISC_INIT if PPC help - Support the library logical memory blocks. - -config LMB_USE_MAX_REGIONS - bool "Use a common number of memory and reserved regions in lmb lib" - default y - help - Define the number of supported memory regions in the library logical - memory blocks. - This feature allow to reduce the lmb library size by using compiler - optimization when LMB_MEMORY_REGIONS == LMB_RESERVED_REGIONS. - -config LMB_MAX_REGIONS - int "Number of memory and reserved regions in lmb lib" - depends on LMB_USE_MAX_REGIONS - default 16 - help - Define the number of supported regions, memory and reserved, in the - library logical memory blocks. - -config LMB_MEMORY_REGIONS - int "Number of memory regions in lmb lib" - depends on !LMB_USE_MAX_REGIONS - default 8 - help - Define the number of supported memory regions in the library logical - memory blocks. - The minimal value is CONFIG_NR_DRAM_BANKS. + Support the library logical memory blocks. This will require + a malloc() implementation for defining the data structures + needed for maintaining the LMB memory map. -config LMB_RESERVED_REGIONS - int "Number of reserved regions in lmb lib" - depends on !LMB_USE_MAX_REGIONS - default 8 +config SPL_LMB + bool "Enable LMB module for SPL" + depends on SPL && SPL_FRAMEWORK && SPL_SYS_MALLOC help - Define the number of supported reserved regions in the library logical - memory blocks. + Enable support for Logical Memory Block library routines in + SPL. This will require a malloc() implementation for defining + the data structures needed for maintaining the LMB memory map. config PHANDLE_CHECK_SEQ bool "Enable phandle check while getting sequence number" diff --git a/lib/Makefile b/lib/Makefile index e389ad014f8..d300249f57c 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -118,7 +118,7 @@ obj-$(CONFIG_$(SPL_TPL_)OF_LIBFDT) += fdtdec.o fdtdec_common.o obj-y += hang.o obj-y += linux_compat.o obj-y += linux_string.o -obj-$(CONFIG_LMB) += lmb.o +obj-$(CONFIG_$(SPL_TPL_)LMB) += lmb.o obj-y += membuff.o obj-$(CONFIG_REGEX) += slre.o obj-y += string.o @@ -147,6 +147,7 @@ endif obj-$(CONFIG_$(SPL_)OID_REGISTRY) += oid_registry.o obj-y += abuf.o +obj-y += alist.o obj-y += date.o obj-y += rtc-lib.o obj-$(CONFIG_LIB_ELF) += elf.o 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/alist.c b/lib/alist.c new file mode 100644 index 00000000000..b7928cad520 --- /dev/null +++ b/lib/alist.c @@ -0,0 +1,158 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * Handles a contiguous list of pointers which be allocated and freed + * + * Copyright 2023 Google LLC + * Written by Simon Glass <sjg@chromium.org> + */ + +#include <alist.h> +#include <display_options.h> +#include <malloc.h> +#include <stdio.h> +#include <string.h> + +enum { + ALIST_INITIAL_SIZE = 4, /* default size of unsized list */ +}; + +bool alist_init(struct alist *lst, uint obj_size, uint start_size) +{ + /* Avoid realloc for the initial size to help malloc_simple */ + memset(lst, '\0', sizeof(struct alist)); + if (start_size) { + lst->data = calloc(obj_size, start_size); + if (!lst->data) { + lst->flags = ALISTF_FAIL; + return false; + } + lst->alloc = start_size; + } + lst->obj_size = obj_size; + + return true; +} + +void alist_uninit(struct alist *lst) +{ + free(lst->data); + + /* Clear fields to avoid any confusion */ + memset(lst, '\0', sizeof(struct alist)); +} + +/** + * alist_expand_to() - Expand a list to the given size + * + * @lst: List to modify + * @inc_by: Amount to expand to + * Return: true if OK, false if out of memory + */ +static bool alist_expand_to(struct alist *lst, uint new_alloc) +{ + void *new_data; + + if (lst->flags & ALISTF_FAIL) + return false; + + /* avoid using realloc() since it increases code size */ + new_data = malloc(lst->obj_size * new_alloc); + if (!new_data) { + lst->flags |= ALISTF_FAIL; + return false; + } + + memcpy(new_data, lst->data, lst->obj_size * lst->alloc); + free(lst->data); + + memset(new_data + lst->obj_size * lst->alloc, '\0', + lst->obj_size * (new_alloc - lst->alloc)); + lst->alloc = new_alloc; + lst->data = new_data; + + return true; +} + +bool alist_expand_by(struct alist *lst, uint inc_by) +{ + return alist_expand_to(lst, lst->alloc + inc_by); +} + +/** + * alist_expand_min() - Expand to at least the provided size + * + * Expands to the lowest power of two which can incorporate the new size + * + * @lst: alist to expand + * @min_alloc: Minimum new allocated size; if 0 then ALIST_INITIAL_SIZE is used + * Return: true if OK, false if out of memory + */ +static bool alist_expand_min(struct alist *lst, uint min_alloc) +{ + uint new_alloc; + + for (new_alloc = lst->alloc ?: ALIST_INITIAL_SIZE; + new_alloc < min_alloc;) + new_alloc *= 2; + + return alist_expand_to(lst, new_alloc); +} + +const void *alist_get_ptr(const struct alist *lst, uint index) +{ + if (index >= lst->count) + return NULL; + + return lst->data + index * lst->obj_size; +} + +void *alist_ensure_ptr(struct alist *lst, uint index) +{ + uint minsize = index + 1; + void *ptr; + + if (index >= lst->alloc && !alist_expand_min(lst, minsize)) + return NULL; + + ptr = lst->data + index * lst->obj_size; + if (minsize >= lst->count) + lst->count = minsize; + + return ptr; +} + +void *alist_add_placeholder(struct alist *lst) +{ + return alist_ensure_ptr(lst, lst->count); +} + +void *alist_add_ptr(struct alist *lst, void *obj) +{ + void *ptr; + + ptr = alist_add_placeholder(lst); + if (!ptr) + return NULL; + memcpy(ptr, obj, lst->obj_size); + + return ptr; +} + +void *alist_uninit_move_ptr(struct alist *alist, size_t *countp) +{ + void *ptr; + + if (countp) + *countp = alist->count; + if (!alist->count) { + alist_uninit(alist); + return NULL; + } + + ptr = alist->data; + + /* Clear everything out so there is no record of the data */ + alist_init(alist, alist->obj_size, 0); + + return ptr; +} diff --git a/lib/asm-offsets.c b/lib/asm-offsets.c index 4e2dbda9a71..b6bbcbf76ca 100644 --- a/lib/asm-offsets.c +++ b/lib/asm-offsets.c @@ -44,7 +44,9 @@ int main(void) DEFINE(GD_NEW_GD, offsetof(struct global_data, new_gd)); +#if CONFIG_IS_ENABLED(ENV_SUPPORT) DEFINE(GD_ENV_ADDR, offsetof(struct global_data, env_addr)); +#endif return 0; } diff --git a/lib/crypto/Kconfig b/lib/crypto/Kconfig index 6e0656ad1c5..742f6d9d4ed 100644 --- a/lib/crypto/Kconfig +++ b/lib/crypto/Kconfig @@ -1,6 +1,6 @@ menuconfig ASYMMETRIC_KEY_TYPE bool "Asymmetric (public-key cryptographic) key Support" - depends on FIT_SIGNATURE + depends on FIT_SIGNATURE || RSA_VERIFY_WITH_PKEY help This option provides support for a key type that holds the data for the asymmetric keys used for public key cryptographic operations such 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..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. diff --git a/lib/elf.c b/lib/elf.c index dc13935e103..e767a42a3b3 100644 --- a/lib/elf.c +++ b/lib/elf.c @@ -86,10 +86,14 @@ unsigned long load_elf64_image_phdr(unsigned long addr) phdr = (Elf64_Phdr *)(addr + (ulong)ehdr->e_phoff); /* Load each program header */ - for (i = 0; i < ehdr->e_phnum; ++i) { + for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) { void *dst = (void *)(ulong)phdr->p_paddr; void *src = (void *)addr + phdr->p_offset; + /* Only load PT_LOAD program header */ + if (phdr->p_type != PT_LOAD) + continue; + debug("Loading phdr %i to 0x%p (%lu bytes)\n", i, dst, (ulong)phdr->p_filesz); if (phdr->p_filesz) @@ -99,7 +103,6 @@ unsigned long load_elf64_image_phdr(unsigned long addr) phdr->p_memsz - phdr->p_filesz); flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); - ++phdr; } if (ehdr->e_machine == EM_PPC64 && (ehdr->e_flags & @@ -201,10 +204,14 @@ unsigned long load_elf_image_phdr(unsigned long addr) phdr = (Elf32_Phdr *)(addr + ehdr->e_phoff); /* Load each program header */ - for (i = 0; i < ehdr->e_phnum; ++i) { + for (i = 0; i < ehdr->e_phnum; ++i, ++phdr) { void *dst = (void *)(uintptr_t)phdr->p_paddr; void *src = (void *)addr + phdr->p_offset; + /* Only load PT_LOAD program header */ + if (phdr->p_type != PT_LOAD) + continue; + debug("Loading phdr %i to 0x%p (%i bytes)\n", i, dst, phdr->p_filesz); if (phdr->p_filesz) @@ -214,7 +221,6 @@ unsigned long load_elf_image_phdr(unsigned long addr) phdr->p_memsz - phdr->p_filesz); flush_cache(rounddown((unsigned long)dst, ARCH_DMA_MINALIGN), roundup(phdr->p_memsz, ARCH_DMA_MINALIGN)); - ++phdr; } return ehdr->e_entry; diff --git a/lib/fdtdec.c b/lib/fdtdec.c index 6865f78c70d..5edc8dd2f9f 100644 --- a/lib/fdtdec.c +++ b/lib/fdtdec.c @@ -1685,6 +1685,7 @@ int fdtdec_setup(void) gd->fdt_src = FDTSRC_BLOBLIST; log_debug("Devicetree is in bloblist at %p\n", gd->fdt_blob); + ret = 0; } else { log_debug("No FDT found in bloblist\n"); ret = -ENOENT; diff --git a/lib/fwu_updates/fwu_mtd.c b/lib/fwu_updates/fwu_mtd.c index ccaba3f3115..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> @@ -60,10 +60,7 @@ int fwu_mtd_get_alt_num(efi_guid_t *image_id, u8 *alt_num, if (ret) return -ENOENT; - nalt = 0; - list_for_each_entry(dfu, &dfu_list, list) - nalt++; - + nalt = list_count_nodes(&dfu_list); if (!nalt) { log_warning("No entities in dfu_alt_info\n"); dfu_free_entities(); diff --git a/lib/lmb.c b/lib/lmb.c index 44f98205310..3ed570fb29b 100644 --- a/lib/lmb.c +++ b/lib/lmb.c @@ -6,50 +6,72 @@ * Copyright (C) 2001 Peter Bergner. */ +#include <alist.h> #include <efi_loader.h> #include <image.h> #include <mapmem.h> #include <lmb.h> #include <log.h> #include <malloc.h> +#include <spl.h> #include <asm/global_data.h> #include <asm/sections.h> +#include <linux/kernel.h> +#include <linux/sizes.h> DECLARE_GLOBAL_DATA_PTR; #define LMB_ALLOC_ANYWHERE 0 +#define LMB_ALIST_INITIAL_SIZE 4 -static void lmb_dump_region(struct lmb_region *rgn, char *name) +static struct lmb lmb; + +static void lmb_print_region_flags(enum lmb_flags flags) +{ + u64 bitpos; + const char *flag_str[] = { "none", "no-map", "no-overwrite" }; + + do { + bitpos = flags ? fls(flags) - 1 : 0; + printf("%s", flag_str[bitpos]); + flags &= ~(1ull << bitpos); + puts(flags ? ", " : "\n"); + } while (flags); +} + +static void lmb_dump_region(struct alist *lmb_rgn_lst, char *name) { + struct lmb_region *rgn = lmb_rgn_lst->data; unsigned long long base, size, end; enum lmb_flags flags; int i; - printf(" %s.cnt = 0x%lx / max = 0x%lx\n", name, rgn->cnt, rgn->max); + printf(" %s.count = 0x%x\n", name, lmb_rgn_lst->count); - for (i = 0; i < rgn->cnt; i++) { - base = rgn->region[i].base; - size = rgn->region[i].size; + for (i = 0; i < lmb_rgn_lst->count; i++) { + base = rgn[i].base; + size = rgn[i].size; end = base + size - 1; - flags = rgn->region[i].flags; + flags = rgn[i].flags; - printf(" %s[%d]\t[0x%llx-0x%llx], 0x%08llx bytes flags: %x\n", - name, i, base, end, size, flags); + printf(" %s[%d]\t[0x%llx-0x%llx], 0x%08llx bytes flags: ", + name, i, base, end, size); + lmb_print_region_flags(flags); } } -void lmb_dump_all_force(struct lmb *lmb) +void lmb_dump_all_force(void) { printf("lmb_dump_all:\n"); - lmb_dump_region(&lmb->memory, "memory"); - lmb_dump_region(&lmb->reserved, "reserved"); + lmb_dump_region(&lmb.free_mem, "memory"); + lmb_dump_region(&lmb.used_mem, "reserved"); } -void lmb_dump_all(struct lmb *lmb) +void lmb_dump_all(void) { #ifdef DEBUG - lmb_dump_all_force(lmb); + lmb_dump_all_force(); #endif } @@ -73,111 +95,71 @@ static long lmb_addrs_adjacent(phys_addr_t base1, phys_size_t size1, return 0; } -static long lmb_regions_overlap(struct lmb_region *rgn, unsigned long r1, +static long lmb_regions_overlap(struct alist *lmb_rgn_lst, unsigned long r1, unsigned long r2) { - phys_addr_t base1 = rgn->region[r1].base; - phys_size_t size1 = rgn->region[r1].size; - phys_addr_t base2 = rgn->region[r2].base; - phys_size_t size2 = rgn->region[r2].size; + struct lmb_region *rgn = lmb_rgn_lst->data; + + phys_addr_t base1 = rgn[r1].base; + phys_size_t size1 = rgn[r1].size; + phys_addr_t base2 = rgn[r2].base; + phys_size_t size2 = rgn[r2].size; return lmb_addrs_overlap(base1, size1, base2, size2); } -static long lmb_regions_adjacent(struct lmb_region *rgn, unsigned long r1, + +static long lmb_regions_adjacent(struct alist *lmb_rgn_lst, unsigned long r1, unsigned long r2) { - phys_addr_t base1 = rgn->region[r1].base; - phys_size_t size1 = rgn->region[r1].size; - phys_addr_t base2 = rgn->region[r2].base; - phys_size_t size2 = rgn->region[r2].size; + struct lmb_region *rgn = lmb_rgn_lst->data; + + phys_addr_t base1 = rgn[r1].base; + phys_size_t size1 = rgn[r1].size; + phys_addr_t base2 = rgn[r2].base; + phys_size_t size2 = rgn[r2].size; return lmb_addrs_adjacent(base1, size1, base2, size2); } -static void lmb_remove_region(struct lmb_region *rgn, unsigned long r) +static void lmb_remove_region(struct alist *lmb_rgn_lst, unsigned long r) { unsigned long i; + struct lmb_region *rgn = lmb_rgn_lst->data; - for (i = r; i < rgn->cnt - 1; i++) { - rgn->region[i].base = rgn->region[i + 1].base; - rgn->region[i].size = rgn->region[i + 1].size; - rgn->region[i].flags = rgn->region[i + 1].flags; + for (i = r; i < lmb_rgn_lst->count - 1; i++) { + rgn[i].base = rgn[i + 1].base; + rgn[i].size = rgn[i + 1].size; + rgn[i].flags = rgn[i + 1].flags; } - rgn->cnt--; + lmb_rgn_lst->count--; } /* Assumption: base addr of region 1 < base addr of region 2 */ -static void lmb_coalesce_regions(struct lmb_region *rgn, unsigned long r1, +static void lmb_coalesce_regions(struct alist *lmb_rgn_lst, unsigned long r1, unsigned long r2) { - rgn->region[r1].size += rgn->region[r2].size; - lmb_remove_region(rgn, r2); + struct lmb_region *rgn = lmb_rgn_lst->data; + + rgn[r1].size += rgn[r2].size; + lmb_remove_region(lmb_rgn_lst, r2); } /*Assumption : base addr of region 1 < base addr of region 2*/ -static void lmb_fix_over_lap_regions(struct lmb_region *rgn, unsigned long r1, - unsigned long r2) +static void lmb_fix_over_lap_regions(struct alist *lmb_rgn_lst, + unsigned long r1, unsigned long r2) { - phys_addr_t base1 = rgn->region[r1].base; - phys_size_t size1 = rgn->region[r1].size; - phys_addr_t base2 = rgn->region[r2].base; - phys_size_t size2 = rgn->region[r2].size; + struct lmb_region *rgn = lmb_rgn_lst->data; + + phys_addr_t base1 = rgn[r1].base; + phys_size_t size1 = rgn[r1].size; + phys_addr_t base2 = rgn[r2].base; + phys_size_t size2 = rgn[r2].size; if (base1 + size1 > base2 + size2) { printf("This will not be a case any time\n"); return; } - rgn->region[r1].size = base2 + size2 - base1; - lmb_remove_region(rgn, r2); -} - -void lmb_init(struct lmb *lmb) -{ -#if IS_ENABLED(CONFIG_LMB_USE_MAX_REGIONS) - lmb->memory.max = CONFIG_LMB_MAX_REGIONS; - lmb->reserved.max = CONFIG_LMB_MAX_REGIONS; -#else - lmb->memory.max = CONFIG_LMB_MEMORY_REGIONS; - lmb->reserved.max = CONFIG_LMB_RESERVED_REGIONS; - lmb->memory.region = lmb->memory_regions; - lmb->reserved.region = lmb->reserved_regions; -#endif - lmb->memory.cnt = 0; - lmb->reserved.cnt = 0; -} - -void arch_lmb_reserve_generic(struct lmb *lmb, ulong sp, ulong end, ulong align) -{ - ulong bank_end; - int bank; - - /* - * Reserve memory from aligned address below the bottom of U-Boot stack - * until end of U-Boot area using LMB to prevent U-Boot from overwriting - * that memory. - */ - debug("## Current stack ends at 0x%08lx ", sp); - - /* adjust sp by 4K to be safe */ - sp -= align; - for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { - if (!gd->bd->bi_dram[bank].size || - sp < gd->bd->bi_dram[bank].start) - continue; - /* Watch out for RAM at end of address space! */ - bank_end = gd->bd->bi_dram[bank].start + - gd->bd->bi_dram[bank].size - 1; - if (sp > bank_end) - continue; - if (bank_end > end) - bank_end = end - 1; - - lmb_reserve(lmb, sp, bank_end - sp + 1); - - if (gd->flags & GD_FLG_SKIP_RELOC) - lmb_reserve(lmb, (phys_addr_t)(uintptr_t)_start, gd->mon_len); - - break; - } + rgn[r1].size = base2 + size2 - base1; + lmb_remove_region(lmb_rgn_lst, r2); } /** @@ -186,10 +168,9 @@ void arch_lmb_reserve_generic(struct lmb *lmb, ulong sp, ulong end, ulong align) * Add reservations for all EFI memory areas that are not * EFI_CONVENTIONAL_MEMORY. * - * @lmb: lmb environment * Return: 0 on success, 1 on failure */ -static __maybe_unused int efi_lmb_reserve(struct lmb *lmb) +static __maybe_unused int efi_lmb_reserve(void) { struct efi_mem_desc *memmap = NULL, *map; efi_uintn_t i, map_size = 0; @@ -201,8 +182,7 @@ static __maybe_unused int efi_lmb_reserve(struct lmb *lmb) for (i = 0, map = memmap; i < map_size / sizeof(*map); ++map, ++i) { if (map->type != EFI_CONVENTIONAL_MEMORY) { - lmb_reserve_flags(lmb, - map_to_sysmem((void *)(uintptr_t) + lmb_reserve_flags(map_to_sysmem((void *)(uintptr_t) map->physical_start), map->num_pages * EFI_PAGE_SIZE, map->type == EFI_RESERVED_MEMORY_TYPE @@ -214,64 +194,199 @@ static __maybe_unused int efi_lmb_reserve(struct lmb *lmb) return 0; } -static void lmb_reserve_common(struct lmb *lmb, void *fdt_blob) +static void lmb_reserve_uboot_region(void) +{ + int bank; + ulong end, bank_end; + phys_addr_t rsv_start; + + rsv_start = gd->start_addr_sp - CONFIG_STACK_SIZE; + end = gd->ram_top; + + /* + * Reserve memory from aligned address below the bottom of U-Boot stack + * until end of RAM area to prevent LMB from overwriting that memory. + */ + debug("## Current stack ends at 0x%08lx ", (ulong)rsv_start); + + /* adjust sp by 16K to be safe */ + rsv_start -= SZ_16K; + for (bank = 0; bank < CONFIG_NR_DRAM_BANKS; bank++) { + if (!gd->bd->bi_dram[bank].size || + rsv_start < gd->bd->bi_dram[bank].start) + continue; + /* Watch out for RAM at end of address space! */ + bank_end = gd->bd->bi_dram[bank].start + + gd->bd->bi_dram[bank].size - 1; + if (rsv_start > bank_end) + continue; + if (bank_end > end) + bank_end = end - 1; + + lmb_reserve_flags(rsv_start, bank_end - rsv_start + 1, + LMB_NOOVERWRITE); + + if (gd->flags & GD_FLG_SKIP_RELOC) + lmb_reserve_flags((phys_addr_t)(uintptr_t)_start, + gd->mon_len, LMB_NOOVERWRITE); + + break; + } +} + +static void lmb_reserve_common(void *fdt_blob) { - arch_lmb_reserve(lmb); - board_lmb_reserve(lmb); + lmb_reserve_uboot_region(); if (CONFIG_IS_ENABLED(OF_LIBFDT) && fdt_blob) - boot_fdt_add_mem_rsv_regions(lmb, fdt_blob); + boot_fdt_add_mem_rsv_regions(fdt_blob); if (CONFIG_IS_ENABLED(EFI_LOADER)) - efi_lmb_reserve(lmb); + efi_lmb_reserve(); +} + +static __maybe_unused void lmb_reserve_common_spl(void) +{ + phys_addr_t rsv_start; + phys_size_t rsv_size; + + /* + * Assume a SPL stack of 16KB. This must be + * more than enough for the SPL stage. + */ + if (IS_ENABLED(CONFIG_SPL_STACK_R_ADDR)) { + rsv_start = gd->start_addr_sp - 16384; + rsv_size = 16384; + lmb_reserve_flags(rsv_start, rsv_size, LMB_NOOVERWRITE); + } + + if (IS_ENABLED(CONFIG_SPL_SEPARATE_BSS)) { + /* Reserve the bss region */ + rsv_start = (phys_addr_t)(uintptr_t)__bss_start; + rsv_size = (phys_addr_t)(uintptr_t)__bss_end - + (phys_addr_t)(uintptr_t)__bss_start; + lmb_reserve_flags(rsv_start, rsv_size, LMB_NOOVERWRITE); + } } -/* Initialize the struct, add memory and call arch/board reserve functions */ -void lmb_init_and_reserve(struct lmb *lmb, struct bd_info *bd, void *fdt_blob) +/** + * lmb_add_memory() - Add memory range for LMB allocations + * + * Add the entire available memory range to the pool of memory that + * can be used by the LMB module for allocations. + * + * Return: None + */ +void lmb_add_memory(void) { int i; + phys_size_t size; + phys_addr_t rgn_top; + u64 ram_top = gd->ram_top; + struct bd_info *bd = gd->bd; - lmb_init(lmb); + /* Assume a 4GB ram_top if not defined */ + if (!ram_top) + ram_top = 0x100000000ULL; for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) { - if (bd->bi_dram[i].size) { - lmb_add(lmb, bd->bi_dram[i].start, - bd->bi_dram[i].size); + size = bd->bi_dram[i].size; + if (size) { + if (bd->bi_dram[i].start > ram_top) + continue; + + rgn_top = bd->bi_dram[i].start + + bd->bi_dram[i].size; + + if (rgn_top > ram_top) + size -= rgn_top - ram_top; + + lmb_add(bd->bi_dram[i].start, size); } } - - lmb_reserve_common(lmb, fdt_blob); } -/* Initialize the struct, add memory and call arch/board reserve functions */ -void lmb_init_and_reserve_range(struct lmb *lmb, phys_addr_t base, - phys_size_t size, void *fdt_blob) +static long lmb_resize_regions(struct alist *lmb_rgn_lst, + unsigned long idx_start, + phys_addr_t base, phys_size_t size) { - lmb_init(lmb); - lmb_add(lmb, base, size); - lmb_reserve_common(lmb, fdt_blob); + phys_size_t rgnsize; + unsigned long rgn_cnt, idx, idx_end; + phys_addr_t rgnbase, rgnend; + phys_addr_t mergebase, mergeend; + struct lmb_region *rgn = lmb_rgn_lst->data; + + rgn_cnt = 0; + idx = idx_start; + idx_end = idx_start; + + /* + * First thing to do is to identify how many regions + * the requested region overlaps. + * If the flags match, combine all these overlapping + * regions into a single region, and remove the merged + * regions. + */ + while (idx <= lmb_rgn_lst->count - 1) { + rgnbase = rgn[idx].base; + rgnsize = rgn[idx].size; + + if (lmb_addrs_overlap(base, size, rgnbase, + rgnsize)) { + if (rgn[idx].flags != LMB_NONE) + return -1; + rgn_cnt++; + idx_end = idx; + } + idx++; + } + + /* The merged region's base and size */ + rgnbase = rgn[idx_start].base; + mergebase = min(base, rgnbase); + rgnend = rgn[idx_end].base + rgn[idx_end].size; + mergeend = max(rgnend, (base + size)); + + rgn[idx_start].base = mergebase; + rgn[idx_start].size = mergeend - mergebase; + + /* Now remove the merged regions */ + while (--rgn_cnt) + lmb_remove_region(lmb_rgn_lst, idx_start + 1); + + return 0; } -/* This routine called with relocation disabled. */ -static long lmb_add_region_flags(struct lmb_region *rgn, phys_addr_t base, +/** + * lmb_add_region_flags() - Add an lmb region to the given list + * @lmb_rgn_lst: LMB list to which region is to be added(free/used) + * @base: Start address of the region + * @size: Size of the region to be added + * @flags: Attributes of the LMB region + * + * Add a region of memory to the list. If the region does not exist, add + * it to the list. Depending on the attributes of the region to be added, + * the function might resize an already existing region or coalesce two + * adjacent regions. + * + * + * Returns: 0 if the region addition successful, -1 on failure + */ +static long lmb_add_region_flags(struct alist *lmb_rgn_lst, phys_addr_t base, phys_size_t size, enum lmb_flags flags) { unsigned long coalesced = 0; - long adjacent, i; + long ret, i; + struct lmb_region *rgn = lmb_rgn_lst->data; - if (rgn->cnt == 0) { - rgn->region[0].base = base; - rgn->region[0].size = size; - rgn->region[0].flags = flags; - rgn->cnt = 1; - return 0; - } + if (alist_err(lmb_rgn_lst)) + return -1; /* First try and coalesce this LMB with another. */ - for (i = 0; i < rgn->cnt; i++) { - phys_addr_t rgnbase = rgn->region[i].base; - phys_size_t rgnsize = rgn->region[i].size; - phys_size_t rgnflags = rgn->region[i].flags; + for (i = 0; i < lmb_rgn_lst->count; i++) { + phys_addr_t rgnbase = rgn[i].base; + phys_size_t rgnsize = rgn[i].size; + phys_size_t rgnflags = rgn[i].flags; phys_addr_t end = base + size - 1; phys_addr_t rgnend = rgnbase + rgnsize - 1; if (rgnbase <= base && end <= rgnend) { @@ -282,119 +397,127 @@ static long lmb_add_region_flags(struct lmb_region *rgn, phys_addr_t base, return -1; /* regions with new flags */ } - adjacent = lmb_addrs_adjacent(base, size, rgnbase, rgnsize); - if (adjacent > 0) { + ret = lmb_addrs_adjacent(base, size, rgnbase, rgnsize); + if (ret > 0) { if (flags != rgnflags) break; - rgn->region[i].base -= size; - rgn->region[i].size += size; + rgn[i].base -= size; + rgn[i].size += size; coalesced++; break; - } else if (adjacent < 0) { + } else if (ret < 0) { if (flags != rgnflags) break; - rgn->region[i].size += size; + rgn[i].size += size; coalesced++; break; } else if (lmb_addrs_overlap(base, size, rgnbase, rgnsize)) { - /* regions overlap */ - return -1; + if (flags == LMB_NONE) { + ret = lmb_resize_regions(lmb_rgn_lst, i, base, + size); + if (ret < 0) + return -1; + + coalesced++; + break; + } else { + return -1; + } } } - if (i < rgn->cnt - 1 && rgn->region[i].flags == rgn->region[i + 1].flags) { - if (lmb_regions_adjacent(rgn, i, i + 1)) { - lmb_coalesce_regions(rgn, i, i + 1); - coalesced++; - } else if (lmb_regions_overlap(rgn, i, i + 1)) { - /* fix overlapping area */ - lmb_fix_over_lap_regions(rgn, i, i + 1); - coalesced++; + if (lmb_rgn_lst->count && i < lmb_rgn_lst->count - 1) { + rgn = lmb_rgn_lst->data; + if (rgn[i].flags == rgn[i + 1].flags) { + if (lmb_regions_adjacent(lmb_rgn_lst, i, i + 1)) { + lmb_coalesce_regions(lmb_rgn_lst, i, i + 1); + coalesced++; + } else if (lmb_regions_overlap(lmb_rgn_lst, i, i + 1)) { + /* fix overlapping area */ + lmb_fix_over_lap_regions(lmb_rgn_lst, i, i + 1); + coalesced++; + } } } if (coalesced) return coalesced; - if (rgn->cnt >= rgn->max) + + if (alist_full(lmb_rgn_lst) && + !alist_expand_by(lmb_rgn_lst, lmb_rgn_lst->alloc)) return -1; + rgn = lmb_rgn_lst->data; /* Couldn't coalesce the LMB, so add it to the sorted table. */ - for (i = rgn->cnt-1; i >= 0; i--) { - if (base < rgn->region[i].base) { - rgn->region[i + 1].base = rgn->region[i].base; - rgn->region[i + 1].size = rgn->region[i].size; - rgn->region[i + 1].flags = rgn->region[i].flags; + for (i = lmb_rgn_lst->count; i >= 0; i--) { + if (i && base < rgn[i - 1].base) { + rgn[i] = rgn[i - 1]; } else { - rgn->region[i + 1].base = base; - rgn->region[i + 1].size = size; - rgn->region[i + 1].flags = flags; + rgn[i].base = base; + rgn[i].size = size; + rgn[i].flags = flags; break; } } - if (base < rgn->region[0].base) { - rgn->region[0].base = base; - rgn->region[0].size = size; - rgn->region[0].flags = flags; - } - - rgn->cnt++; + lmb_rgn_lst->count++; return 0; } -static long lmb_add_region(struct lmb_region *rgn, phys_addr_t base, +static long lmb_add_region(struct alist *lmb_rgn_lst, phys_addr_t base, phys_size_t size) { - return lmb_add_region_flags(rgn, base, size, LMB_NONE); + return lmb_add_region_flags(lmb_rgn_lst, base, size, LMB_NONE); } /* This routine may be called with relocation disabled. */ -long lmb_add(struct lmb *lmb, phys_addr_t base, phys_size_t size) +long lmb_add(phys_addr_t base, phys_size_t size) { - struct lmb_region *_rgn = &(lmb->memory); + struct alist *lmb_rgn_lst = &lmb.free_mem; - return lmb_add_region(_rgn, base, size); + return lmb_add_region(lmb_rgn_lst, base, size); } -long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size) +long lmb_free(phys_addr_t base, phys_size_t size) { - struct lmb_region *rgn = &(lmb->reserved); + struct lmb_region *rgn; + struct alist *lmb_rgn_lst = &lmb.used_mem; phys_addr_t rgnbegin, rgnend; phys_addr_t end = base + size - 1; int i; rgnbegin = rgnend = 0; /* supress gcc warnings */ - + rgn = lmb_rgn_lst->data; /* Find the region where (base, size) belongs to */ - for (i = 0; i < rgn->cnt; i++) { - rgnbegin = rgn->region[i].base; - rgnend = rgnbegin + rgn->region[i].size - 1; + for (i = 0; i < lmb_rgn_lst->count; i++) { + rgnbegin = rgn[i].base; + rgnend = rgnbegin + rgn[i].size - 1; if ((rgnbegin <= base) && (end <= rgnend)) break; } /* Didn't find the region */ - if (i == rgn->cnt) + if (i == lmb_rgn_lst->count) return -1; /* Check to see if we are removing entire region */ if ((rgnbegin == base) && (rgnend == end)) { - lmb_remove_region(rgn, i); + lmb_remove_region(lmb_rgn_lst, i); return 0; } /* Check to see if region is matching at the front */ if (rgnbegin == base) { - rgn->region[i].base = end + 1; - rgn->region[i].size -= size; + rgn[i].base = end + 1; + rgn[i].size -= size; return 0; } /* Check to see if the region is matching at the end */ if (rgnend == end) { - rgn->region[i].size -= size; + rgn[i].size -= size; return 0; } @@ -402,55 +525,37 @@ long lmb_free(struct lmb *lmb, phys_addr_t base, phys_size_t size) * We need to split the entry - adjust the current one to the * beginging of the hole and add the region after hole. */ - rgn->region[i].size = base - rgn->region[i].base; - return lmb_add_region_flags(rgn, end + 1, rgnend - end, - rgn->region[i].flags); + rgn[i].size = base - rgn[i].base; + return lmb_add_region_flags(lmb_rgn_lst, end + 1, rgnend - end, + rgn[i].flags); } -long lmb_reserve_flags(struct lmb *lmb, phys_addr_t base, phys_size_t size, - enum lmb_flags flags) +long lmb_reserve_flags(phys_addr_t base, phys_size_t size, enum lmb_flags flags) { - struct lmb_region *_rgn = &(lmb->reserved); + struct alist *lmb_rgn_lst = &lmb.used_mem; - return lmb_add_region_flags(_rgn, base, size, flags); + return lmb_add_region_flags(lmb_rgn_lst, base, size, flags); } -long lmb_reserve(struct lmb *lmb, phys_addr_t base, phys_size_t size) +long lmb_reserve(phys_addr_t base, phys_size_t size) { - return lmb_reserve_flags(lmb, base, size, LMB_NONE); + return lmb_reserve_flags(base, size, LMB_NONE); } -static long lmb_overlaps_region(struct lmb_region *rgn, phys_addr_t base, +static long lmb_overlaps_region(struct alist *lmb_rgn_lst, phys_addr_t base, phys_size_t size) { unsigned long i; + struct lmb_region *rgn = lmb_rgn_lst->data; - for (i = 0; i < rgn->cnt; i++) { - phys_addr_t rgnbase = rgn->region[i].base; - phys_size_t rgnsize = rgn->region[i].size; + for (i = 0; i < lmb_rgn_lst->count; i++) { + phys_addr_t rgnbase = rgn[i].base; + phys_size_t rgnsize = rgn[i].size; if (lmb_addrs_overlap(base, size, rgnbase, rgnsize)) break; } - return (i < rgn->cnt) ? i : -1; -} - -phys_addr_t lmb_alloc(struct lmb *lmb, phys_size_t size, ulong align) -{ - return lmb_alloc_base(lmb, size, align, LMB_ALLOC_ANYWHERE); -} - -phys_addr_t lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr) -{ - phys_addr_t alloc; - - alloc = __lmb_alloc_base(lmb, size, align, max_addr); - - if (alloc == 0) - printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", - (ulong)size, (ulong)max_addr); - - return alloc; + return (i < lmb_rgn_lst->count) ? i : -1; } static phys_addr_t lmb_align_down(phys_addr_t addr, phys_size_t size) @@ -458,15 +563,18 @@ static phys_addr_t lmb_align_down(phys_addr_t addr, phys_size_t size) return addr & ~(size - 1); } -phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phys_addr_t max_addr) +static phys_addr_t __lmb_alloc_base(phys_size_t size, ulong align, + phys_addr_t max_addr, enum lmb_flags flags) { long i, rgn; phys_addr_t base = 0; phys_addr_t res_base; + struct lmb_region *lmb_used = lmb.used_mem.data; + struct lmb_region *lmb_memory = lmb.free_mem.data; - for (i = lmb->memory.cnt - 1; i >= 0; i--) { - phys_addr_t lmbbase = lmb->memory.region[i].base; - phys_size_t lmbsize = lmb->memory.region[i].size; + for (i = lmb.free_mem.count - 1; i >= 0; i--) { + phys_addr_t lmbbase = lmb_memory[i].base; + phys_size_t lmbsize = lmb_memory[i].size; if (lmbsize < size) continue; @@ -482,15 +590,16 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy continue; while (base && lmbbase <= base) { - rgn = lmb_overlaps_region(&lmb->reserved, base, size); + rgn = lmb_overlaps_region(&lmb.used_mem, base, size); if (rgn < 0) { /* This area isn't reserved, take it */ - if (lmb_add_region(&lmb->reserved, base, - size) < 0) + if (lmb_add_region_flags(&lmb.used_mem, base, + size, flags) < 0) return 0; return base; } - res_base = lmb->reserved.region[rgn].base; + + res_base = lmb_used[rgn].base; if (res_base < size) break; base = lmb_align_down(res_base - size, align); @@ -499,83 +608,177 @@ phys_addr_t __lmb_alloc_base(struct lmb *lmb, phys_size_t size, ulong align, phy return 0; } -/* - * Try to allocate a specific address range: must be in defined memory but not - * reserved - */ -phys_addr_t lmb_alloc_addr(struct lmb *lmb, phys_addr_t base, phys_size_t size) +phys_addr_t lmb_alloc(phys_size_t size, ulong align) +{ + return lmb_alloc_base(size, align, LMB_ALLOC_ANYWHERE); +} + +phys_addr_t lmb_alloc_base(phys_size_t size, ulong align, phys_addr_t max_addr) +{ + phys_addr_t alloc; + + alloc = __lmb_alloc_base(size, align, max_addr, LMB_NONE); + + if (alloc == 0) + printf("ERROR: Failed to allocate 0x%lx bytes below 0x%lx.\n", + (ulong)size, (ulong)max_addr); + + return alloc; +} + +static phys_addr_t __lmb_alloc_addr(phys_addr_t base, phys_size_t size, + enum lmb_flags flags) { long rgn; + struct lmb_region *lmb_memory = lmb.free_mem.data; /* Check if the requested address is in one of the memory regions */ - rgn = lmb_overlaps_region(&lmb->memory, base, size); + rgn = lmb_overlaps_region(&lmb.free_mem, base, size); if (rgn >= 0) { /* * Check if the requested end address is in the same memory * region we found. */ - if (lmb_addrs_overlap(lmb->memory.region[rgn].base, - lmb->memory.region[rgn].size, + if (lmb_addrs_overlap(lmb_memory[rgn].base, + lmb_memory[rgn].size, base + size - 1, 1)) { /* ok, reserve the memory */ - if (lmb_reserve(lmb, base, size) >= 0) + if (lmb_reserve_flags(base, size, flags) >= 0) return base; } } + return 0; } +/* + * Try to allocate a specific address range: must be in defined memory but not + * reserved + */ +phys_addr_t lmb_alloc_addr(phys_addr_t base, phys_size_t size) +{ + return __lmb_alloc_addr(base, size, LMB_NONE); +} + /* Return number of bytes from a given address that are free */ -phys_size_t lmb_get_free_size(struct lmb *lmb, phys_addr_t addr) +phys_size_t lmb_get_free_size(phys_addr_t addr) { int i; long rgn; + struct lmb_region *lmb_used = lmb.used_mem.data; + struct lmb_region *lmb_memory = lmb.free_mem.data; /* check if the requested address is in the memory regions */ - rgn = lmb_overlaps_region(&lmb->memory, addr, 1); + rgn = lmb_overlaps_region(&lmb.free_mem, addr, 1); if (rgn >= 0) { - for (i = 0; i < lmb->reserved.cnt; i++) { - if (addr < lmb->reserved.region[i].base) { + for (i = 0; i < lmb.used_mem.count; i++) { + if (addr < lmb_used[i].base) { /* first reserved range > requested address */ - return lmb->reserved.region[i].base - addr; + return lmb_used[i].base - addr; } - if (lmb->reserved.region[i].base + - lmb->reserved.region[i].size > addr) { + if (lmb_used[i].base + + lmb_used[i].size > addr) { /* requested addr is in this reserved range */ return 0; } } /* if we come here: no reserved ranges above requested addr */ - return lmb->memory.region[lmb->memory.cnt - 1].base + - lmb->memory.region[lmb->memory.cnt - 1].size - addr; + return lmb_memory[lmb.free_mem.count - 1].base + + lmb_memory[lmb.free_mem.count - 1].size - addr; } return 0; } -int lmb_is_reserved_flags(struct lmb *lmb, phys_addr_t addr, int flags) +int lmb_is_reserved_flags(phys_addr_t addr, int flags) { int i; + struct lmb_region *lmb_used = lmb.used_mem.data; - for (i = 0; i < lmb->reserved.cnt; i++) { - phys_addr_t upper = lmb->reserved.region[i].base + - lmb->reserved.region[i].size - 1; - if ((addr >= lmb->reserved.region[i].base) && (addr <= upper)) - return (lmb->reserved.region[i].flags & flags) == flags; + for (i = 0; i < lmb.used_mem.count; i++) { + phys_addr_t upper = lmb_used[i].base + + lmb_used[i].size - 1; + if (addr >= lmb_used[i].base && addr <= upper) + return (lmb_used[i].flags & flags) == flags; } return 0; } -int lmb_is_reserved(struct lmb *lmb, phys_addr_t addr) +static int lmb_setup(void) { - return lmb_is_reserved_flags(lmb, addr, LMB_NONE); + bool ret; + + ret = alist_init(&lmb.free_mem, sizeof(struct lmb_region), + (uint)LMB_ALIST_INITIAL_SIZE); + if (!ret) { + log_debug("Unable to initialise the list for LMB free memory\n"); + return -ENOMEM; + } + + ret = alist_init(&lmb.used_mem, sizeof(struct lmb_region), + (uint)LMB_ALIST_INITIAL_SIZE); + if (!ret) { + log_debug("Unable to initialise the list for LMB used memory\n"); + return -ENOMEM; + } + + return 0; } -__weak void board_lmb_reserve(struct lmb *lmb) +/** + * lmb_init() - Initialise the LMB module + * + * Initialise the LMB lists needed for keeping the memory map. There + * are two lists, in form of alloced list data structure. One for the + * available memory, and one for the used memory. Initialise the two + * lists as part of board init. Add memory to the available memory + * list and reserve common areas by adding them to the used memory + * list. + * + * Return: 0 on success, -ve on error + */ +int lmb_init(void) { - /* please define platform specific board_lmb_reserve() */ + int ret; + + ret = lmb_setup(); + if (ret) { + log_info("Unable to init LMB\n"); + return ret; + } + + lmb_add_memory(); + + /* Reserve the U-Boot image region once U-Boot has relocated */ + if (spl_phase() == PHASE_SPL) + lmb_reserve_common_spl(); + else if (spl_phase() == PHASE_BOARD_R) + lmb_reserve_common((void *)gd->fdt_blob); + + return 0; +} + +#if CONFIG_IS_ENABLED(UNIT_TEST) +struct lmb *lmb_get(void) +{ + return &lmb; +} + +int lmb_push(struct lmb *store) +{ + int ret; + + *store = lmb; + ret = lmb_setup(); + if (ret) + return ret; + + return 0; } -__weak void arch_lmb_reserve(struct lmb *lmb) +void lmb_pop(struct lmb *store) { - /* please define platform specific arch_lmb_reserve() */ + alist_uninit(&lmb.free_mem); + alist_uninit(&lmb.used_mem); + lmb = *store; } +#endif /* UNIT_TEST */ diff --git a/lib/strto.c b/lib/strto.c index 5157332d6c1..f83ac67c666 100644 --- a/lib/strto.c +++ b/lib/strto.c @@ -236,12 +236,14 @@ const char **str_to_list(const char *instr) return NULL; /* count the number of space-separated strings */ - for (count = *str != '\0', p = str; *p; p++) { + for (count = 0, p = str; *p; p++) { if (*p == ' ') { count++; *p = '\0'; } } + if (p != str && p[-1]) + count++; /* allocate the pointer array, allowing for a NULL terminator */ ptr = calloc(count + 1, sizeof(char *)); 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> |