firmware/dmi: Report DMI Bios & EC firmware release
authorErwan Velu <e.velu@criteo.com>
Sat, 6 Jun 2020 09:35:50 +0000 (11:35 +0200)
committerJean Delvare <jdelvare@suse.de>
Sat, 6 Jun 2020 09:35:50 +0000 (11:35 +0200)
Some vendors like HPe or Dell, encode the release version of their BIOS
in the "System BIOS {Major|Minor} Release" fields of Type 0.

This information is used to know which bios release actually runs.
It could be used for some quirks, debugging sessions or inventory tasks.

A typical output for a Dell system running the 65.27 bios is :
[root@t1700 ~]# cat /sys/devices/virtual/dmi/id/bios_release
65.27
[root@t1700 ~]#

Servers that have a BMC encode the release version of their firmware in the
 "Embedded Controller Firmware {Major|Minor} Release" fields of Type 0.

This information is used to know which BMC release actually runs.
It could be used for some quirks, debugging sessions or inventory tasks.

A typical output for a Dell system running the 3.75 bmc release is :
    [root@t1700 ~]# cat /sys/devices/virtual/dmi/id/ec_firmware_release
    3.75
    [root@t1700 ~]#

Signed-off-by: Erwan Velu <e.velu@criteo.com>
Signed-off-by: Jean Delvare <jdelvare@suse.de>
drivers/firmware/dmi-id.c
drivers/firmware/dmi_scan.c
include/linux/mod_devicetable.h
scripts/mod/file2alias.c

index ff39f64f2aae327dfe4c2c97d16bc9664f5ef51d..86d71b0212b1bd74a3548f60cbd7c7a8dc464ca3 100644 (file)
@@ -42,6 +42,8 @@ DEFINE_DMI_ATTR_WITH_SHOW(bios_vendor,                0444, DMI_BIOS_VENDOR);
 DEFINE_DMI_ATTR_WITH_SHOW(bios_version,                0444, DMI_BIOS_VERSION);
 DEFINE_DMI_ATTR_WITH_SHOW(bios_date,           0444, DMI_BIOS_DATE);
 DEFINE_DMI_ATTR_WITH_SHOW(sys_vendor,          0444, DMI_SYS_VENDOR);
+DEFINE_DMI_ATTR_WITH_SHOW(bios_release,                0444, DMI_BIOS_RELEASE);
+DEFINE_DMI_ATTR_WITH_SHOW(ec_firmware_release, 0444, DMI_EC_FIRMWARE_RELEASE);
 DEFINE_DMI_ATTR_WITH_SHOW(product_name,                0444, DMI_PRODUCT_NAME);
 DEFINE_DMI_ATTR_WITH_SHOW(product_version,     0444, DMI_PRODUCT_VERSION);
 DEFINE_DMI_ATTR_WITH_SHOW(product_serial,      0400, DMI_PRODUCT_SERIAL);
@@ -78,6 +80,8 @@ static ssize_t get_modalias(char *buffer, size_t buffer_size)
                { "bvn", DMI_BIOS_VENDOR },
                { "bvr", DMI_BIOS_VERSION },
                { "bd",  DMI_BIOS_DATE },
+               { "br",  DMI_BIOS_RELEASE },
+               { "efr", DMI_EC_FIRMWARE_RELEASE },
                { "svn", DMI_SYS_VENDOR },
                { "pn",  DMI_PRODUCT_NAME },
                { "pvr", DMI_PRODUCT_VERSION },
@@ -187,6 +191,8 @@ static void __init dmi_id_init_attr_table(void)
        ADD_DMI_ATTR(bios_vendor,       DMI_BIOS_VENDOR);
        ADD_DMI_ATTR(bios_version,      DMI_BIOS_VERSION);
        ADD_DMI_ATTR(bios_date,         DMI_BIOS_DATE);
+       ADD_DMI_ATTR(bios_release,      DMI_BIOS_RELEASE);
+       ADD_DMI_ATTR(ec_firmware_release, DMI_EC_FIRMWARE_RELEASE);
        ADD_DMI_ATTR(sys_vendor,        DMI_SYS_VENDOR);
        ADD_DMI_ATTR(product_name,      DMI_PRODUCT_NAME);
        ADD_DMI_ATTR(product_version,   DMI_PRODUCT_VERSION);
index f59163cb7cba85e1c35181c63c2af5b5cb691c8e..5066d1f1d6872078d28ddd1ad29d2bbbed32d604 100644 (file)
@@ -186,6 +186,34 @@ static void __init dmi_save_ident(const struct dmi_header *dm, int slot,
        dmi_ident[slot] = p;
 }
 
+static void __init dmi_save_release(const struct dmi_header *dm, int slot,
+               int index)
+{
+       const u8 *minor, *major;
+       char *s;
+
+       /* If the table doesn't have the field, let's return */
+       if (dmi_ident[slot] || dm->length < index)
+               return;
+
+       minor = (u8 *) dm + index;
+       major = (u8 *) dm + index - 1;
+
+       /* As per the spec, if the system doesn't support this field,
+        * the value is FF
+        */
+       if (*major == 0xFF && *minor == 0xFF)
+               return;
+
+       s = dmi_alloc(8);
+       if (!s)
+               return;
+
+       sprintf(s, "%u.%u", *major, *minor);
+
+       dmi_ident[slot] = s;
+}
+
 static void __init dmi_save_uuid(const struct dmi_header *dm, int slot,
                int index)
 {
@@ -444,6 +472,8 @@ static void __init dmi_decode(const struct dmi_header *dm, void *dummy)
                dmi_save_ident(dm, DMI_BIOS_VENDOR, 4);
                dmi_save_ident(dm, DMI_BIOS_VERSION, 5);
                dmi_save_ident(dm, DMI_BIOS_DATE, 8);
+               dmi_save_release(dm, DMI_BIOS_RELEASE, 21);
+               dmi_save_release(dm, DMI_EC_FIRMWARE_RELEASE, 23);
                break;
        case 1:         /* System Information */
                dmi_save_ident(dm, DMI_SYS_VENDOR, 4);
index 4c2ddd0941a7514e3b30adbb3211db90c9c39aab..4b3d0a4945dfc652d878381ced5aed7b974bc0e4 100644 (file)
@@ -532,6 +532,8 @@ enum dmi_field {
        DMI_BIOS_VENDOR,
        DMI_BIOS_VERSION,
        DMI_BIOS_DATE,
+       DMI_BIOS_RELEASE,
+       DMI_EC_FIRMWARE_RELEASE,
        DMI_SYS_VENDOR,
        DMI_PRODUCT_NAME,
        DMI_PRODUCT_VERSION,
index 02d5d79da2844d263452bb37cf179fa0f909d4af..9599e2a3f1e614a586349e25a3f96bd090624a7b 100644 (file)
@@ -954,6 +954,8 @@ static const struct dmifield {
        { "bvn", DMI_BIOS_VENDOR },
        { "bvr", DMI_BIOS_VERSION },
        { "bd",  DMI_BIOS_DATE },
+       { "br",  DMI_BIOS_RELEASE },
+       { "efr", DMI_EC_FIRMWARE_RELEASE },
        { "svn", DMI_SYS_VENDOR },
        { "pn",  DMI_PRODUCT_NAME },
        { "pvr", DMI_PRODUCT_VERSION },