Skip to content

Commit

Permalink
Add support for reading out the VPD lock bits via MGS
Browse files Browse the repository at this point in the history
Some targets like the gimletlet have a control-plane-agent but no
VPD support, hence the creation of the vpd feature. This does introduce
some runtime overhead but the expectation is that this feature is not
performance critical.
  • Loading branch information
labbott committed Feb 28, 2024
1 parent 0c29f28 commit 08c2fd6
Show file tree
Hide file tree
Showing 12 changed files with 262 additions and 149 deletions.
292 changes: 146 additions & 146 deletions Cargo.lock

Large diffs are not rendered by default.

2 changes: 2 additions & 0 deletions app/gimlet/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -260,12 +260,14 @@ task-slots = [
"i2c_driver",
"packrat",
"user_leds",
"vpd",
]
features = [
"gimlet",
"usart1",
"vlan",
"baud_rate_3M",
"vpd",
]
notifications = ["usart-irq", "socket", "timer"]
interrupts = {"usart1.irq" = "usart-irq"}
Expand Down
3 changes: 2 additions & 1 deletion app/psc/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -140,8 +140,9 @@ task-slots = [
"sprot",
"packrat",
"user_leds",
"vpd",
]
features = ["psc", "vlan"]
features = ["psc", "vlan", "vpd"]
notifications = ["usart-irq", "socket", "timer"]
# usart-irq is unused but present in the code

Expand Down
3 changes: 2 additions & 1 deletion app/sidecar/base.toml
Original file line number Diff line number Diff line change
Expand Up @@ -99,8 +99,9 @@ task-slots = [
"ignition",
"packrat",
"transceivers",
"vpd",
]
features = ["sidecar", "vlan", "auxflash"]
features = ["sidecar", "vlan", "auxflash", "vpd"]
notifications = ["socket", "usart-irq", "timer"]

[tasks.sprot]
Expand Down
6 changes: 6 additions & 0 deletions idl/vpd.idol
Original file line number Diff line number Diff line change
Expand Up @@ -54,5 +54,11 @@ Interface(
err: CLike("VpdError"),
),
),
"num_vpd_devices": (
doc: "Returns the total number of VPD devices in the system",
args: {},
reply: Simple("usize"),
idempotent: true,
),
},
)
3 changes: 2 additions & 1 deletion task/control-plane-agent/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@ drv-stm32h7-usart = { path = "../../drv/stm32h7-usart", features = ["h753"], opt
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 }
task-vpd-api = { path = "../../task/vpd-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" }
Expand All @@ -51,7 +52,7 @@ idol = { workspace = true }
gimlet = ["drv-gimlet-hf-api", "drv-gimlet-seq-api", "drv-stm32h7-usart", "drv-user-leds-api"]
sidecar = ["drv-sidecar-seq-api", "drv-monorail-api", "drv-ignition-api", "drv-transceivers-api"]
psc = ["drv-user-leds-api"]

vpd = ["task-vpd-api"]
vlan = ["task-net-api/vlan"]

usart1 = []
Expand Down
2 changes: 2 additions & 0 deletions task/control-plane-agent/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -78,6 +78,7 @@ enum Log {
GotCabooseChunk([u8; 4]),
ReadRotPage,
IpcRequest(#[count(children)] IpcRequest),
VpdLockStatus,
}

// This enum does not define the actual MGS protocol - it is only used in the
Expand Down Expand Up @@ -163,6 +164,7 @@ enum MgsMessage {
value_len: usize,
},
ReadRotPage,
VpdLockStatus,
}

// This enum does not define the actual IPC protocol - it is only used in the
Expand Down
72 changes: 72 additions & 0 deletions task/control-plane-agent/src/mgs_common.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use gateway_messages::{
CfpaPage, DiscoverResponse, PowerState, RotError, RotRequest, RotResponse,
RotSlotId, RotStateV2, SensorReading, SensorRequest, SensorRequestKind,
SensorResponse, SpComponent, SpError, SpPort, SpStateV2,
VpdError as GatewayVpdError,
};
use ringbuf::ringbuf_entry_root as ringbuf_entry;
use static_assertions::const_assert;
Expand Down Expand Up @@ -405,6 +406,77 @@ impl MgsCommon {
Err(e) => Err(e.into()),
}
}

#[cfg(not(feature = "vpd"))]
pub(crate) fn vpd_lock_status_all(
&self,
_buf: &mut [u8],
) -> Result<usize, SpError> {
ringbuf_entry!(Log::MgsMessage(MgsMessage::VpdLockStatus));
Err(SpError::Vpd(GatewayVpdError::NotImplemented))
}

