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.
This moves more functionality out of the engine, and will allow us to add some
cleverness to the device list to allow the FuDevice to be shared between
different plugins.
This makes CI more useful as there is currently a problem with
gcab 0.7 and big endian architectures not yet fixed.
More details available in:
https://github.com/hughsie/fwupd/issues/318
It's actually less scary to see a SHA1 hash than it is to see a path like
/sys/devices/pci0000:00/0000:00:1d.0/usb1/1-1/1-1.2. It's also way easier to
copy and paste into the various fwupdmgr command that require a device ID and
also means we can match a partial prefix much like git allows.
If we also move to a model where plugins can be changed during different stages
of the update (e.g. during detach) then the device might change connection type
and then the sysfs path not only becomes difficult to paste, but incorrect.
Session software doesn't care about the format of the device ID (it is supposed
to be an implementation detail) and so there's no API or ABI break here. A few
plugins also needed to be ported, but nothing too worrying.
In the latest version of the LVFS you can restrict the firmware to a specific
machine type, for instance a specific baseboard vendor. This is the same as
done in Microsoft Update using the CHID mechanism.
This commit adds support for the <hardware> requires type, although it needs to
be built against appstream-glib 0.7.4 to be supported and/or tested.
When fwupd is installed in long-term support distros it's very hard to backport
new versions as new hardware is released.
There are several reasons why we can't just include the mapping and quirk
information in the AppStream metadata:
* The extra data is hugely specific to the installed fwupd plugin versions
* The device-id is per-device, and the mapping is usually per-plugin
* Often the information is needed before the FuDevice is created
* There are security implications in allowing plugins to handle new devices
The idea with quirks is that the end user can drop an additional (or replace
an existing) file in a .d director with a simple format and the hardware will
magically start working. This assumes no new quirks are required, as this would
obviously need code changes, but allows us to get most existing devices working
in an easy way without the user compiling anything.
This allows us to fix issues like https://github.com/hughsie/fwupd/issues/265
Specifically, fix the progressbar to:
* Print at 100% after an 'unknown' percentage task has completed
* Refresh the progressbar if being called without a main loop running
* Allow the progressbar to start with a h-offset without moving 'left'
* Don't cause high CPU load when calling fu_progressbar_update() ever few us
Also, add some unit tests to discover all the issues.
It only remained on FwupdResult because I couldn't make up my mind about whether
it was a property of the device, or the firmware release. It's more logically
the former, and that's how plugins are using it.
We can use the power of g_autoptr() to automatically close devices that have
gone out of scope. When everything is converted we can drop the GUsbContect
AUTO_OPEN_DEVICES flag which is making us look bad in powertop.
The Linux DMI class still does not provide the information we need, and parsing
the blob directly also allows the Dell and Redfish plugins to get the raw data.
Handling this in one place prevents plugins setting different values for
non-string values like TRUE/false or with different ways to represent integers.
This could be used, for instance, to set a property on ThunderBolt controllers
inside Dell computers saying that they support forcing the power level during
coldplug. It could also be used to set the dock type for the synapticsmst hub.
Adding this level of complexity allows us to avoid the creep of HAVE_DELL and
HAVE_LENOVO into seemingly unrelated plugins, and also allows us to have
multiple vendor plugins providing the same end result with two different
vendor-specific mechanisms.
This also switches around the test for the self signed key to now fail, as the
generated certificate is no longer loaded into the trust list. This is a more
useful test as it more accurately represents what the fwupd daemon is doing.
As a side-note the detached signature from the derivate cannot be generated
using `--no-p7-include-cert` as only the main LVFS-CA certificate is shipped
with fwupd.
This means we return an error when encountering a rollback attack. This can
currently be performed by providing the old metadata and old signature when
calling into UpdateMetadata.
We can use this as an alternative for GPG. No PKCS7 certificates are currently
installed by fwupd and it's expected that the LVFS will still only provide GPG
detached signatures.
If an OEM distributor wants to sign firmware with a PKCS7 and the corresponding
certificate is provided then the firmware will be marked as valid.
Only firmware shipping with a .p7b file will use the PKCS7 functionality,
similarly remote metadata validation will default to GPG unless Keyring=pkcs7
is specified in the config file.
The items that 0.6.13 requires are now guarded by a version test.
This should allow running fwupd master on more distros that haven't
yet picked up appstream-glib 0.6.13.
This commit provides a new "hwids" subcommand for fwupdmgr that shows the
hardware GUIDs on the local system. It also provides API that plugins can use
to self-disable when a specific HWID does not match.
The GUIDs used in this implementation match that of ComputerHardwareIds.exe
This is a large commit that removes all the providers and turns them into
plugins. I think having both providers _and_ plugins was super confusing.
Plugins are loaded at runtime so you could in theory develop a new plugin
without putting it in the fwupd source tree, although there are no installed
headers or PC files as I'm not sure it's a good idea at this stage.
This commit moves all the per-provider docs, tests, notes, debug dumps and test
data to plugin-specific directories -- these also allows the plugin author to
"own" more of the source tree so we don't enforce fu- prefixes and the style
guide everywhere.
This allows us to run the same action on all the plugins in the future, so we
could have a prepare(FuPlugin, FuDevice) and cleanup(FuPlugin, FuDevice) run
on *all* plugins, so doing an update using one plugin would allow us to work
around hardware quirks in other plugins.
If I've broken your out-of-tree provider it's trivial to port to the new API
with sed and a fixed up build file. If you need help please let me know.
This provider will provide support for items that can be flashed
as capsules but aren't present in the ESRT table.
The MST hub and TBT NVM are not yet updatable, but GUIDs are
created to represent them when they are.