save_bios now distinguishes nvflash driver-loaded refusal from a missing sysfs rom node (ROM BAR not exposed) vs enable denial, and appends host lockdown/Secure Boot state to the note. New opt-in last resort: unload NVIDIA modules, retry nvflash --save, always reload (y/N prompt default n, or --bios-unload). Docs (flow, flags, safety, AGENTS.md invariant) updated to match.
cmp170hx_check
Repo: https://git.qbuissondebon.eu.org/qbuissondebon/cmp170hx_check (SSH push: git@git.ssh.qbuissondebon.eu.org:qbuissondebon/cmp170hx_check.git)
Single-card checker for NVIDIA CMP 170HX cards (PCI IDs 10de:20c2 / 10de:2082) — run it one card at a time: it waits for the card, verifies the PCIe capacitor mod, records PCIe bus health, backs up VBIOS, runs the cmpunlocker verification, offers the opt-in cmpunlocker unlock install (then a cold reboot and a re-run for the final PCIe check), and optionally stresses VRAM. Each card gets its own folder + JSON report named by GPU UUID, so the folders accumulate as you go through your batch (e.g. 23 cards).
Reference harness (auto-cloned into harness/ by preflight):
- 170th-Street — community docs, incl.
modifications/pcie-capacitor-mod.md(the pass criteria:LnkSta Width x16after the mod,x4when missing) - cmpunlocker —
verify.shis executed read-only per card;install.shis only run from the separate, opt-in unlock step (see Safety)
Requirements
- Linux x86-64 (tested target: Ubuntu 26.04), Python 3.8+
- sudo privileges — precondition for
--preflightpackage installation, for privileged checks (PCI rescan, link retrain, sysfs ROM,dmesg,verify.sh), and for the opt-in unlock install pciutils(lspci,setpci),git— installed automatically by preflight- NVIDIA driver with
nvidia-smi(nvidia-open, version list in cmpunlockerdriver/VERSION— 610.xx / 615.xx) for unlock verification — preflight can install it for you (asks first) nvflash— bundled in this repo (nvflash_5.867_linux/x64/nvflash), used directly by the script; no system install needed (see nvflash)- Optional:
vkmarkorvulkan-toolsfor the 5-minute VRAM stress test
Preflight (setup step)
python3 check_cards.py --preflight
On Ubuntu 26.04 this:
- Checks the sudo precondition — runs
sudo -vif needed so credentials are cached; if sudo is unavailable it prints the fix and does not install anything (exit code 3 if blocking tools are still missing) - Installs required packages via
apt-get update && apt-get install:git,pciutils,vulkan-tools,vkmark - Offers to install the NVIDIA driver (
ubuntu-drivers install, falling back to thenvidia-drivermetapackage) whennvidia-smiis missing — reboot afterwards - Clones the two harness repos into
harness/ - Prints a tool status table — the bundled
nvflashis detected automatically and its path is shown
Skip installation with --no-install (no sudo needed at all).
nvflash (bundled in this repo)
The Linux build of NVIDIA's nvflash 5.867 is committed to this repo at
nvflash_5.867_linux/x64/nvflash (plus aarch64/ppc64/x86 variants) — the script
uses it directly, no system-wide installation required.
Binary resolution order:
--nvflash /path/to/nvflash(explicit override)- repo copy:
nvflash_*_linux/<arch>/nvflash, then./nvflash nvflashonPATH(optional system install)
Preflight reports nvflash OK and prints the resolved path.
python3 check_cards.py --preflight # shows: nvflash OK / nvflash: <repo>/nvflash_5.867_linux/x64/nvflash
Notes:
- nvflash requires root: the script invokes it via
sudo— cache credentials withsudo -vfirst, or run the script as root. - Only
--save(read-only backup) is used; if it fails while the NVIDIA driver is bound, the script automatically falls back to the sysfs ROM method. - Do not use the AUR nvflash package (known broken), and ignore Windows
.exebuilds.
Optional — install it system-wide anyway:
sudo install -m 755 nvflash_5.867_linux/x64/nvflash /usr/local/bin/nvflash
nvflash --version
sudo nvflash --list # must show the 170HX
Refreshing the bundled copy: download nvflash_5.867_linux.zip from
https://www.techpowerup.com/download/nvidia-nvflash/ , verify SHA256
73ab51e121129059f1377b3bf21a8001f6649d64af2471455499c803a9c80301, extract and replace
the files (keep the executable bit: chmod +x).
Usage (one card per run)
python3 check_cards.py # check the connected card
python3 check_cards.py --preflight # setup: tools, packages, harness clone
python3 check_cards.py --demo # self-test with fake hardware (no GPU needed)
python3 check_cards.py --unlock # check + run the cmpunlocker install without asking
python3 check_cards.py --help # all flags
Flow of a normal run:
- Waits for a CMP 170HX on the bus — prompts you to insert/reseat the card, Enter triggers a PCI rescan (
qquits) - Folder
cards/<GPU-UUID>/from the auto-read GPU UUID (nvidia-smi); physical serial probed from nvflash and saved toserial.txt(N/Awhen the card exposes none) — never prompts - VBIOS backup →
cards/<GPU-UUID>/bios.rom(nvflash, sysfs ROM fallback). On failure the script reports the precise cause (driver-loaded vs missing rom node) and offers an opt-in driver unload → save → reload retry (Unload NVIDIA driver and retry nvflash --save now? (y/N), default n;--bios-unloadruns it without asking) - PCIe checks: link speed/width, AER counters, full config-space dump
- Link retrain test + full bus rescan test (device must survive both)
- Kernel log scrape (
dmesg/journalctl) for this BDF: Xid / AER / NVRM lines nvidia-smisnapshot +harness/cmpunlocker/verify.sh(read-only)- Opt-in unlock:
cmpunlocker unlock (install)— skipped with a note when memory is already unlocked, otherwise asksRun cmpunlocker install.sh now? (y/N)(default n;--unlockruns it without asking). On yes:git pull --ff-onlyon the harness clone, theninstall.shruns fromharness/cmpunlocker/with live terminal output (full log →cards/<GPU-UUID>/install_unlocker.log; the kernel-module build takes 5–15 min) - After a successful install: the VRAM stress is skipped — cold reboot the host (
sudo shutdown -h now, then power it back on) and re-run the same command for the final PCIe check, which must report Gen2 x16 - Last step, optional:
Run 5-min Vulkan VRAM stress test now? (y/N)— refused by default,--vulkan always|neverto override - Result printed +
report.jsonwritten into the card's folder
Remove the card, plug the next one, repeat — no queue, no indices, folders just pile up in cards/.
Checks & scoring (lenient)
| Result | Criteria |
|---|---|
| FAIL | no device detected, link down/untrained, device lost after rescan, link failed retrain, active uncorrectable AER errors, final post-unlock link other than Gen2 x16 ([ERROR] final PCIe link after unlock is <speed> <width> - expected Gen2 x16) |
| WARN | link width ≠ x16 (capacitor mod missing/incomplete, pre-unlock runs only), Gen1 only (Gen2 unlock patch not active, pre-unlock runs only), correctable AER errors, kernel errors / Xid, VBIOS backup failed, cmpunlocker verify not unlocked-ok, cmpunlocker install failed, errors during VRAM stress |
| PASS | everything clean |
Exit codes: 0 PASS/WARN · 1 FAIL · 2 no card found · 3 preflight blocking failure.
Output
cards/
└── <GPU-UUID>/
├── serial.txt # physical serial, or N/A
├── bios.rom # VBIOS backup (+ sha256 in report)
├── report.json # full result: link, AER before/after, retrain,
│ # rescan, dmesg, verify, vulkan, PASS/WARN/FAIL
├── lspci.txt # lspci -vvv (before)
├── lspci_after.txt # lspci -vvv (after retrain/rescan)
├── config_space.hex # lspci -nnvvxxxx full hex dump
├── dmesg.log # kernel lines related to this card
├── verify_unlocker.log # cmpunlocker verify.sh output
└── install_unlocker.log # full install.sh output (only if the opt-in
# unlock step ran)
Flags
| Flag | Meaning |
|---|---|
--preflight |
setup only: sudo precondition + package install + harness clone, then exit |
--demo |
run the whole pipeline against fake hardware (self-test) |
--nvflash PATH |
explicit nvflash binary |
--serial XYZ |
override physical serial recorded in serial.txt (folder stays UUID-named) |
--vulkan ask|always|never |
VRAM test policy (default: ask, last step) |
--unlock |
run the cmpunlocker install.sh step without prompting (default: ask y/N) |
--skip-bios |
skip VBIOS backup |
--bios-unload |
unload NVIDIA driver to retry nvflash --save without prompting (console may freeze briefly, driver is reloaded after) |
--no-install |
never install packages (skips the sudo precondition) |
--no-clone |
don't clone the harness repos |
Safety
This tool reads card state by default. Two steps can change host state, both opt-in:
- Unlock install (opt-in, explicit confirmation) — runs only if you answer
ytoRun cmpunlocker install.sh now? (y/N)(defaultn) or pass--unlock. It executesinstall.shfrom the harness clone (harness/cmpunlocker/, refreshed first withgit pull --ff-only, no extra installer flags), needs root (sudo credentials are cached first), streams its output live, and saves the full log tocards/<GPU-UUID>/install_unlocker.log. It is skipped entirely when memory is already unlocked, when the harness is not cloned, and in--demomode. A successful install replaces kernel modules — the step then skips VRAM stress and asks you to cold reboot and re-run. - VBIOS unload-retry (opt-in, explicit confirmation) — offered only after both backup methods fail with the driver loaded: unloads the NVIDIA modules, retries
nvflash --save, then reloads the modules (local console may freeze briefly). Triggered byyor--bios-unload; skipped in--demomode. - Everything else remains read-only:
verify.shruns without installing anything, no modules are patched and no firmware is flashed (nvflash is only ever used with--save). The only other writes are local files (reports, logs), PCI link retrain/rescan sysfs triggers, and package installation during--preflight(explicitly gated behind the sudo precondition).