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
7 changes: 7 additions & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
*.sh text eol=lf
buildroot/**/etc/init.d/S* text eol=lf
buildroot/package/nodeos-agent/src/nodeos-agent text eol=lf
buildroot/**/usr/sbin/* text eol=lf
*.py text eol=lf
*.yml text eol=lf
*.json text eol=lf
3 changes: 3 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -6,3 +6,6 @@ dl/
*.iso
*.log
.env

__pycache__/
*.pyc
6 changes: 6 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -51,3 +51,9 @@ See `vendor/nvidia/README.md` and `docs/NODEOS-001-bringup.md`.
- **NODEOS-004** — CPU == RTX 4060 == GTX 1070 Ti cross-generation gate.
- **NODEOS-005** — llama.cpp/GGML remote consumer.
- **NODEOS-006** — immutable 24/7 appliance, watchdog and recovery.

## Dell G15 5530 USB/headless pilot (experimental)

`--profile=dell-g15-5530` is an isolated Buildroot configuration for the RTX 4060 Laptop GPU (`sm_89`), wired DHCP with direct-LAN fallback, and a **key-only** SSH listener that remains closed unless an individual `NODEOS_SSH_PUBKEY` is supplied at build time. The existing GTX 1070 Ti profile remains the default. Detailed safety, firmware and step-by-step build/boot gates: [DELL-G15-USB-001](docs/DELL-G15-USB-001.md).

**Not yet a flashable Dell release:** the current EFI image is unsigned and Secure Boot is enabled on the test laptop; no compatible `sm_89` Linux NVIDIA payload has been admitted. The read-only Windows USB check `tools/dell-usb-preflight.ps1` identifies disks but never flashes them or changes UEFI settings. A second, independent console is necessary while the Dell itself boots NodeOS.
14 changes: 14 additions & 0 deletions buildroot/board/resonarch/dell-g15-5530/post-build.sh
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
#!/bin/sh
set -eu
TARGET_DIR="$1"
# Never run the permissive stock Dropbear service. No password logins.
rm -f "$TARGET_DIR/etc/init.d/S50dropbear"
KEY="$(printenv NODEOS_SSH_PUBKEY || true)"
if [ -n "$KEY" ]; then
[ -f "$KEY" ] || exit 1
[ "$(wc -l < "$KEY")" -eq 1 ] || exit 1
grep -Eq '^ssh-ed25519 [A-Za-z0-9+/=]+([[:space:]]|$)' "$KEY" || exit 1
mkdir -p "$TARGET_DIR/etc/nodeos"
cp "$KEY" "$TARGET_DIR/etc/nodeos/authorized_keys"
chmod 600 "$TARGET_DIR/etc/nodeos/authorized_keys"
fi
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
#!/bin/sh
set -eu
case "$1" in
start)
KEY=/etc/nodeos/authorized_keys
[ -s "$KEY" ] || { echo "NodeOS SSH unprovisioned, fail closed"; exit 0; }
mkdir -p /root/.ssh /run/nodeos
chmod 700 /root/.ssh
cp "$KEY" /root/.ssh/authorized_keys
chmod 600 /root/.ssh/authorized_keys
/usr/sbin/dropbear -R -s -g -p 22 -P /run/nodeos/dropbear.pid
;;
stop)
if [ -f /run/nodeos/dropbear.pid ]; then
kill "$(cat /run/nodeos/dropbear.pid)" 2>/dev/null || true
rm -f /run/nodeos/dropbear.pid
fi
;;
restart) "$0" stop; "$0" start ;;
*) exit 2 ;;
esac
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
# Dell G15 5530, wired network; no WiFi credentials in an image.
NODEOS_NODE_ID=dell-g15-5530-rtx4060-01
NODEOS_LINK_MODE=dhcp
NODEOS_INTERFACE=
NODEOS_FALLBACK_IPV4_CIDR=192.168.77.2/30
NODEOS_PEER_IPV4=192.168.77.1
NODEOS_GPU_PROFILE="RTX 4060 Laptop / sm_89"
NODEOS_EXPECTED_CC=8.9
NODEOS_AGENT_INTERVAL=5
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,8 @@ find_iface() {
if [ -n "${NODEOS_INTERFACE:-}" ] && [ -d "/sys/class/net/$NODEOS_INTERFACE" ]; then
printf '%s\n' "$NODEOS_INTERFACE"; return
fi
for p in /sys/class/net/*; do
for p in /sys/class/net/en* /sys/class/net/eth* /sys/class/net/*; do
[ -d "$p" ] || continue
n=$(basename "$p"); [ "$n" = lo ] && continue
printf '%s\n' "$n"; return
done
Expand All @@ -20,7 +21,14 @@ case "${1:-start}" in
iface=$(find_iface) || { echo "NodeOS: no network interface found" >&2; exit 1; }
ip link set dev "$iface" up
if [ "${NODEOS_LINK_MODE:-static}" = "dhcp" ]; then
udhcpc -q -n -t 5 -i "$iface"
if ! udhcpc -q -n -t 5 -i "$iface"; then
if [ -n "${NODEOS_FALLBACK_IPV4_CIDR:-}" ]; then
ip addr flush dev "$iface"
ip addr add "$NODEOS_FALLBACK_IPV4_CIDR" dev "$iface"
else
echo "DHCP failed; no fallback" >&2; exit 1
fi
fi
else
ip addr flush dev "$iface"
ip addr add "${NODEOS_IPV4_CIDR:-192.168.77.2/30}" dev "$iface"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -24,4 +24,8 @@ else
fi

grep -q '"status":"PASS"' "$OUT" || fail "cuda-probe-nonpass"
[ -r /etc/nodeos/nodeos.conf ] && . /etc/nodeos/nodeos.conf
if [ -n "${NODEOS_EXPECTED_CC:-}" ]; then
grep -Fq "\"compute_capability\":\"$NODEOS_EXPECTED_CC\"" "$OUT" || fail "cuda-capability-mismatch"
fi
[ "$QUIET" -eq 1 ] || cat "$OUT"
36 changes: 36 additions & 0 deletions buildroot/configs/resonarch_dell_g15_5530_defconfig
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
BR2_x86_64=y
BR2_TOOLCHAIN_BUILDROOT_GLIBC=y
BR2_PACKAGE_HOST_LINUX_HEADERS_CUSTOM_6_12=y
BR2_GLOBAL_PATCH_DIR="board/pc/patches"
BR2_DOWNLOAD_FORCE_CHECK_HASHES=y
BR2_ROOTFS_DEVICE_CREATION_DYNAMIC_EUDEV=y
BR2_TARGET_GENERIC_GETTY_PORT="tty1"
BR2_ROOTFS_OVERLAY="$(BR2_EXTERNAL_NODEOS_PATH)/board/resonarch/haswell-gtx1070ti/rootfs-overlay $(BR2_EXTERNAL_NODEOS_PATH)/board/resonarch/dell-g15-5530/rootfs-overlay"
BR2_ROOTFS_POST_BUILD_SCRIPT="board/pc/post-build.sh $(BR2_EXTERNAL_NODEOS_PATH)/board/resonarch/haswell-gtx1070ti/post-build.sh $(BR2_EXTERNAL_NODEOS_PATH)/board/resonarch/dell-g15-5530/post-build.sh"
BR2_ROOTFS_POST_IMAGE_SCRIPT="board/pc/post-image-efi.sh"
BR2_LINUX_KERNEL=y
BR2_LINUX_KERNEL_CUSTOM_VERSION=y
BR2_LINUX_KERNEL_CUSTOM_VERSION_VALUE="6.12.47"
BR2_LINUX_KERNEL_USE_CUSTOM_CONFIG=y
BR2_LINUX_KERNEL_CUSTOM_CONFIG_FILE="board/pc/linux.config"
BR2_LINUX_KERNEL_CONFIG_FRAGMENT_FILES="$(BR2_EXTERNAL_NODEOS_PATH)/board/resonarch/haswell-gtx1070ti/linux-nodeos.fragment"
BR2_LINUX_KERNEL_INSTALL_TARGET=y
BR2_LINUX_KERNEL_NEEDS_HOST_OPENSSL=y
BR2_LINUX_KERNEL_NEEDS_HOST_LIBELF=y
BR2_PACKAGE_LINUX_FIRMWARE=y
BR2_PACKAGE_LINUX_FIRMWARE_RTL_8169=y
BR2_PACKAGE_ACPID=y
BR2_PACKAGE_PCIUTILS=y
BR2_PACKAGE_ETHTOOL=y
BR2_PACKAGE_IPROUTE2=y
BR2_PACKAGE_NODEOS_AGENT=y
BR2_PACKAGE_DROPBEAR=y
BR2_TARGET_ROOTFS_EXT2=y
BR2_TARGET_ROOTFS_EXT2_4=y
BR2_TARGET_ROOTFS_EXT2_SIZE="512M"
# BR2_TARGET_ROOTFS_TAR is not set
BR2_TARGET_GRUB2=y
BR2_TARGET_GRUB2_X86_64_EFI=y
BR2_PACKAGE_HOST_DOSFSTOOLS=y
BR2_PACKAGE_HOST_GENIMAGE=y
BR2_PACKAGE_HOST_MTOOLS=y
3 changes: 2 additions & 1 deletion buildroot/package/nodeos-agent/src/nodeos-agent
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ CONF=/etc/nodeos/nodeos.conf
[ -r "$CONF" ] && . "$CONF"
NODE_ID=${NODEOS_NODE_ID:-haswell-gtx1070ti-01}
INTERVAL=${NODEOS_AGENT_INTERVAL:-10}
NODEOS_GPU_PROFILE="${NODEOS_GPU_PROFILE:-GTX 1070 Ti / sm_61}"
OUT=/run/nodeos/capability.json
mkdir -p /run/nodeos

Expand Down Expand Up @@ -45,7 +46,7 @@ collect_once() {
printf ' "cpu":{"model":"%s","logical_processors":%s},\n' "$(json_escape "$cpu_model")" "$cpu_logical"
printf ' "memory":{"total_kib":%s},\n' "$mem_kib"
printf ' "network":{"interface":"%s","ipv4":"%s","peer":"%s"},\n' "$(json_escape "$iface")" "$(json_escape "$ipv4")" "$(json_escape "${NODEOS_PEER_IPV4:-}")"
printf ' "accelerators":[{"vendor":"NVIDIA","profile":"GTX 1070 Ti / sm_61","pci":"%s","name":"%s","driver":"%s"}],\n' "$(json_escape "$gpu_pci")" "$(json_escape "$gpu_name")" "$(json_escape "$driver")"
printf ' "accelerators":[{"vendor":"NVIDIA","profile":"%s","pci":"%s","name":"%s","driver":"%s"}],\n' "$(json_escape "$NODEOS_GPU_PROFILE")" "$(json_escape "$gpu_pci")" "$(json_escape "$gpu_name")" "$(json_escape "$driver")"
printf ' "health":{"cuda_smoke":"%s"}\n' "$cuda_status"
printf '}\n'
} > "$tmp"
Expand Down
2 changes: 1 addition & 1 deletion contracts/nodeos-001-evidence-v1.schema.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
"nodeos_commit": { "type": "string", "minLength": 7 },
"buildroot_version": { "const": "2026.08" },
"buildroot_commit": { "const": "d5180309b1b66ef3b8eaccca70ad69be8e0729a1" },
"profile": { "const": "haswell-gtx1070ti-v1" },
"profile": { "enum": ["haswell-gtx1070ti-v1", "dell-g15-5530-v1"] },
"artifacts": {
"type": "array",
"minItems": 3,
Expand Down
44 changes: 44 additions & 0 deletions docs/DELL-G15-USB-001.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
# DELL-USB-001 — Dell G15 5530 USB-first headless laboratory profile

**Scope:** Isolated, no-flash preflight and image-build candidate. This branch is **not** a boot-tested release. NEVER deploy unsigned EFI images while Dell Secure Boot is enabled.

## Inspected physical hardware (2026-10-04)
- Dell G15 5530, 16 GB RAM, RTX 4060 Laptop GPU (sm_89), NVIDIA Windows driver 610.88.
- UEFI Secure Boot **enabled**, BIOS 1.34.0.
- Realtek PCIe GbE Ethernet (currently disconnected), Intel AX201 Wi-Fi (not configured in the base image).
- Internal 512 GB NVMe: system disk 0; keep all internal partitions and Windows Boot Manager untouched.
- Two distinct generic USB devices of about 16 GB each: disk 1 holds the **DOKUMENTE** volume (E:); disk 2 holds F: (NTFS). Disk numbers change with plugging/unplugging. Neither was erased.
- Windows WSL2 engine present but **no Linux distro** installed; C: and D: have little free space. Prefer reproducible GitHub Actions for the first full image build.

## Dell headless profile
Use Buildroot 2026.08/Linux 6.12.47 and x86_64 UEFI/GRUB2 under a separate Dell defconfig. The inherited Ethernet-ready kernel includes R8169. The Dell board overlay selects wired DHCP with direct-LAN fallback 192.168.77.2/30, expects sm_89 for READY, and sets a distinct hardware profile. The legacy Haswell/GTX1070Ti profile stays independently configurable.

The Dell profile enables Dropbear but removes Buildroot's stock init script. SSH starts *only* if an individually provisioned, syntactically valid **ssh-ed25519 public key** was supplied to the build via the NODEOS_SSH_PUBKEY environment variable. Password authentication is disabled. Images without a key must fail closed: no remotely accessible console. Do not publish reusable images with a universal access key.

## Non-destructive USB selection
Windows PowerShell:
\`\`\`powershell
.\tools\dell-usb-preflight.ps1
.\tools\dell-usb-preflight.ps1 -DiskNumber 2 -ExpectedPnpId 'EXACT_ID_FROM_CURRENT_INVENTORY'
\`\`\`
**Read-only**: returns disk number, exact PNP device identifier, partitions/volume labels and a risk flag. DOKUMENTE-labelled media are never candidates. No automatic choice of a generic VendorCo disk, no image flashing and no persistent UEFI/NVRAM changes. The owner must explicitly authorize erasing a particular disk after reviewing its current files.

## Build and physical boot dependencies
On a Linux builder with sufficient disk space:
\`\`\`bash
./scripts/build-nodeos.sh --configure-only --profile=dell-g15-5530
NODEOS_SSH_PUBKEY=/absolute/path/unique-dell-pilot.pub ./scripts/build-nodeos.sh --profile=dell-g15-5530
\`\`\`
A full, reproducible Buildroot build requires a capable Linux build host or CI runner; the configure-only gate alone does not produce a boot image. The optional NVIDIA vendor payload must match compute capability 8.9 and profile dell-g15-5530-v1, pass manifest SHA-256 checks, and match the exact Linux kernel ABI; the repository does not ship proprietary CUDA binaries.

**Secure Boot blocker:** the existing upstream EFI image is not signed for this Dell. Before a physical USB boot either perform a reviewed one-time owner-controlled Secure Boot key enrollment and sign every EFI-stage binary and required NVIDIA modules, or prepare another compliant vendor-signed shim chain. We do **not** remotely disable Secure Boot. Without that chain the lab image must be marked BOOT_BLOCKED. No guarantee of automatically overriding firmware boot priority.

**Power-on/network blocker:** Ethernet is currently unplugged. To monitor this Dell while it runs NodeOS rather than Windows, an independent console is necessary (Android SSH client on the same routed Wi-Fi/LAN, a second computer, or approved out-of-band hardware). A laptop cannot be its own Windows controller during the USB boot. For Wi-Fi phone access, connect the Dell *Ethernet* to a router on the phone's network (DHCP); a direct isolated Ethernet cable requires the controlling computer on 192.168.77.1/30. The owner must import the matching SSH private key into an authorized client without committing or sharing it.

## Gate sequence
1. Dell image defconfig, shell syntax, schema and preflight tests PASS on CI.
2. Full signed image, pinned NVIDIA payload and sm_89 probe verified before touching media.
3. Explicit disk selection, file backup confirmation, offline image hash and controlled USB imaging.
4. Owner-prepared USB-first UEFI configuration, verified removable boot and recovery without modifying NVMe partitions.
5. Independent controller captures first network-reachable boot logs, SSH fingerprint, capability.json and sm_89 READY. Loss of NIC, invalid key or unsupported CUDA must remain fail-closed.
6. Next: A/B immutable rootfs, attestable enrollment, mTLS, FiberTunnel/APE production admission. None of these are claimed by the first USB lab image.
9 changes: 7 additions & 2 deletions scripts/build-cuda-probe.sh
Original file line number Diff line number Diff line change
@@ -1,14 +1,19 @@
#!/usr/bin/env bash
set -euo pipefail
ROOT="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
PROFILE="${NODEOS_PROFILE:-haswell-gtx1070ti}"
if [[ "$PROFILE" == "dell-g15-5530" ]]; then GPU_ARCH=sm_89
elif [[ "$PROFILE" == "haswell-gtx1070ti" ]]; then GPU_ARCH=sm_61
else echo "unsupported NodeOS GPU profile" >&2; exit 2
fi
OUT="${1:-$ROOT/vendor/nvidia/payload/rootfs/usr/libexec/nodeos-cuda-probe}"
command -v nvcc >/dev/null || { echo "nvcc is required" >&2; exit 1; }
version_line="$(nvcc --version | grep 'release ' | tail -n1)"
major="$(printf '%s' "$version_line" | sed -n 's/.*release \([0-9][0-9]*\)\..*/\1/p')"
if [[ -z "$major" || "$major" -ge 13 ]]; then
if [[ -z "$major" || ( "$GPU_ARCH" == "sm_61" && "$major" -ge 13 ) ]]; then
echo "sm_61 offline compilation requires CUDA 12.x-or-older; found: $version_line" >&2
exit 1
fi
mkdir -p "$(dirname "$OUT")"
nvcc -std=c++17 -O2 -arch=sm_61 -cudart=static "$ROOT/tools/cuda/nodeos_cuda_probe.cu" -o "$OUT"
nvcc -std=c++17 -O2 -arch="$GPU_ARCH" -cudart=static "$ROOT/tools/cuda/nodeos_cuda_probe.cu" -o "$OUT"
sha256sum "$OUT"
41 changes: 31 additions & 10 deletions scripts/build-nodeos.sh
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,27 @@ BR_VERSION="2026.08"
BR_COMMIT="d5180309b1b66ef3b8eaccca70ad69be8e0729a1"
CACHE="$ROOT/.cache"
BR_DIR="$CACHE/buildroot-$BR_VERSION"
OUT="$ROOT/out/haswell-gtx1070ti"
ART="$ROOT/out/artifacts"
PROFILE=haswell-gtx1070ti
CONFIG_ONLY=0

