1Measured Boot using a Discrete TPM (PoC) 2======================================== 3 4Measured Boot is the process of cryptographically measuring the code and 5critical data used at boot time, for example using a TPM, so that the 6security state can be attested later. 7 8The current implementation of the driver included in |TF-A| supports several 9backends and each has a different means to store the measurements. 10This section focuses on the Discrete TPM backend, which stores measurements 11in a PCR within the TPM. This backend can be paired with the `TCG event log`_ 12to provide attestation of the measurements stored in the event log. See 13details in :ref:`Measured Boot Design`. 14 15This section provides instructions to setup and build a proof of concept (PoC) 16that showcases the use of Measured Boot with a Discrete TPM interface. 17 18.. note:: 19 The instructions given in this document are meant to build a PoC to 20 show how Measured Boot on TF-A can interact with a Discrete TPM interface. 21 This PoC is platform specific, and uses a SPI based Discrete TPM, the 22 Raspberry Pi communicates with the TPM via a GPIO pin bit-banged SPI interface. 23 For other platforms, different may be required to interface with the hardware 24 (e.g., different hardware communication protocols) and different TPM interfaces 25 (e.g., |FIFO| vs |CRB|). 26 27Components 28~~~~~~~~~~ 29 30 - **Platform**: The PoC is developed on the Raspberry Pi 3 (rpi3), due to quick 31 driver development and the availability of GPIO pins to interface with a TPM 32 expansion module. Measured boot capabilities using the TCG Event Log are 33 ported to the Raspberry Pi 3 platform inside TF-A. This PoC specifically uses 34 the Raspberry Pi 3 Model B V1.2, but this PoC is compatible with other 35 Raspberry Pi 3 models. 36 37 - **Discrete TPM**: The TPM chip selected is a breakout board compatible with 38 the Raspberry Pi 3 GPIO pins. This PoC uses a |SPI| based LetsTrust TPM 39 breakout board equipped with a Infineon Optiga™ SLB 9670 TPM 2.0 chip. Link 40 to device: https://thepihut.com/products/letstrust-tpm-for-raspberry-pi 41 42 .. note:: 43 If you have another TPM breakout board that uses the same 44 Infineon Optiga™ SLB 9670 TPM 2.0 SPI based chip, it will also work. 45 Ensure that the correct GPIO pins are utilized on the Raspberry Pi 3 to 46 avoid communication issues, and possible hardware failures. 47 48 - **TF-A TPM Drivers**: To interface with a physical (Discrete) TPM chip in 49 TF-A, the PoC uses TF-A drivers that provide the command, interface, link, 50 and platform layers required to send and receive data to and from the TPM. 51 The drivers are located in TFA, and not in a |SP|, so that they may be used 52 in early stages such as BL2, and in some cases, BL1. The design of the TPM 53 Drivers is documented here: :ref:`Discrete TPM drivers`. 54 55 - **U-boot BL33**: This PoC showcases measured boot up to BL33, and for 56 simplicity uses a U-boot image for BL33, so that the image is measured and 57 loaded. Currently U-boot does not have Discrete TPM support for the 58 Raspberry Pi 3 platform so the boot flow ends here. 59 60 61Building the PoC for the Raspberry Pi 3 62~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 63 64**Build instructions for U-Boot.bin for Raspberry Pi 3.** 65 66First, the build requires a BL33 firmware image that can be packaged and measured 67by TF-A. 68 69U-boot can be built for the Raspberry Pi 3, but there are some changes to be made 70to allow the build to succeed. First Clone U-boot and enter the repo. 71 72.. code:: shell 73 74 git clone https://github.com/u-boot/u-boot.git 75 cd u-boot 76 77Now to switch to a specific tag ``v2024.04`` for testing purposes, and then build 78the defconfig labelled ``rpi_3_b_plus_defconfig``. 79 80.. code:: shell 81 82 git checkout tags/v2024.04 -b tfa_dtpm_poc 83 make CROSS_COMPILE=aarch64-linux-gnu- rpi_3_b_plus_defconfig 84 85Lastly open the ``.config`` and change ``CONFIG_TEXT_BASE`` and 86``CONFIG_SYS_UBOOT_START`` to ``0x11000000`` to match the BL33 starting point. 87 88.. code:: shell 89 90 vim .config 91 CONFIG_TEXT_BASE=0x11000000 92 CONFIG_SYS_UBOOT_START=0x11000000 93 94To build the u-boot binary, use the following command. 95 96.. code:: shell 97 98 make CROSS_COMPILE=aarch64-linux-gnu- -j$(nproc) 99 100**Build TF-A for Raspberry Pi 3 with Discrete TPM and Measured Boot.** 101 102Copy over the ``u-boot.bin`` file over to your TF-A working directory. 103 104.. code:: shell 105 106 cp /path/to/u-boot/build/u-boot.bin /path/to/tfa/u-boot.bin 107 108TF-A build command: 109 110.. code:: shell 111 112 CROSS_COMPILE=aarch64-linux-gnu- \ 113 make PLAT=rpi3 \ 114 RPI3_PRELOADED_DTB_BASE=0x200000 \ 115 BL33=u-boot.bin \ 116 SUPPORT_VFP=1 \ 117 DEBUG=0 \ 118 MEASURED_BOOT=1 \ 119 DISCRETE_TPM=1 \ 120 MBOOT_TPM_HASH_ALG=sha256 \ 121 TPM_INTERFACE=FIFO_SPI \ 122 LOG_LEVEL=40 \ 123 fip all 124 125This build command is similar to the one provided in the TF-A Raspberry Pi 3 126platform port, To learn more about the platform and its build options, visit 127:ref:`Raspberry Pi 3`. 128 129 - ``RPI3_PRELOADED_DTB_BASE`` is given a different address to accommodate the 130 larger BL1 and BL2 firmware sizes, this is to accommodate the TPM drivers 131 that are packaged in BL1 and BL2 for this PoC. 132 - ``BL33`` is the non trusted firmware, in this case the U-Boot binary built 133 earlier. 134 - ``SUPPORT_VFP`` is enabled, allows Vector Floating Point operations in EL3. 135 - ``MEASURED_BOOT`` is enabled to allow the Measured Boot flow. 136 - ``DISCRETE_TPM=1`` enables the build of Discrete TPM drivers. 137 - ``MBOOT_TPM_HASH_ALG=sha256`` sets the hash algorithm to sha256, this is 138 the only algorithm supported by both TF-A Measured Boot and the SLB 9670 139 TPM 2.0. 140 - ``TPM_INTERFACE=FIFO_SPI`` specifies the use of the FIFO SPI interface. 141 - ``LOG_LEVEL=40`` ensures that eventlog is printed at the end of BL1 and BL2. 142 143 144**Hardware Setup:** 145 146 - **TPM Connection**: Connect the LetsTrust TPM board to GPIO pins 17 - 26 on 147 the 40-pin GPIO header on the Raspberry Pi board. The 2x5 header of the TPM 148 module must be aligned to the pins in a specific orientation, match the 3v3 149 and RST pins from the TPM board to pins 17 and 18 respectively on the 150 Raspberry Pi 3 header. See `rpi3 pinout`_. 151 152 - **Serial Console**: Establish a serial connection to the Raspberry Pi 3 to 153 view serial output during the boot sequence. The GND, TXD, and RXD pins, 154 which are labelled 6, 8, and 10 on the Raspberry Pi 3 header respectively, 155 are the required pins to establish a serial connection. The recommended way 156 to connect to the board from another system is to use a USB to serial TTL 157 cable to output the serial console in a easy manner. 158 159 - **SD Card Setup**: Format a SD Card as ``FAT32`` with a default Raspbian 160 installation that is similar to the default Raspberry Pi 3 boot partition, 161 this partition will utilize the default files installed in the root 162 directory with Rasbian such as: 163 164 :: 165 166 bcm2710-rpi3-b.dtb 167 bootcode.bin 168 config.txt 169 fixup.dat 170 start.elf 171 172 Open ``config.txt`` and overwrite the file with the following lines: 173 174 :: 175 176 arm_64bit=1 177 disable_commandline_tags=2 178 enable_uart=1 179 armstub=armstub8.bin 180 device_tree_address=0x200000 181 device_tree_end=0x210000 182 183 These configurations are required to enable uart, enable 64bit mode, 184 use the build TF binary, and the modified rpi3 device tree address 185 and size. 186 187 Copy ``armstub8.bin`` from the TF-A build path to the root folder of the 188 SD card. 189 190 The SD Card is now ready to be booted. 191 192Running the PoC for the Raspberry Pi 3 193~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 194 195Insert the SD Card into the Raspberry Pi 3 SD card port and boot the system. 196 197To access the serial console output from the Raspberry Pi 3 you can either: 198 199 - Follow `instructions`_ to use PuTTY to connect to Raspberry Pi 3 serial console. 200 201 - Use the linux ``screen`` command: 202 203 .. code:: shell 204 205 screen /dev/ttyUSB0 115200 206 207Once booted the output from the serial console will look like this: 208 209.. code:: shell 210 211 Raspberry Pi Bootcode 212 213 Read File: config.txt, 153 214 215 Read File: start.elf, 2975040 (bytes) 216 217 Read File: fixup.dat, 7265 (bytes) 218 219 MESS:00:00:01.170422:0: brfs: File read: /mfs/sd/config.txt 220 MESS:00:00:01.174630:0: brfs: File read: 153 bytes 221 MESS:00:00:01.211473:0: HDMI0:EDID error reading EDID block 0 attempt 0 222 MESS:00:00:01.217639:0: HDMI0:EDID error reading EDID block 0 attempt 1 223 MESS:00:00:01.223977:0: HDMI0:EDID error reading EDID block 0 attempt 2 224 MESS:00:00:01.230313:0: HDMI0:EDID error reading EDID block 0 attempt 3 225 MESS:00:00:01.236650:0: HDMI0:EDID error reading EDID block 0 attempt 4 226 MESS:00:00:01.242987:0: HDMI0:EDID error reading EDID block 0 attempt 5 227 MESS:00:00:01.249324:0: HDMI0:EDID error reading EDID block 0 attempt 6 228 MESS:00:00:01.255660:0: HDMI0:EDID error reading EDID block 0 attempt 7 229 MESS:00:00:01.261997:0: HDMI0:EDID error reading EDID block 0 attempt 8 230 MESS:00:00:01.268334:0: HDMI0:EDID error reading EDID block 0 attempt 9 231 MESS:00:00:01.274429:0: HDMI0:EDID giving up on reading EDID block 0 232 MESS:00:00:01.282647:0: brfs: File read: /mfs/sd/config.txt 233 MESS:00:00:01.286929:0: gpioman: gpioman_get_pin_num: pin LEDS_PWR_OK not defined 234 MESS:00:00:01.487295:0: gpioman: gpioman_get_pin_num: pin DISPLAY_DSI_PORT not defined 235 MESS:00:00:01.494853:0: gpioman: gpioman_get_pin_num: pin LEDS_PWR_OK not defined 236 MESS:00:00:01.500763:0: *** Restart logging 237 MESS:00:00:01.504638:0: brfs: File read: 153 bytes 238 MESS:00:00:01.510139:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 0 239 MESS:00:00:01.517254:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 1 240 MESS:00:00:01.524112:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 2 241 MESS:00:00:01.530970:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 3 242 MESS:00:00:01.537826:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 4 243 MESS:00:00:01.544685:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 5 244 MESS:00:00:01.551543:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 6 245 MESS:00:00:01.558399:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 7 246 MESS:00:00:01.565258:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 8 247 MESS:00:00:01.572116:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 9 248 MESS:00:00:01.578730:0: hdmi: HDMI0:EDID giving up on reading EDID block 0 249 MESS:00:00:01.584634:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 0 250 MESS:00:00:01.592427:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 1 251 MESS:00:00:01.599286:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 2 252 MESS:00:00:01.606142:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 3 253 MESS:00:00:01.613001:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 4 254 MESS:00:00:01.619858:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 5 255 MESS:00:00:01.626717:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 6 256 MESS:00:00:01.633575:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 7 257 MESS:00:00:01.640431:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 8 258 MESS:00:00:01.647288:0: hdmi: HDMI0:EDID error reading EDID block 0 attempt 9 259 MESS:00:00:01.653905:0: hdmi: HDMI0:EDID giving up on reading EDID block 0 260 MESS:00:00:01.659769:0: hdmi: HDMI:hdmi_get_state is deprecated, use hdmi_get_display_state instead 261 MESS:00:00:01.668264:0: HDMI0: hdmi_pixel_encoding: 162000000 262 MESS:00:00:01.673988:0: vec: vec_middleware_power_on: vec_base: 0x7e806000 rev-id 0x00002708 @ vec: 0x7e806100 @ 0x00000420 enc: 0x7e806060 @ 0x00000220 cgmsae: 0x7e80605c @ 0x00000000 263 MESS:00:00:01.880234:0: dtb_file 'bcm2710-rpi-3-b.dtb' 264 MESS:00:00:01.889713:0: brfs: File read: /mfs/sd/bcm2710-rpi-3-b.dtb 265 MESS:00:00:01.894375:0: Loaded 'bcm2710-rpi-3-b.dtb' to 0x200000 size 0x7cb2 266 MESS:00:00:01.915761:0: brfs: File read: 31922 bytes 267 MESS:00:00:02.007202:0: brfs: File read: /mfs/sd/config.txt 268 MESS:00:00:02.017277:0: brfs: File read: 153 bytes 269 MESS:00:00:02.020772:0: Failed to open command line file 'cmdline.txt' 270 MESS:00:00:02.042302:0: gpioman: gpioman_get_pin_num: pin EMMC_ENABLE not defined 271 MESS:00:00:02.398066:0: kernel= 272 MESS:00:00:02.455255:0: brfs: File read: /mfs/sd/armstub8.bin 273 MESS:00:00:02.459284:0: Loaded 'armstub8.bin' to 0x0 size 0xdbe74 274 MESS:00:00:02.465109:0: No compatible kernel found 275 MESS:00:00:02.469610:0: Device tree loaded to 0x200000 (size 0x823f) 276 MESS:00:00:02.476805:0: uart: Set PL011 baud rate to 103448.300000 Hz 277 MESS:00:00:02.483381:0: uart: Baud rate change done... 278 MESS:00:00:02.486793:0: uart: Baud rateNOTICE: Booting Trusted Firmware 279 NOTICE: BL1: v2.11.0(release):v2.11.0-187-g0cb1ddc9c-dirty 280 NOTICE: BL1: Built : 10:57:10, Jul 9 2024 281 INFO: BL1: RAM 0x100ee000 - 0x100f9000 282 INFO: Using crypto library 'mbed TLS' 283 NOTICE: TPM Chip: vendor-id 0xd1, device-id 0x0, revision-id: 0x16 284 NOTICE: rpi3: Detected: Raspberry Pi 3 Model B (1GB, Sony, UK) [0x00a02082] 285 INFO: BL1: Loading BL2 286 INFO: Loading image id=1 at address 0x100b4000 287 INFO: Image id=1 loaded: 0x100b4000 - 0x100c0281 288 INFO: TCG_EfiSpecIDEvent: 289 INFO: PCRIndex : 0 290 INFO: EventType : 3 291 INFO: Digest : 00 292 INFO: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 293 INFO: : 00 00 00 294 INFO: EventSize : 33 295 INFO: Signature : Spec ID Event03 296 INFO: PlatformClass : 0 297 INFO: SpecVersion : 2.0.2 298 INFO: UintnSize : 1 299 INFO: NumberOfAlgorithms : 1 300 INFO: DigestSizes : 301 INFO: #0 AlgorithmId : SHA256 302 INFO: DigestSize : 32 303 INFO: VendorInfoSize : 0 304 INFO: PCR_Event2: 305 INFO: PCRIndex : 0 306 INFO: EventType : 3 307 INFO: Digests Count : 1 308 INFO: #0 AlgorithmId : SHA256 309 INFO: Digest : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 310 INFO: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 311 INFO: EventSize : 17 312 INFO: Signature : StartupLocality 313 INFO: StartupLocality : 0 314 INFO: PCR_Event2: 315 INFO: PCRIndex : 0 316 INFO: EventType : 1 317 INFO: Digests Count : 1 318 INFO: #0 AlgorithmId : SHA256 319 INFO: Digest : 55 11 51 d8 8b 7f 41 d3 18 16 f2 e8 80 bf 80 fa 320 INFO: : b4 03 6d 96 4c a0 0a 98 45 cf 25 2f 1e a9 09 3e 321 INFO: EventSize : 5 322 INFO: Event : BL_2 323 NOTICE: BL1: Booting BL2 324 INFO: Entry point address = 0x100b4000 325 INFO: SPSR = 0x3c5 326 NOTICE: BL2: v2.11.0(release):v2.11.0-187-g0cb1ddc9c-dirty 327 NOTICE: BL2: Built : 10:56:39, Jul 9 2024 328 INFO: Using crypto library 'mbed TLS' 329 NOTICE: TPM Chip: vendor-id 0xd1, device-id 0x0, revision-id: 0x16 330 INFO: BL2: Doing platform setup 331 INFO: BL2: Loading image id 3 332 INFO: Loading image id=3 at address 0x100e0000 333 INFO: Image id=3 loaded: 0x100e0000 - 0x100e706b 334 INFO: BL2: Loading image id 5 335 INFO: Loading image id=5 at address 0x11000000 336 INFO: Image id=5 loaded: 0x11000000 - 0x110a8ad8 337 INFO: TCG_EfiSpecIDEvent: 338 INFO: PCRIndex : 0 339 INFO: EventType : 3 340 INFO: Digest : 00 341 INFO: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 342 INFO: : 00 00 00 343 INFO: EventSize : 33 344 INFO: Signature : Spec ID Event03 345 INFO: PlatformClass : 0 346 INFO: SpecVersion : 2.0.2 347 INFO: UintnSize : 1 348 INFO: NumberOfAlgorithms : 1 349 INFO: DigestSizes : 350 INFO: #0 AlgorithmId : SHA256 351 INFO: DigestSize : 32 352 INFO: VendorInfoSize : 0 353 INFO: PCR_Event2: 354 INFO: PCRIndex : 0 355 INFO: EventType : 3 356 INFO: Digests Count : 1 357 INFO: #0 AlgorithmId : SHA256 358 INFO: Digest : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 359 INFO: : 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 360 INFO: EventSize : 17 361 INFO: Signature : StartupLocality 362 INFO: StartupLocality : 0 363 INFO: PCR_Event2: 364 INFO: PCRIndex : 0 365 INFO: EventType : 1 366 INFO: Digests Count : 1 367 INFO: #0 AlgorithmId : SHA256 368 INFO: Digest : 55 11 51 d8 8b 7f 41 d3 18 16 f2 e8 80 bf 80 fa 369 INFO: : b4 03 6d 96 4c a0 0a 98 45 cf 25 2f 1e a9 09 3e 370 INFO: EventSize : 5 371 INFO: Event : BL_2 372 INFO: PCR_Event2: 373 INFO: PCRIndex : 0 374 INFO: EventType : 1 375 INFO: Digests Count : 1 376 INFO: #0 AlgorithmId : SHA256 377 INFO: Digest : f3 00 5c ed a2 12 8b 76 b7 82 da c5 28 c3 02 52 378 INFO: : 19 e4 3a 82 f2 3c ab 1e 0d 78 84 9c b5 fe e2 4f 379 INFO: EventSize : 14 380 INFO: Event : SECURE_RT_EL3 381 INFO: PCR_Event2: 382 INFO: PCRIndex : 0 383 INFO: EventType : 1 384 INFO: Digests Count : 1 385 INFO: #0 AlgorithmId : SHA256 386 INFO: Digest : 90 28 81 42 12 b7 9b ca aa 0c 40 76 33 5a 69 71 387 INFO: : b6 19 2b 90 f2 d2 69 b8 de 8e 6d 05 4d c2 73 f9 388 INFO: EventSize : 6 389 INFO: Event : BL_33 390 NOTICE: BL1: Booting BL31 391 INFO: Entry point address = 0x100e0000 392 INFO: SPSR = 0x3cd 393 NOTICE: BL31: v2.11.0(release):v2.11.0-187-g0cb1ddc9c-dirty 394 NOTICE: BL31: Built : 10:56:58, Jul 9 2024 395 INFO: rpi3: Checking DTB... 396 INFO: rpi3: Reserved 0x10000000 - 0x10100000 in DTB 397 INFO: BL31: Initializing runtime services 398 INFO: BL31: Preparing for EL3 exit to normal world 399 INFO: Entry point address = 0x11000000 400 INFO: SPSR = 0x3c9 401 402 403 U-Boot 2024.04-g84314330-dirty (Apr 23 2024 - 15:41:54 -0500) 404 405 DRAM: 948 MiB 406 RPI 3 Model B (0xa02082) 407 Core: 68 devices, 14 uclasses, devicetree: embed 408 MMC: mmc@7e202000: 0, mmc@7e300000: 1 409 Loading Environment from FAT... OK 410 In: serial,usbkbd 411 Out: serial,vidconsole 412 Err: serial,vidconsole 413 Net: No ethernet found. 414 starting USB... 415 Bus usb@7e980000: USB DWC2 416 scanning bus usb@7e980000 for devices... 417 Error: smsc95xx_eth No valid MAC address found. 418 2 USB Device(s) found 419 scanning usb for storage devices... 0 Storage Device(s) found 420 Hit any key to stop autoboot: 2 1 0 421 Card did not respond to voltage select! : -110 422 No EFI system partition 423 No EFI system partition 424 Failed to persist EFI variables 425 No EFI system partition 426 Failed to persist EFI variables 427 No EFI system partition 428 Failed to persist EFI variables 429 Missing TPMv2 device for EFI_TCG_PROTOCOL 430 ** Booting bootflow '<NULL>' with efi_mgr 431 Loading Boot0000 'mmc 0' failed 432 EFI boot manager: Cannot load any image 433 Boot failed (err=-14) 434 Card did not respond to voltage select! : -110 435 No ethernet found. 436 No ethernet found. 437 U-Boot> 438 439 440Next steps for Discrete TPM and Measured Boot development 441~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ 442 443In order to automatically validate the workings of the Discrete TPM, the creation 444of test cases that compare the eventlog image hashes with what is stored in PCR0 445are a great way to test the core functionality of the Discrete TPM in Measured Boot. 446 447Development of Discrete TPM drivers such as a reference FIFO |I2C|, MMIO, and CRB 448drivers has not started, these drivers will allow a larger number of platform 449to use a Discrete TPM in TF-A. 450 451*Copyright (c) 2025, Arm Limited. All rights reserved.* 452 453.. _TCG event log: https://trustedcomputinggroup.org/resource/tcg-efi-platform-specification/ 454.. _rpi3 pinout: https://www.raspberrypi.com/documentation/computers/raspberry-pi.html#gpio 455.. _instructions: https://www.circuitbasics.com/use-putty-to-access-the-raspberry-pi-terminal-from-a-computer/ 456.. _workaround: https://github.com/mhomran/u-boot-rpi3-b-plus 457