From 38cce236a003dd2202fc785588d2c302de1e8c6c Mon Sep 17 00:00:00 2001 From: ScottW514 Date: Wed, 2 Sep 2026 18:39:17 -0400 Subject: [PATCH] forgetest: image.health proves the boot-armed watchdog is active at 60 s The hardware watchdog is armed by the bootloader and kept fed by the kernel core; nothing in userspace opens it. Until now nothing in the catalog read that it is running. image.health reads watchdog0's state, timeout and bootstatus (CONFIG_WATCHDOG_SYSFS, meta-openglow) and requires active at 60 s; bootstatus goes into the evidence, so a campaign that follows a watchdog reset says so. Bench: on 2026-09-02 the forced hang ended in the factory recovery after the 60 s timeout; the register read WCR 0x771f. The sysfs view itself arrives with the next image, so this check is proven there. Catalog consequence: image.health is always-run. --- forgetest/forgetest/suite/image.py | 11 +++++++++++ 1 file changed, 11 insertions(+) diff --git a/forgetest/forgetest/suite/image.py b/forgetest/forgetest/suite/image.py index ac4d6fc..66a65de 100644 --- a/forgetest/forgetest/suite/image.py +++ b/forgetest/forgetest/suite/image.py @@ -107,6 +107,17 @@ def image_health(ctx): ev[opt] = val ctx.log("%s=%s", opt, val) ctx.check(val in want, "%s=%s, expected one of %s", opt, val, want) + # The boot-armed hardware watchdog, as the kernel's core sees it: U-Boot + # arms WDOG1 at 60 s and the core keeps it fed (no userspace opens it). + # The sysfs view needs CONFIG_WATCHDOG_SYSFS; bootstatus carries the + # last reset's cause (32 = the watchdog's timeout). + wd = {k: (_read("/sys/class/watchdog/watchdog0/" + k) or "").strip() + for k in ("identity", "state", "timeout", "bootstatus")} + ev["watchdog"] = wd + ctx.log("watchdog0: %s", wd) + ctx.check(wd["state"] == "active", "watchdog0 is %r, expected active (armed by the bootloader, " + "fed by the kernel core)", wd["state"] or None) + ctx.check(wd["timeout"] == "60", "watchdog0 timeout %r, expected 60 s", wd["timeout"] or None) rel = _read("/proc/sys/kernel/osrelease", "").strip() ev["kernel_release"] = rel mods = manifest.platform.get("kernel_modules") or []