diff options
Diffstat (limited to 'lib')
56 files changed, 1484 insertions, 381 deletions
diff --git a/lib/Kconfig b/lib/Kconfig index 8f1a96d98c4..1a683dea670 100644 --- a/lib/Kconfig +++ b/lib/Kconfig @@ -514,6 +514,18 @@ config VPL_TPM for the low-level TPM interface, but only one TPM is supported at a time by the TPM library. +config TPM_PCR_ALLOCATE + bool "Re-configurate TPM algorithms in run-time (PCR allocate)" + depends on TPM_V2 && (MEASURED_BOOT || EFI_TCG2_PROTOCOL) + help + This enables a detection for the dismatches of algorithms among TPM + device, eventlog from previous boot stage and U-Boot support. + A PCR allocate command will be sent to reconfigurate the TPM device + in run-time to make sure algorithms in TPM device, eventlog and + U-Boot are aligned with each other. + A system reboot will be proceeded after then to activate the new + algorithms. + endmenu menu "Android Verified Boot" @@ -746,6 +758,16 @@ config VPL_CRC8 checksum with feedback to produce an 8-bit result. The code is small and it does not require a lookup table (unlike CRC32). +config CRC16 + bool "Support CRC16" + default y + help + Enables CRC16 support. This is normally required. Two algorithms are + provided: + + - CCITT, with a polynomical x^16 + x^12 + x^5 + 1 + - standard, with polynomial x^16 + x^15 + x^2 + 1 (0x8005) + config SPL_CRC16 bool "Support CRC16 in SPL" depends on SPL @@ -1067,6 +1089,7 @@ menu "System tables" config BLOBLIST_TABLES bool "Put tables in a bloblist" depends on BLOBLIST + default y if X86 default y if (ARM && EFI_LOADER && GENERATE_ACPI_TABLE) default n help @@ -1091,6 +1114,12 @@ config GENERATE_SMBIOS_TABLE See also SYSINFO_SMBIOS which allows SMBIOS values to be provided in the devicetree. +config GENERATE_SMBIOS_TABLE_VERBOSE + bool "Generate a verbose SMBIOS (System Management BIOS) table" + depends on GENERATE_SMBIOS_TABLE + help + Provide verbose SMBIOS information. + endmenu config LIB_RATIONAL diff --git a/lib/Makefile b/lib/Makefile index 5cb3278d2ef..a7bc2f3134a 100644 --- a/lib/Makefile +++ b/lib/Makefile @@ -35,13 +35,16 @@ obj-$(CONFIG_CIRCBUF) += circbuf.o endif obj-y += crc8.o -obj-y += crc16.o -obj-y += crc16-ccitt.o obj-$(CONFIG_ERRNO_STR) += errno_str.o obj-$(CONFIG_FIT) += fdtdec_common.o obj-$(CONFIG_TEST_FDTDEC) += fdtdec_test.o obj-$(CONFIG_GZIP_COMPRESSED) += gzip.o + +# With QEMU the SMBIOS tables come from there, not from U-Boot +ifndef CONFIG_QFW_SMBIOS obj-$(CONFIG_GENERATE_SMBIOS_TABLE) += smbios.o +endif + obj-$(CONFIG_SMBIOS_PARSER) += smbios-parser.o obj-$(CONFIG_IMAGE_SPARSE) += image-sparse.o obj-y += initcall.o @@ -66,6 +69,7 @@ endif obj-$(CONFIG_$(PHASE_)CRC8) += crc8.o obj-$(CONFIG_$(PHASE_)CRC16) += crc16.o +obj-$(CONFIG_$(PHASE_)CRC16) += crc16-ccitt.o obj-y += crypto/ @@ -75,10 +79,11 @@ obj-$(CONFIG_$(XPL_)RSA) += rsa/ obj-$(CONFIG_HASH) += hash-checksum.o obj-$(CONFIG_BLAKE2) += blake2/blake2b.o -obj-$(CONFIG_$(XPL_)MD5_LEGACY) += md5.o -obj-$(CONFIG_$(XPL_)SHA1_LEGACY) += sha1.o -obj-$(CONFIG_$(XPL_)SHA256_LEGACY) += sha256.o -obj-$(CONFIG_$(XPL_)SHA512_LEGACY) += sha512.o +obj-$(CONFIG_$(PHASE_)MD5_LEGACY) += md5.o +obj-$(CONFIG_$(PHASE_)SHA1_LEGACY) += sha1.o +obj-$(CONFIG_$(PHASE_)SHA256) += sha256_common.o +obj-$(CONFIG_$(PHASE_)SHA256_LEGACY) += sha256.o +obj-$(CONFIG_$(PHASE_)SHA512_LEGACY) += sha512.o obj-$(CONFIG_CRYPT_PW) += crypt/ obj-$(CONFIG_$(XPL_)ASN1_DECODER_LEGACY) += asn1_decoder.o diff --git a/lib/abuf.c b/lib/abuf.c index 937c3df351e..61adf7fc6b1 100644 --- a/lib/abuf.c +++ b/lib/abuf.c @@ -26,6 +26,12 @@ void abuf_map_sysmem(struct abuf *abuf, ulong addr, size_t size) { abuf_set(abuf, map_sysmem(addr, size), size); } + +ulong abuf_addr(const struct abuf *abuf) +{ + return map_to_sysmem(abuf->data); +} + #else /* copied from lib/string.c for convenience */ static char *memdup(const void *src, size_t len) @@ -113,6 +119,12 @@ void abuf_init_set(struct abuf *abuf, void *data, size_t size) abuf_set(abuf, data, size); } +void abuf_init_const(struct abuf *abuf, const void *data, size_t size) +{ + /* for now there is no flag indicating that the abuf data is constant */ + abuf_init_set(abuf, (void *)data, size); +} + void abuf_init_move(struct abuf *abuf, void *data, size_t size) { abuf_init_set(abuf, data, size); diff --git a/lib/acpi/acpi_table.c b/lib/acpi/acpi_table.c index 150f75027a5..c0ed24984af 100644 --- a/lib/acpi/acpi_table.c +++ b/lib/acpi/acpi_table.c @@ -273,7 +273,9 @@ int acpi_write_fadt(struct acpi_ctx *ctx, const struct acpi_writer *entry) return acpi_add_fadt(ctx, fadt); } +#ifndef CONFIG_QFW_ACPI ACPI_WRITER(5fadt, "FADT", acpi_write_fadt, 0); +#endif int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry) { @@ -308,7 +310,9 @@ int acpi_write_madt(struct acpi_ctx *ctx, const struct acpi_writer *entry) return 0; } +#ifndef CONFIG_QFW_ACPI ACPI_WRITER(5madt, "MADT", acpi_write_madt, 0); +#endif void acpi_create_dbg2(struct acpi_dbg2_header *dbg2, int port_type, int port_subtype, diff --git a/lib/crc8.c b/lib/crc8.c index 811e19917b4..bbb229c3892 100644 --- a/lib/crc8.c +++ b/lib/crc8.c @@ -6,11 +6,12 @@ #ifdef USE_HOSTCC #include <arpa/inet.h> #endif +#include <asm/sections.h> #include <u-boot/crc.h> #define POLY (0x1070U << 3) -static unsigned char _crc8(unsigned short data) +__rcode static unsigned char _crc8(unsigned short data) { int i; @@ -23,7 +24,7 @@ static unsigned char _crc8(unsigned short data) return (unsigned char)(data >> 8); } -unsigned int crc8(unsigned int crc, const unsigned char *vptr, int len) +__rcode unsigned int crc8(unsigned int crc, const unsigned char *vptr, int len) { int i; diff --git a/lib/efi_driver/efi_block_device.c b/lib/efi_driver/efi_block_device.c index 19a5ee24794..d3c668dc183 100644 --- a/lib/efi_driver/efi_block_device.c +++ b/lib/efi_driver/efi_block_device.c @@ -28,6 +28,8 @@ * iPXE uses the simple file protocol to load Grub or the Linux Kernel. */ +#define LOG_CATEGORY LOGC_EFI + #include <blk.h> #include <dm.h> #include <efi_driver.h> diff --git a/lib/efi_driver/efi_uclass.c b/lib/efi_driver/efi_uclass.c index e1e28df20b2..495be53cb77 100644 --- a/lib/efi_driver/efi_uclass.c +++ b/lib/efi_driver/efi_uclass.c @@ -17,6 +17,8 @@ * controllers. */ +#define LOG_CATEGORY LOGC_EFI + #include <dm.h> #include <efi_driver.h> #include <log.h> diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig index c46ffe3a9d8..d4f6b56afaa 100644 --- a/lib/efi_loader/Kconfig +++ b/lib/efi_loader/Kconfig @@ -8,13 +8,14 @@ config EFI_LOADER SYS_CPU = armv7 || \ SYS_CPU = armv8) || \ X86 || RISCV || SANDBOX) + # We have not fully removed the requirement for some block device + depends on BLK # We need EFI_STUB_64BIT to be set on x86_64 with EFI_STUB depends on !EFI_STUB || !X86_64 || EFI_STUB_64BIT # We need EFI_STUB_32BIT to be set on x86_32 with EFI_STUB depends on !EFI_STUB || !X86 || X86_64 || EFI_STUB_32BIT depends on !EFI_APP default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8 - select BLK select CHARSET # We need to send DM events, dynamically, in the EFI block driver select DM_EVENT @@ -386,7 +387,7 @@ config EFI_DT_FIXUP config EFI_LOADER_HII bool "HII protocols" - default y + default y if !HAS_BOARD_SIZE_LIMIT help The Human Interface Infrastructure is a complicated framework that allows UEFI applications to draw fancy menus and hook strings using @@ -406,7 +407,7 @@ if EFI_UNICODE_COLLATION_PROTOCOL2 config EFI_UNICODE_CAPITALIZATION bool "Support Unicode capitalization" - default y + default y if !HAS_BOARD_SIZE_LIMIT help Select this option to enable correct handling of the capitalization of Unicode codepoints in the range 0x0000-0xffff. If this option is not @@ -437,15 +438,6 @@ config EFI_TCG2_PROTOCOL Provide a EFI_TCG2_PROTOCOL implementation using the TPM hardware of the platform. -config EFI_TCG2_PROTOCOL_EVENTLOG_SIZE - int "EFI_TCG2_PROTOCOL EventLog size" - depends on EFI_TCG2_PROTOCOL - default 65536 - help - Define the size of the EventLog for EFI_TCG2_PROTOCOL. Note that - this is going to be allocated twice. One for the eventlog it self - and one for the configuration table that is required from the spec - config EFI_TCG2_PROTOCOL_MEASURE_DTB bool "Measure DTB with EFI_TCG2_PROTOCOL" depends on EFI_TCG2_PROTOCOL diff --git a/lib/efi_loader/efi_acpi.c b/lib/efi_loader/efi_acpi.c index 67bd7f8ca24..4422b31ac6a 100644 --- a/lib/efi_loader/efi_acpi.c +++ b/lib/efi_loader/efi_acpi.c @@ -5,6 +5,8 @@ * Copyright (C) 2018, Bin Meng <bmeng.cn@gmail.com> */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <log.h> #include <mapmem.h> @@ -25,6 +27,16 @@ efi_status_t efi_acpi_register(void) ulong addr, start, end; efi_status_t ret; + /* + * The bloblist is already marked reserved. For now, we don't bother + * marking it with EFI_ACPI_RECLAIM_MEMORY since we would need to cut a + * hole in the EFI_BOOT_SERVICES_CODE region added by + * add_u_boot_and_runtime(). At some point that function could create a + * more detailed map. + */ + if (IS_ENABLED(CONFIG_BLOBLIST_TABLES)) + return EFI_SUCCESS; + /* Mark space used for tables */ start = ALIGN_DOWN(gd->arch.table_start, EFI_PAGE_MASK); end = ALIGN(gd->arch.table_end, EFI_PAGE_MASK); diff --git a/lib/efi_loader/efi_bootbin.c b/lib/efi_loader/efi_bootbin.c index b677bbc3124..10ec5e9ada3 100644 --- a/lib/efi_loader/efi_bootbin.c +++ b/lib/efi_loader/efi_bootbin.c @@ -6,13 +6,16 @@ #define LOG_CATEGORY LOGC_EFI +#include <bootflow.h> #include <charset.h> +#include <dm.h> #include <efi.h> #include <efi_loader.h> #include <env.h> #include <image.h> #include <log.h> #include <malloc.h> +#include <mapmem.h> static struct efi_device_path *bootefi_image_path; static struct efi_device_path *bootefi_device_path; @@ -45,11 +48,63 @@ void efi_clear_bootdev(void) } /** + * calculate_paths() - Calculate the device and image patch from strings + * + * @dev: device, e.g. "MMC" + * @devnr: number of the device, e.g. "1:2" + * @path: path to file loaded + * @device_pathp: returns EFI device path + * @image_pathp: returns EFI image path + * Return: EFI_SUCCESS on success, else error code + */ +static efi_status_t calculate_paths(const char *dev, const char *devnr, + const char *path, + struct efi_device_path **device_pathp, + struct efi_device_path **image_pathp) +{ + struct efi_device_path *image, *device; + efi_status_t ret; + +#if IS_ENABLED(CONFIG_NETDEVICES) + if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) { + ret = efi_net_set_dp(dev, devnr); + if (ret != EFI_SUCCESS) + return ret; + } +#endif + + ret = efi_dp_from_name(dev, devnr, path, &device, &image); + if (ret != EFI_SUCCESS) + return ret; + + *device_pathp = device; + if (image) { + /* FIXME: image should not contain device */ + struct efi_device_path *image_tmp = image; + + efi_dp_split_file_path(image, &device, &image); + efi_free_pool(image_tmp); + } + *image_pathp = image; + log_debug("- boot device %pD\n", device); + if (image) + log_debug("- image %pD\n", image); + + return EFI_SUCCESS; +} + +/** * efi_set_bootdev() - set boot device * * This function is called when a file is loaded, e.g. via the 'load' command. * We use the path to this file to inform the UEFI binary about the boot device. * + * For a valid image, it sets: + * - image_addr to the provided buffer + * - image_size to the provided buffer_size + * - bootefi_device_path to the EFI device-path + * - bootefi_image_path to the EFI image-path + * * @dev: device, e.g. "MMC" * @devnr: number of the device, e.g. "1:2" * @path: path to file loaded @@ -59,7 +114,6 @@ void efi_clear_bootdev(void) void efi_set_bootdev(const char *dev, const char *devnr, const char *path, void *buffer, size_t buffer_size) { - struct efi_device_path *device, *image; efi_status_t ret; log_debug("dev=%s, devnr=%s, path=%s, buffer=%p, size=%zx\n", dev, @@ -93,34 +147,12 @@ void efi_set_bootdev(const char *dev, const char *devnr, const char *path, image_addr = buffer; image_size = buffer_size; -#if IS_ENABLED(CONFIG_NETDEVICES) - if (!strcmp(dev, "Net") || !strcmp(dev, "Http")) { - ret = efi_net_set_dp(dev, devnr); - if (ret != EFI_SUCCESS) - goto error; - } -#endif - - ret = efi_dp_from_name(dev, devnr, path, &device, &image); - if (ret != EFI_SUCCESS) - goto error; - - bootefi_device_path = device; - if (image) { - /* FIXME: image should not contain device */ - struct efi_device_path *image_tmp = image; - - efi_dp_split_file_path(image, &device, &image); - efi_free_pool(image_tmp); + ret = calculate_paths(dev, devnr, path, &bootefi_device_path, + &bootefi_image_path); + if (ret) { + log_debug("- efi_dp_from_name() failed, err=%lx\n", ret); + efi_clear_bootdev(); } - bootefi_image_path = image; - log_debug("- boot device %pD\n", device); - if (image) - log_debug("- image %pD\n", image); - return; -error: - log_debug("- efi_dp_from_name() failed, err=%lx\n", ret); - efi_clear_bootdev(); } /** @@ -128,42 +160,21 @@ error: * * @source_buffer: memory address of the UEFI image * @source_size: size of the UEFI image + * @dp_dev: EFI device-path + * @dp_img: EFI image-path * Return: status code */ -efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) +static efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size, + struct efi_device_path *dp_dev, + struct efi_device_path *dp_img) { - efi_handle_t mem_handle = NULL, handle; - struct efi_device_path *file_path = NULL; - struct efi_device_path *msg_path; + efi_handle_t handle; + struct efi_device_path *msg_path, *file_path; efi_status_t ret; u16 *load_options; - if (!bootefi_device_path || !bootefi_image_path) { - log_debug("Not loaded from disk\n"); - /* - * Special case for efi payload not loaded from disk, - * such as 'bootefi hello' or for example payload - * loaded directly into memory via JTAG, etc: - */ - file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, - (uintptr_t)source_buffer, - source_size); - /* - * Make sure that device for device_path exist - * in load_image(). Otherwise, shell and grub will fail. - */ - ret = efi_install_multiple_protocol_interfaces(&mem_handle, - &efi_guid_device_path, - file_path, NULL); - if (ret != EFI_SUCCESS) - goto out; - msg_path = file_path; - } else { - file_path = efi_dp_concat(bootefi_device_path, - bootefi_image_path, 0); - msg_path = bootefi_image_path; - log_debug("Loaded from disk\n"); - } + file_path = efi_dp_concat(dp_dev, dp_img, 0); + msg_path = dp_img; log_info("Booting %pD\n", msg_path); @@ -182,32 +193,27 @@ efi_status_t efi_run_image(void *source_buffer, efi_uintn_t source_size) ret = do_bootefi_exec(handle, load_options); out: - if (mem_handle) { - efi_status_t r; - - r = efi_uninstall_multiple_protocol_interfaces( - mem_handle, &efi_guid_device_path, file_path, NULL); - if (r != EFI_SUCCESS) - log_err("Uninstalling protocol interfaces failed\n"); - } - efi_free_pool(file_path); return ret; } /** - * efi_binary_run() - run loaded UEFI image + * efi_binary_run_dp() - run loaded UEFI image * * @image: memory address of the UEFI image * @size: size of the UEFI image * @fdt: device-tree + * @dp_dev: EFI device-path + * @dp_img: EFI image-path * * Execute an EFI binary image loaded at @image. * @size may be zero if the binary is loaded with U-Boot load command. * * Return: status code */ -efi_status_t efi_binary_run(void *image, size_t size, void *fdt) +static efi_status_t efi_binary_run_dp(void *image, size_t size, void *fdt, + struct efi_device_path *dp_dev, + struct efi_device_path *dp_img) { efi_status_t ret; @@ -223,5 +229,132 @@ efi_status_t efi_binary_run(void *image, size_t size, void *fdt) if (ret != EFI_SUCCESS) return ret; - return efi_run_image(image, size); + return efi_run_image(image, size, dp_dev, dp_img); +} + +/** + * efi_binary_run() - run loaded UEFI image + * + * @image: memory address of the UEFI image + * @size: size of the UEFI image + * @fdt: device-tree + * + * Execute an EFI binary image loaded at @image. + * @size may be zero if the binary is loaded with U-Boot load command. + * + * Return: status code + */ +efi_status_t efi_binary_run(void *image, size_t size, void *fdt) +{ + efi_handle_t mem_handle = NULL; + struct efi_device_path *file_path = NULL; + efi_status_t ret; + + if (!bootefi_device_path || !bootefi_image_path) { + log_debug("Not loaded from disk\n"); + /* + * Special case for efi payload not loaded from disk, + * such as 'bootefi hello' or for example payload + * loaded directly into memory via JTAG, etc: + */ + file_path = efi_dp_from_mem(EFI_RESERVED_MEMORY_TYPE, + (uintptr_t)image, size); + /* + * Make sure that device for device_path exist + * in load_image(). Otherwise, shell and grub will fail. + */ + ret = efi_install_multiple_protocol_interfaces(&mem_handle, + &efi_guid_device_path, + file_path, NULL); + if (ret != EFI_SUCCESS) + goto out; + } else { + log_debug("Loaded from disk\n"); + } + + ret = efi_binary_run_dp(image, size, fdt, bootefi_device_path, + bootefi_image_path); +out: + if (mem_handle) { + efi_status_t r; + + r = efi_uninstall_multiple_protocol_interfaces(mem_handle, + &efi_guid_device_path, file_path, NULL); + if (r != EFI_SUCCESS) + log_err("Uninstalling protocol interfaces failed\n"); + } + efi_free_pool(file_path); + + return ret; +} + +/** + * calc_dev_name() - Calculate the device name to give to EFI + * + * If not supported, this shows an error. + * + * Return name, or NULL if not supported + */ +static const char *calc_dev_name(struct bootflow *bflow) +{ + const struct udevice *media_dev; + + media_dev = dev_get_parent(bflow->dev); + + if (!bflow->blk) { + if (device_get_uclass_id(media_dev) == UCLASS_ETH) + return "Net"; + + log_err("Cannot boot EFI app on media '%s'\n", + dev_get_uclass_name(media_dev)); + + return NULL; + } + + if (device_get_uclass_id(media_dev) == UCLASS_MASS_STORAGE) + return "usb"; + + return blk_get_uclass_name(device_get_uclass_id(media_dev)); +} + +efi_status_t efi_bootflow_run(struct bootflow *bflow) +{ + struct efi_device_path *device, *image; + const struct udevice *media_dev; + struct blk_desc *desc = NULL; + const char *dev_name; + char devnum_str[9]; + efi_status_t ret; + void *fdt; + + media_dev = dev_get_parent(bflow->dev); + if (bflow->blk) { + desc = dev_get_uclass_plat(bflow->blk); + + snprintf(devnum_str, sizeof(devnum_str), "%x:%x", + desc ? desc->devnum : dev_seq(media_dev), bflow->part); + } else { + *devnum_str = '\0'; + } + + dev_name = calc_dev_name(bflow); + log_debug("dev_name '%s' devnum_str '%s' fname '%s' media_dev '%s'\n", + dev_name, devnum_str, bflow->fname, media_dev->name); + if (!dev_name) + return EFI_UNSUPPORTED; + ret = calculate_paths(dev_name, devnum_str, bflow->fname, &device, + &image); + if (ret) + return EFI_UNSUPPORTED; + + if (bflow->flags & BOOTFLOWF_USE_BUILTIN_FDT) { + log_debug("Booting with built-in fdt\n"); + fdt = EFI_FDT_USE_INTERNAL; + } else { + log_debug("Booting with external fdt\n"); + fdt = map_sysmem(bflow->fdt_addr, 0); + } + ret = efi_binary_run_dp(bflow->buf, bflow->size, fdt, device, image); + + return ret; } diff --git a/lib/efi_loader/efi_boottime.c b/lib/efi_loader/efi_boottime.c index 080e7f78ae3..5164cb15986 100644 --- a/lib/efi_loader/efi_boottime.c +++ b/lib/efi_loader/efi_boottime.c @@ -5,6 +5,8 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include <bootm.h> #include <div64.h> #include <dm/device.h> @@ -3256,11 +3258,10 @@ efi_status_t EFIAPI efi_start_image(efi_handle_t image_handle, * To get ready to call EFI_EXIT below we have to execute the * missed out steps of EFI_CALL. */ - assert(__efi_entry_check()); - EFI_PRINT("%lu returned by started image\n", - (unsigned long)((uintptr_t)exit_status & - ~EFI_ERROR_MASK)); + EFI_RETURN(exit_status); + current_image = parent_image; + return EFI_EXIT(exit_status); } @@ -3495,10 +3496,9 @@ static efi_status_t EFIAPI efi_exit(efi_handle_t image_handle, if (IS_ENABLED(CONFIG_EFI_TCG2_PROTOCOL)) { if (image_obj->image_type == IMAGE_SUBSYSTEM_EFI_APPLICATION) { ret = efi_tcg2_measure_efi_app_exit(); - if (ret != EFI_SUCCESS) { - log_warning("tcg2 measurement fails(0x%lx)\n", - ret); - } + if (ret != EFI_SUCCESS) + log_debug("tcg2 measurement fails (0x%lx)\n", + ret); } } @@ -3733,7 +3733,7 @@ out: * * Return: status code */ -static efi_status_t EFIAPI efi_reinstall_protocol_interface( +efi_status_t EFIAPI efi_reinstall_protocol_interface( efi_handle_t handle, const efi_guid_t *protocol, void *old_interface, void *new_interface) { diff --git a/lib/efi_loader/efi_conformance.c b/lib/efi_loader/efi_conformance.c index 167067e26cd..2bae93a94bd 100644 --- a/lib/efi_loader/efi_conformance.c +++ b/lib/efi_loader/efi_conformance.c @@ -5,6 +5,8 @@ * Copyright (C) 2022 Arm Ltd. */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <log.h> #include <efi_api.h> diff --git a/lib/efi_loader/efi_device_path_to_text.c b/lib/efi_loader/efi_device_path_to_text.c index 481a9712d9d..f6889cb7399 100644 --- a/lib/efi_loader/efi_device_path_to_text.c +++ b/lib/efi_loader/efi_device_path_to_text.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include <blk.h> #include <efi_loader.h> #include <malloc.h> diff --git a/lib/efi_loader/efi_device_path_utilities.c b/lib/efi_loader/efi_device_path_utilities.c index ac250bbfcc9..552c5bb1f05 100644 --- a/lib/efi_loader/efi_device_path_utilities.c +++ b/lib/efi_loader/efi_device_path_utilities.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Leif Lindholm */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> const efi_guid_t efi_guid_device_path_utilities_protocol = diff --git a/lib/efi_loader/efi_dt_fixup.c b/lib/efi_loader/efi_dt_fixup.c index 0dac94b0c6c..26928cfc454 100644 --- a/lib/efi_loader/efi_dt_fixup.c +++ b/lib/efi_loader/efi_dt_fixup.c @@ -5,6 +5,8 @@ * Copyright (c) 2020 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_dt_fixup.h> #include <efi_loader.h> #include <efi_rng.h> diff --git a/lib/efi_loader/efi_esrt.c b/lib/efi_loader/efi_esrt.c index 443bd999ce1..e235c8fe91c 100644 --- a/lib/efi_loader/efi_esrt.c +++ b/lib/efi_loader/efi_esrt.c @@ -5,6 +5,8 @@ * Copyright (C) 2021 Arm Ltd. */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <log.h> #include <efi_api.h> diff --git a/lib/efi_loader/efi_fdt.c b/lib/efi_loader/efi_fdt.c index f882622fdad..1ba6641d821 100644 --- a/lib/efi_loader/efi_fdt.c +++ b/lib/efi_loader/efi_fdt.c @@ -6,6 +6,8 @@ * Written by Simon Glass <sjg@chromium.org> */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <env.h> #include <errno.h> diff --git a/lib/efi_loader/efi_file.c b/lib/efi_loader/efi_file.c index 95b3c890ee9..201fa5f8f3c 100644 --- a/lib/efi_loader/efi_file.c +++ b/lib/efi_loader/efi_file.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Rob Clark */ +#define LOG_CATEGORY LOGC_EFI + #include <charset.h> #include <efi_loader.h> #include <log.h> diff --git a/lib/efi_loader/efi_firmware.c b/lib/efi_loader/efi_firmware.c index 112775daf4c..5a754c9cd03 100644 --- a/lib/efi_loader/efi_firmware.c +++ b/lib/efi_loader/efi_firmware.c @@ -6,6 +6,8 @@ * Author: AKASHI Takahiro */ +#define LOG_CATEGORY LOGC_EFI + #include <charset.h> #include <dfu.h> #include <efi_loader.h> diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c index 41e12fa7246..4593975be5a 100644 --- a/lib/efi_loader/efi_gop.c +++ b/lib/efi_loader/efi_gop.c @@ -5,6 +5,8 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include <dm.h> #include <efi_loader.h> #include <log.h> diff --git a/lib/efi_loader/efi_helper.c b/lib/efi_loader/efi_helper.c index bf96f61d3d0..04b2efc4a3b 100644 --- a/lib/efi_loader/efi_helper.c +++ b/lib/efi_loader/efi_helper.c @@ -4,6 +4,7 @@ */ #define LOG_CATEGORY LOGC_EFI + #include <bootm.h> #include <env.h> #include <image.h> diff --git a/lib/efi_loader/efi_hii.c b/lib/efi_loader/efi_hii.c index 74e402df1b8..44235970a7c 100644 --- a/lib/efi_loader/efi_hii.c +++ b/lib/efi_loader/efi_hii.c @@ -6,6 +6,8 @@ * Copyright (c) 2018 AKASHI Takahiro, Linaro Limited */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <malloc.h> #include <asm/unaligned.h> diff --git a/lib/efi_loader/efi_hii_config.c b/lib/efi_loader/efi_hii_config.c index ae0f3ecd3b1..37d8c6629e2 100644 --- a/lib/efi_loader/efi_hii_config.c +++ b/lib/efi_loader/efi_hii_config.c @@ -10,6 +10,8 @@ * the Makefile. */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> const efi_guid_t efi_guid_hii_config_routing_protocol diff --git a/lib/efi_loader/efi_http.c b/lib/efi_loader/efi_http.c index 694e1993418..88816256b03 100644 --- a/lib/efi_loader/efi_http.c +++ b/lib/efi_loader/efi_http.c @@ -7,6 +7,8 @@ * IP4_CONFIG2_PROTOCOL */ +#define LOG_CATEGORY LOGC_EFI + #include <charset.h> #include <efi_loader.h> #include <image.h> diff --git a/lib/efi_loader/efi_image_loader.c b/lib/efi_loader/efi_image_loader.c index bb58cf1badb..d002eb0c744 100644 --- a/lib/efi_loader/efi_image_loader.c +++ b/lib/efi_loader/efi_image_loader.c @@ -122,7 +122,7 @@ static efi_status_t efi_loader_relocate(const IMAGE_BASE_RELOCATION *rel, return EFI_SUCCESS; end = (const IMAGE_BASE_RELOCATION *)((const char *)rel + rel_size); - while (rel < end && rel->SizeOfBlock) { + while (rel + 1 < end && rel->SizeOfBlock) { const uint16_t *relocs = (const uint16_t *)(rel + 1); i = (rel->SizeOfBlock - sizeof(*rel)) / sizeof(uint16_t); while (i--) { diff --git a/lib/efi_loader/efi_ipconfig.c b/lib/efi_loader/efi_ipconfig.c index 0b247a4c028..f1c092daafd 100644 --- a/lib/efi_loader/efi_ipconfig.c +++ b/lib/efi_loader/efi_ipconfig.c @@ -4,6 +4,8 @@ * */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <image.h> #include <malloc.h> diff --git a/lib/efi_loader/efi_load_initrd.c b/lib/efi_loader/efi_load_initrd.c index 23508431c83..fb8cc7bcbe3 100644 --- a/lib/efi_loader/efi_load_initrd.c +++ b/lib/efi_loader/efi_load_initrd.c @@ -4,6 +4,7 @@ */ #define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <efi_load_initrd.h> #include <efi_variable.h> diff --git a/lib/efi_loader/efi_net.c b/lib/efi_loader/efi_net.c index 67593ef50c0..ce9272fa240 100644 --- a/lib/efi_loader/efi_net.c +++ b/lib/efi_loader/efi_net.c @@ -15,6 +15,8 @@ * Reset(): EfiSimpleNetworkInitialized -> EfiSimpleNetworkInitialized */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <dm.h> #include <linux/sizes.h> diff --git a/lib/efi_loader/efi_riscv.c b/lib/efi_loader/efi_riscv.c index 4d398c5be34..6f2ccf4f7e6 100644 --- a/lib/efi_loader/efi_riscv.c +++ b/lib/efi_loader/efi_riscv.c @@ -7,6 +7,7 @@ */ #define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <efi_variable.h> #include <log.h> diff --git a/lib/efi_loader/efi_root_node.c b/lib/efi_loader/efi_root_node.c index 4d7fb74b5d6..74225edad29 100644 --- a/lib/efi_loader/efi_root_node.c +++ b/lib/efi_loader/efi_root_node.c @@ -5,6 +5,8 @@ * Copyright (c) 2018 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include <malloc.h> #include <efi_dt_fixup.h> #include <efi_loader.h> diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c index 05369c47b01..35eb6a77766 100644 --- a/lib/efi_loader/efi_runtime.c +++ b/lib/efi_loader/efi_runtime.c @@ -5,6 +5,8 @@ * Copyright (c) 2016 Alexander Graf */ +#define LOG_CATEGORY LOGC_EFI + #include <command.h> #include <cpu_func.h> #include <dm.h> diff --git a/lib/efi_loader/efi_signature.c b/lib/efi_loader/efi_signature.c index 184eac8cddb..93a4f257016 100644 --- a/lib/efi_loader/efi_signature.c +++ b/lib/efi_loader/efi_signature.c @@ -4,6 +4,8 @@ * Copyright (c) 2019 Linaro Limited, Author: AKASHI Takahiro */ +#define LOG_CATEGORY LOGC_EFI + #include <charset.h> #include <efi_loader.h> #include <efi_variable.h> diff --git a/lib/efi_loader/efi_string.c b/lib/efi_loader/efi_string.c index 413e329b600..50d1daf33a9 100644 --- a/lib/efi_loader/efi_string.c +++ b/lib/efi_loader/efi_string.c @@ -5,6 +5,8 @@ * Copyright (c) 2020 AKASHI Takahiro, Linaro Limited */ +#define LOG_CATEGORY LOGC_EFI + #include <charset.h> #include <efi_loader.h> #include <malloc.h> diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c index 572c6b5bf63..210a846ebc8 100644 --- a/lib/efi_loader/efi_tcg2.c +++ b/lib/efi_loader/efi_tcg2.c @@ -8,6 +8,7 @@ */ #define LOG_CATEGORY LOGC_EFI + #include <dm.h> #include <efi_loader.h> #include <efi_variable.h> @@ -111,7 +112,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type, /* if ExitBootServices hasn't been called update the normal log */ if (!event_log.ebs_called) { if (event_log.truncated || - event_log.pos + event_size > TPM2_EVENT_LOG_SIZE) { + event_log.pos + event_size > CONFIG_TPM2_EVENT_LOG_SIZE) { event_log.truncated = true; return EFI_VOLUME_FULL; } @@ -124,7 +125,7 @@ static efi_status_t tcg2_agile_log_append(u32 pcr_index, u32 event_type, return ret; /* if GetEventLog has been called update FinalEventLog as well */ - if (event_log.final_pos + event_size > TPM2_EVENT_LOG_SIZE) + if (event_log.final_pos + event_size > CONFIG_TPM2_EVENT_LOG_SIZE) return EFI_VOLUME_FULL; log = (void *)((uintptr_t)event_log.final_buffer + event_log.final_pos); @@ -791,7 +792,7 @@ static void tcg2_uninit(void) efi_status_t ret; ret = efi_install_configuration_table(&efi_guid_final_events, NULL); - if (ret != EFI_SUCCESS) + if (ret != EFI_SUCCESS && ret != EFI_NOT_FOUND) log_err("Failed to delete final events config table\n"); efi_free_pool(event_log.buffer); @@ -822,12 +823,12 @@ static efi_status_t create_final_event(void) * EFI_TCG2_GET_EVENT_LOGS need to be stored in an instance of an * EFI_CONFIGURATION_TABLE */ - ret = efi_allocate_pool(EFI_ACPI_MEMORY_NVS, TPM2_EVENT_LOG_SIZE, + ret = efi_allocate_pool(EFI_ACPI_MEMORY_NVS, CONFIG_TPM2_EVENT_LOG_SIZE, &event_log.final_buffer); if (ret != EFI_SUCCESS) goto out; - memset(event_log.final_buffer, 0xff, TPM2_EVENT_LOG_SIZE); + memset(event_log.final_buffer, 0xff, CONFIG_TPM2_EVENT_LOG_SIZE); final_event = event_log.final_buffer; final_event->number_of_events = 0; final_event->version = EFI_TCG2_FINAL_EVENTS_TABLE_VERSION; @@ -913,7 +914,8 @@ static efi_status_t efi_init_event_log(void) if (tcg2_platform_get_tpm2(&dev)) return EFI_DEVICE_ERROR; - ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, TPM2_EVENT_LOG_SIZE, + ret = efi_allocate_pool(EFI_BOOT_SERVICES_DATA, + CONFIG_TPM2_EVENT_LOG_SIZE, (void **)&event_log.buffer); if (ret != EFI_SUCCESS) return ret; @@ -922,7 +924,7 @@ static efi_status_t efi_init_event_log(void) * initialize log area as 0xff so the OS can easily figure out the * last log entry */ - memset(event_log.buffer, 0xff, TPM2_EVENT_LOG_SIZE); + memset(event_log.buffer, 0xff, CONFIG_TPM2_EVENT_LOG_SIZE); /* * The log header is defined to be in SHA1 event log entry format. @@ -939,7 +941,7 @@ static efi_status_t efi_init_event_log(void) * platforms can use different ways to do so. */ elog.log = event_log.buffer; - elog.log_size = TPM2_EVENT_LOG_SIZE; + elog.log_size = CONFIG_TPM2_EVENT_LOG_SIZE; rc = tcg2_log_prepare_buffer(dev, &elog, false); if (rc) { ret = (rc == -ENOBUFS) ? EFI_BUFFER_TOO_SMALL : EFI_DEVICE_ERROR; diff --git a/lib/efi_loader/efi_unicode_collation.c b/lib/efi_loader/efi_unicode_collation.c index d48700a352b..df2a988ee39 100644 --- a/lib/efi_loader/efi_unicode_collation.c +++ b/lib/efi_loader/efi_unicode_collation.c @@ -5,6 +5,8 @@ * Copyright (c) 2018 Heinrich Schuchardt <xypron.glpk@gmx.de> */ +#define LOG_CATEGORY LOGC_EFI + #include <charset.h> #include <cp1250.h> #include <cp437.h> diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c index ea8d2a4cf98..4b34a58b4cf 100644 --- a/lib/efi_loader/efi_var_common.c +++ b/lib/efi_loader/efi_var_common.c @@ -5,6 +5,8 @@ * Copyright (c) 2020 Linaro Limited, Author: AKASHI Takahiro */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <efi_variable.h> #include <stdlib.h> diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c index 139e16aad7c..b265d95dd6b 100644 --- a/lib/efi_loader/efi_var_mem.c +++ b/lib/efi_loader/efi_var_mem.c @@ -5,6 +5,8 @@ * Copyright (c) 2020, Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> #include <efi_variable.h> #include <u-boot/crc.h> diff --git a/lib/efi_loader/efi_variable_tee.c b/lib/efi_loader/efi_variable_tee.c index 8b6b0a39086..0d090d051dd 100644 --- a/lib/efi_loader/efi_variable_tee.c +++ b/lib/efi_loader/efi_variable_tee.c @@ -10,6 +10,8 @@ * Abdellatif El Khlifi <abdellatif.elkhlifi@arm.com> */ +#define LOG_CATEGORY LOGC_EFI + #if CONFIG_IS_ENABLED(ARM_FFA_TRANSPORT) #include <arm_ffa.h> #endif diff --git a/lib/efi_loader/efi_watchdog.c b/lib/efi_loader/efi_watchdog.c index f5fb9117717..c21d8086074 100644 --- a/lib/efi_loader/efi_watchdog.c +++ b/lib/efi_loader/efi_watchdog.c @@ -5,6 +5,8 @@ * Copyright (c) 2017 Heinrich Schuchardt */ +#define LOG_CATEGORY LOGC_EFI + #include <efi_loader.h> /* Conversion factor from seconds to multiples of 100ns */ diff --git a/lib/efi_loader/elf_efi.ldsi b/lib/efi_loader/elf_efi.ldsi new file mode 100644 index 00000000000..190a88fb69e --- /dev/null +++ b/lib/efi_loader/elf_efi.ldsi @@ -0,0 +1,74 @@ +/* SPDX-License-Identifier: BSD-2-Clause */ +/* + * U-Boot EFI linker script include + * + * Modified from elf_aarch64_efi.lds in gnu-efi + */ + +PHDRS +{ + data PT_LOAD FLAGS(3); /* SHF_WRITE | SHF_ALLOC */ +} + +ENTRY(_start) +SECTIONS +{ + .text 0x0 : { + _text = .; + *(.text.head) + *(.text) + *(.text.*) + *(.gnu.linkonce.t.*) + *(.srodata) + *(.rodata*) + . = ALIGN(16); + *(.dynamic); + . = ALIGN(512); + } + .rela.dyn : { *(.rela.dyn) } + .rela.plt : { *(.rela.plt) } + .rela.got : { *(.rela.got) } + .rela.data : { *(.rela.data) *(.rela.data*) } + . = ALIGN(4096); + _etext = .; + _text_size = . - _text; + .data : { + _data = .; + *(.sdata) + *(.data) + *(.data1) + *(.data.*) + *(.got.plt) + *(.got) + + /* + * The EFI loader doesn't seem to like a .bss section, so we + * stick it all into .data: + */ + . = ALIGN(16); + _bss = .; + *(.sbss) + *(.scommon) + *(.dynbss) + *(.bss) + *(.bss.*) + *(COMMON) + . = ALIGN(512); + _bss_end = .; + _edata = .; + } :data + _data_size = _edata - _data; + + . = ALIGN(4096); + .dynsym : { *(.dynsym) } + . = ALIGN(4096); + .dynstr : { *(.dynstr) } + . = ALIGN(4096); + .note.gnu.build-id : { *(.note.gnu.build-id) } + /DISCARD/ : { + *(.rel.reloc) + *(.eh_frame) + *(.note.GNU-stack) + } + .comment 0 : { *(.comment) } +} diff --git a/lib/efi_selftest/efi_selftest_startimage_exit.c b/lib/efi_selftest/efi_selftest_startimage_exit.c index b65a10b7a4b..8d119f054c5 100644 --- a/lib/efi_selftest/efi_selftest_startimage_exit.c +++ b/lib/efi_selftest/efi_selftest_startimage_exit.c @@ -84,13 +84,15 @@ static efi_status_t decompress(u8 **image) static int setup(const efi_handle_t handle, const struct efi_system_table *systable) { + efi_status_t ret; + image_handle = handle; boottime = systable->boottime; /* Load the application image into memory */ - decompress(&image); + ret = decompress(&image); - return EFI_ST_SUCCESS; + return ret; } /* diff --git a/lib/gunzip.c b/lib/gunzip.c index e71d8d00ccb..52007715bda 100644 --- a/lib/gunzip.c +++ b/lib/gunzip.c @@ -15,6 +15,7 @@ #include <u-boot/crc.h> #include <watchdog.h> #include <u-boot/zlib.h> +#include <asm/sections.h> #define HEADER0 '\x1f' #define HEADER1 '\x8b' @@ -43,7 +44,7 @@ void gzfree(void *x, void *addr, unsigned nb) free (addr); } -int gzip_parse_header(const unsigned char *src, unsigned long len) +__rcode int gzip_parse_header(const unsigned char *src, unsigned long len) { int i, flags; @@ -71,7 +72,7 @@ int gzip_parse_header(const unsigned char *src, unsigned long len) return i; } -int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) +__rcode int gunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp) { int offset = gzip_parse_header(src, *lenp); @@ -274,8 +275,8 @@ out: /* * Uncompress blocks compressed with zlib without headers */ -int zunzip(void *dst, int dstlen, unsigned char *src, unsigned long *lenp, - int stoponerr, int offset) +__rcode int zunzip(void *dst, int dstlen, unsigned char *src, + unsigned long *lenp, int stoponerr, int offset) { z_stream s; int err = 0; diff --git a/lib/lz4.c b/lib/lz4.c index 63955a0b178..c718659c590 100644 --- a/lib/lz4.c +++ b/lib/lz4.c @@ -33,15 +33,16 @@ #include <linux/bug.h> #include <asm/unaligned.h> #include <u-boot/lz4.h> +#include <asm/sections.h> #define FORCE_INLINE inline __attribute__((always_inline)) -static FORCE_INLINE u16 LZ4_readLE16(const void *src) +__rcode static FORCE_INLINE u16 LZ4_readLE16(const void *src) { return get_unaligned_le16(src); } -static FORCE_INLINE void LZ4_copy8(void *dst, const void *src) +__rcode static FORCE_INLINE void LZ4_copy8(void *dst, const void *src) { put_unaligned(get_unaligned((const u64 *)src), (u64 *)dst); } @@ -53,7 +54,7 @@ typedef int32_t S32; typedef uint64_t U64; typedef uintptr_t uptrval; -static FORCE_INLINE void LZ4_write32(void *memPtr, U32 value) +__rcode static FORCE_INLINE void LZ4_write32(void *memPtr, U32 value) { put_unaligned(value, (U32 *)memPtr); } @@ -63,7 +64,7 @@ static FORCE_INLINE void LZ4_write32(void *memPtr, U32 value) **************************************/ /* customized version of memcpy, which may overwrite up to 7 bytes beyond dstEnd */ -static void LZ4_wildCopy(void* dstPtr, const void* srcPtr, void* dstEnd) +__rcode static void LZ4_wildCopy(void *dstPtr, const void *srcPtr, void *dstEnd) { BYTE* d = (BYTE*)dstPtr; const BYTE* s = (const BYTE*)srcPtr; @@ -112,13 +113,24 @@ typedef enum { decode_full_block = 0, partial_decode = 1 } earlyEnd_directive; #endif /* + * spl_reloc needs all necessary data to be set up within its code, since the + * code is relocated at runtime. Unfortunately this increase code-size slightly + * so only do it if spl_reloc is enabled + */ +#if CONFIG_IS_ENABLED(RELOC_LOADER) +#define STATIC +#else +#define STATIC static +#endif + +/* * LZ4_decompress_generic() : * This generic decompression function covers all use cases. * It shall be instantiated several times, using different sets of directives. * Note that it is important for performance that this function really get inlined, * in order to remove useless branches during compilation optimization. */ -static FORCE_INLINE int LZ4_decompress_generic( +__rcode static FORCE_INLINE int LZ4_decompress_generic( const char * const src, char * const dst, int srcSize, @@ -141,6 +153,8 @@ static FORCE_INLINE int LZ4_decompress_generic( const size_t dictSize ) { + STATIC const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4}; + STATIC const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3}; const BYTE *ip = (const BYTE *) src; const BYTE * const iend = ip + srcSize; @@ -149,8 +163,6 @@ static FORCE_INLINE int LZ4_decompress_generic( BYTE *cpy; const BYTE * const dictEnd = (const BYTE *)dictStart + dictSize; - static const unsigned int inc32table[8] = {0, 1, 2, 1, 0, 4, 4, 4}; - static const int dec64table[8] = {0, 0, 0, -1, -4, 1, 2, 3}; const int safeDecode = (endOnInput == endOnInputSize); const int checkOffset = ((safeDecode) && (dictSize < (int)(64 * KB))); @@ -514,8 +526,9 @@ _output_error: return (int) (-(((const char *)ip) - src)) - 1; } -int LZ4_decompress_safe(const char *source, char *dest, - int compressedSize, int maxDecompressedSize) +#ifndef CONFIG_SPL_BUILD +__rcode int LZ4_decompress_safe(const char *source, char *dest, + int compressedSize, int maxDecompressedSize) { return LZ4_decompress_generic(source, dest, compressedSize, maxDecompressedSize, @@ -523,11 +536,13 @@ int LZ4_decompress_safe(const char *source, char *dest, noDict, (BYTE *)dest, NULL, 0); } -int LZ4_decompress_safe_partial(const char *src, char *dst, - int compressedSize, int targetOutputSize, int dstCapacity) +__rcode int LZ4_decompress_safe_partial(const char *src, char *dst, + int compressedSize, + int targetOutputSize, int dstCapacity) { dstCapacity = min(targetOutputSize, dstCapacity); return LZ4_decompress_generic(src, dst, compressedSize, dstCapacity, endOnInputSize, partial_decode, noDict, (BYTE *)dst, NULL, 0); } +#endif diff --git a/lib/lz4_wrapper.c b/lib/lz4_wrapper.c index 4d48e7b0e8b..b1204511170 100644 --- a/lib/lz4_wrapper.c +++ b/lib/lz4_wrapper.c @@ -15,7 +15,7 @@ #define LZ4F_BLOCKUNCOMPRESSED_FLAG 0x80000000U -int ulz4fn(const void *src, size_t srcn, void *dst, size_t *dstn) +__rcode int ulz4fn(const void *src, size_t srcn, void *dst, size_t *dstn) { const void *end = dst + *dstn; const void *in = src; diff --git a/lib/mbedtls/Kconfig b/lib/mbedtls/Kconfig index 78167ffa252..35d8c507a89 100644 --- a/lib/mbedtls/Kconfig +++ b/lib/mbedtls/Kconfig @@ -112,6 +112,46 @@ config SPL_MD5_LEGACY endif # SPL +if VPL + +config VPL_SHA1_LEGACY + bool "Enable SHA1 support in VPL with legacy crypto library" + depends on LEGACY_CRYPTO_BASIC && VPL_SHA1 + help + This option enables support of hashing using SHA1 algorithm + with legacy crypto library. + +config VPL_SHA256_LEGACY + bool "Enable SHA256 support in VPL with legacy crypto library" + depends on LEGACY_CRYPTO_BASIC && VPL_SHA256 + help + This option enables support of hashing using SHA256 algorithm + with legacy crypto library. + +config VPL_SHA512_LEGACY + bool "Enable SHA512 support in VPL with legacy crypto library" + depends on LEGACY_CRYPTO_BASIC && VPL_SHA512 + help + This option enables support of hashing using SHA512 algorithm + with legacy crypto library. + +config VPL_SHA384_LEGACY + bool "Enable SHA384 support in VPL with legacy crypto library" + depends on LEGACY_CRYPTO_BASIC && VPL_SHA384 + select VPL_SHA512_LEGACY + help + This option enables support of hashing using SHA384 algorithm + with legacy crypto library. + +config VPL_MD5_LEGACY + bool "Enable MD5 support in VPL with legacy crypto library" + depends on LEGACY_CRYPTO_BASIC && VPL_MD5 + help + This option enables support of hashing using MD5 algorithm + with legacy crypto library. + +endif # VPL + endif # LEGACY_CRYPTO_BASIC config LEGACY_CRYPTO_CERT @@ -297,6 +337,13 @@ config MD5_MBEDTLS This option enables support of hashing using MD5 algorithm with MbedTLS crypto library. +config HKDF_MBEDTLS + bool "Enable HKDF support with MbedTLS crypto library" + depends on MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library. + if SPL config SPL_SHA1_MBEDTLS @@ -335,6 +382,13 @@ config SPL_MD5_MBEDTLS This option enables support of hashing using MD5 algorithm with MbedTLS crypto library. +config SPL_HKDF_MBEDTLS + bool "Enable HKDF support in SPL with MbedTLS crypto library" + depends on MBEDTLS_LIB_CRYPTO + help + This option enables support of key derivation using HKDF algorithm + with MbedTLS crypto library. + endif # SPL endif # MBEDTLS_LIB_CRYPTO diff --git a/lib/mbedtls/Makefile b/lib/mbedtls/Makefile index ce0a61e4054..e66c2018d97 100644 --- a/lib/mbedtls/Makefile +++ b/lib/mbedtls/Makefile @@ -33,6 +33,8 @@ mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA256_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/sha256.o mbedtls_lib_crypto-$(CONFIG_$(SPL_)SHA512_MBEDTLS) += \ $(MBEDTLS_LIB_DIR)/sha512.o +mbedtls_lib_crypto-$(CONFIG_$(SPL_)HKDF_MBEDTLS) += \ + $(MBEDTLS_LIB_DIR)/hkdf.o # MbedTLS X509 library obj-$(CONFIG_MBEDTLS_LIB_X509) += mbedtls_lib_x509.o diff --git a/lib/mbedtls/mbedtls_def_config.h b/lib/mbedtls/mbedtls_def_config.h index 1d2314e90e4..fd440c392f9 100644 --- a/lib/mbedtls/mbedtls_def_config.h +++ b/lib/mbedtls/mbedtls_def_config.h @@ -56,6 +56,10 @@ #endif #endif +#if CONFIG_IS_ENABLED(HKDF_MBEDTLS) +#define MBEDTLS_HKDF_C +#endif + #if defined CONFIG_MBEDTLS_LIB_X509 #if CONFIG_IS_ENABLED(X509_CERTIFICATE_PARSER) diff --git a/lib/mbedtls/sha256.c b/lib/mbedtls/sha256.c index 24aa58fa674..59edcb517df 100644 --- a/lib/mbedtls/sha256.c +++ b/lib/mbedtls/sha256.c @@ -10,6 +10,12 @@ #endif /* USE_HOSTCC */ #include <u-boot/sha256.h> +#include <mbedtls/md.h> + +#if CONFIG_IS_ENABLED(HKDF_MBEDTLS) +#include <mbedtls/hkdf.h> +#endif + const u8 sha256_der_prefix[SHA256_DER_LEN] = { 0x30, 0x31, 0x30, 0x0d, 0x06, 0x09, 0x60, 0x86, 0x48, 0x01, 0x65, 0x03, 0x04, 0x02, 0x01, 0x05, @@ -34,29 +40,34 @@ void sha256_finish(sha256_context *ctx, uint8_t digest[SHA256_SUM_LEN]) mbedtls_sha256_free(ctx); } -void sha256_csum_wd(const unsigned char *input, unsigned int ilen, - unsigned char *output, unsigned int chunk_sz) +int sha256_hmac(const unsigned char *key, int keylen, + const unsigned char *input, unsigned int ilen, + unsigned char *output) { - sha256_context ctx; - - sha256_starts(&ctx); - - if (IS_ENABLED(CONFIG_HW_WATCHDOG) || IS_ENABLED(CONFIG_WATCHDOG)) { - const unsigned char *curr = input; - const unsigned char *end = input + ilen; - int chunk; - - while (curr < end) { - chunk = end - curr; - if (chunk > chunk_sz) - chunk = chunk_sz; - sha256_update(&ctx, curr, chunk); - curr += chunk; - schedule(); - } - } else { - sha256_update(&ctx, input, ilen); - } - - sha256_finish(&ctx, output); + const mbedtls_md_info_t *md; + + md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + if (!md) + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + + return mbedtls_md_hmac(md, key, keylen, input, ilen, output); +} + +#if CONFIG_IS_ENABLED(HKDF_MBEDTLS) +int sha256_hkdf(const unsigned char *salt, int saltlen, + const unsigned char *ikm, int ikmlen, + const unsigned char *info, int infolen, + unsigned char *output, int outputlen) +{ + const mbedtls_md_info_t *md; + + md = mbedtls_md_info_from_type(MBEDTLS_MD_SHA256); + if (!md) + return MBEDTLS_ERR_MD_FEATURE_UNAVAILABLE; + + return mbedtls_hkdf(md, salt, saltlen, + ikm, ikmlen, + info, infolen, + output, outputlen); } +#endif diff --git a/lib/sha256.c b/lib/sha256.c index fb195d988f1..c2e77c854b9 100644 --- a/lib/sha256.c +++ b/lib/sha256.c @@ -265,38 +265,53 @@ void sha256_finish(sha256_context * ctx, uint8_t digest[32]) PUT_UINT32_BE(ctx->state[7], digest, 28); } -/* - * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz' - * bytes of input processed. - */ -void sha256_csum_wd(const unsigned char *input, unsigned int ilen, - unsigned char *output, unsigned int chunk_sz) +int sha256_hmac(const unsigned char *key, int keylen, + const unsigned char *input, unsigned int ilen, + unsigned char *output) { + int i; sha256_context ctx; -#if !defined(USE_HOSTCC) && \ - (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) - const unsigned char *end; - unsigned char *curr; - int chunk; -#endif + unsigned char keybuf[64]; + unsigned char k_ipad[64]; + unsigned char k_opad[64]; + unsigned char tmpbuf[32]; + int keybuf_len; + + if (keylen > 64) { + sha256_starts(&ctx); + sha256_update(&ctx, key, keylen); + sha256_finish(&ctx, keybuf); + + keybuf_len = 32; + } else { + memset(keybuf, 0, sizeof(keybuf)); + memcpy(keybuf, key, keylen); + keybuf_len = keylen; + } - sha256_starts(&ctx); + memset(k_ipad, 0x36, 64); + memset(k_opad, 0x5C, 64); -#if !defined(USE_HOSTCC) && \ - (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) - curr = (unsigned char *)input; - end = input + ilen; - while (curr < end) { - chunk = end - curr; - if (chunk > chunk_sz) - chunk = chunk_sz; - sha256_update(&ctx, curr, chunk); - curr += chunk; - schedule(); + for (i = 0; i < keybuf_len; i++) { + k_ipad[i] ^= keybuf[i]; + k_opad[i] ^= keybuf[i]; } -#else + + sha256_starts(&ctx); + sha256_update(&ctx, k_ipad, sizeof(k_ipad)); sha256_update(&ctx, input, ilen); -#endif + sha256_finish(&ctx, tmpbuf); + sha256_starts(&ctx); + sha256_update(&ctx, k_opad, sizeof(k_opad)); + sha256_update(&ctx, tmpbuf, sizeof(tmpbuf)); sha256_finish(&ctx, output); + + memset(k_ipad, 0, sizeof(k_ipad)); + memset(k_opad, 0, sizeof(k_opad)); + memset(tmpbuf, 0, sizeof(tmpbuf)); + memset(keybuf, 0, sizeof(keybuf)); + memset(&ctx, 0, sizeof(sha256_context)); + + return 0; } diff --git a/lib/sha256_common.c b/lib/sha256_common.c new file mode 100644 index 00000000000..7041abd26d9 --- /dev/null +++ b/lib/sha256_common.c @@ -0,0 +1,50 @@ +// SPDX-License-Identifier: GPL-2.0+ +/* + * FIPS-180-2 compliant SHA-256 implementation + * + * Copyright (C) 2001-2003 Christophe Devine + */ + +#ifndef USE_HOSTCC +#include <u-boot/schedule.h> +#endif /* USE_HOSTCC */ +#include <string.h> +#include <u-boot/sha256.h> + +#include <linux/compiler_attributes.h> + +/* + * Output = SHA-256( input buffer ). Trigger the watchdog every 'chunk_sz' + * bytes of input processed. + */ +void sha256_csum_wd(const unsigned char *input, unsigned int ilen, + unsigned char *output, unsigned int chunk_sz) +{ + sha256_context ctx; +#if !defined(USE_HOSTCC) && \ + (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) + const unsigned char *end; + unsigned char *curr; + int chunk; +#endif + + sha256_starts(&ctx); + +#if !defined(USE_HOSTCC) && \ + (defined(CONFIG_HW_WATCHDOG) || defined(CONFIG_WATCHDOG)) + curr = (unsigned char *)input; + end = input + ilen; + while (curr < end) { + chunk = end - curr; + if (chunk > chunk_sz) + chunk = chunk_sz; + sha256_update(&ctx, curr, chunk); + curr += chunk; + schedule(); + } +#else + sha256_update(&ctx, input, ilen); +#endif + + sha256_finish(&ctx, output); +} diff --git a/lib/smbios.c b/lib/smbios.c index defb6b42f45..78cee8c0c26 100644 --- a/lib/smbios.c +++ b/lib/smbios.c @@ -208,6 +208,43 @@ void get_str_from_dt(const struct map_sysinfo *nprop, char *str, size_t size) } /** + * smbios_get_val_si() - Get value from the devicetree or sysinfo + * + * @ctx: context of SMBIOS + * @prop: property to read + * @sysinfo_id: unique identifier for the value to be read + * @val_def: Default value + * Return: Valid value from sysinfo or device tree, otherwise val_def. + */ +static int smbios_get_val_si(struct smbios_ctx * __maybe_unused ctx, + const char * __maybe_unused prop, + int __maybe_unused sysinfo_id, int val_def) +{ +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + int val; + + if (!ctx->dev) + return val_def; + + if (!sysinfo_get_int(ctx->dev, sysinfo_id, &val)) + return val; + + if (!IS_ENABLED(CONFIG_OF_CONTROL) || !prop) + return val_def; + + if (ofnode_valid(ctx->node) && !ofnode_read_u32(ctx->node, prop, &val)) + return val; + + /* + * If the node or property is not valid fallback and try the root + */ + if (!ofnode_read_u32(ofnode_root(), prop, &val)) + return val; +#endif + return val_def; +} + +/** * smbios_add_prop_si() - Add a property from the devicetree or sysinfo * * Sysinfo is used if available, with a fallback to devicetree @@ -226,9 +263,6 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, if (!dval || !*dval) dval = NULL; - if (!prop) - return smbios_add_string(ctx, dval); - if (sysinfo_id && ctx->dev) { char val[SMBIOS_STR_MAX]; @@ -236,6 +270,9 @@ static int smbios_add_prop_si(struct smbios_ctx *ctx, const char *prop, if (!ret) return smbios_add_string(ctx, val); } + if (!prop) + return smbios_add_string(ctx, dval); + if (IS_ENABLED(CONFIG_OF_CONTROL)) { const char *str = NULL; char str_dt[128] = { 0 }; @@ -331,15 +368,17 @@ static int smbios_write_type0(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type0 *t; - int len = sizeof(struct smbios_type0); + int len = sizeof(*t); t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type0)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->vendor = smbios_add_prop(ctx, NULL, "U-Boot"); + t->vendor = smbios_add_prop_si(ctx, NULL, SYSID_SM_BIOS_VENDOR, + "U-Boot"); - t->bios_ver = smbios_add_prop(ctx, "version", PLAIN_VERSION); + t->bios_ver = smbios_add_prop_si(ctx, "version", SYSID_SM_BIOS_VER, + PLAIN_VERSION); if (t->bios_ver) gd->smbios_version = ctx->last_str; log_debug("smbios_version = %p: '%s'\n", gd->smbios_version, @@ -348,7 +387,9 @@ static int smbios_write_type0(ulong *current, int handle, print_buffer((ulong)gd->smbios_version, gd->smbios_version, 1, strlen(gd->smbios_version) + 1, 0); #endif - t->bios_release_date = smbios_add_prop(ctx, NULL, U_BOOT_DMI_DATE); + t->bios_release_date = smbios_add_prop_si(ctx, NULL, + SYSID_SM_BIOS_REL_DATE, + U_BOOT_DMI_DATE); #ifdef CONFIG_ROM_SIZE if (CONFIG_ROM_SIZE < SZ_16M) { t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1; @@ -375,7 +416,7 @@ static int smbios_write_type0(ulong *current, int handle, t->ec_major_release = 0xff; t->ec_minor_release = 0xff; - len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); @@ -386,37 +427,38 @@ static int smbios_write_type1(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type1 *t; - int len = sizeof(struct smbios_type1); + int len = sizeof(*t); char *serial_str = env_get("serial#"); t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type1)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); + t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", SYSID_SM_SYSTEM_MANUFACTURER, NULL); t->product_name = smbios_add_prop_si(ctx, "product", - SYSID_SM_SYSTEM_PRODUCT, - NULL); - t->version = smbios_add_prop_si(ctx, "version", - SYSID_SM_SYSTEM_VERSION, + SYSID_SM_SYSTEM_PRODUCT, NULL); + t->version = smbios_add_prop_si(ctx, "version", SYSID_SM_SYSTEM_VERSION, NULL); if (serial_str) { t->serial_number = smbios_add_prop(ctx, NULL, serial_str); - strncpy((char *)t->uuid, serial_str, sizeof(t->uuid)); + strlcpy((char *)t->uuid, serial_str, sizeof(t->uuid)); } else { t->serial_number = smbios_add_prop_si(ctx, "serial", SYSID_SM_SYSTEM_SERIAL, NULL); } - t->wakeup_type = SMBIOS_WAKEUP_TYPE_UNKNOWN; - t->sku_number = smbios_add_prop_si(ctx, "sku", - SYSID_SM_SYSTEM_SKU, NULL); - t->family = smbios_add_prop_si(ctx, "family", - SYSID_SM_SYSTEM_FAMILY, NULL); - - len = t->length + smbios_string_table_len(ctx); + t->wakeup_type = smbios_get_val_si(ctx, "wakeup-type", + SYSID_SM_SYSTEM_WAKEUP, + SMBIOS_WAKEUP_TYPE_UNKNOWN); + t->sku_number = smbios_add_prop_si(ctx, "sku", SYSID_SM_SYSTEM_SKU, + NULL); + t->family = smbios_add_prop_si(ctx, "family", SYSID_SM_SYSTEM_FAMILY, + NULL); + + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); @@ -427,33 +469,53 @@ static int smbios_write_type2(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type2 *t; - int len = sizeof(struct smbios_type2); + int len = sizeof(*t); + u8 *eos_addr; + /* + * reserve the space for the dynamic bytes of contained object handles. + * TODO: len += <obj_handle_num> * SMBIOS_TYPE2_CON_OBJ_HANDLE_SIZE + * obj_handle_num can be from DT node "baseboard" or sysinfo driver. + */ t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type2)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle); - smbios_set_eos(ctx, t->eos); + + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", SYSID_SM_BASEBOARD_MANUFACTURER, NULL); t->product_name = smbios_add_prop_si(ctx, "product", - SYSID_SM_BASEBOARD_PRODUCT, - NULL); + SYSID_SM_BASEBOARD_PRODUCT, NULL); t->version = smbios_add_prop_si(ctx, "version", - SYSID_SM_BASEBOARD_VERSION, - NULL); - + SYSID_SM_BASEBOARD_VERSION, NULL); t->serial_number = smbios_add_prop_si(ctx, "serial", - SYSID_SM_BASEBOARD_SERIAL, - NULL); + SYSID_SM_BASEBOARD_SERIAL, NULL); t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag", SYSID_SM_BASEBOARD_ASSET_TAG, NULL); - t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING; - t->board_type = SMBIOS_BOARD_MOTHERBOARD; + t->feature_flags = smbios_get_val_si(ctx, "feature-flags", + SYSID_SM_BASEBOARD_FEATURE, 0); + + t->chassis_location = + smbios_add_prop_si(ctx, "chassis-location", + SYSID_SM_BASEBOARD_CHASSIS_LOCAT, NULL); + t->board_type = smbios_get_val_si(ctx, "board-type", + SYSID_SM_BASEBOARD_TYPE, + SMBIOS_BOARD_TYPE_UNKNOWN); + + /* + * TODO: + * Populate the Contained Object Handles if they exist + * t->number_contained_objects = <obj_handle_num>; + */ + t->chassis_handle = handle + 1; - len = t->length + smbios_string_table_len(ctx); + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); @@ -464,20 +526,77 @@ static int smbios_write_type3(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type3 *t; - int len = sizeof(struct smbios_type3); + int len = sizeof(*t); + u8 *eos_addr; + size_t elem_size = 0; + __maybe_unused u8 *elem_addr; + __maybe_unused u8 *sku_num_addr; + + /* + * reserve the space for the dynamic bytes of contained elements. + * TODO: elem_size = <element_count> * <element_record_length> + * element_count and element_record_length can be from DT node + * "chassis" or sysinfo driver. + */ + len += elem_size; t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type3)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle); - smbios_set_eos(ctx, t->eos); - t->manufacturer = smbios_add_prop(ctx, "manufacturer", NULL); - t->chassis_type = SMBIOS_ENCLOSURE_DESKTOP; - t->bootup_state = SMBIOS_STATE_SAFE; - t->power_supply_state = SMBIOS_STATE_SAFE; - t->thermal_state = SMBIOS_STATE_SAFE; - t->security_status = SMBIOS_SECURITY_NONE; - - len = t->length + smbios_string_table_len(ctx); +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + elem_addr = (u8 *)t + offsetof(struct smbios_type3, sku_number); + sku_num_addr = elem_addr + elem_size; +#endif + /* eos is at the end of the structure */ + eos_addr = (u8 *)t + len - sizeof(t->eos); + smbios_set_eos(ctx, eos_addr); + + t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", + SYSID_SM_ENCLOSURE_MANUFACTURER, + NULL); + t->chassis_type = smbios_get_val_si(ctx, "chassis-type", + SYSID_SM_ENCLOSURE_TYPE, + SMBIOS_ENCLOSURE_UNKNOWN); + t->bootup_state = smbios_get_val_si(ctx, "bootup-state", + SYSID_SM_ENCLOSURE_BOOTUP, + SMBIOS_STATE_UNKNOWN); + t->power_supply_state = smbios_get_val_si(ctx, "power-supply-state", + SYSID_SM_ENCLOSURE_POW, + SMBIOS_STATE_UNKNOWN); + t->thermal_state = smbios_get_val_si(ctx, "thermal-state", + SYSID_SM_ENCLOSURE_THERMAL, + SMBIOS_STATE_UNKNOWN); + t->security_status = smbios_get_val_si(ctx, "security-status", + SYSID_SM_ENCLOSURE_SECURITY, + SMBIOS_SECURITY_UNKNOWN); + +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + t->version = smbios_add_prop_si(ctx, "version", + SYSID_SM_ENCLOSURE_VERSION, NULL); + t->serial_number = smbios_add_prop_si(ctx, "serial", + SYSID_SM_ENCLOSURE_SERIAL, NULL); + t->asset_tag_number = smbios_add_prop_si(ctx, "asset-tag", + SYSID_SM_BASEBOARD_ASSET_TAG, + NULL); + t->oem_defined = smbios_get_val_si(ctx, "oem-defined", + SYSID_SM_ENCLOSURE_OEM, 0); + t->height = smbios_get_val_si(ctx, "height", + SYSID_SM_ENCLOSURE_HEIGHT, 0); + t->number_of_power_cords = + smbios_get_val_si(ctx, "number-of-power-cords", + SYSID_SM_ENCLOSURE_POWCORE_NUM, 0); + + /* + * TODO: Populate the Contained Element Record if they exist + * t->element_count = <element_num>; + * t->element_record_length = <element_len>; + */ + + *sku_num_addr = smbios_add_prop_si(ctx, "sku", SYSID_SM_ENCLOSURE_SKU, + NULL); +#endif + + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); @@ -490,6 +609,8 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN; const char *vendor = NULL; const char *name = NULL; + __maybe_unused void *id_data = NULL; + __maybe_unused size_t id_size = 0; #ifdef CONFIG_CPU char processor_name[49]; @@ -511,46 +632,234 @@ static void smbios_write_type4_dm(struct smbios_type4 *t, name = processor_name; } #endif + if (processor_family == SMBIOS_PROCESSOR_FAMILY_UNKNOWN) + processor_family = + smbios_get_val_si(ctx, "family", + SYSID_SM_PROCESSOR_FAMILY, + SMBIOS_PROCESSOR_FAMILY_UNKNOWN); + + if (processor_family == SMBIOS_PROCESSOR_FAMILY_EXT) + t->processor_family2 = + smbios_get_val_si(ctx, "family2", + SYSID_SM_PROCESSOR_FAMILY2, + SMBIOS_PROCESSOR_FAMILY_UNKNOWN); + + t->processor_family = processor_family; + t->processor_manufacturer = + smbios_add_prop_si(ctx, "manufacturer", + SYSID_SM_PROCESSOR_MANUFACT, vendor); + t->processor_version = smbios_add_prop_si(ctx, "version", + SYSID_SM_PROCESSOR_VERSION, + name); + +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + if (t->processor_id[0] || t->processor_id[1] || + sysinfo_get_data(ctx->dev, SYSID_SM_PROCESSOR_ID, &id_data, + &id_size)) + return; - t->processor_family = 0xfe; - t->processor_family2 = processor_family; - t->processor_manufacturer = smbios_add_prop(ctx, NULL, vendor); - t->processor_version = smbios_add_prop(ctx, NULL, name); + if (id_data && id_size == sizeof(t->processor_id)) + memcpy((u8 *)t->processor_id, id_data, id_size); +#endif } static int smbios_write_type4(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type4 *t; - int len = sizeof(struct smbios_type4); + int len = sizeof(*t); + __maybe_unused void *hdl; + __maybe_unused size_t hdl_size; t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type4)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); - t->processor_type = SMBIOS_PROCESSOR_TYPE_CENTRAL; + t->socket_design = smbios_add_prop_si(ctx, "socket-design", + SYSID_SM_PROCESSOR_SOCKET, NULL); + t->processor_type = smbios_get_val_si(ctx, "processor-type", + SYSID_SM_PROCESSOR_TYPE, + SMBIOS_PROCESSOR_TYPE_UNKNOWN); smbios_write_type4_dm(t, ctx); - t->status = SMBIOS_PROCESSOR_STATUS_ENABLED; - t->processor_upgrade = SMBIOS_PROCESSOR_UPGRADE_NONE; - t->l1_cache_handle = 0xffff; - t->l2_cache_handle = 0xffff; - t->l3_cache_handle = 0xffff; - len = t->length + smbios_string_table_len(ctx); + t->status = smbios_get_val_si(ctx, "processor-status", + SYSID_SM_PROCESSOR_STATUS, + SMBIOS_PROCESSOR_STATUS_UNKNOWN); + t->processor_upgrade = + smbios_get_val_si(ctx, "upgrade", SYSID_SM_PROCESSOR_UPGRADE, + SMBIOS_PROCESSOR_UPGRADE_UNKNOWN); + + t->l1_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + t->l2_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + t->l3_cache_handle = SMBIOS_CACHE_HANDLE_NONE; + +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + t->voltage = smbios_get_val_si(ctx, "voltage", + SYSID_SM_PROCESSOR_VOLTAGE, 0); + t->external_clock = smbios_get_val_si(ctx, "external-clock", + SYSID_SM_PROCESSOR_EXT_CLOCK, 0); + t->max_speed = smbios_get_val_si(ctx, "max-speed", + SYSID_SM_PROCESSOR_MAX_SPEED, 0); + t->current_speed = smbios_get_val_si(ctx, "current-speed", + SYSID_SM_PROCESSOR_CUR_SPEED, 0); + + /* Read the cache handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_CACHE_HANDLE, &hdl, + &hdl_size) && + (hdl_size == SYSINFO_CACHE_LVL_MAX * sizeof(u16))) { + u16 *handle = (u16 *)hdl; + + if (*handle) + t->l1_cache_handle = *handle; + + handle++; + if (*handle) + t->l2_cache_handle = *handle; + + handle++; + if (*handle) + t->l3_cache_handle = *handle; + } + + t->serial_number = smbios_add_prop_si(ctx, "serial", + SYSID_SM_PROCESSOR_SN, NULL); + t->asset_tag = smbios_add_prop_si(ctx, "asset-tag", + SYSID_SM_PROCESSOR_ASSET_TAG, NULL); + t->part_number = smbios_add_prop_si(ctx, "part-number", + SYSID_SM_PROCESSOR_PN, NULL); + t->core_count = smbios_get_val_si(ctx, "core-count", + SYSID_SM_PROCESSOR_CORE_CNT, 0); + t->core_enabled = smbios_get_val_si(ctx, "core-enabled", + SYSID_SM_PROCESSOR_CORE_EN, 0); + t->thread_count = smbios_get_val_si(ctx, "thread-count", + SYSID_SM_PROCESSOR_THREAD_CNT, 0); + t->processor_characteristics = + smbios_get_val_si(ctx, "characteristics", + SYSID_SM_PROCESSOR_CHARA, + SMBIOS_PROCESSOR_UND); + t->core_count2 = smbios_get_val_si(ctx, "core-count2", + SYSID_SM_PROCESSOR_CORE_CNT2, 0); + t->core_enabled2 = smbios_get_val_si(ctx, "core-enabled2", + SYSID_SM_PROCESSOR_CORE_EN2, 0); + t->thread_count2 = smbios_get_val_si(ctx, "thread-count2", + SYSID_SM_PROCESSOR_THREAD_CNT2, 0); + t->thread_enabled = smbios_get_val_si(ctx, "thread-enabled", + SYSID_SM_PROCESSOR_THREAD_EN, 0); +#endif + + len = t->hdr.length + smbios_string_table_len(ctx); + *current += len; + unmap_sysmem(t); + + return len; +} + +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + +static int smbios_write_type7_1level(ulong *current, int handle, + struct smbios_ctx *ctx, int level) +{ + struct smbios_type7 *t; + int len = sizeof(*t); + void *hdl; + size_t hdl_size; + + t = map_sysmem(*current, len); + memset(t, 0, len); + fill_smbios_header(t, SMBIOS_CACHE_INFORMATION, len, handle); + smbios_set_eos(ctx, t->eos); + + t->socket_design = smbios_add_prop_si(ctx, "socket-design", + SYSID_SM_CACHE_SOCKET + level, + NULL); + t->config.data = smbios_get_val_si(ctx, "config", + SYSID_SM_CACHE_CONFIG + level, + (level - 1) | SMBIOS_CACHE_OP_UND); + t->max_size.data = smbios_get_val_si(ctx, "max-size", + SYSID_SM_CACHE_MAX_SIZE + level, + 0); + t->inst_size.data = smbios_get_val_si(ctx, "installed-size", + SYSID_SM_CACHE_INST_SIZE + level, + 0); + t->supp_sram_type.data = + smbios_get_val_si(ctx, "supported-sram-type", + SYSID_SM_CACHE_SUPSRAM_TYPE + level, + SMBIOS_CACHE_SRAM_TYPE_UNKNOWN); + t->curr_sram_type.data = + smbios_get_val_si(ctx, "current-sram-type", + SYSID_SM_CACHE_CURSRAM_TYPE + level, + SMBIOS_CACHE_SRAM_TYPE_UNKNOWN); + t->speed = smbios_get_val_si(ctx, "speed", SYSID_SM_CACHE_SPEED + level, + 0); + t->err_corr_type = smbios_get_val_si(ctx, "error-correction-type", + SYSID_SM_CACHE_ERRCOR_TYPE + level, + SMBIOS_CACHE_ERRCORR_UNKNOWN); + t->sys_cache_type = + smbios_get_val_si(ctx, "system-cache-type", + SYSID_SM_CACHE_SCACHE_TYPE + level, + SMBIOS_CACHE_SYSCACHE_TYPE_UNKNOWN); + t->associativity = smbios_get_val_si(ctx, "associativity", + SYSID_SM_CACHE_ASSOC + level, + SMBIOS_CACHE_ASSOC_UNKNOWN); + t->max_size2.data = smbios_get_val_si(ctx, "max-size2", + SYSID_SM_CACHE_MAX_SIZE2 + level, + 0); + t->inst_size2.data = + smbios_get_val_si(ctx, "installed-size2", + SYSID_SM_CACHE_INST_SIZE2 + level, 0); + + /* Save the cache handles */ + if (!sysinfo_get_data(ctx->dev, SYSID_SM_CACHE_HANDLE, &hdl, + &hdl_size)) { + if (hdl_size == SYSINFO_CACHE_LVL_MAX * sizeof(u16)) + *((u16 *)hdl + level) = handle; + } + + len = t->hdr.length + smbios_string_table_len(ctx); *current += len; unmap_sysmem(t); return len; } +static int smbios_write_type7(ulong *current, int handle, + struct smbios_ctx *ctx) +{ + int len = 0; + int i, level; + ofnode parent = ctx->node; + struct smbios_ctx ctx_bak; + + memcpy(&ctx_bak, ctx, sizeof(ctx_bak)); + + /* Get the number of level */ + level = smbios_get_val_si(ctx, NULL, SYSID_SM_CACHE_LEVEL, 0); + if (level >= SYSINFO_CACHE_LVL_MAX) /* Error, return 0-length */ + return 0; + + for (i = 0; i <= level; i++) { + char buf[9] = ""; + + if (!snprintf(buf, sizeof(buf), "l%d-cache", i + 1)) + return 0; + ctx->subnode_name = buf; + ctx->node = ofnode_find_subnode(parent, ctx->subnode_name); + len += smbios_write_type7_1level(current, handle++, ctx, i); + memcpy(ctx, &ctx_bak, sizeof(*ctx)); + } + return len; +} + +#endif /* #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) */ + static int smbios_write_type32(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type32 *t; - int len = sizeof(struct smbios_type32); + int len = sizeof(*t); t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type32)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle); smbios_set_eos(ctx, t->eos); @@ -564,10 +873,10 @@ static int smbios_write_type127(ulong *current, int handle, struct smbios_ctx *ctx) { struct smbios_type127 *t; - int len = sizeof(struct smbios_type127); + int len = sizeof(*t); t = map_sysmem(*current, len); - memset(t, 0, sizeof(struct smbios_type127)); + memset(t, 0, len); fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle); *current += len; @@ -582,7 +891,11 @@ static struct smbios_write_method smbios_write_funcs[] = { { smbios_write_type2, "baseboard", }, /* Type 3 must immediately follow type 2 due to chassis handle. */ { smbios_write_type3, "chassis", }, - { smbios_write_type4, }, +#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) + /* Type 7 must ahead of type 4 to get cache handles. */ + { smbios_write_type7, "cache", }, +#endif + { smbios_write_type4, "processor"}, { smbios_write_type32, }, { smbios_write_type127 }, }; @@ -599,7 +912,7 @@ ulong write_smbios_table(ulong addr) int i; ctx.node = ofnode_null(); - if (IS_ENABLED(CONFIG_OF_CONTROL) && CONFIG_IS_ENABLED(SYSINFO)) { + if (CONFIG_IS_ENABLED(SYSINFO)) { uclass_first_device(UCLASS_SYSINFO, &ctx.dev); if (ctx.dev) { int ret; diff --git a/lib/string.c b/lib/string.c index feae9519f2f..0e0900de8bf 100644 --- a/lib/string.c +++ b/lib/string.c @@ -21,6 +21,7 @@ #include <linux/string.h> #include <linux/ctype.h> #include <malloc.h> +#include <asm/sections.h> /** * strncasecmp - Case insensitive, length-limited string comparison @@ -559,7 +560,7 @@ __used void * memset(void * s,int c,size_t count) * You should not use this function to access IO space, use memcpy_toio() * or memcpy_fromio() instead. */ -__used void * memcpy(void *dest, const void *src, size_t count) +__rcode __used void *memcpy(void *dest, const void *src, size_t count) { unsigned long *dl = (unsigned long *)dest, *sl = (unsigned long *)src; char *d8, *s8; @@ -593,7 +594,7 @@ __used void * memcpy(void *dest, const void *src, size_t count) * * Unlike memcpy(), memmove() copes with overlapping areas. */ -__used void * memmove(void * dest,const void *src,size_t count) +__rcode __used void *memmove(void *dest, const void *src, size_t count) { char *tmp, *s; diff --git a/lib/tpm-v2.c b/lib/tpm-v2.c index ad2b5ab0c32..9ca7933c094 100644 --- a/lib/tpm-v2.c +++ b/lib/tpm-v2.c @@ -23,12 +23,155 @@ #include "tpm-utils.h" -u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode) +static int tpm2_update_active_banks(struct udevice *dev) { + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); + struct tpml_pcr_selection pcrs; + int ret, i; + + ret = tpm2_get_pcr_info(dev, &pcrs); + if (ret) + return ret; + + priv->active_bank_count = 0; + for (i = 0; i < pcrs.count; i++) { + if (!tpm2_is_active_bank(&pcrs.selection[i])) + continue; + priv->active_banks[priv->active_bank_count] = pcrs.selection[i].hash; + priv->active_bank_count++; + } + + return 0; +} + +static void tpm2_print_selected_algorithm_name(u32 selected) +{ + size_t i; + const char *str; + + for (i = 0; i < ARRAY_SIZE(hash_algo_list); i++) { + const struct digest_info *algo = &hash_algo_list[i]; + + if (!(selected & algo->hash_mask)) + continue; + + str = tpm2_algorithm_name(algo->hash_alg); + if (str) + log_info("%s\n", str); + } +} + +int tpm2_scan_masks(struct udevice *dev, u32 log_active, u32 *mask) +{ + struct tpml_pcr_selection pcrs; + u32 active = 0; + u32 supported = 0; + int rc, i; + + *mask = 0; + + rc = tpm2_get_pcr_info(dev, &pcrs); + if (rc) + return rc; + + for (i = 0; i < pcrs.count; i++) { + struct tpms_pcr_selection *sel = &pcrs.selection[i]; + size_t j; + u32 hash_mask = 0; + + for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) { + if (hash_algo_list[j].hash_alg == sel->hash) + hash_mask = hash_algo_list[j].hash_mask; + } + + if (tpm2_algorithm_supported(sel->hash)) + supported |= hash_mask; + + if (tpm2_is_active_bank(sel)) + active |= hash_mask; + } + + /* All eventlog algorithm(s) must be supported */ + if (log_active & ~supported) { + log_err("EventLog contains U-Boot unsupported algorithm(s)\n"); + tpm2_print_selected_algorithm_name(log_active & ~supported); + rc = -1; + } + if (log_active && active & ~log_active) { + log_warning("TPM active algorithm(s) not exist in eventlog\n"); + tpm2_print_selected_algorithm_name(active & ~log_active); + *mask = log_active; + } + + /* Any active algorithm(s) which are not supported must be removed */ + if (active & ~supported) { + log_warning("TPM active algorithm(s) unsupported by u-boot\n"); + tpm2_print_selected_algorithm_name(active & ~supported); + if (*mask) + *mask = active & supported & *mask; + else + *mask = active & supported; + } + + return rc; +} + +static int tpm2_pcr_allocate(struct udevice *dev, u32 algo_mask) +{ + struct tpml_pcr_selection pcr = { 0 }; + u32 pcr_len = 0; + int rc; + + rc = tpm2_get_pcr_info(dev, &pcr); + if (rc) + return rc; + + rc = tpm2_pcr_config_algo(dev, algo_mask, &pcr, &pcr_len); + if (rc) + return rc; + + /* Assume no password */ + rc = tpm2_send_pcr_allocate(dev, NULL, 0, &pcr, pcr_len); + if (rc) + return rc; + + /* Send TPM2_Shutdown, assume mode = TPM2_SU_CLEAR */ + return tpm2_startup(dev, false, TPM2_SU_CLEAR); +} + +int tpm2_activate_banks(struct udevice *dev, u32 log_active) +{ + u32 algo_mask = 0; + int rc; + + rc = tpm2_scan_masks(dev, log_active, &algo_mask); + if (rc) + return rc; + + if (algo_mask) { + if (!IS_ENABLED(CONFIG_TPM_PCR_ALLOCATE)) + return -1; + + rc = tpm2_pcr_allocate(dev, algo_mask); + if (rc) + return rc; + + log_info("PCR allocate done, shutdown TPM and reboot\n"); + do_reset(NULL, 0, 0, NULL); + log_err("reset does not work!\n"); + return -1; + } + + return 0; +} + +u32 tpm2_startup(struct udevice *dev, bool bon, enum tpm2_startup_types mode) +{ + int op = bon ? TPM2_CC_STARTUP : TPM2_CC_SHUTDOWN; const u8 command_v2[12] = { tpm_u16(TPM2_ST_NO_SESSIONS), tpm_u32(12), - tpm_u32(TPM2_CC_STARTUP), + tpm_u32(op), tpm_u16(mode), }; int ret; @@ -38,10 +181,10 @@ u32 tpm2_startup(struct udevice *dev, enum tpm2_startup_types mode) * but will return RC_INITIALIZE otherwise. */ ret = tpm_sendrecv_command(dev, command_v2, NULL, NULL); - if (ret && ret != TPM2_RC_INITIALIZE) + if ((ret && ret != TPM2_RC_INITIALIZE) || !bon) return ret; - return 0; + return tpm2_update_active_banks(dev); } u32 tpm2_self_test(struct udevice *dev, enum tpm2_yes_no full_test) @@ -63,14 +206,16 @@ u32 tpm2_auto_start(struct udevice *dev) rc = tpm2_self_test(dev, TPMI_YES); if (rc == TPM2_RC_INITIALIZE) { - rc = tpm2_startup(dev, TPM2_SU_CLEAR); + rc = tpm2_startup(dev, true, TPM2_SU_CLEAR); if (rc) return rc; rc = tpm2_self_test(dev, TPMI_YES); } + if (rc) + return rc; - return rc; + return tpm2_update_active_banks(dev); } u32 tpm2_clear(struct udevice *dev, u32 handle, const char *pw, @@ -197,9 +342,12 @@ u32 tpm2_pcr_extend(struct udevice *dev, u32 index, u32 algorithm, if (!digest) return -EINVAL; - if (!tpm2_allow_extend(dev)) { + if (!tpm2_check_active_banks(dev)) { log_err("Cannot extend PCRs if all the TPM enabled algorithms are not supported\n"); - return -EINVAL; + + ret = tpm2_pcr_allocate(dev, 0); + if (ret) + return -EINVAL; } /* * Fill the command structure starting from the first buffer: @@ -376,6 +524,130 @@ u32 tpm2_get_capability(struct udevice *dev, u32 capability, u32 property, return 0; } +u32 tpm2_pcr_config_algo(struct udevice *dev, u32 algo_mask, + struct tpml_pcr_selection *pcr, u32 *pcr_len) +{ + int i; + + if (pcr->count > TPM2_NUM_PCR_BANKS) + return TPM_LIB_ERROR; + + *pcr_len = sizeof(pcr->count); + + for (i = 0; i < pcr->count; i++) { + struct tpms_pcr_selection *sel = &pcr->selection[i]; + u8 pad = 0; + int j; + + if (sel->size_of_select > TPM2_PCR_SELECT_MAX) + return TPM_LIB_ERROR; + + /* + * Found the algorithm (bank) that matches, and enable all PCR + * bits. + * TODO: only select the bits needed + */ + for (j = 0; j < ARRAY_SIZE(hash_algo_list); j++) { + if (hash_algo_list[j].hash_alg != sel->hash) + continue; + + if (algo_mask & hash_algo_list[j].hash_mask) + pad = 0xff; + } + + for (j = 0; j < sel->size_of_select; j++) + sel->pcr_select[j] = pad; + + log_info("set bank[%d] %s %s\n", i, + tpm2_algorithm_name(sel->hash), + tpm2_is_active_bank(sel) ? "on" : "off"); + + *pcr_len += sizeof(sel->hash) + sizeof(sel->size_of_select) + + sel->size_of_select; + } + + return 0; +} + +u32 tpm2_send_pcr_allocate(struct udevice *dev, const char *pw, + const ssize_t pw_sz, struct tpml_pcr_selection *pcr, + u32 pcr_len) +{ + /* Length of the message header, up to start of password */ + uint offset = 27; + u8 command_v2[COMMAND_BUFFER_SIZE] = { + tpm_u16(TPM2_ST_SESSIONS), /* TAG */ + tpm_u32(offset + pw_sz + pcr_len), /* Length */ + tpm_u32(TPM2_CC_PCR_ALLOCATE), /* Command code */ + + /* handles 4 bytes */ + tpm_u32(TPM2_RH_PLATFORM), /* Primary platform seed */ + + /* AUTH_SESSION */ + tpm_u32(9 + pw_sz), /* Authorization size */ + tpm_u32(TPM2_RS_PW), /* Session handle */ + tpm_u16(0), /* Size of <nonce> */ + /* <nonce> (if any) */ + 0, /* Attributes: Cont/Excl/Rst */ + tpm_u16(pw_sz), /* Size of <hmac/password> */ + /* STRING(pw) <hmac/password> (if any) */ + + /* TPML_PCR_SELECTION */ + }; + u8 response[COMMAND_BUFFER_SIZE]; + size_t response_len = COMMAND_BUFFER_SIZE; + u32 i; + int ret; + + /* + * Fill the command structure starting from the first buffer: + * the password (if any) + */ + if (pack_byte_string(command_v2, sizeof(command_v2), "s", offset, pw, + pw_sz)) + return TPM_LIB_ERROR; + + offset += pw_sz; + + /* Pack the count field */ + if (pack_byte_string(command_v2, sizeof(command_v2), "d", offset, pcr->count)) + return TPM_LIB_ERROR; + + offset += sizeof(pcr->count); + + /* Pack each tpms_pcr_selection */ + for (i = 0; i < pcr->count; i++) { + struct tpms_pcr_selection *sel = &pcr->selection[i]; + + /* Pack hash (16-bit) */ + if (pack_byte_string(command_v2, sizeof(command_v2), "w", offset, + sel->hash)) + return TPM_LIB_ERROR; + + offset += sizeof(sel->hash); + + /* Pack size_of_select (8-bit) */ + if (pack_byte_string(command_v2, sizeof(command_v2), "b", offset, + sel->size_of_select)) + return TPM_LIB_ERROR; + + offset += sizeof(sel->size_of_select); + + /* Pack pcr_select array */ + if (pack_byte_string(command_v2, sizeof(command_v2), "s", offset, + sel->pcr_select, sel->size_of_select)) + return TPM_LIB_ERROR; + + offset += sel->size_of_select; + } + + ret = tpm_sendrecv_command(dev, command_v2, response, &response_len); + if (!ret) + tpm_init(dev); + + return ret; +} + static int tpm2_get_num_pcr(struct udevice *dev, u32 *num_pcr) { u8 response[(sizeof(struct tpms_capability_data) - @@ -847,7 +1119,7 @@ u32 tpm2_enable_nvcommits(struct udevice *dev, uint vendor_cmd, return 0; } -bool tpm2_is_active_pcr(struct tpms_pcr_selection *selection) +bool tpm2_is_active_bank(struct tpms_pcr_selection *selection) { int i; @@ -884,6 +1156,18 @@ const char *tpm2_algorithm_name(enum tpm2_algorithms algo) return ""; } +bool tpm2_algorithm_supported(enum tpm2_algorithms algo) +{ + size_t i; + + for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) { + if (hash_algo_list[i].hash_alg == algo) + return hash_algo_list[i].supported; + } + + return false; +} + u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo) { size_t i; @@ -896,7 +1180,7 @@ u16 tpm2_algorithm_to_len(enum tpm2_algorithms algo) return 0; } -bool tpm2_allow_extend(struct udevice *dev) +bool tpm2_check_active_banks(struct udevice *dev) { struct tpml_pcr_selection pcrs; size_t i; @@ -907,10 +1191,33 @@ bool tpm2_allow_extend(struct udevice *dev) return false; for (i = 0; i < pcrs.count; i++) { - if (tpm2_is_active_pcr(&pcrs.selection[i]) && - !tpm2_algorithm_to_len(pcrs.selection[i].hash)) + if (tpm2_is_active_bank(&pcrs.selection[i]) && + !tpm2_algorithm_supported(pcrs.selection[i].hash)) return false; } return true; } + +void tpm2_print_active_banks(struct udevice *dev) +{ + struct tpml_pcr_selection pcrs; + size_t i; + int rc; + + rc = tpm2_get_pcr_info(dev, &pcrs); + if (rc) { + log_err("Can't retrieve active PCRs\n"); + return; + } + + for (i = 0; i < pcrs.count; i++) { + if (tpm2_is_active_bank(&pcrs.selection[i])) { + const char *str; + + str = tpm2_algorithm_name(pcrs.selection[i].hash); + if (str) + log_info("%s\n", str); + } + } +} diff --git a/lib/tpm_api.c b/lib/tpm_api.c index 39a5121e302..576d601e5ff 100644 --- a/lib/tpm_api.c +++ b/lib/tpm_api.c @@ -28,7 +28,7 @@ u32 tpm_startup(struct udevice *dev, enum tpm_startup_type mode) case TPM_ST_DEACTIVATED: return -EINVAL; } - return tpm2_startup(dev, type); + return tpm2_startup(dev, true, type); } else { return -ENOSYS; } @@ -60,7 +60,7 @@ u32 tpm_resume(struct udevice *dev) if (tpm_is_v1(dev)) return tpm1_startup(dev, TPM_ST_STATE); else if (tpm_is_v2(dev)) - return tpm2_startup(dev, TPM2_SU_STATE); + return tpm2_startup(dev, true, TPM2_SU_STATE); else return -ENOSYS; } diff --git a/lib/tpm_tcg2.c b/lib/tpm_tcg2.c index 7f868cc8837..c314b401d0b 100644 --- a/lib/tpm_tcg2.c +++ b/lib/tpm_tcg2.c @@ -19,39 +19,38 @@ #include <linux/unaligned/generic.h> #include <linux/unaligned/le_byteshift.h> #include "tpm-utils.h" +#include <bloblist.h> -int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_pcr, u32 *active_pcr, - u32 *pcr_banks) +int tcg2_get_pcr_info(struct udevice *dev, u32 *supported_bank, u32 *active_bank, + u32 *bank_num) { - u8 response[(sizeof(struct tpms_capability_data) - - offsetof(struct tpms_capability_data, data))]; struct tpml_pcr_selection pcrs; size_t i; u32 ret; - *supported_pcr = 0; - *active_pcr = 0; - *pcr_banks = 0; - memset(response, 0, sizeof(response)); + *supported_bank = 0; + *active_bank = 0; + *bank_num = 0; ret = tpm2_get_pcr_info(dev, &pcrs); if (ret) return ret; for (i = 0; i < pcrs.count; i++) { - u32 hash_mask = tcg2_algorithm_to_mask(pcrs.selection[i].hash); + struct tpms_pcr_selection *sel = &pcrs.selection[i]; + u32 hash_mask = tcg2_algorithm_to_mask(sel->hash); - if (hash_mask) { - *supported_pcr |= hash_mask; - if (tpm2_is_active_pcr(&pcrs.selection[i])) - *active_pcr |= hash_mask; - } else { - printf("%s: unknown algorithm %x\n", __func__, - pcrs.selection[i].hash); - } + if (tpm2_algorithm_supported(sel->hash)) + *supported_bank |= hash_mask; + else + log_warning("%s: unknown algorithm %x\n", __func__, + sel->hash); + + if (tpm2_is_active_bank(sel)) + *active_bank |= hash_mask; } - *pcr_banks = pcrs.count; + *bank_num = pcrs.count; return 0; } @@ -95,57 +94,64 @@ u32 tcg2_event_get_size(struct tpml_digest_values *digest_list) int tcg2_create_digest(struct udevice *dev, const u8 *input, u32 length, struct tpml_digest_values *digest_list) { + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); u8 final[sizeof(union tpmu_ha)]; +#if IS_ENABLED(CONFIG_SHA256) sha256_context ctx_256; +#endif +#if IS_ENABLED(CONFIG_SHA512) sha512_context ctx_512; +#endif +#if IS_ENABLED(CONFIG_SHA1) sha1_context ctx; - u32 active; +#endif size_t i; u32 len; - int rc; - - rc = tcg2_get_active_pcr_banks(dev, &active); - if (rc) - return rc; digest_list->count = 0; - for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) { - if (!(active & hash_algo_list[i].hash_mask)) - continue; + for (i = 0; i < priv->active_bank_count; i++) { - switch (hash_algo_list[i].hash_alg) { + switch (priv->active_banks[i]) { +#if IS_ENABLED(CONFIG_SHA1) case TPM2_ALG_SHA1: sha1_starts(&ctx); sha1_update(&ctx, input, length); sha1_finish(&ctx, final); len = TPM2_SHA1_DIGEST_SIZE; break; +#endif +#if IS_ENABLED(CONFIG_SHA256) case TPM2_ALG_SHA256: sha256_starts(&ctx_256); sha256_update(&ctx_256, input, length); sha256_finish(&ctx_256, final); len = TPM2_SHA256_DIGEST_SIZE; break; +#endif +#if IS_ENABLED(CONFIG_SHA384) case TPM2_ALG_SHA384: sha384_starts(&ctx_512); sha384_update(&ctx_512, input, length); sha384_finish(&ctx_512, final); len = TPM2_SHA384_DIGEST_SIZE; break; +#endif +#if IS_ENABLED(CONFIG_SHA512) case TPM2_ALG_SHA512: sha512_starts(&ctx_512); sha512_update(&ctx_512, input, length); sha512_finish(&ctx_512, final); len = TPM2_SHA512_DIGEST_SIZE; break; +#endif default: printf("%s: unsupported algorithm %x\n", __func__, - hash_algo_list[i].hash_alg); + priv->active_banks[i]); continue; } digest_list->digests[digest_list->count].hash_alg = - hash_algo_list[i].hash_alg; + priv->active_banks[i]; memcpy(&digest_list->digests[digest_list->count].digest, final, len); digest_list->count++; @@ -216,37 +222,17 @@ static int tcg2_log_append_check(struct tcg2_event_log *elog, u32 pcr_index, static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog) { + struct tpm_chip_priv *priv = dev_get_uclass_priv(dev); struct tcg_efi_spec_id_event *ev; struct tcg_pcr_event *log; u32 event_size; u32 count = 0; u32 log_size; - u32 active; size_t i; u16 len; - int rc; - - rc = tcg2_get_active_pcr_banks(dev, &active); - if (rc) - return rc; + count = priv->active_bank_count; event_size = offsetof(struct tcg_efi_spec_id_event, digest_sizes); - for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) { - if (!(active & hash_algo_list[i].hash_mask)) - continue; - - switch (hash_algo_list[i].hash_alg) { - case TPM2_ALG_SHA1: - case TPM2_ALG_SHA256: - case TPM2_ALG_SHA384: - case TPM2_ALG_SHA512: - count++; - break; - default: - continue; - } - } - event_size += 1 + (sizeof(struct tcg_efi_spec_id_event_algorithm_size) * count); log_size = offsetof(struct tcg_pcr_event, event) + event_size; @@ -273,19 +259,11 @@ static int tcg2_log_init(struct udevice *dev, struct tcg2_event_log *elog) ev->uintn_size = sizeof(size_t) / sizeof(u32); put_unaligned_le32(count, &ev->number_of_algorithms); - count = 0; - for (i = 0; i < ARRAY_SIZE(hash_algo_list); ++i) { - if (!(active & hash_algo_list[i].hash_mask)) - continue; - - len = hash_algo_list[i].hash_len; - if (!len) - continue; - - put_unaligned_le16(hash_algo_list[i].hash_alg, - &ev->digest_sizes[count].algorithm_id); - put_unaligned_le16(len, &ev->digest_sizes[count].digest_size); - count++; + for (i = 0; i < count; ++i) { + len = tpm2_algorithm_to_len(priv->active_banks[i]); + put_unaligned_le16(priv->active_banks[i], + &ev->digest_sizes[i].algorithm_id); + put_unaligned_le16(len, &ev->digest_sizes[i].digest_size); } *((u8 *)ev + (event_size - 1)) = 0; @@ -381,12 +359,12 @@ static int tcg2_replay_eventlog(struct tcg2_event_log *elog, return 0; } -static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog) +static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog, + u32 *log_active) { struct tpml_digest_values digest_list; struct tcg_efi_spec_id_event *event; struct tcg_pcr_event *log; - u32 log_active; u32 calc_size; u32 active; u32 count; @@ -396,7 +374,8 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog) u16 len; int rc; u32 i; - u16 j; + + *log_active = 0; if (elog->log_size <= offsetof(struct tcg_pcr_event, event)) return 0; @@ -435,40 +414,48 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog) if (evsz != calc_size) return 0; - rc = tcg2_get_active_pcr_banks(dev, &active); - if (rc) - return rc; - + /* + * Go through the algorithms the EventLog contains. If the EventLog + * algorithms don't match the active TPM ones exit and report the + * erroneous banks. + * We've already checked that U-Boot supports all the enabled TPM + * algorithms, so just check the EvenLog against the TPM active ones. + */ digest_list.count = 0; - log_active = 0; - for (i = 0; i < count; ++i) { algo = get_unaligned_le16(&event->digest_sizes[i].algorithm_id); mask = tcg2_algorithm_to_mask(algo); - if (!(active & mask)) - return 0; - switch (algo) { case TPM2_ALG_SHA1: case TPM2_ALG_SHA256: case TPM2_ALG_SHA384: case TPM2_ALG_SHA512: len = get_unaligned_le16(&event->digest_sizes[i].digest_size); - if (tpm2_algorithm_to_len(algo) != len) - return 0; + if (tpm2_algorithm_to_len(algo) != len) { + log_err("EventLog invalid algorithm length\n"); + return -1; + } digest_list.digests[digest_list.count++].hash_alg = algo; break; default: - return 0; + /* + * We can ignore this if the TPM PCRs is not extended + * by the previous bootloader. But for now just exit + */ + log_err("EventLog has unsupported algorithm 0x%x\n", + algo); + return -1; } - - log_active |= mask; + *log_active |= mask; } - /* Ensure the previous firmware extended all the PCRs. */ - if (log_active != active) - return 0; + rc = tcg2_get_active_pcr_banks(dev, &active); + if (rc) + return rc; + /* If the EventLog and active algorithms don't match exit */ + if (*log_active != active) + return -ERESTARTSYS; /* Read PCR0 to check if previous firmware extended the PCRs or not. */ rc = tcg2_pcr_read(dev, 0, &digest_list); @@ -476,17 +463,13 @@ static int tcg2_log_parse(struct udevice *dev, struct tcg2_event_log *elog) return rc; for (i = 0; i < digest_list.count; ++i) { - len = tpm2_algorithm_to_len(digest_list.digests[i].hash_alg); - for (j = 0; j < len; ++j) { - if (digest_list.digests[i].digest.sha512[j]) - break; - } + u8 hash_buf[TPM2_SHA512_DIGEST_SIZE] = { 0 }; + u16 hash_alg = digest_list.digests[i].hash_alg; - /* PCR is non-zero; it has been extended, so skip extending. */ - if (j != len) { + if (memcmp((u8 *)&digest_list.digests[i].digest, hash_buf, + tpm2_algorithm_to_len(hash_alg))) digest_list.count = 0; - break; - } + } return tcg2_replay_eventlog(elog, dev, &digest_list, @@ -570,6 +553,7 @@ int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog, { struct tcg2_event_log log; int rc; + u32 log_active = 0; elog->log_position = 0; elog->found = false; @@ -580,7 +564,9 @@ int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog, log.found = false; if (!ignore_existing_log) { - rc = tcg2_log_parse(dev, &log); + rc = tcg2_log_parse(dev, &log, &log_active); + if (rc == -ERESTARTSYS && log_active) + goto pcr_allocate; if (rc) return rc; } @@ -607,6 +593,11 @@ int tcg2_log_prepare_buffer(struct udevice *dev, struct tcg2_event_log *elog, elog->found = log.found; } +pcr_allocate: + rc = tpm2_activate_banks(dev, log_active); + if (rc) + return rc; + /* * Initialize the log buffer if no log was discovered and the buffer is * valid. User's can pass in their own buffer as a fallback if no @@ -664,21 +655,42 @@ void tcg2_measurement_term(struct udevice *dev, struct tcg2_event_log *elog, __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size) { - const __be32 *addr_prop; - const __be32 *size_prop; + const __be32 *addr_prop = NULL; + const __be32 *size_prop = NULL; int asize; int ssize; + struct ofnode_phandle_args args; + phys_addr_t a; + fdt_size_t s; *addr = NULL; *size = 0; - addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize); - if (!addr_prop) - addr_prop = dev_read_prop(dev, "linux,sml-base", &asize); + *addr = bloblist_get_blob(BLOBLISTT_TPM_EVLOG, size); + if (*addr && *size) { + *addr = map_physmem((uintptr_t)(*addr), *size, MAP_NOCACHE); + return 0; + } + + /* + * TODO: + * Replace BLOBLIST with a new kconfig for handoff all components + * (fdt, tpm event log, etc...) from previous boot stage via bloblist + * mandatorily following Firmware Handoff spec. + */ + if (!CONFIG_IS_ENABLED(BLOBLIST)) { + addr_prop = dev_read_prop(dev, "tpm_event_log_addr", &asize); + size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize); + } - size_prop = dev_read_prop(dev, "tpm_event_log_size", &ssize); - if (!size_prop) + /* + * If no eventlog was observed, a sml buffer is required for the kernel + * to discover the eventlog. + */ + if (!addr_prop || !size_prop) { + addr_prop = dev_read_prop(dev, "linux,sml-base", &asize); size_prop = dev_read_prop(dev, "linux,sml-size", &ssize); + } if (addr_prop && size_prop) { u64 a = of_read_number(addr_prop, asize / sizeof(__be32)); @@ -686,22 +698,19 @@ __weak int tcg2_platform_get_log(struct udevice *dev, void **addr, u32 *size) *addr = map_physmem(a, s, MAP_NOCACHE); *size = (u32)s; - } else { - struct ofnode_phandle_args args; - phys_addr_t a; - fdt_size_t s; - if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0, - 0, &args)) - return -ENODEV; + return 0; + } - a = ofnode_get_addr_size(args.node, "reg", &s); - if (a == FDT_ADDR_T_NONE) - return -ENOMEM; + if (dev_read_phandle_with_args(dev, "memory-region", NULL, 0, 0, &args)) + return -ENODEV; - *addr = map_physmem(a, s, MAP_NOCACHE); - *size = (u32)s; - } + a = ofnode_get_addr_size(args.node, "reg", &s); + if (a == FDT_ADDR_T_NONE) + return -ENOMEM; + + *addr = map_physmem(a, s, MAP_NOCACHE); + *size = (u32)s; return 0; } diff --git a/lib/zlib/inflate.c b/lib/zlib/inflate.c index f7e81fc8b2a..b4c72cc2c5c 100644 --- a/lib/zlib/inflate.c +++ b/lib/zlib/inflate.c @@ -2,10 +2,12 @@ * Copyright (C) 1995-2005 Mark Adler * For conditions of distribution and use, see copyright notice in zlib.h */ +#include <asm/sections.h> + local void fixedtables OF((struct inflate_state FAR *state)); local int updatewindow OF((z_streamp strm, unsigned out)); -int ZEXPORT inflateReset(z_streamp strm) +__rcode int ZEXPORT inflateReset(z_streamp strm) { struct inflate_state FAR *state; @@ -30,8 +32,8 @@ int ZEXPORT inflateReset(z_streamp strm) return Z_OK; } -int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, - int stream_size) +__rcode int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, + int stream_size) { struct inflate_state FAR *state; @@ -67,12 +69,12 @@ int ZEXPORT inflateInit2_(z_streamp strm, int windowBits, return inflateReset(strm); } -int ZEXPORT inflateInit_(z_streamp strm, int stream_size) +__rcode int ZEXPORT inflateInit_(z_streamp strm, int stream_size) { return inflateInit2_(strm, DEF_WBITS, stream_size); } -local void fixedtables(struct inflate_state FAR *state) +__rcode local void fixedtables(struct inflate_state FAR *state) { state->lencode = lenfix; state->lenbits = 9; @@ -94,7 +96,7 @@ local void fixedtables(struct inflate_state FAR *state) output will fall in the output data, making match copies simpler and faster. The advantage may be dependent on the size of the processor's data caches. */ -local int updatewindow(z_streamp strm, unsigned out) +__rcode local int updatewindow(z_streamp strm, unsigned int out) { struct inflate_state FAR *state; unsigned copy, dist; @@ -322,7 +324,7 @@ local int updatewindow(z_streamp strm, unsigned out) when flush is set to Z_FINISH, inflate() cannot return Z_OK. Instead it will return Z_BUF_ERROR if it has not reached the end of the stream. */ -int ZEXPORT inflate(z_streamp strm, int flush) +__rcode int ZEXPORT inflate(z_streamp strm, int flush) { struct inflate_state FAR *state; unsigned char FAR *next; /* next input */ @@ -924,7 +926,7 @@ int ZEXPORT inflate(z_streamp strm, int flush) return ret; } -int ZEXPORT inflateEnd(z_streamp strm) +__rcode int ZEXPORT inflateEnd(z_streamp strm) { struct inflate_state FAR *state; if (strm == Z_NULL || strm->state == Z_NULL || strm->zfree == (free_func)0) |