Skip to content

Commit 3b9b40d

Browse files
authored
Add MGS command to clear APOB (#2456)
1 parent c03cc5b commit 3b9b40d

10 files changed

Lines changed: 162 additions & 24 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

drv/cosmo-hf/src/apob.rs

Lines changed: 39 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,8 +12,8 @@ use crate::{
1212
SECTOR_SIZE_BYTES,
1313
};
1414
use drv_hf_api::{
15-
ApobBeginError, ApobCommitError, ApobHash, ApobReadError, ApobWriteError,
16-
HfError,
15+
ApobBeginError, ApobClearError, ApobCommitError, ApobHash, ApobReadError,
16+
ApobWriteError, HfError,
1717
};
1818
use idol_runtime::{Leased, R, W};
1919
use ringbuf::{counted_ringbuf, ringbuf_entry};
@@ -276,6 +276,7 @@ enum Trace {
276276
Abl0Version(u32),
277277
ClearingOldMetaVersion(u32),
278278
ClearingNewMetaVersion(u32),
279+
ApobClear,
279280
}
280281
counted_ringbuf!(Trace, 16, Trace::None);
281282

@@ -834,6 +835,42 @@ impl ApobState {
834835
Ok(data.len())
835836
}
836837

838+
pub(crate) fn clear(
839+
&mut self,
840+
drv: &mut FlashDriver,
841+
buf: &mut HfBufs,
842+
) -> Result<(), ApobClearError> {
843+
// Check that the flash is muxed to the SP
844+
drv.check_flash_mux_state()
845+
.map_err(|_| ApobClearError::NotMuxedToSp)?;
846+
847+
match self {
848+
ApobState::Waiting { read_slot, .. } => {
849+
*read_slot = None;
850+
// It's fine to leave write_slot as either value, since they
851+
// will both be erased after we exit this function.
852+
}
853+
ApobState::Ready { .. } => {
854+
// Don't erase the APOB if we're midway through writing, that
855+
// could be confusing!
856+
return Err(ApobClearError::InvalidState);
857+
}
858+
ApobState::Locked { .. } => {
859+
// It's fine to erase the APOB after it's locked
860+
}
861+
}
862+
ringbuf_entry!(Trace::ApobClear);
863+
864+
Self::slot_erase(drv, buf, ApobSlot::Slot0);
865+
Self::slot_erase(drv, buf, ApobSlot::Slot1);
866+
867+
// Overwrite both metadata pages (one sector each)
868+
drv.flash_sector_erase(Meta::Meta0.flash_addr(0).unwrap_lite());
869+
drv.flash_sector_erase(Meta::Meta1.flash_addr(0).unwrap_lite());
870+
871+
Ok(())
872+
}
873+
837874
pub(crate) fn lock(&mut self) {
838875
match *self {
839876
ApobState::Ready { .. } | ApobState::Waiting { .. } => {

drv/cosmo-hf/src/hf.rs

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -587,6 +587,15 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
587587
.map_err(RequestError::from)
588588
}
589589

590+
fn apob_clear(
591+
&mut self,
592+
_: &RecvMessage,
593+
) -> Result<(), RequestError<drv_hf_api::ApobClearError>> {
594+
self.apob_state
595+
.clear(&mut self.drv, &mut self.buf)
596+
.map_err(RequestError::from)
597+
}
598+
590599
fn get_mux(
591600
&mut self,
592601
_: &RecvMessage,
@@ -1079,13 +1088,20 @@ impl idl::InOrderHostFlashImpl for FailServer {
10791088
) -> Result<usize, RequestError<drv_hf_api::ApobReadError>> {
10801089
Err(drv_hf_api::ApobReadError::InvalidState.into())
10811090
}
1091+
1092+
fn apob_clear(
1093+
&mut self,
1094+
_: &RecvMessage,
1095+
) -> Result<(), RequestError<drv_hf_api::ApobClearError>> {
1096+
Err(drv_hf_api::ApobClearError::InvalidState.into())
1097+
}
10821098
}
10831099

10841100
pub mod idl {
10851101
use drv_hf_api::{
1086-
ApobBeginError, ApobCommitError, ApobHash, ApobReadError,
1087-
ApobWriteError, HfChipId, HfDevSelect, HfError, HfMuxState,
1088-
HfPersistentData, HfProtectMode,
1102+
ApobBeginError, ApobClearError, ApobCommitError, ApobHash,
1103+
ApobReadError, ApobWriteError, HfChipId, HfDevSelect, HfError,
1104+
HfMuxState, HfPersistentData, HfProtectMode,
10891105
};
10901106
include!(concat!(env!("OUT_DIR"), "/server_stub.rs"));
10911107
}

drv/gimlet-hf-server/src/main.rs

Lines changed: 16 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -960,6 +960,13 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
960960
) -> Result<usize, RequestError<drv_hf_api::ApobReadError>> {
961961
Err(drv_hf_api::ApobReadError::NotImplemented.into())
962962
}
963+
964+
fn apob_clear(
965+
&mut self,
966+
_: &RecvMessage,
967+
) -> Result<(), RequestError<drv_hf_api::ApobClearError>> {
968+
Err(drv_hf_api::ApobClearError::NotImplemented.into())
969+
}
963970
}
964971

965972
impl NotificationHandler for ServerImpl {
@@ -1193,6 +1200,13 @@ impl idl::InOrderHostFlashImpl for FailServer {
11931200
) -> Result<usize, RequestError<drv_hf_api::ApobReadError>> {
11941201
Err(drv_hf_api::ApobReadError::NotImplemented.into())
11951202
}
1203+
1204+
fn apob_clear(
1205+
&mut self,
1206+
_: &RecvMessage,
1207+
) -> Result<(), RequestError<drv_hf_api::ApobClearError>> {
1208+
Err(drv_hf_api::ApobClearError::NotImplemented.into())
1209+
}
11961210
}
11971211

11981212
/// Failure function, running an Idol response loop that always returns an error
@@ -1210,8 +1224,8 @@ mod idl {
12101224
HfProtectMode,
12111225
};
12121226
use drv_hf_api::{
1213-
ApobBeginError, ApobCommitError, ApobHash, ApobReadError,
1214-
ApobWriteError,
1227+
ApobBeginError, ApobClearError, ApobCommitError, ApobHash,
1228+
ApobReadError, ApobWriteError,
12151229
};
12161230

12171231
include!(concat!(env!("OUT_DIR"), "/server_stub.rs"));

drv/hf-api/src/lib.rs

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -385,4 +385,26 @@ pub enum ApobCommitError {
385385
CommitFailed,
386386
}
387387

388+
#[derive(
389+
Debug,
390+
Clone,
391+
Copy,
392+
PartialEq,
393+
Eq,
394+
Deserialize,
395+
Serialize,
396+
SerializedSize,
397+
FromPrimitive,
398+
IdolError,
399+
counters::Count,
400+
)]
401+
pub enum ApobClearError {
402+
/// APOB is not implemented on this hardware
403+
NotImplemented = 1,
404+
/// Host flash is not muxed to the SP
405+
NotMuxedToSp,
406+
/// The APOB state machine is in an invalid state
407+
InvalidState,
408+
}
409+
388410
include!(concat!(env!("OUT_DIR"), "/client_stub.rs"));

