summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/Kconfig10
-rw-r--r--src/arch/x86/smbios.c81
2 files changed, 71 insertions, 20 deletions
diff --git a/src/Kconfig b/src/Kconfig
index ba9ae86067..c0315239fc 100644
--- a/src/Kconfig
+++ b/src/Kconfig
@@ -730,6 +730,16 @@ config SMBIOS_ENCLOSURE_TYPE
convertible, or tablet enclosure will be used if the appropriate
system type is selected.
+config VPD_SMBIOS_VERSION
+ bool "Populates SMBIOS type 0 version from the VPD_RO variable 'firmware_version'"
+ default n
+ depends on VPD && GENERATE_SMBIOS_TABLES
+ help
+ Selecting this option will read firmware_version from
+ VPD_RO and override SMBIOS type 0 version. One special
+ scenario of using this feature is to assign a BIOS version
+ to a coreboot image without the need to rebuild from source.
+
endmenu
source "payloads/Kconfig"
diff --git a/src/arch/x86/smbios.c b/src/arch/x86/smbios.c
index 7deac63dd6..f23e1dc3cd 100644
--- a/src/arch/x86/smbios.c
+++ b/src/arch/x86/smbios.c
@@ -32,6 +32,8 @@
#if CONFIG(CHROMEOS)
#include <vendorcode/google/chromeos/gnvs.h>
#endif
+#include <drivers/vpd/vpd.h>
+#include <stdlib.h>
#define update_max(len, max_len, stmt) \
do { \
@@ -381,12 +383,64 @@ static int create_smbios_type17_for_dimm(struct dimm_info *dimm,
return t->length + smbios_string_table_len(t->eos);
}
-const char *__weak smbios_mainboard_bios_version(void)
+#define VERSION_VPD "firmware_version"
+static const char *vpd_get_bios_version(void)
+{
+ int size;
+ const char *s;
+ char *version;
+
+ s = vpd_find(VERSION_VPD, &size, VPD_RO);
+ if (!s) {
+ printk(BIOS_ERR, "Find version from VPD %s failed\n", VERSION_VPD);
+ return NULL;
+ }
+
+ version = malloc(size + 1);
+ if (!version) {
+ printk(BIOS_ERR, "Failed to malloc %d bytes for VPD version\n", size + 1);
+ return NULL;
+ }
+ memcpy(version, s, size);
+ version[size] = '\0';
+ printk(BIOS_DEBUG, "Firmware version %s from VPD %s\n", version, VERSION_VPD);
+ return version;
+}
+
+static const char *get_bios_version(void)
{
- if (strlen(CONFIG_LOCALVERSION))
+ const char *s;
+
+#define SPACES \
+ " "
+
+ if (CONFIG(CHROMEOS))
+ return SPACES;
+
+ if (CONFIG(VPD_SMBIOS_VERSION)) {
+ s = vpd_get_bios_version();
+ if (s != NULL)
+ return s;
+ }
+
+ s = smbios_mainboard_bios_version();
+ if (s != NULL)
+ return s;
+
+ if (strlen(CONFIG_LOCALVERSION) != 0) {
+ printk(BIOS_DEBUG, "BIOS version set to CONFIG_LOCALVERSION: '%s'\n",
+ CONFIG_LOCALVERSION);
return CONFIG_LOCALVERSION;
- else
- return coreboot_version;
+ }
+
+ printk(BIOS_DEBUG, "SMBIOS firmware version is set to coreboot_version: '%s'\n",
+ coreboot_version);
+ return coreboot_version;
+}
+
+const char *__weak smbios_mainboard_bios_version(void)
+{
+ return NULL;
}
static int smbios_write_type0(unsigned long *current, int handle)
@@ -400,27 +454,14 @@ static int smbios_write_type0(unsigned long *current, int handle)
t->length = len - 2;
t->vendor = smbios_add_string(t->eos, "coreboot");
-#if !CONFIG(CHROMEOS)
t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);
- t->bios_version = smbios_add_string(t->eos,
- smbios_mainboard_bios_version());
-#else
-#define SPACES \
- " "
- t->bios_release_date = smbios_add_string(t->eos, coreboot_dmi_date);
-#if CONFIG(HAVE_ACPI_TABLES)
+#if CONFIG(CHROMEOS) && CONFIG(HAVE_ACPI_TABLES)
u32 version_offset = (u32)smbios_string_table_len(t->eos);
-#endif
- t->bios_version = smbios_add_string(t->eos, SPACES);
-
-#if CONFIG(HAVE_ACPI_TABLES)
/* SMBIOS offsets start at 1 rather than 0 */
- chromeos_get_chromeos_acpi()->vbt10 =
- (u32)t->eos + (version_offset - 1);
+ chromeos_get_chromeos_acpi()->vbt10 = (u32)t->eos + (version_offset - 1);
#endif
-#endif /* CONFIG_CHROMEOS */
-
+ t->bios_version = smbios_add_string(t->eos, get_bios_version());
uint32_t rom_size = CONFIG_ROM_SIZE;
rom_size = MIN(CONFIG_ROM_SIZE, 16 * MiB);
t->bios_rom_size = (rom_size / 65535) - 1;