Metadata

The LVFS needs additional information about the firmware which is included in the uploaded cabine archive.

MetaInfo Files

The .metainfo.xml file describes the device and firmware and is extra metadata added to the firmware archive by the OEM or ODM. The file is XML format, and uses a subset of the AppStream component specification.

An example metainfo.xml file looks like this:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2018 Richard Hughes <richard@hughsie.com> -->
<component type="firmware">
  <id>com.hughski.ColorHugALS.firmware</id>
  <name>ColorHugALS</name>
  <name_variant_suffix>Black Friday Special Edition</name_variant_suffix>
  <summary>Firmware for the Hughski ColorHug Ambient Light Sensor</summary>
  <description>
    <p>
      Updating the firmware on your ColorHugALS device improves performance and
      adds new features.
    </p>
  </description>
  <provides>
    <firmware type="flashed">84f40464-9272-4ef7-9399-cd95f12da696</firmware>
  </provides>
  <url type="homepage">http://www.hughski.com/</url>
  <metadata_license>CC0-1.0</metadata_license>
  <project_license>proprietary</project_license>
  <developer_name>Hughski Limited</developer_name>
  <releases>
    <release urgency="high" version="3.0.2" date="2017-02-09" install_duration="120">
      <checksum filename="my-custom-name.bin" target="content"/>
      <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>
      <issues>
        <issue type="cve">CVE-2016-12345</issue>
        <issue type="cve">CVE-2017-54321</issue>
        <issue type="dell">DSA-2020-321</issue>
        <issue type="intel">INTEL-SA-54321</issue>
        <issue type="intel">INTEL-TA-12345</issue>
        <issue type="lenovo">LEN-28775</issue>
        <issue type="vince">257161</issue>
      </issues>
    </release>
  </releases>
  <!-- we can optionally restrict this update to specific fwupd versions,
  or even previous firmware or bootloader versions -->
  <requires>
    <id compare="ge" version="0.8.0">org.freedesktop.fwupd</id>
    <firmware compare="ge" version="0.1.2"/>
    <firmware compare="ge" version="0.3.4">bootloader</firmware>
  </requires>
  <custom>
    <value key="LVFS::VersionFormat">example</value>
    <value key="LVFS::UpdateProtocol">org.acme.example</value>
  </custom>
  <!-- these keywords are optional and are used for searching -->
  <keywords>
    <keyword>bios</keyword>
    <keyword>dfu</keyword>
  </keywords>
</component>

Using GUIDs

GUID means ‘Globally Unique Identifier’ and is a 128-bit integer number used to identify a device. GUIDs are often formatted as strings such as 84f40464-9272-4ef7-9399-cd95f12da696. Another name for GUID is UUID (‘Universally Unique Identifier’) and the two terms can be used interchangeably. When using GUIDs on the LVFS they should always be lowercase.

In fwupd the GUID is generated from the DeviceInstanceId strings, so for a single USB device the GUIDs would be generated like this:

$ python
>>> import uuid
>>> print uuid.uuid5(uuid.NAMESPACE_DNS, 'USB\VID_0A5C&PID_6412&REV_0001')
52fd36dc-5904-5936-b114-d98e9d410b25
>>> print uuid.uuid5(uuid.NAMESPACE_DNS, 'USB\VID_0A5C&PID_6412')
7a1ba7b9-6bcd-54a4-8a36-d60cc5ee935c
>>> print uuid.uuid5(uuid.NAMESPACE_DNS, 'USB\VID_0A5C')
ddfc8e56-df0d-582e-af12-c7fa171233dc

or, using appstream-glib:

$ appstream-util generate-guid "USB\VID_0A5C&PID_6412&REV_0001"
52fd36dc-5904-5936-b114-d98e9d410b25

This allows the vendor to choose the GUID for what should match; to match on the vendor+product+revision you’d choose the first one, and the vendor+device you would use the second. We only really use the third GUID for fixing a vendor name, or other very broad quirks that apply to all USB devices from a specific vendor.

In the case for PCI devices and other technologies like NVMe, you can dump the GUIDs generated by fwupd using this tool:

