Merge tag 'smbios-2024-04-rc2' of https://source.denx.de/u-boot/custodians/u-boot-efi

Pull request smbios-2024-04-rc2

* In smbios command
  - write 'Not Specified' for missing strings
  - show correct table size for SMBIOS2.1 entry point
  - adjust formatting of handle numbers
  - add missing colon after UUID
* In generated SMBIOS table
  - avoid introducing 'Unknown' string for missing properties
  - provide RISC-V vendor ID in the type 4 structure
  - provide the correct chassis handle in structure type 2
* Rename Structure Table Maximum Size field in SMBIOS 3 entry point
diff --git a/cmd/smbios.c b/cmd/smbios.c
index feebf93..66f6b76 100644
--- a/cmd/smbios.c
+++ b/cmd/smbios.c
@@ -25,6 +25,10 @@
 {
 	const char *str = (char *)table +
 			  ((struct smbios_header *)table)->length;
+	static const char fallback[] = "Not Specified";
+
+	if (!index)
+		return fallback;
 
 	if (!*str)
 		++str;
@@ -41,7 +45,7 @@
 	if (table->type == SMBIOS_END_OF_TABLE)
 		return NULL;
 
-	str = smbios_get_string(table, 0);
+	str = smbios_get_string(table, -1);
 	return (struct smbios_header *)(++str);
 }
 
@@ -76,7 +80,7 @@
 	smbios_print_str("Version", table, table->version);
 	smbios_print_str("Serial Number", table, table->serial_number);
 	if (table->length >= 0x19) {
-		printf("\tUUID %pUl\n", table->uuid);
+		printf("\tUUID: %pUl\n", table->uuid);
 		smbios_print_str("Wake Up Type", table, table->serial_number);
 	}
 	if (table->length >= 0x1b) {
@@ -95,9 +99,9 @@
 	smbios_print_str("Version", table, table->version);
 	smbios_print_str("Serial Number", table, table->serial_number);
 	smbios_print_str("Asset Tag", table, table->asset_tag_number);
-	printf("\tFeature Flags: 0x%2x\n", table->feature_flags);
+	printf("\tFeature Flags: 0x%04x\n", table->feature_flags);
 	smbios_print_str("Chassis Location", table, table->chassis_location);
-	printf("\tChassis Handle: 0x%2x\n", table->chassis_handle);
+	printf("\tChassis Handle: 0x%04x\n", table->chassis_handle);
 	smbios_print_str("Board Type", table, table->board_type);
 	printf("\tContained Object Handles: ");
 	handle = (void *)table->eos;
@@ -122,7 +126,7 @@
 	static const char smbios_sig[] = "_SM_";
 	static const char smbios3_sig[] = "_SM3_";
 	size_t count = 0;
-	u32 max_struct_size;
+	u32 table_maximum_size;
 
 	addr = gd_smbios_start();
 	if (!addr) {
@@ -138,7 +142,7 @@
 			 entry3->major_ver, entry3->minor_ver, entry3->doc_rev);
 		table = (void *)(uintptr_t)entry3->struct_table_address;
 		size = entry3->length;
-		max_struct_size = entry3->max_struct_size;
+		table_maximum_size = entry3->table_maximum_size;
 	} else if (!memcmp(entry, smbios_sig, sizeof(smbios_sig) - 1)) {
 		struct smbios_entry *entry2 = entry;
 
@@ -146,7 +150,7 @@
 			 entry2->major_ver, entry2->minor_ver);
 		table = (void *)(uintptr_t)entry2->struct_table_address;
 		size = entry2->length;
