use crate::connection::{Channel, IpmiCommand, Message, NetFn, NotEnoughData};
pub struct GetChannelAccess {
channel: Channel,
access_type: ChannelAccessType,
}
impl GetChannelAccess {
pub fn new(channel: Channel, access_type: ChannelAccessType) -> Self {
Self {
channel,
access_type,
}
}
pub fn non_volatile(channel: Channel) -> Self {
Self::new(channel, ChannelAccessType::NonVolatile)
}
pub fn volatile(channel: Channel) -> Self {
Self::new(channel, ChannelAccessType::Volatile)
}
}
impl From<GetChannelAccess> for Message {
fn from(value: GetChannelAccess) -> Self {
let channel = value.channel.value() & 0x0F;
let access_type = match value.access_type {
ChannelAccessType::NonVolatile => 0x40, ChannelAccessType::Volatile => 0x80, };
Message::new_request(NetFn::App, 0x41, vec![channel, access_type])
}
}
impl IpmiCommand for GetChannelAccess {
type Output = ChannelAccess;
type Error = NotEnoughData;
fn parse_success_response(data: &[u8]) -> Result<Self::Output, Self::Error> {
ChannelAccess::parse(data).ok_or(NotEnoughData)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ChannelAccessType {
NonVolatile,
Volatile,
}
#[derive(Clone, Debug, PartialEq)]
pub struct ChannelAccess {
pub access_mode: ChannelAccessMode,
pub alerting_disabled: bool,
pub per_msg_auth_disabled: bool,
pub user_level_auth_disabled: bool,
pub privilege_level_limit: ChannelPrivilegeLevel,
}
impl ChannelAccess {
pub fn parse(data: &[u8]) -> Option<Self> {
if data.len() < 2 {
return None;
}
let access_mode = ChannelAccessMode::from(data[0] & 0x07);
let alerting_disabled = (data[0] & 0x20) == 0x20;
let per_msg_auth_disabled = (data[0] & 0x10) == 0x10;
let user_level_auth_disabled = (data[0] & 0x08) == 0x08;
let privilege_level_limit = ChannelPrivilegeLevel::from(data[1] & 0x0F);
Some(Self {
access_mode,
alerting_disabled,
per_msg_auth_disabled,
user_level_auth_disabled,
privilege_level_limit,
})
}
pub fn is_disabled(&self) -> bool {
matches!(self.access_mode, ChannelAccessMode::Disabled)
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ChannelAccessMode {
Disabled,
PreBootOnly,
AlwaysAvailable,
Shared,
Unknown(u8),
}
impl From<u8> for ChannelAccessMode {
fn from(value: u8) -> Self {
match value {
0x00 => Self::Disabled,
0x01 => Self::PreBootOnly,
0x02 => Self::AlwaysAvailable,
0x03 => Self::Shared,
v => Self::Unknown(v),
}
}
}
impl core::fmt::Display for ChannelAccessMode {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
ChannelAccessMode::Disabled => write!(f, "Disabled"),
ChannelAccessMode::PreBootOnly => write!(f, "Pre-boot Only"),
ChannelAccessMode::AlwaysAvailable => write!(f, "Always Available"),
ChannelAccessMode::Shared => write!(f, "Shared"),
ChannelAccessMode::Unknown(value) => write!(f, "Unknown (0x{value:02X})"),
}
}
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum ChannelPrivilegeLevel {
Reserved,
Callback,
User,
Operator,
Administrator,
Oem,
Unknown(u8),
}
impl From<u8> for ChannelPrivilegeLevel {
fn from(value: u8) -> Self {
match value {
0x00 => Self::Reserved,
0x01 => Self::Callback,
0x02 => Self::User,
0x03 => Self::Operator,
0x04 => Self::Administrator,
0x05 => Self::Oem,
v => Self::Unknown(v),
}
}
}
impl core::fmt::Display for ChannelPrivilegeLevel {
fn fmt(&self, f: &mut core::fmt::Formatter<'_>) -> core::fmt::Result {
match self {
ChannelPrivilegeLevel::Reserved => write!(f, "Reserved"),
ChannelPrivilegeLevel::Callback => write!(f, "Callback"),
ChannelPrivilegeLevel::User => write!(f, "User"),
ChannelPrivilegeLevel::Operator => write!(f, "Operator"),
ChannelPrivilegeLevel::Administrator => write!(f, "Administrator"),
ChannelPrivilegeLevel::Oem => write!(f, "OEM"),
ChannelPrivilegeLevel::Unknown(value) => write!(f, "Unknown (0x{value:02X})"),
}
}
}