blob: d5bf3d264fc29e55ae3cc4a37a271a2cb0c81a9b [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#include "event_logger.hpp"
2
Anupama B Rb53d97c2025-02-24 03:37:34 -06003#include "exceptions.hpp"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05004#include "logger.hpp"
5
6#include <systemd/sd-bus.h>
7
8namespace vpd
9{
10const std::unordered_map<types::SeverityType, std::string>
11 EventLogger::m_severityMap = {
12 {types::SeverityType::Notice,
13 "xyz.openbmc_project.Logging.Entry.Level.Notice"},
14 {types::SeverityType::Informational,
15 "xyz.openbmc_project.Logging.Entry.Level.Informational"},
16 {types::SeverityType::Debug,
17 "xyz.openbmc_project.Logging.Entry.Level.Debug"},
18 {types::SeverityType::Warning,
19 "xyz.openbmc_project.Logging.Entry.Level.Warning"},
20 {types::SeverityType::Critical,
21 "xyz.openbmc_project.Logging.Entry.Level.Critical"},
22 {types::SeverityType::Emergency,
23 "xyz.openbmc_project.Logging.Entry.Level.Emergency"},
24 {types::SeverityType::Alert,
25 "xyz.openbmc_project.Logging.Entry.Level.Alert"},
26 {types::SeverityType::Error,
27 "xyz.openbmc_project.Logging.Entry.Level.Error"}};
28
29const std::unordered_map<types::ErrorType, std::string>
30 EventLogger::m_errorMsgMap = {
31 {types::ErrorType::DefaultValue, "com.ibm.VPD.Error.DefaultValue"},
Sunny Srivastavac09e2102025-04-23 10:47:06 +053032 {types::ErrorType::UndefinedError, "com.ibm.VPD.Error.UndefinedError"},
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050033 {types::ErrorType::InvalidVpdMessage, "com.ibm.VPD.Error.InvalidVPD"},
34 {types::ErrorType::VpdMismatch, "com.ibm.VPD.Error.Mismatch"},
35 {types::ErrorType::InvalidEeprom,
36 "com.ibm.VPD.Error.InvalidEepromPath"},
37 {types::ErrorType::EccCheckFailed, "com.ibm.VPD.Error.EccCheckFailed"},
38 {types::ErrorType::JsonFailure, "com.ibm.VPD.Error.InvalidJson"},
39 {types::ErrorType::DbusFailure, "com.ibm.VPD.Error.DbusFailure"},
40 {types::ErrorType::InvalidSystem,
41 "com.ibm.VPD.Error.UnknownSystemType"},
42 {types::ErrorType::EssentialFru,
43 "com.ibm.VPD.Error.RequiredFRUMissing"},
Sunny Srivastavaa88a2982025-01-23 12:03:21 +053044 {types::ErrorType::GpioError, "com.ibm.VPD.Error.GPIOError"},
45 {types::ErrorType::InternalFailure,
46 "xyz.openbmc_project.Common.Error.InternalFailure"},
Rekha Aparnaffdff312025-03-25 01:10:56 -050047 {types::ErrorType::FruMissing, "com.ibm.VPD.Error.RequiredFRUMissing"},
48 {types::ErrorType::SystemTypeMismatch,
49 "com.ibm.VPD.Error.SystemTypeMismatch"},
50 {types::ErrorType::UnknownSystemSettings,
Sunny Srivastava4fa796c2025-04-01 10:27:02 +053051 "com.ibm.VPD.Error.UnknownSystemSettings"},
52 {types::ErrorType::FirmwareError, "com.ibm.VPD.Error.FirmwareError"}};
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050053
54const std::unordered_map<types::CalloutPriority, std::string>
55 EventLogger::m_priorityMap = {
56 {types::CalloutPriority::High, "H"},
57 {types::CalloutPriority::Medium, "M"},
58 {types::CalloutPriority::MediumGroupA, "A"},
59 {types::CalloutPriority::MediumGroupB, "B"},
60 {types::CalloutPriority::MediumGroupC, "C"},
61 {types::CalloutPriority::Low, "L"}};
62
63void EventLogger::createAsyncPelWithInventoryCallout(
64 const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
65 const std::vector<types::InventoryCalloutData>& i_callouts,
66 const std::string& i_fileName, const std::string& i_funcName,
67 const uint8_t i_internalRc, const std::string& i_description,
68 const std::optional<std::string> i_userData1,
69 const std::optional<std::string> i_userData2,
70 const std::optional<std::string> i_symFru,
71 const std::optional<std::string> i_procedure)
72{
73 (void)i_symFru;
74 (void)i_procedure;
75
76 try
77 {
78 if (i_callouts.empty())
79 {
80 logging::logMessage("Callout information is missing to create PEL");
81 // TODO: Revisit this instead of simpley returning.
82 return;
83 }
84
85 if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
86 {
87 throw std::runtime_error(
88 "Error type not found in the error message map to create PEL");
89 // TODO: Need to handle, instead of throwing exception. Create
90 // default message in message_registry.json.
91 }
92
93 const std::string& l_message = m_errorMsgMap.at(i_errorType);
94
95 const std::string& l_severity =
96 (m_severityMap.find(i_severity) != m_severityMap.end()
97 ? m_severityMap.at(i_severity)
98 : m_severityMap.at(types::SeverityType::Informational));
99
100 std::string l_description =
101 (!i_description.empty() ? i_description : "VPD generic error");
102
103 std::string l_userData1 = (i_userData1) ? (*i_userData1) : "";
104
105 std::string l_userData2 = (i_userData2) ? (*i_userData2) : "";
106
107 const types::InventoryCalloutData& l_invCallout = i_callouts[0];
108 // TODO: Need to handle multiple inventory path callout's, when multiple
109 // callout's is supported by "Logging" service.
110
111 const types::CalloutPriority& l_priorityEnum = get<1>(l_invCallout);
112
113 const std::string& l_priority =
114 (m_priorityMap.find(l_priorityEnum) != m_priorityMap.end()
115 ? m_priorityMap.at(l_priorityEnum)
116 : m_priorityMap.at(types::CalloutPriority::Low));
117
118 sd_bus* l_sdBus = nullptr;
119 sd_bus_default(&l_sdBus);
120
121 const uint8_t l_additionalDataCount = 8;
122 auto l_rc = sd_bus_call_method_async(
123 l_sdBus, NULL, constants::eventLoggingServiceName,
124 constants::eventLoggingObjectPath, constants::eventLoggingInterface,
125 "Create", NULL, NULL, "ssa{ss}", l_message.c_str(),
126 l_severity.c_str(), l_additionalDataCount, "FileName",
127 i_fileName.c_str(), "FunctionName", i_funcName.c_str(),
128 "InternalRc", std::to_string(i_internalRc).c_str(), "DESCRIPTION",
129 l_description.c_str(), "UserData1", l_userData1.c_str(),
130 "UserData2", l_userData2.c_str(), "CALLOUT_INVENTORY_PATH",
131 get<0>(l_invCallout).c_str(), "CALLOUT_PRIORITY",
132 l_priority.c_str());
133
134 if (l_rc < 0)
135 {
136 logging::logMessage(
137 "Error calling sd_bus_call_method_async, Message = " +
138 std::string(strerror(-l_rc)));
139 }
140 }
141 catch (const std::exception& l_ex)
142 {
143 logging::logMessage(
144 "Create PEL failed with error: " + std::string(l_ex.what()));
145 }
146}
147
148void EventLogger::createAsyncPelWithI2cDeviceCallout(
149 const types::ErrorType i_errorType, const types::SeverityType i_severity,
150 const std::vector<types::DeviceCalloutData>& i_callouts,
151 const std::string& i_fileName, const std::string& i_funcName,
152 const uint8_t i_internalRc,
153 const std::optional<std::pair<std::string, std::string>> i_userData1,
154 const std::optional<std::pair<std::string, std::string>> i_userData2)
155{
156 // TODO, implementation needs to be added.
157 (void)i_errorType;
158 (void)i_severity;
159 (void)i_callouts;
160 (void)i_fileName;
161 (void)i_funcName;
162 (void)i_internalRc;
163 (void)i_userData1;
164 (void)i_userData2;
165}
166
167void EventLogger::createAsyncPelWithI2cBusCallout(
168 const types::ErrorType i_errorType, const types::SeverityType i_severity,
169 const std::vector<types::I2cBusCalloutData>& i_callouts,
170 const std::string& i_fileName, const std::string& i_funcName,
171 const uint8_t i_internalRc,
172 const std::optional<std::pair<std::string, std::string>> i_userData1,
173 const std::optional<std::pair<std::string, std::string>> i_userData2)
174{
175 // TODO, implementation needs to be added.
176 (void)i_errorType;
177 (void)i_severity;
178 (void)i_callouts;
179 (void)i_fileName;
180 (void)i_funcName;
181 (void)i_internalRc;
182 (void)i_userData1;
183 (void)i_userData2;
184}
185
186void EventLogger::createAsyncPel(
187 const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
188 const std::string& i_fileName, const std::string& i_funcName,
189 const uint8_t i_internalRc, const std::string& i_description,
190 const std::optional<std::string> i_userData1,
191 const std::optional<std::string> i_userData2,
192 const std::optional<std::string> i_symFru,
193 const std::optional<std::string> i_procedure)
194{
195 (void)i_symFru;
196 (void)i_procedure;
197 try
198 {
199 if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
200 {
201 throw std::runtime_error("Unsupported error type received");
202 // TODO: Need to handle, instead of throwing an exception.
203 }
204
205 const std::string& l_message = m_errorMsgMap.at(i_errorType);
206
207 const std::string& l_severity =
208 (m_severityMap.find(i_severity) != m_severityMap.end()
209 ? m_severityMap.at(i_severity)
210 : m_severityMap.at(types::SeverityType::Informational));
211
212 const std::string l_description =
213 ((!i_description.empty() ? i_description : "VPD generic error"));
214
215 const std::string l_userData1 = ((i_userData1) ? (*i_userData1) : "");
216
217 const std::string l_userData2 = ((i_userData2) ? (*i_userData2) : "");
218
219 sd_bus* l_sdBus = nullptr;
220 sd_bus_default(&l_sdBus);
221
222 // VALUE_6 represents the additional data pair count passing to create
223 // PEL. If there any change in additional data, we need to pass the
224 // correct number.
225 auto l_rc = sd_bus_call_method_async(
226 l_sdBus, NULL, constants::eventLoggingServiceName,
227 constants::eventLoggingObjectPath, constants::eventLoggingInterface,
228 "Create", NULL, NULL, "ssa{ss}", l_message.c_str(),
229 l_severity.c_str(), constants::VALUE_6, "FileName",
230 i_fileName.c_str(), "FunctionName", i_funcName.c_str(),
231 "InternalRc", std::to_string(i_internalRc).c_str(), "DESCRIPTION",
232 l_description.c_str(), "UserData1", l_userData1.c_str(),
233 "UserData2", l_userData2.c_str());
234
235 if (l_rc < 0)
236 {
237 logging::logMessage(
238 "Error calling sd_bus_call_method_async, Message = " +
239 std::string(strerror(-l_rc)));
240 }
241 }
242 catch (const sdbusplus::exception::SdBusError& l_ex)
243 {
244 logging::logMessage("Async PEL creation failed with an error: " +
245 std::string(l_ex.what()));
246 }
247}
248
249void EventLogger::createSyncPel(
250 const types::ErrorType& i_errorType, const types::SeverityType& i_severity,
251 const std::string& i_fileName, const std::string& i_funcName,
252 const uint8_t i_internalRc, const std::string& i_description,
253 const std::optional<std::string> i_userData1,
254 const std::optional<std::string> i_userData2,
255 const std::optional<std::string> i_symFru,
256 const std::optional<std::string> i_procedure)
257{
258 (void)i_symFru;
259 (void)i_procedure;
260 try
261 {
262 if (m_errorMsgMap.find(i_errorType) == m_errorMsgMap.end())
263 {
264 throw std::runtime_error("Unsupported error type received");
265 // TODO: Need to handle, instead of throwing an exception.
266 }
267
268 const std::string& l_message = m_errorMsgMap.at(i_errorType);
269
270 const std::string& l_severity =
271 (m_severityMap.find(i_severity) != m_severityMap.end()
272 ? m_severityMap.at(i_severity)
273 : m_severityMap.at(types::SeverityType::Informational));
274
275 const std::string l_description =
276 ((!i_description.empty() ? i_description : "VPD generic error"));
277
278 const std::string l_userData1 = ((i_userData1) ? (*i_userData1) : "");
279
280 const std::string l_userData2 = ((i_userData2) ? (*i_userData2) : "");
281
282 std::map<std::string, std::string> l_additionalData{
283 {"FileName", i_fileName},
284 {"FunctionName", i_funcName},
285 {"DESCRIPTION", l_description},
286 {"InteranlRc", std::to_string(i_internalRc)},
287 {"UserData1", l_userData1.c_str()},
288 {"UserData2", l_userData2.c_str()}};
289
290 auto l_bus = sdbusplus::bus::new_default();
291 auto l_method =
292 l_bus.new_method_call(constants::eventLoggingServiceName,
293 constants::eventLoggingObjectPath,
294 constants::eventLoggingInterface, "Create");
295 l_method.append(l_message, l_severity, l_additionalData);
296 l_bus.call(l_method);
297 }
298 catch (const sdbusplus::exception::SdBusError& l_ex)
299 {
300 logging::logMessage("Sync PEL creation failed with an error: " +
301 std::string(l_ex.what()));
302 }
303}
Anupama B Rb53d97c2025-02-24 03:37:34 -0600304
305types::ExceptionDataMap EventLogger::getExceptionData(
306 const std::exception& i_exception)
307{
308 types::ExceptionDataMap l_errorInfo{
Sunny Srivastavac09e2102025-04-23 10:47:06 +0530309 {"ErrorType", types::ErrorType::UndefinedError},
Anupama B Rb53d97c2025-02-24 03:37:34 -0600310 {"ErrorMsg", i_exception.what()}};
311
312 try
313 {
314 if (typeid(i_exception) == typeid(DataException))
315 {
316 const DataException& l_ex =
317 dynamic_cast<const DataException&>(i_exception);
318 l_errorInfo["ErrorType"] = l_ex.getErrorType();
319 l_errorInfo["ErrorMsg"] =
320 std::string("Data Exception. Reason: ") + i_exception.what();
321 }
322 else if (typeid(i_exception) == typeid(EccException))
323 {
324 const EccException& l_ex =
325 dynamic_cast<const EccException&>(i_exception);
326 l_errorInfo["ErrorType"] = l_ex.getErrorType();
327 l_errorInfo["ErrorMsg"] =
328 std::string("Ecc Exception. Reason: ") + i_exception.what();
329 }
330 else if (typeid(i_exception) == typeid(JsonException))
331 {
332 const JsonException& l_ex =
333 dynamic_cast<const JsonException&>(i_exception);
334 l_errorInfo["ErrorType"] = l_ex.getErrorType();
335 l_errorInfo["ErrorMsg"] =
336 std::string("Json Exception. Reason: ") + i_exception.what();
337 }
338 else if (typeid(i_exception) == typeid(GpioException))
339 {
340 const GpioException& l_ex =
341 dynamic_cast<const GpioException&>(i_exception);
342 l_errorInfo["ErrorType"] = l_ex.getErrorType();
343 l_errorInfo["ErrorMsg"] =
344 std::string("Gpio Exception. Reason: ") + i_exception.what();
345 }
346 else if (typeid(i_exception) == typeid(DbusException))
347 {
348 const DbusException& l_ex =
349 dynamic_cast<const DbusException&>(i_exception);
350 l_errorInfo["ErrorType"] = l_ex.getErrorType();
351 l_errorInfo["ErrorMsg"] =
352 std::string("Dbus Exception. Reason: ") + i_exception.what();
353 }
354 else if (typeid(i_exception) == typeid(FirmwareException))
355 {
356 const FirmwareException& l_ex =
357 dynamic_cast<const FirmwareException&>(i_exception);
358 l_errorInfo["ErrorType"] = l_ex.getErrorType();
359 l_errorInfo["ErrorMsg"] =
360 std::string("Firmware Exception. Reason: ") +
361 i_exception.what();
362 }
363 else if (typeid(i_exception) == typeid(EepromException))
364 {
365 const EepromException& l_ex =
366 dynamic_cast<const EepromException&>(i_exception);
367 l_errorInfo["ErrorType"] = l_ex.getErrorType();
368 l_errorInfo["ErrorMsg"] =
369 std::string("Eeprom Exception. Reason: ") + i_exception.what();
370 }
Sunny Srivastavac09e2102025-04-23 10:47:06 +0530371 else if (typeid(i_exception) == typeid(std::runtime_error))
372 {
373 // Since it is a standard exception no casting is required and error
374 // type is hardcoded.
375 l_errorInfo["ErrorType"] = types::ErrorType::FirmwareError;
376 l_errorInfo["ErrorMsg"] =
377 std::string("Eeprom Exception. Reason: ") + i_exception.what();
378 }
Anupama B Rb53d97c2025-02-24 03:37:34 -0600379 }
380 catch (const std::exception& l_ex)
381 {
382 logging::logMessage(
383 "Failed to get error info, reason: " + std::string(l_ex.what()));
384 }
385 return l_errorInfo;
386}
Sunny Srivastava15a189a2025-02-26 16:53:19 +0530387
388types::ErrorType EventLogger::getErrorType(const std::exception& i_exception)
389{
390 const auto& l_exceptionDataMap = getExceptionData(i_exception);
391
392 auto l_itrToErrType = l_exceptionDataMap.find("ErrorType");
393 if (l_itrToErrType == l_exceptionDataMap.end())
394 {
Sunny Srivastavac09e2102025-04-23 10:47:06 +0530395 return types::ErrorType::UndefinedError;
Sunny Srivastava15a189a2025-02-26 16:53:19 +0530396 }
397
398 auto l_ptrToErrType =
399 std::get_if<types::ErrorType>(&l_itrToErrType->second);
400 if (!l_ptrToErrType)
401 {
Sunny Srivastavac09e2102025-04-23 10:47:06 +0530402 return types::ErrorType::UndefinedError;
Sunny Srivastava15a189a2025-02-26 16:53:19 +0530403 }
404
405 return *l_ptrToErrType;
406}
407
408std::string EventLogger::getErrorMsg(const std::exception& i_exception)
409{
410 const auto& l_exceptionDataMap = getExceptionData(i_exception);
411
412 auto l_itrToErrMsg = l_exceptionDataMap.find("ErrorMsg");
413 if (l_itrToErrMsg == l_exceptionDataMap.end())
414 {
415 return i_exception.what();
416 }
417
418 auto l_ptrToErrMsg = std::get_if<std::string>(&l_itrToErrMsg->second);
419 if (!l_ptrToErrMsg)
420 {
421 return i_exception.what();
422 }
423
424 return *l_ptrToErrMsg;
425}
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500426} // namespace vpd