16552de05SJayanth Othayoth extern "C"
26552de05SJayanth Othayoth {
36552de05SJayanth Othayoth #include <libpdbg.h>
46552de05SJayanth Othayoth }
56552de05SJayanth Othayoth
66552de05SJayanth Othayoth #include "create_pel.hpp"
7006641efSJayanth Othayoth #include "dump_utils.hpp"
84079f09dSJayanth Othayoth #include "extensions/phal/common_utils.hpp"
96552de05SJayanth Othayoth #include "phal_error.hpp"
104d5b5bfeSMarri Devender Rao #include "util.hpp"
116552de05SJayanth Othayoth
126552de05SJayanth Othayoth #include <attributes_info.H>
136552de05SJayanth Othayoth #include <libekb.H>
144079f09dSJayanth Othayoth #include <libphal.H>
156552de05SJayanth Othayoth
166552de05SJayanth Othayoth #include <nlohmann/json.hpp>
176552de05SJayanth Othayoth #include <phosphor-logging/elog.hpp>
186552de05SJayanth Othayoth
196552de05SJayanth Othayoth #include <algorithm>
206552de05SJayanth Othayoth #include <cstdlib>
216552de05SJayanth Othayoth #include <cstring>
22e0dd7af4SJayanth Othayoth #include <format>
236552de05SJayanth Othayoth #include <iomanip>
246552de05SJayanth Othayoth #include <list>
256552de05SJayanth Othayoth #include <map>
266552de05SJayanth Othayoth #include <sstream>
276552de05SJayanth Othayoth #include <string>
286552de05SJayanth Othayoth
296552de05SJayanth Othayoth namespace openpower
306552de05SJayanth Othayoth {
316552de05SJayanth Othayoth namespace phal
326552de05SJayanth Othayoth {
336552de05SJayanth Othayoth using namespace phosphor::logging;
345d5eb314SJayanth Othayoth using namespace openpower::phal::exception;
354d5b5bfeSMarri Devender Rao using Severity = sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level;
366552de05SJayanth Othayoth
376552de05SJayanth Othayoth /**
386552de05SJayanth Othayoth * Used to pass buffer to pdbg callback api to get required target
396552de05SJayanth Othayoth * data (attributes) based on given data (attribute).
406552de05SJayanth Othayoth */
416552de05SJayanth Othayoth struct TargetInfo
426552de05SJayanth Othayoth {
436552de05SJayanth Othayoth ATTR_PHYS_BIN_PATH_Type physBinPath;
446552de05SJayanth Othayoth ATTR_LOCATION_CODE_Type locationCode;
456552de05SJayanth Othayoth ATTR_PHYS_DEV_PATH_Type physDevPath;
466552de05SJayanth Othayoth ATTR_MRU_ID_Type mruId;
476552de05SJayanth Othayoth
486552de05SJayanth Othayoth bool deconfigure;
496552de05SJayanth Othayoth
TargetInfoopenpower::phal::TargetInfo506552de05SJayanth Othayoth TargetInfo()
516552de05SJayanth Othayoth {
526552de05SJayanth Othayoth memset(&physBinPath, '\0', sizeof(physBinPath));
536552de05SJayanth Othayoth memset(&locationCode, '\0', sizeof(locationCode));
546552de05SJayanth Othayoth memset(&physDevPath, '\0', sizeof(physDevPath));
556552de05SJayanth Othayoth mruId = 0;
566552de05SJayanth Othayoth deconfigure = false;
576552de05SJayanth Othayoth }
586552de05SJayanth Othayoth };
596552de05SJayanth Othayoth
606552de05SJayanth Othayoth /**
616552de05SJayanth Othayoth * Used to return in callback function which are used to get
626552de05SJayanth Othayoth * physical path value and it binary format value.
636552de05SJayanth Othayoth *
646552de05SJayanth Othayoth * The value for constexpr defined based on pdbg_target_traverse function usage.
656552de05SJayanth Othayoth */
666552de05SJayanth Othayoth constexpr int continueTgtTraversal = 0;
676552de05SJayanth Othayoth constexpr int requireAttrFound = 1;
686552de05SJayanth Othayoth constexpr int requireAttrNotFound = 2;
696552de05SJayanth Othayoth
706552de05SJayanth Othayoth /**
716552de05SJayanth Othayoth * @brief Used to get target location code from phal device tree
726552de05SJayanth Othayoth *
736552de05SJayanth Othayoth * @param[in] target current device tree target
746552de05SJayanth Othayoth * @param[out] appPrivData used for accessing|storing from|to application
756552de05SJayanth Othayoth *
766552de05SJayanth Othayoth * @return 0 to continue traverse, non-zero to stop traverse
776552de05SJayanth Othayoth */
pdbgCallbackToGetTgtReqAttrsVal(struct pdbg_target * target,void * appPrivData)786552de05SJayanth Othayoth int pdbgCallbackToGetTgtReqAttrsVal(struct pdbg_target* target,
796552de05SJayanth Othayoth void* appPrivData)
806552de05SJayanth Othayoth {
815d5eb314SJayanth Othayoth using namespace openpower::phal::pdbg;
825d5eb314SJayanth Othayoth
836552de05SJayanth Othayoth TargetInfo* targetInfo = static_cast<TargetInfo*>(appPrivData);
846552de05SJayanth Othayoth
856552de05SJayanth Othayoth ATTR_PHYS_BIN_PATH_Type physBinPath;
866552de05SJayanth Othayoth /**
876552de05SJayanth Othayoth * TODO: Issue: phal/pdata#16
886552de05SJayanth Othayoth * Should not use direct pdbg api to read attribute. Need to use DT_GET_PROP
896552de05SJayanth Othayoth * macro for bmc app's and this will call libdt-api api but, it will print
906552de05SJayanth Othayoth * "pdbg_target_get_attribute failed" trace if attribute is not found and
916552de05SJayanth Othayoth * this callback will call recursively by using pdbg_target_traverse() until
926552de05SJayanth Othayoth * find expected attribute based on return code from this callback. Because,
936552de05SJayanth Othayoth * need to do target iteration to get actual attribute (ATTR_PHYS_BIN_PATH)
946552de05SJayanth Othayoth * value when device tree target info doesn't know to read attribute from
956552de05SJayanth Othayoth * device tree. So, Due to this error trace user will get confusion while
966552de05SJayanth Othayoth * looking traces. Hence using pdbg api to avoid trace until libdt-api
976552de05SJayanth Othayoth * provides log level setup.
986552de05SJayanth Othayoth */
996552de05SJayanth Othayoth if (!pdbg_target_get_attribute(
1006552de05SJayanth Othayoth target, "ATTR_PHYS_BIN_PATH",
1016552de05SJayanth Othayoth std::stoi(dtAttr::fapi2::ATTR_PHYS_BIN_PATH_Spec),
1026552de05SJayanth Othayoth dtAttr::fapi2::ATTR_PHYS_BIN_PATH_ElementCount, physBinPath))
1036552de05SJayanth Othayoth {
1046552de05SJayanth Othayoth return continueTgtTraversal;
1056552de05SJayanth Othayoth }
1066552de05SJayanth Othayoth
1076552de05SJayanth Othayoth if (std::memcmp(physBinPath, targetInfo->physBinPath,
1086552de05SJayanth Othayoth sizeof(physBinPath)) != 0)
1096552de05SJayanth Othayoth {
1106552de05SJayanth Othayoth return continueTgtTraversal;
1116552de05SJayanth Othayoth }
1126552de05SJayanth Othayoth
113de909259SJayanth Othayoth // Found Target, now collect the required attributes associated to the
114de909259SJayanth Othayoth // target. Incase of any attribute read failure, initialize the data with
115de909259SJayanth Othayoth // default value.
1165d5eb314SJayanth Othayoth try
1176552de05SJayanth Othayoth {
1185d5eb314SJayanth Othayoth // Get location code information
1195d5eb314SJayanth Othayoth openpower::phal::pdbg::getLocationCode(target,
1205d5eb314SJayanth Othayoth targetInfo->locationCode);
1215d5eb314SJayanth Othayoth }
1225d5eb314SJayanth Othayoth catch (const std::exception& e)
1235d5eb314SJayanth Othayoth {
124e0dd7af4SJayanth Othayoth log<level::ERR>(std::format("getLocationCode({}): Exception({})",
1255d5eb314SJayanth Othayoth pdbg_target_path(target), e.what())
1265d5eb314SJayanth Othayoth .c_str());
1276552de05SJayanth Othayoth }
1286552de05SJayanth Othayoth
1296552de05SJayanth Othayoth if (DT_GET_PROP(ATTR_PHYS_DEV_PATH, target, targetInfo->physDevPath))
1306552de05SJayanth Othayoth {
131de909259SJayanth Othayoth log<level::ERR>(
132e0dd7af4SJayanth Othayoth std::format("Could not read({}) PHYS_DEV_PATH attribute",
133de909259SJayanth Othayoth pdbg_target_path(target))
134de909259SJayanth Othayoth .c_str());
1356552de05SJayanth Othayoth }
1366552de05SJayanth Othayoth
1376552de05SJayanth Othayoth if (DT_GET_PROP(ATTR_MRU_ID, target, targetInfo->mruId))
1386552de05SJayanth Othayoth {
139e0dd7af4SJayanth Othayoth log<level::ERR>(std::format("Could not read({}) ATTR_MRU_ID attribute",
140de909259SJayanth Othayoth pdbg_target_path(target))
141de909259SJayanth Othayoth .c_str());
1426552de05SJayanth Othayoth }
1436552de05SJayanth Othayoth
1446552de05SJayanth Othayoth return requireAttrFound;
1456552de05SJayanth Othayoth }
1466552de05SJayanth Othayoth
1476552de05SJayanth Othayoth /**
1486552de05SJayanth Othayoth * @brief Used to get target info (attributes data)
1496552de05SJayanth Othayoth *
1506552de05SJayanth Othayoth * To get target required attributes value using another attribute value
1516552de05SJayanth Othayoth * ("PHYS_BIN_PATH" which is present in same target attributes list) by using
1526552de05SJayanth Othayoth * "ipdbg_target_traverse" api because, here we have attribute value only and
1536552de05SJayanth Othayoth * doesn't have respective device tree target info to get required attributes
1546552de05SJayanth Othayoth * values from it attributes list.
1556552de05SJayanth Othayoth *
1566552de05SJayanth Othayoth * @param[in] physBinPath to pass PHYS_BIN_PATH value
1576552de05SJayanth Othayoth * @param[out] targetInfo to pas buufer to fill with required attributes
1586552de05SJayanth Othayoth *
1596552de05SJayanth Othayoth * @return true on success otherwise false
1606552de05SJayanth Othayoth */
getTgtReqAttrsVal(const std::vector<uint8_t> & physBinPath,TargetInfo & targetInfo)1616552de05SJayanth Othayoth bool getTgtReqAttrsVal(const std::vector<uint8_t>& physBinPath,
1626552de05SJayanth Othayoth TargetInfo& targetInfo)
1636552de05SJayanth Othayoth {
1646552de05SJayanth Othayoth std::memcpy(&targetInfo.physBinPath, physBinPath.data(),
1656552de05SJayanth Othayoth sizeof(targetInfo.physBinPath));
1666552de05SJayanth Othayoth
1676552de05SJayanth Othayoth int ret = pdbg_target_traverse(NULL, pdbgCallbackToGetTgtReqAttrsVal,
1686552de05SJayanth Othayoth &targetInfo);
1696552de05SJayanth Othayoth if (ret == 0)
1706552de05SJayanth Othayoth {
171e0dd7af4SJayanth Othayoth std::string fmt;
172e0dd7af4SJayanth Othayoth for (auto value : targetInfo.physBinPath)
173e0dd7af4SJayanth Othayoth {
174e0dd7af4SJayanth Othayoth fmt += std::format("{:02X} ", value);
175e0dd7af4SJayanth Othayoth }
176e0dd7af4SJayanth Othayoth
177e0dd7af4SJayanth Othayoth log<level::ERR>(std::format("Given ATTR_PHYS_BIN_PATH value {} "
1786552de05SJayanth Othayoth "not found in phal device tree",
179e0dd7af4SJayanth Othayoth fmt)
1806552de05SJayanth Othayoth .c_str());
1816552de05SJayanth Othayoth return false;
1826552de05SJayanth Othayoth }
1836552de05SJayanth Othayoth else if (ret == requireAttrNotFound)
1846552de05SJayanth Othayoth {
1856552de05SJayanth Othayoth return false;
1866552de05SJayanth Othayoth }
1876552de05SJayanth Othayoth
1886552de05SJayanth Othayoth return true;
1896552de05SJayanth Othayoth }
1906552de05SJayanth Othayoth } // namespace phal
1916552de05SJayanth Othayoth
1926552de05SJayanth Othayoth namespace pel
1936552de05SJayanth Othayoth {
1946552de05SJayanth Othayoth using namespace phosphor::logging;
1956552de05SJayanth Othayoth
1966552de05SJayanth Othayoth namespace detail
1976552de05SJayanth Othayoth {
1986552de05SJayanth Othayoth using json = nlohmann::json;
1996552de05SJayanth Othayoth
2006552de05SJayanth Othayoth // keys need to be unique so using counter value to generate unique key
2016552de05SJayanth Othayoth static int counter = 0;
2026552de05SJayanth Othayoth
2036552de05SJayanth Othayoth // list of debug traces
2046552de05SJayanth Othayoth static std::vector<std::pair<std::string, std::string>> traceLog;
2056552de05SJayanth Othayoth
206381c3e34SMarri Devender Rao /**
207381c3e34SMarri Devender Rao * @brief Process platform realted boot failure
208381c3e34SMarri Devender Rao *
209381c3e34SMarri Devender Rao * @param[in] errInfo - error details
210381c3e34SMarri Devender Rao */
211381c3e34SMarri Devender Rao static void processPlatBootError(const ipl_error_info& errInfo);
212381c3e34SMarri Devender Rao
processLogTraceCallback(void *,const char * fmt,va_list ap)2136552de05SJayanth Othayoth void processLogTraceCallback(void*, const char* fmt, va_list ap)
2146552de05SJayanth Othayoth {
2156552de05SJayanth Othayoth va_list vap;
2166552de05SJayanth Othayoth va_copy(vap, ap);
2176552de05SJayanth Othayoth std::vector<char> logData(1 + std::vsnprintf(nullptr, 0, fmt, ap));
2186552de05SJayanth Othayoth std::vsnprintf(logData.data(), logData.size(), fmt, vap);
2196552de05SJayanth Othayoth va_end(vap);
2206552de05SJayanth Othayoth std::string logstr(logData.begin(), logData.end());
2216552de05SJayanth Othayoth
2226552de05SJayanth Othayoth log<level::INFO>(logstr.c_str());
2236552de05SJayanth Othayoth
2246552de05SJayanth Othayoth char timeBuf[80];
2256552de05SJayanth Othayoth time_t t = time(0);
2266552de05SJayanth Othayoth tm myTm{};
2276552de05SJayanth Othayoth gmtime_r(&t, &myTm);
2286552de05SJayanth Othayoth strftime(timeBuf, 80, "%Y-%m-%d %H:%M:%S", &myTm);
2296552de05SJayanth Othayoth
2306552de05SJayanth Othayoth // key values need to be unique for PEL
2316552de05SJayanth Othayoth // TODO #openbmc/dev/issues/1563
2326552de05SJayanth Othayoth // If written to Json no need to worry about unique KEY
2336552de05SJayanth Othayoth std::stringstream str;
2346552de05SJayanth Othayoth str << std::setfill('0');
2356552de05SJayanth Othayoth str << "LOG" << std::setw(3) << counter;
2366552de05SJayanth Othayoth str << " " << timeBuf;
2376552de05SJayanth Othayoth traceLog.emplace_back(std::make_pair(str.str(), std::move(logstr)));
2386552de05SJayanth Othayoth counter++;
2396552de05SJayanth Othayoth }
2406552de05SJayanth Othayoth
2416552de05SJayanth Othayoth /**
2426552de05SJayanth Othayoth * @brief GET PEL priority from pHAL priority
2436552de05SJayanth Othayoth *
2446552de05SJayanth Othayoth * The pHAL callout priority is in different format than PEL format
2456552de05SJayanth Othayoth * so, this api is used to return current phal supported priority into
2466552de05SJayanth Othayoth * PEL expected format.
2476552de05SJayanth Othayoth *
2486552de05SJayanth Othayoth * @param[in] phalPriority used to pass phal priority format string
2496552de05SJayanth Othayoth *
2506552de05SJayanth Othayoth * @return pel priority format string else empty if failure
2516552de05SJayanth Othayoth *
2526552de05SJayanth Othayoth * @note For "NONE" returning "L" (LOW)
2536552de05SJayanth Othayoth */
getPelPriority(const std::string & phalPriority)2546552de05SJayanth Othayoth static std::string getPelPriority(const std::string& phalPriority)
2556552de05SJayanth Othayoth {
2566552de05SJayanth Othayoth const std::map<std::string, std::string> priorityMap = {
2576552de05SJayanth Othayoth {"HIGH", "H"}, {"MEDIUM", "M"}, {"LOW", "L"}, {"NONE", "L"}};
2586552de05SJayanth Othayoth
2596552de05SJayanth Othayoth auto it = priorityMap.find(phalPriority);
2606552de05SJayanth Othayoth if (it == priorityMap.end())
2616552de05SJayanth Othayoth {
262e0dd7af4SJayanth Othayoth log<level::ERR>(std::format("Unsupported phal priority({}) is given "
2636552de05SJayanth Othayoth "to get pel priority format",
2646552de05SJayanth Othayoth phalPriority)
2656552de05SJayanth Othayoth .c_str());
2666552de05SJayanth Othayoth return "H";
2676552de05SJayanth Othayoth }
2686552de05SJayanth Othayoth
2696552de05SJayanth Othayoth return it->second;
2706552de05SJayanth Othayoth }
2716552de05SJayanth Othayoth
27269708fbbSJayanth Othayoth /**
27369708fbbSJayanth Othayoth * @brief Helper function to create PEL for non functional boot
27469708fbbSJayanth Othayoth * processor related failure.
27569708fbbSJayanth Othayoth * This function adds the BMC code callout as priority 1 to fix
27669708fbbSJayanth Othayoth * devtree related software issue. Incase the issue still persist
27769708fbbSJayanth Othayoth * after reboot recommend to replacing the primary processor.
27869708fbbSJayanth Othayoth */
processNonFunctionalBootProc()27969708fbbSJayanth Othayoth void processNonFunctionalBootProc()
28069708fbbSJayanth Othayoth {
28169708fbbSJayanth Othayoth json jsonCalloutDataList;
28269708fbbSJayanth Othayoth json jsonProcedCallout;
28369708fbbSJayanth Othayoth // Add BMC code callout
28469708fbbSJayanth Othayoth jsonProcedCallout["Procedure"] = "BMC0001";
28569708fbbSJayanth Othayoth jsonProcedCallout["Priority"] = "H";
28669708fbbSJayanth Othayoth jsonCalloutDataList.emplace_back(std::move(jsonProcedCallout));
28769708fbbSJayanth Othayoth
28869708fbbSJayanth Othayoth // get primary processor
28969708fbbSJayanth Othayoth struct pdbg_target* procTarget;
29069708fbbSJayanth Othayoth pdbg_for_each_class_target("proc", procTarget)
29169708fbbSJayanth Othayoth {
29269708fbbSJayanth Othayoth if (openpower::phal::isPrimaryProc(procTarget))
29369708fbbSJayanth Othayoth break;
29469708fbbSJayanth Othayoth procTarget = nullptr;
29569708fbbSJayanth Othayoth }
29669708fbbSJayanth Othayoth // check valid primary processor is available
29769708fbbSJayanth Othayoth if (procTarget == nullptr)
29869708fbbSJayanth Othayoth {
29969708fbbSJayanth Othayoth log<level::ERR>(
30069708fbbSJayanth Othayoth "processNonFunctionalBootProc: fail to get primary processor");
30169708fbbSJayanth Othayoth }
30269708fbbSJayanth Othayoth else
30369708fbbSJayanth Othayoth {
30469708fbbSJayanth Othayoth try
30569708fbbSJayanth Othayoth {
30669708fbbSJayanth Othayoth ATTR_LOCATION_CODE_Type locationCode = {'\0'};
30769708fbbSJayanth Othayoth // Get location code information
30869708fbbSJayanth Othayoth openpower::phal::pdbg::getLocationCode(procTarget, locationCode);
30969708fbbSJayanth Othayoth json jsonProcCallout;
31069708fbbSJayanth Othayoth jsonProcCallout["LocationCode"] = locationCode;
31169708fbbSJayanth Othayoth jsonProcCallout["Deconfigured"] = false;
31269708fbbSJayanth Othayoth jsonProcCallout["Guarded"] = false;
31369708fbbSJayanth Othayoth jsonProcCallout["Priority"] = "M";
31469708fbbSJayanth Othayoth jsonCalloutDataList.emplace_back(std::move(jsonProcCallout));
31569708fbbSJayanth Othayoth }
31669708fbbSJayanth Othayoth catch (const std::exception& e)
31769708fbbSJayanth Othayoth {
318e0dd7af4SJayanth Othayoth log<level::ERR>(std::format("getLocationCode({}): Exception({})",
31969708fbbSJayanth Othayoth pdbg_target_path(procTarget), e.what())
32069708fbbSJayanth Othayoth .c_str());
32169708fbbSJayanth Othayoth }
32269708fbbSJayanth Othayoth }
32369708fbbSJayanth Othayoth // Adding collected phal logs into PEL additional data
32469708fbbSJayanth Othayoth FFDCData pelAdditionalData;
32569708fbbSJayanth Othayoth for_each(
32669708fbbSJayanth Othayoth traceLog.begin(), traceLog.end(),
32769708fbbSJayanth Othayoth [&pelAdditionalData](std::pair<std::string, std::string>& ele) -> void {
32869708fbbSJayanth Othayoth pelAdditionalData.emplace_back(ele.first, ele.second);
32969708fbbSJayanth Othayoth });
33069708fbbSJayanth Othayoth openpower::pel::createErrorPEL(
33169708fbbSJayanth Othayoth "org.open_power.PHAL.Error.NonFunctionalBootProc", jsonCalloutDataList,
3324d5b5bfeSMarri Devender Rao pelAdditionalData, Severity::Error);
33369708fbbSJayanth Othayoth // reset trace log and exit
33469708fbbSJayanth Othayoth reset();
33569708fbbSJayanth Othayoth }
33669708fbbSJayanth Othayoth
337d8be1ebdSJayanth Othayoth /**
338d8be1ebdSJayanth Othayoth * @brief processClockInfoErrorHelper
339d8be1ebdSJayanth Othayoth *
340d8be1ebdSJayanth Othayoth * Creates informational PEL for spare clock failure
341d8be1ebdSJayanth Othayoth *
342d8be1ebdSJayanth Othayoth * @param[in] ffdc - FFDC data capturd by the HWP
343d8be1ebdSJayanth Othayoth * @param[in] ffdc_prefix - prefix string for logging the data.
344d8be1ebdSJayanth Othayoth */
processClockInfoErrorHelper(FFDC * ffdc,const std::string & ffdc_prefix)345d8be1ebdSJayanth Othayoth void processClockInfoErrorHelper(FFDC* ffdc, const std::string& ffdc_prefix)
346d8be1ebdSJayanth Othayoth {
347d8be1ebdSJayanth Othayoth try
348d8be1ebdSJayanth Othayoth {
349d8be1ebdSJayanth Othayoth log<level::INFO>(
350e0dd7af4SJayanth Othayoth std::format("processClockInfoErrorHelper: FFDC Message[{}]",
351d8be1ebdSJayanth Othayoth ffdc->message)
352d8be1ebdSJayanth Othayoth .c_str());
353d8be1ebdSJayanth Othayoth
354d8be1ebdSJayanth Othayoth // To store callouts details in json format as per pel expectation.
355d8be1ebdSJayanth Othayoth json jsonCalloutDataList;
356d8be1ebdSJayanth Othayoth jsonCalloutDataList = json::array();
357d8be1ebdSJayanth Othayoth
358d8be1ebdSJayanth Othayoth // To store phal trace and other additional data about ffdc.
359d8be1ebdSJayanth Othayoth FFDCData pelAdditionalData;
360d8be1ebdSJayanth Othayoth
361d8be1ebdSJayanth Othayoth std::string keyWithPrefix(ffdc_prefix + "RC");
362d8be1ebdSJayanth Othayoth // Adding hardware procedures return code details
363d8be1ebdSJayanth Othayoth pelAdditionalData.emplace_back(keyWithPrefix, ffdc->hwp_errorinfo.rc);
364d8be1ebdSJayanth Othayoth keyWithPrefix = ffdc_prefix + "RC_DESC";
365d8be1ebdSJayanth Othayoth pelAdditionalData.emplace_back(keyWithPrefix,
366d8be1ebdSJayanth Othayoth ffdc->hwp_errorinfo.rc_desc);
367d8be1ebdSJayanth Othayoth
368d8be1ebdSJayanth Othayoth // Adding hardware procedures required ffdc data for debug
369d8be1ebdSJayanth Othayoth for_each(ffdc->hwp_errorinfo.ffdcs_data.begin(),
370d8be1ebdSJayanth Othayoth ffdc->hwp_errorinfo.ffdcs_data.end(),
371d8be1ebdSJayanth Othayoth [&pelAdditionalData, &ffdc_prefix](
372d8be1ebdSJayanth Othayoth std::pair<std::string, std::string>& ele) -> void {
373d8be1ebdSJayanth Othayoth std::string keyWithPrefix(ffdc_prefix + "FFDC_");
374d8be1ebdSJayanth Othayoth keyWithPrefix.append(ele.first);
375d8be1ebdSJayanth Othayoth
376d8be1ebdSJayanth Othayoth pelAdditionalData.emplace_back(keyWithPrefix, ele.second);
377d8be1ebdSJayanth Othayoth });
378d8be1ebdSJayanth Othayoth // get clock position information
379d8be1ebdSJayanth Othayoth auto clk_pos = 0xFF; // Invalid position.
380d8be1ebdSJayanth Othayoth for (auto& hwCallout : ffdc->hwp_errorinfo.hwcallouts)
381d8be1ebdSJayanth Othayoth {
382d8be1ebdSJayanth Othayoth if ((hwCallout.hwid == "PROC_REF_CLOCK") ||
383d8be1ebdSJayanth Othayoth (hwCallout.hwid == "PCI_REF_CLOCK"))
384d8be1ebdSJayanth Othayoth {
385d8be1ebdSJayanth Othayoth clk_pos = hwCallout.clkPos;
386d8be1ebdSJayanth Othayoth break;
387d8be1ebdSJayanth Othayoth }
388d8be1ebdSJayanth Othayoth }
389d8be1ebdSJayanth Othayoth
390d8be1ebdSJayanth Othayoth // Adding CDG (Only deconfigure) targets details
391d8be1ebdSJayanth Othayoth for_each(ffdc->hwp_errorinfo.cdg_targets.begin(),
392d8be1ebdSJayanth Othayoth ffdc->hwp_errorinfo.cdg_targets.end(),
393d8be1ebdSJayanth Othayoth [&pelAdditionalData, &jsonCalloutDataList,
394d8be1ebdSJayanth Othayoth clk_pos](const CDG_Target& cdg_tgt) -> void {
395d8be1ebdSJayanth Othayoth json jsonCalloutData;
396fe2abd1fSJayanth Othayoth std::string pelPriority = "L";
397d8be1ebdSJayanth Othayoth jsonCalloutData["Priority"] = pelPriority; // Not used
398*1e43be06SPatrick Williams jsonCalloutData["SymbolicFRU"] =
399*1e43be06SPatrick Williams "REFCLK" + std::to_string(clk_pos);
400d8be1ebdSJayanth Othayoth jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
401d8be1ebdSJayanth Othayoth jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
402d8be1ebdSJayanth Othayoth jsonCalloutDataList.emplace_back(jsonCalloutData);
403d8be1ebdSJayanth Othayoth });
404d8be1ebdSJayanth Othayoth
405d8be1ebdSJayanth Othayoth // Adding collected phal logs into PEL additional data
406d8be1ebdSJayanth Othayoth for_each(traceLog.begin(), traceLog.end(),
407d8be1ebdSJayanth Othayoth [&pelAdditionalData](
408d8be1ebdSJayanth Othayoth std::pair<std::string, std::string>& ele) -> void {
409d8be1ebdSJayanth Othayoth pelAdditionalData.emplace_back(ele.first, ele.second);
410d8be1ebdSJayanth Othayoth });
411d8be1ebdSJayanth Othayoth
412d8be1ebdSJayanth Othayoth openpower::pel::createErrorPEL("org.open_power.PHAL.Error.SpareClock",
413d8be1ebdSJayanth Othayoth jsonCalloutDataList, pelAdditionalData,
414d8be1ebdSJayanth Othayoth Severity::Informational);
415d8be1ebdSJayanth Othayoth }
416d8be1ebdSJayanth Othayoth catch (const std::exception& ex)
417d8be1ebdSJayanth Othayoth {
418d8be1ebdSJayanth Othayoth reset();
419d8be1ebdSJayanth Othayoth throw ex;
420d8be1ebdSJayanth Othayoth }
421d8be1ebdSJayanth Othayoth reset();
422d8be1ebdSJayanth Othayoth }
423d8be1ebdSJayanth Othayoth
processIplErrorCallback(const ipl_error_info & errInfo)4242b211701SJayanth Othayoth void processIplErrorCallback(const ipl_error_info& errInfo)
4256552de05SJayanth Othayoth {
4262b211701SJayanth Othayoth log<level::INFO>(
427e0dd7af4SJayanth Othayoth std::format("processIplErrorCallback: Error type({})",
428cb23cb2dSojayanth static_cast<std::underlying_type<ipl_error_type>::type>(
429cb23cb2dSojayanth errInfo.type))
4302b211701SJayanth Othayoth .c_str());
4312b211701SJayanth Othayoth
432381c3e34SMarri Devender Rao switch (errInfo.type)
4332b211701SJayanth Othayoth {
434381c3e34SMarri Devender Rao case IPL_ERR_OK:
4352b211701SJayanth Othayoth // reset trace log and exit
4362b211701SJayanth Othayoth reset();
437381c3e34SMarri Devender Rao break;
438381c3e34SMarri Devender Rao case IPL_ERR_SBE_BOOT:
439381c3e34SMarri Devender Rao case IPL_ERR_SBE_CHIPOP:
440faaef2acSJayanth Othayoth // handle SBE related failures.
4414079f09dSJayanth Othayoth processSbeBootError();
442381c3e34SMarri Devender Rao break;
443381c3e34SMarri Devender Rao case IPL_ERR_HWP:
444faaef2acSJayanth Othayoth // Handle hwp failure
4452b211701SJayanth Othayoth processBootError(false);
446381c3e34SMarri Devender Rao break;
447381c3e34SMarri Devender Rao case IPL_ERR_PLAT:
448381c3e34SMarri Devender Rao processPlatBootError(errInfo);
449381c3e34SMarri Devender Rao break;
45069708fbbSJayanth Othayoth case IPL_ERR_PRI_PROC_NON_FUNC:
45169708fbbSJayanth Othayoth // Handle non functional boot processor error.
45269708fbbSJayanth Othayoth processNonFunctionalBootProc();
45369708fbbSJayanth Othayoth break;
4549f351b05Sdeepakala-k case IPL_ERR_GUARD_PARTITION_ACCESS:
4559f351b05Sdeepakala-k processGuardPartitionAccessError();
4569f351b05Sdeepakala-k break;
457381c3e34SMarri Devender Rao default:
458faaef2acSJayanth Othayoth createPEL("org.open_power.PHAL.Error.Boot");
459faaef2acSJayanth Othayoth // reset trace log and exit
460faaef2acSJayanth Othayoth reset();
461381c3e34SMarri Devender Rao break;
462faaef2acSJayanth Othayoth }
4632b211701SJayanth Othayoth }
4642b211701SJayanth Othayoth
465db924725Srajerpp1 /**
466db924725Srajerpp1 * @brief addPlanarCallout
467db924725Srajerpp1 *
468db924725Srajerpp1 * This function will add a json for planar callout in the input json list.
469db924725Srajerpp1 * The caller can pass this json list into createErrorPEL to apply the callout.
470db924725Srajerpp1 *
471db924725Srajerpp1 * @param[in,out] jsonCalloutDataList - json list where callout json will be
472db924725Srajerpp1 * emplaced
473db924725Srajerpp1 * @param[in] priority - string indicating priority.
474db924725Srajerpp1 */
addPlanarCallout(json & jsonCalloutDataList,const std::string & priority)475db924725Srajerpp1 static void addPlanarCallout(json& jsonCalloutDataList,
476db924725Srajerpp1 const std::string& priority)
477db924725Srajerpp1 {
478db924725Srajerpp1 json jsonCalloutData;
479db924725Srajerpp1
480db924725Srajerpp1 // Inventory path for planar
481db924725Srajerpp1 jsonCalloutData["InventoryPath"] =
482db924725Srajerpp1 "/xyz/openbmc_project/inventory/system/chassis/motherboard";
483db924725Srajerpp1 jsonCalloutData["Deconfigured"] = false;
484db924725Srajerpp1 jsonCalloutData["Guarded"] = false;
485db924725Srajerpp1 jsonCalloutData["Priority"] = priority;
486db924725Srajerpp1
487db924725Srajerpp1 jsonCalloutDataList.emplace_back(jsonCalloutData);
488db924725Srajerpp1 }
489db924725Srajerpp1
4904d5b5bfeSMarri Devender Rao /**
4914d5b5bfeSMarri Devender Rao * @brief processPoweroffError
4924d5b5bfeSMarri Devender Rao *
4934d5b5bfeSMarri Devender Rao * Creates informational PEL for the PLAT/HWP error occured during poweroff
4944d5b5bfeSMarri Devender Rao *
4954d5b5bfeSMarri Devender Rao * Not adding callouts from FFDC as the hardware errors in the poweroff path
4964d5b5bfeSMarri Devender Rao * should be non-visible. so that we don't throw out extraneous callouts for
4974d5b5bfeSMarri Devender Rao * power errors or because the CEC is just not in an expected state.
4984d5b5bfeSMarri Devender Rao *
4994d5b5bfeSMarri Devender Rao * @param[in] ffdc - FFDC data capturd by the HWP
5004d5b5bfeSMarri Devender Rao * @param[in] ffdc_prefix - prefix string for logging the data.
5014d5b5bfeSMarri Devender Rao */
5024d5b5bfeSMarri Devender Rao
processPoweroffError(FFDC * ffdc,const std::string & ffdc_prefix)5034d5b5bfeSMarri Devender Rao void processPoweroffError(FFDC* ffdc, const std::string& ffdc_prefix)
5044d5b5bfeSMarri Devender Rao {
5054d5b5bfeSMarri Devender Rao try
5064d5b5bfeSMarri Devender Rao {
5074d5b5bfeSMarri Devender Rao log<level::INFO>(
508e0dd7af4SJayanth Othayoth std::format("processPoweroffError: Message[{}]", ffdc->message)
5094d5b5bfeSMarri Devender Rao .c_str());
5104d5b5bfeSMarri Devender Rao
5114d5b5bfeSMarri Devender Rao // To store phal trace and other additional data about ffdc.
5124d5b5bfeSMarri Devender Rao FFDCData pelAdditionalData;
5134d5b5bfeSMarri Devender Rao
5144d5b5bfeSMarri Devender Rao if (ffdc->ffdc_type == FFDC_TYPE_HWP)
5154d5b5bfeSMarri Devender Rao {
5164d5b5bfeSMarri Devender Rao std::string keyWithPrefix(ffdc_prefix + "RC");
5174d5b5bfeSMarri Devender Rao // Adding hardware procedures return code details
5184d5b5bfeSMarri Devender Rao pelAdditionalData.emplace_back(keyWithPrefix,
5194d5b5bfeSMarri Devender Rao ffdc->hwp_errorinfo.rc);
5204d5b5bfeSMarri Devender Rao keyWithPrefix = ffdc_prefix + "RC_DESC";
5214d5b5bfeSMarri Devender Rao pelAdditionalData.emplace_back(keyWithPrefix,
5224d5b5bfeSMarri Devender Rao ffdc->hwp_errorinfo.rc_desc);
5234d5b5bfeSMarri Devender Rao }
5244d5b5bfeSMarri Devender Rao else if ((ffdc->ffdc_type != FFDC_TYPE_NONE) &&
5254d5b5bfeSMarri Devender Rao (ffdc->ffdc_type != FFDC_TYPE_UNSUPPORTED))
5264d5b5bfeSMarri Devender Rao {
5274d5b5bfeSMarri Devender Rao log<level::ERR>(
528e0dd7af4SJayanth Othayoth std::format("Unsupported phal FFDC type to create PEL. "
5294d5b5bfeSMarri Devender Rao "MSG: {}",
5304d5b5bfeSMarri Devender Rao ffdc->message)
5314d5b5bfeSMarri Devender Rao .c_str());
5324d5b5bfeSMarri Devender Rao }
5334d5b5bfeSMarri Devender Rao
5344d5b5bfeSMarri Devender Rao // Adding collected phal logs into PEL additional data
5354d5b5bfeSMarri Devender Rao for_each(traceLog.begin(), traceLog.end(),
5364d5b5bfeSMarri Devender Rao [&pelAdditionalData](
5374d5b5bfeSMarri Devender Rao std::pair<std::string, std::string>& ele) -> void {
5384d5b5bfeSMarri Devender Rao pelAdditionalData.emplace_back(ele.first, ele.second);
5394d5b5bfeSMarri Devender Rao });
5404d5b5bfeSMarri Devender Rao
5414d5b5bfeSMarri Devender Rao openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot", {},
5424d5b5bfeSMarri Devender Rao pelAdditionalData,
5434d5b5bfeSMarri Devender Rao Severity::Informational);
5444d5b5bfeSMarri Devender Rao }
5454d5b5bfeSMarri Devender Rao catch (const std::exception& ex)
5464d5b5bfeSMarri Devender Rao {
5474d5b5bfeSMarri Devender Rao reset();
5484d5b5bfeSMarri Devender Rao throw ex;
5494d5b5bfeSMarri Devender Rao }
5504d5b5bfeSMarri Devender Rao reset();
5514d5b5bfeSMarri Devender Rao }
5524d5b5bfeSMarri Devender Rao
processBootErrorHelper(FFDC * ffdc,const std::string & ffdc_prefix)553db924725Srajerpp1 void processBootErrorHelper(FFDC* ffdc, const std::string& ffdc_prefix)
5542b211701SJayanth Othayoth {
555381c3e34SMarri Devender Rao log<level::INFO>("processBootErrorHelper ");
5566552de05SJayanth Othayoth try
5576552de05SJayanth Othayoth {
5586552de05SJayanth Othayoth log<level::INFO>(
559e0dd7af4SJayanth Othayoth std::format("PHAL FFDC: Return Message[{}]", ffdc->message)
560381c3e34SMarri Devender Rao .c_str());
5616552de05SJayanth Othayoth
562d8be1ebdSJayanth Othayoth // Special handling for spare clock related errors.
563d8be1ebdSJayanth Othayoth if (ffdc->ffdc_type == FFDC_TYPE_SPARE_CLOCK_INFO)
564d8be1ebdSJayanth Othayoth {
565d8be1ebdSJayanth Othayoth processClockInfoErrorHelper(ffdc, ffdc_prefix);
566d8be1ebdSJayanth Othayoth return;
567d8be1ebdSJayanth Othayoth }
5686552de05SJayanth Othayoth // To store callouts details in json format as per pel expectation.
5696552de05SJayanth Othayoth json jsonCalloutDataList;
5706552de05SJayanth Othayoth jsonCalloutDataList = json::array();
5716552de05SJayanth Othayoth
5726552de05SJayanth Othayoth // To store phal trace and other additional data about ffdc.
5736552de05SJayanth Othayoth FFDCData pelAdditionalData;
5746552de05SJayanth Othayoth
575381c3e34SMarri Devender Rao if (ffdc->ffdc_type == FFDC_TYPE_HWP)
5766552de05SJayanth Othayoth {
577db924725Srajerpp1 std::string keyWithPrefix(ffdc_prefix + "RC");
5786552de05SJayanth Othayoth // Adding hardware procedures return code details
579db924725Srajerpp1 pelAdditionalData.emplace_back(keyWithPrefix,
580db924725Srajerpp1 ffdc->hwp_errorinfo.rc);
581db924725Srajerpp1 keyWithPrefix = ffdc_prefix + "RC_DESC";
582db924725Srajerpp1 pelAdditionalData.emplace_back(keyWithPrefix,
583381c3e34SMarri Devender Rao ffdc->hwp_errorinfo.rc_desc);
5846552de05SJayanth Othayoth
5856552de05SJayanth Othayoth // Adding hardware procedures required ffdc data for debug
586381c3e34SMarri Devender Rao for_each(ffdc->hwp_errorinfo.ffdcs_data.begin(),
587381c3e34SMarri Devender Rao ffdc->hwp_errorinfo.ffdcs_data.end(),
588db924725Srajerpp1 [&pelAdditionalData, &ffdc_prefix](
5896552de05SJayanth Othayoth std::pair<std::string, std::string>& ele) -> void {
590db924725Srajerpp1 std::string keyWithPrefix(ffdc_prefix + "FFDC_");
5916552de05SJayanth Othayoth keyWithPrefix.append(ele.first);
5926552de05SJayanth Othayoth
593*1e43be06SPatrick Williams pelAdditionalData.emplace_back(keyWithPrefix,
594*1e43be06SPatrick Williams ele.second);
5956552de05SJayanth Othayoth });
5966552de05SJayanth Othayoth
5976552de05SJayanth Othayoth // Adding hardware callout details
5986552de05SJayanth Othayoth int calloutCount = 0;
599*1e43be06SPatrick Williams for_each(
600*1e43be06SPatrick Williams ffdc->hwp_errorinfo.hwcallouts.begin(),
601381c3e34SMarri Devender Rao ffdc->hwp_errorinfo.hwcallouts.end(),
602db924725Srajerpp1 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
603db924725Srajerpp1 &ffdc_prefix](const HWCallout& hwCallout) -> void {
6046552de05SJayanth Othayoth calloutCount++;
6056552de05SJayanth Othayoth std::stringstream keyPrefix;
606db924725Srajerpp1 keyPrefix << ffdc_prefix << "HW_CO_" << std::setfill('0')
6076552de05SJayanth Othayoth << std::setw(2) << calloutCount << "_";
6086552de05SJayanth Othayoth
6096552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6106552de05SJayanth Othayoth std::string(keyPrefix.str()).append("HW_ID"),
6116552de05SJayanth Othayoth hwCallout.hwid);
6126552de05SJayanth Othayoth
6136552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6146552de05SJayanth Othayoth std::string(keyPrefix.str()).append("PRIORITY"),
6156552de05SJayanth Othayoth hwCallout.callout_priority);
6166552de05SJayanth Othayoth
617db924725Srajerpp1 // Log target details only if entity path is
618db924725Srajerpp1 // available. For example target entity path will not
619db924725Srajerpp1 // be available for non-hwp clock failure.
620db924725Srajerpp1 if (!hwCallout.target_entity_path.empty())
621db924725Srajerpp1 {
6226552de05SJayanth Othayoth phal::TargetInfo targetInfo;
6236552de05SJayanth Othayoth phal::getTgtReqAttrsVal(hwCallout.target_entity_path,
6246552de05SJayanth Othayoth targetInfo);
6256552de05SJayanth Othayoth
6266552de05SJayanth Othayoth std::string locationCode =
6276552de05SJayanth Othayoth std::string(targetInfo.locationCode);
6286552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6296552de05SJayanth Othayoth std::string(keyPrefix.str()).append("LOC_CODE"),
6306552de05SJayanth Othayoth locationCode);
6316552de05SJayanth Othayoth
632*1e43be06SPatrick Williams std::string physPath =
633*1e43be06SPatrick Williams std::string(targetInfo.physDevPath);
6346552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6356552de05SJayanth Othayoth std::string(keyPrefix.str()).append("PHYS_PATH"),
6366552de05SJayanth Othayoth physPath);
637db924725Srajerpp1 }
6386552de05SJayanth Othayoth
6396552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6406552de05SJayanth Othayoth std::string(keyPrefix.str()).append("CLK_POS"),
6416552de05SJayanth Othayoth std::to_string(hwCallout.clkPos));
642db924725Srajerpp1
643db924725Srajerpp1 pelAdditionalData.emplace_back(
644db924725Srajerpp1 std::string(keyPrefix.str()).append("CALLOUT_PLANAR"),
645db924725Srajerpp1 (hwCallout.isPlanarCallout == true ? "true" : "false"));
646db924725Srajerpp1
647db924725Srajerpp1 std::string pelPriority =
648db924725Srajerpp1 getPelPriority(hwCallout.callout_priority);
649db924725Srajerpp1
650db924725Srajerpp1 if (hwCallout.isPlanarCallout)
651db924725Srajerpp1 {
652db924725Srajerpp1 addPlanarCallout(jsonCalloutDataList, pelPriority);
653db924725Srajerpp1 }
6546552de05SJayanth Othayoth });
6556552de05SJayanth Othayoth
6566552de05SJayanth Othayoth // Adding CDG (callout, deconfigure and guard) targets details
6576552de05SJayanth Othayoth calloutCount = 0;
658*1e43be06SPatrick Williams for_each(
659*1e43be06SPatrick Williams ffdc->hwp_errorinfo.cdg_targets.begin(),
660381c3e34SMarri Devender Rao ffdc->hwp_errorinfo.cdg_targets.end(),
661db924725Srajerpp1 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
662db924725Srajerpp1 &ffdc_prefix](const CDG_Target& cdg_tgt) -> void {
6636552de05SJayanth Othayoth calloutCount++;
6646552de05SJayanth Othayoth std::stringstream keyPrefix;
665db924725Srajerpp1 keyPrefix << ffdc_prefix << "CDG_TGT_" << std::setfill('0')
6666552de05SJayanth Othayoth << std::setw(2) << calloutCount << "_";
6676552de05SJayanth Othayoth
6686552de05SJayanth Othayoth phal::TargetInfo targetInfo;
6696552de05SJayanth Othayoth targetInfo.deconfigure = cdg_tgt.deconfigure;
6706552de05SJayanth Othayoth
671*1e43be06SPatrick Williams phal::getTgtReqAttrsVal(cdg_tgt.target_entity_path,
672*1e43be06SPatrick Williams targetInfo);
6736552de05SJayanth Othayoth
674*1e43be06SPatrick Williams std::string locationCode =
675*1e43be06SPatrick Williams std::string(targetInfo.locationCode);
6766552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6776552de05SJayanth Othayoth std::string(keyPrefix.str()).append("LOC_CODE"),
6786552de05SJayanth Othayoth locationCode);
679db924725Srajerpp1 std::string physPath = std::string(targetInfo.physDevPath);
6806552de05SJayanth Othayoth pelAdditionalData.emplace_back(
681*1e43be06SPatrick Williams std::string(keyPrefix.str()).append("PHYS_PATH"),
682*1e43be06SPatrick Williams physPath);
6836552de05SJayanth Othayoth
6846552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6856552de05SJayanth Othayoth std::string(keyPrefix.str()).append("CO_REQ"),
6866552de05SJayanth Othayoth (cdg_tgt.callout == true ? "true" : "false"));
6876552de05SJayanth Othayoth
6886552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6896552de05SJayanth Othayoth std::string(keyPrefix.str()).append("CO_PRIORITY"),
6906552de05SJayanth Othayoth cdg_tgt.callout_priority);
6916552de05SJayanth Othayoth
6926552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6936552de05SJayanth Othayoth std::string(keyPrefix.str()).append("DECONF_REQ"),
6946552de05SJayanth Othayoth (cdg_tgt.deconfigure == true ? "true" : "false"));
6956552de05SJayanth Othayoth
6966552de05SJayanth Othayoth pelAdditionalData.emplace_back(
6976552de05SJayanth Othayoth std::string(keyPrefix.str()).append("GUARD_REQ"),
6986552de05SJayanth Othayoth (cdg_tgt.guard == true ? "true" : "false"));
6996552de05SJayanth Othayoth
7006552de05SJayanth Othayoth pelAdditionalData.emplace_back(
7016552de05SJayanth Othayoth std::string(keyPrefix.str()).append("GUARD_TYPE"),
7026552de05SJayanth Othayoth cdg_tgt.guard_type);
7036552de05SJayanth Othayoth
7046552de05SJayanth Othayoth json jsonCalloutData;
7056552de05SJayanth Othayoth jsonCalloutData["LocationCode"] = locationCode;
7066552de05SJayanth Othayoth std::string pelPriority =
7076552de05SJayanth Othayoth getPelPriority(cdg_tgt.callout_priority);
7086552de05SJayanth Othayoth jsonCalloutData["Priority"] = pelPriority;
7096552de05SJayanth Othayoth
7106552de05SJayanth Othayoth if (targetInfo.mruId != 0)
7116552de05SJayanth Othayoth {
7126552de05SJayanth Othayoth jsonCalloutData["MRUs"] = json::array({
713*1e43be06SPatrick Williams {{"ID", targetInfo.mruId},
714*1e43be06SPatrick Williams {"Priority", pelPriority}},
7156552de05SJayanth Othayoth });
7166552de05SJayanth Othayoth }
7176552de05SJayanth Othayoth jsonCalloutData["Deconfigured"] = cdg_tgt.deconfigure;
7186552de05SJayanth Othayoth jsonCalloutData["Guarded"] = cdg_tgt.guard;
7199883ed5fSJayanth Othayoth jsonCalloutData["GuardType"] = cdg_tgt.guard_type;
720db924725Srajerpp1 jsonCalloutData["EntityPath"] = cdg_tgt.target_entity_path;
7216552de05SJayanth Othayoth
7226552de05SJayanth Othayoth jsonCalloutDataList.emplace_back(jsonCalloutData);
7236552de05SJayanth Othayoth });
7240ac7c38fSJayanth Othayoth // Adding procedure callout
7250ac7c38fSJayanth Othayoth calloutCount = 0;
7260ac7c38fSJayanth Othayoth for_each(
727381c3e34SMarri Devender Rao ffdc->hwp_errorinfo.procedures_callout.begin(),
728381c3e34SMarri Devender Rao ffdc->hwp_errorinfo.procedures_callout.end(),
729db924725Srajerpp1 [&pelAdditionalData, &calloutCount, &jsonCalloutDataList,
730db924725Srajerpp1 &ffdc_prefix](const ProcedureCallout& procCallout) -> void {
7310ac7c38fSJayanth Othayoth calloutCount++;
7320ac7c38fSJayanth Othayoth std::stringstream keyPrefix;
733db924725Srajerpp1 keyPrefix << ffdc_prefix << "PROC_CO_" << std::setfill('0')
7340ac7c38fSJayanth Othayoth << std::setw(2) << calloutCount << "_";
7350ac7c38fSJayanth Othayoth
7360ac7c38fSJayanth Othayoth pelAdditionalData.emplace_back(
7370ac7c38fSJayanth Othayoth std::string(keyPrefix.str()).append("PRIORITY"),
7380ac7c38fSJayanth Othayoth procCallout.callout_priority);
7390ac7c38fSJayanth Othayoth
7400ac7c38fSJayanth Othayoth pelAdditionalData.emplace_back(
7410ac7c38fSJayanth Othayoth std::string(keyPrefix.str()).append("MAINT_PROCEDURE"),
7420ac7c38fSJayanth Othayoth procCallout.proc_callout);
7430ac7c38fSJayanth Othayoth
7440ac7c38fSJayanth Othayoth json jsonCalloutData;
7450ac7c38fSJayanth Othayoth jsonCalloutData["Procedure"] = procCallout.proc_callout;
7460ac7c38fSJayanth Othayoth std::string pelPriority =
7470ac7c38fSJayanth Othayoth getPelPriority(procCallout.callout_priority);
7480ac7c38fSJayanth Othayoth jsonCalloutData["Priority"] = pelPriority;
7490ac7c38fSJayanth Othayoth jsonCalloutDataList.emplace_back(jsonCalloutData);
7500ac7c38fSJayanth Othayoth });
7516552de05SJayanth Othayoth }
752381c3e34SMarri Devender Rao else if ((ffdc->ffdc_type != FFDC_TYPE_NONE) &&
753381c3e34SMarri Devender Rao (ffdc->ffdc_type != FFDC_TYPE_UNSUPPORTED))
7546552de05SJayanth Othayoth {
7556552de05SJayanth Othayoth log<level::ERR>(
756e0dd7af4SJayanth Othayoth std::format("Unsupported phal FFDC type to create PEL. "
7576552de05SJayanth Othayoth "MSG: {}",
758381c3e34SMarri Devender Rao ffdc->message)
7596552de05SJayanth Othayoth .c_str());
7606552de05SJayanth Othayoth }
7616552de05SJayanth Othayoth
7626552de05SJayanth Othayoth // Adding collected phal logs into PEL additional data
7636552de05SJayanth Othayoth for_each(traceLog.begin(), traceLog.end(),
7646552de05SJayanth Othayoth [&pelAdditionalData](
7656552de05SJayanth Othayoth std::pair<std::string, std::string>& ele) -> void {
7666552de05SJayanth Othayoth pelAdditionalData.emplace_back(ele.first, ele.second);
7676552de05SJayanth Othayoth });
7686552de05SJayanth Othayoth
7696552de05SJayanth Othayoth // TODO: #ibm-openbmc/dev/issues/2595 : Once enabled this support,
7706552de05SJayanth Othayoth // callout details is not required to sort in H,M and L orders which
7716552de05SJayanth Othayoth // are expected by pel because, pel will take care for sorting callouts
7726552de05SJayanth Othayoth // based on priority so, now adding support to send callout in order
7736552de05SJayanth Othayoth // i.e High -> Medium -> Low.
774915b38feSPatrick Williams std::sort(jsonCalloutDataList.begin(), jsonCalloutDataList.end(),
7756552de05SJayanth Othayoth [](const json& aEle, const json& bEle) -> bool {
776*1e43be06SPatrick Williams // Considering b element having higher priority than a
777*1e43be06SPatrick Williams // element or Both element will be same priorty (to keep
778*1e43be06SPatrick Williams // same order which are given by phal when two callouts
779*1e43be06SPatrick Williams // are having same priority)
780*1e43be06SPatrick Williams if (((aEle["Priority"] == "M") &&
781*1e43be06SPatrick Williams (bEle["Priority"] == "H")) ||
7826552de05SJayanth Othayoth ((aEle["Priority"] == "L") &&
783*1e43be06SPatrick Williams ((bEle["Priority"] == "H") ||
784*1e43be06SPatrick Williams (bEle["Priority"] == "M"))) ||
7856552de05SJayanth Othayoth (aEle["Priority"] == bEle["Priority"]))
7866552de05SJayanth Othayoth {
7876552de05SJayanth Othayoth return false;
7886552de05SJayanth Othayoth }
7896552de05SJayanth Othayoth
790*1e43be06SPatrick Williams // Considering a element having higher priority than b
791*1e43be06SPatrick Williams // element
7926552de05SJayanth Othayoth return true;
7936552de05SJayanth Othayoth });
7948fe9ff91SJayanth Othayoth openpower::pel::createErrorPEL("org.open_power.PHAL.Error.Boot",
7954d5b5bfeSMarri Devender Rao jsonCalloutDataList, pelAdditionalData,
7964d5b5bfeSMarri Devender Rao Severity::Error);
7976552de05SJayanth Othayoth }
7981a9a5a6aSPatrick Williams catch (const std::exception& ex)
7996552de05SJayanth Othayoth {
8006552de05SJayanth Othayoth reset();
8016552de05SJayanth Othayoth throw ex;
8026552de05SJayanth Othayoth }
8036552de05SJayanth Othayoth reset();
8046552de05SJayanth Othayoth }
8056552de05SJayanth Othayoth
processPlatBootError(const ipl_error_info & errInfo)806381c3e34SMarri Devender Rao void processPlatBootError(const ipl_error_info& errInfo)
807381c3e34SMarri Devender Rao {
808381c3e34SMarri Devender Rao log<level::INFO>("processPlatBootError ");
809381c3e34SMarri Devender Rao
810381c3e34SMarri Devender Rao // Collecting ffdc details from phal
811381c3e34SMarri Devender Rao FFDC* ffdc = reinterpret_cast<FFDC*>(errInfo.private_data);
812381c3e34SMarri Devender Rao try
813381c3e34SMarri Devender Rao {
8144d5b5bfeSMarri Devender Rao if (util::isHostPoweringOff())
8154d5b5bfeSMarri Devender Rao {
8164d5b5bfeSMarri Devender Rao processPoweroffError(ffdc, "PLAT_");
8174d5b5bfeSMarri Devender Rao }
8184d5b5bfeSMarri Devender Rao else
8194d5b5bfeSMarri Devender Rao {
820db924725Srajerpp1 processBootErrorHelper(ffdc, "PLAT_");
821381c3e34SMarri Devender Rao }
8224d5b5bfeSMarri Devender Rao }
823381c3e34SMarri Devender Rao catch (const std::exception& ex)
824381c3e34SMarri Devender Rao {
825381c3e34SMarri Devender Rao log<level::ERR>(
826e0dd7af4SJayanth Othayoth std::format("processPlatBootError: exception({})", ex.what())
827381c3e34SMarri Devender Rao .c_str());
828381c3e34SMarri Devender Rao throw ex;
829381c3e34SMarri Devender Rao }
830381c3e34SMarri Devender Rao }
831381c3e34SMarri Devender Rao
processBootError(bool status)832381c3e34SMarri Devender Rao void processBootError(bool status)
833381c3e34SMarri Devender Rao {
834381c3e34SMarri Devender Rao log<level::INFO>(
835e0dd7af4SJayanth Othayoth std::format("processBootError: status({})", status).c_str());
836381c3e34SMarri Devender Rao
837381c3e34SMarri Devender Rao try
838381c3e34SMarri Devender Rao {
839381c3e34SMarri Devender Rao // return If no failure during hwp execution
840381c3e34SMarri Devender Rao if (status)
841381c3e34SMarri Devender Rao return;
842381c3e34SMarri Devender Rao // Collecting ffdc details from phal
843381c3e34SMarri Devender Rao FFDC ffdc;
844381c3e34SMarri Devender Rao libekb_get_ffdc(ffdc);
845381c3e34SMarri Devender Rao
8464d5b5bfeSMarri Devender Rao if (util::isHostPoweringOff())
8474d5b5bfeSMarri Devender Rao {
8484d5b5bfeSMarri Devender Rao processPoweroffError(&ffdc, "HWP_");
8494d5b5bfeSMarri Devender Rao }
8504d5b5bfeSMarri Devender Rao else
8514d5b5bfeSMarri Devender Rao {
852db924725Srajerpp1 processBootErrorHelper(&ffdc, "HWP_");
853381c3e34SMarri Devender Rao }
8544d5b5bfeSMarri Devender Rao }
855381c3e34SMarri Devender Rao catch (const std::exception& ex)
856381c3e34SMarri Devender Rao {
857381c3e34SMarri Devender Rao log<level::ERR>(
858e0dd7af4SJayanth Othayoth std::format("processBootError: exception({})", ex.what()).c_str());
859381c3e34SMarri Devender Rao throw ex;
860381c3e34SMarri Devender Rao }
861381c3e34SMarri Devender Rao }
862381c3e34SMarri Devender Rao
processSbeBootError()8634079f09dSJayanth Othayoth void processSbeBootError()
8644079f09dSJayanth Othayoth {
8654079f09dSJayanth Othayoth log<level::INFO>("processSbeBootError : Entered ");
8664079f09dSJayanth Othayoth
8674079f09dSJayanth Othayoth using namespace openpower::phal::sbe;
8684079f09dSJayanth Othayoth
8694079f09dSJayanth Othayoth // To store phal trace and other additional data about ffdc.
8704079f09dSJayanth Othayoth FFDCData pelAdditionalData;
8714079f09dSJayanth Othayoth
8724079f09dSJayanth Othayoth // Adding collected phal logs into PEL additional data
8734079f09dSJayanth Othayoth for_each(
8744079f09dSJayanth Othayoth traceLog.begin(), traceLog.end(),
8754079f09dSJayanth Othayoth [&pelAdditionalData](std::pair<std::string, std::string>& ele) -> void {
8764079f09dSJayanth Othayoth pelAdditionalData.emplace_back(ele.first, ele.second);
8774079f09dSJayanth Othayoth });
8784079f09dSJayanth Othayoth
8794079f09dSJayanth Othayoth // reset the trace log and counter
8804079f09dSJayanth Othayoth reset();
8814079f09dSJayanth Othayoth
8824079f09dSJayanth Othayoth // get primary processor to collect FFDC/Dump information.
8834079f09dSJayanth Othayoth struct pdbg_target* procTarget;
8844079f09dSJayanth Othayoth pdbg_for_each_class_target("proc", procTarget)
8854079f09dSJayanth Othayoth {
8864079f09dSJayanth Othayoth if (openpower::phal::isPrimaryProc(procTarget))
8874079f09dSJayanth Othayoth break;
8884079f09dSJayanth Othayoth procTarget = nullptr;
8894079f09dSJayanth Othayoth }
8904079f09dSJayanth Othayoth // check valid primary processor is available
8914079f09dSJayanth Othayoth if (procTarget == nullptr)
8924079f09dSJayanth Othayoth {
8934079f09dSJayanth Othayoth log<level::ERR>("processSbeBootError: fail to get primary processor");
8940a516defSJayanth Othayoth // Add BMC code callout and create PEL
8950a516defSJayanth Othayoth json jsonCalloutDataList;
8960a516defSJayanth Othayoth jsonCalloutDataList = json::array();
8970a516defSJayanth Othayoth json jsonCalloutData;
8980a516defSJayanth Othayoth jsonCalloutData["Procedure"] = "BMC0001";
8990a516defSJayanth Othayoth jsonCalloutData["Priority"] = "H";
9000a516defSJayanth Othayoth jsonCalloutDataList.emplace_back(jsonCalloutData);
9010a516defSJayanth Othayoth openpower::pel::createErrorPEL(
9020a516defSJayanth Othayoth "org.open_power.Processor.Error.SbeBootFailure",
9034d5b5bfeSMarri Devender Rao jsonCalloutDataList, {}, Severity::Error);
9044079f09dSJayanth Othayoth return;
9054079f09dSJayanth Othayoth }
9064079f09dSJayanth Othayoth // SBE error object.
9074079f09dSJayanth Othayoth sbeError_t sbeError;
9084079f09dSJayanth Othayoth bool dumpIsRequired = false;
9094079f09dSJayanth Othayoth
9104079f09dSJayanth Othayoth try
9114079f09dSJayanth Othayoth {
9124079f09dSJayanth Othayoth // Capture FFDC information on primary processor
9134079f09dSJayanth Othayoth sbeError = captureFFDC(procTarget);
9144079f09dSJayanth Othayoth }
915faaef2acSJayanth Othayoth catch (const phalError_t& phalError)
9164079f09dSJayanth Othayoth {
9174079f09dSJayanth Othayoth // Fail to collect FFDC information , trigger Dump
9184079f09dSJayanth Othayoth log<level::ERR>(
919e0dd7af4SJayanth Othayoth std::format("captureFFDC: Exception({})", phalError.what())
920faaef2acSJayanth Othayoth .c_str());
9214079f09dSJayanth Othayoth dumpIsRequired = true;
9224079f09dSJayanth Othayoth }
9234079f09dSJayanth Othayoth
924006641efSJayanth Othayoth std::string event;
925006641efSJayanth Othayoth
9264079f09dSJayanth Othayoth if ((sbeError.errType() == SBE_FFDC_NO_DATA) ||
9274079f09dSJayanth Othayoth (sbeError.errType() == SBE_CMD_TIMEOUT) || (dumpIsRequired))
9284079f09dSJayanth Othayoth {
929006641efSJayanth Othayoth event = "org.open_power.Processor.Error.SbeBootTimeout";
930006641efSJayanth Othayoth dumpIsRequired = true;
931006641efSJayanth Othayoth }
932006641efSJayanth Othayoth else
933006641efSJayanth Othayoth {
934006641efSJayanth Othayoth event = "org.open_power.Processor.Error.SbeBootFailure";
9354079f09dSJayanth Othayoth }
9364079f09dSJayanth Othayoth // SRC6 : [0:15] chip position
937006641efSJayanth Othayoth uint32_t index = pdbg_target_index(procTarget);
938006641efSJayanth Othayoth pelAdditionalData.emplace_back("SRC6", std::to_string(index << 16));
9394079f09dSJayanth Othayoth // Create SBE Error with FFDC data.
940*1e43be06SPatrick Williams auto logId =
941*1e43be06SPatrick Williams createSbeErrorPEL(event, sbeError, pelAdditionalData, procTarget);
942006641efSJayanth Othayoth
943006641efSJayanth Othayoth if (dumpIsRequired)
944006641efSJayanth Othayoth {
945006641efSJayanth Othayoth using namespace openpower::phal::dump;
946006641efSJayanth Othayoth DumpParameters dumpParameters = {logId, index, SBE_DUMP_TIMEOUT,
947006641efSJayanth Othayoth DumpType::SBE};
948006641efSJayanth Othayoth try
949006641efSJayanth Othayoth {
950006641efSJayanth Othayoth requestDump(dumpParameters);
951006641efSJayanth Othayoth }
952006641efSJayanth Othayoth catch (const std::runtime_error& e)
953006641efSJayanth Othayoth {
954006641efSJayanth Othayoth // Allowing call back to handle the error gracefully.
955006641efSJayanth Othayoth log<level::ERR>("Dump collection failed");
956006641efSJayanth Othayoth // TODO revist error handling.
957006641efSJayanth Othayoth }
958006641efSJayanth Othayoth }
9594079f09dSJayanth Othayoth }
9604079f09dSJayanth Othayoth
processGuardPartitionAccessError()9619f351b05Sdeepakala-k void processGuardPartitionAccessError()
9629f351b05Sdeepakala-k {
9639f351b05Sdeepakala-k // Adding collected phal logs into PEL additional data
9649f351b05Sdeepakala-k FFDCData pelAdditionalData;
9659f351b05Sdeepakala-k
9669f351b05Sdeepakala-k for_each(
9679f351b05Sdeepakala-k traceLog.begin(), traceLog.end(),
9689f351b05Sdeepakala-k [&pelAdditionalData](std::pair<std::string, std::string>& ele) -> void {
9699f351b05Sdeepakala-k pelAdditionalData.emplace_back(ele.first, ele.second);
9709f351b05Sdeepakala-k });
9719f351b05Sdeepakala-k
9729f351b05Sdeepakala-k openpower::pel::createPEL("org.open_power.PHAL.Error.GuardPartitionAccess",
9739f351b05Sdeepakala-k pelAdditionalData);
9749f351b05Sdeepakala-k }
9759f351b05Sdeepakala-k
reset()9766552de05SJayanth Othayoth void reset()
9776552de05SJayanth Othayoth {
9786552de05SJayanth Othayoth // reset the trace log and counter
9796552de05SJayanth Othayoth traceLog.clear();
9806552de05SJayanth Othayoth counter = 0;
9816552de05SJayanth Othayoth }
9826552de05SJayanth Othayoth
pDBGLogTraceCallbackHelper(int,const char * fmt,va_list ap)9836552de05SJayanth Othayoth void pDBGLogTraceCallbackHelper(int, const char* fmt, va_list ap)
9846552de05SJayanth Othayoth {
9856552de05SJayanth Othayoth processLogTraceCallback(NULL, fmt, ap);
9866552de05SJayanth Othayoth }
9876552de05SJayanth Othayoth } // namespace detail
9886552de05SJayanth Othayoth
getLogLevelFromEnv(const char * env,const uint8_t dValue)9896552de05SJayanth Othayoth static inline uint8_t getLogLevelFromEnv(const char* env, const uint8_t dValue)
9906552de05SJayanth Othayoth {
9916552de05SJayanth Othayoth auto logLevel = dValue;
9926552de05SJayanth Othayoth try
9936552de05SJayanth Othayoth {
9946552de05SJayanth Othayoth if (const char* env_p = std::getenv(env))
9956552de05SJayanth Othayoth {
9966552de05SJayanth Othayoth logLevel = std::stoi(env_p);
9976552de05SJayanth Othayoth }
9986552de05SJayanth Othayoth }
9991a9a5a6aSPatrick Williams catch (const std::exception& e)
10006552de05SJayanth Othayoth {
10016552de05SJayanth Othayoth log<level::ERR>(("Conversion Failure"), entry("ENVIRONMENT=%s", env),
10026552de05SJayanth Othayoth entry("EXCEPTION=%s", e.what()));
10036552de05SJayanth Othayoth }
10046552de05SJayanth Othayoth return logLevel;
10056552de05SJayanth Othayoth }
10066552de05SJayanth Othayoth
addBootErrorCallbacks()10076552de05SJayanth Othayoth void addBootErrorCallbacks()
10086552de05SJayanth Othayoth {
10096552de05SJayanth Othayoth // Get individual phal repos log level from environment variable
10106552de05SJayanth Othayoth // and update the log level.
10116552de05SJayanth Othayoth pdbg_set_loglevel(getLogLevelFromEnv("PDBG_LOG", PDBG_INFO));
10126552de05SJayanth Othayoth libekb_set_loglevel(getLogLevelFromEnv("LIBEKB_LOG", LIBEKB_LOG_IMP));
10136552de05SJayanth Othayoth ipl_set_loglevel(getLogLevelFromEnv("IPL_LOG", IPL_INFO));
10146552de05SJayanth Othayoth
10156552de05SJayanth Othayoth // add callback for debug traces
10166552de05SJayanth Othayoth pdbg_set_logfunc(detail::pDBGLogTraceCallbackHelper);
10176552de05SJayanth Othayoth libekb_set_logfunc(detail::processLogTraceCallback, NULL);
10186552de05SJayanth Othayoth ipl_set_logfunc(detail::processLogTraceCallback, NULL);
10196552de05SJayanth Othayoth
10206552de05SJayanth Othayoth // add callback for ipl failures
10212b211701SJayanth Othayoth ipl_set_error_callback_func(detail::processIplErrorCallback);
10226552de05SJayanth Othayoth }
10236552de05SJayanth Othayoth
10246552de05SJayanth Othayoth } // namespace pel
10256552de05SJayanth Othayoth } // namespace openpower
1026