#[cfg(feature = "vpd")]
pub(crate) fn vpd_lock_status_all(
&self,
buf: &mut [u8],
) -> Result<usize, SpError> {
use task_vpd_api::{Vpd, VpdError};
task_slot!(VPD, vpd);

ringbuf_entry!(Log::MgsMessage(MgsMessage::VpdLockStatus));
let vpd = Vpd::from(VPD.get_task_id());
let cnt = vpd.num_vpd_devices();

for (i, entry) in buf.iter_mut().enumerate().take(cnt) {
// `cnt` is based on the static size of the number of VPD devices.
// All the VPD APIs work off of a `u8` so if the number of VPD
// devices is returned as being greater than a `u8` we wouldn't
// actually be able to access them. We could probably remove this
// panic...
let idx = match u8::try_from(i) {
Ok(v) => v,
Err(_) => panic!(),
};
*entry = match vpd.is_locked(idx) {
Ok(v) => v.into(),
Err(e) => {
return Err(SpError::Vpd(match e {
VpdError::InvalidDevice => {
GatewayVpdError::InvalidDevice
}
VpdError::NotPresent => GatewayVpdError::NotPresent,
VpdError::DeviceError => GatewayVpdError::DeviceError,
VpdError::Unavailable => GatewayVpdError::Unavailable,
VpdError::DeviceTimeout => {
GatewayVpdError::DeviceTimeout
}
VpdError::DeviceOff => GatewayVpdError::DeviceOff,
VpdError::BadAddress => GatewayVpdError::BadAddress,
VpdError::BadBuffer => GatewayVpdError::BadBuffer,
VpdError::BadRead => GatewayVpdError::BadRead,
VpdError::BadWrite => GatewayVpdError::BadWrite,
VpdError::BadLock => GatewayVpdError::BadLock,
VpdError::NotImplemented => {
GatewayVpdError::NotImplemented
}
VpdError::IsLocked => GatewayVpdError::IsLocked,
VpdError::PartiallyLocked => {
GatewayVpdError::PartiallyLocked
}
VpdError::AlreadyLocked => {
GatewayVpdError::AlreadyLocked
}
VpdError::ServerRestarted => {
GatewayVpdError::TaskRestarted
}
}))
}
}
}

Ok(cnt)
}
}

fn translate_sensor_nodata(
Expand Down
7 changes: 7 additions & 0 deletions task/control-plane-agent/src/mgs_gimlet.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1108,6 +1108,13 @@ impl SpHandler for MgsHandler {
) -> Result<RotResponse, SpError> {
self.common.read_rot_page(req, buf)
}

fn vpd_lock_status_all(
&mut self,
buf: &mut [u8],
) -> Result<usize, SpError> {
self.common.vpd_lock_status_all(buf)
}
}

struct UsartHandler {
Expand Down
7 changes: 7 additions & 0 deletions task/control-plane-agent/src/mgs_psc.rs
Original file line number Diff line number Diff line change
Expand Up @@ -642,4 +642,11 @@ impl SpHandler for MgsHandler {
) -> Result<RotResponse, SpError> {
self.common.read_rot_page(req, buf)
}

fn vpd_lock_status_all(
&mut self,
buf: &mut [u8],
) -> Result<usize, SpError> {
self.common.vpd_lock_status_all(buf)
}
}
7 changes: 7 additions & 0 deletions task/control-plane-agent/src/mgs_sidecar.rs
Original file line number Diff line number Diff line change
Expand Up @@ -751,6 +751,13 @@ impl SpHandler for MgsHandler {
) -> Result<RotResponse, SpError> {
self.common.read_rot_page(req, buf)
}

fn vpd_lock_status_all(
&mut self,
buf: &mut [u8],
) -> Result<usize, SpError> {
self.common.vpd_lock_status_all(buf)
}
}

// Helper function for `.map_err()`; we can't use `?` because we can't implement
Expand Down
7 changes: 7 additions & 0 deletions task/vpd/src/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -193,6 +193,13 @@ impl idl::InOrderVpdImpl for ServerImpl {
Ok(()) => Ok(()),
}
}

fn num_vpd_devices(
&mut self,
_: &RecvMessage,
) -> Result<usize, RequestError<core::convert::Infallible>> {
Ok(i2c_config::devices::at24csw080(I2C.get_task_id()).len())
}
}

impl NotificationHandler for ServerImpl {
Expand Down

0 comments on commit 08c2fd6

Please sign in to comment.