If the user is trying to install version '20190104' on something with the
existing version '1.2.3' then something has gone wrong. Ensure the device
release version format matches the release version format and fail to apply the
update if this is not true.
In the common case setting the version with fu_device_set_version('1.2.3')
would set the version format to TRIPLET, and setting <release version='1.2.3'>
so no action is required. In cases where the version format could be ambiguous
then the format should be set both in a quirk and also in the metainfo file.
In the future we'll want to use this flag to signify if the release is an
upgrade, downgrade, below the version-lowest, or if it is locked in some way.
This is intended for devices that it is not safe to immediately activate
the firmware. It may be called at a more convenient time instead.
Both fwupdmgr and fwupdtool support the feature.
- if called at runtime with fwupdmgr it uses the daemon
- during shutdown fwupdtool uses the pending.db to perform this feature.
In some situations SELinux prevents fwupd from executing tpm2_pcrlist, but the
failure mode is that the process just hangs and never completes. This causes
systemd to time out the fwupd daemon startup and then errors to be shown in
GNOME Software.
To prevent this happening, add an optional timeout argument to
fu_common_spawn_sync() and cancel the subprocess if it takes longer than this
to complete.
See https://bugzilla.redhat.com/show_bug.cgi?id=1665701 for details.
This allows hardware from OEMs to *not* match generic firmware supplied by the
device manufacturer. The idea being, that the OEM will supply firmware that
will actually work on the device.
Based on a patch from Mario Limonciello, many thanks.
This allows plugins to load an archive supplied as the 'deliverable' of the
cabinet archive. This means plugins can bundle up a set of images in a cross
platform way, for instance adding boot.img+os.img+manifest.xml into a zip file,
rather than having to (ab)use the DfuSe file format or deal with libarchive
directly.
These are set from the AppStream metadata and are specific to the firmware
release.
If not provided, the install duration falls back to the per-device duration
values which can be set in the quirk files.
If the poll source is scheduled just at the right time, we might only get 8x
'10ms ticks' in a 100ms window. This fixes an occasional build failure on
slower hardware and in CI.
The libxmlb library is much faster to query, and does not require the daemon
to parse the XML metadata at startup. It's a zero-copy mmap design that is more
modern and less clunky.
RSS has reduced from 3Mb (peak 3.61Mb) to 1Mb (peak 1.07Mb) and the startup
time has gone from 280ms to 250ms.
This allows a frontend to call update on an individual device ID which will
cause a CAB file to be downloaded, but then also re-use the same CAB file to
try to process devices with a relationship as part of a transaction.
At the moment firmware can declare that it has certain requirements, for
instance the existing firmware version, the bootloader version, or the
vendor ID of the device.
In some situations we actually want to check the firmware version of a
*different* device. Good examples here would be only allowing an EC upgrade if
a specific BIOS update has already been done, or only allowing a wireless
reciever to be updated if the attached wireless devices have been updated first.
To use this, you can do something like:
<requires>
<id compare="ge" version="1.1.3">org.freedesktop.fwupd</id>
<firmware compare="ge" version="0.9.0">guid-of-other-device</firmware>
</requires>
Now devices can have multiple GUIDs and do not share platform IDs there is
really no point waiting to add the device.
This allows us to remove a whole lot of code for this now-unused functionality.
It wasn't hugely clear what the platform ID was actually meant to represent. In
some cases it was being used like a physical ID, in others it was a logical ID,
and in others it was both. In some cases it was even used as a sysfs path.
Clear up all the confusion by splitting the platform ID into two parts, an
optional *physical* ID to represent the electrical connection, and an optional
*logical* ID to disambiguate composite devices with the same physical ID.
Also create an explicit sysfs_path getter for FuUdevDevice to make this clear.
This allows WAIT_FOR_REPLUG to always work, rather than depending on the order
that the GUIDs were added, and that the kernel would always return the same
sysfs path (which it doesn't have to do, especially for hidraw devices).
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.
Five plugins (soon to be 7) are linking to the DFU plugin just for this simple
segment-aware chunking functionality. Move this into common code to make
building simpler.
Test whether CONFIG_USER_NS and related knobs are set.
* Fail daemon execution if not
* Skip self tests if not.
Detect ENOTTY errno set by process spawn.
Skip self tests if set.
Fixes FTBFS on Debian pbuilder and unprivileged docker.
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
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.
As it turns out, the major and minor BIOS version should also be
represented in hex format in the hash, but in contrast to the
enclosure type, always on 2 digits, padded if necessary. There is no
decimal value in any of the hashes, it seems.
The previous data, I tested with didn't include major/minor version
numbers bigger than 9, so the issue didn't materialize.
Handle the enclosure type as a hex value, not as a decimal.
This is mandated by the SMBios specification, where 0x10h (the value
16) is specifying the enclosure type of "lunch box", while 0x0ah (the
value 10) is "notebook".
They hash BIOS major and minor version with 2 digit padding using
leading zeros. We do the same from now on.
Signed-off-by: Richard Hughes <richard@hughsie.com>
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.
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
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 does mean fixing up the version numbers. The idea is that we have a
virtual device that goes from 1.2.2->1.2.3 for an update, and 1.2.3->1.2.2 for
a downgrade.
Deduplicate based on the ID, without assuming the devices will be the same
in-memory object. Also, only emit the changed signal if the device is waiting
for a replug.
Fixes https://github.com/hughsie/fwupd/issues/364
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.
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
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.
These introduce no functional changes, but do shut up
-Wincompatible-pointer-types-discards-qualifiers warnings.
Signed-off-by: Philip Withnall <withnall@endlessm.com>
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.
In the case where we can trigger the replug automatically we can have to wait
for a USB re-enumeration (typically a few hundred ms) but when the user is
requred to unplug, and then replug we have to wait a bit longer.
The 'remove delay' allows us to modify per-device the removal delay. In the
case the device does not show back up in the correct time the device will be
auto-removed and the session will get a DeviceRemoved signal. In the case where
the device in bootloader mode shows up within the timeout the session just gets
a DeviceChanged event.
For the duration of the delayed removal the flags for the device are set to
zero to ensure the session does not try to interact with the device whilst
re-enumerating.