sudo /usr/libexec/fwupd/fwupdtool --plugin-whitelist nvme get-devices --verbose
...
using e22c4520-43dc-5bb3-8245-5787fead9b63 for NVME\VEN_1179&DEV_010F&REV_01
using 83991323-9951-5adf-b743-d93e882a41e1 for NVME\VEN_1179&DEV_010F
using ad9fe8f7-cdc4-52c9-9fea-31b6f4988ffa for NVME\VEN_1179
...

More details about the GUID generation scheme used in each plugin can be found in the README.md file in each plugin directory.

Note

Metainfo files can contain as many lines of <firmware type="flashed"> as required and any device with any of the GUIDs will match the firmware file.

AppStream ID

The AppStream <id> has to be unique for each device firmware stream as it used to combine separate <release> tags in the .metainfo.xml files into the metadata catalog that is downloaded by end users.

Choosing the correct AppStream ID is thus very important for correct operation of the front end tools.

Firstly, the AppStream ID should have a lowercase prefix that matches the reverse-DNS name of your vendor, similar to Java. For instance, appropriate prefixes would be com.lenovo… or org.hughski….

The ID should also contain the model type, and perhaps also the module that is being updated if there are (or will be) multiple updates for the same hardware. For instance, we would build the ID further into org.hughski.ColorHug2.BIOS….

The ID should always have a suffix of .firmware, which means the finished AppStream ID for this hardware would be org.hughski.ColorHug2.BIOS.firmware

Note

The ID has to be totally specific to the GUIDs used to match the device. For hardware that uses a different firmware stream it is important that the AppStream ID does not match existing firmware with the same ID. The LVFS will warn you if you try to upload firmware with the same ID and different sets of GUIDs.

Including the mode name is just convention; you can use the partial GUID appended if this helps, e.g. com.hughski.ColorHug84f40464.firmware

Warning

Never include forward or backwards slashes in the ID.

Update Category

By telling the LVFS the firmware category to use for the component the front end can correctly translate the update type in the UI. Also for this reason, .metainfo.xml files should not include the words ME, EC, BIOS, Firmware, Device or Update in the component name and they will be removed if included.

The component category can be set as part of the metainfo.xml file or set from the LVFS web console. Most users will want to include the extra metadata to make the upload process quicker for QA engineers. To do this, add this to the metainfo file:

<categories>
  <category>some-value-here</category>
</categories>

Allowed Category Values

Value Displayed Name
X-System System Update
X-Device Device Update
X-EmbeddedController Embedded Controller Update
X-ManagementEngine Management Engine Update
X-Controller Controller Update
X-CorporateManagementEngine Corporate ME Update
X-ConsumerManagementEngine Consumer ME Update
X-ThunderboltController Thunderbolt Controller
X-PlatformSecurityProcessor Platform Security Processor
X-CpuMicrocode CPU Microcode

Update Protocol

The LVFS needs to know what protocol is being used to flash the device. The protocol value is used to provide information about the security of the firmware update to end users.

The update protocol can be set as part of the metainfo.xml file or set from the LVFS web console. Most users will want to include the extra metadata to make the upload process quicker for engineers. To do this, add this to the metainfo file:

<custom>
  <value key="LVFS::UpdateProtocol">some-value-here</value>
</custom>

The latest allowed values for LVFS::UpdateProtocol can be found using the LVFS.

Version Format

Some hardware returns the version number as a string such as 1.23.4567, and this is easily handled as a semantic version. In other cases we are not so lucky, and the hardware returns a uint16_t or uint32_t with no extra metadata about how it should be formatted. This lack of specification precision means that different vendors have chosen to convert the large integer number to various different forms.

The latest allowed values for LVFS::VersionFormat can be found on the LVFS.

To override the default of unknown vendors should ship extra metadata in the metainfo.xml file:

<requires>
  <id compare="ge" version="1.2.0">org.freedesktop.fwupd</id>
</requires>
<custom>
  <value key="LVFS::VersionFormat">intel-me</value>
</custom>

If the version format is unspecified, and cannot be derived from the LVFS::UpdateProtocol then a warning will be shown during upload and the firmware cannot be moved to stable until this is resolved.