-		max_struct_size = entry2->max_struct_size;
+		table_maximum_size = entry2->struct_table_length;
 	} else {
 		log_err("Unknown SMBIOS anchor format\n");
 		return CMD_RET_FAILURE;
@@ -159,7 +163,7 @@
 
 	for (struct smbios_header *pos = table; pos; pos = next_table(pos))
 		++count;
-	printf("%zd structures occupying %d bytes\n", count, max_struct_size);
+	printf("%zd structures occupying %d bytes\n", count, table_maximum_size);
 	printf("Table at 0x%llx\n", (unsigned long long)map_to_sysmem(table));
 
 	for (struct smbios_header *pos = table; pos; pos = next_table(pos)) {
diff --git a/drivers/cpu/riscv_cpu.c b/drivers/cpu/riscv_cpu.c
index a9b2537..5d1026b 100644
--- a/drivers/cpu/riscv_cpu.c
+++ b/drivers/cpu/riscv_cpu.c
@@ -11,6 +11,7 @@
 #include <errno.h>
 #include <log.h>
 #include <asm/global_data.h>
+#include <asm/sbi.h>
 #include <dm/device-internal.h>
 #include <dm/lists.h>
 #include <linux/bitops.h>
@@ -94,13 +95,24 @@
 	struct cpu_plat *plat = dev_get_parent_plat(dev);
 	struct driver *drv;
 	int ret;
+	long mvendorid;
 
 	/* save the hart id */
 	plat->cpu_id = dev_read_addr(dev);
+	/* provide data for SMBIOS */
 	if (IS_ENABLED(CONFIG_64BIT))
 		plat->family = 0x201;
 	else
 		plat->family = 0x200;
+	if (CONFIG_IS_ENABLED(RISCV_SMODE)) {
+		/*
+		 * For RISC-V CPUs the SMBIOS Processor ID field contains
+		 * the Machine Vendor ID from CSR mvendorid.
+		 */
+		ret = sbi_get_mvendorid(&mvendorid);
+		if (!ret)
+			plat->id[0] = mvendorid;
+	}
 	/* first examine the property in current cpu node */
 	ret = dev_read_u32(dev, "timebase-frequency", &plat->timebase_freq);
 	/* if not found, then look at the parent /cpus node */
diff --git a/drivers/misc/qfw_smbios.c b/drivers/misc/qfw_smbios.c
index a898cb4..c3e8c31 100644
--- a/drivers/misc/qfw_smbios.c
+++ b/drivers/misc/qfw_smbios.c
@@ -90,7 +90,7 @@
 		entry->length = sizeof(struct smbios3_entry);
 		entry->major_ver = entry2->major_ver;
 		entry->minor_ver = entry2->minor_ver;
-		entry->max_struct_size = entry2->struct_table_length;
+		entry->table_maximum_size = entry2->struct_table_length;
 	} else {
 		ret = -ENOENT;
 		goto out;
diff --git a/include/smbios.h b/include/smbios.h
index e2b7f69..3df8827 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -75,7 +75,7 @@
 	/** @reserved: reserved */
 	u8 reserved;
 	/** maximum size of SMBIOS table */
-	u32 max_struct_size;
+	u32 table_maximum_size;
 	/** @struct_table_address: 64-bit physical starting address */
 	u64 struct_table_address;
 };
diff --git a/lib/efi_loader/efi_tcg2.c b/lib/efi_loader/efi_tcg2.c
index b5d4aa7..b07e009 100644
--- a/lib/efi_loader/efi_tcg2.c
+++ b/lib/efi_loader/efi_tcg2.c
@@ -1098,7 +1098,7 @@
 	 */
 	event_size = sizeof(struct smbios_handoff_table_pointers2) +
 		     FIELD_SIZEOF(struct efi_configuration_table, guid) +
-		     entry->max_struct_size;
+		     entry->table_maximum_size;
 	event = calloc(1, event_size);
 	if (!event) {
 		ret = EFI_OUT_OF_RESOURCES;
@@ -1113,7 +1113,7 @@
 	smbios_copy = (struct smbios_header *)((uintptr_t)&event->table_entry[0].table);
 	memcpy(&event->table_entry[0].table,
 	       (void *)((uintptr_t)entry->struct_table_address),
-	       entry->max_struct_size);
+	       entry->table_maximum_size);
 
 	smbios_prepare_measurement(entry, smbios_copy);
 
diff --git a/lib/efi_loader/smbiosdump.c b/lib/efi_loader/smbiosdump.c
index f0b9018..2f0b91a 100644
--- a/lib/efi_loader/smbiosdump.c
+++ b/lib/efi_loader/smbiosdump.c
@@ -329,7 +329,7 @@
 			return EFI_LOAD_ERROR;
 		}
 		table = (void *)(uintptr_t)smbios3_anchor->struct_table_address;