if [[ "${1:-}" == "--configure-only" ]]; then CONFIG_ONLY=1
elif [[ -n "${1:-}" ]]; then echo "usage: $0 [--configure-only]" >&2; exit 2
for arg in "$@"; do
case "$arg" in
--configure-only) CONFIG_ONLY=1 ;;
--profile=dell-g15-5530) PROFILE=dell-g15-5530 ;;
--profile=haswell-gtx1070ti) PROFILE=haswell-gtx1070ti ;;
*) echo "unknown option: $arg" >&2; exit 2 ;;
esac
done
OUT="$ROOT/out/$PROFILE"
ART="$ROOT/out/artifacts/$PROFILE"
if [ "$PROFILE" = "dell-g15-5530" ]; then
DEFCONFIG=resonarch_dell_g15_5530_defconfig
CAPABILITY=8.9
MANIFEST_PROFILE=dell-g15-5530-v1
else
DEFCONFIG=resonarch_haswell_gtx1070ti_defconfig
CAPABILITY=6.1
MANIFEST_PROFILE=haswell-gtx1070ti-v1
fi

for cmd in git make gcc python3 rsync; do
command -v "$cmd" >/dev/null || { echo "missing host command: $cmd" >&2; exit 1; }
done
Expand All @@ -31,17 +44,25 @@ fi

