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.
This commit is contained in:
Richard Hughes 2020-02-24 14:17:04 +00:00
parent 984e29ca33
commit b097603800
10 changed files with 74 additions and 134 deletions

View File

@ -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;
}

View File

@ -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 <name> if available
* @FWUPD_DEVICE_FLAG_MD_SET_NAME_CATEGORY: Set the device name from the metadata <category> 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;

View File

@ -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"

View File

@ -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

View File

@ -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;

View File

@ -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");

View File

@ -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

View File

@ -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`

View File

@ -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,

View File

@ -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;
}