Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add ReadRot message for CMPA / CFPA #116

Merged
merged 2 commits into from
Sep 13, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
78 changes: 78 additions & 0 deletions faux-mgs/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@ use anyhow::Context;
use anyhow::Result;
use clap::Parser;
use clap::Subcommand;
use clap::ValueEnum;
use futures::stream::FuturesOrdered;
use futures::FutureExt;
use futures::StreamExt;
Expand All @@ -22,6 +23,7 @@ use gateway_messages::SpComponent;
use gateway_messages::StartupOptions;
use gateway_messages::UpdateId;
use gateway_messages::UpdateStatus;
use gateway_messages::ROT_PAGE_SIZE;
use gateway_sp_comms::InMemoryHostPhase2Provider;
use gateway_sp_comms::SharedSocket;
use gateway_sp_comms::SingleSp;
Expand Down Expand Up @@ -344,6 +346,23 @@ enum Command {
/// Sensor ID
id: u32,
},

/// Reads the CMPA from an attached Root of Trust
ReadCmpa {
/// Output file (by default, pretty-printed to `stdout`)
#[clap(short, long)]
out: Option<PathBuf>,
},

/// Reads a CFPA slot from an attached Root of Trust
ReadCfpa {
/// Output file (by default, pretty-printed to `stdout`)
#[clap(short, long)]
out: Option<PathBuf>,

#[clap(short, long, default_value_t = CfpaSlot::Active)]
slot: CfpaSlot,
},
}

#[derive(Subcommand, Debug, Clone)]
Expand All @@ -356,6 +375,30 @@ enum LedCommand {
Blink,
}

#[derive(ValueEnum, Debug, Clone)]
enum CfpaSlot {
Active,
Inactive,
Scratch,
}

impl std::fmt::Display for CfpaSlot {
fn fmt(
&self,
f: &mut std::fmt::Formatter<'_>,
) -> Result<(), std::fmt::Error> {
write!(
f,
"{}",
match self {
CfpaSlot::Active => "active",
CfpaSlot::Inactive => "inactive",
CfpaSlot::Scratch => "scratch",
}
)
}
}

impl Command {
// If the user didn't specify a listening port, what should we use? We
// allow this to vary by command so that client commands (most of them) can
Expand Down Expand Up @@ -1229,9 +1272,44 @@ async fn run_command(
})
})
}
Command::ReadCmpa { out } => {
let data = sp.read_rot_cmpa().await?;
handle_cxpa("cmpa", data, out, json)
}
Command::ReadCfpa { out, slot } => {
let data = match slot {
CfpaSlot::Active => sp.read_rot_active_cfpa().await,
CfpaSlot::Inactive => sp.read_rot_inactive_cfpa().await,
CfpaSlot::Scratch => sp.read_rot_scratch_cfpa().await,
}?;
handle_cxpa("cfpa", data, out, json)
}
}
}

fn handle_cxpa(
name: &str,
data: [u8; ROT_PAGE_SIZE],
out: Option<PathBuf>,
json: bool,
) -> Result<Output> {
Ok(if let Some(f) = &out {
std::fs::write(f, data).context(format!(
"failed to write {} to {f:?}",
name.to_uppercase()
))?;
if json {
Output::Json(json!({ "ok": true }))
} else {
Output::Lines(vec!["ok".to_string()])
}
} else if json {
Output::Json(json!({ name: data.to_vec() }))
} else {
Output::Lines(vec![format!("{data:x?}")])
})
}

async fn update(
log: &Logger,
sp: &SingleSp,
Expand Down
42 changes: 41 additions & 1 deletion gateway-messages/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,9 @@ pub const SERIAL_CONSOLE_IDLE_TIMEOUT: Duration = Duration::from_secs(20);
/// Maximum size in bytes for a serialized message.
pub const MAX_SERIALIZED_SIZE: usize = 1024;

/// Size for a memory page in the Root of Trust (LPC55)
pub const ROT_PAGE_SIZE: usize = 512;

/// Module specifying the minimum and current version of the MGS protocol.
///
/// Our primary mechanism for serializing requests and responses is enums
Expand Down Expand Up @@ -63,7 +66,7 @@ pub const MAX_SERIALIZED_SIZE: usize = 1024;
/// for more detail and discussion.
pub mod version {
pub const MIN: u32 = 2;
pub const CURRENT: u32 = 9;
pub const CURRENT: u32 = 10;
}

#[derive(
Expand Down Expand Up @@ -193,6 +196,21 @@ pub enum SensorResponse {
ErrorCount(u32),
}

/// Response to an [`RotRequest`]
#[derive(
Debug,
Clone,
Copy,
PartialEq,
SerializedSize,
Serialize,
Deserialize,
strum_macros::IntoStaticStr,
)]
pub enum RotResponse {
Ok,
}

