On 30.12.20 14:57, Sughosh Ganu wrote: > Add documentation highlighting the steps for using the uefi capsule > update feature for updating the u-boot firmware image. > > Signed-off-by: Sughosh Ganu <sughosh.g...@linaro.org> > --- > > Changes since V3: None > > doc/board/emulation/index.rst | 1 + > doc/board/emulation/qemu_capsule_update.rst | 210 ++++++++++++++++++++ > 2 files changed, 211 insertions(+) > create mode 100644 doc/board/emulation/qemu_capsule_update.rst > > diff --git a/doc/board/emulation/index.rst b/doc/board/emulation/index.rst > index 1adefee155..a09ead1c35 100644 > --- a/doc/board/emulation/index.rst > +++ b/doc/board/emulation/index.rst > @@ -10,3 +10,4 @@ Emulation > qemu-mips > qemu-riscv > qemu-x86 > + qemu_capsule_update > diff --git a/doc/board/emulation/qemu_capsule_update.rst > b/doc/board/emulation/qemu_capsule_update.rst > new file mode 100644 > index 0000000000..9fec75f8f1 > --- /dev/null > +++ b/doc/board/emulation/qemu_capsule_update.rst > @@ -0,0 +1,210 @@ > +.. SPDX-License-Identifier: GPL-2.0+ > +.. Copyright (C) 2020, Linaro Limited > + > +Enabling UEFI Capsule Update feature > +------------------------------------ > + > +Support has been added for the UEFI capsule update feature which > +enables updating the U-Boot image using the UEFI firmware management > +protocol (fmp). The capsules are not passed to the firmware through > +the UpdateCapsule runtime service. Instead, capsule-on-disk > +functionality is used for fetching the capsule from the EFI System > +Partition (ESP) by placing the capsule file under the > +\EFI\UpdateCapsule directory. > + > +Currently, support has been added on the QEMU ARM64 virt platform for > +updating the U-Boot binary as a raw image when the platform is booted > +in non-secure mode, i.e. with CONFIG_TFABOOT disabled. For this > +configuration, the QEMU platform needs to be booted with > +'secure=off'. The U-Boot binary placed on the first bank of the NOR > +flash at offset 0x0. The U-Boot environment is placed on the second > +NOR flash bank at offset 0x4000000. > + > +The capsule update feature is enabled with the following configuration > +settings:: > + > + CONFIG_MTD=y > + CONFIG_FLASH_CFI_MTD=y > + CONFIG_CMD_MTDPARTS=y > + CONFIG_CMD_DFU=y > + CONFIG_DFU_MTD=y > + CONFIG_PCI_INIT_R=y > + CONFIG_EFI_CAPSULE_ON_DISK=y > + CONFIG_EFI_CAPSULE_FIRMWARE_MANAGEMENT=y > + CONFIG_EFI_CAPSULE_FIRMWARE=y > + CONFIG_EFI_CAPSULE_FIRMWARE_RAW=y > + CONFIG_EFI_CAPSULE_FMP_HEADER=y > + > +In addition, the following config needs to be disabled(QEMU ARM specific):: > + > + CONFIG_TFABOOT > + > +The capsule file can be generated by using the GenerateCapsule.py > +script in EDKII:: > + > + $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ > + <capsule_file_name> --fw-version <val> --lsv <val> --guid \ > + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose --update-image-index \ > + <val> --verbose <u-boot.bin> > + > +The above is a wrapper script(GenerateCapsule) which eventually calls > +the actual GenerateCapsule.py script. > + > +As per the UEFI specification, the capsule file needs to be placed on > +the EFI System Partition, under the \EFI\UpdateCapsule directory. The > +EFI System Partition can be a virtio-blk-device. > + > +Before initiating the firmware update, the efi variables BootNext, > +BootXXXX and OsIndications need to be set. The BootXXXX variable needs > +to be pointing to the EFI System Partition which contains the capsule > +file. The BootNext, BootXXXX and OsIndications variables can be set > +using the following commands:: > + > + => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name> > + => efidebug boot next 0 > + => setenv -e -nv -bs -rt -v OsIndications =0x04 > + => saveenv > + > +Finally, the capsule update can be initiated with the following > +command:: > + > + => efidebug capsule disk-update > + > +The updated U-Boot image will be booted on subsequent boot. > + > +Enabling Capsule Authentication > +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ > + > +The UEFI specification defines a way of authenticating the capsule to > +be updated by verifying the capsule signature. The capsule signature > +is computed and prepended to the capsule payload at the time of > +capsule generation. This signature is then verified by using the > +public key stored as part of the X509 certificate. This certificate is > +in the form of an efi signature list (esl) file, which is embedded as > +part of the platform's device tree blob using the mkeficapsule > +utility. > + > +On the QEMU virt platforms, the device-tree is generated on the fly > +based on the devices configured. This device tree is then passed on to > +the various software components booting on the platform, including > +U-Boot. Therefore, on the QEMU virt platform, the signatute is > +embedded on an overlay. This overlay is then applied at runtime to the > +base platform device-tree. Steps needed for embedding the esl file in > +the overlay are highlighted below. > + > +The capsule authentication feature can be enabled through the > +following config, in addition to the configs listed above for capsule > +update:: > + > + CONFIG_EFI_CAPSULE_AUTHENTICATE=y > + > +The public and private keys used for the signing process are generated > +and used by the steps highlighted below:: > + > + 1. Install utility commands on your host > + * OPENSSL > + * efitools > + > + 2. Create signing keys and certificate files on your host > + > + $ openssl req -x509 -sha256 -newkey rsa:2048 -subj /CN=CRT/ \ > + -keyout CRT.key -out CRT.crt -nodes -days 365 > + $ cert-to-efi-sig-list CRT.crt CRT.esl > + > + $ openssl x509 -in CRT.crt -out CRT.cer -outform DER > + $ openssl x509 -inform DER -in CRT.cer -outform PEM -out CRT.pub.pem > + > + $ openssl pkcs12 -export -out CRT.pfx -inkey CRT.key -in CRT.crt > + $ openssl pkcs12 -in CRT.pfx -nodes -out CRT.pem > + > +The capsule file can be generated by using the GenerateCapsule.py > +script in EDKII:: > + > + $ ./BaseTools/BinWrappers/PosixLike/GenerateCapsule -e -o \ > + <capsule_file_name> --monotonic-count <val> --fw-version \ > + <val> --lsv <val> --guid \ > + e2bb9c06-70e9-4b14-97a3-5a7913176e3f --verbose \ > + --update-image-index <val> --signer-private-cert \ > + /path/to/CRT.pem --trusted-public-cert \ > + /path/to/CRT.pub.pem --other-public-cert /path/to/CRT.pub.pem \ > + <u-boot.bin> > + > +Place the capsule generated in the above step on the EFI System > +Partition under the EFI/UpdateCapsule directory > + > +For embedding the public key certificate, the following steps need to > +be followed:: > + > + 1. Generate a skeleton overlay dts file, with a single fragment > + node and an empty __overlay__ node > + > + A typical skeleton overlay file will look like this > + > + /dts-v1/; > + /plugin/; > + > + / { > + fragment@0 { > + target-path = "/"; > + __overlay__ { > + }; > + }; > + }; > + > + > + 2. Convert the dts to a corresponding dtb with the following
Shouldn't this be dtbo? > + command > + ./scripts/dtc/dtc -@ -I dts -O dtb -o <ov_dtb_file_name> \ > + <dts_file> > + > + 3. Run the dtb file generated above through the mkeficapsule tool > + in U-Boot > + ./tools/mkeficapsule -O <pub_key.esl> -D <ov_dtb> > + > +Running the above command results in the creation of a 'signature' > +node in the dtb, under which the public key is stored as a > +'capsule-key' property. The '-O' option is to be used since the > +public key certificate(esl) file is being embedded in an overlay. > + > +The dtb file embedded with the certificate is now to be placed on an > +EFI System Partition. This would then be loaded and "merged" with the > +base platform flattened device-tree(dtb) at runtime. > + > +Build U-Boot with the following steps(QEMU ARM64):: > + > + $ make qemu_arm64_defconfig > + $ make menuconfig > + Disable CONFIG_TFABOOT > + Enable CONFIG_EFI_CAPSULE_AUTHENTICATE > + Enable all configs needed for capsule update(listed above) > + $ make all > + > +Boot the platform and perform the following steps on the U-Boot > +command line:: > + > + 1. Enable capsule authentication by setting the following env > + variable > + > + => setenv capsule_authentication_enabled 1 > + => saveenv > + > + 2. Load the overlay dtb to memory and merge it with the base fdt > + > + => fatload virtio 0:1 <$fdtovaddr> EFI/<ov_dtb_file> > + => fdt addr $fdtcontroladdr > + => fdt resize <size_of_ov_dtb_file> > + => fdt apply <$fdtovaddr> Having the public key on the disk means that any public key can be placed here and we get zero security. We need to build the public key into U-Boot. Could you, please, investigate how we can adjust the build process accordingly. Best regards Heinrich > + > + 3. Set the following environment and UEFI boot variables > + > + => setenv -e -nv -bs -rt -v OsIndications =0x04 > + => efidebug boot add 0 Boot0000 virtio 0:1 <capsule_file_name> > + => efidebug boot next 0 > + => saveenv > + > + 4. Finally, the capsule update can be initiated with the following > + command > + > + => efidebug capsule disk-update > + > +On subsequent reboot, the platform should boot the updated U-Boot binary. >