ipmi_rs_core/app/
get_device_id.rs

1use crate::connection::{IpmiCommand, Message, NetFn, NotEnoughData};
2
3/// The Get Device ID command.
4pub struct GetDeviceId;
5
6impl From<GetDeviceId> for Message {
7    fn from(_: GetDeviceId) -> Self {
8        Message::new_request(NetFn::App, 0x01, Vec::new())
9    }
10}
11
12impl IpmiCommand for GetDeviceId {
13    type Output = DeviceId;
14
15    type Error = NotEnoughData;
16
17    fn parse_success_response(data: &[u8]) -> Result<Self::Output, Self::Error> {
18        DeviceId::from_data(data).ok_or(NotEnoughData)
19    }
20}
21
22/// All of the fields that are returned when retrieving a
23/// device's ID.
24#[derive(Clone, Debug, PartialEq)]
25pub struct DeviceId {
26    /// The raw ID of the device.
27    pub device_id: u8,
28    /// The revision of the device.
29    pub device_revision: u8,
30    /// `true` if the device provides device SDRs.
31    pub provides_device_sdrs: bool,
32    /// `true` if the device is availalbe, `false` if the device
33    /// is in device firmware, SDR repository update, or self-initialization state.
34    pub device_available: bool,
35    /// The major version of the firmware revision of the device.
36    pub major_fw_revision: u8,
37    /// The minor version of the firmware of the device.
38    pub minor_fw_revision: u8,
39    /// The major version of the IPMI version supported by the device.
40    pub major_version: u8,
41    /// The minor version of the IPMI version supported by the device.
42    pub minor_version: u8,
43    /// `true` if the device is a chassis device per the ICBM specification.
44    pub chassis_support: bool,
45    /// `true` if the device will response to bridge NetFN commands.
46    pub bridge_support: bool,
47    /// Whether the device will generate event messages onto the IPMB.
48    pub ipmb_event_generator_support: bool,
49    /// Whether the device will generate event messages onto the IPMB.
50    pub ipmb_event_receiver_support: bool,
51    /// Whether if the device supports FRU inventory.
52    pub fru_inventory_support: bool,
53    /// Whether the device supports the SEL.
54    pub sel_device_support: bool,
55    /// Whether the device is an SDR repository device.
56    pub sdr_repository_support: bool,
57    /// Whether the device is a sensor device.
58    pub sensor_device_support: bool,
59    /// The ID of the manufacturer.
60    pub manufacturer_id: u32,
61    /// The ID of the product.
62    pub product_id: u16,
63    /// Optional auxiliary firmware revision information.
64    pub aux_revision: Option<[u8; 4]>,
65}
66
67impl DeviceId {
68    /// Parse a `DeviceID` from IPMI response data.
69    pub fn from_data(data: &[u8]) -> Option<Self> {
70        if data.len() < 11 {
71            return None;
72        }
73
74        let aux_revision = if data.len() < 15 {
75            None
76        } else {
77            Some([data[11], data[12], data[13], data[14]])
78        };
79
80        let fw_min = {
81            let min_nib_low = data[3] & 0xF;
82            let min_nib_high = (data[3] >> 4) & 0xF;
83
84            min_nib_low + min_nib_high * 10
85        };
86
87        let me = Self {
88            device_id: data[0],
89            device_revision: data[1] & 0xF,
90            provides_device_sdrs: (data[1] & 0x80) == 0x80,
91            device_available: (data[2] & 0x80) != 0x80,
92            major_fw_revision: (data[2] & 0x7F),
93            minor_fw_revision: fw_min,
94            major_version: data[4] & 0xF,
95            minor_version: (data[4] >> 4) & 0xF,
96            chassis_support: (data[5] & 0x80) == 0x80,
97            bridge_support: (data[5] & 0x40) == 0x40,
98            ipmb_event_generator_support: (data[5] & 0x20) == 0x20,
99            ipmb_event_receiver_support: (data[5] & 0x10) == 0x10,
100            fru_inventory_support: (data[5] & 0x08) == 0x08,
101            sel_device_support: (data[5] & 0x04) == 0x04,
102            sdr_repository_support: (data[5] & 0x02) == 0x02,
103            sensor_device_support: (data[5] & 0x01) == 0x01,
104            manufacturer_id: u32::from_le_bytes([data[6], data[7], data[8], 0]),
105            product_id: u16::from_le_bytes([data[9], data[10]]),
106            aux_revision,
107        };
108
109        Some(me)
110    }
111}