sel: Add OEM SEL Record data structure
The code only supports SEL Event Records. Re-define the data structure
to use union to support different kinds of SEL records:
* SEL Event Records
* OEM SEL Record, type C0-DF
* OEM SEL Record, type E0-FF
Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: I7cf69c3e1d47664815c029308a52c62049c8e691
diff --git a/selutility.cpp b/selutility.cpp
index cd3b6a6..83a8bd2 100644
--- a/selutility.cpp
+++ b/selutility.cpp
@@ -58,8 +58,6 @@
elog<InternalFailure>();
}
- record.recordID = static_cast<uint16_t>(std::get<uint32_t>(iterId->second));
-
// Read Timestamp from the log entry.
static constexpr auto propTimeStamp = "Timestamp";
auto iterTimeStamp = entryData.find(propTimeStamp);
@@ -68,44 +66,56 @@
log<level::ERR>("Error in reading Timestamp of logging entry");
elog<InternalFailure>();
}
-
std::chrono::milliseconds chronoTimeStamp(
std::get<uint64_t>(iterTimeStamp->second));
- record.timeStamp = static_cast<uint32_t>(
- std::chrono::duration_cast<std::chrono::seconds>(chronoTimeStamp)
- .count());
- static constexpr auto systemEventRecord = 0x02;
- static constexpr auto generatorID = 0x2000;
- static constexpr auto eventMsgRevision = 0x04;
-
- record.recordType = systemEventRecord;
- record.generatorID = generatorID;
- record.eventMsgRevision = eventMsgRevision;
-
- record.sensorType = iter->second.sensorType;
- record.sensorNum = iter->second.sensorID;
- record.eventData1 = iter->second.eventOffset;
-
- // Read Resolved from the log entry.
- static constexpr auto propResolved = "Resolved";
- auto iterResolved = entryData.find(propResolved);
- if (iterResolved == entryData.end())
+ if (iter == invSensors.end())
{
- log<level::ERR>("Error in reading Resolved field of logging entry");
- elog<InternalFailure>();
- }
-
- static constexpr auto deassertEvent = 0x80;
-
- // Evaluate if the event is assertion or deassertion event
- if (std::get<bool>(iterResolved->second))
- {
- record.eventType = deassertEvent | iter->second.eventReadingType;
+ // It is expected to be a custom SEL entry
+ // TODO
}
else
{
- record.eventType = iter->second.eventReadingType;
+
+ record.event.eventRecord.recordID =
+ static_cast<uint16_t>(std::get<uint32_t>(iterId->second));
+ record.event.eventRecord.timeStamp = static_cast<uint32_t>(
+ std::chrono::duration_cast<std::chrono::seconds>(chronoTimeStamp)
+ .count());
+
+ static constexpr auto systemEventRecord = 0x02;
+ static constexpr auto generatorID = 0x2000;
+ static constexpr auto eventMsgRevision = 0x04;
+
+ record.event.eventRecord.recordType = systemEventRecord;
+ record.event.eventRecord.generatorID = generatorID;
+ record.event.eventRecord.eventMsgRevision = eventMsgRevision;
+
+ record.event.eventRecord.sensorType = iter->second.sensorType;
+ record.event.eventRecord.sensorNum = iter->second.sensorID;
+ record.event.eventRecord.eventData1 = iter->second.eventOffset;
+
+ // Read Resolved from the log entry.
+ static constexpr auto propResolved = "Resolved";
+ auto iterResolved = entryData.find(propResolved);
+ if (iterResolved == entryData.end())
+ {
+ log<level::ERR>("Error in reading Resolved field of logging entry");
+ elog<InternalFailure>();
+ }
+
+ static constexpr auto deassertEvent = 0x80;
+
+ // Evaluate if the event is assertion or deassertion event
+ if (std::get<bool>(iterResolved->second))
+ {
+ record.event.eventRecord.eventType =
+ deassertEvent | iter->second.eventReadingType;
+ }
+ else
+ {
+ record.event.eventRecord.eventType = iter->second.eventReadingType;
+ }
}
return record;
@@ -171,12 +181,6 @@
// If there are no callout associations link the log entry to system event
// sensor
auto iter = invSensors.find(SYSTEM_SENSOR);
- if (iter == invSensors.end())
- {
- log<level::ERR>("System event sensor not found");
- elog<InternalFailure>();
- }
-
return internal::prepareSELEntry(objPath, iter);
}
diff --git a/selutility.hpp b/selutility.hpp
index 49ec1b7..06fc453 100644
--- a/selutility.hpp
+++ b/selutility.hpp
@@ -60,13 +60,14 @@
uint8_t readLength; //!< Bytes to read.
} __attribute__((packed));
-/** @struct GetSELEntryResponse
+constexpr size_t SELRecordLength = 16;
+
+/** @struct SELEventRecord
*
- * IPMI payload for Get SEL Entry command response.
+ * IPMI SEL Event Record
*/
-struct GetSELEntryResponse
+struct SELEventRecord
{
- uint16_t nextRecordID; //!< Next RecordID.
uint16_t recordID; //!< Record ID.
uint8_t recordType; //!< Record Type.
uint32_t timeStamp; //!< Timestamp.
@@ -80,6 +81,56 @@
uint8_t eventData3; //!< Event Data 3.
} __attribute__((packed));
+static_assert(sizeof(SELEventRecord) == SELRecordLength);
+
+/** @struct SELOEMRecordTypeCD
+ *
+ * IPMI SEL OEM Record - Type C0h-DFh
+ */
+struct SELOEMRecordTypeCD
+{
+ uint16_t recordID; //!< Record ID.
+ uint8_t recordType; //!< Record Type.
+ uint32_t timeStamp; //!< Timestamp.
+ uint8_t manufacturerID[3]; //!< Manufacturer ID.
+ uint8_t oemDefined[6]; //!< OEM Defined data.
+} __attribute__((packed));
+
+static_assert(sizeof(SELOEMRecordTypeCD) == SELRecordLength);
+
+/** @struct SELOEMRecordTypeEF
+ *
+ * IPMI SEL OEM Record - Type E0h-FFh
+ */
+struct SELOEMRecordTypeEF
+{
+ uint16_t recordID; //!< Record ID.
+ uint8_t recordType; //!< Record Type.
+ uint8_t oemDefined[13]; //!< OEM Defined data.
+} __attribute__((packed));
+
+static_assert(sizeof(SELOEMRecordTypeEF) == SELRecordLength);
+
+union SELEventRecordFormat
+{
+ SELEventRecord eventRecord;
+ SELOEMRecordTypeCD oemCD;
+ SELOEMRecordTypeEF oemEF;
+};
+
+/** @struct GetSELEntryResponse
+ *
+ * IPMI payload for Get SEL Entry command response.
+ */
+struct GetSELEntryResponse
+{
+ uint16_t nextRecordID; //!< Next RecordID.
+ SELEventRecordFormat event; // !< The Event Record.
+} __attribute__((packed));
+
+static_assert(sizeof(GetSELEntryResponse) ==
+ SELRecordLength + sizeof(uint16_t));
+
static constexpr auto initiateErase = 0xAA;
static constexpr auto getEraseStatus = 0x00;
static constexpr auto eraseComplete = 0x01;
diff --git a/storagehandler.cpp b/storagehandler.cpp
index 74e5d65..3f09940 100644
--- a/storagehandler.cpp
+++ b/storagehandler.cpp
@@ -263,7 +263,8 @@
sizeof(record.nextRecordID));
std::memcpy(static_cast<uint8_t*>(response) +
sizeof(record.nextRecordID),
- &record.recordID + requestData->offset, readLength);
+ &record.event.eventRecord.recordID + requestData->offset,
+ readLength);
*data_len = sizeof(record.nextRecordID) + readLength;
}