Skip to content

Commit a7f00a2

Browse files
committed
Add Altera Agilex 5 SDM support via libfcs and alterafcs PACKAGECONFIG
1 parent 5ed8935 commit a7f00a2

7 files changed

Lines changed: 372 additions & 1 deletion

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -784,7 +784,7 @@ This repository contains additional README files with detailed information:
784784
- [recipes-connectivity/README.md](recipes-connectivity/README.md) - BIND,
785785
OpenSSH, Socat
786786
- [recipes-support/README.md](recipes-support/README.md) - curl, libssh2,
787-
strongSwan, tcpdump
787+
strongSwan, tcpdump, libfcs (Altera Agilex 5 SDM)
788788
- [recipes-protocols/README.md](recipes-protocols/README.md) - net-snmp
789789
- [recipes-extended/README.md](recipes-extended/README.md) - rsyslog
790790

conf/layer.conf

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,6 +55,10 @@ BBFILES += "${LAYERDIR}/recipes-wolfssl/wolfssl/*.bb \
5555
# xilinx-bootbin bbappend requires meta-xilinx-tools layer
5656
BBFILES_DYNAMIC += "xilinx-tools:${LAYERDIR}/recipes-bsp/bootbin/*.bbappend"
5757

58+
# Enable with WOLFSSL_ALTERA_FCS = "1" in the build configuration.
59+
WOLFSSL_ALTERA_FCS ?= "0"
60+
BBFILES += "${@'${LAYERDIR}/recipes-support/libfcs/*.bb ${LAYERDIR}/recipes-support/libfcs/*.bbappend' if d.getVar('WOLFSSL_ALTERA_FCS') == '1' else ''}"
61+
5862
# Uncomment if building bind with wolfSSL.
5963
#BBFILES += "${LAYERDIR}/recipes-connectivity/bind/*.bbappend"
6064

recipes-support/README.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,3 +86,9 @@ Zeus, Dunfell, and Gatesgarth
8686
8787
Then just compile the image that use's `tcpdumb` and include the `wolfSSL`
8888
package or preform `bitbake tcpdumb`
89+
90+
libfcs (Altera Agilex 5 SDM crypto)
91+
-----
92+
93+
See [libfcs/agilex5/README.md](libfcs/agilex5/README.md) for the complete
94+
Agilex 5 integration, image deployment, and on-target test procedure.
Lines changed: 279 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,279 @@
1+
# wolfSSL FCS offload on Altera Agilex 5
2+
3+
This guide builds wolfSSL with Secure Device Manager crypto offload, includes
4+
the result in an Agilex 5 Linux image, deploys that image, and verifies the
5+
packaged wolfCrypt test on the board.
6+
7+
## Prerequisites
8+
9+
- An Agilex 5 GSRD Yocto build configured for the exact board and release.
10+
- This `meta-wolfssl` layer in `BBLAYERS`.
11+
- A kernel exposing `/sys/kernel/fcs_sysfs`.
12+
- An owner root key hash provisioned in the SDM.
13+
14+
Provisioning is outside this layer's scope. Follow Altera's device-security
15+
procedure and distinguish recoverable virtual-key programming from permanent
16+
eFuse programming before changing a board. A virtual owner key is cleared when
17+
the board loses power and must be reapplied before each cold-boot test. Once an
18+
owner key is active, boot and FPGA configuration artifacts must be signed by
19+
that owner.
20+
21+
Run BitBake on a Linux build server with the memory and storage required by the
22+
GSRD release. Do not run BitBake on the target board.
23+
24+
The 26.1 GSRD source and board-specific build instructions are published in
25+
Altera's
26+
[DK-A5E013BM16AEA GSRD guide](https://altera-fpga.github.io/rel-26.1/embedded-designs/agilex-5/e-series/013B/gsrd/ug-gsrd-agx5e-013b/).
27+
Install `python3-venv` and Kas as described there. If the build server cannot
28+
install Python packages, the official Kas container is an alternative:
29+
30+
```sh
31+
docker pull ghcr.io/siemens/kas/kas:4.8
32+
```
33+
34+
The 26.1 GSRD kernel append uses Bash conditionals in a BitBake task that runs
35+
under `/bin/sh`. Make those conditionals portable before building:
36+
37+
```sh
38+
sed -i \
39+
-e 's/if \[\[/if [/g' \
40+
-e 's/\]\]; then/]; then/g' \
41+
-e 's/" == "/" = "/g' \
42+
meta-altera-fpga/meta-altera-bsp/recipes-kernel/linux/\
43+
linux-socfpga-lts_%.bbappend
44+
```
45+
46+
Without this correction, `linux-socfpga-lts:do_deploy` reports `[[: not
47+
found` and selects a nonexistent `fit_agilex5_kernel_no_rbf.its` file.
48+
49+
## Add the layer to an Agilex 5 GSRD build
50+
51+
The 26.1 GSRD for the DK-A5E013BM16AEA uses Kas. Add `meta-wolfssl` to the
52+
GSRD `kas.yml` or to a Kas configuration fragment:
53+
54+
```yaml
55+
header:
56+
version: 17
57+
58+
repos:
59+
meta-wolfssl:
60+
url: https://github.com/wolfSSL/meta-wolfssl.git
61+
branch: master
62+
layers:
63+
.:
64+
65+
local_conf_header:
66+
wolfssl-altera-fcs: |
67+
WOLFSSL_ALTERA_FCS = "1"
68+
WOLFSSL_FCS_PROVIDER = "gsrd-intel-fcs-lib"
69+
IMAGE_INSTALL:append = " wolfssl wolfcrypttest wolfcryptbenchmark "
70+
```
71+
72+
Save the fragment as `wolfssl-fcs.yml`. Kas configurations can be combined
73+
without changing the GSRD's supplied `kas.yml`.
74+
75+
For a local `meta-wolfssl` checkout under the GSRD Yocto directory, replace the
76+
repository URL and branch with:
77+
78+
```yaml
79+
meta-wolfssl:
80+
path: meta-wolfssl
81+
layers:
82+
.:
83+
```
84+
85+
The 26.1 GSRD already provides the required headers and versioned runtime
86+
library through `gsrd-intel-fcs-lib`. This layer adds the unversioned
87+
`libFCS.so` linker name required by dependent recipes. Selecting the GSRD
88+
provider prevents two recipes from installing the same library. A non-GSRD
89+
build can omit the override and use meta-wolfssl's `libfcs` recipe instead.
90+
91+
```bitbake
92+
WOLFSSL_FCS_PROVIDER = "gsrd-intel-fcs-lib"
93+
```
94+
95+
Use only one provider for `libFCS.so`.
96+
97+
## Build the Agilex 5 image
98+
99+
From the 26.1 DK-A5E013BM16AEA GSRD `software/yocto_linux` directory, build the
100+
same `gsrd-console-image` target documented by Altera:
101+
102+
```sh
103+
source venv/bin/activate
104+
kas build kas.yml:wolfssl-fcs.yml gsrd-console-image
105+
```
106+
107+
With the Kas container, run the equivalent command from the same directory:
108+
109+
```sh
110+
docker run --rm --user "$(id -u):$(id -g)" \
111+
-e HOME=/work -v "$PWD:/work" -w /work \
112+
ghcr.io/siemens/kas/kas:4.8 \
113+
build kas.yml:wolfssl-fcs.yml gsrd-console-image
114+
```
115+
116+
The expected SD card image is:
117+
118+
```text
119+
build/tmp/deploy/images/agilex5e_013b/gsrd-console-image-agilex5e_013b.rootfs.wic
120+
```
121+
122+
Fail the validation if that file is absent or empty:
123+
124+
```sh
125+
test -s build/tmp/deploy/images/agilex5e_013b/\
126+
gsrd-console-image-agilex5e_013b.rootfs.wic
127+
sha256sum build/tmp/deploy/images/agilex5e_013b/\
128+
gsrd-console-image-agilex5e_013b.rootfs.wic
129+
```
130+
131+
Inspect the partition table and the installed test from an initialized
132+
OpenEmbedded shell:
133+
134+
```sh
135+
(
136+
source poky/oe-init-build-env build
137+
image=tmp/deploy/images/agilex5e_013b/\
138+
gsrd-console-image-agilex5e_013b.rootfs.wic
139+
native="$(find "$PWD/tmp/work" -type d \
140+
-path '*/gsrd-console-image/*/recipe-sysroot-native' \
141+
-print -quit)"
142+
test -n "$native"
143+
wic ls -n "$native" "$image"
144+
wolfcrypt_bins="$(wic ls -n "$native" "$image:2/usr/bin/")"
145+
printf '%s\n' "$wolfcrypt_bins"
146+
printf '%s\n' "$wolfcrypt_bins" | grep -q 'wolfcrypttest'
147+
printf '%s\n' "$wolfcrypt_bins" | grep -q 'wolfcryptbenchmark'
148+
oe-pkgdata-util find-path /usr/bin/wolfcrypttest
149+
)
150+
```
151+
152+
When the image was built with the Kas container, run the same checks through
153+
`kas shell` so Yocto's native tools retain the `/work` path used at build time:
154+
155+
```sh
156+
docker run --rm --user "$(id -u):$(id -g)" \
157+
-e HOME=/work -v "$PWD:/work" -w /work \
158+
ghcr.io/siemens/kas/kas:4.8 \
159+
shell kas.yml:wolfssl-fcs.yml -c '
160+
image=tmp/deploy/images/agilex5e_013b/\
161+
gsrd-console-image-agilex5e_013b.rootfs.wic
162+
native="$(find "$PWD/tmp/work" -type d \
163+
-path "*/gsrd-console-image/*/recipe-sysroot-native" \
164+
-print -quit)"
165+
test -n "$native"
166+
wic ls -n "$native" "$image"
167+
wolfcrypt_bins="$(wic ls -n "$native" "$image:2/usr/bin/")"
168+
printf "%s\n" "$wolfcrypt_bins"
169+
printf "%s\n" "$wolfcrypt_bins" | grep -q wolfcrypttest
170+
printf "%s\n" "$wolfcrypt_bins" | grep -q wolfcryptbenchmark
171+
oe-pkgdata-util find-path /usr/bin/wolfcrypttest
172+
'
173+
```
174+
175+
The image must contain a FAT boot partition and an ext4 root partition. The
176+
second `wic ls` command must show both `wolfcrypttest` and
177+
`wolfcryptbenchmark`, and the package lookup must report `wolfssl`.
178+
179+
Confirm that BitBake also staged the packaged test:
180+
181+
```sh
182+
test -n "$(find build/tmp/work \
183+
-path '*/wolfssl/*/packages-split/*/usr/bin/wolfcrypttest' \
184+
-print -quit)"
185+
```
186+
187+
## Deploy the image
188+
189+
Power off the board and remove its microSD card. Attach the card to the build
190+
server, identify the whole device by its capacity, and unmount any mounted
191+
partitions. Device names vary: USB readers commonly appear as `/dev/sdX`, while
192+
built-in readers may appear as `/dev/mmcblkN`. The example below uses the
193+
device observed on the build server; replace it only after checking `lsblk`:
194+
195+
```sh
196+
image=build/tmp/deploy/images/agilex5e_013b/\
197+
gsrd-console-image-agilex5e_013b.rootfs.wic
198+
card=/dev/mmcblk0
199+
200+
lsblk -o NAME,SIZE,TYPE,TRAN,RM,MODEL,MOUNTPOINTS
201+
test -b "$card"
202+
for part in $(lsblk -lnpo NAME "$card" | tail -n +2); do
203+
if findmnt -rn -S "$part" >/dev/null; then
204+
sudo umount "$part"
205+
fi
206+
done
207+
208+
sudo dd if="$image" of="$card" bs=4M status=progress conv=fsync
209+
image_size=$(stat -Lc %s "$image")
210+
sudo cmp -n "$image_size" "$image" "$card" && echo "WIC verified"
211+
sync
212+
sudo blockdev --flushbufs "$card"
213+
```
214+
215+
Verify the destination with `lsblk` before writing. This operation replaces the
216+
card contents. Do not use a disk containing the build server's root filesystem.
217+
Use a spare card or make a full-device backup first if the existing image must
218+
be recoverable. `cmp` is silent on success; do not remove the card unless it
219+
returns zero and prints `WIC verified`. A built-in MMC reader may not implement
220+
the `eject` command. Once the partitions are unmounted and `blockdev` has
221+
flushed the device, it is safe to remove the card physically.
222+
223+
If the target image enables a package manager and a compatible package feed,
224+
an incremental update is also valid:
225+
226+
```sh
227+
bitbake wolfssl wolfcrypttest
228+
bitbake package-index
229+
```
230+
231+
Publish the generated package feed, refresh the target package index, and
232+
install or upgrade `wolfssl` and `wolfcrypttest` with the target's package
233+
manager. Do not copy a package from a different machine, tune, C library, or
234+
Yocto release.
235+
236+
## Verify on the board
237+
238+
Boot the deployed image and confirm that its packaged files are present:
239+
240+
```sh
241+
test -x /usr/bin/wolfcrypttest
242+
/lib/ld-linux-aarch64.so.1 --list /usr/bin/wolfcrypttest
243+
test -e /sys/kernel/fcs_sysfs
244+
```
245+
246+
The DHCP address can change after booting a replacement image. Use the serial
247+
console, the DHCP server's leases, or a local subnet scan to find the target
248+
rather than assuming its previous address is retained.
249+
250+
The GSRD image does not install `ldd` by default. Invoking the AArch64 dynamic
251+
loader with `--list` performs the same runtime dependency check without adding
252+
a diagnostic package to the image.
253+
254+
Run the installed test:
255+
256+
```sh
257+
/usr/bin/wolfcrypttest
258+
```
259+
260+
The run must exit with status 0 and print:
261+
262+
```text
263+
ALTERA-FCS test passed!
264+
```
265+
266+
The Altera subtests require successful hardware operations for RNG, SHA-256,
267+
and AES. They cannot pass solely through wolfSSL software fallback. Device
268+
resident ECDSA and ECDH keys and HMAC verification are also exercised.
269+
270+
If only the Altera test fails, check SDM provisioning status `0x85`. Status
271+
`0x84` indicates session exhaustion and requires a board power cycle.
272+
273+
## Developer-only smoke test
274+
275+
Copying `${B}/wolfcrypt/test/.libs/testwolfcrypt` directly to a running target
276+
is useful while developing the recipe. It is not the final integration test
277+
because it bypasses image construction, package installation, and runtime
278+
dependency resolution. Use the packaged `/usr/bin/wolfcrypttest` flow above
279+
for release validation.
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# The Agilex 5 GSRD recipe installs only the versioned runtime library. Add the
2+
# development linker name so dependent recipes can use -lFCS from their
3+
# recipe-specific sysroots.
4+
do_install:append() {
5+
if [ -e ${D}${prefix}/lib/libFCS.so.3 ]; then
6+
install -d ${D}${libdir}
7+
if [ "${libdir}" = "${prefix}/lib" ]; then
8+
ln -sfn libFCS.so.3 ${D}${libdir}/libFCS.so
9+
else
10+
ln -sfn ../lib/libFCS.so.3 ${D}${libdir}/libFCS.so
11+
fi
12+
fi
13+
}
Lines changed: 48 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,48 @@
1+
SUMMARY = "Altera FPGA Crypto Services library"
2+
DESCRIPTION = "Userspace library for the FPGA Crypto Services of Altera \
3+
SoCFPGA devices, exposing the Secure Device Manager crypto mailbox through \
4+
/sys/kernel/fcs_sysfs."
5+
HOMEPAGE = "https://github.com/altera-fpga/libfcs"
6+
LICENSE = "MIT-0"
7+
LIC_FILES_CHKSUM = "file://LICENSE;md5=6f25b4c3a6d23285f956387ab54830ad"
8+
9+
SRC_URI = "git://github.com/altera-fpga/libfcs.git;protocol=https;branch=main"
10+
SRCREV = "87b4b726f4981be102fc8f09feab051fe3578334"
11+
PV = "3.01+git"
12+
13+
DEPENDS = "dtc"
14+
15+
COMPATIBLE_HOST = "aarch64.*-linux"
16+
17+
python () {
18+
if d.getVar('UNPACKDIR', False):
19+
d.setVar('S', '${UNPACKDIR}/${BP}')
20+
else:
21+
d.setVar('S', '${WORKDIR}/git')
22+
}
23+
24+
inherit cmake
25+
26+
EXTRA_OECMAKE = "-DARCH=linux_aarch64"
27+
28+
# upstream install() destinations are relative, so they nest under ${prefix}
29+
wolfssl_fcs_fixup_install() {
30+
if [ -d ${D}${prefix}${prefix} ]; then
31+
cp -a ${D}${prefix}${prefix}/. ${D}${prefix}/
32+
rm -rf ${D}${prefix}${prefix}
33+
fi
34+
35+
# libfcs hardcodes /usr/lib. Move the library to Yocto's configured libdir,
36+
# then supply the linker name expected by consumers such as wolfSSL.
37+
if [ "${prefix}/lib" != "${libdir}" ] && \
38+
[ -e ${D}${prefix}/lib/libFCS.so.3 ]; then
39+
install -d ${D}${libdir}
40+
mv ${D}${prefix}/lib/libFCS.so.3 ${D}${libdir}/
41+
rmdir ${D}${prefix}/lib
42+
fi
43+
if [ -e ${D}${libdir}/libFCS.so.3 ]; then
44+
ln -sfn libFCS.so.3 ${D}${libdir}/libFCS.so
45+
fi
46+
}
47+
48+
do_install[postfuncs] += "wolfssl_fcs_fixup_install"
Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
# Altera Agilex 5 SDM crypto offload; needs an FCS provisioned device at
2+
# runtime. GSRD stacks that already build the library can point this at
3+
# their own recipe, e.g. WOLFSSL_FCS_PROVIDER = "gsrd-intel-fcs-lib".
4+
WOLFSSL_FCS_PROVIDER ?= "libfcs"
5+
6+
def wolfssl_fcs_is_target(d):
7+
return (d.getVar('CLASSOVERRIDE') == 'class-target' and
8+
(d.getVar('HOST_SYS') or '').startswith('aarch64-'))
9+
10+
WOLFSSL_FCS_CONFIGURE = "${@'--enable-alterafcs --enable-aesctr' if wolfssl_fcs_is_target(d) else ''}"
11+
WOLFSSL_FCS_DEPENDS = "${@d.getVar('WOLFSSL_FCS_PROVIDER') if wolfssl_fcs_is_target(d) else ''}"
12+
13+
EXTRA_OECONF += "${WOLFSSL_FCS_CONFIGURE}"
14+
DEPENDS += "${WOLFSSL_FCS_DEPENDS}"
15+
16+
python () {
17+
if (d.getVar('CLASSOVERRIDE') == 'class-target' and
18+
not d.getVar('MLPREFIX') and
19+
not (d.getVar('HOST_SYS') or '').startswith('aarch64-')):
20+
bb.fatal('WOLFSSL_ALTERA_FCS requires an AArch64 target')
21+
}

0 commit comments

Comments
 (0)