From b21c3af2eaded9de7e97f6226ea88451194e4e4a Mon Sep 17 00:00:00 2001 From: Patrick Rudolph Date: Wed, 13 Nov 2019 07:07:34 -0500 Subject: [PATCH] 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 --- plugins/coreboot/README.md | 15 ++++++- plugins/coreboot/coreboot.quirk | 2 + plugins/coreboot/fu-coreboot-common.c | 59 +++++++++++++++++++++++++-- plugins/coreboot/fu-plugin-coreboot.c | 2 +- plugins/coreboot/fu-plugin-coreboot.h | 1 + plugins/coreboot/meson.build | 4 ++ 6 files changed, 76 insertions(+), 7 deletions(-) create mode 100644 plugins/coreboot/coreboot.quirk diff --git a/plugins/coreboot/README.md b/plugins/coreboot/README.md index cfaf1aded..e7b55613e 100644 --- a/plugins/coreboot/README.md +++ b/plugins/coreboot/README.md @@ -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 --------------- diff --git a/plugins/coreboot/coreboot.quirk b/plugins/coreboot/coreboot.quirk new file mode 100644 index 000000000..2884572b2 --- /dev/null +++ b/plugins/coreboot/coreboot.quirk @@ -0,0 +1,2 @@ +[SmbiosManufacturer=LENOVO] +CorebootVersionQuirks = lenovo-cbet-prefix diff --git a/plugins/coreboot/fu-coreboot-common.c b/plugins/coreboot/fu-coreboot-common.c index 19202a13b..3bb6f1b22 100644 --- a/plugins/coreboot/fu-coreboot-common.c +++ b/plugins/coreboot/fu-coreboot-common.c @@ -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; +} diff --git a/plugins/coreboot/fu-plugin-coreboot.c b/plugins/coreboot/fu-plugin-coreboot.c index 3ce5b4eae..72dd2896c 100644 --- a/plugins/coreboot/fu-plugin-coreboot.c +++ b/plugins/coreboot/fu-plugin-coreboot.c @@ -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); diff --git a/plugins/coreboot/fu-plugin-coreboot.h b/plugins/coreboot/fu-plugin-coreboot.h index e6260f6e4..436f2c844 100644 --- a/plugins/coreboot/fu-plugin-coreboot.h +++ b/plugins/coreboot/fu-plugin-coreboot.h @@ -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); diff --git a/plugins/coreboot/meson.build b/plugins/coreboot/meson.build index da0026971..2ec0270f9 100644 --- a/plugins/coreboot/meson.build +++ b/plugins/coreboot/meson.build @@ -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',