From 8bf1f7022d6c74e77fc3836b0e489550abb7c73e Mon Sep 17 00:00:00 2001 From: Vasilito Date: Sat, 9 May 2026 01:33:45 +0100 Subject: [PATCH] fix: update phase0 boot evidence diagnostics --- .../scripts/diagnose-phase0-boot-evidence.sh | 261 ++++++++++++++++++ 1 file changed, 261 insertions(+) create mode 100755 local/scripts/diagnose-phase0-boot-evidence.sh diff --git a/local/scripts/diagnose-phase0-boot-evidence.sh b/local/scripts/diagnose-phase0-boot-evidence.sh new file mode 100755 index 0000000000..a4f09d444b --- /dev/null +++ b/local/scripts/diagnose-phase0-boot-evidence.sh @@ -0,0 +1,261 @@ +#!/usr/bin/env bash +# diagnose-phase0-boot-evidence.sh — Phase 0 boot evidence collector +# +# Checks a mounted/extracted Red Bear root tree, or the running root when no +# --root is supplied, for the boot-critical evidence needed to diagnose modern +# hardware bring-up: PCI driver config locations, init service wiring, driver +# binary presence, and optional driver-manager boot-timeline evidence. + +set -euo pipefail + +ROOT="/" +BOOT_LOG="" + +usage() { + cat <<'USAGE' +Usage: + local/scripts/diagnose-phase0-boot-evidence.sh [--root ] [--boot-log ] + +Examples: + local/scripts/diagnose-phase0-boot-evidence.sh --root /mnt/redbear-root + local/scripts/diagnose-phase0-boot-evidence.sh --boot-log serial.log + +Exit codes: + 0 — evidence complete enough for Phase 0 diagnostics + 1 — missing boot-critical evidence found + 2 — usage or input path error +USAGE +} + +while [ $# -gt 0 ]; do + case "$1" in + --root) + [ $# -ge 2 ] || { usage >&2; exit 2; } + ROOT="$2" + shift 2 + ;; + --boot-log) + [ $# -ge 2 ] || { usage >&2; exit 2; } + BOOT_LOG="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; + *) + echo "ERROR: unknown argument: $1" >&2 + usage >&2 + exit 2 + ;; + esac +done + +if [ ! -d "$ROOT" ]; then + echo "ERROR: root path is not a directory: $ROOT" >&2 + exit 2 +fi + +if [ -n "$BOOT_LOG" ] && [ ! -f "$BOOT_LOG" ]; then + echo "ERROR: boot log not found: $BOOT_LOG" >&2 + exit 2 +fi + +failures=0 +warnings=0 + +join_root() { + local path="$1" + if [ "$ROOT" = "/" ]; then + printf '/%s' "${path#/}" + else + printf '%s/%s' "${ROOT%/}" "${path#/}" + fi +} + +section() { + echo "" + echo "=== $* ===" +} + +ok() { echo " OK: $*"; } +warn() { echo " WARN: $*"; warnings=$((warnings + 1)); } +fail() { echo " FAIL: $*"; failures=$((failures + 1)); } + +file_exists() { [ -f "$(join_root "$1")" ]; } +dir_exists() { [ -d "$(join_root "$1")" ]; } +executable_exists() { [ -x "$(join_root "$1")" ]; } + +count_files() { + local dir="$1" + if dir_exists "$dir"; then + find "$(join_root "$dir")" -maxdepth 1 -type f 2>/dev/null | wc -l | tr -d ' ' + else + printf '0' + fi +} + +config_contains_driver() { + local driver="$1" + shift + local dir path + for dir in "$@"; do + path="$(join_root "$dir")" + [ -d "$path" ] || continue + if grep -Rqs "\b${driver}\b" "$path"; then + return 0 + fi + done + return 1 +} + +service_cmd() { + local service="$1" + local path + for path in "/etc/init.d/$service" "/usr/lib/init.d/$service" "/lib/init.d/$service"; do + if file_exists "$path"; then + grep -E '^[[:space:]]*cmd[[:space:]]*=' "$(join_root "$path")" 2>/dev/null | head -n 1 || true + return 0 + fi + done + return 1 +} + +section "Phase 0 root" +echo " root: $ROOT" +[ -n "$BOOT_LOG" ] && echo " boot_log: $BOOT_LOG" + +section "PCI config directories" +pcid_count=0 +for dir in /usr/lib/pcid.d /lib/pcid.d /etc/pcid.d; do + count="$(count_files "$dir")" + echo " $dir: $count files" + pcid_count=$((pcid_count + count)) +done + +driversd_count=0 +for dir in /usr/lib/drivers.d /lib/drivers.d /etc/drivers.d; do + count="$(count_files "$dir")" + echo " $dir: $count files" + driversd_count=$((driversd_count + count)) +done + +if [ "$pcid_count" -eq 0 ] && [ "$driversd_count" -eq 0 ]; then + fail "no pcid.d or drivers.d config files found; driver-manager cannot match devices" +elif [ "$driversd_count" -gt 0 ]; then + ok "drivers.d config files present" +elif [ "$pcid_count" -gt 0 ]; then + ok "pcid.d config files present" +else + warn "unexpected PCI config directory state" +fi + +section "Boot-critical driver config coverage" +check_driver_config() { + local driver="$1" + local description="$2" + if config_contains_driver "$driver" /usr/lib/pcid.d /lib/pcid.d /etc/pcid.d /usr/lib/drivers.d /lib/drivers.d /etc/drivers.d; then + ok "$description has config entry containing '$driver'" + else + fail "$description has no config entry containing '$driver'" + fi +} + +check_driver_config xhcid "xHCI USB" +check_driver_config nvmed "NVMe storage" +check_driver_config ihdad "Intel HDA audio" +check_driver_config redox-drm "DRM/KMS graphics" + +section "Boot-critical binary coverage" +check_binary_anywhere() { + local description="$1" + shift + local candidate + for candidate in "$@"; do + if executable_exists "$candidate"; then + ok "$description binary exists at $candidate" + return 0 + fi + done + fail "$description binary missing; checked: $*" +} + +check_binary_anywhere "pcid" /usr/bin/pcid /usr/lib/drivers/pcid +check_binary_anywhere "driver-manager" /usr/bin/driver-manager /usr/lib/drivers/driver-manager +if executable_exists /usr/bin/pcid-spawner || executable_exists /usr/lib/drivers/pcid-spawner; then + ok "pcid-spawner compatibility binary exists" +else + warn "pcid-spawner compatibility binary missing; this is acceptable when driver-manager owns spawning" +fi +check_binary_anywhere "xHCI" /usr/lib/drivers/xhcid /usr/bin/xhcid +check_binary_anywhere "NVMe" /usr/lib/drivers/nvmed /usr/bin/nvmed +check_binary_anywhere "Intel HDA" /usr/lib/drivers/ihdad /usr/bin/ihdad +check_binary_anywhere "DRM/KMS" /usr/bin/redox-drm /usr/lib/drivers/redox-drm + +section "Init service wiring" +if cmd_line="$(service_cmd 00_driver-manager.service)" && [ -n "$cmd_line" ]; then + ok "00_driver-manager.service present: $cmd_line" +else + fail "00_driver-manager.service missing from init service directories" +fi + +if cmd_line="$(service_cmd 00_pcid-spawner.service)" && [ -n "$cmd_line" ]; then + ok "00_pcid-spawner.service compatibility alias present: $cmd_line" +else + warn "00_pcid-spawner.service compatibility alias not present" +fi + +if [ "$driversd_count" -gt 0 ] && service_cmd 00_driver-manager.service >/dev/null 2>&1; then + cmd_line="$(service_cmd 00_driver-manager.service)" + if echo "$cmd_line" | grep -q 'pcid-spawner'; then + warn "00_driver-manager.service still runs pcid-spawner while drivers.d files exist" + fi +fi + +section "Optional boot log evidence" +if [ -z "$BOOT_LOG" ]; then + warn "no --boot-log supplied; skipping runtime evidence checks" +else + if grep -q '"event":"bus_enumerated"' "$BOOT_LOG"; then + ok "driver-manager bus enumeration timeline evidence found" + grep '"event":"bus_enumerated"' "$BOOT_LOG" | sed 's/^/ /' + elif grep -q 'pcid-spawner: phase0 summary' "$BOOT_LOG"; then + ok "legacy pcid-spawner phase0 summary found" + grep 'pcid-spawner: phase0 summary' "$BOOT_LOG" | sed 's/^/ /' + else + fail "driver-manager bus enumeration evidence not found in boot log" + fi + + if grep -q '"event":"probe".*"status":"bound"' "$BOOT_LOG"; then + ok "driver-manager bound-probe evidence found" + elif grep -q 'pcid-spawner: matched PCI' "$BOOT_LOG"; then + ok "legacy matched PCI driver evidence found" + else + warn "no bound PCI driver evidence found" + fi + + if grep -q '"event":"bus_enumeration_failed"' "$BOOT_LOG"; then + warn "driver-manager bus enumeration failures found" + grep '"event":"bus_enumeration_failed"' "$BOOT_LOG" | sed 's/^/ /' + elif grep -q '"event":"probe".*"status":"failed"' "$BOOT_LOG"; then + warn "driver-manager failed-probe evidence found" + grep '"event":"probe".*"status":"failed"' "$BOOT_LOG" | sed 's/^/ /' + elif grep -q 'pcid-spawner: unmatched PCI' "$BOOT_LOG"; then + warn "legacy unmatched PCI devices found; inspect detailed pcid-spawner logs" + grep 'pcid-spawner: unmatched PCI' "$BOOT_LOG" | sed 's/^/ /' + else + ok "no bus enumeration failure or failed-probe evidence in supplied boot log" + fi +fi + +section "Summary" +echo " failures: $failures" +echo " warnings: $warnings" + +if [ "$failures" -gt 0 ]; then + echo "FAILED: Phase 0 boot evidence is incomplete." >&2 + exit 1 +fi + +echo "OK: Phase 0 boot evidence checks passed." +exit 0