Skip to content

Add AArch64 UEFI support (NVIDIA Jetson Orin) - #818

Open
dgarske wants to merge 4 commits into
wolfSSL:masterfrom
dgarske:aarch64_efi
Open

Add AArch64 UEFI support (NVIDIA Jetson Orin)#818
dgarske wants to merge 4 commits into
wolfSSL:masterfrom
dgarske:aarch64_efi

Conversation

@dgarske

@dgarske dgarske commented Jul 7, 2026

Copy link
Copy Markdown
Member

Summary

Adds a new aarch64_efi target that builds wolfBoot as an AArch64 UEFI application (wolfboot.efi) -- the direct sibling of the existing Qemu x86-64 UEFI target. It uses only UEFI Boot Services (no SoC-specific registers), so the same binary runs on any AArch64 UEFI platform. The platform firmware launches wolfboot.efi, which reads the next-stage image from the EFI Simple File System, authenticates it with wolfCrypt, and boots it via LoadImage/StartImage (an AArch64 Linux Image is itself a PE/COFF EFI-stub application).

Validated end to end on the NVIDIA Jetson Orin Nano Developer Kit (Tegra234): the on-module UEFI firmware (edk2-nvidia) launches wolfBoot after the NVIDIA-signed early chain (BootROM -> MB1 -> MB2 -> UEFI), and wolfBoot verifies and boots NVIDIA Jetson Linux (L4T R36.4.4, 5.15.148-tegra) to an Ubuntu 22.04 login prompt.

What it adds

  • UEFI-application HAL (hal/aarch64_efi.c, hal/aarch64_efi.ld) and config/examples/aarch64_efi.config. No bare-metal init -- UEFI owns DRAM/MMU/GIC; the flash ops are stubs and storage/console come from Boot Services.
  • Measured boot via the firmware TPM (MEASURED_BOOT_TCG2=1): using EFI_TCG2_PROTOCOL, wolfBoot extends the verified kernel, its command line, and the platform device tree into a PCR (MEASURED_PCR_A, default 9) with HashLogExtendEvent, then reads the PCR back. The firmware/fTPM does the hashing and log append, so wolfBoot needs no TPM transport driver and pulls in no wolfTPM.
  • Authenticated kernel command line (new; both EFI targets): the Linux command line is carried in a signature-covered HDR_CMDLINE TLV in the manifest header instead of an unsigned file. wolfBoot reads it from the verified image and passes it to the kernel EFI stub via LoadOptions, so kernel arguments (root=, init=, security flags) cannot be altered without breaking the image signature. Sign with --cmdline "..." (a shorthand for the HDR_CMDLINE string TLV). The same path is added to x86_64_efi (which previously had no command-line mechanism).
  • UEFI Secure Boot enrollment docs: how to enroll wolfBoot's signing identity into the platform db/KEK/PK so the fused firmware enforces wolfboot.efi, which in turn enforces the kernel -- a complete hardware root of trust.

Notable details

  • open_kernel_image() now returns -1 on error rather than a truncated EFI_STATUS (a UINTN whose error high-bit would become a positive int) -- addresses review feedback.
  • The command-line TLV read is a single shared helper (include/wolfboot_efi.h, wolfBoot_efi_get_cmdline()) included by both EFI HALs after their gnu-efi headers -- one auditable copy, no build wiring.
  • Command line is ASCII, up to 255 bytes; it must fit within IMAGE_HEADER_SIZE (the default 256-byte ED25519/SHA256 header holds roughly 70 bytes; set IMAGE_HEADER_SIZE=512 for longer lines). If the image carries no HDR_CMDLINE TLV, wolfBoot boots with no command line and the kernel uses its built-in CONFIG_CMDLINE.

Testing

  • Both aarch64_efi and x86_64_efi build (make with each config; wolfboot.efi produced).
  • sign --ed25519 --sha256 --cmdline "root=..." kernel.img key.der 1 produces a HDR_CMDLINE (0x0034) TLV that reads back exactly via the wolfBoot header parser.
  • On hardware (Jetson Orin Nano): wolfboot.efi + a signed kernel.img on a FAT ESP boots L4T to an Ubuntu login; the console shows Firmware Valid and the TCG2 measurement lines.

Docs

docs/Targets.md gains the "NVIDIA Jetson Orin (aarch64_efi)" section (deploy, boot Linux, Secure Boot enrollment, measured boot); docs/Signing.md documents --cmdline / HDR_CMDLINE.

@dgarske dgarske self-assigned this Jul 7, 2026
Copilot AI review requested due to automatic review settings July 7, 2026 17:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This pull request adds a new aarch64_efi target so wolfBoot can run as an AArch64 UEFI application (validated on NVIDIA Jetson Orin), loading/verifying kernel.img/update.img from the ESP and booting via UEFI LoadImage/StartImage.

