Skip to content
Merged
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
10 changes: 7 additions & 3 deletions ALPHA_RELEASE_PLAN.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,8 +66,11 @@ working scripts, working `pf` tasks, documentation, and at least smoke tests.
- DISA STIG helper (`dod-info`, `dod-stig-check`, `dod-secure-config`).

### 1.7 UUEFI host-side helpers
- `uuefi-install`, `uuefi-apply`, `uuefi-report` (require root /
`efibootmgr`).
- `uuefi-report` (read-only).
- `uuefi-install` / `uuefi-apply` remain present for maintainer testing but
are gated for `v0.1.0-alpha` unless
`PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1` is set. They are not part of
the supported end-user alpha surface until broader host-side validation lands.

### 1.8 CLIs and runners
- `./pf` — symlink to the vendored `pf-runner/pf` launcher. This is the
Expand Down Expand Up @@ -214,7 +217,8 @@ These are concrete, small bugs that block a clean alpha experience.
| 4.3 | `scripts/maintenance/lint.sh` wrote to `out/lint/*.log` without `mkdir -p`. | Already fixed. |
| 4.4 | `scripts/esp-packaging/esp-package-enroll.sh` had the wrong `source` path. | Already fixed. |
| 4.5 | `docs/AGENTS.md` still warns about the `esp-package.sh` `cd` bug. | Update doc to reflect post-fix state. |
| 4.6 | `./phoenixboot list` shows "wrapper commands" only when `pf` is unavailable, but the wording is good. | Keep as-is; verified. |
| 4.6 | `./phoenixboot list` / `./phoenixboot-dod list` were treating a broken `pf` runtime as "available" and surfacing a raw `pf` error. | Probe `pf version` first, then fall back to curated wrapper output plus actionable install hints when the runner is present but unusable. |
| 4.7 | `uuefi-install.sh` could silently fall back to `BootX64.efi`, and `uuefi-install` / `uuefi-apply` lacked broad host-side validation. | Refuse the fallback, gate the mutating host-side helpers behind `PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1`, and keep `uuefi-report` as the safe default. |

The end-to-end "does anything work without `pf` installed" smoke for the
alpha is `./phoenixboot help`, `./phoenixboot status`, `./phoenixboot list`,
Expand Down
6 changes: 3 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -242,11 +242,11 @@ Tools for managing UEFI boot entries:
- `os-boot-clean`: Clean stale UEFI boot entries
- `os-mok-enroll`: Enroll MOK keys for module signing
- `os-mok-list-keys`: List available MOK certificates
- `uuefi-install`: Install UUEFI.efi to system ESP
- `uuefi-apply`: Set BootNext for one-time UUEFI boot
- `uuefi-install`: Install UUEFI.efi to system ESP (**alpha-gated pending broader host-side validation**)
- `uuefi-apply`: Set BootNext for one-time UUEFI boot (**alpha-gated pending broader host-side validation**)
- `uuefi-report`: Display system security status

**Status**: Scripts implemented, tested on real hardware
**Status**: `uuefi-report` is shipped for alpha; host-side mutating helpers stay gated unless `PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1` is set during deliberate maintainer testing

#### 4. **QEMU Testing**
Comprehensive QEMU-based testing:
Expand Down
4 changes: 2 additions & 2 deletions components/core/core.pf
Original file line number Diff line number Diff line change
Expand Up @@ -199,12 +199,12 @@ end

# --- UUEFI Operations ---
task uuefi-install
describe Install UUEFI.efi to system ESP
describe Install UUEFI.efi to system ESP (gated for alpha; set PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1 to override)
shell bash scripts/uefi-tools/uuefi-install.sh
end

task uuefi-apply
describe UUEFI apply (set BootNext; optionally create entry)
describe UUEFI apply (set BootNext; gated for alpha; set PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1 to override)
shell bash scripts/uefi-tools/uuefi-apply.sh
end

Expand Down
18 changes: 18 additions & 0 deletions components/core/scripts/testing/test-phoenixboot-cli.sh
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,24 @@ else
fi
fi

# Test 22: DoD list command should either work or fail loudly with install context
echo "[TEST 22] Testing phoenixboot-dod list..."
dod_list_output=$(./phoenixboot-dod list 2>&1 || true)
if echo "$dod_list_output" | grep -qi "Attempted pf.py arguments: list\|PhoenixBoot - Department of Defense"; then
pass "phoenixboot-dod list provides curated output or clear install context"
else
fail "phoenixboot-dod list did not provide clear install context"
fi

