We can read this from userspace even when SB is turned on and with the kernel
locked down. The kernel securityfs patches are still in-progress, but will take
significant time to get upstream.
The kernel patches are needed when the PCI device is hidden from userspace.
On a system that is not at all locked down running an old kernel several
of the items are a bit confusing.
```
Runtime Suffix -!
✔ fwupd plugins: OK
✔ Linux Kernel: OK
✘ Linux Kernel: Could not open file
✘ Linux Swap: Not encrypted
```
The HSI specification is currently incomplete and in active development.
Sample output for my Lenovo P50 Laptop:
Host Security ID: HSI:2+UA!
HSI-1
✔ UEFI dbx: OK
✔ TPM: v2.0
✔ SPI: Write disabled
✔ SPI: Lock enabled
✔ SPI: SMM required
✔ UEFI Secure Boot: Enabled
HSI-2
✔ TPM Reconstruction: Matched PCR0 reading
HSI-3
✘ Linux Kernel S3 Sleep: Deep sleep available
HSI-4
✘ Intel CET: Unavailable
Runtime Suffix -U
✔ Firmware Updates: Newest release is 8 months old
Runtime Suffix -A
✔ Firmware Attestation: OK
Runtime Suffix -!
✔ fwupd plugins: OK
✔ Linux Kernel: OK
✔ Linux Kernel: Locked down
✘ Linux Swap: Not encrypted
This exports FuSecurityAttrs into libfwupdplugin so that we can pass the plugins
this object rather than a 'bare' GPtrArray. This greatly simplifies the object
ownership, and also allows us to check the object type before adding.
In the future we could also check for duplicate appstream IDs or missing
properties at insertion time.
This change also changes the fu_plugin_add_security_attrs() to not return an
error. This forces the plugin to handle the error, storing the failure in the
attribute itself.
Only the plugin know if a missing file it needs to read indicates a runtime
problem or a simple failure to obtain a specific HSI level.
MATEKF722SE has unconvetional behavior for dfu protocol, where the sector size
isn't specified and sector type is shiffted left by 1. This happens only for
one sector.
Sector parsing from MATEKF722SE:
* `016Kg`
* `64Kg`
* `128Kg`
* `048 e`
* `528e`
* `004 e`
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.
New enough hardware to have this feature isn't going to be in the marketplace
for a while. To use that newer hardware requires a very recent kernel (5.6 at
least, although it will probably be at least 5.9 by the time the hardware is
released).
The CET status will be used in future functionality.
There was some regression between 1.4.0 and now that prevented updates
containing a Thunderbolt controller from finishing. They would just
sit pending Thunderbolt replug without ever finishing.
Remove the old hack for replug and instead push activation to the end
of the composite steps.
This is to avoid the device tree from changing significantly during
the update process.
This still isn't really ideal, we want to be able to add the flag
usable-during-update to the thunderbolt controller, but this requires
some extra work in the kernel.
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
As a consequence, the version number is also set in the event that the silicon
or firmware app-id is not set, which also seems like the right thing to do.
The idea here is that the device would not come back after it was restarted,
and skipping the attach in the engine was only working around the fact that the
ebitdo did not split out an ->attach() function.
We can't really blame it; we only decoupled the _IS_BOOTLOADER requirement
for ->attach() recently...
The USB 2.0 controller is used as a 'backup' in case the USB 3.0 firmware fails
to start. Set USB 3 hubs as a greater priority so that the USB 2 ones do not
not get added if the USB 3 firmware is working.
These are a regression of 9e755e2a5 when devices are asleep.
However due to the current kernel and daemon architecture, logitech devices
are not checked again at any time so if the device isn't awake when
fwupd is started or the unifying dongle is plugged in it won't be present.
This will be changed in the future when the kernel has change events
associated with devices waking up.
Fixes: #1973
This also means we do the right thing when plugins call fu_device_add_flag()
directly, instead of just from a quirk file.
For instance, now `Flags = ~updatable` is a valid and useful thing to have and
allows us to remove the `Flags = None` hack.
This is nice in theory, until you need to look at the bootloader status of the
parent, or of a different device entirely. Handle this in plugins for the few
cases we care about and stop setting or clearing IS_BOOTLOADER manually just to
get the vfuncs to be run.
Note: I do not think we want to use cleanup() for attaching devices not in
bootloader states -- as cleanup is only run at the end of the composite update.
Doing this unconditionally means we accidentally 'bleed' one device mode into
another in a non-obvious way. For instance, a device might have two operating
modes with different GUIDs. If firmware is supplied for both modes in the same
cabinet archive then we might accidentally match the 'wrong' firmware when
the daemon has observed a mode switch and added the counterpart GUIDs.
We only really need the counterpart GUIDs when switching between Jabra, 8bitdo
and DFU devices where the DFU bootloader VID:PID is not manually tagged with
`CounterpartGuid` in a quirk file. In the general case lets keep it simple to
avoid difficult to find bugs.
The cleanup action for the FuVliUsbhubPdDevice is correct, but was not
conditionalized in the composite cleanup, which meant we would reboot twice
for a normal USB hub update.
Move the parent reboot into the right place, although this does mean we might
reboot twice in the rare event of scheduing a FuVliUsbhubPdDevice *and*
FuVliUsbhubDevice update in the same transaction -- but resetting the device
state between updates is arguably correct anyway...
The VID:PID of the device in HPI mode is shared between multiple vendors, and
so we need to use both the silicon ID and the application ID to match specific
firmware updates.
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.
Correctly attach into the alternate mode after the update has completed.
The vendor was appending two files to make LVFS distribution 'easier' but I'd
much rather use the same deliverables as Windows. This also allows us to
simplify the firmware loading.
Sometimes we only want to add the instance ID to get the quirk matches, and it
is confusing to see the "fake" IDs in the 'fwupdmgr get-devices' output.
Quite a few plugins use HID commands to communicate with the hardware. At the
mement we have ~6 implementations of SET_REPORT and are soon to add one more.
Move this into common code.
This works around a silicon errata which makes the existing 0xB0 chip reset
non-functional.
ALso, as VL10x and VL103 are so different now, use different `->attach()` and
`->detach()` implementations for code sanity.
Based on a patch by Sherlock Chu <SherlockChu@via-labs.com>, many thanks.
These are visually similar to Intel hex files, but different enough to demand
their own parser. Multiple images can be stored in one firmware file, with the
`addr` set to the SiliconID and the `idx` set to the position in the file.
The m-stack DFU quirk also requires that we get the runtime status so that the
USB_DFU_SUCCESS_FUNC callback gets called. We were doing this by accident
before, and since switching to the FuDevice subclass this was dropped.
The dfu_device_refresh_and_clear() function is safe to call on a device which
does not have a working runtime interface.
I misunderstood the original specification, and it seems even USB-hub-less
devices have the same header location as their "write-through" counterparts.
The logic was wrong; we should have been using command 0xB0 for attach back to
FW mode for both VL10x and VL103. Using a generic reset on VL103 always reset
the device back into bootloader mode as the ROM signatures were being written
by command 0xC0.
As now attach and detach have different code paths, there's no point having a
`FuVliDevice->reset()` vfunc, and so we can make everything a little simpler at
the same time.
If the measurements are missing but it's a UEFI system, it's a good indication
that the user has secure boot turned off.
Notify the user on the UEFI device through a non-fatal `UpdateMessage`
To accomplish this, move fu-uefi-vars into the plugin library for other plugins to use
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.
This does 'bleed' the metadata contents into areas previously covered by quirks,
but in this case may be pragmatic and more up to date than a build-time
generated quirk file, which increases the user-friendliness of fwupdmgr.
Some vendors want to ship updates for ATA hardware, but there are currently no
lock-down restrictions in place for these kind of devices.
There is the OUI from the WWN block which is supposed to identify the vendor,
but this is not always set and so we have to be a little creative. We can match
90% of hardware using the vendor name prefix, and the last 10% can be detected
with a heuristic that was the result of comparing over 900 drive models.
I'm not including very old drive models, media converters, raid controllers,
or external 'portable' drives as I don't think it is useful. Also, if the drive
contains a Dell vendor block just hardcode this as Dell rather than trying to
be clever.
Also ask the user to contribute OUI values if this data is found with no quirk
data as this is the only real sane way to manage this data long term.
The list of OUIs can be found here: http://standards-oui.ieee.org/oui.txt
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.
The UEFI ESRT table just gives us a table of GUIDs with some basic flags, and
isn't very useful to end users. This is acceptable for Dell as there is only
typically one ESRT entry, which is for the system firmware. On typical Lenovo
hardware there might be half-a-dozen different 'Device' entries which all look
very similar.
As it's not possible to get a channel-of-data from the ODMs to fwupd, use the
existing LVFS metadata to generate some better names for these devices.
Although this looks like a lot of repeated data, libxmlb helpfully dedupes the
strings for us, making the quirk store only slightly larger.
Also, I've deliberately made this a manual step as we're not going to have
internet access on distro builders, and I'd also like the fwupd tarball output
to be deterministic and repeatable.
Currently if there is an invalid boot entry for firmware update, the fwupd
EFI program will not call UpdateCapsule(), even if there is a valid entry.
For example, if the following entries exist the firmware update will fail:
HD(1,GPT,A672BBCA-325E-4D6F-91E1-DD57FAA85A9C)/\EFI\rhel\fw\fwupdate-6cialq.cap ... /*Valid entry*/
HD(1,GPT,E8176B29-6F73-43F2-AE8E-05E09DE20EE5)/\EFI\fedora\fw\fwupd-6dcbd5ed-e82d-4c44-bda1-7194199ad92a.cap ... /*InValid entry*/
Ensure capsule update is happening even if a valid capsule entry exists.
Signed-off-by: Bhaskar Upadhaya <bupadhaya@marvell.com>
Some logitech devices seem to reboot immediately and the failures then
look like a broken pipe, but are actually the device rebooting.
If the device really did fail to detach after the timeout is done we'll
see a message that the device failed to come back instead.
Deleting boot entries from EFI sometimes triggers problems on some firmware.
We don't actually need to do it from the EFI binary, and it's perfectly safe to
leave it in the boot list. It also means when doing multiple updates over
several months we're not creating, deleting, creating, deleting and can just
re-use the same BootXXXX number each time.
It also makes the EFI binary simpler, which is good.
At the moment fwupd creates a BootXXXX for fwupd.efi and marks it BootNext.
It *also* adds it to the end of BootOrder to work around various old firmware
bugs like https://github.com/rhboot/fwupdate/issues/55 which we can perhaps
drop sometime thie century.
Remove the rewriting of BootOrder from the EFI binary; we've accidentally not
been doing it for a long time and nothing broke, and I'd like to make the EFI
binary as small and simple as possible. The user can remove the entry from the
BIOS or using efibootmgr if required, but it's harmless to just leave it.
This reverts commit 44f55e2ee6.
This behavior caused fwupdx64.efi to loop for a very long time until
either aborting, running out of memory or some other problems.
Fixes: #1756Fixes: #1751
The guint16 was promoted to (signed) int for the multiplication, which meant
that the highest address possible was 0x7FFFFFFF not 0xFFFFFFFF. Which doesn't
really matter in reality, as all addresses are much smaller than that now.
gnu-efi 3.0.11 moves a few files around, e.g.
/usr/lib64/gnuefi/elf_x64_efi.lds -> /usr/lib64/gnuefi/x64/efi.lds
...and this causes the UEFI EFI helper to fail to link.
Add support for the 'new' paths and fall back to the old ones.
Fixes https://github.com/fwupd/fwupd/issues/1736
In some composite dock hardware there are two USB devices exported to the host,
both with the same VID:PID values. We need to use the device type (e.g. VL812B3)
to differenciate the devices and install the correct fw on the correct device.
In theory, these should always match the reported PCRx values from the TPM.
If the reconstructed event log checksum does not match the TPM value then
something is either implemented wrongly, or something bad has happened.
This means we use half the amount of memory to store the event hashes, and also
means we can process the raw data in future patches without parsing back out
of ASCII format.
UEFI runtime service GetVariable with DataSize NULL, will fail and get
EFI_INVALID_PARAMETER returned. Set DataSize 0 and allocate the buffer for
getting attributes for the deleted variable.
Also, fix the real reason Boot#### was never found.
Synaptics versions are encoded as BCD, the largest version that will
ever be represented in this field is '99'.
Using 3 digits in this field has caused multiple problems in upgrades from
LVFS.
1. Devices are being upgraded when not necessary.
IE `5.3.10 > 5.3.010`
2. Device upgrades are deemed failures as follows:
```
BootTime=1571436076,
CompileVersion(com.redhat.efivar)=37,
CompileVersion(com.redhat.fwupdate)=12,
CompileVersion(org.freedesktop.fwupd)=1.3.2,
CompileVersion(org.freedesktop.gusb)=0.3.0,
CpuArchitecture=x86_64,
DistroId=fedora,
DistroVariant=workstation,
DistroVersion=32,
FirmwareId=1915,
Flags=4194346,
Guid=f15aa55c-9cd5-5942-85ae-a6bf8740b96c,
MachineId=97aa89528b88d9631867a4e20c68a5208124ef592e19d05f0c5e7d22bd4d7afb,
Plugin=synapticsmst,
RuntimeVersion(com.dell.libsmbios)=2.4,
RuntimeVersion(com.redhat.fwupdate)=12,
RuntimeVersion(org.freedesktop.appstream-glib)=0.7.14,
RuntimeVersion(org.freedesktop.fwupd)=1.3.2,
RuntimeVersion(org.kernel)=5.4.0-0.rc2.git2.1.fc32.x86_64,
UpdateError=device version not updated on success, 05.03.10 != 5.03.010,
UpdateState=failed,
VersionNew=05.03.10,
VersionOld=5.03.010
```
There's no reason to prevent NULL, and doing so means the caller has to check
before setting the value. Only one subclassed type was actually doing this...
No need to fail these self tests when using amdgpu, just skip them.
Fixes unrelated issue found in #1183
Signed-off-by: Richard Hughes <richard@hughsie.com>
Some hardware does not handle upgrading from version 1.2.2 to 1.2.4 and instead
needs to be upgraded from 1.2.2->1.2.3->1.2.4 so that on-device metadata can be
migrated correctly.
Add a new per-device flag `install-all-releases` which causes the daemon to not
skip directly to the newest release. This is designed to be set from a quirk
file.
This can obviously only be used for devices that can apply firmware "live" and
thus do not need a reboot or system shutdown to actually apply the firmware.
This also needs the cabinet archive to ship multiple versions of the firmware,
and for the metainfo.xml file to refer to multiple release objects.
To implement the SPI commands, objects can derive from FuVliDevice and
implement the new vfuncs. This allows us to override the implementation for
minor API changes.
Right now vendor string is detected by walking up the udev chain
until a vendor is found. On some systems this is finding incorrect
data such as `Intel Corporation` for the vendor on the touchpad.
As the plugin only supports Synaptics devices, Correct it by hardcoding
vendor to `Synaptics`.
Sample output:
```
└─Touchpad:
Device ID: b26933c085b020ecf84c490812458523aee710ac
Current version: 1.5.2767034
Bootloader Version: 54.0
Vendor: Synaptics (HIDRAW:0x06CB)
GUIDs: f4384034-9243-5334-8075-a534be913e46 ← HIDRAW\VEN_06CB&DEV_76AF&REV_00
424bd00e-9789-5cdf-a12a-3c81bc4676d6 ← HIDRAW\VEN_06CB&DEV_76AF
140f4458-951b-5bb9-85e2-879bd5b02615 ← SYNAPTICS_RMI\TM3038-003
b29d3c85-cd0e-503e-9c7e-f6731c1eaf2d ← SYNAPTICS_RMI\TM3038
Device Flags: • Internal device
• Updatable
```
Dell does not include the first byte in the ESRT value, ignoring it. Using a
`quad` means we get versions like `0.1.4.0` rather than `1.4.0` which confuses
both users comparing versions to the vendor website, and also anyone trying to
do analysis on the firmware.
Only on Lenovo devices the DMI version string is prefixed with
CBETxxxx to make the thinkpad_acpi kernel module happy.
Add a new quirk called "CorebootVersionQuirks" to detect platforms
that need to cut of the prefix.
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
In fu_plugin_startup we make sure that the FU_HWIDS_KEY_BIOS_VENDOR
matches "coreboot", so there's no need to read it again.
Remove the call to fu_plugin_get_dmi_value and drop the first call
to fu_device_set_vendor as it gets overwritten below.
Hardcode the id string for now.
Signed-off-by: Patrick Rudolph <patrick.rudolph@9elements.com>
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.