-		len = smbios3_anchor->max_struct_size;
+		len = smbios3_anchor->table_maximum_size;
 	} else {
 		struct smbios_entry *smbios_anchor;
 		int r;
@@ -469,7 +469,7 @@
 
 	smbios3_anchor = get_config_table(&smbios3_guid);
 	if (smbios3_anchor) {
-		size = 0x20 + smbios3_anchor->max_struct_size;
+		size = 0x20 + smbios3_anchor->table_maximum_size;
 		ret = bs->allocate_pool(EFI_LOADER_DATA, size, (void **)&buf);
 		if (ret != EFI_SUCCESS) {
 			error(u"Out of memory\n");
@@ -480,7 +480,7 @@
 		memcpy(buf, smbios3_anchor, smbios3_anchor->length);
 		memcpy(buf + 0x20,
 		       (void *)(uintptr_t)smbios3_anchor->struct_table_address,
-		       smbios3_anchor->max_struct_size);
+		       smbios3_anchor->table_maximum_size);
 
 		smbios3_anchor = (struct smbios3_entry *)buf;
 		smbios3_anchor->struct_table_address = 0x20;
diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
index f48d743..9a62b3c 100644
--- a/lib/smbios-parser.c
+++ b/lib/smbios-parser.c
@@ -15,7 +15,7 @@
 {
 	const struct smbios_entry *entry = (struct smbios_entry *)(uintptr_t)address;
 
-	if (!address | !size)
+	if (!address || !size)
 		return NULL;
 
 	if (memcmp(entry->anchor, "_SM_", 4))
@@ -230,7 +230,7 @@
 	void *table_end;
 	struct smbios_header *header;
 
-	table_end = (void *)((u8 *)smbios_copy + entry->max_struct_size);
+	table_end = (void *)((u8 *)smbios_copy + entry->table_maximum_size);
 
 	for (i = 0; i < ARRAY_SIZE(smbios_filter_tables); i++) {
 		header = smbios_copy;
diff --git a/lib/smbios.c b/lib/smbios.c
index 7bd9805..c83af73 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -135,13 +135,16 @@
  *
  * @ctx:	SMBIOS context
  * @str:	string to add
- * Return:	string number in the string area (1 or more)
+ * Return:	string number in the string area. 0 if str is NULL.
  */
 static int smbios_add_string(struct smbios_ctx *ctx, const char *str)
 {
 	int i = 1;
 	char *p = ctx->eos;
 
+	if (!str)
+		return 0;
+
 	for (;;) {
 		if (!*p) {
 			ctx->last_str = p;
@@ -207,6 +210,7 @@
  *
  * @ctx:	context for writing the tables
  * @prop:	property to write
+ * @sysinfo_id: unique identifier for the string value to be read
  * @dval:	Default value to use if the string is not found or is empty
  * Return:	0 if not found, else SMBIOS string number (1 or more)
  */
@@ -216,7 +220,7 @@
 	int ret;
 
 	if (!dval || !*dval)
-		dval = "Unknown";
+		dval = NULL;
 
 	if (!prop)
 		return smbios_add_string(ctx, dval);
@@ -311,6 +315,10 @@
  */
 static int smbios_string_table_len(const struct smbios_ctx *ctx)
 {
+	/* In case no string is defined we have to return two \0 */
+	if (ctx->next_ptr == ctx->eos)
+		return 2;
+
 	/* Allow for the final \0 after all strings */
 	return (ctx->next_ptr + 1) - ctx->eos;
 }
@@ -375,19 +383,19 @@
 	memset(t, 0, sizeof(struct smbios_type1));
 	fill_smbios_header(t, SMBIOS_SYSTEM_INFORMATION, len, handle);
 	smbios_set_eos(ctx, t->eos);
-	t->manufacturer = smbios_add_prop(ctx, "manufacturer", "Unknown");
-	t->product_name = smbios_add_prop(ctx, "product", "Unknown");
+	t->manufacturer = smbios_add_prop(ctx, "manufacturer", NULL);
+	t->product_name = smbios_add_prop(ctx, "product", NULL);
 	t->version = smbios_add_prop_si(ctx, "version",
 					SYSINFO_ID_SMBIOS_SYSTEM_VERSION,
-					"Unknown");
+					NULL);
 	if (serial_str) {
 		t->serial_number = smbios_add_prop(ctx, NULL, serial_str);
 		strncpy((char *)t->uuid, serial_str, sizeof(t->uuid));
 	} else {
-		t->serial_number = smbios_add_prop(ctx, "serial", "Unknown");
+		t->serial_number = smbios_add_prop(ctx, "serial", NULL);
 	}
-	t->sku_number = smbios_add_prop(ctx, "sku", "Unknown");
-	t->family = smbios_add_prop(ctx, "family", "Unknown");
+	t->sku_number = smbios_add_prop(ctx, "sku", NULL);
+	t->family = smbios_add_prop(ctx, "family", NULL);
 
 	len = t->length + smbios_string_table_len(ctx);
 	*current += len;
@@ -406,14 +414,15 @@
 	memset(t, 0, sizeof(struct smbios_type2));
 	fill_smbios_header(t, SMBIOS_BOARD_INFORMATION, len, handle);
 	smbios_set_eos(ctx, t->eos);
-	t->manufacturer = smbios_add_prop(ctx, "manufacturer", "Unknown");
-	t->product_name = smbios_add_prop(ctx, "product", "Unknown");
+	t->manufacturer = smbios_add_prop(ctx, "manufacturer", NULL);
+	t->product_name = smbios_add_prop(ctx, "product", NULL);
 	t->version = smbios_add_prop_si(ctx, "version",
 					SYSINFO_ID_SMBIOS_BASEBOARD_VERSION,
-					"Unknown");
-	t->asset_tag_number = smbios_add_prop(ctx, "asset-tag", "Unknown");
+					NULL);
+	t->asset_tag_number = smbios_add_prop(ctx, "asset-tag", NULL);
 	t->feature_flags = SMBIOS_BOARD_FEATURE_HOSTING;
 	t->board_type = SMBIOS_BOARD_MOTHERBOARD;
+	t->chassis_handle = handle + 1;
 
 	len = t->length + smbios_string_table_len(ctx);
 	*current += len;
@@ -432,7 +441,7 @@
 	memset(t, 0, sizeof(struct smbios_type3));
 	fill_smbios_header(t, SMBIOS_SYSTEM_ENCLOSURE, len, handle);
 	smbios_set_eos(ctx, t->eos);
-	t->manufacturer = smbios_add_prop(ctx, "manufacturer", "Unknown");
+	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;
@@ -450,8 +459,8 @@
 				  struct smbios_ctx *ctx)
 {
 	u16 processor_family = SMBIOS_PROCESSOR_FAMILY_UNKNOWN;
-	const char *vendor = "Unknown";
-	const char *name = "Unknown";
+	const char *vendor = NULL;
+	const char *name = NULL;
 
 #ifdef CONFIG_CPU
 	char processor_name[49];
@@ -542,6 +551,7 @@
 	{ smbios_write_type0, "bios", },
 	{ smbios_write_type1, "system", },
 	{ smbios_write_type2, "baseboard", },
+	/* Type 3 must immediately follow type 2 due to chassis handle. */
 	{ smbios_write_type3, "chassis", },
 	{ smbios_write_type4, },
 	{ smbios_write_type32, },
@@ -556,7 +566,6 @@
 	struct smbios_ctx ctx;
 	ulong tables;
 	int len = 0;
-	int max_struct_size = 0;
 	int handle = 0;
 	int i;
 
@@ -578,7 +587,6 @@
 	/* populate minimum required tables */
 	for (i = 0; i < ARRAY_SIZE(smbios_write_funcs); i++) {
 		const struct smbios_write_method *method;
-		int tmp;
 
 		method = &smbios_write_funcs[i];
 		ctx.subnode_name = NULL;
@@ -588,10 +596,7 @@
 				ctx.node = ofnode_find_subnode(parent_node,
 							       method->subnode_name);
 		}
-		tmp = method->write((ulong *)&addr, handle++, &ctx);
-
-		max_struct_size = max(max_struct_size, tmp);
-		len += tmp;
+		len += method->write((ulong *)&addr, handle++, &ctx);
 	}
 
 	/*
@@ -610,7 +615,7 @@
 	se->minor_ver = SMBIOS_MINOR_VER;
 	se->doc_rev = 0;
 	se->entry_point_rev = 1;
-	se->max_struct_size = len;
+	se->table_maximum_size = len;
 	se->struct_table_address = table_addr;
 	se->checksum = table_compute_checksum(se, sizeof(struct smbios3_entry));
 	unmap_sysmem(se);