blob: 4cbf5af80dcef2a223955bd10b9899ea8a964612 [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 {
deepakala-kcf41cdc2022-11-17 05:25:47 -0600171 log<level::ERR>(fmt::format("Given ATTR_PHYS_BIN_PATH value({:02x}) "
Brad Bishopf6783cd2020-10-27 19:25:09 -0400172 "not found in phal device tree",
deepakala-kcf41cdc2022-11-17 05:25:47 -0600173 fmt::join(targetInfo.physBinPath, ""))
Brad Bishopf6783cd2020-10-27 19:25:09 -0400174 .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 Othayothd8be1eb2022-06-28 07:33:06 -0500331/**
332 * @brief processClockInfoErrorHelper
333 *
334 * Creates informational PEL for spare clock failure
335 *
336 * @param[in] ffdc - FFDC data capturd by the HWP
337 * @param[in] ffdc_prefix - prefix string for logging the data.
338 */
339void processClockInfoErrorHelper(FFDC* ffdc, const std::string& ffdc_prefix)
340{
341 try
342 {
343 log<level::INFO>(
344 fmt::format("processClockInfoErrorHelper: FFDC Message[{}]",
345 ffdc->message)
346 .c_str());
347
348 // To store callouts details in json format as per pel expectation.
349 json jsonCalloutDataList;
350 jsonCalloutDataList = json::array();
351
352 // To store phal trace and other additional data about ffdc.
353 FFDCData pelAdditionalData;
354
355 std::string keyWithPrefix(ffdc_prefix + "RC");
356 // Adding hardware procedures return code details
357 pelAdditionalData.emplace_back(keyWithPrefix, ffdc->hwp_errorinfo.rc);
358 keyWithPrefix = ffdc_prefix + "RC_DESC";
359 pelAdditionalData.emplace_back(keyWithPrefix,
360 ffdc->hwp_errorinfo.rc_desc);
361
362 // Adding hardware procedures required ffdc data for debug
363 for_each(ffdc->hwp_errorinfo.ffdcs_data.begin(),
364 ffdc->hwp_errorinfo.ffdcs_data.end(),
365 [&pelAdditionalData, &ffdc_prefix](
366 std::pair<std::string, std::string>& ele) -> void {
367 std::string keyWithPrefix(ffdc_prefix + "FFDC_");
368 keyWithPrefix.append(ele.first);
369
370 pelAdditionalData.emplace_back(keyWithPrefix, ele.second);
371 });
372 // get clock position information
373 auto clk_pos = 0xFF; // Invalid position.
374 for (auto& hwCallout : ffdc->hwp_errorinfo.hwcallouts)
375 {
376 if ((hwCallout.hwid == "PROC_REF_CLOCK") ||
377 (hwCallout.hwid == "PCI_REF_CLOCK"))
378 {
379 clk_pos = hwCallout.clkPos;
380 break;
381 }
382 }
383
384 // Adding CDG (Only deconfigure) targets details
385 for_each(ffdc->hwp_errorinfo.cdg_targets.begin(),
386 ffdc->hwp_errorinfo.cdg_targets.end(),
387 [&pelAdditionalData, &jsonCalloutDataList,
388 clk_pos](const CDG_Target& cdg_tgt) -> void {
389 json jsonCalloutData;
Jayanth Othayothfe2abd12022-10-28 00:22:10 -0500390 std::string pelPriority = "L";
Jayanth Othayothd8be1eb2022-06-28 07:33:06 -0500391 jsonCalloutData["Priority"] = pelPriority; // Not used
Patrick Williams00dd33e2023-05-10 07:50:37 -0500392 jsonCalloutData["SymbolicFRU"] = "REFCLK" +
393 std::to_string(clk_pos);
Jayanth Othayothd8be1eb2022-06-28 07:33:06 -0500394 jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
395 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
396 jsonCalloutDataList.emplace_back(jsonCalloutData);
397 });
398
399 // Adding collected phal logs into PEL additional data
400 for_each(traceLog.begin(), traceLog.end(),
401 [&pelAdditionalData](
402 std::pair<std::string, std::string>& ele) -> void {
403 pelAdditionalData.emplace_back(ele.first, ele.second);
404 });
405
406 openpower::pel::createErrorPEL("org.open_power.PHAL.Error.SpareClock",
407 jsonCalloutDataList, pelAdditionalData,
408 Severity::Informational);
409 }
410 catch (const std::exception& ex)
411 {
412 reset();
413 throw ex;
414 }
415 reset();
416}
417
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500418void processIplErrorCallback(const ipl_error_info& errInfo)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400419{
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500420 log<level::INFO>(
ojayanthcb23cb22023-06-08 07:13:37 -0500421 fmt::format("processIplErrorCallback: Error type({})",
422 static_cast<std::underlying_type<ipl_error_type>::type>(
423 errInfo.type))
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500424 .c_str());
425
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600426 switch (errInfo.type)
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500427 {
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600428 case IPL_ERR_OK:
429 // reset trace log and exit
430 reset();
431 break;
432 case IPL_ERR_SBE_BOOT:
433 case IPL_ERR_SBE_CHIPOP:
434 // handle SBE related failures.
435 processSbeBootError();
436 break;
437 case IPL_ERR_HWP:
438 // Handle hwp failure
439 processBootError(false);
440 break;
441 case IPL_ERR_PLAT:
442 processPlatBootError(errInfo);
443 break;
Jayanth Othayoth69708fb2022-03-22 04:49:01 -0500444 case IPL_ERR_PRI_PROC_NON_FUNC:
445 // Handle non functional boot processor error.
446 processNonFunctionalBootProc();
447 break;
deepakala-k9f351b02022-10-05 09:03:57 -0500448 case IPL_ERR_GUARD_PARTITION_ACCESS:
449 processGuardPartitionAccessError();
450 break;
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600451 default:
452 createPEL("org.open_power.PHAL.Error.Boot");
453 // reset trace log and exit
454 reset();
455 break;
Jayanth Othayothfaaef2a2021-10-08 06:49:36 -0500456 }
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500457}
458
rajerpp1db924722021-11-30 11:00:05 -0600459/**
460 * @brief addPlanarCallout
461 *
462 * This function will add a json for planar callout in the input json list.
463 * The caller can pass this json list into createErrorPEL to apply the callout.
464 *
465 * @param[in,out] jsonCalloutDataList - json list where callout json will be
466 * emplaced
467 * @param[in] priority - string indicating priority.
468 */
469static void addPlanarCallout(json& jsonCalloutDataList,
470 const std::string& priority)
471{
472 json jsonCalloutData;
473
474 // Inventory path for planar
475 jsonCalloutData["InventoryPath"] =
476 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
477 jsonCalloutData["Deconfigured"] = false;
478 jsonCalloutData["Guarded"] = false;
479 jsonCalloutData["Priority"] = priority;
480
481 jsonCalloutDataList.emplace_back(jsonCalloutData);
482}
483
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500484/**
485 * @brief processPoweroffError
486 *
487 * Creates informational PEL for the PLAT/HWP error occured during poweroff
488 *
489 * Not adding callouts from FFDC as the hardware errors in the poweroff path
490 * should be non-visible. so that we don't throw out extraneous callouts for
491 * power errors or because the CEC is just not in an expected state.
492 *
493 * @param[in] ffdc - FFDC data capturd by the HWP
494 * @param[in] ffdc_prefix - prefix string for logging the data.
495 */
496
497void processPoweroffError(FFDC* ffdc, const std::string& ffdc_prefix)
498{
499 try
500 {
501 log<level::INFO>(
502 fmt::format("processPoweroffError: Message[{}]", ffdc->message)
503 .c_str());
504
505 // To store phal trace and other additional data about ffdc.
506 FFDCData pelAdditionalData;
507
508 if (ffdc->ffdc_type == FFDC_TYPE_HWP)
509 {
510 std::string keyWithPrefix(ffdc_prefix + "RC");
511 // Adding hardware procedures return code details
512 pelAdditionalData.emplace_back(keyWithPrefix,
513 ffdc->hwp_errorinfo.rc);
514 keyWithPrefix = ffdc_prefix + "RC_DESC";
515 pelAdditionalData.emplace_back(keyWithPrefix,
516 ffdc->hwp_errorinfo.rc_desc);
517 }
518 else if ((ffdc->ffdc_type != FFDC_TYPE_NONE) &&
519 (ffdc->ffdc_type != FFDC_TYPE_UNSUPPORTED))
520 {
521 log<level::ERR>(
522 fmt::format("Unsupported phal FFDC type to create PEL. "
523 "MSG: {}",
524 ffdc->message)
525 .c_str());
526 }
527
528 // Adding collected phal logs into PEL additional data
529 for_each(traceLog.begin(), traceLog.end(),
530 [&pelAdditionalData](
531 std::pair<std::string, std::string>& ele) -> void {
532 pelAdditionalData.emplace_back(ele.first, ele.second);
533 });
534
535 openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot", {},
536 pelAdditionalData,
537 Severity::Informational);
538 }
539 catch (const std::exception& ex)
540 {
541 reset();
542 throw ex;
543 }
544 reset();
545}
546
rajerpp1db924722021-11-30 11:00:05 -0600547void processBootErrorHelper(FFDC* ffdc, const std::string& ffdc_prefix)
Jayanth Othayoth2b211702021-09-06 05:14:23 -0500548{
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600549 log<level::INFO>("processBootErrorHelper ");
Brad Bishopf6783cd2020-10-27 19:25:09 -0400550 try
551 {
Ramesh Iyyar3af83eb2020-11-19 23:11:38 -0600552 log<level::INFO>(
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600553 fmt::format("PHAL FFDC: Return Message[{}]", ffdc->message)
554 .c_str());
Brad Bishopf6783cd2020-10-27 19:25:09 -0400555
Jayanth Othayothd8be1eb2022-06-28 07:33:06 -0500556 // Special handling for spare clock related errors.
557 if (ffdc->ffdc_type == FFDC_TYPE_SPARE_CLOCK_INFO)
558 {
559 processClockInfoErrorHelper(ffdc, ffdc_prefix);
560 return;
561 }
Brad Bishopf6783cd2020-10-27 19:25:09 -0400562 // To store callouts details in json format as per pel expectation.
563 json jsonCalloutDataList;
564 jsonCalloutDataList = json::array();
565
566 // To store phal trace and other additional data about ffdc.
567 FFDCData pelAdditionalData;
568
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600569 if (ffdc->ffdc_type == FFDC_TYPE_HWP)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400570 {
rajerpp1db924722021-11-30 11:00:05 -0600571 std::string keyWithPrefix(ffdc_prefix + "RC");
Brad Bishopf6783cd2020-10-27 19:25:09 -0400572 // Adding hardware procedures return code details
rajerpp1db924722021-11-30 11:00:05 -0600573 pelAdditionalData.emplace_back(keyWithPrefix,
574 ffdc->hwp_errorinfo.rc);
575 keyWithPrefix = ffdc_prefix + "RC_DESC";
576 pelAdditionalData.emplace_back(keyWithPrefix,
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600577 ffdc->hwp_errorinfo.rc_desc);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400578
579 // Adding hardware procedures required ffdc data for debug
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600580 for_each(ffdc->hwp_errorinfo.ffdcs_data.begin(),
581 ffdc->hwp_errorinfo.ffdcs_data.end(),
rajerpp1db924722021-11-30 11:00:05 -0600582 [&pelAdditionalData, &ffdc_prefix](
Brad Bishopf6783cd2020-10-27 19:25:09 -0400583 std::pair<std::string, std::string>& ele) -> void {
rajerpp1db924722021-11-30 11:00:05 -0600584 std::string keyWithPrefix(ffdc_prefix + "FFDC_");
Brad Bishopf6783cd2020-10-27 19:25:09 -0400585 keyWithPrefix.append(ele.first);
586
587 pelAdditionalData.emplace_back(keyWithPrefix,
588 ele.second);
589 });
590
591 // Adding hardware callout details
592 int calloutCount = 0;
rajerpp1db924722021-11-30 11:00:05 -0600593 for_each(
594 ffdc->hwp_errorinfo.hwcallouts.begin(),
595 ffdc->hwp_errorinfo.hwcallouts.end(),
596 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
597 &ffdc_prefix](const HWCallout& hwCallout) -> void {
598 calloutCount++;
599 std::stringstream keyPrefix;
600 keyPrefix << ffdc_prefix << "HW_CO_" << std::setfill('0')
601 << std::setw(2) << calloutCount << "_";
Brad Bishopf6783cd2020-10-27 19:25:09 -0400602
rajerpp1db924722021-11-30 11:00:05 -0600603 pelAdditionalData.emplace_back(
604 std::string(keyPrefix.str()).append("HW_ID"),
605 hwCallout.hwid);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400606
rajerpp1db924722021-11-30 11:00:05 -0600607 pelAdditionalData.emplace_back(
608 std::string(keyPrefix.str()).append("PRIORITY"),
609 hwCallout.callout_priority);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400610
rajerpp1db924722021-11-30 11:00:05 -0600611 // Log target details only if entity path is
612 // available. For example target entity path will not
613 // be available for non-hwp clock failure.
614 if (!hwCallout.target_entity_path.empty())
615 {
616 phal::TargetInfo targetInfo;
617 phal::getTgtReqAttrsVal(hwCallout.target_entity_path,
618 targetInfo);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400619
rajerpp1db924722021-11-30 11:00:05 -0600620 std::string locationCode =
621 std::string(targetInfo.locationCode);
622 pelAdditionalData.emplace_back(
623 std::string(keyPrefix.str()).append("LOC_CODE"),
624 locationCode);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400625
rajerpp1db924722021-11-30 11:00:05 -0600626 std::string physPath =
627 std::string(targetInfo.physDevPath);
628 pelAdditionalData.emplace_back(
629 std::string(keyPrefix.str()).append("PHYS_PATH"),
630 physPath);
631 }
Brad Bishopf6783cd2020-10-27 19:25:09 -0400632
rajerpp1db924722021-11-30 11:00:05 -0600633 pelAdditionalData.emplace_back(
634 std::string(keyPrefix.str()).append("CLK_POS"),
635 std::to_string(hwCallout.clkPos));
636
637 pelAdditionalData.emplace_back(
638 std::string(keyPrefix.str()).append("CALLOUT_PLANAR"),
639 (hwCallout.isPlanarCallout == true ? "true" : "false"));
640
641 std::string pelPriority =
642 getPelPriority(hwCallout.callout_priority);
643
644 if (hwCallout.isPlanarCallout)
645 {
646 addPlanarCallout(jsonCalloutDataList, pelPriority);
647 }
648 });
Brad Bishopf6783cd2020-10-27 19:25:09 -0400649
650 // Adding CDG (callout, deconfigure and guard) targets details
651 calloutCount = 0;
rajerpp1db924722021-11-30 11:00:05 -0600652 for_each(
653 ffdc->hwp_errorinfo.cdg_targets.begin(),
654 ffdc->hwp_errorinfo.cdg_targets.end(),
655 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
656 &ffdc_prefix](const CDG_Target& cdg_tgt) -> void {
657 calloutCount++;
658 std::stringstream keyPrefix;
659 keyPrefix << ffdc_prefix << "CDG_TGT_" << std::setfill('0')
660 << std::setw(2) << calloutCount << "_";
Brad Bishopf6783cd2020-10-27 19:25:09 -0400661
rajerpp1db924722021-11-30 11:00:05 -0600662 phal::TargetInfo targetInfo;
663 targetInfo.deconfigure = cdg_tgt.deconfigure;
Brad Bishopf6783cd2020-10-27 19:25:09 -0400664
rajerpp1db924722021-11-30 11:00:05 -0600665 phal::getTgtReqAttrsVal(cdg_tgt.target_entity_path,
666 targetInfo);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400667
rajerpp1db924722021-11-30 11:00:05 -0600668 std::string locationCode =
669 std::string(targetInfo.locationCode);
670 pelAdditionalData.emplace_back(
671 std::string(keyPrefix.str()).append("LOC_CODE"),
672 locationCode);
673 std::string physPath = std::string(targetInfo.physDevPath);
674 pelAdditionalData.emplace_back(
675 std::string(keyPrefix.str()).append("PHYS_PATH"),
676 physPath);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400677
rajerpp1db924722021-11-30 11:00:05 -0600678 pelAdditionalData.emplace_back(
679 std::string(keyPrefix.str()).append("CO_REQ"),
680 (cdg_tgt.callout == true ? "true" : "false"));
Brad Bishopf6783cd2020-10-27 19:25:09 -0400681
rajerpp1db924722021-11-30 11:00:05 -0600682 pelAdditionalData.emplace_back(
683 std::string(keyPrefix.str()).append("CO_PRIORITY"),
684 cdg_tgt.callout_priority);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400685
rajerpp1db924722021-11-30 11:00:05 -0600686 pelAdditionalData.emplace_back(
687 std::string(keyPrefix.str()).append("DECONF_REQ"),
688 (cdg_tgt.deconfigure == true ? "true" : "false"));
Brad Bishopf6783cd2020-10-27 19:25:09 -0400689
rajerpp1db924722021-11-30 11:00:05 -0600690 pelAdditionalData.emplace_back(
691 std::string(keyPrefix.str()).append("GUARD_REQ"),
692 (cdg_tgt.guard == true ? "true" : "false"));
Brad Bishopf6783cd2020-10-27 19:25:09 -0400693
rajerpp1db924722021-11-30 11:00:05 -0600694 pelAdditionalData.emplace_back(
695 std::string(keyPrefix.str()).append("GUARD_TYPE"),
696 cdg_tgt.guard_type);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400697
rajerpp1db924722021-11-30 11:00:05 -0600698 json jsonCalloutData;
699 jsonCalloutData["LocationCode"] = locationCode;
700 std::string pelPriority =
701 getPelPriority(cdg_tgt.callout_priority);
702 jsonCalloutData["Priority"] = pelPriority;
Brad Bishopf6783cd2020-10-27 19:25:09 -0400703
rajerpp1db924722021-11-30 11:00:05 -0600704 if (targetInfo.mruId != 0)
705 {
706 jsonCalloutData["MRUs"] = json::array({
707 {{"ID", targetInfo.mruId},
708 {"Priority", pelPriority}},
709 });
710 }
711 jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
712 jsonCalloutData["Guarded"] = cdg_tgt.guard;
713 jsonCalloutData["GuardType"] = cdg_tgt.guard_type;
714 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
Brad Bishopf6783cd2020-10-27 19:25:09 -0400715
rajerpp1db924722021-11-30 11:00:05 -0600716 jsonCalloutDataList.emplace_back(jsonCalloutData);
717 });
Jayanth Othayoth0ac7c382021-11-15 05:43:24 -0600718 // Adding procedure callout
719 calloutCount = 0;
720 for_each(
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600721 ffdc->hwp_errorinfo.procedures_callout.begin(),
722 ffdc->hwp_errorinfo.procedures_callout.end(),
rajerpp1db924722021-11-30 11:00:05 -0600723 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
724 &ffdc_prefix](const ProcedureCallout& procCallout) -> void {
Jayanth Othayoth0ac7c382021-11-15 05:43:24 -0600725 calloutCount++;
726 std::stringstream keyPrefix;
rajerpp1db924722021-11-30 11:00:05 -0600727 keyPrefix << ffdc_prefix << "PROC_CO_" << std::setfill('0')
Jayanth Othayoth0ac7c382021-11-15 05:43:24 -0600728 << std::setw(2) << calloutCount << "_";
729
730 pelAdditionalData.emplace_back(
731 std::string(keyPrefix.str()).append("PRIORITY"),
732 procCallout.callout_priority);
733
734 pelAdditionalData.emplace_back(
735 std::string(keyPrefix.str()).append("MAINT_PROCEDURE"),
736 procCallout.proc_callout);
737
738 json jsonCalloutData;
739 jsonCalloutData["Procedure"] = procCallout.proc_callout;
740 std::string pelPriority =
741 getPelPriority(procCallout.callout_priority);
742 jsonCalloutData["Priority"] = pelPriority;
743 jsonCalloutDataList.emplace_back(jsonCalloutData);
744 });
Brad Bishopf6783cd2020-10-27 19:25:09 -0400745 }
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600746 else if ((ffdc->ffdc_type != FFDC_TYPE_NONE) &&
747 (ffdc->ffdc_type != FFDC_TYPE_UNSUPPORTED))
Brad Bishopf6783cd2020-10-27 19:25:09 -0400748 {
749 log<level::ERR>(
750 fmt::format("Unsupported phal FFDC type to create PEL. "
751 "MSG: {}",
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600752 ffdc->message)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400753 .c_str());
754 }
755
756 // Adding collected phal logs into PEL additional data
757 for_each(traceLog.begin(), traceLog.end(),
758 [&pelAdditionalData](
759 std::pair<std::string, std::string>& ele) -> void {
760 pelAdditionalData.emplace_back(ele.first, ele.second);
761 });
762
763 // TODO: #ibm-openbmc/dev/issues/2595 : Once enabled this support,
764 // callout details is not required to sort in H,M and L orders which
765 // are expected by pel because, pel will take care for sorting callouts
766 // based on priority so, now adding support to send callout in order
767 // i.e High -> Medium -> Low.
768 std::sort(
769 jsonCalloutDataList.begin(), jsonCalloutDataList.end(),
770 [](const json& aEle, const json& bEle) -> bool {
771 // Considering b element having higher priority than a element
772 // or Both element will be same priorty (to keep same order
773 // which are given by phal when two callouts are having same
774 // priority)
775 if (((aEle["Priority"] == "M") && (bEle["Priority"] == "H")) ||
776 ((aEle["Priority"] == "L") &&
777 ((bEle["Priority"] == "H") ||
778 (bEle["Priority"] == "M"))) ||
779 (aEle["Priority"] == bEle["Priority"]))
780 {
781 return false;
782 }
783
784 // Considering a element having higher priority than b element
785 return true;
786 });
Jayanth Othayoth8fe9ff92021-11-14 09:15:59 -0600787 openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot",
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500788 jsonCalloutDataList, pelAdditionalData,
789 Severity::Error);
Brad Bishopf6783cd2020-10-27 19:25:09 -0400790 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500791 catch (const std::exception& ex)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400792 {
793 reset();
794 throw ex;
795 }
796 reset();
797}
798
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600799void processPlatBootError(const ipl_error_info& errInfo)
800{
801 log<level::INFO>("processPlatBootError ");
802
803 // Collecting ffdc details from phal
804 FFDC* ffdc = reinterpret_cast<FFDC*>(errInfo.private_data);
805 try
806 {
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500807 if (util::isHostPoweringOff())
808 {
809 processPoweroffError(ffdc, "PLAT_");
810 }
811 else
812 {
813 processBootErrorHelper(ffdc, "PLAT_");
814 }
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600815 }
816 catch (const std::exception& ex)
817 {
818 log<level::ERR>(
819 fmt::format("processPlatBootError: exception({})", ex.what())
820 .c_str());
821 throw ex;
822 }
823}
824
825void processBootError(bool status)
826{
827 log<level::INFO>(
828 fmt::format("processBootError: status({})", status).c_str());
829
830 try
831 {
832 // return If no failure during hwp execution
833 if (status)
834 return;
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600835 // Collecting ffdc details from phal
836 FFDC ffdc;
837 libekb_get_ffdc(ffdc);
838
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500839 if (util::isHostPoweringOff())
840 {
841 processPoweroffError(&ffdc, "HWP_");
842 }
843 else
844 {
845 processBootErrorHelper(&ffdc, "HWP_");
846 }
Marri Devender Rao381c3e32021-12-01 06:27:55 -0600847 }
848 catch (const std::exception& ex)
849 {
850 log<level::ERR>(
851 fmt::format("processBootError: exception({})", ex.what()).c_str());
852 throw ex;
853 }
854}
855
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500856void processSbeBootError()
857{
858 log<level::INFO>("processSbeBootError : Entered ");
859
860 using namespace openpower::phal::sbe;
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500861
862 // To store phal trace and other additional data about ffdc.
863 FFDCData pelAdditionalData;
864
865 // Adding collected phal logs into PEL additional data
866 for_each(
867 traceLog.begin(), traceLog.end(),
868 [&pelAdditionalData](std::pair<std::string, std::string>& ele) -> void {
869 pelAdditionalData.emplace_back(ele.first, ele.second);
870 });
871
872 // reset the trace log and counter
873 reset();
874
875 // get primary processor to collect FFDC/Dump information.
876 struct pdbg_target* procTarget;
877 pdbg_for_each_class_target("proc", procTarget)
878 {
879 if (openpower::phal::isPrimaryProc(procTarget))
880 break;
881 procTarget = nullptr;
882 }
883 // check valid primary processor is available
884 if (procTarget == nullptr)
885 {
886 log<level::ERR>("processSbeBootError: fail to get primary processor");
Jayanth Othayoth0a516de2021-11-14 09:59:06 -0600887 // Add BMC code callout and create PEL
888 json jsonCalloutDataList;
889 jsonCalloutDataList = json::array();
890 json jsonCalloutData;
891 jsonCalloutData["Procedure"] = "BMC0001";
892 jsonCalloutData["Priority"] = "H";
893 jsonCalloutDataList.emplace_back(jsonCalloutData);
894 openpower::pel::createErrorPEL(
895 "org.open_power.Processor.Error.SbeBootFailure",
Marri Devender Rao4d5b5bf2022-05-23 09:23:31 -0500896 jsonCalloutDataList, {}, Severity::Error);
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500897 return;
898 }
899 // SBE error object.
900 sbeError_t sbeError;
901 bool dumpIsRequired = false;
902
903 try
904 {
905 // Capture FFDC information on primary processor
906 sbeError = captureFFDC(procTarget);
907 }
Jayanth Othayothfaaef2a2021-10-08 06:49:36 -0500908 catch (const phalError_t& phalError)
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500909 {
910 // Fail to collect FFDC information , trigger Dump
911 log<level::ERR>(
Jayanth Othayothfaaef2a2021-10-08 06:49:36 -0500912 fmt::format("captureFFDC: Exception({})", phalError.what())
913 .c_str());
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500914 dumpIsRequired = true;
915 }
916
Jayanth Othayoth006641e2021-10-07 06:56:24 -0500917 std::string event;
918
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500919 if ((sbeError.errType() == SBE_FFDC_NO_DATA) ||
920 (sbeError.errType() == SBE_CMD_TIMEOUT) || (dumpIsRequired))
921 {
Jayanth Othayoth006641e2021-10-07 06:56:24 -0500922 event = "org.open_power.Processor.Error.SbeBootTimeout";
923 dumpIsRequired = true;
924 }
925 else
926 {
927 event = "org.open_power.Processor.Error.SbeBootFailure";
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500928 }
929 // SRC6 : [0:15] chip position
Jayanth Othayoth006641e2021-10-07 06:56:24 -0500930 uint32_t index = pdbg_target_index(procTarget);
931 pelAdditionalData.emplace_back("SRC6", std::to_string(index << 16));
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500932 // Create SBE Error with FFDC data.
Patrick Williams00dd33e2023-05-10 07:50:37 -0500933 auto logId = createSbeErrorPEL(event, sbeError, pelAdditionalData,
934 procTarget);
Jayanth Othayoth006641e2021-10-07 06:56:24 -0500935
936 if (dumpIsRequired)
937 {
938 using namespace openpower::phal::dump;
939 DumpParameters dumpParameters = {logId, index, SBE_DUMP_TIMEOUT,
940 DumpType::SBE};
941 try
942 {
943 requestDump(dumpParameters);
944 }
945 catch (const std::runtime_error& e)
946 {
947 // Allowing call back to handle the error gracefully.
948 log<level::ERR>("Dump collection failed");
949 // TODO revist error handling.
950 }
951 }
Jayanth Othayoth4079f092021-09-20 07:36:54 -0500952}
953
deepakala-k9f351b02022-10-05 09:03:57 -0500954void processGuardPartitionAccessError()
955{
956 // Adding collected phal logs into PEL additional data
957 FFDCData pelAdditionalData;
958
959 for_each(
960 traceLog.begin(), traceLog.end(),
961 [&pelAdditionalData](std::pair<std::string, std::string>& ele) -> void {
962 pelAdditionalData.emplace_back(ele.first, ele.second);
963 });
964
965 openpower::pel::createPEL("org.open_power.PHAL.Error.GuardPartitionAccess",
966 pelAdditionalData);
967}
968
Brad Bishopf6783cd2020-10-27 19:25:09 -0400969void reset()
970{
971 // reset the trace log and counter
972 traceLog.clear();
973 counter = 0;
974}
975
Brad Bishop63508a72020-10-27 18:55:01 -0400976void pDBGLogTraceCallbackHelper(int, const char* fmt, va_list ap)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400977{
978 processLogTraceCallback(NULL, fmt, ap);
979}
980} // namespace detail
981
982static inline uint8_t getLogLevelFromEnv(const char* env, const uint8_t dValue)
983{
984 auto logLevel = dValue;
985 try
986 {
987 if (const char* env_p = std::getenv(env))
988 {
989 logLevel = std::stoi(env_p);
990 }
991 }
Patrick Williams1a9a5a62021-10-06 13:05:06 -0500992 catch (const std::exception& e)
Brad Bishopf6783cd2020-10-27 19:25:09 -0400993 {
994 log<level::ERR>(("Conversion Failure"), entry("ENVIRONMENT=%s", env),
995 entry("EXCEPTION=%s", e.what()));
996 }
997 return logLevel;
998}
999
1000void addBootErrorCallbacks()
1001{
1002 // Get individual phal repos log level from environment variable
1003 // and update the log level.
1004 pdbg_set_loglevel(getLogLevelFromEnv("PDBG_LOG", PDBG_INFO));
1005 libekb_set_loglevel(getLogLevelFromEnv("LIBEKB_LOG", LIBEKB_LOG_IMP));
1006 ipl_set_loglevel(getLogLevelFromEnv("IPL_LOG", IPL_INFO));
1007
1008 // add callback for debug traces
1009 pdbg_set_logfunc(detail::pDBGLogTraceCallbackHelper);
1010 libekb_set_logfunc(detail::processLogTraceCallback, NULL);
1011 ipl_set_logfunc(detail::processLogTraceCallback, NULL);
1012
1013 // add callback for ipl failures
Jayanth Othayoth2b211702021-09-06 05:14:23 -05001014 ipl_set_error_callback_func(detail::processIplErrorCallback);
Brad Bishopf6783cd2020-10-27 19:25:09 -04001015}
1016
1017} // namespace pel
1018} // namespace openpower