sel: Support OEM record 0xE0~0xFF

The OEM record 0xE0~0xFF only includes record type and 13 bytes OEM
data.

Tested: Add 0xFF OEM SEL and verify the sel list shows the expected
        record.

Signed-off-by: Lei YU <yulei.sh@bytedance.com>
Change-Id: Ied3d68cf4393d37f8841ac66c6ca10c66393b7da
diff --git a/selutility.cpp b/selutility.cpp
index 528cffd..d83aa16 100644
--- a/selutility.cpp
+++ b/selutility.cpp
@@ -22,6 +22,13 @@
 
 constexpr auto systemEventRecord = 0x02;
 
+constexpr auto propAdditionalData = "AdditionalData";
+constexpr auto strEventDir = "EVENT_DIR";
+constexpr auto strGenerateId = "GENERATOR_ID";
+constexpr auto strRecordType = "RECORD_TYPE";
+constexpr auto strSensorData = "SENSOR_DATA";
+constexpr auto strSensorPath = "SENSOR_PATH";
+
 } // namespace
 
 namespace ipmi
@@ -38,6 +45,7 @@
     return recordType != systemEventRecord;
 }
 
+using additionalDataMap = std::map<std::string, std::string>;
 /** Parse the entry with format like key=val */
 std::pair<std::string, std::string> parseEntry(const std::string& entry)
 {
@@ -49,8 +57,7 @@
     return {key, val};
 }
 
-std::map<std::string, std::string>
-    parseAdditionalData(const AdditionalData& data)
+additionalDataMap parseAdditionalData(const AdditionalData& data)
 {
     std::map<std::string, std::string> ret;
 
@@ -81,6 +88,33 @@
     return ret;
 }
 
+/** Construct OEM SEL record according to IPMI spec 32.2, 32.3. */
+void constructOEMSel(uint8_t recordType, std::chrono::milliseconds timestamp,
+                     const additionalDataMap& m, GetSELEntryResponse& record)
+{
+    auto dataIter = m.find(strSensorData);
+    assert(dataIter != m.end());
+    auto sensorData = convertVec(dataIter->second);
+    if (recordType >= 0xC0 && recordType < 0xE0)
+    {
+        record.event.oemCD.timeStamp = static_cast<uint32_t>(
+            std::chrono::duration_cast<std::chrono::seconds>(timestamp)
+                .count());
+        record.event.oemCD.recordType = recordType;
+        // The ManufactureID and OEM Defined are packed in the sensor data
+        // Fill the 9 bytes of Manufacture ID and oemDefined
+        memcpy(&record.event.oemCD.manufacturerID, sensorData.data(),
+               std::min(sensorData.size(), static_cast<size_t>(9)));
+    }
+    else if (recordType >= 0xE0)
+    {
+        record.event.oemEF.recordType = recordType;
+        // The remaining 13 bytes are the OEM Defined data
+        memcpy(&record.event.oemEF.oemDefined, sensorData.data(),
+               std::min(sensorData.size(), static_cast<size_t>(13)));
+    }
+}
+
 GetSELEntryResponse
     prepareSELEntry(const std::string& objPath,
                     ipmi::sensor::InvObjectIDMap::const_iterator iter)
@@ -130,12 +164,6 @@
         // It is expected to be a custom SEL entry
         record.event.oemCD.recordID =
             static_cast<uint16_t>(std::get<uint32_t>(iterId->second));
-        static constexpr auto propAdditionalData = "AdditionalData";
-        // static constexpr auto strEventDir = "EVENT_DIR";
-        // static constexpr auto strGenerateId = "GENERATOR_ID";
-        static constexpr auto strRecordType = "RECORD_TYPE";
-        static constexpr auto strSensorData = "SENSOR_DATA";
-        // static constexpr auto strSensorPath = "SENSOR_PATH";
         iterId = entryData.find(propAdditionalData);
         if (iterId == entryData.end())
         {
@@ -148,24 +176,7 @@
         auto isOEM = isRecordOEM(recordType);
         if (isOEM)
         {
-            if (recordType >= 0xC0 && recordType < 0xE0)
-            {
-                record.event.oemCD.timeStamp = static_cast<uint32_t>(
-                    std::chrono::duration_cast<std::chrono::seconds>(
-                        chronoTimeStamp)
-                        .count());
-                record.event.oemCD.recordType = recordType;
-                // The ManufactureID and OEM Defined are packed in the sensor
-                // data
-                auto sensorData = convertVec(m[strSensorData]);
-                // Fill the 9 bytes of Manufacture ID and oemDefined
-                memcpy(&record.event.oemCD.manufacturerID, sensorData.data(),
-                       std::min(sensorData.size(), static_cast<size_t>(9)));
-            }
-            else if (recordType >= 0xE0)
-            {
-                // TODO
-            }
+            constructOEMSel(recordType, chronoTimeStamp, m, record);
         }
         else
         {