The FWUPD_INSTALL_FLAG_FORCE flag has really unclear semantics, and ignoring a
file CRC, checksum or model ID should only be done when using fwupdtool actually
debugging a plugin or firmware parser.
Use the existing --force flag when we want a "gentle nudge" like reuploading
previously processed reports.
This is only applicable for kernel 5.9 or kernels that backported
the authenticate on disconnect patches.
For installation time this isn't very important since no device will
restart. This also isn't relevant for the authenticate on disconnect
scenario.
However the manual activation scenario, it's important to activate the
WD19TB device first, followed by Thunderbolt.
If the device is not authorized, it may cause a composite update that it's part
of to not behave properly.
If device is authorized at runtime, add updatable flag at runtime as well
See #2374 for more details
Error will show up if (priv->physical_id == NULL) on
fu_device_ensure_id(). This method is called after probe but before
setup on fu_device_open.
Call fu_device_set_physical_id() on fu_thunderbolt_device_probe()
for the retimer case.
Fixes https://github.com/fwupd/fwupd/issues/2371
Change-Id: I0e462fff5e8abf6073318f6424b6736afc8259b8
Print the sysfs path for devices deriving from FuUdevDevice, which also allows
us to use FU_UDEV_DEVICE_DEBUG without monkey-patching the plugins that also
define a device_class->to_string() vfunc.
Trying to explain why ICL thunderbolt isn't updatable doesn't help
people. It just causes fwupdmgr and fwupdtool to show the device
front and center with a confusing message.
Instead don't populate the message and by the default device filter
it will be hidden.
See #2212 for background.
This allows delaying the activation of Thunderbolt firmware until
shutdown/reboot or when the dock is unplugged.
This functionality requires features in the kernel:
https://lore.kernel.org/linux-usb/20200622143035.25327-1-mario.limonciello@dell.com/T/#t
Matrix of cases to support:
* Distro Old Linux kernel (doesn't support authenticate on disconnect)
- WD19TB: Should have `skips-restart` flag set
No flush or activate features called in `thunderbolt` plugin.
`dell_dock` plugin will activate at end of composite update
- All other devices: Shouldn't have flags set
Should authenticate in Thunderbolt plugin.
`1 > nvm_authenticate`
* Distro New Linux kernel (supports authenticate on disconnect)
- WD19TB: Should have `usable-during-update` flag set but not `skips-restart`
Should flush image to SPI in `thunderbolt` plugin
`2 > nvm_authenticate_on_disconnect`
Should configure TBT device for authenticate on disconnect
`1 > nvm_authenticate_on_disconnect`
`dell_dock` plugin will configure dock for authenticate on disconnect
- All other devices: Shouldn't have flags set
Should authenticate in `thunderbolt` plugin.
`1 > nvm_authenticate`
* ChromeOS (supports authenticate on disconnect)
- `thunerbolt.conf` will have `DelayedActivation=true`.
- WD19TB: Should have `usable-during-update` flag set but not `skips-restart`
Should flush image to SPI in `thunderbolt` plugin
`2 > nvm_authenticate_on_disconnect`
Should configure device for authenticate on disconnect
`1 > nvm_authenticate_on_disconnect`
`dell_dock` plugin will configure dock for authenticate on disconnect
- All other devices: Should have both `usable-during-update` and `skips-restart` set
Should flush image to SPI in `thunderbolt` plugin
`2 > nvm_authenticate`
Will activate upon logout/shutdown/reboot
`1 > nvm_authenticate`
This flag is used internally by plugins to indicate that they will
skip the phase of firmware installation that power cycles a device.
It is intended to be set by quirks or other environment settings.
Thunderbolt images brought in from the SPI don't have a FARB header.
Thunderbolt update images do.
So these two types of images need to be handled separately from the
firmware parser.
The kernel interface for force power doesn't support tracking the state
of the device, and so this had to be tracked by fwupd.
Unfortunately due to system and thunderbolt controller firmware behavior
on some systems the thunderbolt controller /still/ didn't return even
when force power state was accurately tracked.
The device model for the uevent related to the device removal being ignored
doesn't really fit into the current fwupd architecture anymore either.
Lastly this is a very legacy feature at this point. Thunderbolt3 controllers
distributed in the last 3 years all operate in 'native' mode meaning that
they will always be powered and use runtime power management.
USB4 controllers won't have a concept of being force powered.
USB4 reimers will have this concept, but the state will be tracked by the
kernel and obfuscated from userspace.
So with all that said, tear out all of the force power related code.
Remove it's references to it's own GUdevclient and instead use
FuUdevDevice.
Some intentional casualties of the move:
* Plugin metadata around native and safe mode dropped.
- These haven't been useful in debugging anything and aren't relevant
on new hardware
* Extra GUID for 2 host controllers in same system dropped
- Although this was normally static information BIOS operations like
turning off PCI-E SD card reader or LAN controller changed things.
* The NVM version is parsed directly instead of through gudev to prevent
cached data breaking change events.
Remaining TODO:
* Force power w/ thunderbolt-power doesn't work
USB4 Controllers were showing up like this:
USB4 Controller:
Device ID: 3df660bc4bdb67fd6fc101b34c6fd8cd235e3f97
Summary: Unmatched performance for high-speed I/O
Current version: 00.00
Update Error: Device is in safe mode
GUID: 4d86f168-e1cc-5995-afd3-ae9df6a14f5e -> TBT-safemode
Device Flags: Internal device
Requires AC power
This allows the PCI topology to change, but assumes that thunderbolt host controllers
are enumerated in the same order every time.
It won't matter if the first controller jumped from bus 5 to 7 and consequently the
second from 65 to 71, but rather that the first was enumerated followed by the second.
If we say that the version format should be the same for the `version_lowest`
and the `version_bootloader` then it does not always make sense to set it at
the same time.
Moving the `version_format` to a standalone first-class property also means it
can be typically be set in the custom device `_init()` function, which means we
don't need to worry about *changing* ther version format as set by the USB and
UDev superclass helpers.
In 1de7cc we checked the version format when checking for update, but there are
many other places that are doing verfmt-insensitive comparisons. For instance,
the predicates in <requires> all fail if the device version format is plain.
his breaks updating some NVMe drives where the `ne` requirements are not
semantic versions.
To avoid trying to catch all the bugs in different places, and in case we have
a future verfmt that should be treated another way, refactor this out in to a
common function and deprecate the old function.
We don't actually need either of the things it provides (looking up in source
and built, and converting to an absolute path) so just replace it with
g_build_filename() instead.
This also has the advantage that it does the right thing on Windows.
Some plugins have devices with more than one protocol. Logically the protocol
belongs to the device, not the plugin, and in the future we could use this to
further check firmware that's about to be deployed.
This is also not exported into libfwupd (yet?) as it's remains a debug-feature
only -- protocols are not actually required for devices to be added.
In an error block that checks for `NULL` sysfs, you will always see
`(null)` in the string.
```
FuPluginThunderbolt Unable to read generation: failed get id generation for (null)
```
Systems with multiple host controllers will most likely have a different
NVM image for each controller but there is no guarantee that the device_id
within the NVM image varies from one controller to another.
To account for this, build a GUID that contains the last element of the
Thunderbolt controller's udev path.
Sample GUID strings from an XPS 9380 (which only contains one host controller):
```
Guid: 0f401ed2-b847-532a-adc8-3193fc737be6 <- TBT-00d408af-native
Guid: 420b0596-f5cb-5fd7-8416-c99d48ad8de9 <- TBT-00d408af-native-0000:05:00.0
```
This commit follows the presumption that the kernel will enumerate the controllers
in the same order every time.
Currently ICL shows up like this:
```
├─Unknown Device:
│ Device ID: d066959bf1b0da600f4fcaab5aa31cab3ff05eee
│ Summary: Unmatched performance for high-speed I/O
│ Current version: 71.00
│ Update Error: Missing non-active nvmem
│ Flags: internal|require-ac|registered
│ GUID: e72e778e-94f7-5ed2-b560-1c1262ee217c
```
Which isn't very useful to end users. Instead show the generic name
`Thunderbolt Controller` which matches the behavior change we've made
in UEFI FW and Touchpad FW items too.
```
├─Thunderbolt Controller:
│ Device ID: d066959bf1b0da600f4fcaab5aa31cab3ff05eee
│ Summary: Unmatched performance for high-speed I/O
│ Current version: 71.00
│ Update Error: Missing non-active nvmem
│ Flags: internal|require-ac|registered
│ GUID: e72e778e-94f7-5ed2-b560-1c1262ee217c
```
Also, quite the messages about missing vid/did as these won't exist
on ICL either.
Use this attribute to determine whether or not to try to read 'native'
from the Thunderbolt NVM image at probe time.
This attribute is new to kernel 5.5.
There are commits to the Thunderbolt kernel driver that make sure
that the upgrade process goes smoothly. If these commits aren't
present then it will look like a fwupd problem, when it's actually
a kernel problem.
When this issue was reported it appeared that commit
e4be8c9b6a
was missing from the locally tested kernel, but it's impossible
to determine that from userspace.
Prevent running the thunderbolt plugin on older kernels than that
set in `$sysconfdir/fwupd/thunderbolt.conf`.
By default that is set to 4.13.0, but if a distribution vendor has
backported all the necessary support it can be decreased to a lower
version for distro packages.
This controller isn't flashable in fwupd, but fwupd can display information
about it.
* Use a generic device ID (similar to safemode)
* Build device name attribute from DMI data