/// An error or issue that led to sensor data not being available
///
/// Equivalent to `NoData` in Hubris.
Expand All @@ -207,6 +225,28 @@ pub enum SensorDataMissing {
DeviceTimeout,
}

/// Request to the CMPA
#[derive(
Debug, Clone, Copy, PartialEq, Eq, SerializedSize, Serialize, Deserialize,
)]
pub enum RotRequest {
ReadCmpa,
ReadCfpa(CfpaPage),
}

/// Specific CFPA page
#[derive(
Debug, Clone, Copy, PartialEq, Eq, SerializedSize, Serialize, Deserialize,
)]
pub enum CfpaPage {
/// Currently active page
Active,
/// Currently inactive page
Inactive,
/// Page that may become active upon reset
Scratch,
}

#[derive(
Debug, Clone, Copy, PartialEq, Eq, SerializedSize, Serialize, Deserialize,
)]
Expand Down
4 changes: 4 additions & 0 deletions gateway-messages/src/mgs_to_sp.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use crate::ignition::TransceiverSelect;
use crate::BadRequestReason;
use crate::PowerState;
use crate::RotRequest;
use crate::RotSlotId;
use crate::SensorRequest;
use crate::SpComponent;
Expand Down Expand Up @@ -165,6 +166,9 @@ pub enum MgsRequest {

/// Requests the target's current time (usually milliseconds since boot)
CurrentTime,

/// Issues a sensor read request
ReadRot(RotRequest),
}

#[derive(
Expand Down
28 changes: 27 additions & 1 deletion gateway-messages/src/sp_impl.rs
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@ use crate::MgsError;
use crate::MgsRequest;
use crate::MgsResponse;
use crate::PowerState;
use crate::RotRequest;
use crate::RotResponse;
use crate::RotSlotId;
use crate::SensorRequest;
use crate::SensorResponse;
Expand All @@ -41,6 +43,7 @@ use crate::TlvPage;
use crate::UpdateChunk;
use crate::UpdateId;
use crate::UpdateStatus;
use crate::ROT_PAGE_SIZE;
use hubpack::error::Error as HubpackError;
use hubpack::error::Result as HubpackResult;

Expand Down Expand Up @@ -382,6 +385,12 @@ pub trait SpHandler {
) -> Result<SensorResponse, SpError>;

fn current_time(&mut self) -> Result<u64, SpError>;

fn read_rot(
&mut self,
request: RotRequest,
buf: &mut [u8],
) -> Result<RotResponse, SpError>;
}