# Test 23: Unknown DoD commands should fail with delegation context
echo "[TEST 23] Testing phoenixboot-dod unknown command handling..."
dod_unknown_output=$(timeout 5 ./phoenixboot-dod invalid_command_xyz 2>&1 || true)
if echo "$dod_unknown_output" | grep -qi "Attempted pf.py arguments: invalid_command_xyz\|phoenixboot-dod ERROR"; then
pass "Unknown DoD commands fail loudly with delegation context"
else
fail "Unknown DoD command handling did not emit clear contextual output"
fi

# Summary
echo
echo "======================="
Expand Down
76 changes: 76 additions & 0 deletions components/core/scripts/testing/test-uuefi-host-helpers.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,76 @@
#!/bin/bash
# Focused regression test for alpha-gated UUEFI host-side helpers.

set -euo pipefail

SCRIPT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")" && pwd)"
if PROJECT_ROOT="$(git -C "$SCRIPT_DIR" rev-parse --show-toplevel 2>/dev/null)"; then
:
else
PROJECT_ROOT="$(cd "$SCRIPT_DIR/../../../.." && pwd)"
fi
cd "$PROJECT_ROOT"

PASSED=0
FAILED=0

GREEN='\033[0;32m'
RED='\033[0;31m'
NC='\033[0m'

pass() {
echo -e " ${GREEN}✓${NC} $1"
PASSED=$((PASSED + 1))
}

fail() {
echo -e " ${RED}✗${NC} $1"
FAILED=$((FAILED + 1))
}

echo "Testing UUEFI host-side helper safety"
echo "====================================="
echo

INSTALL_SCRIPT="$PROJECT_ROOT/scripts/uefi-tools/uuefi-install.sh"
APPLY_SCRIPT="$PROJECT_ROOT/scripts/uefi-tools/uuefi-apply.sh"
Copy link
Copy Markdown

Choose a reason for hiding this comment

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

Test references non-existent script paths at repo root

High Severity

INSTALL_SCRIPT and APPLY_SCRIPT are set to $PROJECT_ROOT/scripts/uefi-tools/uuefi-install.sh and uuefi-apply.sh, but the actual scripts live at $PROJECT_ROOT/components/core/scripts/uefi-tools/. The scripts/ directory at the repo root contains compatibility symlinks per scripts/README.md, but these symlink targets are not resolvable in the repository tree (confirmed by Read returning "File not found" for both paths). On a fresh clone without out-of-tree symlink setup, all three tests will fail to find the scripts and report spurious failures — the bash "$INSTALL_SCRIPT" invocations will error with "No such file" rather than exercising the alpha gate logic being tested.

Fix in Cursor Fix in Web

Reviewed by Cursor Bugbot for commit 6967f1b. Configure here.


echo "[TEST 1] uuefi-install is alpha-gated by default..."
install_output=$(bash "$INSTALL_SCRIPT" 2>&1 || true)
if echo "$install_output" | grep -q "gated off for the alpha release"; then
pass "uuefi-install refuses to run without explicit opt-in"
else
fail "uuefi-install did not enforce the alpha gate"
fi

echo "[TEST 2] uuefi-apply is alpha-gated by default..."
apply_output=$(bash "$APPLY_SCRIPT" 2>&1 || true)
if echo "$apply_output" | grep -q "gated off for the alpha release"; then
pass "uuefi-apply refuses to run without explicit opt-in"
else
fail "uuefi-apply did not enforce the alpha gate"
fi

echo "[TEST 3] uuefi-install refuses BootX64 placeholder fallback..."
missing_binary_output=$(PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1 UUEFI_SRC=/definitely/missing/UUEFI.efi bash "$INSTALL_SCRIPT" 2>&1 || true)
if echo "$missing_binary_output" | grep -q "Refusing to fall back to BootX64.efi"; then
pass "uuefi-install requires a real UUEFI binary"
else
fail "uuefi-install still allows a BootX64 placeholder fallback"
fi

echo
echo "======================="
echo "Test Summary"
echo "======================="
echo -e "${GREEN}Passed:${NC} ${PASSED}"
echo -e "${RED}Failed:${NC} ${FAILED}"
echo

if [ "$FAILED" -eq 0 ]; then
echo -e "${GREEN}✓ All UUEFI host-helper tests passed!${NC}"
exit 0
else
echo -e "${RED}✗ Some UUEFI host-helper tests failed${NC}"
exit 1
fi
7 changes: 5 additions & 2 deletions components/core/scripts/uefi-tools/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ Scripts for UEFI operations and diagnostics.

## UUEFI Operations

- `uuefi-install.sh` - Install UUEFI to system ESP
- `uuefi-apply.sh` - Set BootNext for one-time UUEFI boot
- `uuefi-install.sh` - Install UUEFI to system ESP (**alpha-gated pending broader host-side validation**)
- `uuefi-apply.sh` - Set BootNext for one-time UUEFI boot (**alpha-gated pending broader host-side validation**)
- `uuefi-report.sh` - Display UEFI system status
- `host-uuefi-once.sh` - Boot UUEFI once on host

