fix: update phase0 boot evidence diagnostics

This commit is contained in:
2026-05-09 01:33:45 +01:00
parent 4672ddd20c
commit 4c6a53c76d
+261
View File
@@ -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 <mounted-root>] [--boot-log <log-file>]
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