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