fu-engine: Make two passes of requirements checking

Resolves installation for local CAB files that have `VersionFormat`
    set but not yet also set from metadata.

    In the first pass ignore the version format. This will rule out all
    other checks such as GUID and protocol.

    Then apply version format to the device if specified in the CAB.
    Lastly do a second pass with all requirements set.
This commit is contained in:
Mario Limonciello 2020-03-09 15:38:17 -05:00 committed by Mario Limonciello
parent f430da01e5
commit 537da0e98b
5 changed files with 46 additions and 12 deletions

View File

@ -2811,12 +2811,9 @@ fu_engine_md_refresh_device_verfmt (FuEngine *self, FuDevice *device, XbNode *co
}
}
static void
void
fu_engine_md_refresh_device_from_component (FuEngine *self, FuDevice *device, XbNode *component)
{
/* set or clear the SUPPORTED flag */
fu_engine_md_refresh_device_supported (self, device, component);
/* set the name */
if (fu_device_has_flag (device, FWUPD_DEVICE_FLAG_MD_SET_NAME))
fu_engine_md_refresh_device_name (self, device, component);
@ -2835,6 +2832,11 @@ fu_engine_md_refresh_devices (FuEngine *self)
for (guint i = 0; i < devices->len; i++) {
FuDevice *device = g_ptr_array_index (devices, i);
g_autoptr(XbNode) component = fu_engine_get_component_by_guids (self, device);
/* set or clear the SUPPORTED flag */
fu_engine_md_refresh_device_supported (self, device, component);
/* fixup the name and format as needed */
fu_engine_md_refresh_device_from_component (self, device, component);
}
}

View File

@ -156,6 +156,9 @@ gboolean fu_engine_modify_config (FuEngine *self,
GPtrArray *fu_engine_get_firmware_gtype_ids (FuEngine *engine);
GType fu_engine_get_firmware_gtype_by_id (FuEngine *engine,
const gchar *id);
void fu_engine_md_refresh_device_from_component (FuEngine *self,
FuDevice *device,
XbNode *component);
/* for the self tests */
void fu_engine_add_device (FuEngine *self,

View File

@ -334,12 +334,14 @@ fu_install_task_check_requirements (FuInstallTask *self,
}
/* check the version formats match if set in the release */
verfmts = xb_node_query (self->component,
"custom/value[@key='LVFS::VersionFormat']",
0, NULL);
if (verfmts != NULL) {
if (!fu_install_task_check_verfmt (self, verfmts, flags, error))
return FALSE;
if ((flags & FWUPD_INSTALL_FLAG_FORCE) == 0) {
verfmts = xb_node_query (self->component,
"custom/value[@key='LVFS::VersionFormat']",
0, NULL);
if (verfmts != NULL) {
if (!fu_install_task_check_verfmt (self, verfmts, flags, error))
return FALSE;
}
}
/* compare to the lowest supported version, if it exists */

View File

@ -727,11 +727,25 @@ fu_main_install_with_helper (FuMainAuthHelper *helper_ref, GError **error)
/* is this component valid for the device */
task = fu_install_task_new (device, component);
if (!fu_engine_check_requirements (priv->engine,
task,
helper->flags | FWUPD_INSTALL_FLAG_FORCE,
&error_local)) {
g_debug ("first pass requirement on %s:%s failed: %s",
fu_device_get_id (device),
xb_node_query_text (component, "id", NULL),
error_local->message);
g_ptr_array_add (errors, g_steal_pointer (&error_local));
continue;
}
/* make a second pass using possibly updated version format now */
fu_engine_md_refresh_device_from_component (priv->engine, device, component);
if (!fu_engine_check_requirements (priv->engine,
task,
helper->flags,
&error_local)) {
g_debug ("requirement on %s:%s failed: %s",
g_debug ("second pass requirement on %s:%s failed: %s",
fu_device_get_id (device),
xb_node_query_text (component, "id", NULL),
error_local->message);

View File

@ -878,10 +878,23 @@ fu_util_install (FuUtilPrivate *priv, gchar **values, GError **error)
/* is this component valid for the device */
task = fu_install_task_new (device, component);
if (!fu_engine_check_requirements (priv->engine,
task, priv->flags | FWUPD_INSTALL_FLAG_FORCE,
&error_local)) {
g_debug ("first pass requirement on %s:%s failed: %s",
fu_device_get_id (device),
xb_node_query_text (component, "id", NULL),
error_local->message);
g_ptr_array_add (errors, g_steal_pointer (&error_local));
continue;
}
/* make a second pass using possibly updated version format now */
fu_engine_md_refresh_device_from_component (priv->engine, device, component);
if (!fu_engine_check_requirements (priv->engine,
task, priv->flags,
&error_local)) {
g_debug ("requirement on %s:%s failed: %s",
g_debug ("second pass requirement on %s:%s failed: %s",
fu_device_get_id (device),
xb_node_query_text (component, "id", NULL),
error_local->message);