summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig29
-rw-r--r--lib/Makefile17
-rw-r--r--lib/abuf.c12
-rw-r--r--lib/acpi/acpi_table.c4
-rw-r--r--lib/crc8.c5
-rw-r--r--lib/efi_driver/efi_block_device.c2
-rw-r--r--lib/efi_driver/efi_uclass.c2
-rw-r--r--lib/efi_loader/Kconfig16
-rw-r--r--lib/efi_loader/efi_acpi.c12
-rw-r--r--lib/efi_loader/efi_bootbin.c273
-rw-r--r--lib/efi_loader/efi_boottime.c18
-rw-r--r--lib/efi_loader/efi_conformance.c2
-rw-r--r--lib/efi_loader/efi_device_path_to_text.c2
-rw-r--r--lib/efi_loader/efi_device_path_utilities.c2
-rw-r--r--lib/efi_loader/efi_dt_fixup.c2
-rw-r--r--lib/efi_loader/efi_esrt.c2
-rw-r--r--lib/efi_loader/efi_fdt.c2
-rw-r--r--lib/efi_loader/efi_file.c2
-rw-r--r--lib/efi_loader/efi_firmware.c2
-rw-r--r--lib/efi_loader/efi_gop.c2
-rw-r--r--lib/efi_loader/efi_helper.c1
-rw-r--r--lib/efi_loader/efi_hii.c2
-rw-r--r--lib/efi_loader/efi_hii_config.c2
-rw-r--r--lib/efi_loader/efi_http.c2
-rw-r--r--lib/efi_loader/efi_image_loader.c2
-rw-r--r--lib/efi_loader/efi_ipconfig.c2
-rw-r--r--lib/efi_loader/efi_load_initrd.c1
-rw-r--r--lib/efi_loader/efi_net.c2
-rw-r--r--lib/efi_loader/efi_riscv.c1
-rw-r--r--lib/efi_loader/efi_root_node.c2
-rw-r--r--lib/efi_loader/efi_runtime.c2
-rw-r--r--lib/efi_loader/efi_signature.c2
-rw-r--r--lib/efi_loader/efi_string.c2
-rw-r--r--lib/efi_loader/efi_tcg2.c18
-rw-r--r--lib/efi_loader/efi_unicode_collation.c2
-rw-r--r--lib/efi_loader/efi_var_common.c2
-rw-r--r--lib/efi_loader/efi_var_mem.c2
-rw-r--r--lib/efi_loader/efi_variable_tee.c2
-rw-r--r--lib/efi_loader/efi_watchdog.c2
-rw-r--r--lib/efi_loader/elf_efi.ldsi74
-rw-r--r--lib/efi_selftest/efi_selftest_startimage_exit.c6
-rw-r--r--lib/gunzip.c9
-rw-r--r--lib/lz4.c37
-rw-r--r--lib/lz4_wrapper.c2
-rw-r--r--lib/mbedtls/Kconfig54
-rw-r--r--lib/mbedtls/Makefile2
-rw-r--r--lib/mbedtls/mbedtls_def_config.h4
-rw-r--r--lib/mbedtls/sha256.c59
-rw-r--r--lib/sha256.c67
-rw-r--r--lib/sha256_common.c50
-rw-r--r--lib/smbios.c445
-rw-r--r--lib/string.c5
-rw-r--r--lib/tpm-v2.c331
-rw-r--r--lib/tpm_api.c4
-rw-r--r--lib/tpm_tcg2.c239
-rw-r--r--lib/zlib/inflate.c18
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)