use core::fmt;
use bitflags::bitflags;
use crate::{MalformedStructureError, RawStructure};
#[allow(non_camel_case_types)]
#[derive(Copy, Clone, Debug, Eq, Hash, PartialEq)]
pub enum BoardType {
Unknown,
Other,
ServerBlade,
ConnectivitySwitch,
SystemManagementModule,
ProcessorModule,
IoModule,
MemoryModule,
DaughterBoard,
MotherBoard,
ProcessorMemoryModule,
ProcessorIoModule,
InterconnectBoard,
Undefined(u8),
}
impl From<u8> for BoardType {
fn from(_type: u8) -> BoardType {
match _type {
1 => BoardType::Unknown,
2 => BoardType::Other,
3 => BoardType::ServerBlade,
4 => BoardType::ConnectivitySwitch,
5 => BoardType::SystemManagementModule,
6 => BoardType::ProcessorModule,
7 => BoardType::IoModule,
8 => BoardType::MemoryModule,
9 => BoardType::DaughterBoard,
10 => BoardType::MotherBoard,
11 => BoardType::ProcessorMemoryModule,
12 => BoardType::ProcessorIoModule,
13 => BoardType::InterconnectBoard,
t => BoardType::Undefined(t),
}
}
}
impl fmt::Display for BoardType {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
BoardType::Unknown => write!(f, "Unknown"),
BoardType::Other => write!(f, "Other"),
BoardType::ServerBlade => write!(f, "Server Blade"),
BoardType::ConnectivitySwitch => write!(f, "Connectivity Switch"),
BoardType::SystemManagementModule => write!(f, "System Management Module"),
BoardType::ProcessorModule => write!(f, "Processor Module"),
BoardType::IoModule => write!(f, "I/O Module"),
BoardType::MemoryModule => write!(f, "Memory Module"),
BoardType::DaughterBoard => write!(f, "Daughter board"),
BoardType::MotherBoard => {
write!(f, "Motherboard (includes processor, memory, and I/O)")
}
BoardType::ProcessorMemoryModule => write!(f, "Processor/Memory Module"),
BoardType::ProcessorIoModule => write!(f, "Processor/IO Module"),
BoardType::InterconnectBoard => write!(f, "Interconnect board"),
BoardType::Undefined(t) => write!(f, "Undefined: {t}"),
}
}
}
bitflags! {
#[derive(Debug, Clone, PartialEq, Eq, Hash)]
pub struct BaseBoardFlags: u8 {
const HOSTING = 0b0000_0001;
const REQUIRES_DAUGHTER = 0b0000_0010;
const IS_REMOVABLE = 0b0000_0100;
const IS_REPLACEABLE = 0b0000_1000;
const IS_HOT_SWAPPABLE = 0b0001_0000;
}
}
#[derive(Clone, Debug, Eq, Hash, PartialEq)]
pub struct BaseBoard<'buffer> {
pub handle: u16,
pub manufacturer: &'buffer str,
pub product: &'buffer str,
pub version: &'buffer str,
pub serial: &'buffer str,
pub asset: Option<&'buffer str>,
pub feature_flags: Option<BaseBoardFlags>,
pub location_in_chassis: Option<&'buffer str>,
pub chassis_handle: Option<u16>,
pub board_type: Option<BoardType>,
}
impl<'buffer> BaseBoard<'buffer> {
pub(crate) fn try_from(structure: RawStructure<'buffer>) -> Result<BaseBoard<'buffer>, MalformedStructureError> {
#[repr(C)]
#[repr(packed)]
struct BaseBoardPacked {
manufacturer: u8,
product: u8,
version: u8,
serial: u8,
asset: u8,
feature_flags: u8,
location_in_chassis: u8,
chassis_handle: u16,
board_type: u8,
}
let_as_struct!(packed, BaseBoardPacked, structure.data);
let asset = if structure.data.len() > 4 {
Some(structure.find_string(packed.asset)?)
} else {
None
};
let feature_flags = if structure.data.len() > 5 {
Some(BaseBoardFlags::from_bits_truncate(packed.feature_flags))
} else {
None
};
let location_in_chassis = if structure.data.len() > 6 {
Some(structure.find_string(packed.location_in_chassis)?)
} else {
None
};
let chassis_handle = if structure.data.len() > 7 {
Some(u16::from_le(packed.chassis_handle))
} else {
None
};
let board_type = if structure.data.len() > 9 {
Some(packed.board_type.into())
} else {
None
};
Ok(BaseBoard {
handle: structure.handle,
manufacturer: structure.find_string(packed.manufacturer)?,
product: structure.find_string(packed.product)?,
version: structure.find_string(packed.version)?,
serial: structure.find_string(packed.serial)?,
asset,
feature_flags,
location_in_chassis,
chassis_handle,
board_type,
})
}
}