Various security teams also want us to always show the device firmware version with the correct format, even if an update is not available. This may be for audit reasons, or just so customers know the version of the firmware compared to release notes written for another operating system. For instance, if the vendor release notes says the firmware should be any version above 39.0.45.x (formatted as a quad) and the user is running 39.0.11522 (formatted as a triplet) it is not clear to the user what to do.

To change from the default triplet version format we can set a fwupd quirk on the hardware device. For instance, changing the UEFI Lenovo ME device to use the intel-me format. Quirk files can be added upstream for future fwupd versions, or simply copied to /usr/share/fwupd/quirks.d. The fwupd daemon will detect the new file and refresh devices as required.

Adding Restrictions

When the user requests updates for a specific device, all the GUIDs provided by the device will be match against any of the GUIDs in the metadata. To limit these matches using a variety or requirements the <requires> tag can be used. For instance, the update can be conditional on the firmware version of another device, or on the kernel version of the installed system.

Requirements can use different methods to compare version numbers.

Type Example Description
eq 1.2.3 Equal
ne 1.2.3 Not equal
lt 1.2.3 Less than
le 1.2.3 Less than or equal
gt 1.2.3 Greater than
ge 1.2.3 Greater than or equal
glob ??FWA* Filename glob
regex FW[1-7] Perl compatible regular expression

Using CHID

Newer versions of fwupd can restrict updates to a specific Computer Hardware ID, much like Microsoft update:

<!-- only newer versions of fwupd understand 'hardware' requirements -->
<requires>
  <id compare="ge" version="1.0.1">org.freedesktop.fwupd</id>
  <hardware>6de5d951-d755-576b-bd09-c5cf66b27234</hardware>
</requires>

If multiple <hardware> entries are specified then all must be present. Newer versions of fwupd can understand an OR requirement using a | separator between the listed GUIDs.

<!-- only newer versions of fwupd understand OR requirements -->
<requires>
  <id compare="ge" version="1.0.8">org.freedesktop.fwupd</id>
  <hardware>6de5d951-d755-576b-bd09-c5cf66b27234|27234951-d755-576b-bd09-c5cf66b27234</hardware>
</requires>

CHIDs can also be added or removed in the LVFS web UI, but only before the firmware is published to stable channel.

component requirements

Modifying requirements of an uploaded firmware.

Other Firmware Version

Newer versions of fwupd can restrict updates on one device depending on the version of firmware on another device. This is most useful when requiring a minimum EC controller version before updating a system firmware, or when a modem firmware needs a specific fix for the baseband firmware:

<!-- only newer versions of fwupd understand 'other firmware' requirements -->
<requires>
  <id compare="ge" version="1.1.3">org.freedesktop.fwupd</id>
  <firmware compare="ge" version="0.1.2">6de5d951-d755-576b-bd09-c5cf66b27234</firmware>
</requires>

Newer versions of fwupd can restrict updates on one device depending if another firmware GUID exists on the system of any version. This is similar to the CHID method above but uses the GUID of the firmware, not a hardware ID.

This can be used to ensure that a specific embedded controller is detected for a specific system firmware update, for example.

<!-- only newer versions of fwupd understand 'other firmware' requirements -->
<requires>
  <id compare="ge" version="1.2.11">org.freedesktop.fwupd</id>
  <firmware>6de5d951-d755-576b-bd09-c5cf66b27234</firmware>
</requires>

Parent Version

For composite devices such as docks you might want to restrict the child device with respect to the parent, for instance requiring the parent to have greater than a specific bootloader version number.

The other useful thing to use this for is checking if the parent has a specific GUID (of any version) which allows us to match against the common VID&PID instance IDs. This would allow us to restrict a generic child device update to a specific OEM vendor parent.

Depth is specified as 1 to match the parent device and 2 to match the grandparent device:

<!-- only newer versions of fwupd understand the 'depth' property -->
<requires>
  <id compare="ge" version="1.3.4">org.freedesktop.fwupd</id>
  <firmware depth="1" compare="ge" version="0.1.2">bootloader</firmware>
  <firmware depth="1">12345678-1234-1234-1234-123456789012</firmware>
