Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
35 changes: 35 additions & 0 deletions docs/src/content/docs/ghaf/overview/arch/secureboot.mdx
Original file line number Diff line number Diff line change
Expand Up @@ -41,3 +41,38 @@ efi-readvar -v PK
efi-readvar -v KEK
efi-readvar -v db
```

## Jetson Orin signed flashing workflow

Jetson Orin targets produce two independent build artifacts in CI:

1. The flash script (`nix build .#nvidia-jetson-orin-agx-debug-from-x86_64-flash-script`) which orchestrates NVIDIA's flashing tools.
2. The filesystem image (`nix build .#nvidia-jetson-orin-agx-debug-from-x86_64`) that contains the ESP and root partitions.

After the filesystem image is signed, pass its Nix store path directly to the flash helper:

```sh
SIGNED_SD_IMAGE=$(nix path-info .#nvidia-jetson-orin-agx-debug-from-x86_64)
./result/bin/initrd-flash-ghaf-host -s "$SIGNED_SD_IMAGE"
```

The `-s/--signed-sd-image` flag extracts `BOOTAA64.EFI` and the kernel from the signed image, wires them into the flashing workdir, and launches NVIDIA's flashing script without requiring any additional staging directories or host key material.

For ad-hoc debugging you can also point `-s` to a copy of the signed build outside the Nix store (for example, `cp -a $(nix path-info …) /tmp/orin-signed` and then pass `/tmp/orin-signed`), which is useful when the original store path is unavailable on the flashing host.

For CI jobs that still need a deterministic artifact directory (for example when reusing the same signed files across multiple runs), the helper `modules/secureboot/extract-signed-orin-artifacts.sh` can be used:

```sh
./modules/secureboot/extract-signed-orin-artifacts.sh \
--sd-image-dir "$SIGNED_SD_IMAGE" \
--output /build/orin-flash-artifacts \
--force

# Optional: reuse the staged directory via configuration or the environment
export SIGNED_ARTIFACTS_DIR=/build/orin-flash-artifacts
./result/bin/initrd-flash-ghaf-host
```

The helper resolves the supplied directory—whether it's a `/nix/store/...` path or a copy under `/tmp`—before extracting the ESP and root partitions.

The existing module option `ghaf.hardware.nvidia.orin.flashScriptOverrides.signedArtifactsPath` still forces the flash script to pick up a specific directory when the environment variable is not convenient.
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
imports = [
./partition-template.nix
./jetson-orin.nix
./secureboot.nix
./pci-passthrough-common.nix
./virtualization
./optee.nix
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,20 @@ in
default = "";
};

flashScriptOverrides.signedArtifactsPath = mkOption {
description = ''
Absolute path on the host that contains pre-signed Jetson Orin boot
artifacts.

The flash script expects at least `BOOTAA64.EFI` and `Image` to be
present in this directory. Optional files such as `initrd` or device
trees can be staged as well. The directory can also be provided at
runtime through the `SIGNED_ARTIFACTS_DIR` environment variable.
'';
type = types.nullOr types.str;
default = null;
};

somType = mkOption {
description = "SoM config Type (NX|AGX32|AGX64|Nano)";
type = types.str;
Expand All @@ -51,6 +65,8 @@ in
};

config = mkIf cfg.enable {
ghaf.hardware.nvidia.orin.secureboot.enable = lib.mkDefault true;

hardware.nvidia-jetpack.kernel.version = "${cfg.kernelVersion}";
nixpkgs.hostPlatform.system = "aarch64-linux";

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -147,6 +147,53 @@ let
mkdir -pv "$WORKDIR/bootloader"
rm -fv "$WORKDIR/bootloader/esp.img"

${lib.optionalString (cfg.flashScriptOverrides.signedArtifactsPath != null) ''
if [ -z "''${SIGNED_ARTIFACTS_DIR:-}" ]; then
SIGNED_ARTIFACTS_DIR=${lib.escapeShellArg cfg.flashScriptOverrides.signedArtifactsPath}
fi
''}

if [ -n "''${SIGNED_ARTIFACTS_DIR:-}" ]; then
echo "Using signed artifacts from $SIGNED_ARTIFACTS_DIR"

for artifact in BOOTAA64.EFI Image; do
if [ ! -f "$SIGNED_ARTIFACTS_DIR/$artifact" ]; then
echo "ERROR: Missing $artifact in $SIGNED_ARTIFACTS_DIR" >&2
exit 1
fi
done

export BOOTAA64_EFI="$SIGNED_ARTIFACTS_DIR/BOOTAA64.EFI"
export KERNEL_IMAGE="$SIGNED_ARTIFACTS_DIR/Image"

if [ -f "$SIGNED_ARTIFACTS_DIR/initrd" ]; then
export INITRD_IMAGE="$SIGNED_ARTIFACTS_DIR/initrd"
fi

if [ -f "$SIGNED_ARTIFACTS_DIR/dtb" ]; then
export DTB_IMAGE="$SIGNED_ARTIFACTS_DIR/dtb"
fi
fi

if [ -n "''${BOOTAA64_EFI:-}" ]; then
if [ ! -f "$BOOTAA64_EFI" ]; then
echo "ERROR: BOOTAA64_EFI not found: $BOOTAA64_EFI" >&2
exit 1
fi
echo "Using external BOOTAA64.EFI: $BOOTAA64_EFI"
cp -f "$BOOTAA64_EFI" "$WORKDIR/bootloader/BOOTAA64.EFI"
fi

if [ -n "''${KERNEL_IMAGE:-}" ]; then
if [ ! -f "$KERNEL_IMAGE" ]; then
echo "ERROR: KERNEL_IMAGE not found: $KERNEL_IMAGE" >&2
exit 1
fi
echo "Using external kernel Image: $KERNEL_IMAGE"
mkdir -pv "$WORKDIR/kernel"
cp -f "$KERNEL_IMAGE" "$WORKDIR/kernel/Image"
fi

${lib.optionalString (!cfg.flashScriptOverrides.onlyQSPI) ''
# Read partition offsets and sizes from sdImage metadata
ESP_OFFSET=$(cat "${images}/esp.offset")
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# SPDX-FileCopyrightText: 2022-2026 TII (SSRC) and the Ghaf contributors
# SPDX-License-Identifier: Apache-2.0

{
config,
lib,
pkgs,
...
}:
let
cfg = config.ghaf.hardware.nvidia.orin.secureboot;

eslFromCert =
name: cert:
pkgs.runCommand name { nativeBuildInputs = [ pkgs.buildPackages.efitools ]; } ''
${pkgs.buildPackages.efitools}/bin/cert-to-efi-sig-list ${cert} $out
'';

keysDir = cfg.keysSource;

pkEsl = eslFromCert "PK.esl" "${keysDir}/PK.crt";
kekEsl = eslFromCert "KEK.esl" "${keysDir}/KEK.crt";
dbEsl = eslFromCert "db.esl" "${keysDir}/db.crt";
in
{
options.ghaf.hardware.nvidia.orin.secureboot = {
enable = lib.mkEnableOption "UEFI Secure Boot key enrollment for Jetson Orin";

keysSource = lib.mkOption {
type = lib.types.path;
default = ../../../../secureboot/keys;
description = "Directory containing PK.crt, KEK.crt and db.crt used to generate ESLs.";
};
};

config = lib.mkIf cfg.enable {
hardware.nvidia-jetpack.firmware.uefi.secureBoot = {
enrollDefaultKeys = true;
defaultPkEslFile = pkEsl;
defaultKekEslFile = kekEsl;
defaultDbEslFile = dbEsl;
};
};
}
Loading
Loading