1*a743e384SChau Ly #include "oem_event_manager.hpp"
2*a743e384SChau Ly 
3*a743e384SChau Ly #include "requester/handler.hpp"
4*a743e384SChau Ly #include "requester/request.hpp"
5*a743e384SChau Ly 
6*a743e384SChau Ly #include <config.h>
7*a743e384SChau Ly #include <libpldm/pldm.h>
8*a743e384SChau Ly #include <libpldm/utils.h>
9*a743e384SChau Ly #include <systemd/sd-journal.h>
10*a743e384SChau Ly 
11*a743e384SChau Ly #include <phosphor-logging/lg2.hpp>
12*a743e384SChau Ly #include <xyz/openbmc_project/Logging/Entry/server.hpp>
13*a743e384SChau Ly 
14*a743e384SChau Ly #include <algorithm>
15*a743e384SChau Ly #include <map>
16*a743e384SChau Ly #include <sstream>
17*a743e384SChau Ly #include <string>
18*a743e384SChau Ly #include <unordered_map>
19*a743e384SChau Ly 
20*a743e384SChau Ly namespace pldm
21*a743e384SChau Ly {
22*a743e384SChau Ly namespace oem_ampere
23*a743e384SChau Ly {
24*a743e384SChau Ly namespace boot_stage = boot::stage;
25*a743e384SChau Ly 
26*a743e384SChau Ly constexpr const char* BIOSFWPanicRegistry =
27*a743e384SChau Ly     "OpenBMC.0.1.BIOSFirmwarePanicReason.Warning";
28*a743e384SChau Ly constexpr auto maxDIMMIdxBitNum = 24;
29*a743e384SChau Ly 
30*a743e384SChau Ly /*
31*a743e384SChau Ly     An array of possible boot status of a boot stage.
32*a743e384SChau Ly     The index maps with byte 0 of boot code.
33*a743e384SChau Ly */
34*a743e384SChau Ly std::array<std::string, 3> bootStatMsg = {" booting", " completed", " failed"};
35*a743e384SChau Ly 
36*a743e384SChau Ly /*
37*a743e384SChau Ly     An array of possible boot status of DDR training stage.
38*a743e384SChau Ly     The index maps with byte 0 of boot code.
39*a743e384SChau Ly */
40*a743e384SChau Ly std::array<std::string, 3> ddrTrainingMsg = {
41*a743e384SChau Ly     " progress started", " in-progress", " progress completed"};
42*a743e384SChau Ly 
43*a743e384SChau Ly /*
44*a743e384SChau Ly     In Ampere systems, BMC only directly communicates with MCTP/PLDM SoC
45*a743e384SChau Ly     EPs through SMBus and PCIe. When host boots up, SMBUS interface
46*a743e384SChau Ly     comes up first. In this interface, BMC is bus owner.
47*a743e384SChau Ly 
48*a743e384SChau Ly     mctpd will set the EID 0x14 for S0 and 0x16 for S1 (if available).
49*a743e384SChau Ly     pldmd will always use TID 1 for S0 and TID 2 for S1 (if available).
50*a743e384SChau Ly */
51*a743e384SChau Ly EventToMsgMap_t tidToSocketNameMap = {{1, "SOCKET 0"}, {2, "SOCKET 1"}};
52*a743e384SChau Ly 
53*a743e384SChau Ly /*
54*a743e384SChau Ly     A map between sensor IDs and their names in string.
55*a743e384SChau Ly     Using pldm::oem::sensor_ids
56*a743e384SChau Ly */
57*a743e384SChau Ly EventToMsgMap_t sensorIdToStrMap = {{BOOT_OVERALL, "BOOT_OVERALL"}};
58*a743e384SChau Ly 
59*a743e384SChau Ly /*
60*a743e384SChau Ly     A map between the boot stages and logging strings.
61*a743e384SChau Ly     Using pldm::oem::boot::stage::boot_stage
62*a743e384SChau Ly */
63*a743e384SChau Ly EventToMsgMap_t bootStageToMsgMap = {
64*a743e384SChau Ly     {boot_stage::SECPRO, "SECpro"},
65*a743e384SChau Ly     {boot_stage::MPRO, "Mpro"},
66*a743e384SChau Ly     {boot_stage::ATF_BL1, "ATF BL1"},
67*a743e384SChau Ly     {boot_stage::ATF_BL2, "ATF BL2"},
68*a743e384SChau Ly     {boot_stage::DDR_INITIALIZATION, "DDR initialization"},
69*a743e384SChau Ly     {boot_stage::DDR_TRAINING, "DDR training"},
70*a743e384SChau Ly     {boot_stage::S0_DDR_TRAINING_FAILURE, "DDR training failure"},
71*a743e384SChau Ly     {boot_stage::ATF_BL31, "ATF BL31"},
72*a743e384SChau Ly     {boot_stage::ATF_BL32, "ATF BL32"},
73*a743e384SChau Ly     {boot_stage::S1_DDR_TRAINING_FAILURE, "DDR training failure"},
74*a743e384SChau Ly     {boot_stage::UEFI_STATUS_CLASS_CODE_MIN,
75*a743e384SChau Ly      "ATF BL33 (UEFI) booting status = "}};
76*a743e384SChau Ly 
77*a743e384SChau Ly /*
78*a743e384SChau Ly     A map between log level and the registry used for Redfish SEL log
79*a743e384SChau Ly     Using pldm::oem::log_level
80*a743e384SChau Ly */
81*a743e384SChau Ly std::unordered_map<log_level, std::string> logLevelToRedfishMsgIdMap = {
82*a743e384SChau Ly     {log_level::BIOSFWPANIC, BIOSFWPanicRegistry}};
83*a743e384SChau Ly 
84*a743e384SChau Ly std::string
prefixMsgStrCreation(pldm_tid_t tid,uint16_t sensorId)85*a743e384SChau Ly     OemEventManager::prefixMsgStrCreation(pldm_tid_t tid, uint16_t sensorId)
86*a743e384SChau Ly {
87*a743e384SChau Ly     std::string description;
88*a743e384SChau Ly     if (!tidToSocketNameMap.contains(tid))
89*a743e384SChau Ly     {
90*a743e384SChau Ly         description += "TID " + std::to_string(tid) + ": ";
91*a743e384SChau Ly     }
92*a743e384SChau Ly     else
93*a743e384SChau Ly     {
94*a743e384SChau Ly         description += tidToSocketNameMap[tid] + ": ";
95*a743e384SChau Ly     }
96*a743e384SChau Ly 
97*a743e384SChau Ly     if (!sensorIdToStrMap.contains(sensorId))
98*a743e384SChau Ly     {
99*a743e384SChau Ly         description += "Sensor ID " + std::to_string(sensorId) + ": ";
100*a743e384SChau Ly     }
101*a743e384SChau Ly     else
102*a743e384SChau Ly     {
103*a743e384SChau Ly         description += sensorIdToStrMap[sensorId] + ": ";
104*a743e384SChau Ly     }
105*a743e384SChau Ly 
106*a743e384SChau Ly     return description;
107*a743e384SChau Ly }
108*a743e384SChau Ly 
sendJournalRedfish(const std::string & description,log_level & logLevel)109*a743e384SChau Ly void OemEventManager::sendJournalRedfish(const std::string& description,
110*a743e384SChau Ly                                          log_level& logLevel)
111*a743e384SChau Ly {
112*a743e384SChau Ly     if (description.empty())
113*a743e384SChau Ly     {
114*a743e384SChau Ly         return;
115*a743e384SChau Ly     }
116*a743e384SChau Ly 
117*a743e384SChau Ly     if (!logLevelToRedfishMsgIdMap.contains(logLevel))
118*a743e384SChau Ly     {
119*a743e384SChau Ly         lg2::error("Invalid {LEVEL} Description {DES}", "LEVEL", logLevel,
120*a743e384SChau Ly                    "DES", description);
121*a743e384SChau Ly         return;
122*a743e384SChau Ly     }
123*a743e384SChau Ly     auto redfishMsgId = logLevelToRedfishMsgIdMap[logLevel];
124*a743e384SChau Ly     lg2::info("MESSAGE={DES}", "DES", description, "REDFISH_MESSAGE_ID",
125*a743e384SChau Ly               redfishMsgId, "REDFISH_MESSAGE_ARGS", description);
126*a743e384SChau Ly }
127*a743e384SChau Ly 
dimmIdxsToString(uint32_t dimmIdxs)128*a743e384SChau Ly std::string OemEventManager::dimmIdxsToString(uint32_t dimmIdxs)
129*a743e384SChau Ly {
130*a743e384SChau Ly     std::string description;
131*a743e384SChau Ly     for (const auto bitIdx : std::views::iota(0, maxDIMMIdxBitNum))
132*a743e384SChau Ly     {
133*a743e384SChau Ly         if (dimmIdxs & (static_cast<uint32_t>(1) << bitIdx))
134*a743e384SChau Ly         {
135*a743e384SChau Ly             description += " #" + std::to_string(bitIdx);
136*a743e384SChau Ly         }
137*a743e384SChau Ly     }
138*a743e384SChau Ly     return description;
139*a743e384SChau Ly }
140*a743e384SChau Ly 
handleBootOverallEvent(pldm_tid_t,uint16_t,uint32_t presentReading)141*a743e384SChau Ly void OemEventManager::handleBootOverallEvent(
142*a743e384SChau Ly     pldm_tid_t /*tid*/, uint16_t /*sensorId*/, uint32_t presentReading)
143*a743e384SChau Ly {
144*a743e384SChau Ly     log_level logLevel{log_level::OK};
145*a743e384SChau Ly     std::string description;
146*a743e384SChau Ly     std::stringstream strStream;
147*a743e384SChau Ly 
148*a743e384SChau Ly     uint8_t byte0 = (presentReading & 0x000000ff);
149*a743e384SChau Ly     uint8_t byte1 = (presentReading & 0x0000ff00) >> 8;
150*a743e384SChau Ly     uint8_t byte2 = (presentReading & 0x00ff0000) >> 16;
151*a743e384SChau Ly     uint8_t byte3 = (presentReading & 0xff000000) >> 24;
152*a743e384SChau Ly     /*
153*a743e384SChau Ly      * Handle SECpro, Mpro, ATF BL1, ATF BL2, ATF BL31,
154*a743e384SChau Ly      * ATF BL32 and DDR initialization
155*a743e384SChau Ly      */
156*a743e384SChau Ly     if (bootStageToMsgMap.contains(byte3))
157*a743e384SChau Ly     {
158*a743e384SChau Ly         // Boot stage adding
159*a743e384SChau Ly         description += bootStageToMsgMap[byte3];
160*a743e384SChau Ly 
161*a743e384SChau Ly         switch (byte3)
162*a743e384SChau Ly         {
163*a743e384SChau Ly             case boot_stage::DDR_TRAINING:
164*a743e384SChau Ly                 if (byte0 >= ddrTrainingMsg.size())
165*a743e384SChau Ly                 {
166*a743e384SChau Ly                     logLevel = log_level::BIOSFWPANIC;
167*a743e384SChau Ly                     description += " unknown status";
168*a743e384SChau Ly                 }
169*a743e384SChau Ly                 else
170*a743e384SChau Ly                 {
171*a743e384SChau Ly                     description += ddrTrainingMsg[byte0];
172*a743e384SChau Ly                 }
173*a743e384SChau Ly                 if (0x01 == byte0)
174*a743e384SChau Ly                 {
175*a743e384SChau Ly                     // Add complete percentage
176*a743e384SChau Ly                     description += " at " + std::to_string(byte1) + "%";
177*a743e384SChau Ly                 }
178*a743e384SChau Ly                 break;
179*a743e384SChau Ly             case boot_stage::S0_DDR_TRAINING_FAILURE:
180*a743e384SChau Ly             case boot_stage::S1_DDR_TRAINING_FAILURE:
181*a743e384SChau Ly                 // ddr_training_status_msg()
182*a743e384SChau Ly                 logLevel = log_level::BIOSFWPANIC;
183*a743e384SChau Ly                 description += " at DIMMs:";
184*a743e384SChau Ly                 // dimmIdxs = presentReading & 0x00ffffff;
185*a743e384SChau Ly                 description += dimmIdxsToString(presentReading & 0x00ffffff);
186*a743e384SChau Ly                 description += " of socket ";
187*a743e384SChau Ly                 description +=
188*a743e384SChau Ly                     (boot_stage::S0_DDR_TRAINING_FAILURE == byte3) ? "0" : "1";
189*a743e384SChau Ly                 break;
190*a743e384SChau Ly             default:
191*a743e384SChau Ly                 if (byte0 >= bootStatMsg.size())
192*a743e384SChau Ly                 {
193*a743e384SChau Ly                     logLevel = log_level::BIOSFWPANIC;
194*a743e384SChau Ly                     description += " unknown status";
195*a743e384SChau Ly                 }
196*a743e384SChau Ly                 else
197*a743e384SChau Ly                 {
198*a743e384SChau Ly                     description += bootStatMsg[byte0];
199*a743e384SChau Ly                 }
200*a743e384SChau Ly                 break;
201*a743e384SChau Ly         }
202*a743e384SChau Ly 
203*a743e384SChau Ly         // Sensor report action is fail
204*a743e384SChau Ly         if (boot::status::BOOT_STATUS_FAILURE == byte2)
205*a743e384SChau Ly         {
206*a743e384SChau Ly             logLevel = log_level::BIOSFWPANIC;
207*a743e384SChau Ly         }
208*a743e384SChau Ly     }
209*a743e384SChau Ly     else
210*a743e384SChau Ly     {
211*a743e384SChau Ly         if (byte3 <= boot_stage::UEFI_STATUS_CLASS_CODE_MAX)
212*a743e384SChau Ly         {
213*a743e384SChau Ly             description +=
214*a743e384SChau Ly                 bootStageToMsgMap[boot_stage::UEFI_STATUS_CLASS_CODE_MIN];
215*a743e384SChau Ly 
216*a743e384SChau Ly             strStream
217*a743e384SChau Ly                 << "Segment (0x" << std::setfill('0') << std::hex
218*a743e384SChau Ly                 << std::setw(8) << static_cast<uint32_t>(presentReading)
219*a743e384SChau Ly                 << "), Status Class (0x" << std::setw(2)
220*a743e384SChau Ly                 << static_cast<uint32_t>(byte3) << "), Status SubClass (0x"
221*a743e384SChau Ly                 << std::setw(2) << static_cast<uint32_t>(byte2)
222*a743e384SChau Ly                 << "), Operation Code (0x" << std::setw(4)
223*a743e384SChau Ly                 << static_cast<uint32_t>((presentReading & 0xffff0000) >> 16)
224*a743e384SChau Ly                 << ")" << std::dec;
225*a743e384SChau Ly 
226*a743e384SChau Ly             description += strStream.str();
227*a743e384SChau Ly         }
228*a743e384SChau Ly     }
229*a743e384SChau Ly 
230*a743e384SChau Ly     // Log to Redfish event
231*a743e384SChau Ly     sendJournalRedfish(description, logLevel);
232*a743e384SChau Ly }
233*a743e384SChau Ly 
processNumericSensorEvent(pldm_tid_t tid,uint16_t sensorId,const uint8_t * sensorData,size_t sensorDataLength)234*a743e384SChau Ly int OemEventManager::processNumericSensorEvent(
235*a743e384SChau Ly     pldm_tid_t tid, uint16_t sensorId, const uint8_t* sensorData,
236*a743e384SChau Ly     size_t sensorDataLength)
237*a743e384SChau Ly {
238*a743e384SChau Ly     uint8_t eventState = 0;
239*a743e384SChau Ly     uint8_t previousEventState = 0;
240*a743e384SChau Ly     uint8_t sensorDataSize = 0;
241*a743e384SChau Ly     uint32_t presentReading;
242*a743e384SChau Ly     auto rc = decode_numeric_sensor_data(
243*a743e384SChau Ly         sensorData, sensorDataLength, &eventState, &previousEventState,
244*a743e384SChau Ly         &sensorDataSize, &presentReading);
245*a743e384SChau Ly     if (rc)
246*a743e384SChau Ly     {
247*a743e384SChau Ly         lg2::error(
248*a743e384SChau Ly             "Failed to decode numericSensorState event for terminus ID {TID}, error {RC} ",
249*a743e384SChau Ly             "TID", tid, "RC", rc);
250*a743e384SChau Ly         return rc;
251*a743e384SChau Ly     }
252*a743e384SChau Ly 
253*a743e384SChau Ly     switch (sensorId)
254*a743e384SChau Ly     {
255*a743e384SChau Ly         case BOOT_OVERALL:
256*a743e384SChau Ly             handleBootOverallEvent(tid, sensorId, presentReading);
257*a743e384SChau Ly             break;
258*a743e384SChau Ly         default:
259*a743e384SChau Ly             std::string description;
260*a743e384SChau Ly             std::stringstream strStream;
261*a743e384SChau Ly             log_level logLevel = log_level::OK;
262*a743e384SChau Ly 
263*a743e384SChau Ly             description += "SENSOR_EVENT : NUMERIC_SENSOR_STATE: ";
264*a743e384SChau Ly             description += prefixMsgStrCreation(tid, sensorId);
265*a743e384SChau Ly             strStream << std::setfill('0') << std::hex << "eventState 0x"
266*a743e384SChau Ly                       << std::setw(2) << static_cast<uint32_t>(eventState)
267*a743e384SChau Ly                       << " previousEventState 0x" << std::setw(2)
268*a743e384SChau Ly                       << static_cast<uint32_t>(previousEventState)
269*a743e384SChau Ly                       << " sensorDataSize 0x" << std::setw(2)
270*a743e384SChau Ly                       << static_cast<uint32_t>(sensorDataSize)
271*a743e384SChau Ly                       << " presentReading 0x" << std::setw(8)
272*a743e384SChau Ly                       << static_cast<uint32_t>(presentReading) << std::dec;
273*a743e384SChau Ly             description += strStream.str();
274*a743e384SChau Ly 
275*a743e384SChau Ly             sendJournalRedfish(description, logLevel);
276*a743e384SChau Ly             break;
277*a743e384SChau Ly     }
278*a743e384SChau Ly     return PLDM_SUCCESS;
279*a743e384SChau Ly }
280*a743e384SChau Ly 
processStateSensorEvent(pldm_tid_t tid,uint16_t sensorId,const uint8_t * sensorData,size_t sensorDataLength)281*a743e384SChau Ly int OemEventManager::processStateSensorEvent(pldm_tid_t tid, uint16_t sensorId,
282*a743e384SChau Ly                                              const uint8_t* sensorData,
283*a743e384SChau Ly                                              size_t sensorDataLength)
284*a743e384SChau Ly {
285*a743e384SChau Ly     uint8_t sensorOffset = 0;
286*a743e384SChau Ly     uint8_t eventState = 0;
287*a743e384SChau Ly     uint8_t previousEventState = 0;
288*a743e384SChau Ly 
289*a743e384SChau Ly     auto rc =
290*a743e384SChau Ly         decode_state_sensor_data(sensorData, sensorDataLength, &sensorOffset,
291*a743e384SChau Ly                                  &eventState, &previousEventState);
292*a743e384SChau Ly     if (rc)
293*a743e384SChau Ly     {
294*a743e384SChau Ly         lg2::error(
295*a743e384SChau Ly             "Failed to decode stateSensorState event for terminus ID {TID}, error {RC}",
296*a743e384SChau Ly             "TID", tid, "RC", rc);
297*a743e384SChau Ly         return rc;
298*a743e384SChau Ly     }
299*a743e384SChau Ly 
300*a743e384SChau Ly     std::string description;
301*a743e384SChau Ly     std::stringstream strStream;
302*a743e384SChau Ly     log_level logLevel = log_level::OK;
303*a743e384SChau Ly 
304*a743e384SChau Ly     description += "SENSOR_EVENT : STATE_SENSOR_STATE: ";
305*a743e384SChau Ly     description += prefixMsgStrCreation(tid, sensorId);
306*a743e384SChau Ly     strStream << std::setfill('0') << std::hex << "sensorOffset 0x"
307*a743e384SChau Ly               << std::setw(2) << static_cast<uint32_t>(sensorOffset)
308*a743e384SChau Ly               << "eventState 0x" << std::setw(2)
309*a743e384SChau Ly               << static_cast<uint32_t>(eventState) << " previousEventState 0x"
310*a743e384SChau Ly               << std::setw(2) << static_cast<uint32_t>(previousEventState)
311*a743e384SChau Ly               << std::dec;
312*a743e384SChau Ly     description += strStream.str();
313*a743e384SChau Ly 
314*a743e384SChau Ly     sendJournalRedfish(description, logLevel);
315*a743e384SChau Ly 
316*a743e384SChau Ly     return PLDM_SUCCESS;
317*a743e384SChau Ly }
318*a743e384SChau Ly 
processSensorOpStateEvent(pldm_tid_t tid,uint16_t sensorId,const uint8_t * sensorData,size_t sensorDataLength)319*a743e384SChau Ly int OemEventManager::processSensorOpStateEvent(
320*a743e384SChau Ly     pldm_tid_t tid, uint16_t sensorId, const uint8_t* sensorData,
321*a743e384SChau Ly     size_t sensorDataLength)
322*a743e384SChau Ly {
323*a743e384SChau Ly     uint8_t present_op_state = 0;
324*a743e384SChau Ly     uint8_t previous_op_state = 0;
325*a743e384SChau Ly 
326*a743e384SChau Ly     auto rc = decode_sensor_op_data(sensorData, sensorDataLength,
327*a743e384SChau Ly                                     &present_op_state, &previous_op_state);
328*a743e384SChau Ly     if (rc)
329*a743e384SChau Ly     {
330*a743e384SChau Ly         lg2::error(
331*a743e384SChau Ly             "Failed to decode sensorOpState event for terminus ID {TID}, error {RC}",
332*a743e384SChau Ly             "TID", tid, "RC", rc);
333*a743e384SChau Ly         return rc;
334*a743e384SChau Ly     }
335*a743e384SChau Ly 
336*a743e384SChau Ly     std::string description;
337*a743e384SChau Ly     std::stringstream strStream;
338*a743e384SChau Ly     log_level logLevel = log_level::OK;
339*a743e384SChau Ly 
340*a743e384SChau Ly     description += "SENSOR_EVENT : SENSOR_OP_STATE: ";
341*a743e384SChau Ly     description += prefixMsgStrCreation(tid, sensorId);
342*a743e384SChau Ly     strStream << std::setfill('0') << std::hex << "present_op_state 0x"
343*a743e384SChau Ly               << std::setw(2) << static_cast<uint32_t>(present_op_state)
344*a743e384SChau Ly               << "previous_op_state 0x" << std::setw(2)
345*a743e384SChau Ly               << static_cast<uint32_t>(previous_op_state) << std::dec;
346*a743e384SChau Ly     description += strStream.str();
347*a743e384SChau Ly 
348*a743e384SChau Ly     sendJournalRedfish(description, logLevel);
349*a743e384SChau Ly 
350*a743e384SChau Ly     return PLDM_SUCCESS;
351*a743e384SChau Ly }
352*a743e384SChau Ly 
handleSensorEvent(const pldm_msg * request,size_t payloadLength,uint8_t,pldm_tid_t tid,size_t eventDataOffset)353*a743e384SChau Ly int OemEventManager::handleSensorEvent(
354*a743e384SChau Ly     const pldm_msg* request, size_t payloadLength, uint8_t /* formatVersion */,
355*a743e384SChau Ly     pldm_tid_t tid, size_t eventDataOffset)
356*a743e384SChau Ly {
357*a743e384SChau Ly     /* This OEM event handler is only used for SoC terminus*/
358*a743e384SChau Ly     if (!tidToSocketNameMap.contains(tid))
359*a743e384SChau Ly     {
360*a743e384SChau Ly         return PLDM_SUCCESS;
361*a743e384SChau Ly     }
362*a743e384SChau Ly     auto eventData =
363*a743e384SChau Ly         reinterpret_cast<const uint8_t*>(request->payload) + eventDataOffset;
364*a743e384SChau Ly     auto eventDataSize = payloadLength - eventDataOffset;
365*a743e384SChau Ly 
366*a743e384SChau Ly     uint16_t sensorId = 0;
367*a743e384SChau Ly     uint8_t sensorEventClassType = 0;
368*a743e384SChau Ly     size_t eventClassDataOffset = 0;
369*a743e384SChau Ly     auto rc =
370*a743e384SChau Ly         decode_sensor_event_data(eventData, eventDataSize, &sensorId,
371*a743e384SChau Ly                                  &sensorEventClassType, &eventClassDataOffset);
372*a743e384SChau Ly     if (rc)
373*a743e384SChau Ly     {
374*a743e384SChau Ly         lg2::error("Failed to decode sensor event data return code {RC}.", "RC",
375*a743e384SChau Ly                    rc);
376*a743e384SChau Ly         return rc;
377*a743e384SChau Ly     }
378*a743e384SChau Ly     const uint8_t* sensorData = eventData + eventClassDataOffset;
379*a743e384SChau Ly     size_t sensorDataLength = eventDataSize - eventClassDataOffset;
380*a743e384SChau Ly 
381*a743e384SChau Ly     switch (sensorEventClassType)
382*a743e384SChau Ly     {
383*a743e384SChau Ly         case PLDM_NUMERIC_SENSOR_STATE:
384*a743e384SChau Ly         {
385*a743e384SChau Ly             return processNumericSensorEvent(tid, sensorId, sensorData,
386*a743e384SChau Ly                                              sensorDataLength);
387*a743e384SChau Ly         }
388*a743e384SChau Ly         case PLDM_STATE_SENSOR_STATE:
389*a743e384SChau Ly         {
390*a743e384SChau Ly             return processStateSensorEvent(tid, sensorId, sensorData,
391*a743e384SChau Ly                                            sensorDataLength);
392*a743e384SChau Ly         }
393*a743e384SChau Ly         case PLDM_SENSOR_OP_STATE:
394*a743e384SChau Ly         {
395*a743e384SChau Ly             return processSensorOpStateEvent(tid, sensorId, sensorData,
396*a743e384SChau Ly                                              sensorDataLength);
397*a743e384SChau Ly         }
398*a743e384SChau Ly         default:
399*a743e384SChau Ly             std::string description;
400*a743e384SChau Ly             std::stringstream strStream;
401*a743e384SChau Ly             log_level logLevel = log_level::OK;
402*a743e384SChau Ly 
403*a743e384SChau Ly             description += "SENSOR_EVENT : Unsupported Sensor Class " +
404*a743e384SChau Ly                            std::to_string(sensorEventClassType) + ": ";
405*a743e384SChau Ly             description += prefixMsgStrCreation(tid, sensorId);
406*a743e384SChau Ly             strStream << std::setfill('0') << std::hex
407*a743e384SChau Ly                       << std::setw(sizeof(sensorData) * 2) << "Sensor data: ";
408*a743e384SChau Ly 
409*a743e384SChau Ly             auto dataPtr = sensorData;
410*a743e384SChau Ly             for ([[maybe_unused]] const auto& i :
411*a743e384SChau Ly                  std::views::iota(0, (int)sensorDataLength))
412*a743e384SChau Ly             {
413*a743e384SChau Ly                 strStream << "0x" << static_cast<uint32_t>(*dataPtr);
414*a743e384SChau Ly                 dataPtr += sizeof(sensorData);
415*a743e384SChau Ly             }
416*a743e384SChau Ly 
417*a743e384SChau Ly             description += strStream.str();
418*a743e384SChau Ly 
419*a743e384SChau Ly             sendJournalRedfish(description, logLevel);
420*a743e384SChau Ly     }
421*a743e384SChau Ly     lg2::info("Unsupported class type {CLASSTYPE}", "CLASSTYPE",
422*a743e384SChau Ly               sensorEventClassType);
423*a743e384SChau Ly     return PLDM_ERROR;
424*a743e384SChau Ly }
425*a743e384SChau Ly 
426*a743e384SChau Ly } // namespace oem_ampere
427*a743e384SChau Ly } // namespace pldm
428