</requires>

Client Features

Versions of fwupd >=1.4.5 can restrict updates depending on the features the client can provide. For instance, if the tools are being run in non-interactive mode then it may not be possible to ask the user to perform a manual action.

Some devices may need to show the user some text or an image of how to manually detach the firmware from runtime mode to bootloader mode.

<screenshots>
  <screenshot type="default">
    <caption>Unplug the controller, hold down L+R+START for 3 seconds until both LEDs are flashing then reconnect the controller.</caption>
    <image>https://raw.githubusercontent.com/hughsie/8bitdo-firmware/master/screenshots/FC30.png</image>
  </screenshot>
</screenshots><!-- only newer versions of fwupd understand 'client' requirements -->
<requires>
  <id compare="ge" version="1.4.5">org.freedesktop.fwupd</id>
  <client>detach-action</client>
</requires>

Other firmware may require showing the user a message or image on how to reset the hardware when the firmware update has completed. This specific post-update message functionality is only available in very new versions of GNOME Software for instance.

Post-installation dialog

Showing the user some instructions to reboot the hardware.

This action can be performed with one or two metadata keys set in the .metainfo.xml file, or chosen using the LVFS component editor.

<custom>
  <value key="LVFS::UpdateMessage">Please turn the device off and back on again for the update to complete</value>
  <value key="LVFS::UpdateImage">https://people.freedesktop.org/~hughsient/temp/unifying-power.png</value>
</custom><!-- only newer versions of fwupd understand 'client' requirements -->
<requires>
  <id compare="ge" version="1.4.5">org.freedesktop.fwupd</id>
  <client>update-action</client>
</requires>

Restricting Direct Downloads

If you’d rather not have users downloading the .cab archive directly you can opt to hide the direct download links in the LVFS search results. To do this, add this to the metainfo file:

<!-- most OEMs do not need to do this... -->
<custom>
  <value key="LVFS::InhibitDownload"/>
</custom>

Controlling .inf Parsing

In some cases the .inf file is unparsable, or contains details that are deliberately different from the values shown when using Windows Update. To disable the .inf parsing and verification on the LVFS please use:

<!-- most OEMs do not need to do this... -->
<requires>
  <id compare="ge" version="0.7.3">org.freedesktop.fwupd</id>
</requires>
<custom>
  <value key="LVFS::EnableInfParsing">false</value>
</custom>

The default action is to verify the provided .inf files, but firmware should use <value key="LVFS::EnableInfParsing">true</value> if relying on the DisplayVersion in case this default changes in the future. Additionally, no LVFS::EnableInfParsing value is required if the cabinet archive does not contain an .inf file.

Embargoed and Sanctioned Countries

The LVFS administrator can configure the policy for all firmware owned by the vendor to be blocked from download in embargoed or otherwise sanctioned countries.

The blocked ISO 3166 country codes can also be specified in the firmware itself, using the LVFS::BannedCountryCodes metadata key.

<custom>
  <value key="LVFS::BannedCountryCodes">SYR</value>
</custom>

Source Requirements

If a vendor is distributing GPL licensed firmware on the LVFS then they should include a source URL in the releases section in the metainfo file. This should point to the release-specific source code that can be used to rebuild the binary from the code, for instance:

<release>
  <project_license>GPL-2.0+</project_license>
  <release urgency="low" version="1.2.6" >
  <url type="source">https://github.com/hughski/colorhug1-firmware/releases/tag/1.2.6</url>
</release>

GPL firmware without source information can not be moved to testing or stable. You can also edit or add the source URL in the existing Update Details section in the component view:

component source URL

Device Icons

The icon show in GUI fwupd clients is normally set by the plugin automatically. In some cases the plugin may not know the appropriate icon until firmware has been uploaded to the LVFS.

For this cosmetic purpose the firmware uploader can specify the stock icon in the metainfo.xml file which gets put in the the AppStream metadata and used by the graphical clients. In most cases specifying the icon is not required.

To manually override the icon to one of the stock values, use this:

<component><icon type="stock">battery</icon><component>

Valid stock icons include:

