fwmanager: Add BootMonitor capability and GpioBootMonitor adapter - #368
Merged
Conversation
leongross
force-pushed
the
add-boot-monitor
branch
from
July 25, 2026 14:03
9a20392 to
a921386
Compare
embediver
reviewed
Jul 28, 2026
rusty1968
reviewed
Jul 29, 2026
rusty1968
reviewed
Jul 29, 2026
rusty1968
reviewed
Jul 29, 2026
rusty1968
reviewed
Jul 29, 2026
rusty1968
reviewed
Jul 29, 2026
chrysh
added a commit
to 9elements/openprot
that referenced
this pull request
Jul 29, 2026
InReset is orchestrator state, not something a monitor can observe — a device held in reset reads exactly like one still booting, so the variant could never be reported. Remove it from BootStatus. Document on boot_status() that any given backend may only ever produce a subset of BootStatus depending on the signals it can access (a single ready pin yields only Booting/Booted); this is a capability difference between backends, and consumers must still handle the full set. Addresses review feedback on PR OpenPRoT#368. Assisted-by: Claude:claude-fable-5 Signed-off-by: Christina Quast <christina.quast@9elements.com>
chrysh
added a commit
to 9elements/openprot
that referenced
this pull request
Jul 29, 2026
Owning the port swallowed a whole GPIO bank per monitor, making a second monitor on the same bank impossible. On the AST1060 SGPIOM a bank packs 32 unrelated lines, so distinct devices' ready signals routinely share one bank by construction. The monitor only reads (read_input takes &self), so hold &'a P instead: several monitors can now watch different lines of the same bank, with platform configuration keeping the bank alive for as long as its monitors. Also note in the adapter docs that a single ready line only ever yields the Booting/Booted subset of BootStatus. Addresses review feedback on PR OpenPRoT#368. Assisted-by: Claude:claude-fable-5 Signed-off-by: Christina Quast <christina.quast@9elements.com>
chrysh
added a commit
to 9elements/openprot
that referenced
this pull request
Jul 29, 2026
InReset is orchestrator state, not something a monitor can observe — a device held in reset reads exactly like one still booting, so the variant could never be reported. Remove it from BootStatus. Document on boot_status() that any given backend may only ever produce a subset of BootStatus depending on the signals it can access (a single ready pin yields only Booting/Booted); this is a capability difference between backends, and consumers must still handle the full set. Addresses review feedback on PR OpenPRoT#368. Assisted-by: Claude:claude-fable-5 Signed-off-by: Christina Quast <christina.quast@9elements.com>
chrysh
added a commit
to 9elements/openprot
that referenced
this pull request
Jul 29, 2026
Owning the port swallowed a whole GPIO bank per monitor, making a second monitor on the same bank impossible. On the AST1060 SGPIOM a bank packs 32 unrelated lines, so distinct devices' ready signals routinely share one bank by construction. The monitor only reads (read_input takes &self), so hold &'a P instead: several monitors can now watch different lines of the same bank, with platform configuration keeping the bank alive for as long as its monitors. Also note in the adapter docs that a single ready line only ever yields the Booting/Booted subset of BootStatus. Addresses review feedback on PR OpenPRoT#368. Assisted-by: Claude:claude-fable-5 Signed-off-by: Christina Quast <christina.quast@9elements.com>
rusty1968
approved these changes
Jul 30, 2026
BootMonitor reports a device's boot liveness as BootStatus in the api leaf crate; GpioBootMonitor implements it over one HAL GpioPort input line. MonitorError meets the core::error::Error bound and keeps the concrete HAL error reachable through source(). new() rejects empty pin masks; boot latches are cleared by the reset path, never the observer. Closes: #6 Assisted-by: Claude:claude-opus-4-8 Assisted-by: Claude:claude-fable-5 Signed-off-by: Christina Quast <christina.quast@9elements.com>
InReset is orchestrator state, not something a monitor can observe — a device held in reset reads exactly like one still booting, so the variant could never be reported. Remove it from BootStatus. Document on boot_status() that any given backend may only ever produce a subset of BootStatus depending on the signals it can access (a single ready pin yields only Booting/Booted); this is a capability difference between backends, and consumers must still handle the full set. Addresses review feedback on PR OpenPRoT#368. Assisted-by: Claude:claude-fable-5 Signed-off-by: Christina Quast <christina.quast@9elements.com>
Owning the port swallowed a whole GPIO bank per monitor, making a second monitor on the same bank impossible. On the AST1060 SGPIOM a bank packs 32 unrelated lines, so distinct devices' ready signals routinely share one bank by construction. The monitor only reads (read_input takes &self), so hold &'a P instead: several monitors can now watch different lines of the same bank, with platform configuration keeping the bank alive for as long as its monitors. Also note in the adapter docs that a single ready line only ever yields the Booting/Booted subset of BootStatus. Addresses review feedback on PR OpenPRoT#368. Assisted-by: Claude:claude-fable-5 Signed-off-by: Christina Quast <christina.quast@9elements.com>
rusty1968
force-pushed
the
add-boot-monitor
branch
from
July 31, 2026 13:18
66f76f8 to
ae3b581
Compare
FerralCoder
reviewed
Jul 31, 2026
Collaborator
API usage modelConsider this bare metal toy example just for illustration purposes. use fwmanager_api::{BootMonitor, BootStatus};
use orchestrator_sm::{ComponentId, Event, Orchestrator, Platform};
/// The shell's per-component boot watch. Called after the SM has emitted
/// `Effect::ReleaseReset(id)` for `id` and the platform actually let it go.
///
/// This is the *only* place `BootStatus` crosses into the SM: a `Booted` read
/// becomes `Event::Booted`, a device-reported `Failed` short-circuits into
/// recovery, and "still `Booting` when the budget runs out" is the watchdog
/// firing `Event::Timeout`. Reset / authenticate / measure never appear here —
/// the SM already drove those before it emitted `ReleaseReset`.
fn watch_boot<const N: usize, const E: usize, M, P>(
sm: &mut Orchestrator<N, E>,
platform: &mut P,
monitor: &M,
id: ComponentId,
poll_budget: usize,
) where
M: BootMonitor,
P: Platform,
{
for _ in 0..poll_budget {
match monitor.boot_status() {
// Came up: hand the SM its post-release liveness event. The SM
// clears this component's boot-progress watchdog and advances the
// chain walk (or, for an Active part, this pairs with ComponentReady).
Ok(BootStatus::Booted) => {
sm.dispatch(platform, Event::Booted(id));
return;
}
// Released but not up yet — not a failure. Keep waiting inside the
// budget; the SM is unaware a poll even happened.
Ok(BootStatus::Booting) => continue,
// Device reported a fault. The SM has no dedicated "boot failed"
// event — a device that doesn't come up enters recovery via the
// boot-progress watchdog — so surface an early, explicit fault as
// that same Timeout path instead of waiting the window out.
Ok(BootStatus::Failed) => {
sm.dispatch(platform, Event::Timeout(id));
return;
}
// Couldn't even read the signal. Treat an unreadable liveness
// channel as no-progress and let recovery decide.
Err(_e) => {
sm.dispatch(platform, Event::Timeout(id));
return;
}
}
}
// Budget exhausted, never saw Booted: the boot-progress watchdog fires.
// The SM routes Timeout(id) for an awaiting component straight into recovery.
sm.dispatch(platform, Event::Timeout(id));
} |
FerralCoder
approved these changes
Jul 31, 2026
FerralCoder
pushed a commit
that referenced
this pull request
Jul 31, 2026
InReset is orchestrator state, not something a monitor can observe — a device held in reset reads exactly like one still booting, so the variant could never be reported. Remove it from BootStatus. Document on boot_status() that any given backend may only ever produce a subset of BootStatus depending on the signals it can access (a single ready pin yields only Booting/Booted); this is a capability difference between backends, and consumers must still handle the full set. Addresses review feedback on PR #368. Assisted-by: Claude:claude-fable-5 Signed-off-by: Christina Quast <christina.quast@9elements.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
BootMonitor reports a device's boot liveness as BootStatus in the api leaf crate; GpioBootMonitor implements it over one HAL GpioPort input line. MonitorError meets the core::error::Error bound and keeps the concrete HAL error reachable through source(). new() rejects empty pin masks; boot latches are cleared by the reset path, never the observer.
Closes 9elements#6.
(Replaces 9elements#20, which was opened against the fork's main by mistake.)