fwupd is a simple daemon to allow session software to update device firmware on your local machine. It's designed for desktops, but this project is probably quite interesting for phones, tablets and server farms, so I'd be really happy if this gets used on other non-desktop hardware.
You can either use a GUI software manager like GNOME Software to view and apply updates, the command-line tool or the system D-Bus interface directly.
Updating firmware easily is actually split into two parts:
- Providing metadata about what vendor updates are available (AppStream)
- A mechanism to actually apply the file onto specific hardware (this project)
What do we actually need to apply firmware easily? A raw binary firmware file isn't so useful, and so Microsoft have decided we should all package it up in a .cab file (a bit like a .zip file) along with a .inf file that describes the update in more detail. The .inf file gives us the hardware ID of what the firmware is referring to, as well as the vendor and a short update description.
I'm asking friendly upstream vendors to also include a MetaInfo file alongside the .inf file in the firmware .cab file. This means we can have fully localized update descriptions, along with all the usual things you'd expect from an update, e.g. the upstream vendor, the licensing information, etc.
A lot of people don't have UEFI hardware that is capable of applying capsule firmware updates, so I've also added a ColorHug provider, which predictably also lets you update the firmware on your ColorHug devices.
I'm also happy to accept patches for other hardware that supports updates, although the internal API isn't 100% stable yet. The provider concept allows vendors to do pretty much anything to get the list of attached hardware, as long as a unique hardware component is in some way mapped to a GUID value. Ideally the tools would be open source, or better still not needing any external tools at all. Reading a VID/PID and then writing firmware to a chip usually isn't rocket science.
What is standardised is the metadata, using AppStream 0.9 as the interchange
format. A lot of tools already talk AppStream and so this makes working with
other desktop and server tools very easy. Actually generating the AppStream
metadata can either be done using using appstream-builder
or the Linux
Vendor Firmware Service.
By default, any users are able to install firmware to removable hardware. The logic here is that if the hardware can be removed, it can easily be moved to a device that the user already has root access on, and asking for authentication would just be security theatre.
For non-removable devices, e.g. UEFI firmware, admin users are able to update firmware without the root password. By default, we already let admin user and root update glibc and the kernel without additional authentication, and these would be a much easier target to backdoor. The firmware updates themselves have a checksum, and the metadata describing this checksum is provided by the distribution either as GPG-signed repository metadata, or installed from a package, which is expected to also be signed. It is important that clients that are downloading firmware for fwupd check the checksum before asking fwupd to update a specific device.
No user interaction should be required when actually applying updates. Making it prohibited means we can do the upgrade with a fancy graphical splash screen, without having to worry about locales and input methods. Updating firmware should be no more dangerous than installing a new kernel or glibc package.
Offline updates are done using a special boot target which means that the usual graphical environment is not started. Once the firmware update has completed the system will reboot.
Devices go through the following lifecycles:
- created ->
SCHEDULED
->SUCCESS
-> deleted - created ->
SCHEDULED
->FAILED
-> deleted
Any user-visible output is available using the GetResults()
D-Bus method, and
the database entry is only deleted once the ClearResults()
method is called.
The results are obtained and cleared either using a provider-supplied method
or using a small SQLite database located at /var/lib/fwupd/pending.db
You need to install colord 1.2.9 which may be newer that your distribution provides. Compile it from source https://github.com/hughsie/colord or grab the RPMs here http://people.freedesktop.org/~hughsient/fedora/
If you don't want or need this functionality you can use the
--disable-colorhug
option.
If you're wondering where to get fwupdate
from, either compile it form source
(you might also need a newer efivar
) from https://github.com/rhinstaller/fwupdate
or grab the RPMs here https://pjones.fedorapeople.org/fwupdate/
If you don't want or need this functionality you can use the --disable-uefi
option.
This document explains what steps a vendor needs to take so that firmware updates are downloaded and applied to user hardware automatically.
Different hardware update methods can be supported, but would require a new plugin and there would need to be interfaces available to be able to write (or at least trigger) the firmware from userspace as the root user.
As per the Microsoft guidelines,
package up your firmware into a .cab
file, with these files inside:
- The actual
.cap
file your engineers have created - The
.inf
file describing the .cap file, described here - The optional
.asc
file which is a detached GPG signature of the firmware file. - The optional
.metainfo.xml
file with a long description and extra metadata, described here
You can create a .cab
file using makecab.exe
on Windows and gcab --create
on Linux.
It is recommended you name the .cab
file with the hardware name and the version
number, e.g. colorhug-als-1.2.3.cab
. It's mandatory that the files inside the
.cab
file have the same basename, for example this is would be valid:
colorhug2-1.2.3.cab
|- firmware.inf
|- firmware.bin
|- firmware.bin.asc
\- firmware.metainfo.xml
An example .inf
file might look like this:
[Version]
Class=Firmware
ClassGuid=84f40464-9272-4ef7-9399-cd95f12da696
DriverVer=03/03/2015,3.0.2
[Firmware_CopyFiles]
firmware.bin
An example .metainfo.xml
file might look like this:
<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2015 Richard Hughes <richard@hughsie.com> -->
<component type="firmware">
<id>84f40464-9272-4ef7-9399-cd95f12da696</id>
<name>ColorHugALS Firmware</name>
<summary>Firmware for the ColorHugALS Ambient Light Sensor</summary>
<description>
<p>
Updating the firmware on your ColorHugALS device improves performance and
adds new features.
</p>
</description>
<url type="homepage">http://www.hughski.com/</url>
<metadata_license>CC0-1.0</metadata_license>
<project_license>GPL-2.0+</project_license>
<developer_name>Hughski Limited</developer_name>
<releases>
<release version="3.0.2" timestamp="1424116753">
<location>http://www.hughski.com/downloads/colorhug-als/firmware/colorhug-als-3.0.2.cab</location>
<description>
<p>This stable release fixes the following bugs:</p>
<ul>
<li>Fix the return code from GetHardwareVersion</li>
<li>Scale the output of TakeReadingRaw by the datasheet values</li>
</ul>
</description>
</release>
</releases>
</component>
If the firmware is not redistributable you have to indicate it in in the
.metainfo.xml
file with <project_license>proprietary</project_license>
.
If the firmware location is not stable you can use the Linux Vendor Firmware
Service to mirror your file.
We will scrape the .inf
and .metainfo.xml
files when building and composing
metadata for distributions; end users will still be downloading the .cab
files directly from the vendor site.
The best way to validate the data is by using the appstream-util validate
tool available from the appstream-glib project.
The easiest way to upload new firmware is to use the Linux Vendor Firmware Service which will validate your firmware, generate the metadata and mirror them automatically.
Vendors can also produce and upload the AppStream metadata themselves using the
appstream-builder
command line tool, for example:
appstream-builder \
--basename=colorhug-firmware \
--origin=hughski \
ColorHug*/firmware-releases/*.*.*/*.cab
...will produce this file: http://www.hughski.com/downloads/colorhug-firmware.xml
Please email us if you want more help using either generation method.
For generic USB devices you can use a firmware vendor extensions that are used by a few OpenHardware projects. This means the fwupd daemon can obtain the GUID and firmware version without claiming the interface on the device and preventing other software from using it. For closed-source devices a product-specific provider can also be used, although this isn't covered here.
To implement the firmware version extension just create an interface descriptor
with class code 0xff
, subclass code 0x46
and protocol 0x57
pointing to a
string descriptor with the firmware version.
An example commit to the ColorHug project can be found here.
Furthermore, using the firmware GUID extension allows fwupd to detect firmware updates for devices it does not know how to update. These types of devices will however show up in the command line and GUI tools, so the user is at least aware that updates are available.
To implement this, add an interface descriptor with class code 0xff
, subclass
code 0x47
and protocol 0x55
pointing to a string descriptor with the GUID.
If the GUID matches the '' obtained from the AppStream metadata then the
device will be shown.
An example commit to the ColorHug project can be found here.
Installing a public key to /etc/pki/fwupd
allows firmware signed with a
matching private key to be recognized as trusted, which may require less
authentication to install than for untrusted files. By default trusted firmware
can be upgraded (but not downgraded) without the user or administrator
password.
Only very few keys will be installed by default. These are the keys of vendors who have a proven security track record and a thorough understanding of public-private key security.
In particular, private keys should only be kept on Hardware Security Mechanisms, and used on machines (or virtual machine) that have limited network access, or networking completely disabled. The machine and any backups also need to be kept physically secure.
If you think your key should be added by default and trusted by all users, please open a pull request with details about your company including items such as a day time phone number and any relevant security policies already in place.