The daemon creates a baseclass of either FuUsbDevice or FuUdevDevice when the
devices are added or coldplugged to match the quirk database and to find out
what plugin to run.
This is proxied to plugins, but they are given the GUsbDevice or GUdevDevice and
the FuDevice is just thrown away. Most plugins either use a FuUsbDevice or
superclassed version like FuNvmeDevice and so we re-create the FuDevice, re-probe
the hardware, re-query the quirk database and then return this to the daemon.
In some cases, plugins actually probe the hardware three times (!) by creating
a FuUsbDevice to get the quirks, so that the plugin knows what kind of
superclass to create, which then itself probes the hardware again.
Passing the temporary FuDevice to the plugins means that the simplest ones can
just fu_plugin_device_add() the passed in object, or create a superclass and
incorporate the actual GUsbDevice and all the GUIDs.
This breaks internal plugin API but speeds up startup substantially and deletes
a lot of code.
Similar to commit 7d35278 regarding the install option with a daemon compiled without
GPG, but now, if you also have a daemon compiled without GPG, and if you have downloaded a
CAB file from LVFS and ran get-details, it would fail to display the contents
of the associated CAB file.
This allows it to still display the contents of the CAB file, and
a warning will be displayed in the logs.
This allows us to match non-DeviceID GUIDs, and also GUIDs we don't know how to
generate.
To make this fully useful, search for device quirks when GUIDs are added.
Allowing plugins to 'register' for different udev subsystems in _init() allows
us to move the client to the engine, reducing the number of wakeups considerably
for each device event. It also will reduce the amount of boilerplate code in
each plugin that uses GUdev, much like we have done for GUsb.
Some devices take a long time to initialize and tools like fu-tool
have no feedback during this time.
Show a status message to indicate what's going on.
This isn't useful for most people and just takes up space in the logs.
When there is a problem it's typically specifically with a plugin
and at that time we ask them to run the daemon with verbose anyway.
In this instance, we define the 'same device' to be a FuDevice that has at
least one matching GUID. We allow the plugins to define which one is 'better'
than other plugins, and use this to only have one FuDevice for the physical
device.
Alternative to https://github.com/hughsie/fwupd/pull/604
Fix a logic error when testing requirements; what was supposed to happen was
that a the firmware requirements were only processed when we had a FuDevice set
in the FuInstallTask, but instead we were falling through to the handler for
'unknown requirement type'.
This pivots the data storage so that the group is used as the preconditon
and the key name is used as the parameter to change. This allows a more natural
data flow, where a new device needs one new group and a few few keys, rather
than multiple groups, each with one key.
This also allows us to remove the key globbing when matching the version format
which is often a source of confusion.
Whilst changing all the quirk files, change the key prefixes to be more familiar
to Windows users (e.g. Hwid -> Smbios, and FuUsbDevice -> DeviceInstanceId)
who have to use the same IDs in Windows Update.
This also allows us to pre-match the desired plugin, rather than calling the
probe() function on each plugin.
Not calling dozens of ->probe() functions is dramatically more efficient when
there are a large number of USB devices attached.
This requires plugins to 'opt-in' to the new behaviour, and also to supply
quirks that match all devices.
If the daemon either de-duplicates or replaces the object passed emitted from
device-added then the object set as the alternate may not be the same instance
as the daemon version. This causes weird things to happen.
To make this less fragile, specify the *ID* of the object that should be the
alternate device, which allows the daemon to do clever things, and then assign
the object from the ID as the last step.
Although fixing no bug, this makes implementing future functionality easier.
Now we can update multiple devices (in multiple plugins) using one firmware
archive we need a way to cleanup after all the plugins have been run.
Fixes https://github.com/hughsie/fwupd/issues/561
This can be used to select the AA.BB.CC.DD format rather than the default
AA.BB.CCDD format for firmware versions. This allows us to support new vendor
requirements without adding more complicated rules to the quirk file.
Fixes a segfault that occurs during cleanup of USB plugins.
When g_module_close was called memory allocated by the plugin would
get freed leading to the finalize method for object class pointing
to garbage.
When developing code it's really convenient to only run the new plugin. This
means you don't have to wait for the other hardware to initialize and there
are no side-effects from other plugins when installing firmware.
You can specify multiple plugins as globs, for instance:
fwupdtool get-devices \
--plugin-whitelist wacom \
--plugin-whitelist "thunderbolt*"
When using failed to open firmware.cab we pass in a device ID of '*' which
tells the daemon to update anything that matches. The current implementation
will fail in two ways:
* If duplicate hardware is installed (for instance two Unifying receivers) then
only the first matching device will be updated.
* If the firmware archive contains two different images then we only try and
upgrade the first device that matches. This means we're unable to update
composite devices using one firmware file.
To fix both issues, carefully build a list of tasks that can be processed using
the given firmware and installed devices, request authentication using all the
different action IDs, then upgrade all the devices one-at-a-time.
Based on a patch by Mario Limonciello <mario.limonciello@dell.com>, many thanks.
This allows us to find out the logical parent device, for instance in composite
devices with more than one firmware image for a single device.
We also allow lazily specifying the device parent using a GUID and the engine
then automatically sets the parent object when the GUIDs match, which allows
children and parents to exist in different plugins.
We don't want to use the version= attribute as the HWIDs are not versions, and
thinkgs like globbing just doesn't make sense given they are from hashes.
Fixes the client side part of https://github.com/hughsie/lvfs-website/issues/110
This allows plugins to set and explicit build-time version. It also uses the
same AppStream component-ID scheme rather than the home-grown 'FooVersion' key.
Also, use the new runtime and compile-time versions in the report metadata.
Due to the key change we'll also need to update some LVFS rules.
In some cases firmware can only be installed with an up to date GUsb (e.g. with
some STM-DFU hardware) or with a new version of fwupdate (e.g. any UEFI
UpdateCapsule without a capsule header).
We should be able to match against other software versions like we can the
fwupd version, e.g.
<requires>
<id compare="ge" version="0.9.2">org.freedesktop.fwupd</id>
<id compare="ge" version="11">com.redhat.fwupdate</id>
</requires>
Also, rather than checking each requirement we know about on the component,
check each requirement on the component about things we know. This ensures we
don't allow firmware to be installs that requires for instance fwupdate 22 when
the runtime version is only being added in fwupdate 12 and up.
This means the following is now an error that will fail to allow the firmware
to be installed:
<requires>
<firmware>doesnotexist</firmware>
<some_future_tag>also_unknown</some_future_tag>
</requires>
Also add a lot of self tests to test the various new failure modes.
Fixes https://github.com/hughsie/fwupd/issues/463
There are a lot of hacks here;
* Pulling newer libappstream-glib from Fedora
* Pulling a systemd backport
* Manually installing pillow and pygobject
* PKCS7 is turned off (gnutls is too old)
Don't optimize the device flag away. We need to be able to set the flag on all
devices that match the device ID, not just the one that happens to match now.
If the device firmware was set incorrectly make then set it to the release
version so the database update works correctly. We can't do any kind of vercmp
in the database, so use a daemon warning so we can either fix the plugin or
the XML.
This fixes up the issue that the hardware reports '28.00' and the AppStream
release specifies '28.0'.
Fixes: https://github.com/hughsie/fwupd/issues/387
If this happens:
1.2.3 -> 1.2.4 = failure
1.2.3 -> 1.2.5 = success
...we want to preserve both in the history database so they can both be shared
with the LVFS. Use the device ID and the new and old firmware versions when
modifying and deleting entries.
This fix is made slightly more tricky as we have to drop the PRIMARY KEY
attribute on the device_id, and due to a limitation in SQLite, it means copying
the old history into a new table.
Previous to having the history database we could only notify about firmware that
as installed using the uefi plugin, as that had a few system-wide API calls to
say 'this update failed' or 'this was the error'.
Now we have the local history database not only can we report more details about
the UEFI update (e.g. the old version number) but we can also offer the same
functionality for all other plugins.
Although this does rework how the data for GetResults() is populated, it does
make the FuEngine object quite a lot less confused.
It also fixes a warning in the fwupd plugin for gnome-software, which was
expecting the FwupdRelease to be populated for the FwupdDevice.
This allows us to record whether we've shown the user a notification (either in
the terminal or in a GUI) that an update failed or was successful.
This can't be done in the session otherwise we'd get a notification for every
different user on the system. Notifying also isn't the same as reporting,
although one can certainly follow on from the latter.
In the case of failing to even set up UpdateCapsule, the uefi plugin would
dutifully return SUCCESS as it was referring to the 2nd-to-last update that
actually worked.
The SUPPORTED flag is used when a device appears in the AppStream metadata of
any enabled remote, so when we rescan the modified store also ensure the flag
state is still correct.
Fixes https://github.com/hughsie/fwupd/issues/363
Rename FuPending to FuHistory to better represent what the object is now doing.
Also, while we're here, switch to using SQLite prepared statements to avoid a
possible invalid read on i386 hardware.
Always set the AppStream app properties on the FwupdRelease. In some cases we
were returning FwupdRelease objects with no name or summary which gnome-software
was ignoring.
Using old versions of gcab we could only do one thing: extract the files in the
cabinet archive to a new directory in /tmp, and then fwupd would have to read
them back in to memory to parse them. This was both inelegant and wasteful, and
probably not an awesome idea from a security or privacy point of view.
Using libgcab >= 1.0 we can decompress to a GBytes blob, and then verify the
firmware and metainfo file without anything being written to disk.
As this is a security sensitive operation, move the fwupd-specific helper code
out of libappstream-glib and also add a lot of internal self tests.
The gcab code will have to remain in libappstream-glib for a long time, but we
don't have to use it. Handling the cab file here also allows us to fix two
long-standing bugs:
* MetaInfo or firmware files in a subdirectory are handled correctly
* The archive can also be self-signed using PKCS7 instead of using GPG
In the case of multiple <component> sections with different AppStream IDs, but
with the same GUID <provides>, filter using the requirements rather than just
choosing the first one.
This allows the update of Logitech devices with secure bootloaders. Many thanks
to Ogier Bouvier for identifying the problem.
This ensures we get progress events when replugging a device. Also, remove the
callbacks on the 'old' device to avoid causing multiple events on a 2nd-replug.
This makes more sense; we're updating the device, not the plugin itself.
This also means we don't need to funnel everything through callbacks like
GFileProgressCallback and we can also update the state without adding an
explicit callback to each derived device type.
`Not compatible with fwupd version 1.0.2, requires >= 1.0.3`
...is easier to understand than...
`Value of org.freedesktop.fwupd incorrect: failed predicate [1.0.3 ge 1.0.2]`
This saves all the USB plugins from connecting to the context and managing the
device lifecycle and allows devices that uses FuUsbDevice to be removed
automatically.
This makes supported plugins *much* smaller indeed.
When changing from runtime->bootloader->runtime the usual way of handling this
in a fwupd plugin is to:
* reset the device and wait for a replug
* flash the hardware
* reset the device and wait for a replug
This works well when the runtime and bootloader modes are handled by the same
plugin. For situations like the Nitrokey device, where one plugin handles the
runtime (nitrokey), and another handles the bootloader (dfu) we have to have
the ability to 'ignore' the device removal and just issue a 'changed' signal
so the client refreshes the properties.