rust_ipmi/parser/ipmi/payload/
ipmi_payload.rs1use 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!(), }
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
72impl 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), }
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}