blob: 8879964dea378995ab6e5a4c5be585a2255f5453 [file] [log] [blame]
Brad Bishop5e5d4452020-10-27 19:46:13 -04001extern "C"
2{
Brad Bishopf6783cd2020-10-27 19:25:09 -04003#include <libpdbg.h>
4}
5
6#include "create_pel.hpp"
Jayanth Othayoth006641e2021-10-07 06:56:24 -05007#include "dump_utils.hpp"
Jayanth Othayoth4079f092021-09-20 07:36:54 -05008#include "extensions/phal/common_utils.hpp"
Brad Bishopf6783cd2020-10-27 19:25:09 -04009#include "phal_error.hpp"
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -050010#include "util.hpp"
Brad Bishopf6783cd2020-10-27 19:25:09 -040011
12#include <attributes_info.H>
13#include <fmt/format.h>
14#include <libekb.H>
Jayanth Othayoth4079f092021-09-20 07:36:54 -050015#include <libphal.H>
Brad Bishopf6783cd2020-10-27 19:25:09 -040016
Brad Bishop5e5d4452020-10-27 19:46:13 -040017#include <nlohmann/json.hpp>
18#include <phosphor-logging/elog.hpp>
19
Brad Bishopf6783cd2020-10-27 19:25:09 -040020#include <algorithm>
21#include <cstdlib>
22#include <cstring>
23#include <iomanip>
24#include <list>
25#include <map>
Brad Bishopf6783cd2020-10-27 19:25:09 -040026#include <sstream>
27#include <string>
28
29namespace openpower
30{
31namespace phal
32{
33using namespace phosphor::logging;
Jayanth Othayoth5d5eb312021-11-15 01:54:07 -060034using namespace openpower::phal::exception;
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -050035using Severity = sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level;
Brad Bishopf6783cd2020-10-27 19:25:09 -040036
37/**
38 * Used to pass buffer to pdbg callback api to get required target
39 * data (attributes) based on given data (attribute).
40 */
41struct TargetInfo
42{
43 ATTR_PHYS_BIN_PATH_Type physBinPath;
44 ATTR_LOCATION_CODE_Type locationCode;
45 ATTR_PHYS_DEV_PATH_Type physDevPath;
46 ATTR_MRU_ID_Type mruId;
47
48 bool deconfigure;
49
50 TargetInfo()
51 {
52 memset(&physBinPath, '\0', sizeof(physBinPath));
53 memset(&locationCode, '\0', sizeof(locationCode));
54 memset(&physDevPath, '\0', sizeof(physDevPath));
55 mruId = 0;
56 deconfigure = false;
57 }
58};
59
60/**
61 * Used to return in callback function which are used to get
62 * physical path value and it binary format value.
63 *
64 * The value for constexpr defined based on pdbg_target_traverse function usage.
65 */
66constexpr int continueTgtTraversal = 0;
67constexpr int requireAttrFound = 1;
68constexpr int requireAttrNotFound = 2;
69
70/**
71 * @brief Used to get target location code from phal device tree
72 *
73 * @param[in] target current device tree target
74 * @param[out] appPrivData used for accessing|storing from|to application
75 *
76 * @return 0 to continue traverse, non-zero to stop traverse
77 */
78int pdbgCallbackToGetTgtReqAttrsVal(struct pdbg_target* target,
79 void* appPrivData)
80{
Jayanth Othayoth5d5eb312021-11-15 01:54:07 -060081 using namespace openpower::phal::pdbg;
82
Brad Bishopf6783cd2020-10-27 19:25:09 -040083 TargetInfo* targetInfo = static_cast<TargetInfo*>(appPrivData);
84
85 ATTR_PHYS_BIN_PATH_Type physBinPath;
86 /**
87 * TODO: Issue: phal/pdata#16
88 * Should not use direct pdbg api to read attribute. Need to use DT_GET_PROP
89 * macro for bmc app's and this will call libdt-api api but, it will print
90 * "pdbg_target_get_attribute failed" trace if attribute is not found and
91 * this callback will call recursively by using pdbg_target_traverse() until
92 * find expected attribute based on return code from this callback. Because,
93 * need to do target iteration to get actual attribute (ATTR_PHYS_BIN_PATH)
94 * value when device tree target info doesn't know to read attribute from
95 * device tree. So, Due to this error trace user will get confusion while
96 * looking traces. Hence using pdbg api to avoid trace until libdt-api
97 * provides log level setup.
98 */
99 if (!pdbg_target_get_attribute(
100 target, "ATTR_PHYS_BIN_PATH",
101 std::stoi(dtAttr::fapi2::ATTR_PHYS_BIN_PATH_Spec),
102 dtAttr::fapi2::ATTR_PHYS_BIN_PATH_ElementCount, physBinPath))
103 {
104 return continueTgtTraversal;
105 }
106
107 if (std::memcmp(physBinPath, targetInfo->physBinPath,
108 sizeof(physBinPath)) != 0)
109 {
110 return continueTgtTraversal;
111 }
112
Jayanth Othayothde909252021-11-15 02:36:45 -0600113 // Found Target, now collect the required attributes associated to the
114 // target. Incase of any attribute read failure, initialize the data with
115 // default value.
Jayanth Othayoth5d5eb312021-11-15 01:54:07 -0600116 try
Brad Bishopf6783cd2020-10-27 19:25:09 -0400117 {
Jayanth Othayoth5d5eb312021-11-15 01:54:07 -0600118 // Get location code information
119 openpower::phal::pdbg::getLocationCode(target,
120 targetInfo->locationCode);
121 }
122 catch (const std::exception& e)
123 {
Jayanth Othayoth5d5eb312021-11-15 01:54:07 -0600124 log<level::ERR>(fmt::format("getLocationCode({}): Exception({})",
125 pdbg_target_path(target), e.what())
126 .c_str());
Brad Bishopf6783cd2020-10-27 19:25:09 -0400127 }
128
129 if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, target, targetInfo->physDevPath))
130 {
Jayanth Othayothde909252021-11-15 02:36:45 -0600131 log<level::ERR>(
132 fmt::format("Could not read({}) PHYS_DEV_PATH attribute",
133 pdbg_target_path(target))
134 .c_str());
Brad Bishopf6783cd2020-10-27 19:25:09 -0400135 }
136
137 if (DT_GET_PROP(ATTR_MRU_ID, target, targetInfo->mruId))
138 {
Jayanth Othayothde909252021-11-15 02:36:45 -0600139 log<level::ERR>(fmt::format("Could not read({}) ATTR_MRU_ID attribute",
140 pdbg_target_path(target))
141 .c_str());
Brad Bishopf6783cd2020-10-27 19:25:09 -0400142 }
143
Brad Bishopf6783cd2020-10-27 19:25:09 -0400144 return requireAttrFound;
145}
146
147/**
148 * @brief Used to get target info (attributes data)
149 *
150 * To get target required attributes value using another attribute value
151 * ("PHYS_BIN_PATH" which is present in same target attributes list) by using
152 * "ipdbg_target_traverse" api because, here we have attribute value only and
153 * doesn't have respective device tree target info to get required attributes
154 * values from it attributes list.
155 *
156 * @param[in] physBinPath to pass PHYS_BIN_PATH value
157 * @param[out] targetInfo to pas buufer to fill with required attributes
158 *
159 * @return true on success otherwise false
160 */
161bool getTgtReqAttrsVal(const std::vector<uint8_t>& physBinPath,
162 TargetInfo& targetInfo)
163{
164 std::memcpy(&targetInfo.physBinPath, physBinPath.data(),
165 sizeof(targetInfo.physBinPath));
166
167 int ret = pdbg_target_traverse(NULL, pdbgCallbackToGetTgtReqAttrsVal,
168 &targetInfo);
169 if (ret == 0)
170 {
171 log<level::ERR>(fmt::format("Given ATTR_PHYS_BIN_PATH value({}) "
172 "not found in phal device tree",
173 targetInfo.physBinPath)
174 .c_str());
175 return false;
176 }
177 else if (ret == requireAttrNotFound)
178 {
179 return false;
180 }
181
182 return true;
183}
184} // namespace phal
185
186namespace pel
187{
188using namespace phosphor::logging;
189
190namespace detail
191{
192using json = nlohmann::json;
193
194// keys need to be unique so using counter value to generate unique key
195static int counter = 0;
196
197// list of debug traces
198static std::vector<std::pair<std::string, std::string>> traceLog;
199
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600200/**
201 * @brief Process platform realted boot failure
202 *
203 * @param[in] errInfo - error details
204 */
205static void processPlatBootError(const ipl_error_info& errInfo);
206
Brad Bishop63508a72020-10-27 18:55:01 -0400207void processLogTraceCallback(void*, const char* fmt, va_list ap)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400208{
209 va_list vap;
210 va_copy(vap, ap);
211 std::vector<char> logData(1 + std::vsnprintf(nullptr, 0, fmt, ap));
212 std::vsnprintf(logData.data(), logData.size(), fmt, vap);
213 va_end(vap);
214 std::string logstr(logData.begin(), logData.end());
215
216 log<level::INFO>(logstr.c_str());
217
218 char timeBuf[80];
219 time_t t = time(0);
220 tm myTm{};
221 gmtime_r(&t, &myTm);
222 strftime(timeBuf, 80, "%Y-%m-%d %H:%M:%S", &myTm);
223
224 // key values need to be unique for PEL
225 // TODO #openbmc/dev/issues/1563
226 // If written to Json no need to worry about unique KEY
227 std::stringstream str;
228 str << std::setfill('0');
229 str << "LOG" << std::setw(3) << counter;
230 str << " " << timeBuf;
231 traceLog.emplace_back(std::make_pair(str.str(), std::move(logstr)));
232 counter++;
233}
234
235/**
236 * @brief GET PEL priority from pHAL priority
237 *
238 * The pHAL callout priority is in different format than PEL format
239 * so, this api is used to return current phal supported priority into
240 * PEL expected format.
241 *
242 * @param[in] phalPriority used to pass phal priority format string
243 *
244 * @return pel priority format string else empty if failure
245 *
246 * @note For "NONE" returning "L" (LOW)
247 */
248static std::string getPelPriority(const std::string& phalPriority)
249{
250 const std::map<std::string, std::string> priorityMap = {
251 {"HIGH", "H"}, {"MEDIUM", "M"}, {"LOW", "L"}, {"NONE", "L"}};
252
253 auto it = priorityMap.find(phalPriority);
254 if (it == priorityMap.end())
255 {
256 log<level::ERR>(fmt::format("Unsupported phal priority({}) is given "
257 "to get pel priority format",
258 phalPriority)
259 .c_str());
260 return "H";
261 }
262
263 return it->second;
264}
265
Jayanth Othayoth69708fb2022-03-22 04:49:01 -0500266/**
267 * @brief Helper function to create PEL for non functional boot
268 * processor related failure.
269 * This function adds the BMC code callout as priority 1 to fix
270 * devtree related software issue. Incase the issue still persist
271 * after reboot recommend to replacing the primary processor.
272 */
273void processNonFunctionalBootProc()
274{
275 json jsonCalloutDataList;
276 json jsonProcedCallout;
277 // Add BMC code callout
278 jsonProcedCallout["Procedure"] = "BMC0001";
279 jsonProcedCallout["Priority"] = "H";
280 jsonCalloutDataList.emplace_back(std::move(jsonProcedCallout));
281
282 // get primary processor
283 struct pdbg_target* procTarget;
284 pdbg_for_each_class_target("proc", procTarget)
285 {
286 if (openpower::phal::isPrimaryProc(procTarget))
287 break;
288 procTarget = nullptr;
289 }
290 // check valid primary processor is available
291 if (procTarget == nullptr)
292 {
293 log<level::ERR>(
294 "processNonFunctionalBootProc: fail to get primary processor");
295 }
296 else
297 {
298 try
299 {
300 ATTR_LOCATION_CODE_Type locationCode = {'\0'};
301 // Get location code information
302 openpower::phal::pdbg::getLocationCode(procTarget, locationCode);
303 json jsonProcCallout;
304 jsonProcCallout["LocationCode"] = locationCode;
305 jsonProcCallout["Deconfigured"] = false;
306 jsonProcCallout["Guarded"] = false;
307 jsonProcCallout["Priority"] = "M";
308 jsonCalloutDataList.emplace_back(std::move(jsonProcCallout));
309 }
310 catch (const std::exception& e)
311 {
312 log<level::ERR>(fmt::format("getLocationCode({}): Exception({})",
313 pdbg_target_path(procTarget), e.what())
314 .c_str());
315 }
316 }
317 // Adding collected phal logs into PEL additional data
318 FFDCData pelAdditionalData;
319 for_each(
320 traceLog.begin(), traceLog.end(),
321 [&pelAdditionalData](std::pair<std::string, std::string>& ele) -> void {
322 pelAdditionalData.emplace_back(ele.first, ele.second);
323 });
324 openpower::pel::createErrorPEL(
325 "org.open_power.PHAL.Error.NonFunctionalBootProc", jsonCalloutDataList,
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500326 pelAdditionalData, Severity::Error);
Jayanth Othayoth69708fb2022-03-22 04:49:01 -0500327 // reset trace log and exit
328 reset();
329}
330
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500331void processIplErrorCallback(const ipl_error_info& errInfo)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400332{
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500333 log<level::INFO>(
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500334 fmt::format("processIplErrorCallback: Error type({})", errInfo.type)
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500335 .c_str());
336
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600337 switch (errInfo.type)
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500338 {
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600339 case IPL_ERR_OK:
340 // reset trace log and exit
341 reset();
342 break;
343 case IPL_ERR_SBE_BOOT:
344 case IPL_ERR_SBE_CHIPOP:
345 // handle SBE related failures.
346 processSbeBootError();
347 break;
348 case IPL_ERR_HWP:
349 // Handle hwp failure
350 processBootError(false);
351 break;
352 case IPL_ERR_PLAT:
353 processPlatBootError(errInfo);
354 break;
Jayanth Othayoth69708fb2022-03-22 04:49:01 -0500355 case IPL_ERR_PRI_PROC_NON_FUNC:
356 // Handle non functional boot processor error.
357 processNonFunctionalBootProc();
358 break;
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600359 default:
360 createPEL("org.open_power.PHAL.Error.Boot");
361 // reset trace log and exit
362 reset();
363 break;
Jayanth Othayothfaaef2a2021-10-08 06:49:36 -0500364 }
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500365}
366
rajerpp1db924722021-11-30 11:00:05 -0600367/**
368 * @brief addPlanarCallout
369 *
370 * This function will add a json for planar callout in the input json list.
371 * The caller can pass this json list into createErrorPEL to apply the callout.
372 *
373 * @param[in,out] jsonCalloutDataList - json list where callout json will be
374 * emplaced
375 * @param[in] priority - string indicating priority.
376 */
377static void addPlanarCallout(json& jsonCalloutDataList,
378 const std::string& priority)
379{
380 json jsonCalloutData;
381
382 // Inventory path for planar
383 jsonCalloutData["InventoryPath"] =
384 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
385 jsonCalloutData["Deconfigured"] = false;
386 jsonCalloutData["Guarded"] = false;
387 jsonCalloutData["Priority"] = priority;
388
389 jsonCalloutDataList.emplace_back(jsonCalloutData);
390}
391
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500392/**
393 * @brief processPoweroffError
394 *
395 * Creates informational PEL for the PLAT/HWP error occured during poweroff
396 *
397 * Not adding callouts from FFDC as the hardware errors in the poweroff path
398 * should be non-visible. so that we don't throw out extraneous callouts for
399 * power errors or because the CEC is just not in an expected state.
400 *
401 * @param[in] ffdc - FFDC data capturd by the HWP
402 * @param[in] ffdc_prefix - prefix string for logging the data.
403 */
404
405void processPoweroffError(FFDC* ffdc, const std::string& ffdc_prefix)
406{
407 try
408 {
409 log<level::INFO>(
410 fmt::format("processPoweroffError: Message[{}]", ffdc->message)
411 .c_str());
412
413 // To store phal trace and other additional data about ffdc.
414 FFDCData pelAdditionalData;
415
416 if (ffdc->ffdc_type == FFDC_TYPE_HWP)
417 {
418 std::string keyWithPrefix(ffdc_prefix + "RC");
419 // Adding hardware procedures return code details
420 pelAdditionalData.emplace_back(keyWithPrefix,
421 ffdc->hwp_errorinfo.rc);
422 keyWithPrefix = ffdc_prefix + "RC_DESC";
423 pelAdditionalData.emplace_back(keyWithPrefix,
424 ffdc->hwp_errorinfo.rc_desc);
425 }
426 else if ((ffdc->ffdc_type != FFDC_TYPE_NONE) &&
427 (ffdc->ffdc_type != FFDC_TYPE_UNSUPPORTED))
428 {
429 log<level::ERR>(
430 fmt::format("Unsupported phal FFDC type to create PEL. "
431 "MSG: {}",
432 ffdc->message)
433 .c_str());
434 }
435
436 // Adding collected phal logs into PEL additional data
437 for_each(traceLog.begin(), traceLog.end(),
438 [&pelAdditionalData](
439 std::pair<std::string, std::string>& ele) -> void {
440 pelAdditionalData.emplace_back(ele.first, ele.second);
441 });
442
443 openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot", {},
444 pelAdditionalData,
445 Severity::Informational);
446 }
447 catch (const std::exception& ex)
448 {
449 reset();
450 throw ex;
451 }
452 reset();
453}
454
rajerpp1db924722021-11-30 11:00:05 -0600455void processBootErrorHelper(FFDC* ffdc, const std::string& ffdc_prefix)
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500456{
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600457 log<level::INFO>("processBootErrorHelper ");
Brad Bishopf6783cd2020-10-27 19:25:09 -0400458 try
459 {
Ramesh Iyyar3af83eb2020-11-19 23:11:38 -0600460 log<level::INFO>(
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600461 fmt::format("PHAL FFDC: Return Message[{}]", ffdc->message)
462 .c_str());
Brad Bishopf6783cd2020-10-27 19:25:09 -0400463
464 // To store callouts details in json format as per pel expectation.
465 json jsonCalloutDataList;
466 jsonCalloutDataList = json::array();
467
468 // To store phal trace and other additional data about ffdc.
469 FFDCData pelAdditionalData;
470
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600471 if (ffdc->ffdc_type == FFDC_TYPE_HWP)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400472 {
rajerpp1db924722021-11-30 11:00:05 -0600473 std::string keyWithPrefix(ffdc_prefix + "RC");
Brad Bishopf6783cd2020-10-27 19:25:09 -0400474 // Adding hardware procedures return code details
rajerpp1db924722021-11-30 11:00:05 -0600475 pelAdditionalData.emplace_back(keyWithPrefix,
476 ffdc->hwp_errorinfo.rc);
477 keyWithPrefix = ffdc_prefix + "RC_DESC";
478 pelAdditionalData.emplace_back(keyWithPrefix,
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600479 ffdc->hwp_errorinfo.rc_desc);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400480
481 // Adding hardware procedures required ffdc data for debug
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600482 for_each(ffdc->hwp_errorinfo.ffdcs_data.begin(),
483 ffdc->hwp_errorinfo.ffdcs_data.end(),
rajerpp1db924722021-11-30 11:00:05 -0600484 [&pelAdditionalData, &ffdc_prefix](
Brad Bishopf6783cd2020-10-27 19:25:09 -0400485 std::pair<std::string, std::string>& ele) -> void {
rajerpp1db924722021-11-30 11:00:05 -0600486 std::string keyWithPrefix(ffdc_prefix + "FFDC_");
Brad Bishopf6783cd2020-10-27 19:25:09 -0400487 keyWithPrefix.append(ele.first);
488
489 pelAdditionalData.emplace_back(keyWithPrefix,
490 ele.second);
491 });
492
493 // Adding hardware callout details
494 int calloutCount = 0;
rajerpp1db924722021-11-30 11:00:05 -0600495 for_each(
496 ffdc->hwp_errorinfo.hwcallouts.begin(),
497 ffdc->hwp_errorinfo.hwcallouts.end(),
498 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
499 &ffdc_prefix](const HWCallout& hwCallout) -> void {
500 calloutCount++;
501 std::stringstream keyPrefix;
502 keyPrefix << ffdc_prefix << "HW_CO_" << std::setfill('0')
503 << std::setw(2) << calloutCount << "_";
Brad Bishopf6783cd2020-10-27 19:25:09 -0400504
rajerpp1db924722021-11-30 11:00:05 -0600505 pelAdditionalData.emplace_back(
506 std::string(keyPrefix.str()).append("HW_ID"),
507 hwCallout.hwid);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400508
rajerpp1db924722021-11-30 11:00:05 -0600509 pelAdditionalData.emplace_back(
510 std::string(keyPrefix.str()).append("PRIORITY"),
511 hwCallout.callout_priority);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400512
rajerpp1db924722021-11-30 11:00:05 -0600513 // Log target details only if entity path is
514 // available. For example target entity path will not
515 // be available for non-hwp clock failure.
516 if (!hwCallout.target_entity_path.empty())
517 {
518 phal::TargetInfo targetInfo;
519 phal::getTgtReqAttrsVal(hwCallout.target_entity_path,
520 targetInfo);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400521
rajerpp1db924722021-11-30 11:00:05 -0600522 std::string locationCode =
523 std::string(targetInfo.locationCode);
524 pelAdditionalData.emplace_back(
525 std::string(keyPrefix.str()).append("LOC_CODE"),
526 locationCode);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400527
rajerpp1db924722021-11-30 11:00:05 -0600528 std::string physPath =
529 std::string(targetInfo.physDevPath);
530 pelAdditionalData.emplace_back(
531 std::string(keyPrefix.str()).append("PHYS_PATH"),
532 physPath);
533 }
Brad Bishopf6783cd2020-10-27 19:25:09 -0400534
rajerpp1db924722021-11-30 11:00:05 -0600535 pelAdditionalData.emplace_back(
536 std::string(keyPrefix.str()).append("CLK_POS"),
537 std::to_string(hwCallout.clkPos));
538
539 pelAdditionalData.emplace_back(
540 std::string(keyPrefix.str()).append("CALLOUT_PLANAR"),
541 (hwCallout.isPlanarCallout == true ? "true" : "false"));
542
543 std::string pelPriority =
544 getPelPriority(hwCallout.callout_priority);
545
546 if (hwCallout.isPlanarCallout)
547 {
548 addPlanarCallout(jsonCalloutDataList, pelPriority);
549 }
550 });
Brad Bishopf6783cd2020-10-27 19:25:09 -0400551
552 // Adding CDG (callout, deconfigure and guard) targets details
553 calloutCount = 0;
rajerpp1db924722021-11-30 11:00:05 -0600554 for_each(
555 ffdc->hwp_errorinfo.cdg_targets.begin(),
556 ffdc->hwp_errorinfo.cdg_targets.end(),
557 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
558 &ffdc_prefix](const CDG_Target& cdg_tgt) -> void {
559 calloutCount++;
560 std::stringstream keyPrefix;
561 keyPrefix << ffdc_prefix << "CDG_TGT_" << std::setfill('0')
562 << std::setw(2) << calloutCount << "_";
Brad Bishopf6783cd2020-10-27 19:25:09 -0400563
rajerpp1db924722021-11-30 11:00:05 -0600564 phal::TargetInfo targetInfo;
565 targetInfo.deconfigure = cdg_tgt.deconfigure;
Brad Bishopf6783cd2020-10-27 19:25:09 -0400566
rajerpp1db924722021-11-30 11:00:05 -0600567 phal::getTgtReqAttrsVal(cdg_tgt.target_entity_path,
568 targetInfo);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400569
rajerpp1db924722021-11-30 11:00:05 -0600570 std::string locationCode =
571 std::string(targetInfo.locationCode);
572 pelAdditionalData.emplace_back(
573 std::string(keyPrefix.str()).append("LOC_CODE"),
574 locationCode);
575 std::string physPath = std::string(targetInfo.physDevPath);
576 pelAdditionalData.emplace_back(
577 std::string(keyPrefix.str()).append("PHYS_PATH"),
578 physPath);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400579
rajerpp1db924722021-11-30 11:00:05 -0600580 pelAdditionalData.emplace_back(
581 std::string(keyPrefix.str()).append("CO_REQ"),
582 (cdg_tgt.callout == true ? "true" : "false"));
Brad Bishopf6783cd2020-10-27 19:25:09 -0400583
rajerpp1db924722021-11-30 11:00:05 -0600584 pelAdditionalData.emplace_back(
585 std::string(keyPrefix.str()).append("CO_PRIORITY"),
586 cdg_tgt.callout_priority);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400587
rajerpp1db924722021-11-30 11:00:05 -0600588 pelAdditionalData.emplace_back(
589 std::string(keyPrefix.str()).append("DECONF_REQ"),
590 (cdg_tgt.deconfigure == true ? "true" : "false"));
Brad Bishopf6783cd2020-10-27 19:25:09 -0400591
rajerpp1db924722021-11-30 11:00:05 -0600592 pelAdditionalData.emplace_back(
593 std::string(keyPrefix.str()).append("GUARD_REQ"),
594 (cdg_tgt.guard == true ? "true" : "false"));
Brad Bishopf6783cd2020-10-27 19:25:09 -0400595
rajerpp1db924722021-11-30 11:00:05 -0600596 pelAdditionalData.emplace_back(
597 std::string(keyPrefix.str()).append("GUARD_TYPE"),
598 cdg_tgt.guard_type);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400599
rajerpp1db924722021-11-30 11:00:05 -0600600 json jsonCalloutData;
601 jsonCalloutData["LocationCode"] = locationCode;
602 std::string pelPriority =
603 getPelPriority(cdg_tgt.callout_priority);
604 jsonCalloutData["Priority"] = pelPriority;
Brad Bishopf6783cd2020-10-27 19:25:09 -0400605
rajerpp1db924722021-11-30 11:00:05 -0600606 if (targetInfo.mruId != 0)
607 {
608 jsonCalloutData["MRUs"] = json::array({
609 {{"ID", targetInfo.mruId},
610 {"Priority", pelPriority}},
611 });
612 }
613 jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
614 jsonCalloutData["Guarded"] = cdg_tgt.guard;
615 jsonCalloutData["GuardType"] = cdg_tgt.guard_type;
616 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
Brad Bishopf6783cd2020-10-27 19:25:09 -0400617
rajerpp1db924722021-11-30 11:00:05 -0600618 jsonCalloutDataList.emplace_back(jsonCalloutData);
619 });
Jayanth Othayoth0ac7c382021-11-15 05:43:24 -0600620 // Adding procedure callout
621 calloutCount = 0;
622 for_each(
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600623 ffdc->hwp_errorinfo.procedures_callout.begin(),
624 ffdc->hwp_errorinfo.procedures_callout.end(),
rajerpp1db924722021-11-30 11:00:05 -0600625 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
626 &ffdc_prefix](const ProcedureCallout& procCallout) -> void {
Jayanth Othayoth0ac7c382021-11-15 05:43:24 -0600627 calloutCount++;
628 std::stringstream keyPrefix;
rajerpp1db924722021-11-30 11:00:05 -0600629 keyPrefix << ffdc_prefix << "PROC_CO_" << std::setfill('0')
Jayanth Othayoth0ac7c382021-11-15 05:43:24 -0600630 << std::setw(2) << calloutCount << "_";
631
632 pelAdditionalData.emplace_back(
633 std::string(keyPrefix.str()).append("PRIORITY"),
634 procCallout.callout_priority);
635
636 pelAdditionalData.emplace_back(
637 std::string(keyPrefix.str()).append("MAINT_PROCEDURE"),
638 procCallout.proc_callout);
639
640 json jsonCalloutData;
641 jsonCalloutData["Procedure"] = procCallout.proc_callout;
642 std::string pelPriority =
643 getPelPriority(procCallout.callout_priority);
644 jsonCalloutData["Priority"] = pelPriority;
645 jsonCalloutDataList.emplace_back(jsonCalloutData);
646 });
Brad Bishopf6783cd2020-10-27 19:25:09 -0400647 }
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600648 else if ((ffdc->ffdc_type != FFDC_TYPE_NONE) &&
649 (ffdc->ffdc_type != FFDC_TYPE_UNSUPPORTED))
Brad Bishopf6783cd2020-10-27 19:25:09 -0400650 {
651 log<level::ERR>(
652 fmt::format("Unsupported phal FFDC type to create PEL. "
653 "MSG: {}",
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600654 ffdc->message)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400655 .c_str());
656 }
657
658 // Adding collected phal logs into PEL additional data
659 for_each(traceLog.begin(), traceLog.end(),
660 [&pelAdditionalData](
661 std::pair<std::string, std::string>& ele) -> void {
662 pelAdditionalData.emplace_back(ele.first, ele.second);
663 });
664
665 // TODO: #ibm-openbmc/dev/issues/2595 : Once enabled this support,
666 // callout details is not required to sort in H,M and L orders which
667 // are expected by pel because, pel will take care for sorting callouts
668 // based on priority so, now adding support to send callout in order
669 // i.e High -> Medium -> Low.
670 std::sort(
671 jsonCalloutDataList.begin(), jsonCalloutDataList.end(),
672 [](const json& aEle, const json& bEle) -> bool {
673 // Considering b element having higher priority than a element
674 // or Both element will be same priorty (to keep same order
675 // which are given by phal when two callouts are having same
676 // priority)
677 if (((aEle["Priority"] == "M") && (bEle["Priority"] == "H")) ||
678 ((aEle["Priority"] == "L") &&
679 ((bEle["Priority"] == "H") ||
680 (bEle["Priority"] == "M"))) ||
681 (aEle["Priority"] == bEle["Priority"]))
682 {
683 return false;
684 }
685
686 // Considering a element having higher priority than b element
687 return true;
688 });
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -0600689 openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot",
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500690 jsonCalloutDataList, pelAdditionalData,
691 Severity::Error);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400692 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500693 catch (const std::exception& ex)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400694 {
695 reset();
696 throw ex;
697 }
698 reset();
699}
700
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600701void processPlatBootError(const ipl_error_info& errInfo)
702{
703 log<level::INFO>("processPlatBootError ");
704
705 // Collecting ffdc details from phal
706 FFDC* ffdc = reinterpret_cast<FFDC*>(errInfo.private_data);
707 try
708 {
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500709 if (util::isHostPoweringOff())
710 {
711 processPoweroffError(ffdc, "PLAT_");
712 }
713 else
714 {
715 processBootErrorHelper(ffdc, "PLAT_");
716 }
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600717 }
718 catch (const std::exception& ex)
719 {
720 log<level::ERR>(
721 fmt::format("processPlatBootError: exception({})", ex.what())
722 .c_str());
723 throw ex;
724 }
725}
726
727void processBootError(bool status)
728{
729 log<level::INFO>(
730 fmt::format("processBootError: status({})", status).c_str());
731
732 try
733 {
734 // return If no failure during hwp execution
735 if (status)
736 return;
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600737 // Collecting ffdc details from phal
738 FFDC ffdc;
739 libekb_get_ffdc(ffdc);
740
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500741 if (util::isHostPoweringOff())
742 {
743 processPoweroffError(&ffdc, "HWP_");
744 }
745 else
746 {
747 processBootErrorHelper(&ffdc, "HWP_");
748 }
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600749 }
750 catch (const std::exception& ex)
751 {
752 log<level::ERR>(
753 fmt::format("processBootError: exception({})", ex.what()).c_str());
754 throw ex;
755 }
756}
757
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500758void processSbeBootError()
759{
760 log<level::INFO>("processSbeBootError : Entered ");
761
762 using namespace openpower::phal::sbe;
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500763
764 // To store phal trace and other additional data about ffdc.
765 FFDCData pelAdditionalData;
766
767 // Adding collected phal logs into PEL additional data
768 for_each(
769 traceLog.begin(), traceLog.end(),
770 [&pelAdditionalData](std::pair<std::string, std::string>& ele) -> void {
771 pelAdditionalData.emplace_back(ele.first, ele.second);
772 });
773
774 // reset the trace log and counter
775 reset();
776
777 // get primary processor to collect FFDC/Dump information.
778 struct pdbg_target* procTarget;
779 pdbg_for_each_class_target("proc", procTarget)
780 {
781 if (openpower::phal::isPrimaryProc(procTarget))
782 break;
783 procTarget = nullptr;
784 }
785 // check valid primary processor is available
786 if (procTarget == nullptr)
787 {
788 log<level::ERR>("processSbeBootError: fail to get primary processor");
Jayanth Othayoth0a516de2021-11-14 09:59:06 -0600789 // Add BMC code callout and create PEL
790 json jsonCalloutDataList;
791 jsonCalloutDataList = json::array();
792 json jsonCalloutData;
793 jsonCalloutData["Procedure"] = "BMC0001";
794 jsonCalloutData["Priority"] = "H";
795 jsonCalloutDataList.emplace_back(jsonCalloutData);
796 openpower::pel::createErrorPEL(
797 "org.open_power.Processor.Error.SbeBootFailure",
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500798 jsonCalloutDataList, {}, Severity::Error);
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500799 return;
800 }
801 // SBE error object.
802 sbeError_t sbeError;
803 bool dumpIsRequired = false;
804
805 try
806 {
807 // Capture FFDC information on primary processor
808 sbeError = captureFFDC(procTarget);
809 }
Jayanth Othayothfaaef2a2021-10-08 06:49:36 -0500810 catch (const phalError_t& phalError)
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500811 {
812 // Fail to collect FFDC information , trigger Dump
813 log<level::ERR>(
Jayanth Othayothfaaef2a2021-10-08 06:49:36 -0500814 fmt::format("captureFFDC: Exception({})", phalError.what())
815 .c_str());
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500816 dumpIsRequired = true;
817 }
818
Jayanth Othayoth006641e2021-10-07 06:56:24 -0500819 std::string event;
820
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500821 if ((sbeError.errType() == SBE_FFDC_NO_DATA) ||
822 (sbeError.errType() == SBE_CMD_TIMEOUT) || (dumpIsRequired))
823 {
Jayanth Othayoth006641e2021-10-07 06:56:24 -0500824 event = "org.open_power.Processor.Error.SbeBootTimeout";
825 dumpIsRequired = true;
826 }
827 else
828 {
829 event = "org.open_power.Processor.Error.SbeBootFailure";
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500830 }
831 // SRC6 : [0:15] chip position
Jayanth Othayoth006641e2021-10-07 06:56:24 -0500832 uint32_t index = pdbg_target_index(procTarget);
833 pelAdditionalData.emplace_back("SRC6", std::to_string(index << 16));
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500834 // Create SBE Error with FFDC data.
Jayanth Othayothe5ba5fd2022-01-27 09:29:01 -0600835 auto logId =
836 createSbeErrorPEL(event, sbeError, pelAdditionalData, procTarget);
Jayanth Othayoth006641e2021-10-07 06:56:24 -0500837
838 if (dumpIsRequired)
839 {
840 using namespace openpower::phal::dump;
841 DumpParameters dumpParameters = {logId, index, SBE_DUMP_TIMEOUT,
842 DumpType::SBE};
843 try
844 {
845 requestDump(dumpParameters);
846 }
847 catch (const std::runtime_error& e)
848 {
849 // Allowing call back to handle the error gracefully.
850 log<level::ERR>("Dump collection failed");
851 // TODO revist error handling.
852 }
853 }
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500854}
855
Brad Bishopf6783cd2020-10-27 19:25:09 -0400856void reset()
857{
858 // reset the trace log and counter
859 traceLog.clear();
860 counter = 0;
861}
862
Brad Bishop63508a72020-10-27 18:55:01 -0400863void pDBGLogTraceCallbackHelper(int, const char* fmt, va_list ap)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400864{
865 processLogTraceCallback(NULL, fmt, ap);
866}
867} // namespace detail
868
869static inline uint8_t getLogLevelFromEnv(const char* env, const uint8_t dValue)
870{
871 auto logLevel = dValue;
872 try
873 {
874 if (const char* env_p = std::getenv(env))
875 {
876 logLevel = std::stoi(env_p);
877 }
878 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500879 catch (const std::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400880 {
881 log<level::ERR>(("Conversion Failure"), entry("ENVIRONMENT=%s", env),
882 entry("EXCEPTION=%s", e.what()));
883 }
884 return logLevel;
885}
886
887void addBootErrorCallbacks()
888{
889 // Get individual phal repos log level from environment variable
890 // and update the log level.
891 pdbg_set_loglevel(getLogLevelFromEnv("PDBG_LOG", PDBG_INFO));
892 libekb_set_loglevel(getLogLevelFromEnv("LIBEKB_LOG", LIBEKB_LOG_IMP));
893 ipl_set_loglevel(getLogLevelFromEnv("IPL_LOG", IPL_INFO));
894
895 // add callback for debug traces
896 pdbg_set_logfunc(detail::pDBGLogTraceCallbackHelper);
897 libekb_set_logfunc(detail::processLogTraceCallback, NULL);
898 ipl_set_logfunc(detail::processLogTraceCallback, NULL);
899
900 // add callback for ipl failures
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500901 ipl_set_error_callback_func(detail::processIplErrorCallback);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400902}
903
904} // namespace pel
905} // namespace openpower