Expand All @@ -17,6 +17,9 @@ Scripts for UEFI operations and diagnostics.
## Usage

```bash
# Alpha safety gate for host-side mutating helpers
export PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1

# Install UUEFI
sudo ./scripts/uefi-tools/uuefi-install.sh

Expand Down
11 changes: 9 additions & 2 deletions components/core/scripts/uefi-tools/uuefi-apply.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,15 +3,22 @@ set -euo pipefail
cd "$(dirname "$0")/../.."
source includes/lib/common.sh

info "☠ UUEFI apply (set BootNext for selected app)"

# Dry-run mode: UUEFI_DRYRUN=1
DRY=${UUEFI_DRYRUN:-}
run() { if [ -n "$DRY" ]; then echo "DRYRUN: $*"; else "$@"; fi }
need_sudo() {
if [ -n "$DRY" ]; then echo sudo -n "$@" || true; else sudo -n "$@"; fi
}

require_alpha_opt_in() {
[ "${PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST:-0}" = "1" ] && return 0
die "uuefi-apply is gated off for the alpha release pending broader host-side validation. Use uuefi-report for read-only inspection, track follow-up in docs/TODO.md, and only override with PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1 during deliberate maintainer testing."
}

require_alpha_opt_in

info "☠ UUEFI apply (set BootNext for selected app)"

if ! command -v efibootmgr >/dev/null 2>&1; then
die "efibootmgr not installed"
fi
Expand Down
22 changes: 11 additions & 11 deletions components/core/scripts/uefi-tools/uuefi-install.sh
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,21 @@ set -euo pipefail
cd "$(dirname "$0")/../.."
source includes/lib/common.sh

info "☠ Installing UUEFI.efi to system ESP"

# Config
EESP=${EESP:-/boot/efi}
UUEFI_SRC=${UUEFI_SRC:-staging/boot/UUEFI.efi}
OUT_DIR="out/uuefi"
ensure_dir "$OUT_DIR"

require_alpha_opt_in() {
[ "${PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST:-0}" = "1" ] && return 0
die "uuefi-install is gated off for the alpha release pending broader host-side validation. Use uuefi-report for read-only inspection, track follow-up in docs/TODO.md, and only override with PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1 during deliberate maintainer testing."
}

require_alpha_opt_in

info "☠ Installing UUEFI.efi to system ESP"

need_sudo() {
if sudo -n true 2>/dev/null; then
sudo -n "$@"
Expand All @@ -19,15 +26,9 @@ need_sudo() {
fi
}

# Resolve source binary (fallback to BootX64.efi if UUEFI.efi missing)
# Resolve source binary
if [ ! -f "$UUEFI_SRC" ]; then
warn "UUEFI source not found at $UUEFI_SRC"
if [ -f out/staging/BootX64.efi ]; then
warn "Falling back to out/staging/BootX64.efi as UUEFI placeholder"
UUEFI_SRC="out/staging/BootX64.efi"
else
die "No UUEFI.efi or out/staging/BootX64.efi present. Build or provide UUEFI.efi first."
fi
die "UUEFI source not found at $UUEFI_SRC. Refusing to fall back to BootX64.efi for alpha safety; provide the real UUEFI.efi binary explicitly."
fi

# Locate ESP mount
Expand Down Expand Up @@ -116,4 +117,3 @@ echo " APP=UUEFI EFI_DISK=$EFI_DISK EFI_PART=$EFI_PART ./pf.py uuefi-apply"
else
echo " APP=UUEFI EFI_DISK=/dev/sdX EFI_PART=1 ./pf.py uuefi-apply"
fi

6 changes: 3 additions & 3 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -230,11 +230,11 @@ Tools for managing UEFI boot entries:
- `os-boot-clean`: Clean stale UEFI boot entries
- `os-mok-enroll`: Enroll MOK keys for module signing
- `os-mok-list-keys`: List available MOK certificates
- `uuefi-install`: Install UUEFI.efi to system ESP
- `uuefi-apply`: Set BootNext for one-time UUEFI boot
- `uuefi-install`: Install UUEFI.efi to system ESP (**alpha-gated pending broader host-side validation**)
- `uuefi-apply`: Set BootNext for one-time UUEFI boot (**alpha-gated pending broader host-side validation**)
- `uuefi-report`: Display system security status

**Status**: Scripts implemented, tested on real hardware
**Status**: `uuefi-report` is shipped for alpha; host-side mutating helpers stay gated unless `PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1` is set during deliberate maintainer testing

#### 4. **QEMU Testing**
Comprehensive QEMU-based testing:
Expand Down
4 changes: 3 additions & 1 deletion docs/TODO.md
Original file line number Diff line number Diff line change
Expand Up @@ -225,10 +225,12 @@ The UUEFI diagnostic tool has significantly evolved. The issue noted it was "rea

- [ ] Install `efitools` (`cert-to-efi-sig-list`) to unblock `secure-make-auth` and downstream tasks
- [ ] Install `qemu-system-x86_64` + `ovmf` + `mtools` to enable QEMU test suite
- [ ] Add broader host-side validation for `uuefi-install` / `uuefi-apply` before removing the alpha gate (`PHOENIXBOOT_ALPHA_ALLOW_UNTESTED_UUEFI_HOST=1`)
- [ ] Add end-to-end coverage for the DoD CLI delegation paths (`list` / unknown-command fallback) in CI, not just the main CLI smoke script
- [ ] Install EDK2 toolchain to enable `build-build` and UEFI binary compilation
- [ ] Fix `pf` binary installation so `pf.py list` and all task-list UX works correctly (see `.pf_fix.py` for patch details)
- [ ] Add `pf` binary availability check to `scripts/maintenance/toolchain-check.sh`
- [ ] Investigate `test-cli` test 6 failure: `phoenixboot list` falls through to `pf.py` which requires `pf` binary
- [x] Make `phoenixboot` / `phoenixboot-dod` fail loudly with install hints when `pf` exists but is not actually runnable

## Modularity Follow-up

Expand Down
1 change: 1 addition & 0 deletions pb
62 changes: 59 additions & 3 deletions phoenixboot
Original file line number Diff line number Diff line change
Expand Up @@ -104,6 +104,11 @@ run_pf() {
"Then retry. See ALPHA_RELEASE_PLAN.md and docs/AGENTS.md for more."
fi

if ! pf_runner_probe; then
print_pf_runner_unavailable "$*"
exit 127
fi

CURRENT_ACTION="running pf task(s): $*"
"$PF_SCRIPT" "$@"
}
Expand Down Expand Up @@ -142,8 +147,60 @@ require_existing_task_paths() {
fi
}

pf_runner_launcher() {
if [ -x "${PHOENIX_ROOT:-.}/pf" ]; then
printf '%s\n' "${PHOENIX_ROOT}/pf"
return 0
fi

command -v pf 2>/dev/null || return 1
}

pf_runner_probe() {
if [ "${PF_RUNNER_PROBED:-0}" = "1" ]; then
[ "${PF_RUNNER_PROBE_STATUS:-1}" -eq 0 ]
return
fi

PF_RUNNER_PROBED=1
PF_RUNNER_PROBE_STATUS=1
PF_RUNNER_PROBE_OUTPUT=""
PF_RUNNER_LAUNCHER=""

if ! PF_RUNNER_LAUNCHER="$(pf_runner_launcher)"; then
PF_RUNNER_PROBE_OUTPUT="No vendored ./pf launcher or PATH-installed pf executable was found."
return 1
fi

set +e
PF_RUNNER_PROBE_OUTPUT="$("$PF_RUNNER_LAUNCHER" version 2>&1)"
PF_RUNNER_PROBE_STATUS=$?
set -e

[ "$PF_RUNNER_PROBE_STATUS" -eq 0 ]
}

has_pf_runner() {
[ -x "${PHOENIX_ROOT:-.}/pf" ] || command -v pf >/dev/null 2>&1
pf_runner_probe >/dev/null 2>&1
}

print_pf_runner_unavailable() {
pf_runner_probe >/dev/null 2>&1 || true

local attempted_args="$1"
local launcher="${PF_RUNNER_LAUNCHER:-$PHOENIX_ROOT/pf}"
local probe_summary="${PF_RUNNER_PROBE_OUTPUT:-Unknown pf runner failure.}"

probe_summary="$(printf '%s\n' "$probe_summary" | head -n 1)"

echo "phoenixboot ERROR: cannot execute PhoenixBoot task(s)." >&2
echo " - Attempted pf.py arguments: $attempted_args" >&2
echo " - Probe command: $launcher version" >&2
echo " - Probe result: $probe_summary" >&2
echo " - Install hints:" >&2
echo " - If the vendored launcher is missing, restore it with: git checkout -- pf-runner pf" >&2
echo " - If the launcher exists but python deps are missing, run: pip install --user -e ./pf-runner" >&2
echo " - You can also point PF_PYTHON at a working Python 3 interpreter if needed." >&2
}

print_builtin_list() {
Expand Down Expand Up @@ -262,8 +319,7 @@ case "$cmd" in
else
print_builtin_list
echo
echo "Full pf task listing is unavailable because the 'pf' runner is not installed." >&2
echo "Install pf-runner or make 'pf' available in PATH to list all project tasks." >&2
print_pf_runner_unavailable "list"
fi
;;

Expand Down
Loading