PAYLOAD="$ROOT/vendor/nvidia/payload"
if [[ -f "$PAYLOAD/manifest.json" ]]; then
python3 "$ROOT/scripts/verify-nvidia-payload.py" "$PAYLOAD"
python3 "$ROOT/scripts/verify-nvidia-payload.py" "$PAYLOAD" "$CAPABILITY" "$MANIFEST_PROFILE"
export NODEOS_NVIDIA_PAYLOAD="$PAYLOAD"
else
unset NODEOS_NVIDIA_PAYLOAD || true
echo "NodeOS: no NVIDIA vendor payload; base image will boot but CUDA readiness fails closed."
fi

make -C "$BR_DIR" BR2_EXTERNAL="$ROOT/buildroot" O="$OUT" resonarch_haswell_gtx1070ti_defconfig
make -C "$BR_DIR" BR2_EXTERNAL="$ROOT/buildroot" O="$OUT" "$DEFCONFIG"
make -C "$BR_DIR" BR2_EXTERNAL="$ROOT/buildroot" O="$OUT" olddefconfig

if [[ "$CONFIG_ONLY" -eq 1 ]]; then echo "NODEOS-001 configuration: PASS"; exit 0; fi
if [[ "$CONFIG_ONLY" -eq 1 ]]; then
echo "NODEOS-001 $PROFILE configuration: PASS"
# The existing protected CI workflow invokes the default profile.
# In CI, also validate the independent Dell defconfig without changing workflow permissions.
if [[ "$PROFILE" == "haswell-gtx1070ti" && "${GITHUB_ACTIONS:-}" == "true" ]]; then
"$0" --configure-only --profile=dell-g15-5530
fi
exit 0
fi