ac-adapter _images/ac-adapter.png
audio-card _images/audio-card.png
audio-headphones _images/audio-headphones.png
audio-headset _images/audio-headset.png
audio-input-microphone _images/audio-input-microphone.png
audio-speakers _images/audio-speakers.png
auth-fingerprint _images/auth-fingerprint.png
auth-otp _images/auth-otp.png
battery _images/battery.png
camera-photo _images/camera-photo.png
camera-video _images/camera-video.png
camera-web _images/camera-web.png
colorimeter-colorhug _images/colorimeter-colorhug.png
computer _images/computer.png
dock _images/dock.png
dock-usb _images/dock-usb.png
drive-harddisk-ieee1394 _images/drive-harddisk-ieee1394.png
drive-harddisk _images/drive-harddisk.png
drive-harddisk-solidstate _images/drive-harddisk-solidstate.png
drive-harddisk-system _images/drive-harddisk-system.png
drive-harddisk-system-solidstate _images/drive-harddisk-system-solidstate.png
drive-harddisk-usb _images/drive-harddisk-usb.png
drive-multidisk _images/drive-multidisk.png
drive-optical _images/drive-optical.png
drive-removable-media _images/drive-removable-media.png
input-dialpad _images/input-dialpad.png
input-gaming _images/input-gaming.png
input-keyboard _images/input-keyboard.png
input-mouse _images/input-mouse.png
input-tablet _images/input-tablet.png
input-touchpad _images/input-touchpad.png
media-flash _images/media-flash.png
media-floppy _images/media-floppy.png
media-optical _images/media-optical.png
media-removable _images/media-removable.png
media-tape _images/media-tape.png
modem _images/modem.png
multimedia-player _images/multimedia-player.png
network-vpn _images/network-vpn.png
network-wired _images/network-wired.png
network-wireless _images/network-wireless.png
pda _images/pda.png
phone _images/phone.png
printer _images/printer.png
printer-network _images/printer-network.png
scanner _images/scanner.png
uninterruptible-power-supply _images/uninterruptible-power-supply.png
video-display _images/video-display.png

Composite Hardware

A vendor can build a single .cab archive with multiple firmware files with different .metainfo.xml files describing them. This allows a single file to be used to update either multiple devices, or a single composite device. An example of a composite device would be a Dell dock, where electrically there are various components connected using USB, but physically it looks like one piece of hardware. Wacom does the same for the various Intuit tablets.

Some tools such as gnome-software may be unable to show more than one update description for the single .cab file. The LVFS also needs to know how to sort the components inside the firmware when showing the logged in user.

To solve this, assign the firmware components a priority, where higher numbers are better. For example main.metainfo.xml:

<?xml version="1.0" encoding="utf-8"?>
<component priority="1" type="firmware">
  <id>com.hughski.dock.firmware</id>
  <name>Hughski Dock Update</name>
  ...
</component>

and also rts1234.metainfo.xml:

<?xml version="1.0" encoding="utf-8"?>
<component type="firmware">
  <id>com.hughski.dock.rts1234.firmware</id>
  <name>RTS1234 Update for Hughski Dock</name>
  ...
</component>

and atmel567.metainfo.xml:

<?xml version="1.0" encoding="utf-8"?>
<component type="firmware">
  <id>com.hughski.dock.atmel567.firmware</id>
  <name>ATMEL567 Update for Hughski Dock</name>
  ...
</component>
topology cli output

Showing the topology of a dock device.

Further Details

There are currently quite strict limits on the format of the release description included in the description part of the metainfo, or edited on the LVFS. For instance, OEMs are not allowed to include links within the text and have to adhere to a limiting style guide. As a workaround, all firmware can now specify an additional url:

<release>
  <url type="details">https://www.hughski.com/releases/colorhug1/1_2_6.pdf</url>
</release>

This should point to a website page or PDF description of the specific release. This would allow vendors to provide more information about specific CVEs or provide more technical information mentioned in the update details. Whist the update details should still be considered the “primary” method to convey information about the firmware release, the URL may be useful for larger OEMs with existing contractual requirements.

Release Urgency Values

It is important to set the urgency of the release to the correct value as this may influence how the client notifies the user. For instance, critical updates may cause a daily session notification to the user, but low priority updates might only be visible when the user manually visits the software center.

