fix for rebuild of wolfboot check, change wolfhsm name to match convention, add depend on virtual/wolfssl

pull/174/head
JacobBarthelmeh 2026-09-01 10:05:42 -06:00
parent 8128ebd873
commit 4311e14978
6 changed files with 119 additions and 37 deletions

View File

@ -11,6 +11,13 @@ LIC_FILES_CHKSUM = "file://${COMMON_LICENSE_DIR}/GPL-3.0-only;md5=c79ff39f19dfec
inherit deploy
# Keep this recipe out of 'bitbake world'. It cannot build unattended: it
# needs a user-supplied WOLFBOOT_SIGNING_KEY, and KERNEL_PN below defaults to
# linux-xlnx, which makes world fail dependency resolution outright with
# "Nothing PROVIDES 'linux-xlnx'" on any non-Xilinx configuration. Build it
# explicitly, or pull it in from an image recipe.
EXCLUDE_FROM_WORLD = "1"
DEPENDS = "wolfboot-keytools-native"
# REQUIRED: absolute path to the same wolfBoot signing private key used by

View File

@ -45,25 +45,38 @@ SRCREV_wolfboot ?= "9a667f2a7527da2b8e490ae7923665321af2d3ac"
SRCREV_wolfssl ?= "1d363f3adceba9d1478230ede476a37b0dcdef24"
SRCREV_FORMAT = "${@'wolfboot' if d.getVar('WOLFBOOT_WOLFSSL_SRC') else 'wolfboot_wolfssl'}"
# Directories and file patterns the staging copy below leaves out. Kept in one
# place because the fingerprint must prune exactly what the copy prunes: a file
# that is skipped by the copy but hashed by the fingerprint (a stale .o from a
# native ./configure && make, say) would rebuild wolfBoot over a file that never
# reaches the build.
WOLFBOOT_WOLFSSL_EXCLUDE_DIRS = ".git .libs"
WOLFBOOT_WOLFSSL_EXCLUDE_GLOBS = "*.o *.lo *.a *.la *.so *.so.*"
def wolfboot_wolfssl_src_id(d):
"""Fingerprint the external wolfSSL tree: relative path, size and mtime of
every file. Fed into the task hashes below so that editing the tree rebuilds
wolfBoot. BitBake otherwise hashes only the WOLFBOOT_WOLFSSL_SRC *string*,
and changes to its contents would silently reuse a stale wolfboot.elf.
Returns '' (and costs nothing) when the feature is not in use."""
every file that do_stage_external_wolfssl would copy. Fed into the task
hashes below so that editing the tree rebuilds wolfBoot. BitBake otherwise
hashes only the WOLFBOOT_WOLFSSL_SRC *string*, and changes to its contents
would silently reuse a stale wolfboot.elf. Returns '' (and costs nothing)
when the feature is not in use."""
import os
import fnmatch
import hashlib
src = d.getVar('WOLFBOOT_WOLFSSL_SRC')
if not src or not os.path.isdir(src):
return ''
skip_dirs = (d.getVar('WOLFBOOT_WOLFSSL_EXCLUDE_DIRS') or '').split()
skip_globs = (d.getVar('WOLFBOOT_WOLFSSL_EXCLUDE_GLOBS') or '').split()
h = hashlib.sha256()
for root, dirs, files in os.walk(src):
# Same pruning as the copy below, so the fingerprint tracks exactly
# what gets staged.
dirs[:] = sorted(x for x in dirs if x not in ('.git', '.libs'))
dirs[:] = sorted(x for x in dirs if x not in skip_dirs)
for name in sorted(files):
if any(fnmatch.fnmatch(name, pat) for pat in skip_globs):
continue
path = os.path.join(root, name)
try:
st = os.lstat(path)
@ -74,7 +87,21 @@ def wolfboot_wolfssl_src_id(d):
h.update(entry.encode())
return h.hexdigest()
WOLFBOOT_WOLFSSL_SRC_ID = "${@wolfboot_wolfssl_src_id(d)}"
# The fingerprint has to be a plain string in the datastore, not a deferred
# ${@...} expansion: vardeps hashes a variable's *unexpanded* value, so
# "${@wolfboot_wolfssl_src_id(d)}" is a constant as far as the task hashes are
# concerned and editing the tree would never rebuild. Setting the value here
# puts the digest itself into the hash.
python () {
if d.getVar('WOLFBOOT_WOLFSSL_SRC'):
d.setVar('WOLFBOOT_WOLFSSL_SRC_ID', wolfboot_wolfssl_src_id(d))
}
# ...and the recipe must be re-parsed every time for that to be re-evaluated;
# a cached parse would keep serving the digest from whenever the tree was last
# looked at. Only when the feature is in use, so ordinary builds keep their
# parse cache.
BB_DONT_CACHE = "${@'1' if d.getVar('WOLFBOOT_WOLFSSL_SRC') else ''}"
python check_wolfboot_wolfssl_src() {
import os
@ -110,15 +137,38 @@ do_stage_external_wolfssl() {
# Two steps through an intermediate archive rather than tar|tar: a plain
# POSIX shell reports only the extract side of a pipeline, so a create
# side that died halfway (read error, vanished file) would go unnoticed
# and leave a silently incomplete tree. Run separately, each tar's exit
# status aborts the task.
# and leave a silently incomplete tree. Each tar is checked on its own so
# the failure names which half broke; letting 'set -e' abort the task here
# would report a bare ExecutionError and leave the intermediate archive
# (an entire wolfSSL tree's worth of it) behind in ${WORKDIR}.
#
# The exclusions come from the shared lists above so they cannot drift
# from what the fingerprint hashes. 'set -f' keeps the shell from
# expanding the *.o-style patterns against the current directory while
# they are being assembled into the argument list.
set -f
tar_excludes=""
for pat in ${WOLFBOOT_WOLFSSL_EXCLUDE_DIRS} ${WOLFBOOT_WOLFSSL_EXCLUDE_GLOBS}; do
tar_excludes="$tar_excludes --exclude=$pat"
done
rm -f "${WOLFBOOT_WOLFSSL_STAGED_SRC}.tar"
tar -cf "${WOLFBOOT_WOLFSSL_STAGED_SRC}.tar" -C "${WOLFBOOT_WOLFSSL_SRC}" \
--exclude=.git --exclude=.libs \
--exclude='*.o' --exclude='*.lo' --exclude='*.a' --exclude='*.la' \
--exclude='*.so' --exclude='*.so.*' \
.
tar -xf "${WOLFBOOT_WOLFSSL_STAGED_SRC}.tar" -C "${WOLFBOOT_WOLFSSL_STAGED_SRC}"
if ! tar -cf "${WOLFBOOT_WOLFSSL_STAGED_SRC}.tar" \
-C "${WOLFBOOT_WOLFSSL_SRC}" $tar_excludes . ; then
rm -f "${WOLFBOOT_WOLFSSL_STAGED_SRC}.tar"
set +f
bbfatal "Failed to archive WOLFBOOT_WOLFSSL_SRC='${WOLFBOOT_WOLFSSL_SRC}'." \
"The tree may be unreadable or changing underneath the build."
fi
if ! tar -xf "${WOLFBOOT_WOLFSSL_STAGED_SRC}.tar" \
-C "${WOLFBOOT_WOLFSSL_STAGED_SRC}" ; then
rm -f "${WOLFBOOT_WOLFSSL_STAGED_SRC}.tar"
set +f
bbfatal "Failed to unpack the staging copy of" \
"WOLFBOOT_WOLFSSL_SRC='${WOLFBOOT_WOLFSSL_SRC}' into" \
"${WOLFBOOT_WOLFSSL_STAGED_SRC}. Out of space in ${WORKDIR}?"
fi
set +f
rm -f "${WOLFBOOT_WOLFSSL_STAGED_SRC}.tar"
if [ ! -f "${WOLFBOOT_WOLFSSL_STAGED_SRC}/wolfcrypt/src/asn.c" ]; then

View File

@ -9,6 +9,12 @@ require wolfboot.inc
inherit deploy wolfssl-compatibility
# Keep this recipe out of 'bitbake world' for the same reason as
# wolfboot-signed-image.bb: do_compile requires a signing key pair that the
# user supplies out-of-band, so an unattended world build can only ever fail
# here. Build it explicitly, or pull it in from an image recipe.
EXCLUDE_FROM_WORLD = "1"
# Which config/examples/*.config template to build against. Override in
# local.conf / image recipe to target a different board or boot medium.
# Examples: zynqmp_sdcard.config, zynqmp.config (QSPI), versal_sdcard.config

View File

@ -7,7 +7,7 @@ the sysroot so other recipes can compile them into their own binaries.
| Recipe | Purpose |
|---|---|
| `wolfhsm_git.bb` | Stages `wolfhsm/` (headers), `src/` and the selected `port/` directories to `${datadir}/wolfhsm`, plus a `wolfhsm.mk` build fragment. Also installs the headers at `${includedir}/wolfhsm`. |
| `wolfhsm_1.5.0.bb` | Stages `wolfhsm/` (headers), `src/` and the selected `port/` directories to `${datadir}/wolfhsm`, plus a `wolfhsm.mk` build fragment. Also installs the headers at `${includedir}/wolfhsm`. |
## Why this stages source instead of building a library
@ -38,6 +38,22 @@ Your Makefile then compiles `$(WOLFHSM_DIR)/src/*.c` and
`$(WOLFHSM_DIR)/port/posix/*.c` with `-I$(WOLFHSM_DIR) -DWOLFHSM_CFG` and an
include path pointing at your own `wolfhsm_cfg.h`.
### wolfSSL requirements
`wolfhsm/wh_settings.h` includes `<wolfssl/options.h>` and the wolfCrypt
headers unless `WOLFHSM_CFG_NO_CRYPTO` is defined, so the recipe carries
`DEPENDS += "virtual/wolfssl"` and the headers are in your sysroot without you
asking for them. Two things it cannot do for you:
- wolfSSL must be configured with `--enable-cryptocb --enable-keygen`. Add
them in `local.conf`, e.g.
`EXTRA_OECONF:append:pn-wolfssl = " --enable-cryptocb --enable-keygen"`.
- Do not compile the staged sources with a strict `-std=c99` (or `-std=c90`);
use `-std=gnu99` or later. Worth stating because upstream's own
`examples/posix` Makefiles do exactly that
(`wh_posix_server` sets `-std=c99`, `wh_posix_client` sets `CSTD ?=
-std=c90`), so copying one of them verbatim into a recipe will not build.
Alternatively, include the staged fragment and use the variables it defines:
```make
@ -51,10 +67,10 @@ unchanged from a recipe sysroot, an SDK sysroot, or a plain copy.
## Selecting ports
wolfHSM ships ports for `posix`, `skeleton`, `microchip`, `infineon`,
`stmicro`, `renesas` and `ti`. Only `posix` is staged by default; staging all
of them would put a lot of unrelated vendor code in every sysroot. Override in
`local.conf` or a bbappend:
wolfHSM ships ports for `posix`, `skeleton`, `armv8m-tz`, `microchip`,
`infineon`, `stmicro`, `renesas` and `ti`. Only `posix` is staged by default;
staging all of them would put a lot of unrelated vendor code in every sysroot.
Override in `local.conf` or a bbappend:
```bitbake
WOLFHSM_PORTS = "posix infineon"
@ -92,12 +108,12 @@ TOOLCHAIN_TARGET_TASK:append = " wolfhsm-dev"
## Pinning
`SRCREV` is pinned in `wolfhsm.inc`. Override per-build with:
```bitbake
SRCREV:pn-wolfhsm = "<sha>"
```
`wolfhsm.inc` pins the release with `nobranch=1;rev=<sha>` in `SRC_URI`, the
same way the other recipes in this layer do, and the `.bb` filename carries
the matching version. To build a different revision, override the whole
`SRC_URI` from a bbappend rather than setting `SRCREV`, which has no effect
when the revision is given in the URL.
The snippets above use the colon override syntax of honister and later. On
sumo through hardknott, write them with underscores instead
(`RDEPENDS_${PN}-dev`, `TOOLCHAIN_TARGET_TASK_append`, `SRCREV_pn-wolfhsm`).
(`RDEPENDS_${PN}-dev`, `TOOLCHAIN_TARGET_TASK_append`).

View File

@ -10,11 +10,8 @@ SECTION = "libs"
LICENSE = "GPL-3.0-only"
LIC_FILES_CHKSUM = "file://LICENSE;md5=1ebbd3e34237af26da5dc08a4e440464"
# NOTE: pinned to a wolfSSL/wolfHSM main tip at the time of writing. Bump as
# upstream evolves. Downstream users can override via local.conf:
# SRCREV:pn-wolfhsm = "<sha>"
SRC_URI = "git://github.com/wolfSSL/wolfHSM.git;protocol=https;branch=main"
SRCREV ?= "4aeecb2c35686bd4daeb40b3537500d15a93aff9"
# Pinned to the wolfHSM release git tag.
SRC_URI = "git://github.com/wolfSSL/wolfHSM.git;nobranch=1;protocol=https;rev=dd3ff8835cfdac7b9bede42afe52e729a999f3d7"
# Newer releases (styhead+/wrynose) unpack into ${UNPACKDIR} and name the git
# checkout after the recipe; oe-core there rejects S = "${WORKDIR}/git"

View File

@ -25,6 +25,14 @@ compile in-tree; it does not build a library. See the note below."
require wolfhsm.inc
# wolfhsm/wh_settings.h includes <wolfssl/options.h> (and wolfcrypt headers
# below that) unless WOLFHSM_CFG_NO_CRYPTO is defined, so every consumer of
# the staged headers needs wolfSSL in the sysroot. Declared here rather than
# left to the consumer so that following README.md is enough. Consumers must
# still configure wolfSSL with --enable-cryptocb --enable-keygen, and must not
# compile with -std=c99; see README.md.
DEPENDS += "virtual/wolfssl"
# For wolfssl_varSet(): the package variables below have to be written with
# either ':' or '_' depending on the Yocto release, and this layer still
# supports both (LAYERSERIES_COMPAT reaches back to sumo).
@ -33,13 +41,11 @@ inherit wolfssl-compatibility
SRC_URI += "file://wolfhsm.mk"
# Which port/ directories to stage. wolfHSM ships ports for posix, skeleton,
# microchip, infineon, stmicro, renesas and ti; staging all of them would put
# a lot of unrelated vendor code in every sysroot. Override in local.conf or a
# bbappend, e.g. WOLFHSM_PORTS = "posix infineon".
# armv8m-tz, microchip, infineon, stmicro, renesas and ti; staging all of them
# would put a lot of unrelated vendor code in every sysroot. Override in
# local.conf or a bbappend, e.g. WOLFHSM_PORTS = "posix infineon".
WOLFHSM_PORTS ?= "posix"
PV = "1.4.0+git"
# file:// SRC_URI entries land in ${UNPACKDIR} on newer releases (styhead+)
# and straight in ${WORKDIR} on scarthgap and older, which don't define
# UNPACKDIR. Resolve wolfhsm.mk from whichever location this release uses.