To use this example project:
- Copy
.cproject
and.project
into the wolfBoot root. - From the Xilinx SDK Import wolfBoot using "Import" -> "Existing Projects into Workspace".
This project uses a BSP named standalone_bsp_0
, which must be configured to use "hypervisor guest" in the BSP configuration settings, which is edited by opening the platform.spr
file under "standalone on psa_cortexa53_0" -> "Board Support Package" -> "Modify BSP Settings".
This will enable the EL-1 support required with Bl31 (ARM Trusted Firmware). The BSP generates a include/bspconfig.h
, which should have these defines set:
#define EL1_NONSECURE 1
#define HYP_GUEST 1
You may need to adjust/add the following project settings under Properties -> C/C++ General:
-
Platform bspInclude path: "Paths and Symbols" -> "Includes" -> "GNU C" -> "Add" -> Workspace Path for platform (example:
/zcu102/export/zcu102/sw/zcu102/standalone_domain/bspinclude/include
). -
Platform BSP Library path: See "Library Paths" -> "Add" (example:
/zcu102/psu_cortexa53_0/standalone_domain/bsp/psu_cortexa53_0/lib
).
A build settings template for Zynq UltraScale+ can be found here ./config/examples/zynqmp.config
. This file can be copied to wolfBoot root as .config
for building from the command line.
$ cp ./config/examples/zynqmp.config .config
$ make keytools
These template settings are also in this .cproject
as preprocessor macros. These settings are loaded into the target.h.in
template by the wolfBoot make
. If not using the built-in make then the following defines will need to be manually created in target.h
:
#define WOLFBOOT_SECTOR_SIZE 0x20000
#define WOLFBOOT_PARTITION_BOOT_ADDRESS 0x800000
#define WOLFBOOT_LOAD_ADDRESS 0x10000000
#define WOLFBOOT_PARTITION_SIZE 0x2A00000
#define WOLFBOOT_PARTITION_UPDATE_ADDRESS 0x3A00000
#define WOLFBOOT_PARTITION_SWAP_ADDRESS 0x63E0000
#define WOLFBOOT_DTS_BOOT_ADDRESS 0x7E0000
#define WOLFBOOT_DTS_UPDATE_ADDRESS 0x39E0000
#define WOLFBOOT_LOAD_DTS_ADDRESS 0x11800000
The default .cproject build symbols are:
ARCH_AARCH64
ARCH_FLASH_OFFSET=0x0
CORTEX_A53
DEBUG_ZYNQ=1
EXT_FLASH=1
FILL_BYTE=0xFF
IMAGE_HEADER_SIZE=1024
MMU
NO_QNX
NO_XIP
PART_BOOT_EXT=1
PART_SWAP_EXT=1
PART_UPDATE_EXT=1
TARGET_zynq
WC_HASH_DATA_ALIGNMENT=8
WOLFBOOT_ARCH_AARCH64
WOLFBOOT_DUALBOOT
WOLFBOOT_ELF
WOLFBOOT_HASH_SHA3_384
WOLFBOOT_ORIGIN=0x0
WOLFBOOT_SHA_BLOCK_SIZE=4096
WOLFBOOT_SIGN_RSA4096
WOLFBOOT_UBOOT_LEGACY
Note: If not using Position Independent Code (PIC) the linker script ldscript.ld
must have the start address offset to match the WOLFBOOT_LOAD_ADDRESS
.
To enable ARM assembly speedups for SHA:
- Add these build symbols:
WOLFSSL_ARMASM
WOLFSSL_ARMASM_INLINE
- Add these compiler misc flags:
-mcpu=generic+crypto -mstrict-align -DWOLFSSL_AARCH64_NO_SQRMLSH
The keygen tool creates an RSA 4096-bit private key (wolfboot_signing_private_key.der
) and exports the public key to src/keystore.c
for wolfBoot to use at compile-time as the default root-of-trust.
$ ./tools/keytools/keygen --rsa4096 -g wolfboot_signing_private_key.der
Keytype: RSA4096
Generating key (type: RSA4096)
RSA public key len: 550 bytes
Associated key file: wolfboot_signing_private_key.der
Partition ids mask: ffffffff
Key type : RSA4096
Public key slot: 0
Done.
$ ./tools/keytools/sign --rsa4096 --sha3 ../hello_world/Debug/hello_world.elf ./wolfboot_signing_private_key.der 1
wolfBoot KeyTools (Compiled C version)
wolfBoot version 2020000
Update type: Firmware
Input image: ../hello_world/Debug/hello_world.elf
Selected cipher: RSA4096
Selected hash : SHA3
Public key: ./wolfboot_signing_private_key.der
Output image: ../hello_world/Debug/hello_world_v1_signed.bin
Target partition id : 1
Found RSA512 key
image header size calculated at runtime (1024 bytes)
Calculating SHA3 digest...
Signing the digest...
Output image(s) successfully created.
Xilinx uses a bootgen
tool for generating a boot binary image that has Xilinx headers, which the FSBL (First Stage Boot Loader) understands. See the boot.bif
and boot_auth.bif
as examples.
- Use "partition_owner=uboot" to prevent a partition from being loaded into RAM.
- Use "offset=" option to place the application into a specific location in flash.
- Use "load=" option to have FSBL load into specific location in RAM.
Default install locations for bootgen tools:
- Linux:
/tools/Xilinx/Vitis/2022.1/bin
- Windows:
C:\Xilinx\Vitis\2022.1\bin
Open the Vitis Shell from the IDE by using file menu "Xilinx" -> "Vitis Shell".
Generating a boot.bin (from boot.bif). Example boot.bif in workspace root:
// Boot BIF example for wolfBoot with signed Hello World
// Note: "partition_owner=uboot" prevents partition from being loaded to RAM
the_ROM_image:
{
[bootloader, destination_cpu=a53-0] zcu102\zynqmp_fsbl\fsbl_a53.elf
[destination_cpu=a53-0, exception_level=el-2] wolfboot\Debug\wolfboot.elf
[destination_cpu=a53-0, partition_owner=uboot, offset=0x800000] hello_world\Debug\hello_world_v1_signed.bin
}
You can also use exception level 3 or 1 depending on your needs.
From the workspace root:
bootgen -image boot.bif -arch zynqmp -w -o BOOT.bin
****** Xilinx Bootgen v2022.1
**** Build date : Apr 18 2022-16:02:32
** Copyright 1986-2022 Xilinx, Inc. All Rights Reserved.
[INFO] : Bootimage generated successfully
- QSPI: Flash using Vitis -> Xilinx (menu) -> Program Flash
- SD: or copy boot.bin to SDCARD
Boot Mode | MODE Pins 3:0 | Mode SW6[4:1] |
---|---|---|
JTAG | 0 0 0 0 | on, on, on, on |
QSPI32 | 0 0 1 0 | on, on, off,on |
SD | 1 1 1 0 | off,off,off,on |
wolfBoot Secure Boot
Read FlashID Lower: Ret 0, 20 BB 20
Read FlashID Upper: Ret 0, 20 BB 20
Versions: Boot 1, Update 0
Trying Boot partition at 800000
Boot partition: 800000 (size 226024, version 0x1)
info: LMS wolfBoot_verify_signature
info: using LMS parameters: L2-H5-W8
info: wc_LmsKey_Verify returned OK
Successfully selected image in part: 0
Firmware Valid
Loading flash image from 8014A8 to RAM at 10000000 (226024 bytes)
Loading elf at 10000000
Found valid elf64 (little endian)
Program Headers 2 (size 56)
Load 57536 bytes (offset 10000) to 0 (p 0)
Clear 20600 bytes at 0 (p 0)
Entry point 0
DTB boot partition: 7B0000
Failed parsing DTB to load
Booting at 0
Hello World
Successfully ran Hello World application
-
Generate keys:
bootgen.exe -generate_keys auth pem -arch zynqmp -image boot.bif
-
Create hash for primary key:
bootgen.exe -image boot.bif -arch zynqmp -w -o i BOOT.BIN -efuseppkbits ppkf_hash.txt
-
Import example project for programming eFuses:
- New BSP project (program efuses , ZCU102_hw_platform, standalone, CPU: PSU_cortexa53_0)
- Goto Xilinx Board Support Packet Settings.
- Scroll down to Supported Libraries and Check the xiskey library
- In the system.mss pane, scroll down to Libraries and click Import Examples.
- Check the xilskey_esfuseps_zynqmp_example
-
Edit
xilskey_efuseps_zynqmp_input.h
- 433
#define XSK_EFUSEPS_WRITE_PPK0_HASH TRUE
- 453
#define XSK_EFUSEPS_PPK0_IS_SHA3 TRUE
- 454 `#define XSK_EFUSEPS_PPK0_HASH "0000000000000000000000000000000000000000000000000000000000000000" /* from ppkf_hash.txt */``
- 433
-
Update boot.bif (see boot_auth.bif)
[auth_params] ppk_select=0; spk_id=0x00000000 [pskfile] pskf.pem [sskfile] sskf.pem authentication=rsa
-
Build “boot.bin” image:
bootgen -image boot.bif -arch zynqmp -o i BOOT.BIN -w
Note: To generate a report of a boot.bin use the bootgen_utility
or after 2022.1 use bootgen -read
:
bootgen -arch zynqmp -read BOOT.BIN
- Add these build symbols to the Xilinx project:
Note: Make sure and remove the existing
WOLFBOOT_SIGN_*
,WOLFBOOT_HASH_*
andIMAGE_HEADER_SIZE
WOLFBOOT_SIGN_XMSS
WOLFBOOT_HASH_SHA256
WOLFSSL_HAVE_XMSS
WOLFSSL_WC_XMSS
WOLFSSL_WC_XMSS_SMALL
WOLFBOOT_XMSS_PARAMS='\"XMSS-SHA2_10_256\"'
WOLFSSL_XMSS_VERIFY_ONLY
WOLFSSL_XMSS_MAX_HEIGHT=32
WOLFBOOT_SHA_BLOCK_SIZE=4096
IMAGE_SIGNATURE_SIZE=2500
XMSS_IMAGE_SIGNATURE_SIZE=2500
IMAGE_HEADER_SIZE=5000
- Create and sign image:
$ ./tools/keytools/keygen --xmss -g wolfboot_signing_private_key.der
Keytype: XMSS
Generating key (type: XMSS)
info: using XMSS parameters: XMSS-SHA2_10_256
Associated key file: wolfboot_signing_private_key.der
Partition ids mask: ffffffff
Key type : XMSS
Public key slot: 0
Done.
$ ./tools/keytools/sign --xmss ../hello_world/Debug/hello_world.elf wolfboot_signing_private_key.der 1
wolfBoot KeyTools (Compiled C version)
wolfBoot version 2020000
Update type: Firmware
Input image: ../hello_world/Debug/hello_world.elf
Selected cipher: XMSS
Selected hash : SHA256
Public key: wolfboot_signing_private_key.der
Output image: ../hello_world/Debug/hello_world_v1_signed.bin
Target partition id : 1
info: using XMSS parameters: XMSS-SHA2_10_256
info: XMSS signature size: 2500
info: xmss sk len: 1343
info: xmss pk len: 68
Found XMSS key
image header size calculated at runtime (5000 bytes)
Calculating SHA256 digest...
Signing the digest...
Output image(s) successfully created.
- Add these build symbols to the Xilinx project:
Note: Make sure and remove the existing
WOLFBOOT_SIGN_*
,WOLFBOOT_HASH_*
andIMAGE_HEADER_SIZE
WOLFBOOT_SIGN_LMS
WOLFBOOT_HASH_SHA256
WOLFSSL_HAVE_LMS
WOLFSSL_WC_LMS
WOLFSSL_WC_LMS_SMALL
WOLFSSL_LMS_VERIFY_ONLY
WOLFSSL_LMS_MAX_LEVELS=2
WOLFSSL_LMS_MAX_HEIGHT=5
LMS_LEVELS=2
LMS_HEIGHT=5
LMS_WINTERNITZ=8
IMAGE_SIGNATURE_SIZE=2644
IMAGE_HEADER_SIZE=5288
- Create and sign image:
$ ./tools/keytools/keygen --lms -g wolfboot_signing_private_key.der
Keytype: LMS
Generating key (type: LMS)
info: using LMS parameters: L2-H5-W8
Associated key file: wolfboot_signing_private_key.der
Partition ids mask: ffffffff
Key type : LMS
Public key slot: 0
Done.
$ ./tools/keytools/sign --lms ../hello_world/Debug/hello_world.elf wolfboot_signing_private_key.der 1
wolfBoot KeyTools (Compiled C version)
wolfBoot version 2020000
Update type: Firmware
Input image: ../hello_world/Debug/hello_world.elf
Selected cipher: LMS
Selected hash : SHA256
Public key: wolfboot_signing_private_key.der
Output image: ../hello_world/Debug/hello_world_v1_signed.bin
Target partition id : 1
info: using LMS parameters: L2-H5-W8
info: LMS signature size: 2644
Found LMS key
image header size calculated at runtime (5288 bytes)
Calculating SHA256 digest...
Signing the digest...
Output image(s) successfully created.
- ZAPP1319: Programming BBRAM and eFUSEs
- UG1283: Bootgen User Guide
- Using Cryptography in Zynq UltraScale MPSoC