diff --git a/Cargo.lock b/Cargo.lock index 66e76a751c..fd2a9b6855 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1140,6 +1140,7 @@ dependencies = [ "hubpack", "idol-runtime", "lpc55-pac", + "lpc55-rom-data", "lpc55_romapi", "mutable-statics", "num-traits", @@ -2167,7 +2168,7 @@ checksum = "e6d5a32815ae3f33302d95fdcb2ce17862f8c65363dcfd29360480ba1001fc9c" [[package]] name = "gateway-messages" version = "0.1.0" -source = "git+https://github.com/oxidecomputer/management-gateway-service#65744c516cb528776dc9b36d44b11c1ae4269f62" +source = "git+https://github.com/oxidecomputer/management-gateway-service?branch=read-rot-message#8ae20d8dd0715c6cffb174440ce8ee26276465f7" dependencies = [ "bitflags 1.3.2", "hubpack", @@ -3991,6 +3992,7 @@ dependencies = [ "host-sp-messages", "idol", "idol-runtime", + "lpc55-rom-data", "mutable-statics", "num-traits", "ringbuf", diff --git a/Cargo.toml b/Cargo.toml index 4b2949ca6a..2e7e49c60b 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -116,7 +116,7 @@ zip = { version = "0.6", default-features = false, features = ["bzip2"] } # Oxide forks and repos dice-mfg-msgs = { git = "https://github.com/oxidecomputer/dice-util", default-features = false, version = "0.2.1" } -gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", default-features = false, features = ["smoltcp"] } +gateway-messages = { git = "https://github.com/oxidecomputer/management-gateway-service", default-features = false, features = ["smoltcp"], branch = "read-rot-message" } hif = { git = "https://github.com/oxidecomputer/hif", default-features = false } humpty = { git = "https://github.com/oxidecomputer/humpty", default-features = false, version = "0.1.3" } hubtools = { git = "https://github.com/oxidecomputer/hubtools", default-features = false, version = "0.4.1" } diff --git a/app/oxide-rot-1/app-dev.toml b/app/oxide-rot-1/app-dev.toml index 8f5f3abdd9..3717c51bce 100644 --- a/app/oxide-rot-1/app-dev.toml +++ b/app/oxide-rot-1/app-dev.toml @@ -77,7 +77,7 @@ task-slots = ["syscon_driver"] [tasks.sprot] name = "drv-lpc55-sprot-server" priority = 6 -max-sizes = {flash = 44384, ram = 32768} +max-sizes = {flash = 45216, ram = 32768} uses = ["flexcomm8", "bootrom"] features = ["spi0"] start = true diff --git a/app/oxide-rot-1/app.toml b/app/oxide-rot-1/app.toml index e42ee11f7e..2c109ad814 100644 --- a/app/oxide-rot-1/app.toml +++ b/app/oxide-rot-1/app.toml @@ -68,7 +68,7 @@ task-slots = ["syscon_driver"] [tasks.sprot] name = "drv-lpc55-sprot-server" priority = 6 -max-sizes = {flash = 44384, ram = 32768} +max-sizes = {flash = 45216, ram = 32768} uses = ["flexcomm8", "bootrom"] features = ["spi0"] start = true diff --git a/app/rot-carrier/app.toml b/app/rot-carrier/app.toml index 788ec65b1b..7a1c409981 100644 --- a/app/rot-carrier/app.toml +++ b/app/rot-carrier/app.toml @@ -108,7 +108,7 @@ task-slots = ["syscon_driver"] [tasks.sprot] name = "drv-lpc55-sprot-server" priority = 6 -max-sizes = {flash = 44384, ram = 32768} +max-sizes = {flash = 45216, ram = 32768} uses = ["flexcomm8", "bootrom"] features = ["spi0"] start = true diff --git a/drv/lpc55-sprot-server/Cargo.toml b/drv/lpc55-sprot-server/Cargo.toml index 8712fe41c4..a4384986ce 100644 --- a/drv/lpc55-sprot-server/Cargo.toml +++ b/drv/lpc55-sprot-server/Cargo.toml @@ -28,6 +28,7 @@ mutable-statics = { path = "../../lib/mutable-statics" } ringbuf = { path = "../../lib/ringbuf" } task-jefe-api = { path = "../../task/jefe-api" } userlib = { path = "../../sys/userlib" } +lpc55-rom-data = { path = "../../lib/lpc55-rom-data" } [build-dependencies] build-lpc55pins = { path = "../../build/lpc55pins" } diff --git a/drv/lpc55-sprot-server/src/handler.rs b/drv/lpc55-sprot-server/src/handler.rs index cdc5704e2b..e44da2310c 100644 --- a/drv/lpc55-sprot-server/src/handler.rs +++ b/drv/lpc55-sprot-server/src/handler.rs @@ -5,10 +5,10 @@ use crate::Trace; use attest_api::Attest; use crc::{Crc, CRC_32_CKSUM}; -use drv_lpc55_update_api::{SlotId, Update}; +use drv_lpc55_update_api::{RotPage, SlotId, Update}; use drv_sprot_api::{ AttestReq, AttestRsp, CabooseReq, CabooseRsp, DumpReq, DumpRsp, ReqBody, - Request, Response, RotIoStats, RotState, RotStatus, RspBody, + Request, Response, RotIoStats, RotPageRsp, RotState, RotStatus, RspBody, SprocketsError, SprotError, SprotProtocolError, UpdateReq, UpdateRsp, CURRENT_VERSION, MIN_VERSION, REQUEST_BUF_SIZE, RESPONSE_BUF_SIZE, }; @@ -46,6 +46,7 @@ pub struct StartupState { pub enum TrailingData { Caboose { slot: SlotId, start: u32, size: u32 }, Attest { index: u32, offset: u32, size: u32 }, + RotPage { page: RotPage }, } pub struct Handler { @@ -152,6 +153,22 @@ impl Handler { } } } + Some(TrailingData::RotPage { page }) => { + let size: usize = lpc55_rom_data::FLASH_PAGE_SIZE; + static_assertions::const_assert!( + lpc55_rom_data::FLASH_PAGE_SIZE + <= drv_sprot_api::MAX_BLOB_SIZE + ); + match Response::pack_with_cb(&rsp_body, tx_buf, |buf| { + self.update + .read_rot_page(page, &mut buf[..size]) + .map_err(|e| RspBody::Page(Err(e)))?; + Ok(size) + }) { + Ok(size) => size, + Err(e) => Response::pack(&Ok(e), tx_buf), + } + } _ => Response::pack(&rsp_body, tx_buf), } } @@ -300,6 +317,16 @@ impl Handler { }; Ok((RspBody::Attest(rsp), None)) } + ReqBody::RotPage { page } => { + // This command returns a variable amount of data that belongs + // in the trailing data region of the response. We return a + // marker struct with the data necessary retrieve this data so + // the work can be done elsewhere. + Ok(( + RspBody::Page(Ok(RotPageRsp::RotPage)), + Some(TrailingData::RotPage { page }), + )) + } } } } diff --git a/drv/lpc55-update-api/src/lib.rs b/drv/lpc55-update-api/src/lib.rs index 7c057cbbcb..4b55f8f66f 100644 --- a/drv/lpc55-update-api/src/lib.rs +++ b/drv/lpc55-update-api/src/lib.rs @@ -73,6 +73,19 @@ pub struct RotBootInfo { pub slot_b_sha3_256_digest: Option<[u8; 32]>, } +#[derive(Clone, Copy, Serialize, Deserialize, SerializedSize)] +pub enum RotPage { + // The manufacturing area that cannot be changed + Cmpa, + // The field page that is currently active (highest version) + CfpaActive, + // The field page that will be applied after the next reboot (assuming + // version is incremented) + CfpaScratch, + // The field page that is not currently active (lower version, ignoring scratch) + CfpaInactive, +} + /// Target for an update operation /// /// This `enum` is used as part of the wire format for SP-RoT communication, and diff --git a/drv/lpc55-update-server/src/main.rs b/drv/lpc55-update-server/src/main.rs index 2176615306..242a1d3eb5 100644 --- a/drv/lpc55-update-server/src/main.rs +++ b/drv/lpc55-update-server/src/main.rs @@ -13,10 +13,10 @@ use core::convert::Infallible; use core::mem::MaybeUninit; use drv_lpc55_flash::BYTES_PER_FLASH_PAGE; use drv_lpc55_update_api::{ - RawCabooseError, RotBootInfo, SlotId, SwitchDuration, UpdateTarget, + RawCabooseError, RotBootInfo, RotPage, SlotId, SwitchDuration, UpdateTarget, }; use drv_update_api::UpdateError; -use idol_runtime::{ClientError, Leased, LenLimit, RequestError, R}; +use idol_runtime::{ClientError, Leased, LenLimit, RequestError, R, W}; use stage0_handoff::{ HandoffData, HandoffDataLoadError, ImageVersion, RotBootState, }; @@ -69,12 +69,19 @@ const BLOCK_SIZE_BYTES: usize = BYTES_PER_FLASH_PAGE; const MAX_LEASE: usize = 1024; const HEADER_BLOCK: usize = 0; +const CMPA_FLASH_WORD: u32 = 0x9E40; const CFPA_PING_FLASH_WORD: u32 = 0x9E00; const CFPA_PONG_FLASH_WORD: u32 = 0x9E20; const CFPA_SCRATCH_FLASH_WORD: u32 = 0x9DE0; const CFPA_SCRATCH_FLASH_ADDR: u32 = CFPA_SCRATCH_FLASH_WORD << 4; const BOOT_PREFERENCE_FLASH_WORD_OFFSET: u32 = 0x10; +#[derive(PartialEq)] +enum CfpaPage { + Active, + Inactive, +} + impl idl::InOrderUpdateImpl for ServerImpl<'_> { fn prep_image_update( &mut self, @@ -325,7 +332,7 @@ impl idl::InOrderUpdateImpl for ServerImpl<'_> { // Ping 0x9_E000 0x9E00 // Pong 0x9_E200 0x9E20 let (cfpa_word_number, _) = - self.cfpa_word_number_and_version()?; + self.cfpa_word_number_and_version(CfpaPage::Active)?; // Read current CFPA contents. let mut cfpa = [[0u32; 4]; 512 / 16]; @@ -425,11 +432,44 @@ impl idl::InOrderUpdateImpl for ServerImpl<'_> { self.syscon.chip_reset(); panic!() } + + fn read_rot_page( + &mut self, + _: &RecvMessage, + page: RotPage, + dest: LenLimit, BYTES_PER_FLASH_PAGE>, + ) -> Result<(), RequestError> { + let start_addr = match page { + RotPage::Cmpa => CMPA_FLASH_WORD << 4, + RotPage::CfpaScratch => CFPA_SCRATCH_FLASH_ADDR, + RotPage::CfpaActive => { + let (cfpa_word, _) = + self.cfpa_word_number_and_version(CfpaPage::Active)?; + cfpa_word << 4 + } + RotPage::CfpaInactive => { + let (cfpa_word, _) = + self.cfpa_word_number_and_version(CfpaPage::Inactive)?; + cfpa_word << 4 + } + }; + + const PAGE_SIZE: u32 = BYTES_PER_FLASH_PAGE as u32; + + copy_from_flash_range( + &self.flash, + start_addr..(start_addr + PAGE_SIZE), + 0..PAGE_SIZE, + dest, + )?; + Ok(()) + } } impl ServerImpl<'_> { fn cfpa_word_number_and_version( &mut self, + page: CfpaPage, ) -> Result<(u32, u32), UpdateError> { // Read the two versions. We do this with smaller buffers so // we don't need 2x 512B buffers to read the entire CFPAs. @@ -447,12 +487,12 @@ impl ServerImpl<'_> { core::slice::from_mut(&mut pong_header), )?; - // Work out where to read the authoritative contents from. - let val = if ping_header[1] >= pong_header[1] { - (CFPA_PING_FLASH_WORD, ping_header[1]) - } else { - (CFPA_PONG_FLASH_WORD, pong_header[1]) - }; + let val = + if ping_header[1] >= pong_header[1] && page == CfpaPage::Active { + (CFPA_PING_FLASH_WORD, ping_header[1]) + } else { + (CFPA_PONG_FLASH_WORD, pong_header[1]) + }; Ok(val) } @@ -462,7 +502,7 @@ impl ServerImpl<'_> { &mut self, ) -> Result<(SlotId, Option, Option), UpdateError> { let (cfpa_word_number, cfpa_version) = - self.cfpa_word_number_and_version()?; + self.cfpa_word_number_and_version(CfpaPage::Active)?; // Read the authoritative boot selection let boot_selection_word_number = @@ -883,6 +923,33 @@ fn copy_from_caboose_chunk( Ok(()) } +fn copy_from_flash_range( + flash: &drv_lpc55_flash::Flash<'_>, + range: core::ops::Range, + pos: core::ops::Range, + data: LenLimit, BYTES_PER_FLASH_PAGE>, +) -> Result<(), RequestError> { + // Early exit if the caller didn't provide enough space in the lease + let mut remaining = pos.end - pos.start; + if remaining as usize > data.len() { + return Err(RequestError::Fail(ClientError::BadLease))?; + } + + const BUF_SIZE: usize = 128; + let mut offset = 0; + let mut buf = [0u8; BUF_SIZE]; + while remaining > 0 { + let count = remaining.min(buf.len() as u32); + let buf = &mut buf[..count as usize]; + indirect_flash_read(flash, range.start + pos.start + offset, buf)?; + data.write_range(offset as usize..(offset + count) as usize, buf) + .map_err(|_| RequestError::Fail(ClientError::WentAway))?; + offset += count; + remaining -= count; + } + Ok(()) +} + task_slot!(SYSCON, syscon); task_slot!(JEFE, jefe); @@ -915,7 +982,7 @@ include!(concat!(env!("OUT_DIR"), "/notifications.rs")); mod idl { use super::{ HandoffDataLoadError, ImageVersion, RawCabooseError, RotBootInfo, - RotBootState, SlotId, SwitchDuration, UpdateTarget, + RotPage, SlotId, SwitchDuration, UpdateTarget, }; include!(concat!(env!("OUT_DIR"), "/server_stub.rs")); diff --git a/drv/sprot-api/src/lib.rs b/drv/sprot-api/src/lib.rs index 19dd43f30f..58feccd055 100644 --- a/drv/sprot-api/src/lib.rs +++ b/drv/sprot-api/src/lib.rs @@ -20,9 +20,10 @@ pub use error::{ use crc::{Crc, CRC_16_XMODEM}; use derive_more::From; pub use drv_lpc55_update_api::{ - HandoffDataLoadError, RawCabooseError, RotBootInfo, RotBootState, RotSlot, - SlotId, SwitchDuration, UpdateTarget, + HandoffDataLoadError, RawCabooseError, RotBootInfo, RotBootState, RotPage, + RotSlot, SlotId, SwitchDuration, UpdateTarget, }; +pub use drv_update_api::UpdateError; use hubpack::SerializedSize; use idol_runtime::{Leased, LenLimit, R}; use serde::{de::DeserializeOwned, Deserialize, Serialize}; @@ -46,7 +47,7 @@ pub const MIN_VERSION: Version = Version(2); /// Code between the `CURRENT_VERSION` and `MIN_VERSION` must remain /// compatible. Use the rules described in the comments for [`Msg`] to evolve /// the protocol such that this remains true. -pub const CURRENT_VERSION: Version = Version(3); +pub const CURRENT_VERSION: Version = Version(4); /// We allow room in the buffer for message evolution pub const REQUEST_BUF_SIZE: usize = 1024; @@ -316,6 +317,21 @@ where )] pub struct Version(pub u32); +#[derive(Clone, Serialize, Deserialize, SerializedSize)] +pub enum CfpaState { + /// The CFPA page used by the ROM + Active, + /// The CFPA that will be applied on the next update + Pending, + /// The CFPA region that is neither pending or active + Alternate, +} + +#[derive(Clone, Serialize, Deserialize, SerializedSize)] +pub enum PageReq { + Page(RotPage), +} + /// The body of a sprot request. /// /// See [`Msg`] for details about versioning and message evolution. @@ -330,6 +346,8 @@ pub enum ReqBody { // Added in sprot protocol version 3 Caboose(CabooseReq), Attest(AttestReq), + // Added in sprot protocol version 4 + RotPage { page: RotPage }, } /// Instruct the RoT to take a dump of the SP via SWD @@ -424,6 +442,14 @@ pub enum RspBody { Caboose(Result), Attest(Result), + + Page(Result), +} + +/// A response for reading a ROT page +#[derive(Copy, Clone, Serialize, Deserialize, SerializedSize)] +pub enum RotPageRsp { + RotPage, } /// A response from the Dumper diff --git a/drv/stm32h7-sprot-server/src/main.rs b/drv/stm32h7-sprot-server/src/main.rs index eda364674a..9ef4ad965f 100644 --- a/drv/stm32h7-sprot-server/src/main.rs +++ b/drv/stm32h7-sprot-server/src/main.rs @@ -8,7 +8,9 @@ use attest_api::HashAlgorithm; use core::convert::Into; -use drv_lpc55_update_api::{RotBootInfo, SlotId, SwitchDuration, UpdateTarget}; +use drv_lpc55_update_api::{ + RotBootInfo, RotPage, SlotId, SwitchDuration, UpdateTarget, +}; use drv_spi_api::{CsState, SpiDevice, SpiServer}; use drv_sprot_api::*; use drv_stm32xx_sys_api as sys_api; @@ -57,6 +59,7 @@ enum Trace { RotReadyTimeout, RspTimeout, RxBuf([u8; 16]), + RotPage, } ringbuf!(Trace, 64, Trace::None); @@ -71,8 +74,8 @@ const RETRY_TIMEOUT: u64 = 5; const TIMEOUT_QUICK: u32 = 5; /// Default covers fail, pulse, retry const DEFAULT_ATTEMPTS: u16 = 3; -// Tune the RoT flash write timeout -const TIMEOUT_WRITE_ONE_BLOCK: u32 = 50; +/// Slightly longer timeout +const TIMEOUT_MEDIUM: u32 = 50; // Delay between asserting CSn and sending the portion of a message // that fits entierly in the RoT's FIFO. @@ -629,7 +632,7 @@ impl idl::InOrderSpRotImpl for ServerImpl { let rsp = self.do_send_recv_retries( tx_size, - TIMEOUT_WRITE_ONE_BLOCK, + TIMEOUT_MEDIUM, MAX_UPDATE_ATTEMPTS, )?; @@ -906,13 +909,51 @@ impl idl::InOrderSpRotImpl for ServerImpl { Err(e) => Err(AttestOrSprotError::Sprot(e).into()), } } + + fn read_rot_page( + &mut self, + _: &userlib::RecvMessage, + page: RotPage, + data: idol_runtime::Leased, + ) -> Result<(), idol_runtime::RequestError> { + ringbuf_entry!(Trace::RotPage); + let body = ReqBody::RotPage { page }; + let tx_size = Request::pack(&body, &mut self.tx_buf); + let rsp = self.do_send_recv_retries( + tx_size, + TIMEOUT_MEDIUM, + DEFAULT_ATTEMPTS, + )?; + + match rsp.body { + Ok(RspBody::Page(Ok(RotPageRsp::RotPage))) => { + // Copy from the trailing data into the lease + if rsp.blob.len() < data.len() { + return Err(idol_runtime::RequestError::Fail( + idol_runtime::ClientError::BadLease, + )); + } + data.write_range(0..data.len(), &rsp.blob[..data.len()]) + .map_err(|()| { + idol_runtime::RequestError::Fail( + idol_runtime::ClientError::WentAway, + ) + })?; + Ok(()) + } + Ok(RspBody::Page(_)) | Ok(_) => { + Err(SprotProtocolError::UnexpectedResponse)? + } + Err(e) => Err(e.into()), + } + } } mod idl { use super::{ AttestOrSprotError, DumpOrSprotError, HashAlgorithm, PulseStatus, - RawCabooseOrSprotError, RotBootInfo, RotState, SlotId, SprotError, - SprotIoStats, SprotStatus, SwitchDuration, UpdateTarget, + RawCabooseOrSprotError, RotBootInfo, RotPage, RotState, SlotId, + SprotError, SprotIoStats, SprotStatus, SwitchDuration, UpdateTarget, }; include!(concat!(env!("OUT_DIR"), "/server_stub.rs")); diff --git a/idl/lpc55-update.idol b/idl/lpc55-update.idol index e039f84967..1bc217c76f 100644 --- a/idl/lpc55-update.idol +++ b/idl/lpc55-update.idol @@ -62,7 +62,7 @@ Interface( doc: "Get info about installed images (deprecated - use rot_boot_info)", args: { }, reply : Result( - ok: "RotBootState", + ok: "stage0_handoff::RotBootState", err: Complex("HandoffDataLoadError"), ), idempotent: true, @@ -128,5 +128,20 @@ Interface( encoding: Hubpack, idempotent: true, ), + "read_rot_page": ( + doc: "Read CMPA/CFPA page", + args: { + "page": "RotPage", + }, + leases : { + "data": (type: "[u8]", write: true, max_len: Some(512)), + }, + reply: Result ( + ok: "()", + err: CLike("drv_update_api::UpdateError"), + ), + encoding: Hubpack, + idempotent: true, + ), }, ) diff --git a/idl/sprot.idol b/idl/sprot.idol index a616b8ac64..7c479bed21 100644 --- a/idl/sprot.idol +++ b/idl/sprot.idol @@ -219,5 +219,21 @@ Interface( ), encoding: Hubpack, ), + "read_rot_page": ( + doc: "Read a CMPA/CFPA page from the RoT", + args: { + "page": "RotPage", + }, + leases: { + "dest": (type: "[u8]", write: true), + }, + reply: Result( + ok: "()", + err: Complex("SprotError"), + ), + encoding: Hubpack, + idempotent: true, + ), + } ) diff --git a/task/control-plane-agent/Cargo.toml b/task/control-plane-agent/Cargo.toml index 2410cfa420..ce31a657af 100644 --- a/task/control-plane-agent/Cargo.toml +++ b/task/control-plane-agent/Cargo.toml @@ -30,6 +30,7 @@ drv-transceivers-api = { path = "../../drv/transceivers-api", optional = true } drv-update-api = { path = "../../drv/update-api" } drv-user-leds-api = { path = "../../drv/user-leds-api", optional = true } host-sp-messages = { path = "../../lib/host-sp-messages" } +lpc55-rom-data = { path = "../../lib/lpc55-rom-data" } mutable-statics = { path = "../../lib/mutable-statics" } ringbuf = { path = "../../lib/ringbuf" } task-control-plane-agent-api = { path = "../control-plane-agent-api" } diff --git a/task/control-plane-agent/src/main.rs b/task/control-plane-agent/src/main.rs index 9621d1cbe9..0af764690a 100644 --- a/task/control-plane-agent/src/main.rs +++ b/task/control-plane-agent/src/main.rs @@ -65,6 +65,7 @@ enum Log { SprotCabooseSize(u32), ReadCaboose(u32, usize), GotCabooseChunk([u8; 4]), + ReadRotPage, } // This enum does not define the actual MGS protocol - it is only used in the @@ -149,6 +150,7 @@ enum MgsMessage { key: u8, value_len: usize, }, + ReadRotPage, } ringbuf!(Log, 16, Log::Empty); diff --git a/task/control-plane-agent/src/mgs_common.rs b/task/control-plane-agent/src/mgs_common.rs index bca080a7cc..6fd0f6748f 100644 --- a/task/control-plane-agent/src/mgs_common.rs +++ b/task/control-plane-agent/src/mgs_common.rs @@ -10,9 +10,9 @@ use drv_sprot_api::{ }; use drv_stm32h7_update_api::Update; use gateway_messages::{ - DiscoverResponse, PowerState, RotError, RotSlotId, RotStateV2, - SensorReading, SensorRequest, SensorRequestKind, SensorResponse, - SpComponent, SpError, SpPort, SpStateV2, + CfpaPage, DiscoverResponse, PowerState, RotError, RotRequest, RotResponse, + RotSlotId, RotStateV2, SensorReading, SensorRequest, SensorRequestKind, + SensorResponse, SpComponent, SpError, SpPort, SpStateV2, }; use ringbuf::ringbuf_entry_root as ringbuf_entry; use static_assertions::const_assert; @@ -377,6 +377,34 @@ impl MgsCommon { pub(crate) fn current_time(&mut self) -> Result { Ok(sys_get_timer().now) } + + pub(crate) fn read_rot_page( + &mut self, + req: RotRequest, + buf: &mut [u8], + ) -> Result { + ringbuf_entry!(Log::MgsMessage(MgsMessage::ReadRotPage)); + let page = match req { + RotRequest::ReadCmpa => drv_sprot_api::RotPage::Cmpa, + RotRequest::ReadCfpa(CfpaPage::Scratch) => { + drv_sprot_api::RotPage::CfpaScratch + } + RotRequest::ReadCfpa(CfpaPage::Active) => { + drv_sprot_api::RotPage::CfpaActive + } + RotRequest::ReadCfpa(CfpaPage::Inactive) => { + drv_sprot_api::RotPage::CfpaInactive + } + }; + + match self + .sprot + .read_rot_page(page, &mut buf[..lpc55_rom_data::FLASH_PAGE_SIZE]) + { + Ok(_) => Ok(RotResponse::Ok), + Err(e) => Err(e.into()), + } + } } fn translate_sensor_nodata( diff --git a/task/control-plane-agent/src/mgs_gimlet.rs b/task/control-plane-agent/src/mgs_gimlet.rs index 8a2e383ad3..4341ecfda0 100644 --- a/task/control-plane-agent/src/mgs_gimlet.rs +++ b/task/control-plane-agent/src/mgs_gimlet.rs @@ -18,9 +18,10 @@ use gateway_messages::sp_impl::{ use gateway_messages::{ ignition, ComponentAction, ComponentDetails, ComponentUpdatePrepare, DiscoverResponse, Header, IgnitionCommand, IgnitionState, Message, - MessageKind, MgsError, PowerState, SensorRequest, SensorResponse, - SpComponent, SpError, SpPort, SpRequest, SpStateV2, SpUpdatePrepare, - UpdateChunk, UpdateId, UpdateStatus, SERIAL_CONSOLE_IDLE_TIMEOUT, + MessageKind, MgsError, PowerState, RotRequest, RotResponse, SensorRequest, + SensorResponse, SpComponent, SpError, SpPort, SpRequest, SpStateV2, + SpUpdatePrepare, UpdateChunk, UpdateId, UpdateStatus, + SERIAL_CONSOLE_IDLE_TIMEOUT, }; use heapless::{Deque, Vec}; use host_sp_messages::HostStartupOptions; @@ -1072,6 +1073,14 @@ impl SpHandler for MgsHandler { fn current_time(&mut self) -> Result { self.common.current_time() } + + fn read_rot( + &mut self, + req: RotRequest, + buf: &mut [u8], + ) -> Result { + self.common.read_rot_page(req, buf) + } } struct UsartHandler { diff --git a/task/control-plane-agent/src/mgs_psc.rs b/task/control-plane-agent/src/mgs_psc.rs index b1b11f9fc7..a970431433 100644 --- a/task/control-plane-agent/src/mgs_psc.rs +++ b/task/control-plane-agent/src/mgs_psc.rs @@ -13,8 +13,9 @@ use gateway_messages::sp_impl::{ use gateway_messages::{ ignition, ComponentAction, ComponentDetails, ComponentUpdatePrepare, DiscoverResponse, IgnitionCommand, IgnitionState, MgsError, PowerState, - SensorRequest, SensorResponse, SpComponent, SpError, SpPort, SpStateV2, - SpUpdatePrepare, UpdateChunk, UpdateId, UpdateStatus, + RotRequest, RotResponse, SensorRequest, SensorResponse, SpComponent, + SpError, SpPort, SpStateV2, SpUpdatePrepare, UpdateChunk, UpdateId, + UpdateStatus, }; use host_sp_messages::HostStartupOptions; use idol_runtime::{Leased, RequestError}; @@ -608,4 +609,12 @@ impl SpHandler for MgsHandler { fn current_time(&mut self) -> Result { self.common.current_time() } + + fn read_rot( + &mut self, + req: RotRequest, + buf: &mut [u8], + ) -> Result { + self.common.read_rot_page(req, buf) + } } diff --git a/task/control-plane-agent/src/mgs_sidecar.rs b/task/control-plane-agent/src/mgs_sidecar.rs index 65b7649e68..43d597e2db 100644 --- a/task/control-plane-agent/src/mgs_sidecar.rs +++ b/task/control-plane-agent/src/mgs_sidecar.rs @@ -16,8 +16,9 @@ use gateway_messages::sp_impl::{ use gateway_messages::{ ignition, ComponentAction, ComponentDetails, ComponentUpdatePrepare, DiscoverResponse, IgnitionCommand, IgnitionState, MgsError, PowerState, - SensorRequest, SensorResponse, SpComponent, SpError, SpPort, SpStateV2, - SpUpdatePrepare, UpdateChunk, UpdateId, UpdateStatus, + RotRequest, RotResponse, SensorRequest, SensorResponse, SpComponent, + SpError, SpPort, SpStateV2, SpUpdatePrepare, UpdateChunk, UpdateId, + UpdateStatus, }; use host_sp_messages::HostStartupOptions; use idol_runtime::{Leased, RequestError}; @@ -717,6 +718,14 @@ impl SpHandler for MgsHandler { fn current_time(&mut self) -> Result { self.common.current_time() } + + fn read_rot( + &mut self, + req: RotRequest, + buf: &mut [u8], + ) -> Result { + self.common.read_rot_page(req, buf) + } } // Helper function for `.map_err()`; we can't use `?` because we can't implement