Skip to main content

Overview

This page is a hands-on walkthrough for performing a multi-image UEFI capsule update from the U-Boot console. It complements the conceptual capsule pages in this chapter by showing the exact commands to:
  1. Discover which firmware images a board can update.
  2. Build the mkeficapsule host tool.
  3. Bundle several firmware payloads (U-Boot, TZ, XBL, and so on) into a single UEFI capsule, signed or unsigned.
  4. Land the capsule on the EFI system partition (ESP), arm the update by setting OsIndications, and reboot to apply it.
  5. Verify the result.

Supported SoCs

The flow is identical across the following SoCs. Only the defconfig differs.

Discover supported images

Flash U-Boot, stop at the U-Boot console, and run:
This command walks every Firmware Management Protocol (FMP) instance and prints one row per updatable image the board exposes:
This list is board-specific (built from that board’s GPT), so not every board shows every component. Only images that appear here can be updated by capsule on that board. Note the image-guid and image-index values that this command reports for each component — they’re used in the capsule config in the subsequent sections. The image-guid is what selects the target partition at apply time.

Build the mkeficapsule tool

First, get the source:
Then build the host tool into a .output folder:
The binary is produced at .output/tools/mkeficapsule. All commands below invoke it by path.

Set up the capsule folder

Create a working folder for the board with the following structure:
Only include the payloads for the images to be updated. Each must appear in the efidebug capsule images output.

Capsule config-file format

The config is a series of { … } blocks, each a set of key: value pairs. One block describes one payload. Grouping rule: payloads that share the same capsule: filename are bundled into a single multi-image capsule. Different filenames produce separate capsules. A ready-made sample config to model the config on is at test/py/tests/test_efi_capsule/sandbox_capsule_cfg.txt.

Unsigned multi-image capsule

Example using values reported by efidebug capsule images. The image-guid is what selects the target partition; set each image-index to the value the command reports for that component:
All three blocks use capsule: Unsigned.cap, so the tool packs all three payloads into that one file.

Signed multi-image capsule

First, generate a signing key and a self-signed public certificate with OpenSSL. The private key signs each payload; the certificate is embedded in the U-Boot image (see Enable authentication for signed capsules) and used on the board to verify the signature:
Then add private-key: / pub-key-cert: (and monotonic-count:) to each block, pointing at the key and certificate generated above:
Verifying a signed capsule on the board additionally requires the U-Boot image to be built with capsule authentication enabled and the matching public cert. See Enable authentication for signed capsules.

Generate the capsule

Run the tool from inside the board folder so the payload:/capsule: relative paths resolve:
For a multi-image config, the output is:
Verify the capsule structure by dumping its headers:
Confirm that EFI_FMP_HDR.PAYLOAD_ITEM_COUNT equals the payload count, and that each FMP_CAPSULE_IMAGE_HDR.UPDATE_IMAGE_TYPE_ID / UPDATE_IMAGE_INDEX matches the config. For a signed capsule, each payload additionally shows an EFI_FIRMWARE_IMAGE_AUTH block.

Enable authentication for signed capsules

Skip this section for unsigned capsules. The shipped board image already has EFI_CAPSULE_ON_DISK and EFI_CAPSULE_FIRMWARE_RAW enabled, so go straight to Get the capsule onto the ESP.
Signed capsules require capsule authentication in the U-Boot image, which isn’t enabled by default, so this must be done before applying the capsule:
  1. Clone the qualcomm-linux/u-boot repo and switch to qcom-next (skip if the checkout from Build the mkeficapsule tool already exists):
  2. Copy the generated public certificate (capsule_pub.crt) into the U-Boot tree, then add the capsule authentication options to the board’s defconfig (configs/<board>_defconfig, for example configs/qcom_lemans_defconfig), pointing CONFIG_EFI_CAPSULE_CRT_FILE at that certificate (path relative to the U-Boot tree):
  3. Build U-Boot (see U-Boot on Qualcomm Linux) and flash the resulting image to the board’s uefi partition.
A capsule signed with a key that doesn’t match the embedded cert is rejected at apply time.

Get the capsule onto the ESP

Place the .cap in \EFI\UpdateCapsule\ on the ESP. Use whatever transfer mechanism the board supports to copy the file there — for example, mount the ESP (mount /dev/disk/by-partlabel/efi /mnt/esp), create the EFI/UpdateCapsule directory if it doesn’t exist, and copy the capsule into it. Capsule-on-disk only runs when OsIndications has the bit EFI_OS_INDICATIONS_FILE_CAPSULE_DELIVERY_SUPPORTED (0x4) set. U-Boot (check_run_capsules() in lib/efi_loader/efi_capsule.c) clears the bit after applying, so re-arm before every apply. On the next boot, capsule-on-disk auto-discovers \EFI\UpdateCapsule\*.cap, applies every payload, clears the file, and clears the OsIndications bit — no U-Boot console command is needed to kick it off. Once the capsule is in place, arm the update from the kernel prompt and reboot:

Verify the result

After the apply boot, at the U-Boot console:
Confirm, per updated image, that fw_version advanced to the config’s fw-version and last_attempt_status = success.
Shows the per-capsule result code from the last apply.
Re-confirms the image set and reflects the updated versions.