summaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
authorTom Rini <[email protected]>2026-04-06 12:16:57 -0600
committerTom Rini <[email protected]>2026-04-06 12:16:57 -0600
commit93f84ee022a8401421cdaab84fe7d106d83fdb4a (patch)
treefb15a4af876e8faf9893fd86c1c0e127265dbe9a /lib
parent88dc2788777babfd6322fa655df549a019aa1e69 (diff)
parente2138cf1e6088f12ffa874e87cc8f4b198378635 (diff)
Merge branch 'next'
Diffstat (limited to 'lib')
-rw-r--r--lib/Kconfig9
-rw-r--r--lib/Makefile1
-rw-r--r--lib/efi_loader/Kconfig38
-rw-r--r--lib/efi_loader/Makefile3
-rw-r--r--lib/efi_loader/efi_capsule.c8
-rw-r--r--lib/efi_loader/efi_conformance.c2
-rw-r--r--lib/efi_loader/efi_disk.c9
-rw-r--r--lib/efi_loader/efi_gop.c3
-rw-r--r--lib/efi_loader/efi_rng.c3
-rw-r--r--lib/efi_loader/efi_runtime.c24
-rw-r--r--lib/efi_loader/efi_var_common.c44
-rw-r--r--lib/efi_loader/efi_var_file.c65
-rw-r--r--lib/efi_loader/efi_var_mem.c29
-rw-r--r--lib/efi_loader/efi_var_sf.c111
-rw-r--r--lib/efi_loader/efi_variable.c44
-rw-r--r--lib/efi_selftest/efi_selftest_block_device.c26
-rw-r--r--lib/fdtdec.c16
-rw-r--r--lib/fwu_updates/Kconfig1
-rw-r--r--lib/fwu_updates/fwu.c6
-rw-r--r--lib/fwu_updates/fwu_v1.c16
-rw-r--r--lib/fwu_updates/fwu_v2.c50
-rw-r--r--lib/linux_compat.c3
-rw-r--r--lib/lmb.c17
-rw-r--r--lib/lwip/u-boot/lwipopts.h22
-rw-r--r--lib/optee/Kconfig1
-rw-r--r--lib/smbios.c1151
-rw-r--r--lib/uuid.c6
27 files changed, 1530 insertions, 178 deletions
diff --git a/lib/Kconfig b/lib/Kconfig
index 931d5206936..46384283c43 100644
--- a/lib/Kconfig
+++ b/lib/Kconfig
@@ -71,10 +71,14 @@ config DYNAMIC_CRC_TABLE
Enable this option to calculate entries for CRC tables at runtime.
This can be helpful when reducing the size of the build image
-config FW_LOADER
- bool "Enable firmware loader using environment script"
+config SUPPORTS_FW_LOADER
+ bool
depends on CMDLINE
depends on ENV_SUPPORT
+
+config FW_LOADER
+ bool "Enable firmware loader using environment script"
+ depends on SUPPORTS_FW_LOADER
help
Enable this option to make firmware loading using user-provided
U-Boot environment script functionality accessible to U-Boot code.
@@ -334,6 +338,7 @@ config SPL_ACPI
config GENERATE_ACPI_TABLE
bool "Generate an ACPI (Advanced Configuration and Power Interface) table"
depends on ACPI
+ select ACPIGEN if !QFW_ACPI
select BLOBLIST
select QFW if QEMU
help
diff --git a/lib/Makefile b/lib/Makefile
index 70667f3728c..d0ffabc2b47 100644
--- a/lib/Makefile
+++ b/lib/Makefile
@@ -147,6 +147,7 @@ else
obj-$(CONFIG_$(PHASE_)SPRINTF) += vsprintf.o
endif
obj-$(CONFIG_$(PHASE_)STRTO) += strto.o
+obj-$(CONFIG_$(PHASE_)UFS_SUPPORT) += charset.o
else
# Main U-Boot always uses the full printf support
obj-y += vsprintf.o strto.o
diff --git a/lib/efi_loader/Kconfig b/lib/efi_loader/Kconfig
index 13e44be1d06..b5f81e0ff53 100644
--- a/lib/efi_loader/Kconfig
+++ b/lib/efi_loader/Kconfig
@@ -15,6 +15,8 @@ config EFI_LOADER
# 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
+ # The EFI specification requires 128 KiB or more of stack space
+ depends on STACK_SIZE >= 0x20000
default y if !ARM || SYS_CPU = armv7 || SYS_CPU = armv8
select EFI
select CHARSET
@@ -112,7 +114,8 @@ menu "UEFI Variables"
choice
prompt "Store for non-volatile UEFI variables"
- default EFI_VARIABLE_FILE_STORE
+ default EFI_VARIABLE_FILE_STORE if FAT_WRITE
+ default EFI_VARIABLE_NO_STORE
help
Select where non-volatile UEFI variables shall be stored.
@@ -123,6 +126,24 @@ config EFI_VARIABLE_FILE_STORE
Select this option if you want non-volatile UEFI variables to be
stored as file /ubootefi.var on the EFI system partition.
+config EFI_VARIABLE_SF_STORE
+ bool "Store non-volatile UEFI variables in SPI Flash"
+ depends on SPI_FLASH
+ help
+ Select this option if you want non-volatile UEFI variables to be
+ stored in SPI Flash.
+
+ Define CONFIG_EFI_VARIABLE_SF_OFFSET as offset in SPI Flash to use as
+ the storage for variables. CONFIG_EFI_VAR_BUF_SIZE defines the space
+ needed.
+
+ Note that SPI Flash devices have a limited number of program/erase
+ cycles. Frequent updates to UEFI variables may cause excessive wear
+ and can permanently damage the flash device, particularly on SPI NAND
+ or low-end SPI NOR parts without wear leveling. This option should be
+ used with care on such systems, and is not recommended for platforms
+ where UEFI variables are updated frequently.
+
config EFI_MM_COMM_TEE
bool "UEFI variables storage service via the trusted world"
depends on OPTEE
@@ -193,6 +214,21 @@ config FFA_SHARED_MM_BUF_ADDR
the MM SP in secure world.
It is assumed that the MM SP knows the address of the shared MM communication buffer.
+config EFI_VARIABLE_SF_OFFSET
+ hex "EFI variables in SPI flash offset"
+ depends on EFI_VARIABLE_SF_STORE
+ help
+ Offset from the start of the SPI Flash where EFI variables will be stored.
+ This should be aligned to the sector size of SPI Flash.
+
+config EFI_VARIABLE_SF_DEVICE_INDEX
+ int "Device Index for target SPI Flash"
+ depends on EFI_VARIABLE_SF_STORE
+ default 0
+ help
+ The index of SPI Flash device used for storing EFI variables. This would be
+ needed if there are more than 1 SPI Flash devices available to use.
+
config EFI_VARIABLES_PRESEED
bool "Initial values for UEFI variables"
depends on !COMPILE_TEST
diff --git a/lib/efi_loader/Makefile b/lib/efi_loader/Makefile
index f490081f654..d73ad43951b 100644
--- a/lib/efi_loader/Makefile
+++ b/lib/efi_loader/Makefile
@@ -53,7 +53,8 @@ ifeq ($(CONFIG_EFI_MM_COMM_TEE),y)
obj-y += efi_variable_tee.o
else
obj-y += efi_variable.o
-obj-y += efi_var_file.o
+obj-$(CONFIG_EFI_VARIABLE_FILE_STORE) += efi_var_file.o
+obj-$(CONFIG_EFI_VARIABLE_SF_STORE) += efi_var_sf.o
obj-$(CONFIG_EFI_VARIABLES_PRESEED) += efi_var_seed.o
endif
obj-y += efi_watchdog.o
diff --git a/lib/efi_loader/efi_capsule.c b/lib/efi_loader/efi_capsule.c
index 89e63ed8dd5..52887f7c274 100644
--- a/lib/efi_loader/efi_capsule.c
+++ b/lib/efi_loader/efi_capsule.c
@@ -21,7 +21,6 @@
#include <mapmem.h>
#include <sort.h>
#include <sysreset.h>
-#include <asm/global_data.h>
#include <u-boot/uuid.h>
#include <asm/sections.h>
@@ -29,8 +28,6 @@
#include <crypto/pkcs7_parser.h>
#include <linux/err.h>
-DECLARE_GLOBAL_DATA_PTR;
-
const efi_guid_t efi_guid_capsule_report = EFI_CAPSULE_REPORT_GUID;
static const efi_guid_t efi_guid_firmware_management_capsule_id =
EFI_FIRMWARE_MANAGEMENT_CAPSULE_ID_GUID;
@@ -465,7 +462,7 @@ static __maybe_unused efi_status_t fwu_empty_capsule_process(
log_err("Unable to set the Accept bit for the image %pUs\n",
image_guid);
- status = fwu_state_machine_updates(0, active_idx);
+ status = fwu_state_machine_updates(FWU_BANK_ACCEPTED, active_idx);
if (status < 0)
ret = EFI_DEVICE_ERROR;
@@ -510,7 +507,8 @@ static __maybe_unused efi_status_t fwu_post_update_process(bool fw_accept_os)
log_err("Failed to update FWU metadata index values\n");
} else {
log_debug("Successfully updated the active_index\n");
- status = fwu_state_machine_updates(fw_accept_os ? 1 : 0,
+ status = fwu_state_machine_updates(fw_accept_os ?
+ FWU_BANK_VALID : FWU_BANK_ACCEPTED,
update_index);
if (status < 0)
ret = EFI_DEVICE_ERROR;
diff --git a/lib/efi_loader/efi_conformance.c b/lib/efi_loader/efi_conformance.c
index 2d31800ccb8..470141af483 100644
--- a/lib/efi_loader/efi_conformance.c
+++ b/lib/efi_loader/efi_conformance.c
@@ -12,7 +12,7 @@
#include <efi_api.h>
#include <malloc.h>
-static const efi_guid_t efi_ecpt_guid = EFI_CONFORMANCE_PROFILES_TABLE_GUID;
+const efi_guid_t efi_ecpt_guid = EFI_CONFORMANCE_PROFILES_TABLE_GUID;
/**
* efi_ecpt_register() - Install the ECPT system table.
diff --git a/lib/efi_loader/efi_disk.c b/lib/efi_loader/efi_disk.c
index 130c4db9606..f8a57539ec6 100644
--- a/lib/efi_loader/efi_disk.c
+++ b/lib/efi_loader/efi_disk.c
@@ -475,9 +475,12 @@ static efi_status_t efi_disk_add_dev(
#if CONFIG_IS_ENABLED(DOS_PARTITION)
case PART_TYPE_DOS:
info->type = PARTITION_TYPE_MBR;
-
- /* TODO: implement support for MBR partition types */
- log_debug("EFI_PARTITION_INFO_PROTOCOL doesn't support MBR\n");
+ ret = part_get_mbr(desc, part, &info->info.mbr);
+ if (ret) {
+ log_debug("get MBR for part %d failed %ld\n",
+ part, ret);
+ goto error;
+ }
break;
#endif
default:
diff --git a/lib/efi_loader/efi_gop.c b/lib/efi_loader/efi_gop.c
index 3abb47d610e..9403e09691e 100644
--- a/lib/efi_loader/efi_gop.c
+++ b/lib/efi_loader/efi_gop.c
@@ -13,9 +13,6 @@
#include <malloc.h>
#include <mapmem.h>
#include <video.h>
-#include <asm/global_data.h>
-
-DECLARE_GLOBAL_DATA_PTR;
static const efi_guid_t efi_gop_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID;
diff --git a/lib/efi_loader/efi_rng.c b/lib/efi_loader/efi_rng.c
index 4734f95eee1..7810b4e47ea 100644
--- a/lib/efi_loader/efi_rng.c
+++ b/lib/efi_loader/efi_rng.c
@@ -10,9 +10,6 @@
#include <efi_rng.h>
#include <log.h>
#include <rng.h>
-#include <asm/global_data.h>
-
-DECLARE_GLOBAL_DATA_PTR;
const efi_guid_t efi_guid_rng_protocol = EFI_RNG_PROTOCOL_GUID;
diff --git a/lib/efi_loader/efi_runtime.c b/lib/efi_loader/efi_runtime.c
index 35eb6a77766..73d4097464c 100644
--- a/lib/efi_loader/efi_runtime.c
+++ b/lib/efi_loader/efi_runtime.c
@@ -210,6 +210,30 @@ void __efi_runtime efi_memcpy_runtime(void *dest, const void *src, size_t n)
}
/**
+ * efi_memcmp_runtime() - compare memory areas
+ *
+ * At runtime memcmp() is not available.
+ *
+ * @s1: first memory area
+ * @s2: second memory area
+ * @n: number of bytes to compare
+ * Return: 0 if equal, negative if s1 < s2, positive if s1 > s2
+ */
+int __efi_runtime efi_memcmp_runtime(const void *s1, const void *s2, size_t n)
+{
+ const u8 *pos1 = s1;
+ const u8 *pos2 = s2;
+
+ for (; n; --n) {
+ if (*pos1 != *pos2)
+ return *pos1 - *pos2;
+ ++pos1;
+ ++pos2;
+ }
+ return 0;
+}
+
+/**
* efi_update_table_header_crc32() - Update crc32 in table header
*
* @table: EFI table
diff --git a/lib/efi_loader/efi_var_common.c b/lib/efi_loader/efi_var_common.c
index 4b34a58b4cf..d63c2d1b1cd 100644
--- a/lib/efi_loader/efi_var_common.c
+++ b/lib/efi_loader/efi_var_common.c
@@ -41,6 +41,7 @@ static const struct efi_auth_var_name_type name_type[] = {
static bool efi_secure_boot;
static enum efi_secure_mode efi_secure_mode;
+static const efi_guid_t shim_lock_guid = SHIM_LOCK_GUID;
/**
* efi_efi_get_variable() - retrieve value of a UEFI variable
@@ -488,3 +489,46 @@ efi_status_t __maybe_unused efi_var_collect(struct efi_var_file **bufp, loff_t *
return EFI_SUCCESS;
}
+
+efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe)
+{
+ struct efi_var_entry *var, *last_var;
+ u16 *data;
+ efi_status_t ret;
+
+ if (buf->reserved || buf->magic != EFI_VAR_FILE_MAGIC ||
+ buf->length > EFI_VAR_BUF_SIZE ||
+ buf->length < sizeof(struct efi_var_file) ||
+ buf->crc32 != crc32(0, (u8 *)buf->var,
+ buf->length - sizeof(struct efi_var_file))) {
+ log_err("Invalid EFI variables file\n");
+ return EFI_INVALID_PARAMETER;
+ }
+
+ last_var = (struct efi_var_entry *)((u8 *)buf + buf->length);
+ for (var = buf->var; var < last_var;
+ var = (struct efi_var_entry *)ALIGN((uintptr_t)data + var->length, 8)) {
+ data = var->name + u16_strlen(var->name) + 1;
+
+ /*
+ * Secure boot related and volatile variables shall only be
+ * restored from U-Boot's preseed.
+ */
+ if (!safe &&
+ (efi_auth_var_get_type(var->name, &var->guid) !=
+ EFI_AUTH_VAR_NONE ||
+ !guidcmp(&var->guid, &shim_lock_guid) ||
+ !(var->attr & EFI_VARIABLE_NON_VOLATILE)))
+ continue;
+ if (!var->length)
+ continue;
+ if (efi_var_mem_find(&var->guid, var->name, NULL))
+ continue;
+ ret = efi_var_mem_ins(var->name, &var->guid, var->attr,
+ var->length, data, 0, NULL,
+ var->time, NULL);
+ if (ret != EFI_SUCCESS)
+ log_err("Failed to set EFI variable %ls\n", var->name);
+ }
+ return EFI_SUCCESS;
+}
diff --git a/lib/efi_loader/efi_var_file.c b/lib/efi_loader/efi_var_file.c
index f23a964a418..9cda38f319e 100644
--- a/lib/efi_loader/efi_var_file.c
+++ b/lib/efi_loader/efi_var_file.c
@@ -14,17 +14,9 @@
#include <mapmem.h>
#include <efi_loader.h>
#include <efi_variable.h>
-#include <u-boot/crc.h>
#define PART_STR_LEN 10
-/* GUID used by Shim to store the MOK database */
-#define SHIM_LOCK_GUID \
- EFI_GUID(0x605dab50, 0xe046, 0x4300, \
- 0xab, 0xb6, 0x3d, 0xd8, 0x10, 0xdd, 0x8b, 0x23)
-
-static const efi_guid_t shim_lock_guid = SHIM_LOCK_GUID;
-
/**
* efi_set_blk_dev_to_system_partition() - select EFI system partition
*
@@ -51,15 +43,14 @@ static efi_status_t __maybe_unused efi_set_blk_dev_to_system_partition(void)
}
/**
- * efi_var_to_file() - save non-volatile variables as file
+ * efi_var_to_storage() - save non-volatile variables as file
*
* File ubootefi.var is created on the EFI system partion.
*
* Return: status code
*/
-efi_status_t efi_var_to_file(void)
+efi_status_t efi_var_to_storage(void)
{
-#ifdef CONFIG_EFI_VARIABLE_FILE_STORE
efi_status_t ret;
struct efi_var_file *buf;
loff_t len;
@@ -91,56 +82,10 @@ error:
out:
free(buf);
return ret;
-#else
- return EFI_SUCCESS;
-#endif
-}
-
-efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe)
-{
- struct efi_var_entry *var, *last_var;
- u16 *data;
- efi_status_t ret;
-
- if (buf->reserved || buf->magic != EFI_VAR_FILE_MAGIC ||
- buf->crc32 != crc32(0, (u8 *)buf->var,
- buf->length - sizeof(struct efi_var_file))) {
- log_err("Invalid EFI variables file\n");
- return EFI_INVALID_PARAMETER;
- }
-
- last_var = (struct efi_var_entry *)((u8 *)buf + buf->length);
- for (var = buf->var; var < last_var;
- var = (struct efi_var_entry *)
- ALIGN((uintptr_t)data + var->length, 8)) {
-
- data = var->name + u16_strlen(var->name) + 1;
-
- /*
- * Secure boot related and volatile variables shall only be
- * restored from U-Boot's preseed.
- */
- if (!safe &&
- (efi_auth_var_get_type(var->name, &var->guid) !=
- EFI_AUTH_VAR_NONE ||
- !guidcmp(&var->guid, &shim_lock_guid) ||
- !(var->attr & EFI_VARIABLE_NON_VOLATILE)))
- continue;
- if (!var->length)
- continue;
- if (efi_var_mem_find(&var->guid, var->name, NULL))
- continue;
- ret = efi_var_mem_ins(var->name, &var->guid, var->attr,
- var->length, data, 0, NULL,
- var->time);
- if (ret != EFI_SUCCESS)
- log_err("Failed to set EFI variable %ls\n", var->name);
- }
- return EFI_SUCCESS;
}
/**
- * efi_var_from_file() - read variables from file
+ * efi_var_from_storage() - read variables from file
*
* File ubootefi.var is read from the EFI system partitions and the variables
* stored in the file are created.
@@ -153,9 +98,8 @@ efi_status_t efi_var_restore(struct efi_var_file *buf, bool safe)
*
* Return: status code
*/
-efi_status_t efi_var_from_file(void)
+efi_status_t efi_var_from_storage(void)
{
-#ifdef CONFIG_EFI_VARIABLE_FILE_STORE
struct efi_var_file *buf;
loff_t len;
efi_status_t ret;
@@ -180,6 +124,5 @@ efi_status_t efi_var_from_file(void)
log_err("Invalid EFI variables file\n");
error:
free(buf);
-#endif
return EFI_SUCCESS;
}
diff --git a/lib/efi_loader/efi_var_mem.c b/lib/efi_loader/efi_var_mem.c
index 31180df9e3a..8d5f99f4870 100644
--- a/lib/efi_loader/efi_var_mem.c
+++ b/lib/efi_loader/efi_var_mem.c
@@ -159,12 +159,39 @@ efi_status_t __efi_runtime efi_var_mem_ins(
const efi_guid_t *vendor, u32 attributes,
const efi_uintn_t size1, const void *data1,
const efi_uintn_t size2, const void *data2,
- const u64 time)
+ const u64 time, bool *changep)
{
u16 *data;
struct efi_var_entry *var;
u32 var_name_len;
+ if (changep)
+ *changep = true;
+
+ /*
+ * If this is not an append (size2 == 0), check whether the variable
+ * already exists with identical attributes and data. When nothing
+ * changed we can skip the write and avoid superfluous erases.
+ */
+ if (!size2 && changep) {
+ struct efi_var_entry *old;
+
+ old = efi_var_mem_find(vendor, variable_name, NULL);
+ if (old && old->attr == attributes &&
+ old->length == size1 && old->time == time) {
+ u16 *old_data;
+
+ for (old_data = old->name; *old_data; ++old_data)
+ ;
+ ++old_data;
+
+ if (!efi_memcmp_runtime(old_data, data1, size1)) {
+ *changep = false;
+ return EFI_SUCCESS;
+ }
+ }
+ }
+
var = (struct efi_var_entry *)
((uintptr_t)efi_var_buf + efi_var_buf->length);
var_name_len = u16_strlen(variable_name) + 1;
diff --git a/lib/efi_loader/efi_var_sf.c b/lib/efi_loader/efi_var_sf.c
new file mode 100644
index 00000000000..6eae8d46464
--- /dev/null
+++ b/lib/efi_loader/efi_var_sf.c
@@ -0,0 +1,111 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * SPI Flash interface for UEFI variables
+ *
+ * Copyright (c) 2023, Shantur Rathore
+ * Copyright (C) 2026, Advanced Micro Devices, Inc.
+ */
+
+#define LOG_CATEGORY LOGC_EFI
+
+#include <efi_loader.h>
+#include <efi_variable.h>
+#include <spi_flash.h>
+#include <dm.h>
+
+efi_status_t efi_var_to_storage(void)
+{
+ struct efi_var_file *buf;
+ struct spi_flash *flash;
+ struct udevice *sfdev;
+ efi_status_t ret;
+ size_t erase_len;
+ loff_t len;
+ int r;
+
+ ret = efi_var_collect(&buf, &len, EFI_VARIABLE_NON_VOLATILE);
+ if (ret != EFI_SUCCESS)
+ goto error;
+
+ if (len > EFI_VAR_BUF_SIZE) {
+ log_debug("EFI var buffer length more than target SPI Flash size\n");
+ ret = EFI_OUT_OF_RESOURCES;
+ goto error;
+ }
+
+ log_debug("Got buffer to write buf->len: %d\n", buf->length);
+
+ r = uclass_get_device(UCLASS_SPI_FLASH,
+ CONFIG_EFI_VARIABLE_SF_DEVICE_INDEX, &sfdev);
+ if (r) {
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ flash = dev_get_uclass_priv(sfdev);
+ if (!flash) {
+ log_debug("Failed to get SPI Flash priv data\n");
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+ erase_len = ALIGN(len, flash->sector_size);
+
+ r = spi_flash_erase_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET,
+ erase_len);
+ if (r) {
+ log_debug("Failed to erase SPI Flash\n");
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ r = spi_flash_write_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET, len, buf);
+ if (r) {
+ log_debug("Failed to write to SPI Flash: %d\n", r);
+ ret = EFI_DEVICE_ERROR;
+ }
+
+error:
+ free(buf);
+ return ret;
+}
+
+efi_status_t efi_var_from_storage(void)
+{
+ struct efi_var_file *buf;
+ struct udevice *sfdev;
+ efi_status_t ret;
+ int r;
+
+ buf = calloc(1, EFI_VAR_BUF_SIZE);
+ if (!buf) {
+ log_err("Unable to allocate buffer\n");
+ return EFI_OUT_OF_RESOURCES;
+ }
+
+ r = uclass_get_device(UCLASS_SPI_FLASH,
+ CONFIG_EFI_VARIABLE_SF_DEVICE_INDEX, &sfdev);
+ if (r) {
+ log_err("Failed to get SPI Flash device: %d\n", r);
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ r = spi_flash_read_dm(sfdev, CONFIG_EFI_VARIABLE_SF_OFFSET,
+ EFI_VAR_BUF_SIZE, buf);
+ if (r) {
+ log_err("Failed to read from SPI Flash: %d\n", r);
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ if (efi_var_restore(buf, false) != EFI_SUCCESS) {
+ log_err("No valid EFI variables in SPI Flash\n");
+ ret = EFI_DEVICE_ERROR;
+ goto error;
+ }
+
+ ret = EFI_SUCCESS;
+error:
+ free(buf);
+ return ret;
+}
diff --git a/lib/efi_loader/efi_variable.c b/lib/efi_loader/efi_variable.c
index f3533f4def3..9923936c1b5 100644
--- a/lib/efi_loader/efi_variable.c
+++ b/lib/efi_loader/efi_variable.c
@@ -277,6 +277,7 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
struct efi_var_entry *var;
efi_uintn_t ret;
bool append, delete;
+ bool changed = false;
u64 time = 0;
enum efi_auth_var_type var_type;
@@ -366,6 +367,7 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
if (delete) {
/* EFI_NOT_FOUND has been handled before */
attributes = var->attr;
+ changed = true;
ret = EFI_SUCCESS;
} else if (append && var) {
/*
@@ -380,15 +382,19 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
ret = efi_var_mem_ins(variable_name, vendor,
attributes & ~EFI_VARIABLE_APPEND_WRITE,
var->length, old_data, data_size, data,
- time);
+ time, &changed);
} else {
ret = efi_var_mem_ins(variable_name, vendor, attributes,
- data_size, data, 0, NULL, time);
+ data_size, data, 0, NULL, time,
+ &changed);
}
if (ret != EFI_SUCCESS)
return ret;
+ if (!changed)
+ return EFI_SUCCESS;
+
efi_var_mem_del(var);
if (var_type == EFI_AUTH_VAR_PK)
@@ -396,12 +402,13 @@ efi_status_t efi_set_variable_int(const u16 *variable_name,
else
ret = EFI_SUCCESS;
- /*
- * Write non-volatile EFI variables to file
- * TODO: check if a value change has occured to avoid superfluous writes
- */
- if (attributes & EFI_VARIABLE_NON_VOLATILE)
- efi_var_to_file();
+ /* Write non-volatile EFI variables to storage */
+ if (attributes & EFI_VARIABLE_NON_VOLATILE) {
+ if (IS_ENABLED(CONFIG_EFI_VARIABLE_NO_STORE))
+ return EFI_SUCCESS;
+
+ efi_var_to_storage();
+ }
return EFI_SUCCESS;
}
@@ -494,6 +501,7 @@ efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
struct efi_var_entry *var;
efi_uintn_t ret;
bool append, delete;
+ bool changed = false;
u64 time = 0;
if (!IS_ENABLED(CONFIG_EFI_RT_VOLATILE_STORE))
@@ -545,6 +553,7 @@ efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
if (delete) {
/* EFI_NOT_FOUND has been handled before */
attributes = var->attr;
+ changed = true;
ret = EFI_SUCCESS;
} else if (append && var) {
u16 *old_data = (void *)((uintptr_t)var->name +
@@ -552,15 +561,19 @@ efi_set_variable_runtime(u16 *variable_name, const efi_guid_t *vendor,
ret = efi_var_mem_ins(variable_name, vendor, attributes,
var->length, old_data, data_size, data,
- time);
+ time, &changed);
} else {
ret = efi_var_mem_ins(variable_name, vendor, attributes,
- data_size, data, 0, NULL, time);
+ data_size, data, 0, NULL, time,
+ &changed);
}
if (ret != EFI_SUCCESS)
return ret;
- /* We are always inserting new variables, get rid of the old copy */
+
+ if (!changed)
+ return EFI_SUCCESS;
+
efi_var_mem_del(var);
return EFI_SUCCESS;
@@ -594,9 +607,12 @@ efi_status_t efi_init_variables(void)
if (ret != EFI_SUCCESS)
return ret;
- ret = efi_var_from_file();
- if (ret != EFI_SUCCESS)
- return ret;
+ if (!IS_ENABLED(CONFIG_EFI_VARIABLE_NO_STORE)) {
+ ret = efi_var_from_storage();
+ if (ret != EFI_SUCCESS)
+ return ret;
+ }
+
if (IS_ENABLED(CONFIG_EFI_VARIABLES_PRESEED)) {
ret = efi_var_restore((struct efi_var_file *)
__efi_var_file_begin, true);
diff --git a/lib/efi_selftest/efi_selftest_block_device.c b/lib/efi_selftest/efi_selftest_block_device.c
index f145e58a267..9c4be834eeb 100644
--- a/lib/efi_selftest/efi_selftest_block_device.c
+++ b/lib/efi_selftest/efi_selftest_block_device.c
@@ -19,6 +19,7 @@
#include "efi_selftest_disk_image.h"
#include <asm/cache.h>
#include <part_efi.h>
+#include <part.h>
/* Block size of compressed disk image */
#define COMPRESSED_DISK_IMAGE_BLOCK_SIZE 8
@@ -319,6 +320,25 @@ static int execute(void)
u64 pos;
char block_io_aligned[1 << LB_BLOCK_SIZE] __aligned(1 << LB_BLOCK_SIZE);
+ /*
+ * The test disk image is defined in efi_selftest_disk_image.h,
+ * it contains a single FAT12 partition of 127 sectors size.
+ */
+ static const dos_partition_t mbr_expected = {
+ .boot_ind = 0x00,
+ .head = 0x00,
+ .sector = 0x02,
+ .cyl = 0x00,
+ .sys_ind = 0x01, /* FAT12 */
+ .end_head = 0x02,
+ .end_sector = 0x02,
+ .end_cyl = 0x00,
+ /* LBA 1 */
+ .start_sect = cpu_to_le32(1),
+ /* Size 127 sectors (0x7f) */
+ .nr_sects = cpu_to_le32(127),
+ };
+
/* Connect controller to virtual disk */
ret = boottime->connect_controller(disk_handle, NULL, NULL, 1);
if (ret != EFI_SUCCESS) {
@@ -405,6 +425,12 @@ static int execute(void)
return EFI_ST_FAILURE;
}
+ /* Compare the obtained MBR with the expected one for the test partition */
+ if (memcmp(&part_info->info.mbr, &mbr_expected, sizeof(mbr_expected))) {
+ efi_st_error("MBR partition record mismatch\n");
+ return EFI_ST_FAILURE;
+ }
+
/* Open the simple file system protocol */
ret = boottime->open_protocol(handle_partition,
&guid_simple_file_system_protocol,
diff --git a/lib/fdtdec.c b/lib/fdtdec.c
index c38738b48c7..fb3375ea157 100644
--- a/lib/fdtdec.c
+++ b/lib/fdtdec.c
@@ -1077,13 +1077,12 @@ int fdtdec_setup_mem_size_base(void)
gd->ram_size = (phys_size_t)(res.end - res.start + 1);
gd->ram_base = (unsigned long)res.start;
- debug("%s: Initial DRAM size %llx\n", __func__,
- (unsigned long long)gd->ram_size);
+ debug("%s: Initial DRAM size %pap\n", __func__, &gd->ram_size);
return 0;
}
-ofnode get_next_memory_node(ofnode mem)
+static ofnode get_next_memory_node(ofnode mem)
{
do {
mem = ofnode_by_prop_value(mem, "device_type", "memory", 7);
@@ -1092,6 +1091,11 @@ ofnode get_next_memory_node(ofnode mem)
return mem;
}
+ofnode fdtdec_get_next_memory_node(ofnode mem)
+{
+ return get_next_memory_node(mem);
+}
+
int fdtdec_setup_memory_banksize(void)
{
int bank, ret, reg = 0;
@@ -1124,10 +1128,10 @@ int fdtdec_setup_memory_banksize(void)
gd->bd->bi_dram[bank].size =
(phys_size_t)(res.end - res.start + 1);
- debug("%s: DRAM Bank #%d: start = 0x%llx, size = 0x%llx\n",
+ debug("%s: DRAM Bank #%d: start = %pap, size = %pap\n",
__func__, bank,
- (unsigned long long)gd->bd->bi_dram[bank].start,
- (unsigned long long)gd->bd->bi_dram[bank].size);
+ &gd->bd->bi_dram[bank].start,
+ &gd->bd->bi_dram[bank].size);
}
return 0;
diff --git a/lib/fwu_updates/Kconfig b/lib/fwu_updates/Kconfig
index a722107c129..b38808e3463 100644
--- a/lib/fwu_updates/Kconfig
+++ b/lib/fwu_updates/Kconfig
@@ -1,6 +1,7 @@
menuconfig FWU_MULTI_BANK_UPDATE
bool "Enable FWU Multi Bank Update Feature"
depends on EFI_CAPSULE_ON_DISK
+ select EFI_PARTITION
select PARTITION_TYPE_GUID
select FWU_MDATA
imply EFI_CAPSULE_ON_DISK_EARLY
diff --git a/lib/fwu_updates/fwu.c b/lib/fwu_updates/fwu.c
index 0f5ef2ba515..37c613014d1 100644
--- a/lib/fwu_updates/fwu.c
+++ b/lib/fwu_updates/fwu.c
@@ -766,6 +766,12 @@ static int fwu_boottime_checks(void)
if (boot_idx != active_idx) {
log_info("Boot idx %u is not matching active idx %u, changing active_idx\n",
boot_idx, active_idx);
+
+ ret = fwu_state_machine_updates(FWU_BANK_INVALID, active_idx);
+ if (ret)
+ log_err("Unable to set bank %u state as invalid",
+ active_idx);
+
ret = fwu_set_active_index(boot_idx);
if (!ret)
boottime_check = 1;
diff --git a/lib/fwu_updates/fwu_v1.c b/lib/fwu_updates/fwu_v1.c
index 974abf216f6..5824cca98cf 100644
--- a/lib/fwu_updates/fwu_v1.c
+++ b/lib/fwu_updates/fwu_v1.c
@@ -98,27 +98,27 @@ void fwu_populate_mdata_image_info(struct fwu_data *data)
/**
* fwu_state_machine_updates() - Update FWU state of the platform
- * @trial_state: Is platform transitioning into Trial State
+ * @state: FWU bank state
* @update_index: Bank number to which images have been updated
*
- * On successful completion of updates, transition the platform to
- * either Trial State or Regular State.
+ * FWU_BANK_VALID transition the platform to Trial state
+ * FWU_BANK_ACCEPTED accept the FWU bank state
+ * FWU_BANK_INVALID invalid the FWU bank state
*
* To transition the platform to Trial State, start the
* TrialStateCtr counter, followed by setting the value of bank_state
* field of the metadata to Valid state(applicable only in version 2
* of metadata).
*
- * In case, the platform is to transition directly to Regular State,
- * update the bank_state field of the metadata to Accepted
- * state(applicable only in version 2 of metadata).
+ * Saving the bank_state field of the metadata is only applicable in
+ * version 2 of metadata.
*
* Return: 0 if OK, -ve on error
*/
-int fwu_state_machine_updates(bool trial_state,
+int fwu_state_machine_updates(enum fwu_bank_states state,
uint32_t update_index)
{
- return fwu_trial_state_update(trial_state, update_index);
+ return fwu_trial_state_update(state == FWU_BANK_VALID, update_index);
}
/**
diff --git a/lib/fwu_updates/fwu_v2.c b/lib/fwu_updates/fwu_v2.c
index 159315b45b9..f48b6d1264b 100644
--- a/lib/fwu_updates/fwu_v2.c
+++ b/lib/fwu_updates/fwu_v2.c
@@ -80,42 +80,27 @@ static int fwu_mdata_sanity_checks(void)
return 0;
}
-static int fwu_bank_state_update(bool trial_state, uint32_t bank)
+static int fwu_bank_state_update(enum fwu_bank_states state, uint32_t bank)
{
int ret;
struct fwu_data *data = fwu_get_data();
struct fwu_mdata *mdata = data->fwu_mdata;
- if (!trial_state && !fwu_bank_accepted(data, bank))
+ if (state == FWU_BANK_ACCEPTED && !fwu_bank_accepted(data, bank))
return 0;
- mdata->bank_state[bank] = data->bank_state[bank] = trial_state ?
- FWU_BANK_VALID : FWU_BANK_ACCEPTED;
+ mdata->bank_state[bank] = (uint8_t)state;
+ data->bank_state[bank] = (uint8_t)state;
ret = fwu_sync_mdata(mdata, BOTH_PARTS);
if (ret)
log_err("Unable to set bank_state for bank %u\n", bank);
else
- data->trial_state = trial_state;
+ data->trial_state = state == FWU_BANK_VALID ? 1 : 0;
return ret;
}
-static int fwu_trial_state_start(uint update_index)
-{
- int ret;
-
- ret = fwu_trial_state_ctr_start();
- if (ret)
- return ret;
-
- ret = fwu_bank_state_update(1, update_index);
- if (ret)
- return ret;
-
- return 0;
-}
-
static bool fwu_get_mdata_mandatory(uint part)
{
int ret = 0;
@@ -171,27 +156,34 @@ void fwu_populate_mdata_image_info(struct fwu_data *data)
/**
* fwu_state_machine_updates() - Update FWU state of the platform
- * @trial_state: Is platform transitioning into Trial State
+ * @state: FWU bank state
* @update_index: Bank number to which images have been updated
*
- * On successful completion of updates, transition the platform to
- * either Trial State or Regular State.
+ * FWU_BANK_VALID transition the platform to Trial state
+ * FWU_BANK_ACCEPTED accept the FWU bank state
+ * FWU_BANK_INVALID invalid the FWU bank state
*
* To transition the platform to Trial State, start the
* TrialStateCtr counter, followed by setting the value of bank_state
* field of the metadata to Valid state(applicable only in version 2
* of metadata).
*
- * In case, the platform is to transition directly to Regular State,
- * update the bank_state field of the metadata to Accepted
- * state(applicable only in version 2 of metadata).
+ * Saving the bank_state field of the metadata is only applicable in
+ * version 2 of metadata.
*
* Return: 0 if OK, -ve on error
*/
-int fwu_state_machine_updates(bool trial_state, uint32_t update_index)
+int fwu_state_machine_updates(enum fwu_bank_states state, uint32_t update_index)
{
- return trial_state ? fwu_trial_state_start(update_index) :
- fwu_bank_state_update(0, update_index);
+ int ret;
+
+ if (state == FWU_BANK_VALID) {
+ ret = fwu_trial_state_ctr_start();
+ if (ret)
+ return ret;
+ }
+
+ return fwu_bank_state_update(state, update_index);
}
/**
diff --git a/lib/linux_compat.c b/lib/linux_compat.c
index 985e88eb397..e4a3293e3af 100644
--- a/lib/linux_compat.c
+++ b/lib/linux_compat.c
@@ -32,6 +32,9 @@ struct kmem_cache *get_mem(int element_sz)
struct kmem_cache *ret;
ret = memalign(ARCH_DMA_MINALIGN, sizeof(struct kmem_cache));
+ if (!ret)
+ return NULL;
+
ret->sz = element_sz;
return ret;
diff --git a/lib/lmb.c b/lib/lmb.c
index e2d9fe86c14..8f12c6ad8e5 100644
--- a/lib/lmb.c
+++ b/lib/lmb.c
@@ -611,7 +611,6 @@ static __maybe_unused void lmb_reserve_common_spl(void)
static void lmb_add_memory(void)
{
int i;
- phys_addr_t bank_end;
phys_size_t size;
u64 ram_top = gd->ram_top;
struct bd_info *bd = gd->bd;
@@ -625,23 +624,9 @@ static void lmb_add_memory(void)
for (i = 0; i < CONFIG_NR_DRAM_BANKS; i++) {
size = bd->bi_dram[i].size;
- bank_end = bd->bi_dram[i].start + size;
- if (size) {
+ if (size)
lmb_add(bd->bi_dram[i].start, size);
-
- /*
- * Reserve memory above ram_top as
- * no-overwrite so that it cannot be
- * allocated
- */
- if (bd->bi_dram[i].start >= ram_top)
- lmb_reserve(bd->bi_dram[i].start, size,
- LMB_NOOVERWRITE);
- else if (bank_end > ram_top)
- lmb_reserve(ram_top, bank_end - ram_top,
- LMB_NOOVERWRITE);
- }
}
}
diff --git a/lib/lwip/u-boot/lwipopts.h b/lib/lwip/u-boot/lwipopts.h
index e8a2c9d7a0a..8dae004f1a2 100644
--- a/lib/lwip/u-boot/lwipopts.h
+++ b/lib/lwip/u-boot/lwipopts.h
@@ -65,7 +65,21 @@
#define MEM_ALIGNMENT 8
#define MEMP_NUM_TCP_SEG 16
+
+/* IP fragmentation parameters for TFTP reassembly */
+#define IP_FRAG_MTU_USABLE 1480
+#define PBUF_POOL_HEADROOM 6
+#define PBUF_POOL_RESERVE 4
+#define TFTP_BLOCKSIZE_THRESHOLD 4096
+
+#if defined(CONFIG_TFTP_BLOCKSIZE) && (CONFIG_TFTP_BLOCKSIZE > TFTP_BLOCKSIZE_THRESHOLD)
+#define PBUF_POOL_SIZE (((CONFIG_TFTP_BLOCKSIZE + (IP_FRAG_MTU_USABLE - 1)) / \
+ IP_FRAG_MTU_USABLE) + PBUF_POOL_HEADROOM)
+#define IP_REASS_MAX_PBUFS (PBUF_POOL_SIZE - PBUF_POOL_RESERVE)
+#else
#define PBUF_POOL_SIZE 8
+#define IP_REASS_MAX_PBUFS 4
+#endif
#define LWIP_ARP 1
#define ARP_TABLE_SIZE 4
@@ -76,7 +90,7 @@
#define IP_REASSEMBLY 1
#define IP_FRAG 1
#define IP_REASS_MAXAGE 3
-#define IP_REASS_MAX_PBUFS 4
+
#define IP_FRAG_USES_STATIC_BUF 0
#define IP_DEFAULT_TTL 255
@@ -121,9 +135,13 @@
#define LWIP_UDP 0
#endif
+/*
+ * PBUF_POOL_BUFSIZE is derived from TCP_MSS even when
+ * CONFIG_PROT_TCP_LWIP is not defined
+ */
+#define TCP_MSS 1460
#if defined(CONFIG_PROT_TCP_LWIP)
#define LWIP_TCP 1
-#define TCP_MSS 1460
#define TCP_WND CONFIG_LWIP_TCP_WND
#define LWIP_WND_SCALE 1
#define TCP_RCV_SCALE 0x7
diff --git a/lib/optee/Kconfig b/lib/optee/Kconfig
index 34b9d8afe67..e0de57e2930 100644
--- a/lib/optee/Kconfig
+++ b/lib/optee/Kconfig
@@ -40,6 +40,7 @@ config OPTEE_TZDRAM_SIZE
config BOOTM_OPTEE
bool "Support OPTEE bootm command"
+ depends on LIB_BOOTI || LIB_BOOTM || LIB_BOOTZ
select BOOTM_LINUX
select OPTEE_IMAGE
help
diff --git a/lib/smbios.c b/lib/smbios.c
index b8c2846277a..d5f18c8bd69 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -66,11 +66,47 @@ struct map_sysinfo {
static const struct map_sysinfo sysinfo_to_dt[] = {
{ .si_node = "system", .si_str = "product", .dt_str = "model", 2 },
- { .si_node = "system", .si_str = "manufacturer", .dt_str = "compatible", 1 },
- { .si_node = "baseboard", .si_str = "product", .dt_str = "model", 2 },
- { .si_node = "baseboard", .si_str = "manufacturer", .dt_str = "compatible", 1 },
+ { .si_node = "system", .si_str = "manufacturer",
+ .dt_str = "compatible", 1 },
+ { .si_node = "baseboard", .si_str = "product",
+ .dt_str = "model", 2 },
+ { .si_node = "baseboard", .si_str = "manufacturer",
+ .dt_str = "compatible", 1 },
+ { .si_node = "system-slot", .si_str = "slot-type",
+ .dt_str = "device_type", 0},
+ { .si_node = "system-slot", .si_str = "segment-group-number",
+ .dt_str = "linux,pci-domain", 0},
};
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+static const struct pci_attr_lookup_table pci_attr[] = {
+ { "pci-host-ecam-generic", SMBIOS_SYSSLOT_TYPE_PCIE,
+ SMBIOS_SYSSLOT_WIDTH_8X, SMBIOS_SYSSLOT_LENG_LONG,
+ SMBIOS_SYSSLOT_CHAR_3_3V, SMBIOS_SYSSLOT_CHAR_PCIPME },
+ { "pci-host-cam-generic", SMBIOS_SYSSLOT_TYPE_PCI,
+ SMBIOS_SYSSLOT_WIDTH_32BIT, SMBIOS_SYSSLOT_LENG_SHORT,
+ SMBIOS_SYSSLOT_CHAR_5V | SMBIOS_SYSSLOT_CHAR_3_3V,
+ SMBIOS_SYSSLOT_CHAR_PCIPME },
+ { "pci-host-thunder-ecam", SMBIOS_SYSSLOT_TYPE_PCIEGEN3,
+ SMBIOS_SYSSLOT_WIDTH_8X, SMBIOS_SYSSLOT_LENG_LONG,
+ SMBIOS_SYSSLOT_CHAR_3_3V,
+ SMBIOS_SYSSLOT_CHAR_PCIPME | SMBIOS_SYSSLOT_CHAR_HOTPLUG },
+ { "pci-host-octeontx-ecam", SMBIOS_SYSSLOT_TYPE_PCIEGEN3X16,
+ SMBIOS_SYSSLOT_WIDTH_16X, SMBIOS_SYSSLOT_LENG_LONG,
+ SMBIOS_SYSSLOT_CHAR_3_3V,
+ SMBIOS_SYSSLOT_CHAR_PCIPME | SMBIOS_SYSSLOT_CHAR_HOTPLUG },
+ { "pci-host-thunder-pem", SMBIOS_SYSSLOT_TYPE_PCIEGEN4X8,
+ SMBIOS_SYSSLOT_WIDTH_8X, SMBIOS_SYSSLOT_LENG_LONG,
+ SMBIOS_SYSSLOT_CHAR_3_3V,
+ SMBIOS_SYSSLOT_CHAR_PCIPME | SMBIOS_SYSSLOT_CHAR_HOTPLUG },
+ { "pci-host-octeontx2-pem", SMBIOS_SYSSLOT_TYPE_PCIEGEN4X16,
+ SMBIOS_SYSSLOT_WIDTH_16X, SMBIOS_SYSSLOT_LENG_LONG,
+ SMBIOS_SYSSLOT_CHAR_3_3V,
+ SMBIOS_SYSSLOT_CHAR_PCIPME | SMBIOS_SYSSLOT_CHAR_HOTPLUG |
+ SMBIOS_SYSSLOT_CHAR_PCIBIF },
+};
+#endif
+
/**
* struct smbios_ctx - context for writing SMBIOS tables
*
@@ -95,6 +131,18 @@ struct smbios_ctx {
char *last_str;
};
+typedef int (*smbios_write_subnode)(ulong *current, int handle,
+ struct smbios_ctx *ctx, int idx,
+ int type);
+
+typedef int (*smbios_write_memnode)(ulong *current, int handle,
+ struct smbios_ctx *ctx, int idx,
+ int type);
+
+typedef int (*smbios_write_memctrlnode)(ulong *current, int handle,
+ struct smbios_ctx *ctx, int idx,
+ u64 base, u64 sz);
+
/**
* Function prototype to write a specific type of SMBIOS structure
*
@@ -103,7 +151,7 @@ struct smbios_ctx {
* @ctx: context for writing the tables
* Return: size of the structure
*/
-typedef int (*smbios_write_type)(ulong *addr, int handle,
+typedef int (*smbios_write_type)(ulong *addr, int *handle,
struct smbios_ctx *ctx);
/**
@@ -222,6 +270,7 @@ static int smbios_get_val_si(struct smbios_ctx * __maybe_unused ctx,
{
#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
int val;
+ const struct map_sysinfo *nprop;
if (!ctx->dev)
return val_def;
@@ -240,10 +289,58 @@ static int smbios_get_val_si(struct smbios_ctx * __maybe_unused ctx,
*/
if (!ofnode_read_u32(ofnode_root(), prop, &val))
return val;
+
+ /* If the node is still missing, try with the mapping values */
+ nprop = convert_sysinfo_to_dt(ctx->subnode_name, prop);
+ if (!ofnode_read_u32(ofnode_root(), nprop->dt_str, &val))
+ return val;
#endif
return val_def;
}
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+static u64 smbios_get_u64_si(struct smbios_ctx * __maybe_unused ctx,
+ const char * __maybe_unused prop,
+ int __maybe_unused sysinfo_id, u64 val_def)
+{
+ size_t len;
+ void *data;
+ const fdt32_t *prop_val;
+ int prop_len;
+ u64 val = 0;
+
+ if (!ctx->dev)
+ return val_def;
+
+ if (!sysinfo_get_data(ctx->dev, sysinfo_id, &data, &len))
+ return *((u64 *)data);
+
+ if (!IS_ENABLED(CONFIG_OF_CONTROL) || !prop || !ofnode_valid(ctx->node))
+ return val_def;
+
+ prop_val = ofnode_read_prop(ctx->node, prop, &prop_len);
+ if (!prop_val || prop_len < sizeof(fdt32_t) ||
+ prop_len % sizeof(fdt32_t)) {
+ /*
+ * If the node or property is not valid fallback and try the root
+ */
+ prop_val = ofnode_read_prop(ofnode_root(), prop, &prop_len);
+ if (!prop_val || prop_len < sizeof(fdt32_t) ||
+ prop_len % sizeof(fdt32_t))
+ return val_def;
+ }
+
+ /* 64-bit: <hi lo> or 32-bit */
+ if (prop_len >= sizeof(fdt32_t) * 2) {
+ val = ((u64)fdt32_to_cpu(prop_val[0]) << 32) |
+ fdt32_to_cpu(prop_val[1]);
+ } else {
+ val = fdt32_to_cpu(prop_val[0]);
+ }
+ return val;
+}
+#endif
+
/**
* smbios_add_prop_si() - Add a property from the devicetree or sysinfo
*
@@ -364,7 +461,7 @@ static int smbios_string_table_len(const struct smbios_ctx *ctx)
return (ctx->next_ptr + 1) - ctx->eos;
}
-static int smbios_write_type0(ulong *current, int handle,
+static int smbios_write_type0(ulong *current, int *handle,
struct smbios_ctx *ctx)
{
struct smbios_type0 *t;
@@ -372,7 +469,7 @@ static int smbios_write_type0(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, len);
- fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
+ fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, *handle);
smbios_set_eos(ctx, t->eos);
t->vendor = smbios_add_prop_si(ctx, NULL, SYSID_SM_BIOS_VENDOR,
"U-Boot");
@@ -423,7 +520,7 @@ static int smbios_write_type0(ulong *current, int handle,
return len;
}
-static int smbios_write_type1(ulong *current, int handle,
+static int smbios_write_type1(ulong *current, int *handle,
struct smbios_ctx *ctx)
{
struct smbios_type1 *t;
@@ -434,7 +531,7 @@ static int smbios_write_type1(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, len);
- fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
+ fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, *handle);
smbios_set_eos(ctx, t->eos);
t->manufacturer = smbios_add_prop_si(ctx, "manufacturer",
@@ -471,7 +568,7 @@ static int smbios_write_type1(ulong *current, int handle,
return len;
}
-static int smbios_write_type2(ulong *current, int handle,
+static int smbios_write_type2(ulong *current, int *handle,
struct smbios_ctx *ctx)
{
struct smbios_type2 *t;
@@ -485,7 +582,7 @@ static int smbios_write_type2(ulong *current, int handle,
*/
t = map_sysmem(*current, len);
memset(t, 0, len);
- fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
+ fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, *handle);
/* eos is at the end of the structure */
eos_addr = (u8 *)t + len - sizeof(t->eos);
@@ -519,7 +616,7 @@ static int smbios_write_type2(ulong *current, int handle,
* t->number_contained_objects = <obj_handle_num>;
*/
- t->chassis_handle = handle + 1;
+ t->chassis_handle = *handle + 1;
len = t->hdr.length + smbios_string_table_len(ctx);
*current += len;
@@ -528,7 +625,7 @@ static int smbios_write_type2(ulong *current, int handle,
return len;
}
-static int smbios_write_type3(ulong *current, int handle,
+static int smbios_write_type3(ulong *current, int *handle,
struct smbios_ctx *ctx)
{
struct smbios_type3 *t;
@@ -548,7 +645,7 @@ static int smbios_write_type3(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, len);
- fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
+ fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, *handle);
#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;
@@ -669,7 +766,7 @@ static void smbios_write_type4_dm(struct smbios_type4 *t,
#endif
}
-static int smbios_write_type4(ulong *current, int handle,
+static int smbios_write_type4(ulong *current, int *handle,
struct smbios_ctx *ctx)
{
struct smbios_type4 *t;
@@ -679,7 +776,7 @@ static int smbios_write_type4(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, len);
- fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, handle);
+ fill_smbios_header(t, SMBIOS_PROCESSOR_INFORMATION, len, *handle);
smbios_set_eos(ctx, t->eos);
t->socket_design = smbios_add_prop_si(ctx, "socket-design",
SYSID_SM_PROCESSOR_SOCKET, NULL);
@@ -828,13 +925,14 @@ static int smbios_write_type7_1level(ulong *current, int handle,
return len;
}
-static int smbios_write_type7(ulong *current, int handle,
+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;
+ int hdl_base = *handle;
memcpy(&ctx_bak, ctx, sizeof(ctx_bak));
@@ -850,15 +948,1017 @@ static int smbios_write_type7(ulong *current, int handle,
return 0;
ctx->subnode_name = buf;
ctx->node = ofnode_find_subnode(parent, ctx->subnode_name);
- len += smbios_write_type7_1level(current, handle++, ctx, i);
+ *handle = hdl_base + i;
+ len += smbios_write_type7_1level(current, *handle, ctx, i);
+ memcpy(ctx, &ctx_bak, sizeof(*ctx));
+ }
+
+ return len;
+}
+
+static int smbios_scan_subnodes(ulong *current, struct smbios_ctx *ctx,
+ int *handle, smbios_write_subnode cb, int type)
+{
+ ofnode child;
+ int i;
+ int hdl_base = *handle;
+ int len = 0;
+ struct smbios_ctx ctx_bak;
+
+ memcpy(&ctx_bak, ctx, sizeof(ctx_bak));
+
+ for (i = 0, child = ofnode_first_subnode(ctx->node);
+ ofnode_valid(child); child = ofnode_next_subnode(child), i++) {
+ ctx->node = child;
+ *handle = hdl_base + i;
+ len += cb(current, *handle, ctx, i, type);
+ memcpy(ctx, &ctx_bak, sizeof(*ctx));
+ }
+
+ return len;
+}
+
+static void smbios_lookup_pci_attr(struct smbios_ctx *ctx,
+ struct smbios_type9 *t)
+{
+ const char *compatible;
+ u32 addr_cells, size_cells, total_cells;
+ const fdt32_t *reg;
+ int reglen;
+ int i;
+
+ /* default attributes */
+ t->slot_type = SMBIOS_SYSSLOT_TYPE_PCI;
+ t->slot_data_bus_width = SMBIOS_SYSSLOT_WIDTH_UNKNOWN;
+ t->slot_characteristics_1 = SMBIOS_SYSSLOT_CHAR_UND;
+ t->current_usage = SMBIOS_SYSSLOT_USAGE_UNKNOWN;
+ t->slot_length = SMBIOS_SYSSLOT_LENG_UNKNOWN;
+ t->segment_group_number = smbios_get_val_si(ctx, "segment-group-number",
+ SYSID_NONE,
+ SMBIOS_SYSSLOT_SGGNUM_UND);
+
+ /*
+ * Get #address-cells and #size-cells dynamically
+ * Default 3 for #address-cells and 2 for #size-cells
+ */
+ addr_cells = ofnode_read_u32_default(ctx->node, "#address-cells", 3);
+ size_cells = ofnode_read_u32_default(ctx->node, "#size-cells", 2);
+ total_cells = addr_cells + size_cells;
+
+ /* Read property 'reg' from the node */
+ reg = ofnode_read_prop(ctx->node, "reg", &reglen);
+ if (reg && reglen > addr_cells * sizeof(*reg)) {
+ /* First address-cell: Bus Number */
+ if (addr_cells >= 1)
+ t->bus_number = fdt32_to_cpu(reg[0]);
+ /* Second address-cell: Device/Function */
+ if (addr_cells >= 2)
+ t->device_function_number.data = fdt32_to_cpu(reg[1]);
+ /*
+ * Third address-cell 'Register Offset' and the following
+ * size-cell bytes are not useful for SMBIOS type 9, just
+ * ignore them.
+ */
+ /*
+ * As neither PCI IRQ Routing Table ($PIRQ) nor FDT
+ * property to represent a Slot ID, try to derive a
+ * Slot ID programmatically.
+ */
+ t->slot_id = t->device_function_number.fields.dev_num |
+ (t->bus_number << 5);
+ }
+
+ /* Read 'compatible' property */
+ compatible = ofnode_read_string(ctx->node, "compatible");
+ if (!compatible)
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(pci_attr); i++) {
+ if (strstr(compatible, pci_attr[i].str)) {
+ t->slot_type = pci_attr[i].slot_type;
+ t->slot_data_bus_width = pci_attr[i].data_bus_width;
+ t->slot_length = pci_attr[i].slot_length;
+ t->slot_characteristics_1 = pci_attr[i].chara1;
+ t->slot_characteristics_2 = pci_attr[i].chara2;
+ /* mark it as in-use arbitrarily */
+ t->current_usage = SMBIOS_SYSSLOT_USAGE_INUSE;
+ return;
+ }
+ }
+}
+
+static void smbios_write_type9_fields(struct smbios_ctx *ctx,
+ struct smbios_type9 *t)
+{
+ t->slot_type = smbios_get_val_si(ctx, "slot-type", SYSID_NONE,
+ SMBIOS_SYSSLOT_TYPE_UNKNOWN);
+ t->slot_data_bus_width =
+ smbios_get_val_si(ctx, "data-bus-width",
+ SYSID_NONE, SMBIOS_SYSSLOT_WIDTH_UNKNOWN);
+ t->current_usage = smbios_get_val_si(ctx, "current-usage", SYSID_NONE,
+ SMBIOS_SYSSLOT_USAGE_UNKNOWN);
+ t->slot_length = smbios_get_val_si(ctx, "slot-length", SYSID_NONE,
+ SMBIOS_SYSSLOT_LENG_UNKNOWN);
+ t->slot_id = smbios_get_val_si(ctx, "slot-id", SYSID_NONE, 0);
+ t->slot_characteristics_1 =
+ smbios_get_val_si(ctx, "slot-characteristics-1", SYSID_NONE,
+ SMBIOS_SYSSLOT_CHAR_UND);
+ t->slot_characteristics_2 = smbios_get_val_si(ctx,
+ "slot-characteristics-2",
+ SYSID_NONE, 0);
+ t->segment_group_number = smbios_get_val_si(ctx, "segment-group-number",
+ SYSID_NONE, 0);
+ t->bus_number = smbios_get_val_si(ctx, "bus-number", SYSID_NONE, 0);
+ t->device_function_number.data =
+ smbios_get_val_si(ctx, "device-function-number", SYSID_NONE, 0);
+}
+
+static int smbios_write_type9_1slot(ulong *current, int handle,
+ struct smbios_ctx *ctx,
+ int __maybe_unused idx, int devtype)
+{
+ struct smbios_type9 *t;
+ int len = sizeof(*t);
+ u8 pgroups_cnt;
+ u8 *eos_addr;
+ size_t pgroups_size;
+ void *wp;
+
+ pgroups_cnt = smbios_get_val_si(ctx, "peer-grouping-count",
+ SYSID_NONE, 0);
+ pgroups_size = pgroups_cnt * SMBIOS_TYPE9_PGROUP_SIZE;
+
+ /*
+ * reserve the space for the dynamic bytes of peer_groups.
+ * TODO:
+ * peer_groups = <peer_grouping_count> * SMBIOS_TYPE9_PGROUP_SIZE
+ */
+ len += pgroups_size;
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, len);
+
+ fill_smbios_header(t, SMBIOS_SYSTEM_SLOTS, len, handle);
+
+ /* eos is at the end of the structure */
+ eos_addr = (u8 *)t + len - sizeof(t->eos);
+ smbios_set_eos(ctx, eos_addr);
+
+ /* Write the general fields */
+ t->peer_grouping_count = pgroups_cnt;
+ t->socket_design = smbios_add_prop_si(ctx, "socket-design", SYSID_NONE,
+ NULL);
+ t->electrical_bus_width = smbios_get_val_si(ctx, "data-bus-width",
+ SYSID_NONE, 0);
+
+ /* skip the reserved peer groups and write the following fields from eos */
+ /* t->slot_height */
+ wp = eos_addr - sizeof(t->slot_height);
+ *((u8 *)wp) = smbios_get_val_si(ctx, "slot-height", SYSID_NONE, 0);
+ /* t->slot_pitch */
+ wp -= sizeof(t->slot_pitch);
+ *((u16 *)wp) = smbios_get_val_si(ctx, "slot-pitch", SYSID_NONE, 0);
+ /* t->slot_physical_width */
+ wp -= sizeof(t->slot_physical_width);
+ *((u8 *)wp) = smbios_get_val_si(ctx, "slot-physical-width", SYSID_NONE, 0);
+ /* t->slot_information */
+ wp -= sizeof(t->slot_information);
+ *((u8 *)wp) = smbios_get_val_si(ctx, "slot-information", SYSID_NONE, 0);
+
+ /* For PCI, some fields can be extracted from FDT node */
+ if (devtype == SMBIOS_SYSSLOT_TYPE_PCI)
+ /* Populate PCI attributes from existing PCI properties */
+ smbios_lookup_pci_attr(ctx, t);
+ else if (devtype == SMBIOS_SYSSLOT_TYPE_UNKNOWN) {
+ /* Properties that expected in smbios subnode 'system-slot' */
+ smbios_write_type9_fields(ctx, t);
+ }
+ len = t->hdr.length + smbios_string_table_len(ctx);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_scan_slot_type(ulong *current, int *handle,
+ struct smbios_ctx *ctx)
+{
+ int i = 0;
+ struct smbios_ctx ctx_bak;
+ ofnode child;
+ const struct map_sysinfo *prop;
+ int hdl_base = *handle;
+ int len = 0;
+
+ memcpy(&ctx_bak, ctx, sizeof(ctx_bak));
+ prop = convert_sysinfo_to_dt(ctx->subnode_name, "slot-type");
+ for (child = ofnode_first_subnode(ofnode_root()); ofnode_valid(child);
+ child = ofnode_next_subnode(child)) {
+ const char *dev_type_str;
+ u8 dev_type = SMBIOS_SYSSLOT_TYPE_UNKNOWN;
+
+ dev_type_str = ofnode_read_string(child, prop->dt_str);
+ if (!dev_type_str)
+ continue;
+
+ if (!strcmp(dev_type_str, "pci"))
+ dev_type = SMBIOS_SYSSLOT_TYPE_PCI;
+ else if (!strcmp(dev_type_str, "isa"))
+ dev_type = SMBIOS_SYSSLOT_TYPE_ISA;
+ else if (!strcmp(dev_type_str, "pcmcia"))
+ dev_type = SMBIOS_SYSSLOT_TYPE_PCMCIA;
+ else
+ continue;
+
+ *handle = hdl_base + i;
+ ctx->node = child;
+ len += smbios_write_type9_1slot(current, *handle, ctx, 0,
+ dev_type);
memcpy(ctx, &ctx_bak, sizeof(*ctx));
+ i++;
+ }
+
+ return len;
+}
+
+static int smbios_write_type9(ulong *current, int *handle,
+ struct smbios_ctx *ctx)
+{
+ int len;
+
+ /* TODO: Get system slot information via pci subsystem */
+ if (!IS_ENABLED(CONFIG_OF_CONTROL))
+ return 0; /* Error, return 0-length */
+
+ len = smbios_scan_subnodes(current, ctx, handle,
+ smbios_write_type9_1slot,
+ SMBIOS_SYSSLOT_TYPE_UNKNOWN);
+ if (len)
+ return len;
+
+ /* if no subnode under 'system-slot', try scan the entire FDT */
+ len = smbios_scan_slot_type(current, handle, ctx);
+
+ return len;
+}
+
+static u64 smbios_pop_size_from_memory_node(ofnode node)
+{
+ const fdt32_t *reg;
+ int len;
+ u64 size_bytes;
+
+ /* Read property 'reg' from the node */
+ reg = ofnode_read_prop(node, "reg", &len);
+ if (!reg || len < sizeof(fdt32_t) * 4 || len % sizeof(fdt32_t))
+ return 0;
+
+ /* Combine hi/lo for size (typically 64-bit) */
+ size_bytes = ((u64)fdt32_to_cpu(reg[2]) << 32) | fdt32_to_cpu(reg[3]);
+
+ return size_bytes;
+}
+
+static int
+smbios_write_type16_sum_memory_nodes(ulong *current, int handle,
+ struct smbios_ctx *ctx, u16 cnt, u64 size)
+{
+ struct smbios_type16 *t;
+ int len = sizeof(*t);
+ u8 *eos_addr;
+ void *hdl;
+ size_t hdl_size;
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, len);
+
+ fill_smbios_header(t, SMBIOS_PHYS_MEMORY_ARRAY, len, handle);
+
+ /* eos is at the end of the structure */
+ eos_addr = (u8 *)t + len - sizeof(t->eos);
+ smbios_set_eos(ctx, eos_addr);
+
+ /* default attributes */
+ t->location = SMBIOS_MA_LOCATION_MOTHERBOARD;
+ t->use = SMBIOS_MA_USE_SYSTEM;
+ t->mem_err_corr = SMBIOS_MA_ERRCORR_UNKNOWN;
+ t->mem_err_info_hdl = SMBIOS_MA_ERRINFO_NONE;
+ t->num_of_mem_dev = cnt;
+
+ /* Use extended field */
+ t->max_cap = cpu_to_le32(0x80000000);
+ t->ext_max_cap = cpu_to_le64(size >> 10); /* In KB */
+
+ /* Save the memory array handles */
+ if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl,
+ &hdl_size) &&
+ hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16))
+ *((u16 *)hdl) = handle;
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static void
+smbios_pop_type16_from_memcontroller_node(ofnode node, struct smbios_type16 *t)
+{
+ ofnode child;
+ int count = 0;
+ u64 total = 0;
+
+ /* default attributes */
+ t->location = SMBIOS_MA_LOCATION_MOTHERBOARD;
+ t->use = SMBIOS_MA_USE_SYSTEM;
+ t->mem_err_info_hdl = SMBIOS_MA_ERRINFO_NONE;
+
+ /* Check custom property 'ecc-enabled' */
+ if (ofnode_read_bool(node, "ecc-enabled"))
+ t->mem_err_corr = SMBIOS_MA_ERRCORR_SBITECC;
+ else
+ t->mem_err_corr = SMBIOS_MA_ERRCORR_UNKNOWN;
+
+ /* Read subnodes with 'size' property */
+ for (child = ofnode_first_subnode(node); ofnode_valid(child);
+ child = ofnode_next_subnode(child)) {
+ u64 sz = 0;
+ const fdt32_t *size;
+ int len;
+
+ size = ofnode_read_prop(child, "size", &len);
+ if (!size || len < sizeof(fdt32_t) || len % sizeof(fdt32_t))
+ continue;
+
+ /* 64-bit size: <hi lo> or 32-bit size */
+ if (len >= sizeof(fdt32_t) * 2)
+ sz = ((u64)fdt32_to_cpu(size[0]) << 32) |
+ fdt32_to_cpu(size[1]);
+ else
+ sz = fdt32_to_cpu(size[0]);
+
+ count++;
+ total += sz;
}
+
+ /*
+ * Number of memory devices associated with this array
+ * (i.e., how many Type17 entries link to this Type16 array)
+ */
+ t->num_of_mem_dev = count;
+
+ /* Use extended field */
+ t->max_cap = cpu_to_le32(0x80000000);
+ t->ext_max_cap = cpu_to_le64(total >> 10); /* In KB */
+}
+
+static void smbios_pop_type16_si(struct smbios_ctx *ctx,
+ struct smbios_type16 *t)
+{
+ t->location = smbios_get_val_si(ctx, "location", SYSID_NONE,
+ SMBIOS_MA_LOCATION_UNKNOWN);
+ t->use = smbios_get_val_si(ctx, "use", SYSID_NONE,
+ SMBIOS_MA_USE_UNKNOWN);
+ t->mem_err_corr = smbios_get_val_si(ctx, "memory-error-correction", SYSID_NONE,
+ SMBIOS_MA_ERRCORR_UNKNOWN);
+ t->max_cap = smbios_get_val_si(ctx, "maximum-capacity", SYSID_NONE, 0);
+ t->mem_err_info_hdl = smbios_get_val_si(ctx, "memory-error-information-handle",
+ SYSID_NONE, SMBIOS_MA_ERRINFO_NONE);
+ t->num_of_mem_dev = smbios_get_val_si(ctx, "number-of-memory-devices", SYSID_NONE, 1);
+ t->ext_max_cap = smbios_get_u64_si(ctx, "extended-maximum-capacity", SYSID_NONE, 0);
+}
+
+static int smbios_write_type16_1array(ulong *current, int handle,
+ struct smbios_ctx *ctx, int idx,
+ int type)
+{
+ struct smbios_type16 *t;
+ int len = sizeof(*t);
+ u8 *eos_addr;
+ void *hdl;
+ size_t hdl_size;
+
+ t = map_sysmem(*current, len);
+ memset(t, 0, len);
+
+ fill_smbios_header(t, SMBIOS_PHYS_MEMORY_ARRAY, len, handle);
+
+ /* eos is at the end of the structure */
+ eos_addr = (u8 *)t + len - sizeof(t->eos);
+ smbios_set_eos(ctx, eos_addr);
+
+ if (type == SMBIOS_MEM_CUSTOM)
+ smbios_pop_type16_si(ctx, t);
+ else if (type == SMBIOS_MEM_FDT_MEMCON_NODE)
+ smbios_pop_type16_from_memcontroller_node(ctx->node, t);
+
+ /* Save the memory array handles */
+ if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl,
+ &hdl_size) &&
+ hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16))
+ *((u16 *)hdl + idx) = handle;
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
+ *current += len;
+ unmap_sysmem(t);
+
return len;
}
+static int smbios_write_type16(ulong *current, int *handle,
+ struct smbios_ctx *ctx)
+{
+ int len;
+ struct smbios_ctx ctx_bak;
+ ofnode child;
+ int idx;
+ u64 total = 0;
+ int count = 0;
+ int hdl_base = *handle;
+
+ if (!IS_ENABLED(CONFIG_OF_CONTROL))
+ return 0; /* Error, return 0-length */
+
+ /* Step 1: Scan any subnode exists under 'memory-array' */
+ len = smbios_scan_subnodes(current, ctx, handle,
+ smbios_write_type16_1array,
+ SMBIOS_MEM_CUSTOM);
+ if (len)
+ return len;
+
+ /* Step 2: Scan 'memory' node from the entire FDT */
+ for (child = ofnode_first_subnode(ofnode_root());
+ ofnode_valid(child); child = ofnode_next_subnode(child)) {
+ const char *str;
+
+ /* Look up for 'device_type = "memory"' */
+ str = ofnode_read_string(child, "device_type");
+ if (str && !strcmp(str, "memory")) {
+ count++;
+ total += smbios_pop_size_from_memory_node(child);
+ }
+ }
+ /*
+ * Generate one type16 instance for all 'memory' nodes,
+ * use idx=0 implicitly
+ */
+ if (count)
+ len += smbios_write_type16_sum_memory_nodes(current, *handle,
+ ctx, count, total);
+
+ /* Step 3: Scan 'memory-controller' node from the entire FDT */
+ /* idx starts from 1 */
+ memcpy(&ctx_bak, ctx, sizeof(ctx_bak));
+ for (idx = 1, child = ofnode_first_subnode(ofnode_root());
+ ofnode_valid(child); child = ofnode_next_subnode(child)) {
+ const char *compat;
+ const char *name;
+
+ /*
+ * Look up for node with name or property 'compatible'
+ * containing 'memory-controller'.
+ */
+ name = ofnode_get_name(child);
+ compat = ofnode_read_string(child, "compatible");
+ if ((!compat || !strstr(compat, "memory-controller")) &&
+ (!name || !strstr(name, "memory-controller")))
+ continue;
+
+ *handle = hdl_base + idx;
+ ctx->node = child;
+ /*
+ * Generate one type16 instance for each 'memory-controller'
+ * node, sum the 'size' of all subnodes.
+ */
+ len += smbios_write_type16_1array(current, *handle, ctx, idx,
+ SMBIOS_MEM_FDT_MEMCON_NODE);
+ idx++;
+ memcpy(ctx, &ctx_bak, sizeof(*ctx));
+ }
+
+ return len;
+}
+
+static void smbios_pop_type17_general_si(struct smbios_ctx *ctx,
+ struct smbios_type17 *t)
+{
+ t->mem_err_info_hdl =
+ smbios_get_val_si(ctx, "memory-error-information-handle",
+ SYSID_NONE, SMBIOS_MD_ERRINFO_NONE);
+ t->total_width = smbios_get_val_si(ctx, "total-width", SYSID_NONE, 0);
+ t->data_width = smbios_get_val_si(ctx, "data-width", SYSID_NONE, 0);
+ t->form_factor = smbios_get_val_si(ctx, "form-factor",
+ SYSID_NONE, SMBIOS_MD_FF_UNKNOWN);
+ t->dev_set = smbios_get_val_si(ctx, "device-set", SYSID_NONE,
+ SMBIOS_MD_DEVSET_UNKNOWN);
+ t->dev_locator = smbios_add_prop_si(ctx, "device-locator", SYSID_NONE,
+ NULL);
+ t->bank_locator = smbios_add_prop_si(ctx, "bank-locator", SYSID_NONE,
+ NULL);
+ t->mem_type = smbios_get_val_si(ctx, "memory-type",
+ SYSID_NONE, SMBIOS_MD_TYPE_UNKNOWN);
+ t->type_detail = smbios_get_val_si(ctx, "type-detail",
+ SYSID_NONE, SMBIOS_MD_TD_UNKNOWN);
+ t->speed = smbios_get_val_si(ctx, "speed", SYSID_NONE,
+ SMBIOS_MD_SPEED_UNKNOWN);
+ t->manufacturer = smbios_add_prop_si(ctx, "manufacturer", SYSID_NONE,
+ NULL);
+ t->serial_number = smbios_add_prop_si(ctx, "serial-number", SYSID_NONE,
+ NULL);
+ t->asset_tag = smbios_add_prop_si(ctx, "asset-tag", SYSID_NONE, NULL);
+ t->part_number = smbios_add_prop_si(ctx, "part-number", SYSID_NONE,
+ NULL);
+ t->attributes = smbios_get_val_si(ctx, "attributes", SYSID_NONE,
+ SMBIOS_MD_ATTR_RANK_UNKNOWN);
+ t->config_mem_speed = smbios_get_val_si(ctx, "configured-memory-speed",
+ SYSID_NONE,
+ SMBIOS_MD_CONFSPEED_UNKNOWN);
+ t->min_voltage = smbios_get_val_si(ctx, "minimum-voltage", SYSID_NONE,
+ SMBIOS_MD_VOLTAGE_UNKNOWN);
+ t->max_voltage = smbios_get_val_si(ctx, "maximum-voltage", SYSID_NONE,
+ SMBIOS_MD_VOLTAGE_UNKNOWN);
+ t->config_voltage = smbios_get_val_si(ctx, "configured-voltage",
+ SYSID_NONE,
+ SMBIOS_MD_VOLTAGE_UNKNOWN);
+ t->mem_tech = smbios_get_val_si(ctx, "memory-technology",
+ SYSID_NONE, SMBIOS_MD_TECH_UNKNOWN);
+ t->mem_op_mode_cap =
+ smbios_get_val_si(ctx, "memory-operating-mode-capability",
+ SYSID_NONE, SMBIOS_MD_OPMC_UNKNOWN);
+ t->fw_ver = smbios_add_prop_si(ctx, "firmware-version", SYSID_NONE,
+ NULL);
+ t->module_man_id = smbios_get_val_si(ctx, "module-manufacturer-id",
+ SYSID_NONE, 0);
+ t->module_prod_id = smbios_get_val_si(ctx, "module-product-id",
+ SYSID_NONE, 0);
+ t->mem_subsys_con_man_id =
+ smbios_get_val_si(ctx,
+ "memory-subsystem-controller-manufacturer-id",
+ SYSID_NONE, 0);
+ t->mem_subsys_con_prod_id =
+ smbios_get_val_si(ctx,
+ "memory-subsystem-controller-product-id",
+ SYSID_NONE, 0);
+ t->nonvolatile_size = smbios_get_u64_si(ctx, "non-volatile-size",
+ SYSID_NONE,
+ SMBIOS_MS_PORT_SIZE_UNKNOWN);
+ t->volatile_size = smbios_get_u64_si(ctx, "volatile-size",
+ SYSID_NONE,
+ SMBIOS_MS_PORT_SIZE_UNKNOWN);
+ t->cache_size = smbios_get_u64_si(ctx, "cache-size",
+ SYSID_NONE,
+ SMBIOS_MS_PORT_SIZE_UNKNOWN);
+ t->logical_size = smbios_get_u64_si(ctx, "logical-size",
+ SYSID_NONE,
+ SMBIOS_MS_PORT_SIZE_UNKNOWN);
+ t->ext_speed = smbios_get_val_si(ctx, "extended-speed", SYSID_NONE, 0);
+ t->ext_config_mem_speed =
+ smbios_get_val_si(ctx, "extended-configured-memory-speed",
+ SYSID_NONE, 0);
+ t->pmic0_man_id = smbios_get_val_si(ctx, "pmic0-manufacturer-id",
+ SYSID_NONE, 0);
+ t->pmic0_rev_num = smbios_get_val_si(ctx, "pmic0-revision-number",
+ SYSID_NONE, 0);
+ t->rcd_man_id = smbios_get_val_si(ctx, "rcd-manufacturer-id",
+ SYSID_NONE, 0);
+ t->rcd_rev_num = smbios_get_val_si(ctx, "rcd-revision-number",
+ SYSID_NONE, 0);
+}
+
+static void
+smbios_pop_type17_size_from_memory_node(ofnode node, struct smbios_type17 *t)
+{
+ const fdt32_t *reg;
+ int len;
+ u64 sz;
+ u32 size_mb;
+
+ /* Read property 'reg' from the node */
+ reg = ofnode_read_prop(node, "reg", &len);
+ if (!reg || len < sizeof(fdt32_t) * 4 || len % sizeof(fdt32_t))
+ return;
+
+ /* Combine hi/lo for size (typically 64-bit) */
+ sz = ((u64)fdt32_to_cpu(reg[2]) << 32) | fdt32_to_cpu(reg[3]);
+
+ /* Convert size to MB */
+ size_mb = (u32)(sz >> 20); /* 1 MB = 2^20 */
+ if (size_mb < SMBIOS_MD_SIZE_EXT) {
+ t->size = cpu_to_le16(size_mb);
+ t->ext_size = 0;
+ return;
+ }
+
+ t->size = cpu_to_le16(SMBIOS_MD_SIZE_EXT); /* Signal extended used */
+ t->ext_size = cpu_to_le32((u32)(sz >> 10)); /* In KB */
+}
+
+static void smbios_pop_type17_size_si(struct smbios_ctx *ctx,
+ struct smbios_type17 *t)
+{
+ t->size = smbios_get_val_si(ctx, "size", SYSID_NONE,
+ SMBIOS_MD_SIZE_UNKNOWN);
+ t->ext_size = smbios_get_val_si(ctx, "extended-size", SYSID_NONE, 0);
+}
+
+static int
+smbios_scan_memctrl_subnode(ulong *current, int *handle, struct smbios_ctx *ctx,
+ int idx, smbios_write_memctrlnode cb)
+{
+ int total_len = 0;
+ ofnode child;
+ int i = 0;
+ int hdl_base = *handle;
+ u64 base = 0;
+
+ /*
+ * Enumerate all subnodes of 'memory-controller' that contain 'size'
+ * property and generate one instance for each.
+ */
+ for (child = ofnode_first_subnode(ctx->node); ofnode_valid(child);
+ child = ofnode_next_subnode(child)) {
+ u64 sz = 0;
+ const fdt32_t *size;
+ int proplen;
+
+ size = ofnode_read_prop(child, "size", &proplen);
+ if (!size || proplen < sizeof(fdt32_t) ||
+ proplen % sizeof(fdt32_t))
+ continue;
+
+ /* 64-bit size: <hi lo> or 32-bit size */
+ if (proplen >= sizeof(fdt32_t) * 2)
+ sz = ((u64)fdt32_to_cpu(size[0]) << 32) |
+ fdt32_to_cpu(size[1]);
+ else
+ sz = fdt32_to_cpu(size[0]);
+
+ *handle = hdl_base + i;
+ total_len += cb(current, *handle, ctx, idx, base, sz);
+ base += sz;
+ i++;
+ }
+
+ return total_len;
+}
+
+static int
+smbios_write_type17_from_memctrl_node(ulong *current, int handle,
+ struct smbios_ctx *ctx, int idx,
+ u64 __maybe_unused base, u64 sz)
+{
+ struct smbios_type17 *t;
+ int len;
+ u8 *eos_addr;
+ u32 size_mb;
+ void *hdl;
+ size_t hdl_size;
+
+ len = sizeof(*t);
+ t = map_sysmem(*current, len);
+ memset(t, 0, len);
+
+ fill_smbios_header(t, SMBIOS_MEMORY_DEVICE, len, handle);
+
+ /* eos is at the end of the structure */
+ eos_addr = (u8 *)t + len - sizeof(t->eos);
+ smbios_set_eos(ctx, eos_addr);
+
+ /* Read the memory array handles */
+ if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl,
+ &hdl_size) &&
+ hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16))
+ t->phy_mem_array_hdl = *((u16 *)hdl + idx);
+
+ /* Convert to MB */
+ size_mb = (u32)(sz >> 20);
+ if (size_mb < SMBIOS_MD_SIZE_EXT) {
+ /* Use 16-bit size field */
+ t->size = cpu_to_le16(size_mb); /* In MB */
+ t->ext_size = cpu_to_le32(0);
+ } else {
+ /* Signal use of extended size field */
+ t->size = cpu_to_le16(SMBIOS_MD_SIZE_EXT);
+ t->ext_size = cpu_to_le32((u32)(sz >> 10)); /* In KB */
+ }
+
+ /* Write other general fields */
+ smbios_pop_type17_general_si(ctx, t);
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_write_type17_mem(ulong *current, int handle,
+ struct smbios_ctx *ctx, int idx,
+ int type)
+{
+ struct smbios_type17 *t;
+ int len;
+ u8 *eos_addr;
+ void *hdl;
+ size_t hdl_size;
+
+ len = sizeof(*t);
+ t = map_sysmem(*current, len);
+ memset(t, 0, len);
+
+ fill_smbios_header(t, SMBIOS_MEMORY_DEVICE, len, handle);
+
+ /* eos is at the end of the structure */
+ eos_addr = (u8 *)t + len - sizeof(t->eos);
+ smbios_set_eos(ctx, eos_addr);
+
+ if (type == SMBIOS_MEM_CUSTOM) {
+ smbios_pop_type17_size_si(ctx, t);
+
+ t->phy_mem_array_hdl =
+ smbios_get_val_si(ctx, "physical-memory-array-handle",
+ SYSID_NONE, 0);
+ } else if (type == SMBIOS_MEM_FDT_MEM_NODE) {
+ smbios_pop_type17_size_from_memory_node(ctx->node, t);
+
+ /* Read the memory array handles */
+ if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl,
+ &hdl_size) &&
+ hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16))
+ t->phy_mem_array_hdl = *((u16 *)hdl + idx);
+ }
+
+ /* Write other general fields */
+ smbios_pop_type17_general_si(ctx, t);
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_scan_mem_nodes(ulong *current, int *handle,
+ struct smbios_ctx *ctx,
+ smbios_write_memnode mem_cb,
+ int *idx)
+{
+ int len = 0;
+ struct smbios_ctx ctx_bak;
+ ofnode child;
+ int hdl_base = *handle;
+
+ memcpy(&ctx_bak, ctx, sizeof(ctx_bak));
+
+ for (child = ofnode_first_subnode(ofnode_root());
+ ofnode_valid(child); child = ofnode_next_subnode(child)) {
+ const char *str;
+
+ /* Look up for 'device_type = "memory"' */
+ str = ofnode_read_string(child, "device_type");
+ if (!str || strcmp(str, "memory"))
+ continue;
+
+ ctx->node = child;
+ *handle = hdl_base + *idx;
+ /* Generate one instance for each 'memory' node */
+ len += mem_cb(current, *handle, ctx, *idx,
+ SMBIOS_MEM_FDT_MEM_NODE);
+ memcpy(ctx, &ctx_bak, sizeof(*ctx));
+ (*idx)++;
+ }
+
+ return len;
+}
+
+static int smbios_scan_mctrl_subnodes(ulong *current, int *handle,
+ struct smbios_ctx *ctx,
+ smbios_write_memctrlnode mctrl_wcb,
+ int *idx)
+{
+ int len = 0;
+ struct smbios_ctx ctx_bak;
+ ofnode child;
+
+ memcpy(&ctx_bak, ctx, sizeof(ctx_bak));
+
+ for (child = ofnode_first_subnode(ofnode_root());
+ ofnode_valid(child); child = ofnode_next_subnode(child)) {
+ const char *compat;
+ const char *name;
+
+ /*
+ * Look up for node with name or property 'compatible'
+ * containing 'memory-controller'.
+ */
+ name = ofnode_get_name(child);
+ compat = ofnode_read_string(child, "compatible");
+ if ((!compat || !strstr(compat, "memory-controller")) &&
+ (!name || !strstr(name, "memory-controller")))
+ continue;
+
+ (*handle)++;
+ ctx->node = child;
+ /*
+ * Generate one instance for each subnode of
+ * 'memory-controller' which contains property 'size'.
+ */
+ len += smbios_scan_memctrl_subnode(current, handle, ctx,
+ *idx, mctrl_wcb);
+ memcpy(ctx, &ctx_bak, sizeof(*ctx));
+ (*idx)++;
+ }
+ return len;
+}
+
+static int smbios_write_type1719(ulong *current, int *handle,
+ struct smbios_ctx *ctx,
+ smbios_write_memnode mem_cb,
+ smbios_write_memctrlnode mctrl_wcb)
+{
+ int len = 0;
+ int idx;
+
+ if (!IS_ENABLED(CONFIG_OF_CONTROL))
+ return 0; /* Error, return 0-length */
+
+ /* Step 1: Scan any subnode exists */
+ len = smbios_scan_subnodes(current, ctx, handle, mem_cb,
+ SMBIOS_MEM_CUSTOM);
+ if (len)
+ return len;
+
+ /* Step 2: Scan 'memory' node from the entire FDT */
+ idx = 0;
+ len += smbios_scan_mem_nodes(current, handle, ctx, mem_cb, &idx);
+
+ /* Step 3: Scan 'memory-controller' node from the entire FDT */
+ len += smbios_scan_mctrl_subnodes(current, handle, ctx, mctrl_wcb, &idx);
+
+ return len;
+}
+
+static int smbios_write_type17(ulong *current, int *handle,
+ struct smbios_ctx *ctx)
+{
+ return smbios_write_type1719(current, handle, ctx,
+ smbios_write_type17_mem,
+ smbios_write_type17_from_memctrl_node);
+}
+
+static void smbios_pop_type19_general_si(struct smbios_ctx *ctx,
+ struct smbios_type19 *t)
+{
+ t->partition_wid =
+ smbios_get_val_si(ctx, "partition-width ",
+ SYSID_NONE, SMBIOS_MAMA_PW_DEF);
+}
+
+static void smbios_pop_type19_addr_si(struct smbios_ctx *ctx,
+ struct smbios_type19 *t)
+{
+ t->start_addr = smbios_get_val_si(ctx, "starting-address", SYSID_NONE,
+ 0);
+ t->end_addr = smbios_get_val_si(ctx, "ending-address", SYSID_NONE, 0);
+ t->ext_start_addr = smbios_get_u64_si(ctx, "extended-starting-address",
+ SYSID_NONE, 0);
+ t->ext_end_addr = smbios_get_u64_si(ctx, "extended-ending-address",
+ SYSID_NONE, 0);
+}
+
+static void
+smbios_pop_type19_addr_from_memory_node(ofnode node, struct smbios_type19 *t)
+{
+ const fdt32_t *reg;
+ int len;
+ u64 sz;
+ u64 addr;
+
+ /* Read property 'reg' from the node */
+ reg = ofnode_read_prop(node, "reg", &len);
+ if (!reg || len < sizeof(fdt32_t) * 4 || len % sizeof(fdt32_t))
+ return;
+
+ /* Combine hi/lo for size and address (typically 64-bit) */
+ sz = ((u64)fdt32_to_cpu(reg[2]) << 32) | fdt32_to_cpu(reg[3]);
+ addr = ((u64)fdt32_to_cpu(reg[0]) << 32) | fdt32_to_cpu(reg[1]);
+
+ t->ext_start_addr = cpu_to_le64(addr);
+ t->ext_end_addr = cpu_to_le64(addr + sz - 1);
+
+ /* If address range fits in 32-bit, populate legacy fields */
+ if ((addr + sz - 1) <= 0xFFFFFFFFULL) {
+ t->start_addr = cpu_to_le32((u32)addr);
+ t->end_addr = cpu_to_le32((u32)(addr + sz - 1));
+ } else {
+ t->start_addr = cpu_to_le32(0xFFFFFFFF);
+ t->end_addr = cpu_to_le32(0xFFFFFFFF);
+ }
+}
+
+static int
+smbios_write_type19_from_memctrl_node(ulong *current, int handle,
+ struct smbios_ctx *ctx, int idx,
+ u64 base, u64 sz)
+{
+ struct smbios_type19 *t;
+ int len;
+ u8 *eos_addr;
+ void *hdl;
+ size_t hdl_size;
+
+ len = sizeof(*t);
+ t = map_sysmem(*current, len);
+ memset(t, 0, len);
+
+ fill_smbios_header(t, SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS, len, handle);
+
+ /* eos is at the end of the structure */
+ eos_addr = (u8 *)t + len - sizeof(t->eos);
+ smbios_set_eos(ctx, eos_addr);
+
+ /* Read the memory array handles */
+ if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl,
+ &hdl_size) &&
+ hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16))
+ t->mem_array_hdl = *((u16 *)hdl + idx);
+
+ t->ext_start_addr = cpu_to_le64(base);
+ t->ext_end_addr = cpu_to_le64(base + sz - 1);
+
+ if ((base + sz - 1) <= 0xFFFFFFFFULL) {
+ t->start_addr = cpu_to_le32((u32)base);
+ t->end_addr = cpu_to_le32((u32)(base + sz - 1));
+ } else {
+ t->start_addr = cpu_to_le32(0xFFFFFFFF);
+ t->end_addr = cpu_to_le32(0xFFFFFFFF);
+ }
+
+ /* Write other general fields */
+ smbios_pop_type19_general_si(ctx, t);
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_write_type19_mem(ulong *current, int handle,
+ struct smbios_ctx *ctx, int idx,
+ int type)
+{
+ struct smbios_type19 *t;
+ int len;
+ u8 *eos_addr;
+ void *hdl;
+ size_t hdl_size;
+
+ len = sizeof(*t);
+ t = map_sysmem(*current, len);
+ memset(t, 0, len);
+
+ fill_smbios_header(t, SMBIOS_MEMORY_ARRAY_MAPPED_ADDRESS, len, handle);
+
+ /* eos is at the end of the structure */
+ eos_addr = (u8 *)t + len - sizeof(t->eos);
+ smbios_set_eos(ctx, eos_addr);
+
+ if (type == SMBIOS_MEM_CUSTOM) {
+ smbios_pop_type19_addr_si(ctx, t);
+ t->mem_array_hdl = smbios_get_val_si(ctx, "memory-array-handle",
+ SYSID_NONE, 0);
+ } else if (type == SMBIOS_MEM_FDT_MEM_NODE) {
+ smbios_pop_type19_addr_from_memory_node(ctx->node, t);
+ /* Read the memory array handles */
+ if (!sysinfo_get_data(ctx->dev, SYSID_SM_MEMARRAY_HANDLE, &hdl,
+ &hdl_size) &&
+ hdl_size == SYSINFO_MEM_HANDLE_MAX * sizeof(u16))
+ t->mem_array_hdl = *((u16 *)hdl + idx);
+ }
+
+ /* Write other general fields */
+ smbios_pop_type19_general_si(ctx, t);
+
+ len = t->hdr.length + smbios_string_table_len(ctx);
+ *current += len;
+ unmap_sysmem(t);
+
+ return len;
+}
+
+static int smbios_write_type19(ulong *current, int *handle,
+ struct smbios_ctx *ctx)
+{
+ return smbios_write_type1719(current, handle, ctx,
+ smbios_write_type19_mem,
+ smbios_write_type19_from_memctrl_node);
+}
+
#endif /* #if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE) */
-static int smbios_write_type32(ulong *current, int handle,
+static int smbios_write_type32(ulong *current, int *handle,
struct smbios_ctx *ctx)
{
struct smbios_type32 *t;
@@ -866,7 +1966,7 @@ static int smbios_write_type32(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, len);
- fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, handle);
+ fill_smbios_header(t, SMBIOS_SYSTEM_BOOT_INFORMATION, len, *handle);
smbios_set_eos(ctx, t->eos);
*current += len;
@@ -875,7 +1975,7 @@ static int smbios_write_type32(ulong *current, int handle,
return len;
}
-static int smbios_write_type127(ulong *current, int handle,
+static int smbios_write_type127(ulong *current, int *handle,
struct smbios_ctx *ctx)
{
struct smbios_type127 *t;
@@ -883,7 +1983,7 @@ static int smbios_write_type127(ulong *current, int handle,
t = map_sysmem(*current, len);
memset(t, 0, len);
- fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, handle);
+ fill_smbios_header(t, SMBIOS_END_OF_TABLE, len, *handle);
*current += len;
unmap_sysmem(t);
@@ -902,6 +2002,12 @@ static struct smbios_write_method smbios_write_funcs[] = {
{ smbios_write_type7, "cache", },
#endif
{ smbios_write_type4, "processor"},
+#if IS_ENABLED(CONFIG_GENERATE_SMBIOS_TABLE_VERBOSE)
+ { smbios_write_type9, "system-slot"},
+ { smbios_write_type16, "memory-array"},
+ { smbios_write_type17, "memory-device"},
+ { smbios_write_type19, "memory-array-mapped-address"},
+#endif
{ smbios_write_type32, },
{ smbios_write_type127 },
};
@@ -954,7 +2060,8 @@ ulong write_smbios_table(ulong addr)
ctx.node = ofnode_find_subnode(parent_node,
method->subnode_name);
}
- len += method->write((ulong *)&addr, handle++, &ctx);
+ len += method->write((ulong *)&addr, &handle, &ctx);
+ handle++;
}
/*
diff --git a/lib/uuid.c b/lib/uuid.c
index 0a166320e07..3a666d0430d 100644
--- a/lib/uuid.c
+++ b/lib/uuid.c
@@ -254,6 +254,12 @@ static const struct {
NULL, "EFI Conformance Profiles Table",
EFI_CONFORMANCE_PROFILES_TABLE_GUID,
},
+#if CONFIG_IS_ENABLED(EFI_ECPT)
+ {
+ NULL, "EFI EBBR 2.1 Conformance Profile",
+ EFI_CONFORMANCE_PROFILE_EBBR_2_1_GUID,
+ },
+#endif
#ifdef CONFIG_EFI_RISCV_BOOT_PROTOCOL
{
NULL, "RISC-V Boot",