fix: correct recipe licenses to match upstream sources |
||
|---|---|---|
| .. | ||
| README.md | ||
| wolfboot-keytools-native_git.bb | ||
| wolfboot-signed-image.bb | ||
| wolfboot.inc | ||
| wolfboot_git.bb | ||
README.md
wolfBoot (Yocto/OE recipes)
Recipes that build wolfBoot, wolfSSL's portable secure bootloader, as part of a Yocto / OpenEmbedded image.
Recipes
| Recipe | Purpose |
|---|---|
wolfboot-keytools-native_git.bb |
Host-side wolfboot-keygen and wolfboot-sign utilities (key generation and image signing: RSA4096+SHA3-384 by default, ECC384+SHA-384 for the PolarFire config). |
wolfboot_git.bb |
Cross-compiles wolfboot.elf (bare-metal, AArch64 / AArch32 / RISC-V). Picks a config from ${S}/config/examples/ per the WOLFBOOT_CONFIG variable. Consumes a user-supplied signing key via WOLFBOOT_SIGNING_KEY (see "Signing-key provisioning" below). |
wolfboot-signed-image.bb |
Signs the kernel FIT image (default fitImage) with WOLFBOOT_SIGN_ALGO + WOLFBOOT_HASH_ALGO (RSA4096+SHA3-384 by default) and emits image_v${WOLFBOOT_IMAGE_VERSION}_signed.bin into DEPLOY_DIR_IMAGE. |
A companion recipes-bsp/bootbin/xilinx-bootbin_%.bbappend overrides the
AMD/Xilinx xilinx-bootbin recipe to swap U-Boot for wolfboot.elf in
BOOT.BIN on ZynqMP. It only activates when WOLFBOOT_ENABLE = "1" is
set in configuration (local.conf or a machine .conf).
Signing-key provisioning (required)
wolfboot_git.bb and wolfboot-signed-image.bb both require you to
supply a pre-generated private key via WOLFBOOT_SIGNING_KEY (RSA4096 by
default; ECC384 for the PolarFire config, see the PolarFire SoC quick start
below).
The recipes will not auto-generate one — that would leak the
private half through sstate and DEPLOY_DIR_IMAGE.
Generate the key pair once on your workstation:
# One-time host-side build of the keytools (outside Yocto):
make -C /path/to/wolfBoot/tools/keytools keygen sign
# Generate the RSA4096 key pair:
/path/to/wolfBoot/tools/keytools/keygen --rsa4096 \
-g /secure/path/wolfboot_signing_private_key.der
Store wolfboot_signing_private_key.der outside the build tree — a
secrets manager, an encrypted volume, or at minimum a .gitignored
directory. Back it up: losing the private key means you can never sign
another A/B update image that your deployed wolfboot.elf will accept.
Quick start (AMD/Xilinx ZynqMP, SD-card boot)
Set the following in local.conf (or a machine .conf). These must live
in configuration, not inside an image recipe: the xilinx-bootbin
bbappend reads WOLFBOOT_ENABLE at parse time, which runs before any
image recipe is evaluated.
# Activate the xilinx-bootbin bbappend (swap U-Boot for wolfBoot in BOOT.BIN)
WOLFBOOT_ENABLE = "1"
# Ensure the signed FIT image is built alongside the image.
EXTRA_IMAGEDEPENDS:append = " wolfboot-signed-image"
# REQUIRED: absolute path to the pre-generated signing private key.
WOLFBOOT_SIGNING_KEY = "/secure/path/wolfboot_signing_private_key.der"
# Pick a config template from wolfBoot/config/examples/
WOLFBOOT_CONFIG = "zynqmp_sdcard.config"
# Override the Linux rootfs partition in the DTB bootargs fixup.
# Default in the ZynqMP SD-card example is /dev/mmcblk0p4.
WOLFBOOT_LINUX_BOOTARGS_ROOT = "/dev/mmcblk0p4"
# Bump to "2" for A/B update images, etc.
WOLFBOOT_IMAGE_VERSION = "1"
Build:
bitbake <your-image>
Artifacts deployed to tmp/deploy/images/<MACHINE>/:
BOOT.BIN- FSBL + PMUFW + ATF + wolfBoot.elfwolfboot.elf- bare-metal bootloaderwolfboot_signing_public_key.der- verifying key (safe to publish; only ifWOLFBOOT_PUBLIC_KEYis set)image_v1_signed.bin- signed FIT image (for OFP_A partition)
Note: the private signing key is not deployed — it stays on the
workstation / secrets store you pointed WOLFBOOT_SIGNING_KEY at.
Quick start (Microchip PolarFire SoC, standalone M-mode, SD-card boot)
On PolarFire SoC wolfBoot can replace the Hart Software Services (HSS) entirely: it boots from eNVM on the E51, initialises the PLL and LPDDR4, loads a signed Linux FIT from the SD card and hands off to S-mode (polarfire_mpfs250_m.config). The eNVM image is programmed with Microchip's mpfsBootmodeProgrammer, so the recipe deploys wolfboot.elf and leaves the eNVM programming to the user.
Three things differ from the ZynqMP flow:
- The M-mode build needs the Libero design's
fpga_design_configheader directory (DDR, clock and SEG settings). Pass it throughWOLFBOOT_EXTRA_MAKE_FLAGS; the build has no way to generate it. - The PolarFire example config signs with ECC384 / SHA-384, so the signing key is an ECC384 pair from
wolfboot-keygen --ecc384 -g <key>.der. The private file keygen writes isQx || Qy || d; the public half forWOLFBOOT_PUBLIC_KEYis its first 96 bytes (head -c 96 <key>.der > <pub>.der), whichkeygen -ireads as a raw public key. - Partitions 1 and 2 of the SD card are the raw A/B slots (
BOOT_PART_A = 0,BOOT_PART_B = 1);files/wic/mpfs-wolfboot.wksfills slot A with the signed FIT, leaves slot B empty, keeps the rootfs at partition 3 and moves the BSP's GUID-tagged HSS payload to partition 4, so the same card still boots under HSS + U-Boot if the eNVM is reprogrammed. - The PolarFire config is in wolfBoot v2.10.0 and later, and the link flags the recipe adds need wolfBoot's
LDFLAGS_EXTRA(wolfSSL/wolfBoot#921; on older revisions the recipe falls back toCCandLDoverrides). PointSRCREV_wolfbootat a revision with both, as shown below.
WOLFBOOT_CONFIG = "polarfire_mpfs250_m.config"
WOLFBOOT_SIGNING_KEY = "/secure/path/wolfboot_signing_private_key.der"
WOLFBOOT_PUBLIC_KEY = "/secure/path/wolfboot_signing_public_key.der"
WOLFBOOT_EXTRA_MAKE_FLAGS = "LIBERO_FPGA_CONFIG_DIR=/path/to/boards/mpfs-video-kit/fpga_design_config"
# The M-mode image is soft-float lp64; the Linux toolchain's libgcc is lp64d
# and cannot be linked, and wolfBoot needs nothing from it on this target.
WOLFBOOT_NOSTDLIB = "1"
# The Microchip BSP builds its FIT with a gzip-compressed kernel.
WOLFBOOT_EXTRA_CONFIG_LINES = "GZIP=1"
# Match the config's SIGN / HASH.
WOLFBOOT_SIGN_ALGO = "ecc384"
WOLFBOOT_HASH_ALGO = "sha384"
KERNEL_PN:pn-wolfboot-signed-image = "linux-mchp"
EXTRA_IMAGEDEPENDS:append = " wolfboot wolfboot-signed-image"
WKS_FILE = "mpfs-wolfboot.wks"
WKS_FILE_DEPENDS:append = " wolfboot-signed-image"
# Releases before wrynose search <layer>/wic, not <layer>/files/wic, for .wks files.
WKS_SEARCH_PATH:prepend = "${WOLFSSL_LAYERDIR}/files/wic:"
Build with MACHINE=mpfs-video-kit bitbake mchp-base-image. The .wic is written to the SD card as-is; wolfboot.elf goes to eNVM with mpfsBootmodeProgrammer.jar --bootmode 1.
To build a wolfBoot branch that is not on wolfssl/wolfBoot master, point the fetcher at it instead of editing the recipe:
WOLFBOOT_GIT_URI = "git://github.com/<fork>/wolfBoot.git;protocol=https"
WOLFBOOT_GIT_BRANCH = "<branch>"
SRCREV_wolfboot = "<full commit sha on that branch>"
SRCREV_wolfssl = "<the branch's lib/wolfssl submodule commit>"
Using an existing wolfSSL source tree
By default wolfboot.inc fetches a pinned wolfSSL (SRCREV_wolfssl) into
lib/wolfssl alongside wolfBoot. To build wolfCrypt from a tree you already
have instead, set an absolute path in local.conf:
WOLFBOOT_WOLFSSL_SRC = "/path/to/wolfssl"
This drops the wolfSSL entry from SRC_URI entirely — nothing is downloaded
and SRCREV_wolfssl is unused. Both wolfboot_git.bb and
wolfboot-keytools-native_git.bb pick it up, so the bootloader and the
signing tools stay on one wolfCrypt version.
Things worth knowing:
- It is a source tree, not a library. wolfBoot compiles the wolfCrypt
sources into a
-nostdlibbare-metal image; it cannot link the targetlibwolfssl.sothat thewolfsslrecipe builds. Point this at wolfSSL sources. - The tree is copied into
${WORKDIR}before use, by thedo_stage_external_wolfssltask. wolfBoot writes its object files next to the wolfCrypt sources, so an in-place build would dirty your tree. The original may therefore be read-only or shared, but the copy is a full one — prefer a clean source tree over a working directory with a large.gitand build output in it. - Prebuilt objects are excluded from that copy (
*.o,*.a,*.lo,*.la,*.so*,.libs,.git). Without this, a natively configured tree (./configure && make) would hand the cross build host x86 objects thatmakeconsiders newer than their sources. - Changes to the tree do trigger a rebuild. The recipe fingerprints every
file's path, size and mtime into the task hashes, since BitBake would
otherwise hash only the
WOLFBOOT_WOLFSSL_SRCstring and happily reuse a stalewolfboot.elf. - The path must be absolute. wolfBoot's
MakefileabspathsWOLFBOOT_LIB_WOLFSSLonly for its own default; a command-line override — how the recipe passes it — reaches every sub-makefile verbatim. The recipe rejects relative paths rather than let them resolve against whichever directory each sub-make runs in.
SD card layout (wolfBoot A/B scheme)
| Partition | Size | Type | Contents |
|---|---|---|---|
| p1 | 128 MB | FAT32 | BOOT.BIN |
| p2 | 200 MB | raw | image_v1_signed.bin (OFP_A = primary) |
| p3 | 200 MB | raw | update slot (OFP_B) |
| p4 | rest | ext4 | Linux rootfs |
See wolfBoot/tools/scripts/ for helper scripts to create the SD card
and flash update images (once upstreamed).
Key management
The signing key pair is user-supplied, not generated inside the build.
WOLFBOOT_SIGNING_KEY must point at a pre-generated RSA4096 private key
file (DER format) — see the "Signing-key provisioning" section at the top
of this README. The recipe:
- Stages the private key at
${S}/wolfboot_signing_private_key.derso the wolfBoot Makefile can derive the public half and compile it intowolfboot.elfviasrc/keystore.c. - Does not deploy the private key to
DEPLOY_DIR_IMAGE. Onlywolfboot.elf(and optionally the public key, ifWOLFBOOT_PUBLIC_KEYis set) is deployed. wolfboot-signed-image.bbreads the sameWOLFBOOT_SIGNING_KEYdirectly to sign the FIT, so there is no on-disk hand-off of the private key between recipes.
To rotate keys:
- Generate a new RSA4096 key pair with
wolfboot-keygen --rsa4096 -g …. Prefer a new filename/path for each rotation (e.g.wolfboot_signing_private_key_v2.der) rather than overwriting the existing.derin place — see the caveat below. - Update
WOLFBOOT_SIGNING_KEYto the new private key path. - Build:
wolfboot.elfembeds the new public key, andimage_v<N>_signed.binis signed with the new private key. - Flash the new
BOOT.BIN(contains newwolfboot.elf) to the device, followed by a signed update image signed with the new key.
sstate caveat. WOLFBOOT_SIGNING_KEY points at an absolute path
outside the recipe tree, so BitBake does not checksum the key file's
contents into the task hash — only the path string participates. If you
overwrite the same .der file in place with new key material, sstate
and stamps may reuse the previously-built wolfboot.elf and signed
image, leaving you with a mismatched public/private pair. To stay safe:
- Preferred: rotate to a new filename/path. Changing the value of
WOLFBOOT_SIGNING_KEYinvalidates the task hash naturally. - Fallback (if you must reuse the same path): force a rebuild with
bitbake -c cleansstate wolfboot wolfboot-signed-imagebefore the nextbitbake <your-image>.
Swapping U-Boot for wolfBoot
The recipes-bsp/bootbin/xilinx-bootbin_%.bbappend rewrites the BIF so
BOOT.BIN contains wolfboot.elf instead of u-boot.elf at EL2, and
drops the standalone DTB partition (wolfBoot loads the DTB out of the
signed FIT image). It activates only when WOLFBOOT_ENABLE = "1" is set
in configuration (local.conf or a machine .conf). Setting it inside
an image recipe is not sufficient: the bbappend's anonymous python
runs at parse time, before image recipes are evaluated.
ZynqMP caveats
See the comments in wolfBoot/config/examples/zynqmp_sdcard.config for
two non-obvious points:
-
Root device: when the XSA disables
sdhci0(common on ZCU102 boards where only the external SD slot is populated), SD1 enumerates as/dev/mmcblk0, not/dev/mmcblk1. The template default ismmcblk0p4; flip tommcblk1p4only if both sdhci0 + sdhci1 are enabled. Controlled viaWOLFBOOT_LINUX_BOOTARGS_ROOT. -
BOOT_EL1:
BOOT_EL1?=1in the example is currently inert on ZynqMP becauseEL2_HYPERVISORis defined inhal/zynq.h(included bysrc/boot_aarch64_start.S) but not insrc/boot_aarch64.c. wolfBoot stays at EL2 before jumping to Linux, which matches standard PetaLinux U-Boot behavior. See the comments in the template.
Future work
PROVIDES += "virtual/bootloader"— On vanilla Yocto where U-Boot is the sole bootloader,PREFERRED_PROVIDER_virtual/bootloader = "wolfboot"would be a cleaner selector thanWOLFBOOT_ENABLE = "1"plus thexilinx-bootbinbbappend. We deliberately do not declare that PROVIDES yet, because on AMD/Xilinx ZynqMP — the only target this layer has been validated against — it does not actually simplify the integration:xilinx-bootbinreferences U-Boot by PN (u-boot-xlnx) inside its BIF generation rather than going throughvirtual/bootloader, andIMAGE_BOOT_FILESlists U-Boot artifacts by literal name. The current bbappend rewrites the BIF entry surgically; that swap would still be required regardless of who providesvirtual/bootloader. The right time to add this PROVIDES is when a non-Xilinx BSP integration lands, so the contract can be tested end-to-end.