Introduction

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>
  <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>
    </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>
  <!-- these keywords are optional and are used for searching -->
  <keywords>
    <keyword>bios</keyword>
    <keyword>dfu</keyword>
  </keywords>
</component>

Which GUID Do I Use?

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 interchangably.

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.

Can I match more than one GUID?

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.


Restricting 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>

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.

Restricting using 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>

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>

Settting the 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:

ID Example Description fwupd supported
plain 12345678 Plain integer >=1.2.0
pair 1234.5678 Two large numbers >=1.2.0
triplet 12.34.5678 Microsoft-style >=1.1.0
quad 12.34.56.78 Dell-style >=1.1.0
intel-me 12.2.34.5678 Intel ME-style, with bitshift >=1.2.0
intel-me2 1.2.34.5678 Intel ME-style >=1.2.0
bcd 1.2 Binary coded decimal >=1.1.0

To override the default of triplet vendors can ship extra metadata in the metainfo.xml file:

  <!-- most devices do not need to do this... -->
  <custom>
    <id compare="ge" version="1.2.0">org.freedesktop.fwupd</id>
    <value key="LVFS::VersionFormat">intel-me</value>
  </custom>

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.


Style Guide

<id>
  • Use a reverse-DNS vendor prefix similar to Java, e.g. com.hughski or org.freedesktop
  • The ID has to be totally specific to the device. You can use the partial GUID appended if this helps, e.g. com.hughski.ColorHug84f40464.firmware
  • Always use a .firmware suffix
<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
<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."