-
Notifications
You must be signed in to change notification settings - Fork 13
Remote Platform Erase
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:
- Keep
/api/v1/*behavior stable and additive. - Keep controller -> feature -> WSMAN layering; no controller-side WSMAN logic.
- Handle both hardware erase targets (SSD/TPM/BIOS) and CSME unconfigure behavior.
- Tolerate firmware differences where some AMT operations may return errors but still partially apply.
- Avoid power actions that could reboot without properly latched erase flags.
We implemented RPE as a dedicated vertical slice across API, use case, and WSMAN layers.
Added the following endpoints under existing v1 AMT routes:
GET /api/v1/amt/boot/remoteErase/:guidPOST /api/v1/amt/boot/remoteErase/:guid
Request/response DTOs were added for:
-
RemoteEraseRequestwith option flags and optional SSD password. -
BootCapabilitieswith capability booleans returned to clients.
RPE DTO field details used by this flow:
-
RemoteEraseRequest(POST /api/v1/amt/boot/remoteErase/:guid)secureEraseAllSSDstpmClearrestoreBIOSToEOMunconfigureCSME-
ssdPassword(optional)
-
BootCapabilities(GET /api/v1/amt/boot/remoteErase/:guid)secureEraseAllSSDstpmClearrestoreBIOSToEOMunconfigureCSME
- 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:
-
secureEraseAllSSDs=truecontributes the hardware secure erase bit to the internal erase mask and is sent through the RPE TLV payload. -
ssdPasswordis forwarded to AMT asRSEPasswordin BootSettingData PUT. - Password is optional. Empty string means no password is set in the request payload.
- The upstream WSMAN package also defines
RPE_SSD_MASTER_PASSWORDwith max size 64 bytes in its RPE TLV model. - Console flow does not use that 64-byte RPE password TLV parameter directly; it forwards
ssdPasswordviaRSEPasswordin BootSettingData PUT. - Console code does not apply an explicit local length/ASCII validation for
ssdPassword; enforcement is both done in the webUI and delegated to AMT behavior.
OpenAPI declarations were added for both operations so the generated spec stays in sync.
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.
RPE execution is implemented in a dedicated WSMAN component (wsman/rpe.go) with explicit steps:
- Return boot service to idle state (best-effort).
- Attempt to latch
PlatformErase=true(best-effort pre-latch). - Read boot settings and fail fast if BIOS has RPE disabled.
- Split the API erase mask into:
- hardware TLV targets, and
-
RPEConfigurationDataResetSignalBit(CSME reset signal).
- For CSME-only requests, clear boot-order override before setting reset flags.
- Enable RPE boot service state.
- PUT boot settings with:
-
ConfigurationDataResetfor CSME unconfigure, -
PlatformEraseand TLV payload for hardware targets, - optional SSD password.
-
- If PUT errors, do a follow-up GET to verify whether required flags latched; abort with explicit sentinel errors if they did not.
- Activate boot config role.
- Choose power action based on current state:
- Power on if host is off.
- Hard power cycle if host is already on.
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.
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.
Positive:
- RPE behavior is available via stable v1 endpoints and reflected in OpenAPI/Postman workflows.
- Clean architecture boundaries are preserved.
- Firmware variability is handled more safely via "PUT then verify latch" logic.
- CSME-only and hardware-target erase paths are explicitly modeled and testable.
Tradeoffs:
- The sequence is more complex than a single WSMAN call and must remain well tested.
- Best-effort compatibility steps (idle/latch attempts) require careful maintenance with firmware changes.
- Power-state-aware restart behavior adds additional dependencies on reliable power-state reads.
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.
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
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.
This state diagram reflects current code behavior for validation, mask composition, CSME-only versus hardware/combined branching, and PUT error verification.
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 --> [*]