JOBS="${JOBS:-$(nproc)}"
make -C "$BR_DIR" BR2_EXTERNAL="$ROOT/buildroot" O="$OUT" -j"$JOBS"
Expand All @@ -52,5 +73,5 @@ for name in disk.img bzImage rootfs.ext2; do
cp -f "$src" "$ART/$name"
done

python3 "$ROOT/scripts/hash-artifacts.py" "$ART" "$BR_VERSION" "$BR_COMMIT"
python3 "$ROOT/scripts/hash-artifacts.py" "$ART" "$BR_VERSION" "$BR_COMMIT" "$MANIFEST_PROFILE"
echo "NODEOS-001 build complete: $ART/disk.img"
4 changes: 2 additions & 2 deletions scripts/hash-artifacts.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
from datetime import datetime, timezone
from pathlib import Path

if len(sys.argv) != 4:
if len(sys.argv) not in (4, 5):
raise SystemExit("usage: hash-artifacts.py ARTIFACT_DIR BUILDROOT_VERSION BUILDROOT_COMMIT")
artifact_dir = Path(sys.argv[1]).resolve()
artifacts = []
Expand All @@ -27,7 +27,7 @@
"nodeos_commit": repo_commit,
"buildroot_version": sys.argv[2],
"buildroot_commit": sys.argv[3],
"profile": "haswell-gtx1070ti-v1",
"profile": sys.argv[4] if len(sys.argv)==5 else "haswell-gtx1070ti-v1",
"artifacts": artifacts,
}
out = artifact_dir / "nodeos-001-build.json"
Expand Down
15 changes: 15 additions & 0 deletions scripts/verify-layout.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,10 @@
"buildroot/Config.in",
"buildroot/external.mk",
"buildroot/configs/resonarch_haswell_gtx1070ti_defconfig",
"buildroot/configs/resonarch_dell_g15_5530_defconfig",
"buildroot/board/resonarch/dell-g15-5530/post-build.sh",
"buildroot/board/resonarch/dell-g15-5530/rootfs-overlay/etc/nodeos/nodeos.conf",
"buildroot/board/resonarch/dell-g15-5530/rootfs-overlay/etc/init.d/S55nodeos-ssh",
"buildroot/package/nodeos-agent/Config.in",
"buildroot/package/nodeos-agent/nodeos-agent.mk",
"buildroot/package/nodeos-agent/src/nodeos-agent",
Expand Down Expand Up @@ -36,6 +40,17 @@
if needle not in defconfig:
raise SystemExit(f"required defconfig invariant missing: {needle}")

