rust_ipmi/parser/ipmi/payload/
ipmi_payload.rs

1use core::fmt;
2
3use bitvec::{field::BitField, order::Msb0, slice::BitSlice};
4
5use crate::err::{IpmiPayloadError, LunError};
6
7use super::ipmi_payload_request::IpmiPayloadRequest;
8use super::ipmi_payload_response::IpmiPayloadResponse;
9
10#[derive(Clone)]
11pub enum IpmiPayload {
12    Request(IpmiPayloadRequest),
13    Response(IpmiPayloadResponse),
14}
15
16impl TryFrom<&[u8]> for IpmiPayload {
17    type Error = IpmiPayloadError;
18
19    fn try_from(value: &[u8]) -> Result<Self, Self::Error> {
20        if value.len() < 7 {
21            Err(IpmiPayloadError::WrongLength)?
22        }
23        let netfn_rqlun: &BitSlice<u8, Msb0> = BitSlice::<u8, Msb0>::from_element(&value[1]);
24        let netfn = netfn_rqlun[0..6].load::<u8>();
25        let command_type: CommandType = netfn.into();
26
27        match command_type {
28            CommandType::Request => Ok(IpmiPayload::Request(value.try_into()?)),
29            CommandType::Response => Ok(IpmiPayload::Response(value.try_into()?)),
30        }
31    }
32}
33
34impl Into<Vec<u8>> for IpmiPayload {
35    fn into(self) -> Vec<u8> {
36        match self {
37            IpmiPayload::Request(payload) => payload.into(),
38            _ => todo!(), // IpmiPayload::Response(header) => header.to_bytes(),
39        }
40    }
41}
42
43#[derive(Clone, Copy, Debug)]
44pub enum NetFn {
45    Chassis,
46    Bridge,
47    SensorEvent,
48    App,
49    Firmware,
50    Storage,
51    Transport,
52    Reserved,
53    Unknown(u8),
54}
55
56impl fmt::Display for NetFn {
57    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
58        match self {
59            NetFn::Chassis => write!(f, "Chassis"),
60            NetFn::Bridge => write!(f, "Bridge"),
61            NetFn::SensorEvent => write!(f, "Sensor Event"),
62            NetFn::App => write!(f, "App"),
63            NetFn::Firmware => write!(f, "Firmware"),
64            NetFn::Storage => write!(f, "Storage"),
65            NetFn::Transport => write!(f, "Transport"),
66            NetFn::Reserved => write!(f, "Reserved"),
67            NetFn::Unknown(x) => write!(f, "Unknown: {}", x),
68        }
69    }
70}
71
72// impl TryFrom<u8> for NetFn {
73//     type Error = NetFnError;
74//     fn try_from(value: u8) -> Result<Self, NetFnError> {
75//         match value {
76//             0x00..=0x01 => Ok(NetFn::Chassis),
77//             0x02..=0x03 => Ok(NetFn::Bridge),
78//             0x04..=0x05 => Ok(NetFn::SensorEvent),
79//             0x06..=0x07 => Ok(NetFn::App),
80//             0x08..=0x09 => Ok(NetFn::Firmware),
81//             0x0A..=0x0B => Ok(NetFn::Storage),
82//             0x0C..=0x0D => Ok(NetFn::Transport),
83//             0x0E..=0x2B => Ok(NetFn::Reserved),
84//             _ => Ok(NetFn::Unknown(value)), // _ => Err(NetFnError::UnknownNetFn(value)),
85//         }
86//     }
87// }
88
89impl From<u8> for NetFn {
90    fn from(value: u8) -> Self {
91        match value {
92            0x00..=0x01 => NetFn::Chassis,
93            0x02..=0x03 => NetFn::Bridge,
94            0x04..=0x05 => NetFn::SensorEvent,
95            0x06..=0x07 => NetFn::App,
96            0x08..=0x09 => NetFn::Firmware,
97            0x0A..=0x0B => NetFn::Storage,
98            0x0C..=0x0D => NetFn::Transport,
99            0x0E..=0x2B => NetFn::Reserved,
100            _ => NetFn::Unknown(value), // _ => Err(NetFnError::UnknownNetFn(value)),
101        }
102    }
103}
104
105impl NetFn {
106    pub fn to_u8(&self, command_type: CommandType) -> u8 {
107        match self {
108            NetFn::Chassis => match command_type {
109                CommandType::Request => 0x00,
110                CommandType::Response => 0x01,
111            },
112            NetFn::Bridge => match command_type {
113                CommandType::Request => 0x02,
114                CommandType::Response => 0x03,
115            },
116            NetFn::SensorEvent => match command_type {
117                CommandType::Request => 0x04,
118                CommandType::Response => 0x05,
119            },
120            NetFn::App => match command_type {
121                CommandType::Request => 0x06,
122                CommandType::Response => 0x07,
123            },
124            NetFn::Firmware => match command_type {
125                CommandType::Request => 0x08,
126                CommandType::Response => 0x09,
127            },
128            NetFn::Storage => match command_type {
129                CommandType::Request => 0x0A,
130                CommandType::Response => 0x0B,
131            },
132            NetFn::Transport => match command_type {
133                CommandType::Request => 0x0C,
134                CommandType::Response => 0x0D,
135            },
136            NetFn::Reserved => match command_type {
137                CommandType::Request => 0x0E,
138                CommandType::Response => 0x2B,
139            },
140            NetFn::Unknown(fn_code) => match command_type {
141                CommandType::Request => *fn_code,
142                CommandType::Response => *fn_code,
143            },
144        }
145    }
146}
147
148pub enum CommandType {
149    Request,
150    Response,
151}
152
153impl From<u8> for CommandType {
154    fn from(value: u8) -> Self {
155        if value % 2 == 0 {
156            CommandType::Request
157        } else {
158            CommandType::Response
159        }
160    }
161}
162
163#[derive(Clone, Debug)]
164pub enum Lun {
165    Bmc,
166    Oem1,
167    Sms,
168    Oem2,
169}
170
171impl fmt::Display for Lun {
172    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
173        match self {
174            Lun::Bmc => write!(f, "BMC"),
175            Lun::Oem1 => write!(f, "OEM1"),
176            Lun::Sms => write!(f, "SMS"),
177            Lun::Oem2 => write!(f, "OEM2"),
178        }
179    }
180}
181
182impl TryFrom<u8> for Lun {
183    type Error = LunError;
184
185    fn try_from(value: u8) -> Result<Self, Self::Error> {
186        match value {
187            0b00 => Ok(Lun::Bmc),
188            0b01 => Ok(Lun::Oem1),
189            0b10 => Ok(Lun::Sms),
190            0b11 => Ok(Lun::Oem2),
191            _ => Err(LunError::UnknownLun(value)),
192        }
193    }
194}
195
196impl Into<u8> for Lun {
197    fn into(self) -> u8 {
198        match self {
199            Lun::Bmc => 0b00,
200            Lun::Oem1 => 0b01,
201            Lun::Sms => 0b10,
202            Lun::Oem2 => 0b11,
203        }
204    }
205}
206
207pub enum AddrType {
208    SlaveAddress,
209    SoftwareId,
210}
211
212impl From<bool> for AddrType {
213    fn from(value: bool) -> Self {
214        match value {
215            false => AddrType::SlaveAddress,
216            true => AddrType::SoftwareId,
217        }
218    }
219}
220
221impl Into<u8> for AddrType {
222    fn into(self) -> u8 {
223        match self {
224            AddrType::SlaveAddress => 0,
225            AddrType::SoftwareId => 2,
226        }
227    }
228}
229
230#[derive(Clone, Debug)]
231pub enum SoftwareType {
232    Bios,
233    SmiHandler,
234    SystemManagementSoftware,
235    Oem,
236    RemoteConsoleSoftware(u8),
237    TerminalModeRemoteConsole,
238    Reserved(u8),
239}
240
241impl fmt::Display for SoftwareType {
242    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
243        match self {
244            SoftwareType::Bios => write!(f, "BIOS"),
245            SoftwareType::SmiHandler => write!(f, "SMI Handler"),
246            SoftwareType::SystemManagementSoftware => write!(f, "System Management Software"),
247            SoftwareType::Oem => write!(f, "OEM"),
248            SoftwareType::RemoteConsoleSoftware(x) => write!(f, "Remote Console Software: {}", x),
249            SoftwareType::TerminalModeRemoteConsole => write!(f, "Terminal Mode Remote Console"),
250            SoftwareType::Reserved(x) => write!(f, "Reserved: {}", x),
251        }
252    }
253}
254
255impl From<u8> for SoftwareType {
256    fn from(value: u8) -> Self {
257        match value {
258            0x00..=0x0F => SoftwareType::Bios,
259            0x10..=0x1F => SoftwareType::SmiHandler,
260            0x20..=0x2F => SoftwareType::SystemManagementSoftware,
261            0x30..=0x3F => SoftwareType::Oem,
262            0x40..=0x46 => SoftwareType::RemoteConsoleSoftware(value - 0x3F),
263            0x47 => SoftwareType::TerminalModeRemoteConsole,
264            _ => SoftwareType::Reserved(value),
265        }
266    }
267}
268
269impl Into<u8> for SoftwareType {
270    fn into(self) -> u8 {
271        match self {
272            SoftwareType::Bios => 0x00,
273            SoftwareType::SmiHandler => 0x10,
274            SoftwareType::SystemManagementSoftware => 0x20,
275            SoftwareType::Oem => 0x30,
276            SoftwareType::RemoteConsoleSoftware(a) => a,
277            SoftwareType::TerminalModeRemoteConsole => 0x47,
278            SoftwareType::Reserved(a) => a,
279        }
280    }
281}
282
283#[derive(Clone, Debug)]
284pub enum SlaveAddress {
285    Bmc,
286    Unknown(u8),
287}
288
289impl fmt::Display for SlaveAddress {
290    fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
291        match self {
292            SlaveAddress::Bmc => write!(f, "BMC"),
293            SlaveAddress::Unknown(x) => write!(f, "Unknown: {}", x),
294        }
295    }
296}
297
298impl From<u8> for SlaveAddress {
299    fn from(value: u8) -> Self {
300        match value {
301            0x20 => SlaveAddress::Bmc,
302            _ => SlaveAddress::Unknown(value),
303        }
304    }
305}
306
307impl Into<u8> for SlaveAddress {
308    fn into(self) -> u8 {
309        match self {
310            SlaveAddress::Bmc => 0x20,
311            SlaveAddress::Unknown(a) => a,
312        }
313    }
314}