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.
Objects deriving from FuUdevDevice() like FuNvmeDevice typically want to do
FuDevice->FuUdevDevice->FuNvmeDevice rather than FuDevice->FuNvmeDevice.
This matches what FuUsbDevice does.
The setup() is the counterpart to probe(), the difference being the former needs
the device open and the latter does not.
This allows objects that derive from FuDevice, and use FuDeviceLocker to use
open() and close() without worrying about the performance implications of
probing the hardware, i.e. open() now simply opens a file or device.
Probe is supposed to be used to check things like the VID and PID, and to
optionally add extra GUIDs to the device. Crucially, it doesn't require open()
to operate, and so it's wrong to reprobe() on calling close().
This caused errors of mismatching devices that didn't have platform
ID's set.
Example:
18:40:24:0555 Fu ignoring device 370e10407b1f04ade798a9f1d3e1fa57c67750c3 [uefi] existing device 088df415cdee883ec89563e41e6d495924250174 [amt] already exists
Fixes: 3a8d5328 ("Allow the device list to take care of waiting for the device replug")
Commit 0f72ef2f88 causes probe to be re-run on FuDevices.
Any devices derived from FuUsbDevice that set the "Name" key will have the
quirks re-evaluated when GUIDs are added again leading to warnings like this:
```
(fwupdtool:8259): Fu-WARNING **: 23:04:43.144: device 970e85c8400ed95ec5c02b86e52a0ca4ce6fc051 overwriting same name value: Dell USB hub
```
ComputerHardwareIds.exe seems to strip any trailing whitespace before building
the UTF-16 string for hashing. If a SMBIOS blob contains strings with trailing
whitespace then until now the 'fwupdmgr hwids' output would show different
HwIds than when running Windows on the same hardware -- which confuses everyone.
Although this may change the HwIds from 1.1.1 to 1.1.2 on some hardware, I'd
argue it's more important to match the Windows Hardware IDs rather than have
a 'similar, but not the same' implementation.
This affects the Lenovo X380 Yoga, although may also affect other machines.
We can't pretend we're accurate to 10m in the precision of the float when we're
doing things like USB re-enumeration which can take several seconds. I believe
users want some indication of 'should I wait or go do something else' rather
than any precise timings.
These are GUIDs that are related to the main device, but should not be used for
quirk matching. For instance, we might want to list the GUIDs for a bootloader
mode, but we don't want to import all the quirks for the bootloader when in the
runtime mode.
Rather than guessing the keys that might be present, and doing two hash lookups
for each, get the key values in one call. This is somewhat more performant, and
allows us to do clever things in the future.
At the moment quirks are hashed with a key based on the group appended with the
key, which is sometimes made into a GUID. This is suboptimal as when a device
has many different quirk keys (e.g. Name, Summary and Flags) as we hash and
store the same key prefix each time.
Instead, use a 1st level hash to map the group (typically the GUID) to another
hash table. Then use the 2nd level hash to get the value using the key.
This does increase the query time slightly, although reduces RSS considerably --
although not by as much as you'd think as creating a GHashTable with one entry
is more RSS than just storing the string.
This representation does have one huge benefit: You can now get all the keys
of quirk entry without having to guess what they might be. This lets us do some
more efficiency gains with follow up patches.
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.
This was compiling and passing CI as the un-implemented legacy functionality
was still exported in the header.
Remove the prototypes for the missing symbols and fix up the plugin.
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.
There are currently three plugins that use GUdev rather than libusb, and there
are several more in the works. Add a helper object so we can make the plugins
smaller and simpler, much like we already do with FuUsbDevice.
Currently if you download a CAB file from LVFS and try to install it
on a daemon compiled without GPG it will fail to install since LVFS has signed
it. You had to make an intentional decision to disable GPG.
Allow this scenario to work just as if the CAB file were unsigned, but save
a warning in the logs that it happened.
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.
The frontend was never notified of the release (and didn't parse the CAB) so
it doesn't know at this time what the version of the release is and
so this shows a NULL assertion at the time.
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.
Commit 171ec0d added support for 'update' and 'downgrade' operations
in fwupdmgr. Since users can also install CAB files manually
show the titles for those too.
Commit 171ec0dd95 added this information for 'update' and 'downgrade'
operations in fwupdmgr but forgot to add for the 'install' and 'install-blob'
operations of fwupdtool
This prevents horrible things happening when different plugins provide the
parent and child, and the child gets added before the parent.
Alternative to https://github.com/hughsie/fwupd/pull/645
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.
Multiple devices can be updated from one cabinet archive, and it would be quite
confusing just to print the first device title and then have the progressbar go
from 0..100 multiple times.
Use the existing device-changed signal to set the 'current device' and print a
new header if the device changes during the install phase.
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
With composite CAB files it's difficult to see between devices when packed:
Homepage: http://support.dell.com/
Vendor: Dell Inc.
TrustFlags: none
Unknown Device
Guid: 558d18fa-5530-5fc8-9e4b-de3ee8a5eca7
Homepage: http://support.dell.com/
Vendor: Dell Inc.
TrustFlags: none
Unknown Device
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'.
As seen by recent testing this is not working every time.
Since e6cda81f we're now building GUIDs that represent all the possibilities
for shared parts so it's not important to set dock type.
Previously if missing secure boot binaries, or invalid ESP was created the
plugin would just not load.
Now instead populate UpdateError and remove the updateble flag, but still show
the device in fwupdmgr and fwupdtool.
Per https://github.com/projectatomic/bubblewrap/issues/200
the paths need to be built differently to be able to accomodate
an unmerged /usr that Debian has.
Use ro bind mounts rather than symlinks to be compatible to both
Fedora's approach and Debian's approach
In Fedora the only user of libfwupdate is fwupd and the fwupdate command line
tool. It makes sense to absorb the libfwupdate library interface into the
uefi plugin in fwupd. Benefits I can see include:
* fwupd and fwupdate are very similar names; a lot of OEMs are confused
* fwupd already depends on efivar for other things
* We are maintaining an artificial library interface
* The CI and translation hooks are already in place for fwupd
* We don't need to check for features or versions in fwupd, we can just develop
the feature (e.g. BGRT) all in one place.
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.
We were looking for 'active' and 'old' devices with a specific ID. Due to a
copy and paste thinko we were actually matching the active list twice,
triggering the 'device ID was not unique' failure.
Fixes half of https://github.com/hughsie/fwupd/issues/565
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.
Some USB 3.0 Host Controllers are super slow to re-enumerate, one AMD 43b9 chip
being measured at over 7000ms (!) for a simple soft-replug. This also explains
the various device_detach() failures seen on the LVFS for Logitech firmware.
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.
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 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*"
Using just the default GUID is fragile and might break if the GUIDs get added
in the 'wrong' order or if the GUID list is sorted.
Fixes https://github.com/hughsie/fwupd/issues/518
This is designed to be run as root accessing the hardware directly rather than
using the daemon. This would allow a snap or flatpak package to write firmware
even when the host fwupd daemon is too old.
Also, move the SMBIOS parsing code here as this is not needed in fwupdmgr.
This means we can avoid loading a ton of non-fwupd files, and reduces our
running RSS from 5.4Mb to 2.8Mb. Old versions of appstream-glib caches a lot of
the localization string data which we just don't care about for firmware files.
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)
GLib creates two static inline functions for paramaters that may
not be used that set off warnings in clang but not gcc.
Ignore these on clang builds everywhere that
G_DEFINE_AUTOPTR_CLEANUP_FUNC is used.
We need to show this agreement text in every fwupd frontend and exporting a
helper function allows us to do two things:
* Share the semi-complicated code (and fallback) to avoid copy and pasting
* Easily change the code in the future, for instance allowing merging Metainfo
and AppStream metadata without updating all the front ends with new logic.
This allows us to use PolicyKit, which means we will get prompted for
authorization if logged in as a user without permissions.
Fixes https://github.com/hughsie/fwupd/issues/455