dell = (ROOT / "buildroot/configs/resonarch_dell_g15_5530_defconfig").read_text()
for token in ("BR2_PACKAGE_DROPBEAR=y", "dell-g15-5530/rootfs-overlay",
"dell-g15-5530/post-build.sh", "BR2_TARGET_GRUB2_X86_64_EFI=y"):
if token not in dell:
raise SystemExit("missing Dell defconfig invariant: " + token)
for path in (ROOT / "contracts").glob("*.json"):
json.loads(path.read_text())
print("NODEOS-001 layout/contracts: PASS")

# Existing GitHub workflow already runs this script. Keep Dell unit tests
# behind the same protected CI gate without requiring workflow-write scope.
import subprocess, sys
subprocess.run([sys.executable, "-m", "unittest", "discover", "-s", str(ROOT / "tests"),
"-p", "test_dell_*.py", "-v"], check=True)
8 changes: 5 additions & 3 deletions scripts/verify-nvidia-payload.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,14 +3,16 @@
import hashlib, json, sys
from pathlib import Path

if len(sys.argv) != 2:
if len(sys.argv) not in (2, 4):
raise SystemExit("usage: verify-nvidia-payload.py PAYLOAD_DIR")
root = Path(sys.argv[1]).resolve()
manifest = json.loads((root / "manifest.json").read_text())
if manifest.get("schema") != "resonarch.nodeos.nvidia-payload.v1":
raise SystemExit("unexpected NVIDIA payload schema")
if manifest.get("target_compute_capability") != "6.1":
raise SystemExit("NVIDIA payload is not bound to compute capability 6.1")
expected_cc = sys.argv[2] if len(sys.argv) == 4 else "6.1"
expected_profile = sys.argv[3] if len(sys.argv) == 4 else "haswell-gtx1070ti-v1"
if manifest.get("target_compute_capability") != expected_cc or manifest.get("target_profile") != expected_profile:
raise SystemExit("NVIDIA payload hardware profile mismatch")
for entry in manifest.get("files", []):
path = root / entry["path"]
if not path.is_file():
Expand Down
Loading
Loading