Skip to content

orchestrator: Move the SVN floor advance to the update agent's ask - #568

Merged
chrysh merged 3 commits into
OpenPRoT:ocp-global-demo-wipfrom
9elements:svn-floor-on-0x22
Oct 15, 2026
Merged

chrysh merged 3 commits into
OpenPRoT:ocp-global-demo-wipfrom
9elements:svn-floor-on-0x22

Conversation

@chrysh

@chrysh chrysh commented Oct 13, 2026 •

Copy link
Copy Markdown
Contributor

Builds on #565, merged into ocp-global-demo-wip.

Issue: 9elements#18

An eRoT-held anti-rollback floor moved on Event::BootConfirmed, the moment
the orchestrator decided the updated image was healthy. That floor belongs to a
component that tracks no SVN of its own, and the agent commands the advance
with UpdateSecurityRevision (PLDM 0x22), so moving on the boot would burn
anti-rollback before the agent asked for it.

Event::SvnCommitRequest(id) is that request arriving. The floor it names is
one the eRoT holds, so there is no device-side commit to wait for; what gates
the advance is the window BootConfirmed opened. BootConfirmed now closes the commit-or-lock window and records the
component in awaiting_floor_advance; the matching SvnCommitRequest emits
CommitSvnFloor and clears it. An ask for a component with nothing
outstanding is dropped, so the floor takes the SVN once however many times
the agent asks.

Two design calls worth ratifying in review, both mirroring what the eRoT's own
session does rather than what the old BootConfirmed path did:

No watchdog bounds the wait. An agent that never sends UpdateSecurityRevision
leaves the floor where it is, the way a confirmed self-update session sits at
AwaitingFloorAdvance. Locking the platform because a remote agent went quiet
costs more than losing anti-rollback coverage for one image. CommitTimeout
still guards pending_commit alone, so commit-or-lock stays "the device has
to boot".

An outstanding advance is voided by anything that puts the running image under
suspicion: entry to Updating or Recovering, and gating the component out of
service. The SVN the floor would take is the driver's reading of the image the
update verified, which a superseding update overwrites, so a late ask would
otherwise advance the floor past an image that never booted. The gating case
has its own test, checked against the failure it exists for.

The eRoT's own floor already behaved this way and is unchanged: the only thing
that writes it is commit_self_svn_floor, which refuses a session that does
not read Committed. #565 is what gets a session there.

What is still missing is in GAPS.md: no firmware device parks at
SvnCommitPending, so both update scenarios dispatch SvnCommitRequest
themselves, the way they already dispatch BootConfirmed. Under that sit two
pieces, neither in this PR. The pldm-lib FdOps callback that turns a received
0x22 into the status is not in the pinned revision (c709ae4 predates it, and
it is not on pldm-lib main yet). The event-loop glue that reads the status
and answers is the other, for a device with commit_svn_floor and for the
eRoT's own floor with commit_self_svn_floor.

Tested: bazel test //services/... passes 38/38 and
bazel test --config=virt_ast10x0 //target/ast10x0/tests/integration/...
passes 26/26. ./pw presubmit is green.

`Event::BootConfirmed` emitted `Effect::CommitSvnFloor`, so an eRoT-held
floor moved as soon as the orchestrator decided the image was healthy.
The advance is the update agent's to command, with UpdateSecurityRevision
(PLDM 0x22); moving on the boot burns anti-rollback before anyone asked.

`Event::SvnCommitRequest(id)` is that request arriving. `BootConfirmed`
now closes the commit-or-lock window and records the component in
`awaiting_floor_advance`; the matching `SvnCommitRequest` emits
`CommitSvnFloor` and clears it. One for a component with nothing
outstanding is dropped, so the floor takes the SVN once.

No watchdog bounds the wait. An agent that never asks leaves the floor
where it is, which is what the eRoT's own session does with
`AwaitingFloorAdvance`; locking the platform because a remote agent
stayed silent would be worse than losing anti-rollback coverage for one
image. `CommitTimeout` still guards `pending_commit` alone, so
commit-or-lock remains "the device has to boot".

Entry to `Updating` and `Recovering` clears the outstanding advance the
way it clears `pending_commit`. The SVN the floor would take is the
driver's reading of the image the update verified, which a superseding
update overwrites, so a late ask would otherwise advance the floor past
an image that never booted.

Assisted-by: Claude Opus 5
Signed-off-by: Christina Quast <christina.quast@9elements.com>
@chrysh
chrysh force-pushed the svn-floor-on-0x22 branch 2 times, most recently from 17be37c to ef10d6f Compare October 15, 2026 15:02
Both scenarios treated the confirmed boot as the end of the update. The
floor now waits for `Event::SvnCommitRequest`, so each main dispatches it
after `BootConfirmed`, the way it already dispatches `BootConfirmed`
itself after the device comes back up.

The event stands in for the UpdateSecurityRevision exchange because no
firmware device parks at `SvnCommitPending` yet: the pinned pldm-lib
predates the FdOps callback that turns a received 0x22 into that status,
and nothing reads the status and answers. GAPS.md records both halves.

Assisted-by: Claude Opus 5
Signed-off-by: Christina Quast <christina.quast@9elements.com>
The machine doc lists what lives in shared storage and what each state
answers, so it drifts the moment either changes. `awaiting_floor_advance` is
the new flag, `BootConfirmed` no longer emits `CommitSvnFloor`, and
`SvnCommitRequest` is what does.

The `Ready` table was already missing `BootConfirmed` and `CommitTimeout`,
both of which the state handles; they go in with the new rows.

Assisted-by: Claude Opus 5
Signed-off-by: Christina Quast <christina.quast@9elements.com>
@chrysh
chrysh force-pushed the svn-floor-on-0x22 branch from ef10d6f to 3a7ffdb Compare October 15, 2026 16:47
@chrysh
chrysh merged commit 33b0e3e into OpenPRoT:ocp-global-demo-wip Oct 15, 2026
4 checks passed
@chrysh
chrysh deleted the svn-floor-on-0x22 branch October 15, 2026 16:49
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant