plugins/coreboot: Improve version detection

Only on Lenovo devices the DMI version string is prefixed with
CBETxxxx to make the thinkpad_acpi kernel module happy.

Add a new quirk called "CorebootVersionQuirks" to detect platforms
that need to cut of the prefix.

Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
This commit is contained in:
Patrick Rudolph 2019-11-13 07:07:34 -05:00 committed by Richard Hughes
parent bd94740404
commit b21c3af2ea
6 changed files with 76 additions and 7 deletions

View File

@ -20,13 +20,24 @@ coreboot can be detected the following ways:
coreboot version string
-----------------------
The coreboot version string always starts with `CBET`.
After the prefix the *version*, *major*, *minor* string follows and finally
The coreboot version string can have an optional prefix (see below).
After the optional prefix the *major*, *minor* string follows and finally
the *build string*, containing the exact commit and repository state, follows.
For example:
> 4.10-989-gc8a4e4b9c5-dirty
**Exception on Lenovo devices:**
The thinkpad_acpi kernel module requires a specific pattern in the DMI version
string. To satisfy those requirements coreboot adds the CBETxxxx prefix to the
DMI version string on all Lenovo devices.
For example:
> CBET4000 4.10-989-gc8a4e4b9c5-dirty
The coreboot DMI version string always starts with `CBET`.
GUID Generation
---------------

View File

@ -0,0 +1,2 @@
[SmbiosManufacturer=LENOVO]
CorebootVersionQuirks = lenovo-cbet-prefix

View File

@ -11,20 +11,37 @@
#include "fu-plugin-coreboot.h"
/**
* FU_QUIRKS_COREBOOT_VERSION:
* @key: The SMBIOS manufacturer name
* @value: One of the following: "lenovo-cbet-prefix"
*
* "lenovo-cbet-prefix" quirk:
* The thinkpad_acpi kernel module requires a specific pattern
* in the DMI version string. To satisfy those requirements
* coreboot adds the CBETxxxx prefix to the DMI version string
* on all Lenovo devices. The prefix isn't present in the
* version string found in coreboot tables, or on other
* coreboot enabled devices.
*
* Since: 1.3.5
*/
#define FU_QUIRKS_COREBOOT_VERSION "CorebootVersionQuirks"
#define FU_QUIRK_CBET_PREFIX "lenovo-cbet-prefix"
/* Tries to convert the coreboot version string to a triplet string.
* Returns NULL on error. */
gchar *
fu_plugin_coreboot_version_string_to_triplet (const gchar *coreboot_version,
GError **error)
{
guint cb_version = 0;
guint cb_major = 0;
guint cb_minor = 0;
guint cb_build = 0;
gint rc;
rc = sscanf (coreboot_version, "CBET%u %u.%u-%u", &cb_version, &cb_major,
&cb_minor, &cb_build);
rc = sscanf (coreboot_version, "%u.%u-%u", &cb_major, &cb_minor, &cb_build);
if (rc < 0) {
g_set_error (error,
G_IO_ERROR,
@ -34,7 +51,7 @@ fu_plugin_coreboot_version_string_to_triplet (const gchar *coreboot_version,
}
/* Sanity check */
if (cb_major == 0 || cb_version == 0) {
if (cb_major == 0) {
g_set_error (error,
G_IO_ERROR,
G_IO_ERROR_INVALID_DATA,
@ -62,3 +79,37 @@ fu_plugin_coreboot_get_name_for_type (FuPlugin *plugin,
g_string_prepend (display_name, "coreboot System Firmware");
return g_string_free (display_name, FALSE);
}
/* Returns the version string with possible quirks applied */
gchar *
fu_plugin_coreboot_get_version_string (FuPlugin *plugin)
{
const gchar *version;
const gchar *manufacturer;
const gchar *quirk = NULL;
version = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_BIOS_VERSION);
if (version == NULL)
return NULL;
manufacturer = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_MANUFACTURER);
if (manufacturer != NULL) {
g_autofree gchar *group = NULL;
/* any quirks match */
group = g_strdup_printf ("SmbiosManufacturer=%s", manufacturer);
quirk = fu_plugin_lookup_quirk_by_id (plugin, group,
FU_QUIRKS_COREBOOT_VERSION);
}
if (quirk == NULL)
return version;
if (g_strcmp0(quirk, FU_QUIRK_CBET_PREFIX) == 0) {
if (strlen (version) > 9 && g_str_has_prefix (version, "CBET"))
version += 9;
return version;
}
return version;
}

View File

@ -44,7 +44,7 @@ fu_plugin_coldplug (FuPlugin *plugin, GError **error)
"HardwareID-10",
};
version = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_BIOS_VERSION);
version = fu_plugin_coreboot_get_version_string (plugin);
if (version != NULL)
triplet = fu_plugin_coreboot_version_string_to_triplet (version, error);

View File

@ -13,3 +13,4 @@ gchar *fu_plugin_coreboot_version_string_to_triplet (const gchar *coreboot_vers
GError **error);
gchar *fu_plugin_coreboot_get_name_for_type (FuPlugin *plugin,
const gchar *vboot_partition);
gchar *fu_plugin_coreboot_get_version_string (FuPlugin *plugin);

View File

@ -1,5 +1,9 @@
cargs = ['-DG_LOG_DOMAIN="FuPluginCoreboot"']
install_data(['coreboot.quirk'],
install_dir: join_paths(datadir, 'fwupd', 'quirks.d')
)
shared_module('fu_plugin_coreboot',
sources : [
'fu-plugin-coreboot.c',