| .. SPDX-License-Identifier: GPL-2.0+ | |
| .. Copyright (c) 2022 Linaro Limited | |
| FWU Multi Bank Updates in U-Boot | |
| ================================ | |
| The FWU Multi Bank Update feature implements the firmware update | |
| mechanism described in the PSA Firmware Update for A-profile Arm | |
| Architecture specification [1]. Certain aspects of the Dependable | |
| Boot specification [2] are also implemented. The feature provides a | |
| mechanism to have multiple banks of updatable firmware images and for | |
| updating the firmware images on the non-booted bank. On a successful | |
| update, the platform boots from the updated bank on subsequent | |
| boot. The UEFI capsule-on-disk update feature is used for performing | |
| the actual updates of the updatable firmware images. | |
| The bookkeeping of the updatable images is done through a structure | |
| called metadata. Currently, the FWU metadata supports identification | |
| of images based on image GUIDs stored on a GPT partitioned storage | |
| media. There are plans to extend the metadata structure for non GPT | |
| partitioned devices as well. | |
| Accessing the FWU metadata is done through generic API's which are | |
| defined in a driver which complies with the U-Boot's driver model. A | |
| new uclass UCLASS_FWU_MDATA has been added for accessing the FWU | |
| metadata. Individual drivers can be added based on the type of storage | |
| media, and its partitioning method. Details of the storage device | |
| containing the FWU metadata partitions are specified through a U-Boot | |
| specific device tree property `fwu-mdata-store`. Please refer to | |
| U-Boot :download:`fwu-mdata-gpt.yaml | |
| </device-tree-bindings/firmware/fwu-mdata-gpt.yaml>` | |
| for the device tree bindings. | |
| Enabling the FWU Multi Bank Update feature | |
| ------------------------------------------ | |
| The feature can be enabled by specifying the following configs:: | |
| CONFIG_EFI_CAPSULE_ON_DISK=y | |
| CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y | |
| CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y | |
| CONFIG_FWU_MULTI_BANK_UPDATE=y | |
| CONFIG_FWU_MDATA=y | |
| CONFIG_FWU_MDATA_GPT_BLK=y | |
| CONFIG_FWU_NUM_BANKS=<val> | |
| CONFIG_FWU_NUM_IMAGES_PER_BANK=<val> | |
| CONFIG_FWU_MDATA_V1=y or CONFIG_FWU_MDATA_V2=y | |
| in the .config file | |
| By enabling the CONFIG_CMD_FWU_METADATA config option, the | |
| fwu_mdata_read command can be used to check the current state of the | |
| FWU metadata structure. | |
| The first group of configuration settings enable the UEFI | |
| capsule-on-disk update functionality. The second group of configs | |
| enable the FWU Multi Bank Update functionality. Please refer to the | |
| section :ref:`uefi_capsule_update_ref` for more details on generation | |
| of the UEFI capsule. | |
| FWU Metadata | |
| ------------ | |
| U-Boot supports both versions(1 and 2) of the FWU metadata defined in | |
| the two revisions of the specification. Support can be enabled for | |
| either of the two versions through a config flag. The mkfwumdata tool | |
| can generate metadata for both the supported versions. On the target side, | |
| the fwumdata tool can read and update FWU metadata located in memory, | |
| similarly to how fw_printenv/fw_setenv works. | |
| Setting up the device for GPT partitioned storage | |
| ------------------------------------------------- | |
| Before enabling the functionality in U-Boot, a GPT partitioned storage | |
| device is required. Assuming a GPT partitioned storage device, the | |
| storage media needs to be partitioned with the correct number of | |
| partitions, given the number of banks and number of images per bank | |
| that the platform is going to support. Each updatable firmware image | |
| will be stored on a separate partition. In addition, the two copies | |
| of the FWU metadata will be stored on two separate partitions. These | |
| partitions need to be created at the time of the platform's | |
| provisioning. | |
| As an example, a platform supporting two banks with each bank | |
| containing three images would need to have 2 * 3 = 6 partitions plus | |
| the two metadata partitions, or 8 partitions. In addition the storage | |
| media can have additional partitions of non-updatable images, like the | |
| EFI System Partition(ESP), a partition for the root file system | |
| etc. An example list of images on the storage medium would be | |
| * FWU metadata 1 | |
| * U-Boot 1 | |
| * OP-TEE 1 | |
| * FWU metadata 2 | |
| * OP-TEE 2 | |
| * U-Boot 2 | |
| * ESP | |
| * rootfs | |
| When generating the partitions, a few aspects need to be taken care | |
| of. Each GPT partition entry in the GPT header has two GUIDs:: | |
| * PartitionTypeGUID | |
| * UniquePartitionGUID | |
| The PartitionTypeGUID value should correspond to the | |
| ``image_type_guid`` field of the FWU metadata. This field is used to | |
| identify a given type of updatable firmware image, e.g. U-Boot, | |
| OP-TEE, FIP etc. This GUID should also be used for specifying the | |
| `--guid` parameter when generating the capsule. | |
| The UniquePartitionGUID value should correspond to the ``image_guid`` | |
| field in the FWU metadata. This GUID is used to identify images of a | |
| given image type in different banks. | |
| The FWU specification defines the GUID value to be used for the | |
| metadata partitions. This would be the PartitionTypeGUID for the | |
| metadata partitions. Similarly, the UEFI specification defines the ESP | |
| GUID to be be used. | |
| When generating the metadata, the ``image_type_guid`` and the | |
| ``image_guid`` values should match the *PartitionTypeGUID* and the | |
| *UniquePartitionGUID* values respectively. | |
| Performing the Update | |
| --------------------- | |
| Once the storage media has been partitioned and populated with the | |
| metadata partitions, the UEFI capsule-on-disk update functionality can | |
| be used for performing the update. Refer to the section | |
| :ref:`uefi_capsule_update_ref` for details on how the update can be | |
| invoked. | |
| On a successful update, the FWU metadata gets updated to reflect the | |
| bank from which the platform would be booting on subsequent boot. | |
| Based on the value of bit15 of the Flags member of the capsule header, | |
| the updated images would either be accepted by the U-Boot's UEFI | |
| implementation, or by the Operating System. If the Operating System is | |
| accepting the firmware images, it does so by generating an empty | |
| *accept* capsule. The Operating System can also reject the updated | |
| firmware by generating a *revert* capsule. The empty capsule can be | |
| applied by using the exact same procedure used for performing the | |
| capsule-on-disk update. | |
| The task of accepting the different firmware images, post an update | |
| may be done by multiple, separate components in the Operating | |
| System. To help identify the firmware image that is being accepted, | |
| the accept capsule passes the image GUID of the firmware image being | |
| accepted. The relevant code in U-Boot then sets the Accept bit of the | |
| corresponding firmware image for which the accept capsule was | |
| found. Only when all the firmware components in a bank have been | |
| accepted does the platform transition from trial state to regular | |
| state. | |
| The revert capsule on the other hand does not pass any image GUID, | |
| since reverting any image of the bank has the same result of the | |
| platform booting from the other bank on subsequent boot. | |
| In the scenario that bit15 of the Flags member of the capsule header | |
| has not been set, the images being updated are accepted by the | |
| U-Boot's UEFI firmware implementation by default, on successful | |
| update of the image. | |
| Generating an empty capsule | |
| --------------------------- | |
| The empty capsule can be generated using the mkeficapsule utility. To | |
| build the tool, enable:: | |
| CONFIG_TOOLS_MKEFICAPSULE=y | |
| Run the following commands to generate the accept/revert capsules: | |
| .. code-block:: bash | |
| $ ./tools/mkeficapsule \ | |
| [--fw-accept --guid <image guid>] | \ | |
| [--fw-revert] \ | |
| <capsule_file_name> | |
| Some examples of using the mkeficapsule tool for generation of the | |
| empty capsule would be: | |
| .. code-block:: bash | |
| $ ./tools/mkeficapsule --fw-accept --guid <image guid> \ | |
| <accept_capsule_name> | |
| $ ./tools/mkeficapsule --fw-revert <revert_capsule_name> | |
| Links | |
| ----- | |
| * [1] https://developer.arm.com/documentation/den0118/ - FWU Specification | |
| * [2] https://git.codelinaro.org/linaro/dependable-boot/mbfw/uploads/6f7ddfe3be24e18d4319e108a758d02e/mbfw.pdf - Dependable Boot Specification |