ipmi_rs/storage/sel/
get_info.rs

1use crate::{
2    connection::{IpmiCommand, Message, NetFn, ParseResponseError},
3    log_vec,
4    storage::Timestamp,
5    Loggable,
6};
7
8pub struct GetInfo;
9
10impl IpmiCommand for GetInfo {
11    type Output = Info;
12
13    type Error = ();
14
15    fn parse_response(
16        completion_code: crate::connection::CompletionCode,
17        data: &[u8],
18    ) -> Result<Self::Output, ParseResponseError<Self::Error>> {
19        Self::check_cc_success(completion_code)?;
20        Info::from_data(data).ok_or(ParseResponseError::NotEnoughData)
21    }
22}
23
24impl From<GetInfo> for Message {
25    fn from(_: GetInfo) -> Self {
26        Message::new_request(NetFn::Storage, 0x40, Vec::new())
27    }
28}
29
30#[derive(Clone, Copy, Debug, PartialEq)]
31pub enum Command {
32    Clear,
33    PartialAddEntry,
34    Reserve,
35    GetAllocInfo,
36}
37
38#[derive(Debug, Clone)]
39pub struct Info {
40    pub version_maj: u8,
41    pub version_min: u8,
42    pub entries: u16,
43    pub bytes_free: u16,
44    pub last_add_time: Timestamp,
45    pub last_del_time: Timestamp,
46    pub overflow: bool,
47    pub supported_cmds: Vec<Command>,
48}
49
50impl Info {
51    pub fn from_data(data: &[u8]) -> Option<Self> {
52        if data.len() != 14 {
53            return None;
54        }
55
56        let version_maj = data[0] & 0xF;
57        let version_min = (data[0] >> 4) & 0xF;
58
59        let entries = u16::from_le_bytes([data[1], data[2]]);
60        let free = u16::from_le_bytes([data[3], data[4]]);
61
62        let last_add_time = u32::from_le_bytes([data[5], data[6], data[7], data[8]]);
63        let last_del_time = u32::from_le_bytes([data[9], data[10], data[11], data[12]]);
64        let overflow = data[13] & 0x80 == 0x80;
65
66        let mut supported_cmds = Vec::with_capacity(4);
67
68        if data[13] & 0x08 == 0x08 {
69            supported_cmds.push(Command::Clear);
70        }
71        if data[13] & 0x04 == 0x04 {
72            supported_cmds.push(Command::PartialAddEntry);
73        }
74        if data[13] & 0x02 == 0x02 {
75            supported_cmds.push(Command::Reserve);
76        }
77        if data[13] & 0x01 == 0x01 {
78            supported_cmds.push(Command::GetAllocInfo);
79        }
80
81        Some(Info {
82            version_maj,
83            version_min,
84            entries,
85            bytes_free: free,
86            last_add_time: Timestamp(last_add_time),
87            last_del_time: Timestamp(last_del_time),
88            overflow,
89            supported_cmds,
90        })
91    }
92}
93
94impl Loggable for Info {
95    fn as_log(&self) -> Vec<crate::fmt::LogItem> {
96        let (ver_maj, ver_min) = (self.version_maj, self.version_min);
97
98        let supported_cmds: Vec<_> = self
99            .supported_cmds
100            .iter()
101            .map(|cmd| match cmd {
102                Command::GetAllocInfo => "Get Alloc Info",
103                Command::Clear => "Clear",
104                Command::PartialAddEntry => "Partial Add",
105                Command::Reserve => "Reserve",
106            })
107            .collect();
108
109        log_vec![
110            (0, "SEL information"),
111            (1, "Version", format!("{}.{}", ver_maj, ver_min)),
112            (1, "Entries", self.entries),
113            (1, "Bytes free", self.bytes_free),
114            (1, "Last addition", self.last_add_time),
115            (1, "Last erase", self.last_del_time),
116            (1, "Overflowed", self.overflow),
117            (1, "Supported cmds", format!("{:?}", supported_cmds)),
118        ]
119    }
120}