/// Handle a single incoming message.
Expand Down Expand Up @@ -690,7 +699,8 @@ fn handle_mgs_request<H: SpHandler>(
let trailing_data = match &kind {
MgsRequest::UpdateChunk(_)
| MgsRequest::SerialConsoleWrite { .. }
| MgsRequest::SetIpccKeyLookupValue { .. } => leftover,
| MgsRequest::SetIpccKeyLookupValue { .. }
| MgsRequest::ReadRot(_) => leftover,
_ => {
if !leftover.is_empty() {
return (
Expand Down Expand Up @@ -928,6 +938,14 @@ fn handle_mgs_request<H: SpHandler>(
MgsRequest::ReadSensor(req) => {
handler.read_sensor(req).map(SpResponse::ReadSensor)
}
MgsRequest::ReadRot(req) => {
let r = handler.read_rot(req, trailing_tx_buf);
if r.is_ok() {
outgoing_trailing_data =
Some(OutgoingTrailingData::ShiftFromTail(ROT_PAGE_SIZE));
}
r.map(SpResponse::ReadRot)
}
MgsRequest::CurrentTime => {
handler.current_time().map(SpResponse::CurrentTime)
}
Expand Down Expand Up @@ -1317,6 +1335,14 @@ mod tests {
unimplemented!()
}

fn read_rot(
&mut self,
_r: RotRequest,
_buf: &mut [u8],
) -> Result<RotResponse, SpError> {
unimplemented!()
}

fn current_time(&mut self) -> Result<u64, SpError> {
unimplemented!()
}
Expand Down
2 changes: 2 additions & 0 deletions gateway-messages/src/sp_to_mgs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
use crate::tlv;
use crate::BadRequestReason;
use crate::PowerState;
use crate::RotResponse;
use crate::RotSlotId;
use crate::SensorResponse;
use crate::SpComponent;
Expand Down Expand Up @@ -124,6 +125,7 @@ pub enum SpResponse {
SpStateV2(SpStateV2),
ReadSensor(SensorResponse),
CurrentTime(u64),
ReadRot(RotResponse),
}

/// Identifier for one of of an SP's KSZ8463 management-network-facing ports.
Expand Down
17 changes: 9 additions & 8 deletions gateway-messages/tests/versioning/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,14 +6,15 @@

use serde::Serialize;

mod v2;
mod v3;
mod v4;
mod v5;
mod v6;
mod v7;
mod v8;
mod v9;
mod v02;
mod v03;
mod v04;
mod v05;
mod v06;
mod v07;
mod v08;
mod v09;
mod v10;

pub fn assert_serialized(
out: &mut [u8],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -70,15 +70,15 @@ fn host_request() {
let request =
MgsRequest::ReadSensor(SensorRequest { kind, id: 0x1234 });
let mut expected = vec![
38, // SpResponse::ReadSensor
38, // MgsRequest::ReadSensor
];
expected.extend_from_slice(serialized);
assert_serialized(&mut out, &expected, &request);
}

let request = MgsRequest::CurrentTime;
let expected = vec![
39, // SpResponse::CurrentTime
39, // MgsRequest::CurrentTime
];
assert_serialized(&mut out, &expected, &request);
}
Expand Down
53 changes: 53 additions & 0 deletions gateway-messages/tests/versioning/v10.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
// This Source Code Form is subject to the terms of the Mozilla Public
// License, v. 2.0. If a copy of the MPL was not distributed with this
// file, You can obtain one at https://mozilla.org/MPL/2.0/.

//! The tests in this module check that the serialized form of messages from MGS
//! protocol version 10 have not changed.
//!
//! If a test in this module fails, _do not change the test_! This means you
//! have changed, deleted, or reordered an existing message type or enum
//! variant, and you should revert that change. This will remain true until we
//! bump the `version::MIN` to a value higher than 10, at which point these
//! tests can be removed as we will stop supporting v10.

use super::assert_serialized;
use gateway_messages::CfpaPage;
use gateway_messages::MgsRequest;
use gateway_messages::RotRequest;
use gateway_messages::RotResponse;
use gateway_messages::SerializedSize;
use gateway_messages::SpResponse;

#[test]
fn sp_response() {
let mut out = [0; SpResponse::MAX_SIZE];
let response = SpResponse::ReadRot(RotResponse::Ok);
let expected = [40, 0];
assert_serialized(&mut out, &expected, &response);
}

#[test]
fn host_request() {
let mut out = [0; MgsRequest::MAX_SIZE];
for (r, serialized) in [
(RotRequest::ReadCmpa, &[0u8] as &[_]),
(RotRequest::ReadCfpa(CfpaPage::Active), &[1, 0]),
] {
let request = MgsRequest::ReadRot(r);
let mut expected = vec![
40, // MgsRequest::ReadRot
];
expected.extend_from_slice(serialized);
assert_serialized(&mut out, &expected, &request);
}
}

#[test]
fn cfpa_page() {
let mut out = [0; CfpaPage::MAX_SIZE];

assert_serialized(&mut out, &[0], &CfpaPage::Active);
assert_serialized(&mut out, &[1], &CfpaPage::Inactive);
assert_serialized(&mut out, &[2], &CfpaPage::Scratch);
}
2 changes: 2 additions & 0 deletions gateway-sp-comms/src/error.rs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,8 @@ pub enum CommunicationError {
IpccKeyLookupValueTooLarge,
#[error("Packet included unexpected trailing data: {0:x?}")]
UnexpectedTrailingData(Vec<u8>),
#[error("Trailing data is wrong length: expected {expected}, got {got}")]
BadTrailingDataSize { expected: usize, got: usize },
}

impl From<SingleSpHandleError> for CommunicationError {
Expand Down
Loading
Loading