drv/mock-gimlet-hf-server/src/main.rs

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -279,6 +279,13 @@ impl idl::InOrderHostFlashImpl for ServerImpl {
279279
) -> Result<usize, RequestError<drv_hf_api::ApobReadError>> {
280280
Err(drv_hf_api::ApobReadError::InvalidState.into())
281281
}
282+
283+
fn apob_clear(
284+
&mut self,
285+
_: &RecvMessage,
286+
) -> Result<(), RequestError<drv_hf_api::ApobClearError>> {
287+
Err(drv_hf_api::ApobClearError::NotImplemented.into())
288+
}
282289
}
283290

284291
impl NotificationHandler for ServerImpl {
@@ -297,8 +304,8 @@ mod idl {
297304
HfProtectMode,
298305
};
299306
use drv_hf_api::{
300-
ApobBeginError, ApobCommitError, ApobHash, ApobReadError,
301-
ApobWriteError,
307+
ApobBeginError, ApobClearError, ApobCommitError, ApobHash,
308+
ApobReadError, ApobWriteError,
302309
};
303310

304311
include!(concat!(env!("OUT_DIR"), "/server_stub.rs"));

idl/hf.idol

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -305,5 +305,13 @@ Interface(
305305
),
306306
idempotent: true,
307307
),
308+
"apob_clear": (
309+
description: "clears the APOB",
310+
reply: Result(
311+
ok: "()",
312+
err: CLike("ApobClearError"),
313+
),
314+
idempotent: true,
315+
),
308316
},
309317
)

