1*77e6fe7aSGilbert Chen #include "event_manager.hpp"
2*77e6fe7aSGilbert Chen 
3*77e6fe7aSGilbert Chen #include "libpldm/utils.h"
4*77e6fe7aSGilbert Chen 
5*77e6fe7aSGilbert Chen #include "terminus_manager.hpp"
6*77e6fe7aSGilbert Chen 
7*77e6fe7aSGilbert Chen #include <phosphor-logging/lg2.hpp>
8*77e6fe7aSGilbert Chen #include <xyz/openbmc_project/Logging/Entry/server.hpp>
9*77e6fe7aSGilbert Chen 
10*77e6fe7aSGilbert Chen #include <cerrno>
11*77e6fe7aSGilbert Chen #include <memory>
12*77e6fe7aSGilbert Chen 
13*77e6fe7aSGilbert Chen PHOSPHOR_LOG2_USING;
14*77e6fe7aSGilbert Chen 
15*77e6fe7aSGilbert Chen namespace pldm
16*77e6fe7aSGilbert Chen {
17*77e6fe7aSGilbert Chen namespace platform_mc
18*77e6fe7aSGilbert Chen {
19*77e6fe7aSGilbert Chen namespace fs = std::filesystem;
20*77e6fe7aSGilbert Chen 
21*77e6fe7aSGilbert Chen int EventManager::handlePlatformEvent(
22*77e6fe7aSGilbert Chen     pldm_tid_t tid, uint16_t eventId, uint8_t eventClass,
23*77e6fe7aSGilbert Chen     const uint8_t* eventData, size_t eventDataSize)
24*77e6fe7aSGilbert Chen {
25*77e6fe7aSGilbert Chen     /* EventClass sensorEvent `Table 11 - PLDM Event Types` DSP0248 */
26*77e6fe7aSGilbert Chen     if (eventClass == PLDM_SENSOR_EVENT)
27*77e6fe7aSGilbert Chen     {
28*77e6fe7aSGilbert Chen         uint16_t sensorId = 0;
29*77e6fe7aSGilbert Chen         uint8_t sensorEventClassType = 0;
30*77e6fe7aSGilbert Chen         size_t eventClassDataOffset = 0;
31*77e6fe7aSGilbert Chen         auto rc = decode_sensor_event_data(eventData, eventDataSize, &sensorId,
32*77e6fe7aSGilbert Chen                                            &sensorEventClassType,
33*77e6fe7aSGilbert Chen                                            &eventClassDataOffset);
34*77e6fe7aSGilbert Chen         if (rc)
35*77e6fe7aSGilbert Chen         {
36*77e6fe7aSGilbert Chen             lg2::error(
37*77e6fe7aSGilbert Chen                 "Failed to decode sensor event data from terminus ID {TID}, event class {CLASS}, event ID {EVENTID} with return code {RC}.",
38*77e6fe7aSGilbert Chen                 "TID", tid, "CLASS", eventClass, "EVENTID", eventId, "RC", rc);
39*77e6fe7aSGilbert Chen             return rc;
40*77e6fe7aSGilbert Chen         }
41*77e6fe7aSGilbert Chen         switch (sensorEventClassType)
42*77e6fe7aSGilbert Chen         {
43*77e6fe7aSGilbert Chen             case PLDM_NUMERIC_SENSOR_STATE:
44*77e6fe7aSGilbert Chen             {
45*77e6fe7aSGilbert Chen                 const uint8_t* sensorData = eventData + eventClassDataOffset;
46*77e6fe7aSGilbert Chen                 size_t sensorDataLength = eventDataSize - eventClassDataOffset;
47*77e6fe7aSGilbert Chen                 return processNumericSensorEvent(tid, sensorId, sensorData,
48*77e6fe7aSGilbert Chen                                                  sensorDataLength);
49*77e6fe7aSGilbert Chen             }
50*77e6fe7aSGilbert Chen             case PLDM_STATE_SENSOR_STATE:
51*77e6fe7aSGilbert Chen             case PLDM_SENSOR_OP_STATE:
52*77e6fe7aSGilbert Chen             default:
53*77e6fe7aSGilbert Chen                 lg2::info(
54*77e6fe7aSGilbert Chen                     "Unsupported class type {CLASSTYPE} for the sensor event from terminus ID {TID} sensorId {SID}",
55*77e6fe7aSGilbert Chen                     "CLASSTYPE", sensorEventClassType, "TID", tid, "SID",
56*77e6fe7aSGilbert Chen                     sensorId);
57*77e6fe7aSGilbert Chen                 return PLDM_ERROR;
58*77e6fe7aSGilbert Chen         }
59*77e6fe7aSGilbert Chen     }
60*77e6fe7aSGilbert Chen 
61*77e6fe7aSGilbert Chen     lg2::info("Unsupported class type {CLASSTYPE}", "CLASSTYPE", eventClass);
62*77e6fe7aSGilbert Chen 
63*77e6fe7aSGilbert Chen     return PLDM_ERROR;
64*77e6fe7aSGilbert Chen }
65*77e6fe7aSGilbert Chen 
66*77e6fe7aSGilbert Chen int EventManager::processNumericSensorEvent(pldm_tid_t tid, uint16_t sensorId,
67*77e6fe7aSGilbert Chen                                             const uint8_t* sensorData,
68*77e6fe7aSGilbert Chen                                             size_t sensorDataLength)
69*77e6fe7aSGilbert Chen {
70*77e6fe7aSGilbert Chen     uint8_t eventState = 0;
71*77e6fe7aSGilbert Chen     uint8_t previousEventState = 0;
72*77e6fe7aSGilbert Chen     uint8_t sensorDataSize = 0;
73*77e6fe7aSGilbert Chen     uint32_t presentReading;
74*77e6fe7aSGilbert Chen     auto rc = decode_numeric_sensor_data(
75*77e6fe7aSGilbert Chen         sensorData, sensorDataLength, &eventState, &previousEventState,
76*77e6fe7aSGilbert Chen         &sensorDataSize, &presentReading);
77*77e6fe7aSGilbert Chen     if (rc)
78*77e6fe7aSGilbert Chen     {
79*77e6fe7aSGilbert Chen         lg2::error(
80*77e6fe7aSGilbert Chen             "Failed to decode numericSensorState event for terminus ID {TID}, error {RC} ",
81*77e6fe7aSGilbert Chen             "TID", tid, "RC", rc);
82*77e6fe7aSGilbert Chen         return rc;
83*77e6fe7aSGilbert Chen     }
84*77e6fe7aSGilbert Chen 
85*77e6fe7aSGilbert Chen     double value = static_cast<double>(presentReading);
86*77e6fe7aSGilbert Chen     lg2::error(
87*77e6fe7aSGilbert Chen         "processNumericSensorEvent tid {TID}, sensorID {SID} value {VAL} previousState {PSTATE} eventState {ESTATE}",
88*77e6fe7aSGilbert Chen         "TID", tid, "SID", sensorId, "VAL", value, "PSTATE", previousEventState,
89*77e6fe7aSGilbert Chen         "ESTATE", eventState);
90*77e6fe7aSGilbert Chen 
91*77e6fe7aSGilbert Chen     if (!termini.contains(tid) || !termini[tid])
92*77e6fe7aSGilbert Chen     {
93*77e6fe7aSGilbert Chen         lg2::error("Terminus ID {TID} is not in the managing list.", "TID",
94*77e6fe7aSGilbert Chen                    tid);
95*77e6fe7aSGilbert Chen         return PLDM_ERROR;
96*77e6fe7aSGilbert Chen     }
97*77e6fe7aSGilbert Chen 
98*77e6fe7aSGilbert Chen     auto& terminus = termini[tid];
99*77e6fe7aSGilbert Chen 
100*77e6fe7aSGilbert Chen     auto sensor = terminus->getSensorObject(sensorId);
101*77e6fe7aSGilbert Chen     if (!sensor)
102*77e6fe7aSGilbert Chen     {
103*77e6fe7aSGilbert Chen         lg2::error(
104*77e6fe7aSGilbert Chen             "Terminus ID {TID} has no sensor object with sensor ID {SID}.",
105*77e6fe7aSGilbert Chen             "TID", tid, "SID", sensorId);
106*77e6fe7aSGilbert Chen         return PLDM_ERROR;
107*77e6fe7aSGilbert Chen     }
108*77e6fe7aSGilbert Chen 
109*77e6fe7aSGilbert Chen     switch (previousEventState)
110*77e6fe7aSGilbert Chen     {
111*77e6fe7aSGilbert Chen         case PLDM_SENSOR_UNKNOWN:
112*77e6fe7aSGilbert Chen         case PLDM_SENSOR_NORMAL:
113*77e6fe7aSGilbert Chen         {
114*77e6fe7aSGilbert Chen             switch (eventState)
115*77e6fe7aSGilbert Chen             {
116*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
117*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
118*77e6fe7aSGilbert Chen                 {
119*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
120*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
121*77e6fe7aSGilbert Chen                                                   value, true, true);
122*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
123*77e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
124*77e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
125*77e6fe7aSGilbert Chen                 }
126*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
127*77e6fe7aSGilbert Chen                 {
128*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
129*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
130*77e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
131*77e6fe7aSGilbert Chen                 }
132*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
133*77e6fe7aSGilbert Chen                     break;
134*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
135*77e6fe7aSGilbert Chen                 {
136*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
137*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
138*77e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
139*77e6fe7aSGilbert Chen                 }
140*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
141*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
142*77e6fe7aSGilbert Chen                 {
143*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
144*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
145*77e6fe7aSGilbert Chen                                                   value, true, true);
146*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
147*77e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
148*77e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
149*77e6fe7aSGilbert Chen                 }
150*77e6fe7aSGilbert Chen                 default:
151*77e6fe7aSGilbert Chen                     break;
152*77e6fe7aSGilbert Chen             }
153*77e6fe7aSGilbert Chen             break;
154*77e6fe7aSGilbert Chen         }
155*77e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERWARNING:
156*77e6fe7aSGilbert Chen         {
157*77e6fe7aSGilbert Chen             switch (eventState)
158*77e6fe7aSGilbert Chen             {
159*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
160*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
161*77e6fe7aSGilbert Chen                     break;
162*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
163*77e6fe7aSGilbert Chen                 {
164*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
165*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
166*77e6fe7aSGilbert Chen                                                   value, false, false);
167*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
168*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
169*77e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
170*77e6fe7aSGilbert Chen                 }
171*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
172*77e6fe7aSGilbert Chen                 {
173*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
174*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
175*77e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, false, false);
176*77e6fe7aSGilbert Chen                 }
177*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
178*77e6fe7aSGilbert Chen                     break;
179*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
180*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
181*77e6fe7aSGilbert Chen                 {
182*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
183*77e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
184*77e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
185*77e6fe7aSGilbert Chen                 }
186*77e6fe7aSGilbert Chen                 default:
187*77e6fe7aSGilbert Chen                     break;
188*77e6fe7aSGilbert Chen             }
189*77e6fe7aSGilbert Chen             break;
190*77e6fe7aSGilbert Chen         }
191*77e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERCRITICAL:
192*77e6fe7aSGilbert Chen         case PLDM_SENSOR_LOWERFATAL:
193*77e6fe7aSGilbert Chen         {
194*77e6fe7aSGilbert Chen             switch (eventState)
195*77e6fe7aSGilbert Chen             {
196*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
197*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
198*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
199*77e6fe7aSGilbert Chen                     break;
200*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
201*77e6fe7aSGilbert Chen                 {
202*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
203*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
204*77e6fe7aSGilbert Chen                                                   value, false, false);
205*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
206*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
207*77e6fe7aSGilbert Chen                                                   value, true, true);
208*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
209*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
210*77e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, false, false);
211*77e6fe7aSGilbert Chen                 }
212*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
213*77e6fe7aSGilbert Chen                 {
214*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
215*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::LOW,
216*77e6fe7aSGilbert Chen                                                   value, false, false);
217*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
218*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
219*77e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
220*77e6fe7aSGilbert Chen                 }
221*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
222*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
223*77e6fe7aSGilbert Chen                 default:
224*77e6fe7aSGilbert Chen                     break;
225*77e6fe7aSGilbert Chen             }
226*77e6fe7aSGilbert Chen             break;
227*77e6fe7aSGilbert Chen         }
228*77e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERFATAL:
229*77e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERCRITICAL:
230*77e6fe7aSGilbert Chen         {
231*77e6fe7aSGilbert Chen             switch (eventState)
232*77e6fe7aSGilbert Chen             {
233*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
234*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
235*77e6fe7aSGilbert Chen                     break;
236*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
237*77e6fe7aSGilbert Chen                 {
238*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
239*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
240*77e6fe7aSGilbert Chen                                                   value, false, false);
241*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
242*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
243*77e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
244*77e6fe7aSGilbert Chen                 }
245*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
246*77e6fe7aSGilbert Chen                 {
247*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::CRITICAL,
248*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
249*77e6fe7aSGilbert Chen                                                   value, false, false);
250*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
251*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
252*77e6fe7aSGilbert Chen                                                   value, true, true);
253*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
254*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
255*77e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, false, false);
256*77e6fe7aSGilbert Chen                 }
257*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
258*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
259*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
260*77e6fe7aSGilbert Chen                 default:
261*77e6fe7aSGilbert Chen                     break;
262*77e6fe7aSGilbert Chen             }
263*77e6fe7aSGilbert Chen             break;
264*77e6fe7aSGilbert Chen         }
265*77e6fe7aSGilbert Chen         case PLDM_SENSOR_UPPERWARNING:
266*77e6fe7aSGilbert Chen         {
267*77e6fe7aSGilbert Chen             switch (eventState)
268*77e6fe7aSGilbert Chen             {
269*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERFATAL:
270*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERCRITICAL:
271*77e6fe7aSGilbert Chen                 {
272*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
273*77e6fe7aSGilbert Chen                         pldm::utils::Level::CRITICAL,
274*77e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, true, true);
275*77e6fe7aSGilbert Chen                 }
276*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_UPPERWARNING:
277*77e6fe7aSGilbert Chen                     break;
278*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_NORMAL:
279*77e6fe7aSGilbert Chen                 {
280*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
281*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
282*77e6fe7aSGilbert Chen                         pldm::utils::Direction::HIGH, value, false, false);
283*77e6fe7aSGilbert Chen                 }
284*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERWARNING:
285*77e6fe7aSGilbert Chen                 {
286*77e6fe7aSGilbert Chen                     sensor->triggerThresholdEvent(pldm::utils::Level::WARNING,
287*77e6fe7aSGilbert Chen                                                   pldm::utils::Direction::HIGH,
288*77e6fe7aSGilbert Chen                                                   value, false, false);
289*77e6fe7aSGilbert Chen                     return sensor->triggerThresholdEvent(
290*77e6fe7aSGilbert Chen                         pldm::utils::Level::WARNING,
291*77e6fe7aSGilbert Chen                         pldm::utils::Direction::LOW, value, true, true);
292*77e6fe7aSGilbert Chen                 }
293*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERCRITICAL:
294*77e6fe7aSGilbert Chen                 case PLDM_SENSOR_LOWERFATAL:
295*77e6fe7aSGilbert Chen                 default:
296*77e6fe7aSGilbert Chen                     break;
297*77e6fe7aSGilbert Chen             }
298*77e6fe7aSGilbert Chen             break;
299*77e6fe7aSGilbert Chen         }
300*77e6fe7aSGilbert Chen         default:
301*77e6fe7aSGilbert Chen             break;
302*77e6fe7aSGilbert Chen     }
303*77e6fe7aSGilbert Chen 
304*77e6fe7aSGilbert Chen     return PLDM_SUCCESS;
305*77e6fe7aSGilbert Chen }
306*77e6fe7aSGilbert Chen 
307*77e6fe7aSGilbert Chen } // namespace platform_mc
308*77e6fe7aSGilbert Chen } // namespace pldm
309