xref: /openbmc/openpower-proc-control/extensions/phal/phal_error.cpp (revision 1e43be06b83f426360cab248c60822c242bbd544)
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