task/control-plane-agent/src/inventory.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -280,6 +280,14 @@ mod devices_with_static_validation {
280280
capabilities: DeviceCapabilities::UPDATEABLE,
281281
presence: DevicePresence::Present, // TODO: ok to assume always present?
282282
},
283+
#[cfg(feature = "cosmo")]
284+
DeviceDescription {
285+
component: SpComponent::HOST_CPU_BOOT_APOB,
286+
device: SpComponent::HOST_CPU_BOOT_APOB.const_as_str(),
287+
description: "Cosmo host boot APOB region",
288+
capabilities: DeviceCapabilities::empty(),
289+
presence: DevicePresence::Present, // matches HOST_CPU_BOOT_FLASH
290+
},
283291
// If we're building for sidecar, we always claim to have a monorail.
284292
#[cfg(feature = "sidecar")]
285293
DeviceDescription {

task/control-plane-agent/src/mgs_compute_sled.rs

Lines changed: 19 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -15,14 +15,14 @@ use gateway_messages::sp_impl::{
1515
BoundsChecked, DeviceDescription, Sender, SpHandler,
1616
};
1717
use gateway_messages::{
18-
ignition, ComponentAction, ComponentActionResponse, ComponentDetails,
19-
ComponentUpdatePrepare, DiscoverResponse, DumpSegment, DumpTask,
20-
GpioToggleCount, Header, IgnitionCommand, IgnitionState, LastPostCode,
21-
Message, MessageKind, MgsError, MgsRequest, MgsResponse, PostCode,
22-
PowerState, PowerStateTransition, RotBootInfo, RotRequest, RotResponse,
23-
SensorRequest, SensorResponse, SpComponent, SpError, SpPort as GwSpPort,
24-
SpRequest, SpStateV2, SpUpdatePrepare, UpdateChunk, UpdateId, UpdateStatus,
25-
SERIAL_CONSOLE_IDLE_TIMEOUT,
18+
ignition, ApobComponentAction, ComponentAction, ComponentActionResponse,
19+
ComponentDetails, ComponentUpdatePrepare, DiscoverResponse, DumpSegment,
20+
DumpTask, GpioToggleCount, Header, IgnitionCommand, IgnitionState,
21+
LastPostCode, Message, MessageKind, MgsError, MgsRequest, MgsResponse,
22+
PostCode, PowerState, PowerStateTransition, RotBootInfo, RotRequest,
23+
RotResponse, SensorRequest, SensorResponse, SpComponent, SpError,
24+
SpPort as GwSpPort, SpRequest, SpStateV2, SpUpdatePrepare, UpdateChunk,
25+
UpdateId, UpdateStatus, SERIAL_CONSOLE_IDLE_TIMEOUT,
2626
};
2727
use heapless::{Deque, Vec};
2828
use host_sp_messages::HostStartupOptions;
@@ -613,6 +613,17 @@ impl SpHandler for MgsHandler {
613613
.unwrap();
614614
Ok(ComponentActionResponse::Ack)
615615
}
616+
(
617+
SpComponent::HOST_CPU_BOOT_APOB,
618+
ComponentAction::Apob(action),
619+
) => {
620+
let r = match action {
621+
ApobComponentAction::Clear => {
622+
self.host_flash_update.apob_clear()
623+
}
624+
};
625+
Ok(ComponentActionResponse::Apob(r))
626+
}
616627
_ => Err(SpError::RequestUnsupportedForComponent),
617628
}
618629
}

task/control-plane-agent/src/update/host_flash.rs

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ use super::{common::CurrentUpdate, ComponentUpdater};
66
use crate::mgs_handler::{BorrowedUpdateBuffer, UpdateBuffer};
77
use core::ops::Range;
88
use drv_hf_api::{
9-
HfDevSelect, HfError, HfProtectMode, HostFlash, PAGE_SIZE_BYTES,
10-
SECTOR_SIZE_BYTES,
9+
ApobClearError, HfDevSelect, HfError, HfProtectMode, HostFlash,
10+
PAGE_SIZE_BYTES, SECTOR_SIZE_BYTES,
1111
};
1212
use gateway_messages::{
13-
ComponentUpdatePrepare, HfError as GwHfError, SpComponent, SpError,
14-
UpdateId, UpdateInProgressStatus, UpdatePreparationProgress,
15-
UpdatePreparationStatus, UpdateStatus,
13+
ApobComponentActionResponse, ComponentUpdatePrepare, HfError as GwHfError,
14+
SpComponent, SpError, UpdateId, UpdateInProgressStatus,
15+
UpdatePreparationProgress, UpdatePreparationStatus, UpdateStatus,
1616
};
1717

1818
userlib::task_slot!(HOST_FLASH, hf);
@@ -140,6 +140,21 @@ impl HostFlashUpdate {
140140
Ok(())
141141
}
142142
}
143+
144+
pub(crate) fn apob_clear(&self) -> ApobComponentActionResponse {
145+
match self.task.apob_clear() {
146+
Ok(()) => ApobComponentActionResponse::Success,
147+
Err(ApobClearError::NotImplemented) => {
148+
ApobComponentActionResponse::NotImplemented
149+
}
150+
Err(ApobClearError::NotMuxedToSp) => {
151+
ApobComponentActionResponse::NotMuxedToSp
152+
}
153+
Err(ApobClearError::InvalidState) => {
154+
ApobComponentActionResponse::InvalidState
155+
}
156+
}
157+
}
143158
}
144159

145160
// Ensure our `UpdateBuffer` type is sized large enough for us.

0 commit comments

Comments
 (0)