diff options
-rw-r--r-- | include/asm-generic/global_data.h | 6 | ||||
-rw-r--r-- | include/smbios.h | 12 | ||||
-rw-r--r-- | lib/smbios.c | 58 |
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", }, |