PHAL: Added non functional boot processor failure handling

Added support to create PELs' specific to non functional
boot processor related failure during boot window.

Implemented "NonFunctionalBootProc" message registry
specific PEL function and special callouts to these type
of failures.

Tested: verified PEL manually.

Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
Change-Id: I17c208197a9fd08b1a0aca519da4e03813862255
diff --git a/extensions/phal/phal_error.cpp b/extensions/phal/phal_error.cpp
index 5bfd9f0..a53ba77 100644
--- a/extensions/phal/phal_error.cpp
+++ b/extensions/phal/phal_error.cpp
@@ -261,6 +261,71 @@
     return it->second;
 }
 
+/**
+ * @brief Helper function to create PEL for non functional boot
+ *        processor related failure.
+ * This function adds the BMC code callout as priority 1 to fix
+ * devtree related software issue. Incase the issue still persist
+ * after reboot recommend to replacing the primary processor.
+ */
+void processNonFunctionalBootProc()
+{
+    json jsonCalloutDataList;
+    json jsonProcedCallout;
+    // Add BMC code callout
+    jsonProcedCallout["Procedure"] = "BMC0001";
+    jsonProcedCallout["Priority"] = "H";
+    jsonCalloutDataList.emplace_back(std::move(jsonProcedCallout));
+
+    // get primary processor
+    struct pdbg_target* procTarget;
+    pdbg_for_each_class_target("proc", procTarget)
+    {
+        if (openpower::phal::isPrimaryProc(procTarget))
+            break;
+        procTarget = nullptr;
+    }
+    // check valid primary processor is available
+    if (procTarget == nullptr)
+    {
+        log<level::ERR>(
+            "processNonFunctionalBootProc: fail to get primary processor");
+    }
+    else
+    {
+        try
+        {
+            ATTR_LOCATION_CODE_Type locationCode = {'\0'};
+            // Get location code information
+            openpower::phal::pdbg::getLocationCode(procTarget, locationCode);
+            json jsonProcCallout;
+            jsonProcCallout["LocationCode"] = locationCode;
+            jsonProcCallout["Deconfigured"] = false;
+            jsonProcCallout["Guarded"] = false;
+            jsonProcCallout["Priority"] = "M";
+            jsonCalloutDataList.emplace_back(std::move(jsonProcCallout));
+        }
+        catch (const std::exception& e)
+        {
+            log<level::ERR>(fmt::format("getLocationCode({}): Exception({})",
+                                        pdbg_target_path(procTarget), e.what())
+                                .c_str());
+        }
+    }
+    // Adding collected phal logs into PEL additional data
+    FFDCData pelAdditionalData;
+    for_each(
+        traceLog.begin(), traceLog.end(),
+        [&pelAdditionalData](std::pair<std::string, std::string>& ele) -> void {
+            pelAdditionalData.emplace_back(ele.first, ele.second);
+        });
+    openpower::pel::createErrorPEL(
+        "org.open_power.PHAL.Error.NonFunctionalBootProc", jsonCalloutDataList,
+        pelAdditionalData);
+    // reset trace log and exit
+    reset();
+}
+
 void processIplErrorCallback(const ipl_error_info& errInfo)
 {
     log<level::INFO>(
@@ -285,6 +350,10 @@
         case IPL_ERR_PLAT:
             processPlatBootError(errInfo);
             break;
+        case IPL_ERR_PRI_PROC_NON_FUNC:
+            // Handle non functional boot processor error.
+            processNonFunctionalBootProc();
+            break;
         default:
             createPEL("org.open_power.PHAL.Error.Boot");
             // reset trace log and exit