Changes:

  • Add a new AArch64 UEFI HAL (hal/aarch64_efi.c) plus boot glue (src/boot_aarch64_efi.c) and linker-script stub.
  • Extend the build system to support an AArch64 PE/COFF wolfboot.efi output and a new example config.
  • Add helper scripts and documentation for building gnu-efi for AArch64 and running under QEMU/Jetson deployment.

Reviewed changes

Copilot reviewed 10 out of 11 changed files in this pull request and generated 6 comments.

Show a summary per file
File Description
tools/scripts/build-gnu-efi-aarch64.sh Helper to clone/build/install gnu-efi (AArch64) into the repo tree
tools/scripts/aarch64-efi-qemu.sh Convenience runner for wolfboot.efi under QEMU + AAVMF
tools/keytools/keygen.c Extends keystore section handling for the new UEFI target macro
src/boot_aarch64_efi.c Adds UEFI-target do_boot() glue for AArch64
Makefile Makes the wolfboot.efi objcopy output format configurable per target
hal/aarch64_efi.ld Empty placeholder linker script (gnu-efi script used instead)
hal/aarch64_efi.c New AArch64 UEFI HAL: ESP file loading, verification, LoadImage/StartImage handoff
docs/Targets.md Adds aarch64_efi target documentation (Jetson Orin + QEMU workflow)
config/examples/aarch64_efi.config Example configuration for aarch64_efi
arch.mk Adds aarch64_efi target build flags, gnu-efi paths, and linking rules
.gitignore Ignores gnu-efi build artifacts and staging dirs for the new target

💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.

Comment thread hal/aarch64_efi.c
Comment thread src/boot_aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c
Comment thread tools/scripts/build-gnu-efi-aarch64.sh Outdated
Comment thread arch.mk
@dgarske
dgarske requested a review from Copilot July 8, 2026 00:05

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 12 out of 13 changed files in this pull request and generated 11 comments.

Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c
Comment thread src/boot_aarch64_efi.c Outdated
@dgarske
dgarske force-pushed the aarch64_efi branch 2 times, most recently from 308bf22 to 1963856 Compare July 11, 2026 00:03
@dgarske
dgarske requested a review from Copilot July 11, 2026 00:29
@dgarske
dgarske marked this pull request as ready for review July 11, 2026 00:39

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 23 changed files in this pull request and generated 8 comments.

Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c
Comment thread src/boot_aarch64_efi.c Outdated
Comment thread tools/scripts/sign-efi-secureboot.sh
Comment thread .github/workflows/test-configs.yml Outdated

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 23 changed files in this pull request and generated 12 comments.

Comments suppressed due to low confidence (1)

hal/aarch64_efi.c:1

  • UEFI EFI_FILE_PROTOCOL.Open() ignores the Attributes parameter unless EFI_FILE_MODE_CREATE is set; passing READ_ONLY|HIDDEN|SYSTEM here is nonstandard and can cause opens to fail on stricter firmwares. For read-only opens, pass 0 for the Attributes argument and keep access control via EFI_FILE_MODE_READ.
