[PATCH 11/34] smbios: Allow writing to the coreboot version string

Simon Glass sjg at chromium.org
Mon Mar 15 06:00:11 CET 2021


When U-Boot is booted from coreboot the SMBIOS tables are written by
coreboot, not U-Boot. The existing method of updating the BIOS version
string does not work in that case, since gd->smbios_version is only set
when U-Boot writes the tables.

Add a new function which allows the version to be updated by parsing the
tables and writing the string in the correct place. Since coreboot
provides a pointer to the SMBIOS tables in its sysinfo structure, this
makes it easy to do the update.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

 include/smbios.h    | 20 ++++++++++++++++++++
 lib/smbios-parser.c | 38 ++++++++++++++++++++++++++++++++++++++
 lib/smbios.c        |  4 ----
 3 files changed, 58 insertions(+), 4 deletions(-)

diff --git a/include/smbios.h b/include/smbios.h
index ecc4fd1de3b..ffeefb47372 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -14,6 +14,10 @@
 #define SMBIOS_MAJOR_VER	3
 #define SMBIOS_MINOR_VER	0
 
+enum {
+	SMBIOS_STR_MAX	= 64,	/* Maximum length allowed for a string */
+};
+
 /* SMBIOS structure types */
 enum {
 	SMBIOS_BIOS_INFORMATION = 0,
@@ -269,4 +273,20 @@ const char *smbios_string(const struct smbios_header *header, int index);
  */
 int smbios_update_version(const char *version);
 
+/**
+ * smbios_update_version_full() - Update the version string
+ *
+ * This can be called after the SMBIOS tables are written (e.g. after the U-Boot
+ * main loop has started) to update the BIOS version string (SMBIOS table 0).
+ * It scans for the correct place to put the version, so does not need U-Boot
+ * to have actually written the tables itself (e.g. if a previous bootloader
+ * did it).
+ *
+ * @smbios_tab: Start of SMBIOS tables
+ * @version: New version string to use
+ * @return 0 if OK, -ENOENT if no version string was previously written,
+ *	-ENOSPC if the new string is too large to fit
+ */
+int smbios_update_version_full(void *smbios_tab, const char *version);
+
 #endif /* _SMBIOS_H_ */
diff --git a/lib/smbios-parser.c b/lib/smbios-parser.c
index b89f988ef9f..34203f952c9 100644
--- a/lib/smbios-parser.c
+++ b/lib/smbios-parser.c
@@ -3,6 +3,8 @@
  * Copyright (C) 2020, Bachmann electronic GmbH
  */
 
+#define LOG_CATEGORY	LOGC_BOOT
+
 #include <common.h>
 #include <smbios.h>
 
@@ -94,3 +96,39 @@ const char *smbios_string(const struct smbios_header *header, int index)
 
 	return string_from_smbios_table(header, index);
 }
+
+int smbios_update_version_full(void *smbios_tab, const char *version)
+{
+	const struct smbios_header *hdr;
+	struct smbios_type0 *bios;
+	uint old_len, len;
+	char *ptr;
+
+	log_info("Updating SMBIOS table at %p\n", smbios_tab);
+	hdr = smbios_header(smbios_tab, SMBIOS_BIOS_INFORMATION);
+	if (!hdr)
+		return log_msg_ret("tab", -ENOENT);
+	bios = (struct smbios_type0 *)hdr;
+	ptr = (char *)smbios_string(hdr, bios->bios_ver);
+	if (!ptr)
+		return log_msg_ret("str", -ENOMEDIUM);
+
+	/*
+	 * This string is supposed to have at least enough bytes and is
+	 * padded with spaces. Update it, taking care not to move the
+	 * \0 terminator, so that other strings in the string table
+	 * are not disturbed. See smbios_add_string()
+	 */
+	old_len = strnlen(ptr, SMBIOS_STR_MAX);
+	len = strnlen(version, SMBIOS_STR_MAX);
+	if (len > old_len)
+		return log_ret(-ENOSPC);
+
+	log_debug("Replacing SMBIOS type 0 version string '%s'\n", ptr);
+	memcpy(ptr, version, len);
+#ifdef LOG_DEBUG
+	print_buffer((ulong)ptr, ptr, 1, old_len + 1, 0);
+#endif
+
+	return 0;
+}
diff --git a/lib/smbios.c b/lib/smbios.c
index 7d463c84a93..9eb226ec9fb 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -20,10 +20,6 @@
 
 DECLARE_GLOBAL_DATA_PTR;
 
-enum {
-	SMBIOS_STR_MAX	= 64,	/* Maximum length allowed for a string */
-};
-
 /**
  * struct smbios_ctx - context for writing SMBIOS tables
  *
-- 
2.31.0.rc2.261.g7f71774620-goog



More information about the U-Boot mailing list