1.. SPDX-License-Identifier: GPL-2.0+ 2.. Copyright (C) 2020, Linaro Limited 3 4Enabling UEFI Capsule Update feature 5------------------------------------ 6 7Support has been added for the UEFI capsule update feature which 8enables updating the U-Boot image using the UEFI firmware management 9protocol (fmp). The capsules are not passed to the firmware through 10the UpdateCapsule runtime service. Instead, capsule-on-disk 11functionality is used for fetching the capsule from the EFI System 12Partition (ESP) by placing the capsule file under the 13\EFI\UpdateCapsule directory. 14 15Currently, support has been added on the QEMU ARM64 virt platform for 16updating the U-Boot binary as a raw image when the platform is booted 17in non-secure mode, i.e. with CONFIG_TFABOOT disabled. For this 18configuration, the QEMU platform needs to be booted with 19'secure=off'. The U-Boot binary placed on the first bank of the NOR 20flash at offset 0x0. The U-Boot environment is placed on the second 21NOR flash bank at offset 0x4000000. 22 23The capsule update feature is enabled with the following configuration 24settings:: 25 26 CONFIG_MTD=y 27 CONFIG_FLASH_CFI_MTD=y 28 CONFIG_CMD_MTDPARTS=y 29 CONFIG_CMD_DFU=y 30 CONFIG_DFU_MTD=y 31 CONFIG_PCI_INIT_R=y 32 CONFIG_EFI_CAPSULE_ON_DISK=y 33 CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y 34 CONFIG_EFI_CAPSULE_FIRMWARE=y 35 CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y 36 CONFIG_EFI_CAPSULE_FMP_HEADER=y 37 38In addition, the following config needs to be disabled(QEMU ARM specific):: 39 40 CONFIG_TFABOOT 41 42The capsule file can be generated by using the GenerateCapsule.py 43script in EDKII:: 44 45 $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ 46 <capsule_file_name> --fw-version <val> --lsv <val> --guid \ 47 e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose --update-image-index \ 48 <val> --verbose <u-boot.bin> 49 50The above is a wrapper script(GenerateCapsule) which eventually calls 51the actual GenerateCapsule.py script. 52 53As per the UEFI specification, the capsule file needs to be placed on 54the EFI System Partition, under the \EFI\UpdateCapsule directory. The 55EFI System Partition can be a virtio-blk-device. 56 57Before initiating the firmware update, the efi variables BootNext, 58BootXXXX and OsIndications need to be set. The BootXXXX variable needs 59to be pointing to the EFI System Partition which contains the capsule 60file. The BootNext, BootXXXX and OsIndications variables can be set 61using the following commands:: 62 63 => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name> 64 => efidebug boot next 0 65 => setenv -e -nv -bs -rt -v OsIndications =0x04 66 => saveenv 67 68Finally, the capsule update can be initiated with the following 69command:: 70 71 => efidebug capsule disk-update 72 73The updated U-Boot image will be booted on subsequent boot. 74 75Enabling Capsule Authentication 76^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ 77 78The UEFI specification defines a way of authenticating the capsule to 79be updated by verifying the capsule signature. The capsule signature 80is computed and prepended to the capsule payload at the time of 81capsule generation. This signature is then verified by using the 82public key stored as part of the X509 certificate. This certificate is 83in the form of an efi signature list (esl) file, which is embedded as 84part of the platform's device tree blob using the mkeficapsule 85utility. 86 87On the QEMU virt platforms, the device-tree is generated on the fly 88based on the devices configured. This device tree is then passed on to 89the various software components booting on the platform, including 90U-Boot. Therefore, on the QEMU virt platform, the signatute is 91embedded on an overlay. This overlay is then applied at runtime to the 92base platform device-tree. Steps needed for embedding the esl file in 93the overlay are highlighted below. 94 95The capsule authentication feature can be enabled through the 96following config, in addition to the configs listed above for capsule 97update:: 98 99 CONFIG_EFI_CAPSULE_AUTHENTICATE=y 100 101The public and private keys used for the signing process are generated 102and used by the steps highlighted below:: 103 104 1. Install utility commands on your host 105 * OPENSSL 106 * efitools 107 108 2. Create signing keys and certificate files on your host 109 110 $ openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ \ 111 -keyout CRT.key -out CRT.crt -nodes -days 365 112 $ cert-to-efi-sig-list CRT.crt CRT.esl 113 114 $ openssl x509 -in CRT.crt -out CRT.cer -outform DER 115 $ openssl x509 -inform DER -in CRT.cer -outform PEM -out CRT.pub.pem 116 117 $ openssl pkcs12 -export -out CRT.pfx -inkey CRT.key -in CRT.crt 118 $ openssl pkcs12 -in CRT.pfx -nodes -out CRT.pem 119 120The capsule file can be generated by using the GenerateCapsule.py 121script in EDKII:: 122 123 $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ 124 <capsule_file_name> --monotonic-count <val> --fw-version \ 125 <val> --lsv <val> --guid \ 126 e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose \ 127 --update-image-index <val> --signer-private-cert \ 128 /path/to/CRT.pem --trusted-public-cert \ 129 /path/to/CRT.pub.pem --other-public-cert /path/to/CRT.pub.pem \ 130 <u-boot.bin> 131 132Place the capsule generated in the above step on the EFI System 133Partition under the EFI/UpdateCapsule directory 134 135For embedding the public key certificate, the following steps need to 136be followed:: 137 138 1. Generate a skeleton overlay dts file, with a single fragment 139 node and an empty __overlay__ node 140 141 A typical skeleton overlay file will look like this 142 143 /dts-v1/; 144 /plugin/; 145 146 / { 147 fragment@0 { 148 target-path = "/"; 149 __overlay__ { 150 }; 151 }; 152 }; 153 154 155 2. Convert the dts to a corresponding dtb with the following 156 command 157 ./scripts/dtc/dtc -@ -I dts -O dtb -o <ov_dtb_file_name> \ 158 <dts_file> 159 160 3. Run the dtb file generated above through the mkeficapsule tool 161 in U-Boot 162 ./tools/mkeficapsule -O <pub_key.esl> -D <ov_dtb> 163 164Running the above command results in the creation of a 'signature' 165node in the dtb, under which the public key is stored as a 166'capsule-key' property. The '-O' option is to be used since the 167public key certificate(esl) file is being embedded in an overlay. 168 169The dtb file embedded with the certificate is now to be placed on an 170EFI System Partition. This would then be loaded and "merged" with the 171base platform flattened device-tree(dtb) at runtime. 172 173Build U-Boot with the following steps(QEMU ARM64):: 174 175 $ make qemu_arm64_defconfig 176 $ make menuconfig 177 Disable CONFIG_TFABOOT 178 Enable CONFIG_EFI_CAPSULE_AUTHENTICATE 179 Enable all configs needed for capsule update(listed above) 180 $ make all 181 182Boot the platform and perform the following steps on the U-Boot 183command line:: 184 185 1. Enable capsule authentication by setting the following env 186 variable 187 188 => setenv capsule_authentication_enabled 1 189 => saveenv 190 191 2. Load the overlay dtb to memory and merge it with the base fdt 192 193 => fatload virtio 0:1 <$fdtovaddr> EFI/<ov_dtb_file> 194 => fdt addr $fdtcontroladdr 195 => fdt resize <size_of_ov_dtb_file> 196 => fdt apply <$fdtovaddr> 197 198 3. Set the following environment and UEFI boot variables 199 200 => setenv -e -nv -bs -rt -v OsIndications =0x04 201 => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name> 202 => efidebug boot next 0 203 => saveenv 204 205 4. Finally, the capsule update can be initiated with the following 206 command 207 208 => efidebug capsule disk-update 209 210On subsequent reboot, the platform should boot the updated U-Boot binary. 211