From b097603800c03f6f99e2d559f60b4891d5fa0a88 Mon Sep 17 00:00:00 2001 From: Richard Hughes Date: Mon, 24 Feb 2020 14:17:04 +0000 Subject: [PATCH] Allow server metadata to set the version format on some devices It appears just choosing 'if Dell then QUAD else TRIPLET' isn't good enough. --- libfwupd/fwupd-enums.c | 4 ++ libfwupd/fwupd-enums.h | 2 + libfwupdplugin/fu-quirks.h | 2 - plugins/dell/dell.quirk | 6 -- plugins/dell/fu-plugin-dell.c | 23 +------ plugins/uefi/fu-plugin-uefi.c | 32 +-------- plugins/uefi/fu-uefi-device.c | 2 + src/README.md | 15 ----- src/fu-engine.c | 118 +++++++++++++++++----------------- src/fu-util-common.c | 4 ++ 10 files changed, 74 insertions(+), 134 deletions(-) diff --git a/libfwupd/fwupd-enums.c b/libfwupd/fwupd-enums.c index c2a065d13..cb7cdbaa2 100644 --- a/libfwupd/fwupd-enums.c +++ b/libfwupd/fwupd-enums.c @@ -187,6 +187,8 @@ fwupd_device_flag_to_string (FwupdDeviceFlags device_flag) return "md-set-name"; if (device_flag == FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY) return "md-set-name-category"; + if (device_flag == FWUPD_DEVICE_FLAG_MD_SET_VERFMT) + return "md-set-verfmt"; if (device_flag == FWUPD_DEVICE_FLAG_UNKNOWN) return "unknown"; return NULL; @@ -275,6 +277,8 @@ fwupd_device_flag_from_string (const gchar *device_flag) return FWUPD_DEVICE_FLAG_MD_SET_NAME; if (g_strcmp0 (device_flag, "md-set-name-category") == 0) return FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY; + if (g_strcmp0 (device_flag, "md-set-verfmt") == 0) + return FWUPD_DEVICE_FLAG_MD_SET_VERFMT; return FWUPD_DEVICE_FLAG_UNKNOWN; } diff --git a/libfwupd/fwupd-enums.h b/libfwupd/fwupd-enums.h index a0f34982f..bb5b93e8c 100644 --- a/libfwupd/fwupd-enums.h +++ b/libfwupd/fwupd-enums.h @@ -101,6 +101,7 @@ typedef enum { * @FWUPD_DEVICE_FLAG_INSTALL_ALL_RELEASES: Install each intermediate release rather than jumping direct to newest * @FWUPD_DEVICE_FLAG_MD_SET_NAME: Set the device name from the metadata if available * @FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY: Set the device name from the metadata if available + * @FWUPD_DEVICE_FLAG_MD_SET_VERFMT: Set the device version format from the metadata if available * * The device flags. **/ @@ -139,6 +140,7 @@ typedef enum { #define FWUPD_DEVICE_FLAG_INSTALL_ALL_RELEASES (1u << 31) /* Since: 1.3.7 */ #define FWUPD_DEVICE_FLAG_MD_SET_NAME (1llu << 32) /* Since: 1.3.9 */ #define FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY (1llu << 33) /* Since: 1.3.9 */ +#define FWUPD_DEVICE_FLAG_MD_SET_VERFMT (1llu << 34) /* Since: 1.3.9 */ #define FWUPD_DEVICE_FLAG_UNKNOWN G_MAXUINT64 /* Since: 0.7.3 */ typedef guint64 FwupdDeviceFlags; diff --git a/libfwupdplugin/fu-quirks.h b/libfwupdplugin/fu-quirks.h index 12e42d1db..ffd3187d5 100644 --- a/libfwupdplugin/fu-quirks.h +++ b/libfwupdplugin/fu-quirks.h @@ -44,8 +44,6 @@ gboolean fu_quirks_lookup_by_id_iter (FuQuirks *self, gpointer user_data); #define FU_QUIRKS_PLUGIN "Plugin" -#define FU_QUIRKS_UEFI_VERSION_FORMAT "UefiVersionFormat" -#define FU_QUIRKS_DAEMON_VERSION_FORMAT "ComponentIDs" #define FU_QUIRKS_FLAGS "Flags" #define FU_QUIRKS_SUMMARY "Summary" #define FU_QUIRKS_ICON "Icon" diff --git a/plugins/dell/dell.quirk b/plugins/dell/dell.quirk index 432421191..d856485c4 100644 --- a/plugins/dell/dell.quirk +++ b/plugins/dell/dell.quirk @@ -32,9 +32,3 @@ ParentGuid = e7ca1f36-bf73-4574-afe6-a4ccacabf479 [Guid=MST-tb18-vmm3330-274] Plugin = synaptics_mst ParentGuid = e7ca1f36-bf73-4574-afe6-a4ccacabf479 - -[SmbiosManufacturer=Dell Inc.] -UefiVersionFormat = dell-bios - -[SmbiosManufacturer=Alienware] -UefiVersionFormat = dell-bios diff --git a/plugins/dell/fu-plugin-dell.c b/plugins/dell/fu-plugin-dell.c index e15f63bcb..9c068e821 100644 --- a/plugins/dell/fu-plugin-dell.c +++ b/plugins/dell/fu-plugin-dell.c @@ -231,26 +231,6 @@ fu_plugin_dell_inject_fake_data (FuPlugin *plugin, data->can_switch_modes = TRUE; } -static FwupdVersionFormat -fu_plugin_dell_get_version_format (FuPlugin *plugin) -{ - const gchar *content; - const gchar *quirk; - g_autofree gchar *group = NULL; - - content = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_MANUFACTURER); - if (content == NULL) - return FWUPD_VERSION_FORMAT_TRIPLET; - - /* any quirks match */ - group = g_strdup_printf ("SmbiosManufacturer=%s", content); - quirk = fu_plugin_lookup_quirk_by_id (plugin, group, - FU_QUIRKS_UEFI_VERSION_FORMAT); - if (quirk == NULL) - return FWUPD_VERSION_FORMAT_TRIPLET; - return fwupd_version_format_from_string (quirk); -} - static gboolean fu_plugin_dell_capsule_supported (FuPlugin *plugin) { @@ -319,7 +299,7 @@ fu_plugin_usb_device_added (FuPlugin *plugin, GError **error) { FuPluginData *data = fu_plugin_get_data (plugin); - FwupdVersionFormat version_format; + FwupdVersionFormat version_format = FWUPD_VERSION_FORMAT_DELL_BIOS; guint16 pid; guint16 vid; const gchar *query_str; @@ -372,7 +352,6 @@ fu_plugin_usb_device_added (FuPlugin *plugin, g_debug ("Dock cable type: %" G_GUINT32_FORMAT, dock_info->cable_type); g_debug ("Dock location: %d", dock_info->location); g_debug ("Dock component count: %d", dock_info->component_count); - version_format = fu_plugin_dell_get_version_format (plugin); for (guint i = 0; i < dock_info->component_count; i++) { g_autofree gchar *fw_str = NULL; diff --git a/plugins/uefi/fu-plugin-uefi.c b/plugins/uefi/fu-plugin-uefi.c index 261d4eedd..2ef324338 100644 --- a/plugins/uefi/fu-plugin-uefi.c +++ b/plugins/uefi/fu-plugin-uefi.c @@ -463,30 +463,6 @@ fu_plugin_device_registered (FuPlugin *plugin, FuDevice *device) } } -static FwupdVersionFormat -fu_plugin_uefi_get_version_format_for_type (FuPlugin *plugin, FuUefiDeviceKind device_kind) -{ - const gchar *content; - const gchar *quirk; - g_autofree gchar *group = NULL; - - /* we have no information for devices */ - if (device_kind == FU_UEFI_DEVICE_KIND_DEVICE_FIRMWARE) - return FWUPD_VERSION_FORMAT_TRIPLET; - - content = fu_plugin_get_dmi_value (plugin, FU_HWIDS_KEY_MANUFACTURER); - if (content == NULL) - return FWUPD_VERSION_FORMAT_TRIPLET; - - /* any quirks match */ - group = g_strdup_printf ("SmbiosManufacturer=%s", content); - quirk = fu_plugin_lookup_quirk_by_id (plugin, group, - FU_QUIRKS_UEFI_VERSION_FORMAT); - if (quirk == NULL) - return FWUPD_VERSION_FORMAT_TRIPLET; - return fwupd_version_format_from_string (quirk); -} - static const gchar * fu_plugin_uefi_uefi_type_to_string (FuUefiDeviceKind device_kind) { @@ -519,12 +495,6 @@ static gboolean fu_plugin_uefi_coldplug_device (FuPlugin *plugin, FuUefiDevice *dev, GError **error) { FuUefiDeviceKind device_kind; - FwupdVersionFormat version_format; - - /* set default version format */ - device_kind = fu_uefi_device_get_kind (dev); - version_format = fu_plugin_uefi_get_version_format_for_type (plugin, device_kind); - fu_device_set_version_format (FU_DEVICE (dev), version_format); /* probe to get add GUIDs (and hence any quirk fixups) */ if (!fu_device_probe (FU_DEVICE (dev), error)) @@ -540,6 +510,7 @@ fu_plugin_uefi_coldplug_device (FuPlugin *plugin, FuUefiDevice *dev, GError **er } /* set fallback name if nothing else is set */ + device_kind = fu_uefi_device_get_kind (dev); if (fu_device_get_name (FU_DEVICE (dev)) == NULL) { g_autofree gchar *name = NULL; name = fu_plugin_uefi_get_name_for_type (plugin, device_kind); @@ -761,6 +732,7 @@ fu_plugin_uefi_create_dummy (FuPlugin *plugin, const gchar *reason, GError **err fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_INTERNAL); fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_NEEDS_REBOOT); fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_REQUIRE_AC); + fu_device_add_flag (dev, FWUPD_DEVICE_FLAG_MD_SET_VERFMT); fu_device_add_icon (dev, "computer"); fu_device_set_id (dev, "UEFI-dummy"); diff --git a/plugins/uefi/fu-uefi-device.c b/plugins/uefi/fu-uefi-device.c index b76a30cb9..5a699b12f 100644 --- a/plugins/uefi/fu-uefi-device.c +++ b/plugins/uefi/fu-uefi-device.c @@ -695,6 +695,7 @@ fu_uefi_device_probe (FuDevice *device, GError **error) fu_device_add_flag (device, FWUPD_DEVICE_FLAG_INTERNAL); fu_device_add_flag (device, FWUPD_DEVICE_FLAG_NEEDS_REBOOT); fu_device_add_flag (device, FWUPD_DEVICE_FLAG_REQUIRE_AC); + fu_device_add_flag (device, FWUPD_DEVICE_FLAG_MD_SET_VERFMT); /* add icons */ if (self->kind == FU_UEFI_DEVICE_KIND_DEVICE_FIRMWARE) { @@ -726,6 +727,7 @@ static void fu_uefi_device_init (FuUefiDevice *self) { fu_device_set_protocol (FU_DEVICE (self), "org.uefi.capsule"); + fu_device_set_version_format (FU_DEVICE (self), FWUPD_VERSION_FORMAT_NUMBER); } static void diff --git a/src/README.md b/src/README.md index 63423e78b..888e31754 100644 --- a/src/README.md +++ b/src/README.md @@ -13,21 +13,6 @@ Sets the plugin to use for a specific hardware device. * Key: the device ID, e.g. `DeviceInstanceId=USB\VID_0763&PID_2806` * Value: the plugin name, e.g. `csr` * Minimum fwupd version: **1.1.0** -### UefiVersionFormat -Assigns the version format to use for a specific manufacturer. A specific version -format is sometimes chosen to match the appearance of other systems or -specifications. -* Key: a %FU_HWIDS_KEY_MANUFACTURER, e.g. `Alienware` -* Value: the version format, e.g. `none` -* Supported values: `none`, `use-triplet` -* Minimum fwupd version: **1.0.1** -### ComponentIDs -Assigns the version format to use for a specific AppStream component. A specific -version format is sometimes chosen to match the appearance of other systems or -specifications. -* Key: the optionally wildcarded AppStream ID e.g. `com.dell.uefi*.firmware` -* Value: the version format, e.g. `none` -* Minimum fwupd version: **1.0.1** ### Flags Assigns optional quirks to use for a 8bitdo device * Key: the device ID, e.g. `DeviceInstanceId=USB\VID_0763&PID_2806` diff --git a/src/fu-engine.c b/src/fu-engine.c index 30d3f29d4..d673eddd0 100644 --- a/src/fu-engine.c +++ b/src/fu-engine.c @@ -263,61 +263,6 @@ fu_engine_device_changed_cb (FuDeviceList *device_list, FuDevice *device, FuEngi fu_engine_emit_device_changed (self, device); } -static gboolean -fu_engine_set_device_version_format (FuEngine *self, FuDevice *device, XbNode *component, GError **error) -{ - FwupdVersionFormat fmt; - const gchar *developer_name; - const gchar *version_format; - - /* specified in metadata */ - version_format = xb_node_query_text (component, - "custom/value[@key='LVFS::VersionFormat']", - NULL); - if (version_format != NULL) { - fmt = fwupd_version_format_from_string (version_format); - if (fmt == FWUPD_VERSION_FORMAT_UNKNOWN) { - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_NOT_SUPPORTED, - "version format from metadata %s unsupported", - version_format); - return FALSE; - } - g_debug ("using VersionFormat %s from metadata", version_format); - fu_device_set_version_format (device, fmt); - return TRUE; - } - - /* fall back to the SmbiosManufacturer quirk */ - developer_name = xb_node_query_text (component, "developer_name", NULL); - if (developer_name != NULL && - fu_device_has_flag (device, FWUPD_DEVICE_FLAG_INTERNAL)) { - g_autofree gchar *group = NULL; - group = g_strdup_printf ("SmbiosManufacturer=%s", developer_name); - version_format = fu_quirks_lookup_by_id (self->quirks, group, - FU_QUIRKS_UEFI_VERSION_FORMAT); - if (version_format != NULL) { - fmt = fwupd_version_format_from_string (version_format); - if (fmt == FWUPD_VERSION_FORMAT_UNKNOWN) { - g_set_error (error, - FWUPD_ERROR, - FWUPD_ERROR_NOT_SUPPORTED, - "version format %s from quirk %s unsupported", - version_format, developer_name); - return FALSE; - } - g_debug ("using VersionFormat %s from SmbiosManufacturer %s", - version_format, developer_name); - fu_device_set_version_format (device, fmt); - return TRUE; - } - } - - /* nothing found, which is probably fine */ - return TRUE; -} - /* convert hex and decimal versions to dotted style */ static gchar * fu_engine_get_release_version (FuEngine *self, FuDevice *dev, XbNode *rel, GError **error) @@ -2809,6 +2754,61 @@ fu_engine_md_refresh_device_name_category (FuEngine *self, FuDevice *device, XbN fu_device_set_name (device, name); } +static void +_g_ptr_array_reverse (GPtrArray *array) +{ + guint last_idx = array->len - 1; + for (guint i = 0; i < array->len / 2; i++) { + gpointer tmp = array->pdata[i]; + array->pdata[i] = array->pdata[last_idx - i]; + array->pdata[last_idx - i] = tmp; + } +} + +static void +fu_engine_md_refresh_device_verfmt (FuEngine *self, FuDevice *device, XbNode *component) +{ + FwupdVersionFormat verfmt = FWUPD_VERSION_FORMAT_UNKNOWN; + g_autoptr(GPtrArray) verfmts = NULL; + + /* require data */ + if (component == NULL) + return; + + /* get metadata */ + verfmts = xb_node_query (component, "custom/value[@key='LVFS::VersionFormat']", 0, NULL); + if (verfmts == NULL) + return; + _g_ptr_array_reverse (verfmts); + for (guint i = 0; i < verfmts->len; i++) { + XbNode *value = g_ptr_array_index (verfmts, i); + verfmt = fwupd_version_format_from_string (xb_node_get_text (value)); + if (verfmt != FWUPD_VERSION_FORMAT_UNKNOWN) + break; + } + + /* found and different to existing */ + if (verfmt != FWUPD_VERSION_FORMAT_UNKNOWN && + fu_device_get_version_format (device) != verfmt) { + fu_device_set_version_format (device, verfmt); + if (fu_device_get_version_raw (device) != 0x0) { + g_autofree gchar *version = NULL; + version = fu_common_version_from_uint32 (fu_device_get_version_raw (device), verfmt); + fu_device_set_version (device, version); + } + if (fu_device_get_version_lowest_raw (device) != 0x0) { + g_autofree gchar *version = NULL; + version = fu_common_version_from_uint32 (fu_device_get_version_lowest_raw (device), verfmt); + fu_device_set_version_lowest (device, version); + } + if (fu_device_get_version_bootloader_raw (device) != 0x0) { + g_autofree gchar *version = NULL; + version = fu_common_version_from_uint32 (fu_device_get_version_bootloader_raw (device), verfmt); + fu_device_set_version_bootloader (device, version); + } + } +} + static void fu_engine_md_refresh_device (FuEngine *self, FuDevice *device) { @@ -2822,6 +2822,10 @@ fu_engine_md_refresh_device (FuEngine *self, FuDevice *device) fu_engine_md_refresh_device_name (self, device, component); if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY)) fu_engine_md_refresh_device_name_category (self, device, component); + + /* fix the version */ + if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_MD_SET_VERFMT)) + fu_engine_md_refresh_device_verfmt (self, device, component); } static void @@ -3253,10 +3257,6 @@ fu_engine_get_result_from_component (FuEngine *self, XbNode *component, GError * return NULL; } - /* get (or guess) the component version format */ - if (!fu_engine_set_device_version_format (self, dev, component, error)) - return NULL; - /* check we can install it */ task = fu_install_task_new (NULL, component); if (!fu_engine_check_requirements (self, task, diff --git a/src/fu-util-common.c b/src/fu-util-common.c index 259a430f7..bdba5d267 100644 --- a/src/fu-util-common.c +++ b/src/fu-util-common.c @@ -1092,6 +1092,10 @@ fu_util_device_flag_to_string (guint64 device_flag) /* skip */ return NULL; } + if (device_flag == FWUPD_DEVICE_FLAG_MD_SET_VERFMT) { + /* skip */ + return NULL; + } if (device_flag == FWUPD_DEVICE_FLAG_UNKNOWN) { return NULL; }