ipmi_rs/storage/sel/
get_info.rs1use 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}