Skip to content

orchestrator: Add the update intake seam for an update source - #455

Draft
chrysh wants to merge 3 commits into
OpenPRoT:mainfrom
9elements:pldm-service-iface
Draft

orchestrator: Add the update intake seam for an update source#455
chrysh wants to merge 3 commits into
OpenPRoT:mainfrom
9elements:pldm-service-iface

Conversation

@chrysh

@chrysh chrysh commented Sep 1, 2026

Copy link
Copy Markdown
Contributor

The IPC channel between services/pldm and the orchestrator, as its contract.

wire.rs is the channel protocol: a 16-byte request header plus the chunk on
Write, a 20-byte response, five opcodes, and MAX_CHUNK = 512 to match
FD_MAX_XFER_SIZE in pldm-interface so a RequestFirmwareData chunk passes
through unsplit. Decoding validates lengths, opcodes, reserved fields and the
chunk bound before anything looks at the payload, and never panics: the
request side is another process and is treated as untrusted.

traits.rs is the UpdateIntake call surface, status.rs the IntakeStatus
phases the orchestrator answers with. Host-buildable, depends only on
zerocopy, and both processes depend on it.

The source is the channel's initiator and the orchestrator its handler, with
no channel the other way, so the orchestrator never waits on a source and a
wedged source cannot delay a boot window or a recovery.

Not here, and why:

  • The channel_transact client and the channel_read/channel_respond
    handler loop are separate PRs, trait first.
  • The system.json5 endpoint declarations cannot land yet:
    target/ast10x0/erot/system.json5 is kernel-only and has no apps: key, so
    there are no processes to hang a channel_handler and channel_initiator
    off.
  • services/storage is still a stub, so nothing moves a real image. The crate
    and its tests stand alone on the host.

Draft because one thing is unresolved: Event::UpdateRequest fires at
RequestUpdate accept on main (#442), which enters State::Updating and
emits AuthenticateUpdate with no bytes to authenticate. The README no longer
claims complete() is what hands the state machine the request, but where
that event should fire is not settled here.

Stacked on Anthony's runtime-concept commit (51b4dfa), which is not merged.
Review the last two commits only.

rusty1968 and others added 3 commits August 28, 2026 09:47
The contract between the orchestrator and an update source (the PLDM
firmware-device service today, self-update later): the UpdateIntake trait
a source calls, the IntakeStatus phases the orchestrator answers with, and
the wire encoding that carries both over a kernel channel. Api layer only,
no transport and no dispatch, so it builds and tests on the host.

The source is the channel's initiator and the orchestrator its handler,
with no channel the other way, so the orchestrator never waits on the
source and a wedged source cannot delay a boot window. That is why the
seam is polled: everything the orchestrator decides comes back as the
phase on a response, including the two update reports, which latch a
phase instead of sending a message.
IntakeStatus documented one order. A board that writes the candidate
straight into the target's inactive slot authenticates by reading that slot
back, and a target gated on a signed manifest is authenticated before any
byte moves, so the order differs by board and a source must not assume one.
Staging is now marked as reachable only where the orchestrator stages into a
region of its own.

Write-through is the expected shape here: the part has 768 KB of SRAM
against a payload of tens of megabytes, so there is no room to hold a copy.

The README also stops saying complete() hands the state machine the update
request. Where that event fires is still open, so the step now says only
what complete() itself does.
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.

2 participants