jetson-orin: A/B verity boot with Secure Boot and OTA updates#1811
jetson-orin: A/B verity boot with Secure Boot and OTA updates#1811
Conversation
|
Also opened tiiuae/ghaf-givc#372 |
8ae6aa8 to
153fdac
Compare
153fdac to
f952184
Compare
f952184 to
76737d5
Compare
|
Depends on #1678 |
bed36d2 to
665641e
Compare
665641e to
6880b3b
Compare
6880b3b to
bc6e3c8
Compare
bc6e3c8 to
eb1077b
Compare
eb1077b to
bb81111
Compare
670ec82 to
c6ec782
Compare
c6ec782 to
75a8047
Compare
|
Have to investigate this device: |
Add splice-flash-xml.py, a Python script that replaces the <device type="sdmmc_user"> partitions in NVIDIA's flash XML with a custom layout defined in JSON. This replaces fragile line-count based head/tail splicing that breaks when the upstream BSP XML changes. Convert partition-template.nix to use the new script. The partition layout is now defined as structured Nix data serialized to JSON. Partition sizes are injected at build time from sdImage metadata via --set instead of flash-time sed substitution. Features: --set PARTITION.FIELD=VALUE override partition child element values --remove-device remove sdmmc_user device (QSPI-only) Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
Add verity-image.nix that builds ESP and LVM partition images for A/B verity boot on Jetson AGX Orin. ESP contains systemd-boot + a UKI (Unified Kernel Image) that embeds kernel, initrd, and cmdline with the dm-verity roothash. The UKI is built WITHOUT a .dtb section because NVIDIA's EFI_DT_FIXUP_PROTOCOL corrupts device trees loaded from memory by sd-stub. Without .dtb, sd-stub skips devicetree_fixup() and the kernel uses the firmware's DTB already in the EFI Configuration Table (installed by DtPlatformDxe during UEFI boot). LVM image contains A/B erofs root + verity hash tree slots, swap, and a btrfs persist volume. Slot sizes are computed dynamically from actual image sizes at build time. Images are converted to NVIDIA sparse format via mksparse for efficient USB flashing with tegradevflash_v2. Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
Use lz4hc level 9 for erofs compression, which reduces the nix store image from 9.37 GiB to 5.30 GiB (43% savings). With A/B partitioning this saves ~8 GiB of flash storage. Decompression throughput for lz4 is ~1.0 GB/s on x86_64 (streaming 9.4 GiB image). zstd would provide slightly better compression (5.09 GiB) and ~60% faster decompression (~1.6 GB/s), but EROFS_FS_ZIP_ZSTD requires kernel >= 6.10 (commit 7c35de4df105) while the Jetson BSP ships kernel 6.6. Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
Move swap, persist and B-slot placeholder LV creation from the pre-built LVM image to a first-boot systemd service. This shrinks the flash image from ~16 GiB to ~6 GiB (only A-slot root + verity), eliminating the sparse image conversion step. On first boot, firstboot-persist.service: 1. Resizes the GPT/APP partition to fill the eMMC 2. Expands the LVM PV to match 3. Creates swap (4G) and persist (btrfs) LVs 4. Reserves 1.5x the A-slot size for a future B-slot Each step is idempotent so the service can safely re-run after a power loss. Swap uses randomEncryption for security. Systemd ordering is handled naturally: persist.mount waits for /dev/pool/persist to appear (device unit dependency), and the NixOS-generated mkswap service is explicitly ordered after firstboot-persist. Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
75a8047 to
e89abf0
Compare
e89abf0 to
49f1be2
Compare
Enable givc on Orin (was disabled) and bump ghaf-givc to include auto-create and resize of LVM slots for OTA updates (PR #372). Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
The secureboot PR (#1713) enrolls PK/KEK/db keys into the Jetson Orin firmware, but nothing was signing the UKI or systemd-boot. Once keys are enrolled and the UEFI leaves Setup Mode, it rejects unsigned binaries with 'Access denied', bricking the device. Move ESP image construction from a Nix derivation into the flash script so we can sign EFI binaries with sbsign just before writing them to the FAT partition. The private key is read at flash time from SECURE_BOOT_SIGNING_KEY_DIR (or the signingKeyDir option), keeping it out of the Nix store. Add self-signed development keys under modules/secureboot/dev-keys/ for testing. These are explicitly not secret and must not be used in production. Tested on Jetson AGX Orin: device boots with Secure Boot enabled (user mode), unsigned UKI is rejected with 'Access denied'. Signed-off-by: Jörg Thalheim <joerg@thalheim.io>
49f1be2 to
bb29bc9
Compare
|
I ran the steps defined in "Testing" (with small modifications) for Orin AGX. The update works as expected but noticed that nix-gc.service is failing at boot after update. |
(There is no physical eth on ghaf-host either.) Are we supposed to stop using plain |
|
Tried It fails with I assume this is expected at this stage because "uki-signing-key-dir places dev private keys in the Nix store" |
|
Previous checks I made with I just noticed that Jörg has been pushing at the same time I have been testing. |
Description
A/B verity boot end-to-end on Jetson AGX Orin, with UEFI Secure Boot and OTA update support.
Verity boot: UKI-based boot with dm-verity root filesystem on erofs (lz4hc compressed). First-boot service creates swap/persist/B-slot placeholder on the device.
Secure Boot: Cherry-picks #1713 for UEFI key enrollment, then adds flash-time EFI signing with sbsign. Private keys stay out of the Nix store — the flash script reads them from
SECURE_BOOT_SIGNING_KEY_DIRat runtime (falls back to embedded dev-keys path). OTA update UKIs are signed at build time in debug builds (asserts ondebugEnable); in production the OTA server signs images before distribution.OTA updates: Enable givc on Orin with upstream ghaf-givc (PR tiiuae/ghaf-givc#372 merged). The manifest includes
unpacked_sizeso ota-update can create and resize LVM slots on demand.Depends on tiiuae/ghaf-givc#372 (merged)
Verified on Jetson AGX Orin devkit
Tested on physical Jetson AGX Orin devkit, cross-compiled from x86_64-linux.
Secure Boot: enabled (user)ota-update image installwrites signed UKI + root + verity to auto-created LVsbootctl set-oneshot→ reboot into slot B (26.03.2) — accepted by Secure Bootactive: trueafter rebootota-update image removerecycles old slotKnown limitation
OTA update UKI signing uses
uki-signing-key-dirwhich places dev private keys in the Nix store. This is gated by an assertion to debug builds only. In production, the OTA server must sign UKIs before distribution — this integration is not yet implemented. Seesecureboot.mdxfor details.Testing
Build and flash
Verify boot (serial console or SSH)
Test OTA update