Value Meaning
low Low importance
medium Medium importance, e.g. optional update
high High importance, e.g. recommended update
critical Critical importance, e.g. urgent or security issue

Screenshots

In some circumstances we may need to ask the user to perform an action to manually put the device into a special firmware-update mode. We can achieve this using a translatable update caption and an optional line-art image:

Pre-installation dialog

Showing the user some instructions before updating firmware.

To achieve this the firmware needs to declare the public location of the image in the metainfo file:

<?xml version='1.0' encoding='UTF-8'?>
  <component type="firmware"><screenshots>
      <screenshot type="default">
        <caption>Unplug the controller, hold down L+R+START for 3 seconds until both LEDs are flashing then reconnect the controller.</caption>
        <image>https://raw.githubusercontent.com/hughsie/8bitdo-firmware/master/screenshots/FC30.png</image>
      </screenshot>
    </screenshots></component>

In the public metadata the URL is rewritten to use the LVFS CDN to preserve the privacy of the remote client.

The screenshot will only be shown by the front end client when the device has the _NEEDS_BOOTLOADER flag.

Please also add a <client> requirement if the update cannot be performed without showing the image or caption.

Generic Components

Vendors can include an extra .metainfo.xml file with the <component type="generic"> to supply information used by the LVFS to identify the top-level device. This is only useful when there is no obvious existing high-priority component that can be used for display.

This would be useful for a dock to have the title WonderDock2 rather than showing a seemingly random sub-component of it on the public pages.

An example generic.metainfo.xml file would look like this:

<?xml version="1.0" encoding="UTF-8"?>
<!-- Copyright 2020 Richard Hughes <richard@hughsie.com> -->
<component priority="9" type="generic">
  <id>com.hughsie.WonderDock.firmware</id>
  <name>WonderDock</name>
  <summary>Firmware for the ACME WonderDock</summary>
  <url type="homepage">http://www.hughsie.com/</url>
  <metadata_license>CC0-1.0</metadata_license>
  <developer_name>Richard Hughes</developer_name>
</component>

A generic component can also be created for composite firmware manually on the LVFS for firmware that has already been uploaded.

Style Guide

When all vendors use the same style everything looks more consistent for the end user. Here are some of our suggestions:

<name>

  • Use a short device name, e.g. “ThinkPad” or “ColorHug”.
  • Use a UTF-8 character (e.g. ™ or ®) rather than (R) if required
  • Don’t include the vendor name

<name_variant_suffix>

  • Only use this optional tag if the <name> would be duplicated, e.g. if there are two variants of the same hardware
  • Use a short string, as it will be appended to the visible name with brackets if required
  • Don’t duplicate any part of the name

<branch>

  • Only use this optional tag if there are multiple vendors providing different firmware streams for the same hardware.
  • Use a familiar lower case single word string, as it will be shown in the UI

<summary>

  • Refer to the type of hardware, e.g. “Firmware for the Hughski ColorHug Colorimeter”
  • Include the vendor name before the full device description
  • Use a UTF-8 character (e.g. ™ or ®) rather than (R) if required

<description>

  • Try to avoid explaining the implementation details of the fix, e.g. “Ensure accurate color profile creation with high screen brightness.” rather than “Fix overflow in counter when over 500 Lux detected.”
  • Do not use overly technical descriptions when simpler text would suffice, e.g. use “Fix LED color during system start up.” rather than “Fix LED color during POST.”
  • Try to describe fixed bugs and new features from the point of view of the user and how it affects them
  • For security or important updates also include the effect of not applying the update, e.g. “Disk corruption resulting in possible data loss may occur until this update is installed.”

<release tag="N1NET43W" …>

  • The release tag may be optional or required based on component category and vendor policy. If provided it can used to show a vendor-specific text identifier that is different from the version number.
  • The tag may be unique only to the model, or be unique for the entire vendor.
  • This attribute should not be used if the tag is not used to identify the specific firmware on the vendor homepage.
  • Depending on vendor policy, the release tag may be displayed with the header External release Software ID or Machine Type Model.