/* aarch64_efi.c

Comment thread hal/tegra234.ld Outdated
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c
Comment thread tools/scripts/sign-efi-secureboot.sh
Comment thread tools/scripts/sign-efi-secureboot.sh

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 22 out of 23 changed files in this pull request and generated 2 comments.

Comments suppressed due to low confidence (2)

hal/aarch64_efi.c:504

  • open_kernel_image() stores FileSize() into a uint32_t, which truncates files >4GiB. That can lead to partial reads and confusing verification failures. Also, returning EFI_STATUS from an int-returning function can truncate the high-bit error codes on 64-bit builds; it’s safer to keep the return values as 0/-1 here since the caller doesn’t consume EFI_STATUS.
    *sz =  FileSize(file);
    pages = (*sz / PAGE_SIZE) + 1;
    wolfBoot_printf("Opening file: %s, size: %u\n", filename, *sz);
    status = uefi_call_wrapper(BS->AllocatePages,
                          4,

hal/aarch64_efi.c:528

  • On Read() failure, open_kernel_image() returns EFI_STATUS through an int return type. On AArch64, EFI_STATUS uses the high bit for errors, so truncating to int can turn errors into 0 (success) if a future caller checks it. Return -1 here (and rely on the already-printed status) to keep the int contract consistent.
    if (status != EFI_SUCCESS) {
        wolfBoot_printf("file Read failed: 0x%lx\n", (unsigned long)status);
        uefi_call_wrapper(BS->FreePages, 2, *_addr, pages);
        *_addr = 0;
        return status;

Comment thread hal/aarch64_efi.c Outdated
Comment thread hal/aarch64_efi.c
@dgarske
dgarske force-pushed the aarch64_efi branch 2 times, most recently from 1f35be7 to d325fbd Compare July 23, 2026 18:44
@dgarske
dgarske requested a review from Copilot July 23, 2026 18:45

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 14 out of 15 changed files in this pull request and generated 3 comments.

Comments suppressed due to low confidence (1)

hal/aarch64_efi.c:528

  • open_kernel_image() assigns the UINT64 EFI file size into a uint32_t and then computes pages as (sz / PAGE_SIZE) + 1, which always over-allocates when the file is an exact multiple of PAGE_SIZE and silently truncates sizes >4GiB. Validate the file size up front and compute the page count with a proper round-up division.
    *sz =  FileSize(file);
    pages = (*sz / PAGE_SIZE) + 1;
    wolfBoot_printf("Opening file: %s, size: %u\n", filename, *sz);

Comment thread hal/aarch64_efi.c
Comment thread hal/aarch64_efi.c
Comment thread docs/Targets.md
Comment thread docs/Targets.md Outdated
Comment thread hal/aarch64_efi.c
@danielinux danielinux assigned dgarske and unassigned danielinux Jul 30, 2026

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Not ready to approve

The AArch64 EFI file-loading path currently truncates 64-bit file sizes into a 32-bit length and miscomputes page rounding, which can cause incorrect allocation/reads and should be fixed before merging.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

This review doesn't count toward merge requirements. Sign up for the private preview to control whether Copilot approvals count.

Review details

Suppressed comments (4)

hal/aarch64_efi.c:550

  • FileSize() returns a UINT64, but open_kernel_image stores it into a uint32_t and uses that truncated value for page allocation and Read(). A file >4GiB would be silently truncated, potentially causing partial reads/under-allocation. Also, pages is computed as (sz/PAGE_SIZE)+1, which over-allocates an extra page when the size is an exact multiple of PAGE_SIZE.
    *sz =  FileSize(file);
    pages = (*sz / PAGE_SIZE) + 1;
    wolfBoot_printf("Opening file: %s, size: %u\n", filename, *sz);

tools/scripts/aarch64-efi-qemu.sh:27

  • This script still claims wolfBoot reads an external \cmdline.txt and copies cmdline.txt into the ESP, but the EFI targets now take the kernel command line from the authenticated HDR_CMDLINE TLV inside kernel.img (no external file is consumed). Keeping this copy/comment is misleading for users trying to change the command line.
# optional Linux kernel command line (M3): read by wolfboot as \cmdline.txt
cp "$ROOT/aarch64_efi-stage/cmdline.txt" "$ESP"/ 2>/dev/null || true

tools/keytools/sign.c:3595

  • The new --cmdline option introduces user-facing argument parsing and TLV encoding constraints (1..255 bytes, tag HDR_CMDLINE) but there is no automated coverage for it. Existing CI/unit tests already exercise other sign-tool options (e.g. --custom-tlv-string/buffer), so adding a targeted test for --cmdline would help prevent regressions (including length boundary cases and verifying the emitted TLV tag/value).
        else if (strcmp(argv[i], "--cmdline") == 0) {
            /* Shorthand for --custom-tlv-string HDR_CMDLINE "<args>": stores the
             * OS command line as a signature-covered TLV in the manifest. */
            int p = CMD.custom_tlvs;
            uint16_t len;
            uint32_t j;
            if (p >= MAX_CUSTOM_TLVS) {
                fprintf(stderr, "Too many custom TLVs.\n");
                exit(16);
            }
            if (argc < (i + 2)) {
                fprintf(stderr, "Missing --cmdline argument.\n");
                exit(16);
            }
            len = (uint16_t)strlen(argv[i + 1]);
            if (len == 0 || len > 255) {
                fprintf(stderr, "cmdline must be 1..255 bytes: %s\n", argv[i + 1]);
                exit(16);
            }
            CMD.custom_tlv[p].tag = HDR_CMDLINE;
            CMD.custom_tlv[p].len = len;
            CMD.custom_tlv[p].buffer = malloc(len);
            if (CMD.custom_tlv[p].buffer == NULL) {
                fprintf(stderr, "Error malloc for cmdline tlv buffer %d\n", len);
                exit(16);
            }
            for (j = 0; j < len; j++) {
                CMD.custom_tlv[p].buffer[j] = (uint8_t)argv[i + 1][j];
            }
            CMD.custom_tlvs++;
            i += 1;
        }

tools/scripts/sign-efi-secureboot.sh:86

  • The script generates PEM .crt, .esl and .auth outputs, but many UEFI setup menus expect DER-encoded certs (commonly .cer/.der) for file-based enrollment. Since openssl is already required, consider emitting a DER .cer alongside the PEM to avoid an extra manual conversion step (and to better match the docs' enrollment flow).
    # ESL (EFI signature list) form of the cert, tagged with our owner GUID.
    cert-to-efi-sig-list -g "$GUID" "$name.crt" "$name.esl"
  • Files reviewed: 19/20 changed files
  • Comments generated: 0 new
  • Review effort level: Lite

We're testing this review assessment. Please use 👍 or 👎 to tell us if it's correct.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

4 participants