summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--include/asm-generic/global_data.h6
-rw-r--r--include/smbios.h12
-rw-r--r--lib/smbios.c58
3 files changed, 73 insertions, 3 deletions
diff --git a/include/asm-generic/global_data.h b/include/asm-generic/global_data.h
index 998beb0176..b6a9991fc9 100644
--- a/include/asm-generic/global_data.h
+++ b/include/asm-generic/global_data.h
@@ -447,6 +447,12 @@ struct global_data {
*/
struct acpi_ctx *acpi_ctx;
#endif
+#if CONFIG_IS_ENABLED(GENERATE_SMBIOS_TABLE)
+ /**
+ * @smbios_version: Points to SMBIOS type 0 version
+ */
+ char *smbios_version;
+#endif
};
/**
diff --git a/include/smbios.h b/include/smbios.h
index 1cbeabf952..ecc4fd1de3 100644
--- a/include/smbios.h
+++ b/include/smbios.h
@@ -257,4 +257,16 @@ const struct smbios_header *smbios_header(const struct smbios_entry *entry, int
*/
const char *smbios_string(const struct smbios_header *header, int index);
+/**
+ * smbios_update_version() - 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).
+ *
+ * @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(const char *version);
+
#endif /* _SMBIOS_H_ */
diff --git a/lib/smbios.c b/lib/smbios.c
index a7273529cc..e8bfc9ee1c 100644
--- a/lib/smbios.c
+++ b/lib/smbios.c
@@ -17,6 +17,12 @@
#include <dm/uclass-internal.h>
#endif
+DECLARE_GLOBAL_DATA_PTR;
+
+enum {
+ SMBIOS_STR_MAX = 64, /* Maximum length allowed for a string */
+};
+
/**
* struct smbios_ctx - context for writing SMBIOS tables
*
@@ -27,12 +33,15 @@
* @next_ptr: pointer to the start of the next string to be added. When the
* table is nopt empty, this points to the byte after the \0 of the
* previous string.
+ * @last_str: points to the last string that was written to the table, or NULL
+ * if none
*/
struct smbios_ctx {
ofnode node;
struct udevice *dev;
char *eos;
char *next_ptr;
+ char *last_str;
};
/**
@@ -78,6 +87,7 @@ static int smbios_add_string(struct smbios_ctx *ctx, const char *str)
for (;;) {
if (!*p) {
+ ctx->last_str = p;
strcpy(p, str);
p += strlen(str);
*p++ = '\0';
@@ -87,8 +97,10 @@ static int smbios_add_string(struct smbios_ctx *ctx, const char *str)
return i;
}
- if (!strcmp(p, str))
+ if (!strcmp(p, str)) {
+ ctx->last_str = p;
return i;
+ }
p += strlen(p) + 1;
i++;
@@ -119,6 +131,35 @@ static void smbios_set_eos(struct smbios_ctx *ctx, char *eos)
{
ctx->eos = eos;
ctx->next_ptr = eos;
+ ctx->last_str = NULL;
+}
+
+int smbios_update_version(const char *version)
+{
+ char *ptr = gd->smbios_version;
+ uint old_len, len;
+
+ if (!ptr)
+ return log_ret(-ENOENT);
+
+ /*
+ * 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;
}
/**
@@ -146,7 +187,18 @@ static int smbios_write_type0(ulong *current, int handle,
fill_smbios_header(t, SMBIOS_BIOS_INFORMATION, len, handle);
smbios_set_eos(ctx, t->eos);
t->vendor = smbios_add_string(ctx, "U-Boot");
- t->bios_ver = smbios_add_string(ctx, PLAIN_VERSION);
+
+ t->bios_ver = smbios_add_prop(ctx, "version");
+ if (!t->bios_ver)
+ t->bios_ver = smbios_add_string(ctx, PLAIN_VERSION);
+ if (t->bios_ver)
+ gd->smbios_version = ctx->last_str;
+ log_debug("smbios_version = %p: '%s'\n", gd->smbios_version,
+ gd->smbios_version);
+#ifdef LOG_DEBUG
+ print_buffer((ulong)gd->smbios_version, gd->smbios_version,
+ 1, strlen(gd->smbios_version) + 1, 0);
+#endif
t->bios_release_date = smbios_add_string(ctx, U_BOOT_DMI_DATE);
#ifdef CONFIG_ROM_SIZE
t->bios_rom_size = (CONFIG_ROM_SIZE / 65536) - 1;
@@ -345,7 +397,7 @@ static int smbios_write_type127(ulong *current, int handle,
}
static struct smbios_write_method smbios_write_funcs[] = {
- { smbios_write_type0, },
+ { smbios_write_type0, "bios", },
{ smbios_write_type1, "system", },
{ smbios_write_type2, "baseboard", },
{ smbios_write_type3, "chassis", },