Skip to content
Merged
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
47 changes: 38 additions & 9 deletions ipmi-rs-core/src/storage/sdr/event_data.rs
Original file line number Diff line number Diff line change
@@ -1,14 +1,15 @@
//! Event Data Field Decoding
//!
//! Reference: IPMI 2.0 Specification, Section 29.7 "Event Data Field Formats"
//! Reference: IPMI 2.0 Specification, Section 29.7 "Event Data Field Formats",
//! particularly Table 29-6 "Event Request Message Event Data Field Contents"
//!
//! This module provides decoding for the 3-byte event data field in SEL entries.

use core::fmt;

use nonmax::NonMaxU8;

/// Event data byte 2 availability/format (from event_data\[0\] bits \[5:4\])
/// Event data byte 2 availability/format (from event_data\[0\] bits \[7:6\])
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EventData2Type {
/// Unspecified (00b)
Expand All @@ -21,7 +22,7 @@ pub enum EventData2Type {
SensorSpecific(NonMaxU8),
}

/// Event data byte 3 availability/format (from event_data\[0\] bits \[7:6\])
/// Event data byte 3 availability/format (from event_data\[0\] bits \[5:4\])
#[derive(Debug, Clone, Copy, PartialEq)]
pub enum EventData3Type {
/// Unspecified (00b)
Expand Down Expand Up @@ -98,7 +99,7 @@ impl fmt::Display for EventData3Type {

/// Decoded event data from a SEL entry.
///
/// Reference: IPMI 2.0 Specification, Section 29.7
/// Reference: IPMI 2.0 Specification, Section 29.7, Table 29-6
#[derive(Debug, Clone, PartialEq)]
pub struct EventData {
/// Event offset (bits \[3:0\] of byte 1)
Expand All @@ -113,8 +114,8 @@ impl EventData {
/// Parse event data from the 3-byte event data field.
pub fn parse(data: &[u8; 3]) -> Self {
let offset = data[0] & 0x0F;
let data2_type = EventData2Type::parse((data[0] >> 4) & 0x03, data[1]);
let data3_type = EventData3Type::parse((data[0] >> 6) & 0x03, data[2]);
let data2_type = EventData2Type::parse((data[0] >> 6) & 0x03, data[1]);
let data3_type = EventData3Type::parse((data[0] >> 4) & 0x03, data[2]);

Self {
offset,
Expand All @@ -139,9 +140,6 @@ impl fmt::Display for EventData {
}
}

/// Decode Power Supply sensor-specific event data.
///
/// Reference: IPMI 2.0 Specification, Table 42-3, Sensor Type 08h
#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -172,4 +170,35 @@ mod tests {
let data = EventData::parse(&[0x00, 0xFF, 0xFF]);
assert_eq!(data.to_string(), "");
}

#[test]
fn test_data2_sensor_specific_selector_uses_bits_7_6() {
// IPMI 2.0, Table 42-3: System Firmware Progress (sensor type 0Fh),
// offset 02h, extension 13h means "Starting operating system boot
// process". Per Table 29-6, C2h selects a sensor-specific extension
// in Event Data 2 (bits 7:6 = 11b) and leaves Event Data 3 unspecified
// (bits 5:4 = 00b).
let data = EventData::parse(&[0xC2, 0x13, 0xFF]);

assert_eq!(data.offset, 0x02);
assert_eq!(
data.data2_type,
EventData2Type::SensorSpecific(NonMaxU8::new(0x13).unwrap())
);
assert_eq!(data.data3_type, EventData3Type::Unspecified);
}

#[test]
fn test_data3_sensor_specific_selector_uses_bits_5_4() {
// Use unequal selector fields to ensure Event Data 3 is selected only
// by bits 5:4, independently of Event Data 2's bits 7:6.
let data = EventData::parse(&[0x32, 0xFF, 0x23]);

assert_eq!(data.offset, 0x02);
assert_eq!(data.data2_type, EventData2Type::Unspecified);
assert_eq!(
data.data3_type,
EventData3Type::SensorSpecific(NonMaxU8::new(0x23).unwrap())
);
}
}