Skip to content

Remote Platform Erase

Natalie Gaston edited this page Aug 5, 2026 · 3 revisions

ADR: Remote Platform Erase Architecture in Console

Context

Console and MPS needed Remote Platform Erase (RPE) support as part of the v1 management API surface. The implementation had to stay aligned with existing MPS/RPS-compatible contracts while introducing the RPE sequence safely for real devices.

Key constraints:

  1. Keep /api/v1/* behavior stable and additive.
  2. Keep controller -> feature -> WSMAN layering; no controller-side WSMAN logic.
  3. Handle both hardware erase targets (SSD/TPM/BIOS) and CSME unconfigure behavior.
  4. Tolerate firmware differences where some AMT operations may return errors but still partially apply.
  5. Avoid power actions that could reboot without properly latched erase flags.

Decision

We implemented RPE as a dedicated vertical slice across API, use case, and WSMAN layers.

1) API contract (v1)

Added the following endpoints under existing v1 AMT routes:

  • GET /api/v1/amt/boot/remoteErase/:guid
  • POST /api/v1/amt/boot/remoteErase/:guid

Request/response DTOs were added for:

  • RemoteEraseRequest with option flags and optional SSD password.
  • BootCapabilities with capability booleans returned to clients.

RPE DTO field details used by this flow:

  1. RemoteEraseRequest (POST /api/v1/amt/boot/remoteErase/:guid)
    • secureEraseAllSSDs
    • tpmClear
    • restoreBIOSToEOM
    • unconfigureCSME
    • ssdPassword (optional)
  2. BootCapabilities (GET /api/v1/amt/boot/remoteErase/:guid)
    • secureEraseAllSSDs
    • tpmClear
    • restoreBIOSToEOM
    • unconfigureCSME
  3. Feature payloads now use RPE terminology:
    • rpe: whether RPE is currently enabled
    • rpeSupported: whether the device BIOS supports RPE

Note: this replaces older naming that used remoteErase in feature payload context. remoteErase was there, but not actually used before this PR.

SSD secure erase and optional SSD/Pyrite password notes:

  1. secureEraseAllSSDs=true contributes the hardware secure erase bit to the internal erase mask and is sent through the RPE TLV payload.
  2. ssdPassword is forwarded to AMT as RSEPassword in BootSettingData PUT.
  3. Password is optional. Empty string means no password is set in the request payload.
  4. The upstream WSMAN package also defines RPE_SSD_MASTER_PASSWORD with max size 64 bytes in its RPE TLV model.
  5. Current Console flow does not use that 64-byte RPE password TLV parameter directly; it forwards ssdPassword via RSEPassword in BootSettingData PUT.
  6. Current Console code does not apply an explicit local length/ASCII validation for ssdPassword; enforcement is delegated to AMT behavior.

OpenAPI declarations were added for both operations so the generated spec stays in sync.

2) Use case ownership of business rules

RPE validation and request mapping are handled in devices.UseCase:

  • Resolve device by GUID and set up WSMAN client.
  • Read boot/power capabilities before execution.
  • Reject requests when device supports neither PlatformErase nor ConfigurationDataReset.
  • Build erase mask from client-selected options.
  • Enforce "at least one erase option".
  • Translate firmware-level "RPE not enabled" into a user-facing not-supported error.

This keeps transport concerns in controllers and business behavior in the use case layer.

3) Dedicated WSMAN RPE sequence with safety gates

RPE execution is implemented in a dedicated WSMAN component (wsman/rpe.go) with explicit steps:

  1. Return boot service to idle state (best-effort).
  2. Attempt to latch PlatformErase=true (best-effort pre-latch).
  3. Read boot settings and fail fast if BIOS has RPE disabled.
  4. Split the API erase mask into:
    • hardware TLV targets, and
    • RPEConfigurationDataResetSignalBit (CSME reset signal).
  5. For CSME-only requests, clear boot-order override before setting reset flags.
  6. Enable RPE boot service state.
  7. PUT boot settings with:
    • ConfigurationDataReset for CSME unconfigure,
    • PlatformErase and TLV payload for hardware targets,
    • optional SSD password.
  8. If PUT errors, do a follow-up GET to verify whether required flags latched; abort with explicit sentinel errors if they did not.
  9. Activate boot config role.
  10. Choose power action based on current state:
    • Power on if host is off.
    • Hard power cycle if host is already on.

4) Capability and signal semantics

We intentionally treat RPEConfigurationDataResetSignalBit as an API input signal for CSME unconfigure, not as a hardware TLV capability bit. This avoids conflating CSME reset signaling with hardware target selection.

5) Test coverage strategy

Coverage was added at multiple layers:

  • HTTP handler tests for GET/POST behavior and payload forwarding.
  • Use case tests for capability checks, mask construction, error mapping, and SSD password forwarding.
  • OpenAPI test asserting both remote erase operations are registered.
  • WSMAN-level tests for TLV/mask handling and sequencing behavior.

Consequences

Positive:

  1. RPE behavior is available via stable v1 endpoints and reflected in OpenAPI/Postman workflows.
  2. Clean architecture boundaries are preserved.
  3. Firmware variability is handled more safely via "PUT then verify latch" logic.
  4. CSME-only and hardware-target erase paths are explicitly modeled and testable.

Tradeoffs:

  1. The sequence is more complex than a single WSMAN call and must remain well tested.
  2. Best-effort compatibility steps (idle/latch attempts) require careful maintenance with firmware changes.
  3. Power-state-aware restart behavior adds additional dependencies on reliable power-state reads.

RPE Sequence

This sequence shows the end-to-end call path for remote erase, from client request through AMT operations, including where SSD password handling and AMT message logging settings appear in execution.

Flow Diagram

sequenceDiagram
	autonumber
	participant Client
	participant API as HTTP v1 route
	participant UC as devices use case
	participant Repo as Device repo
	participant W as WSMAN adapter
	participant AMT as AMT firmware

	Client->>API: POST remoteErase with options and optional ssdPassword
	API->>UC: SetRemoteEraseOptions(guid, request)
	UC->>Repo: GetByID(guid)
	Repo-->>UC: device
	UC->>W: SetupWsmanClient(..., logAMTMessages=true)
	UC->>W: GetBootCapabilities()
	W->>AMT: BootCapabilities.Get
	AMT-->>W: PlatformErase bitmask
	W-->>UC: capabilities
	UC->>UC: Build eraseMask from request flags
	UC->>W: SetRemoteEraseOptions(eraseMask, ssdPassword)
	Note over W: Split eraseMask into wantCSMEReset and tlvMask (hardware bits)
	W->>AMT: RequestStateChange(32768 idle baseline)
	W->>AMT: Optional SetRPEEnabled(true) and BootSettingData.Get
	alt CSME-only request (wantCSMEReset=true, tlvMask=0)
		W->>AMT: ChangeBootOrder("") to clear boot override
	else Hardware-only or Combined request (tlvMask!=0)
		Note over W,AMT: Skip ChangeBootOrder and preserve hardware erase path behavior
	end
	W->>AMT: RequestStateChange(32770 RPE mode)
	W->>AMT: BootSettingData.Put with PlatformErase/TLV and/or ConfigurationDataReset
	W->>AMT: SetBootConfigRole and RequestPowerStateChange
	AMT-->>W: success or error
	W-->>UC: mapped result
	UC-->>API: success or mapped error
	API-->>Client: 200 or error status
Loading

Combined requests are supported in current code: when both CSME and hardware options are selected, ConfigurationDataReset=true and hardware TLV parameters are sent in the same BootSettingData PUT.

RPE State Machine

This state diagram reflects current code behavior for validation, mask composition, CSME-only versus hardware/combined branching, and PUT error verification.

Flow Diagram

stateDiagram-v2
	[*] --> ValidateDevice

	ValidateDevice --> RejectDevice: device lookup/setup fails
	ValidateDevice --> ValidateCapabilities

	ValidateCapabilities --> RejectNoRPE: PlatformErase == 0 and ConfigurationDataReset == false
	ValidateCapabilities --> BuildMask

	BuildMask --> RejectMaskZero: no options selected
	BuildMask --> SplitMask

	SplitMask --> CSMEOnly: wantCSMEReset and tlvMask == 0
	SplitMask --> HardwareOnly: tlvMask != 0 and wantCSMEReset == false
	SplitMask --> Combined: tlvMask != 0 and wantCSMEReset == true

	CSMEOnly --> ClearBootOrder
	ClearBootOrder --> ExecuteFlow
	HardwareOnly --> ExecuteFlow
	Combined --> ExecuteFlow

	ExecuteFlow --> RejectBiosDisabled: RPEEnabled == false
	ExecuteFlow --> PutBootData

	PutBootData --> ContinueOnLatched: PUT success
	PutBootData --> VerifyLatchOnError: PUT error

	VerifyLatchOnError --> AbortOnNotLatched
	VerifyLatchOnError --> ContinueOnLatched

	ContinueOnLatched --> SetBootConfigRole
	SetBootConfigRole --> ChoosePowerAction
	ChoosePowerAction --> PowerOnIfOff
	ChoosePowerAction --> PowerCycleIfOn

	RejectDevice --> [*]
	RejectNoRPE --> [*]
	RejectMaskZero --> [*]
	RejectBiosDisabled --> [*]
	AbortOnNotLatched --> [*]
	PowerOnIfOff --> [*]
	PowerCycleIfOn --> [*]
Loading

Clone this wiki locally