blob: 9fec75f8f1c9ab76c47317c6a2073ed2e4c259ac [file] [log] [blame]
Sughosh Ganuf4d15942020-12-30 19:27:12 +05301.. 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.