PEL: Add deconfigure records

PHAL enabled systems enabled harwdare deconfigure (set state
to non-functional, do any Deconfigure actions and create a
deconfigure Record in cec devtree) during PEL create.
This function enabled only for the PEL create request with
required "Deconfigured" key in the callout information.

libphal api is used for creating deconfigure records.

Tested: Verified deconfigure records in the cec devtree

root@xxxx:~# attributes read /proc0 ATTR_HWAS_STATE
ATTR_HWAS_STATE = 0x50000684 0x40

Signed-off-by: Jayanth Othayoth <ojayanth@in.ibm.com>
Change-Id: I77b630da00d9c1f2807aac06a0220e4c14c79fdb
diff --git a/extensions/openpower-pels/meson.build b/extensions/openpower-pels/meson.build
index 4659945..bfa3889 100644
--- a/extensions/openpower-pels/meson.build
+++ b/extensions/openpower-pels/meson.build
@@ -45,6 +45,7 @@
         dependency('libdt-api'),
         cpp.find_library('pdbg'),
         cpp.find_library('ekb'),
+        cpp.find_library('phal'),
     ]
     extra_args += [
         '-DPEL_ENABLE_PHAL',
diff --git a/extensions/openpower-pels/pel.cpp b/extensions/openpower-pels/pel.cpp
index 30fbf51..ed4c3f3 100644
--- a/extensions/openpower-pels/pel.cpp
+++ b/extensions/openpower-pels/pel.cpp
@@ -159,7 +159,8 @@
 
 #ifdef PEL_ENABLE_PHAL
     auto path = std::string(OBJ_ENTRY) + '/' + std::to_string(obmcLogID);
-    openpower::pels::phal::createServiceActions(callouts, path, dataIface);
+    openpower::pels::phal::createServiceActions(callouts, path, dataIface,
+                                                plid());
 #endif
 
     // Store in the PEL any important debug data created while
diff --git a/extensions/openpower-pels/phal_service_actions.cpp b/extensions/openpower-pels/phal_service_actions.cpp
index a534ddf..a65fe21 100644
--- a/extensions/openpower-pels/phal_service_actions.cpp
+++ b/extensions/openpower-pels/phal_service_actions.cpp
@@ -2,6 +2,7 @@
 
 #include <attributes_info.H>
 #include <fmt/format.h>
+#include <libphal.H>
 
 #include <phosphor-logging/log.hpp>
 
@@ -139,13 +140,92 @@
     }
 }
 
+/**
+ * @brief Helper function to create deconfig records.
+ *
+ * User need to fill the JSON callouts array with below keywords/data
+ * "EntityPath": entity path of the hardware from the PHAL device tree.
+ * "Deconfigured": boolean, true to create deconfigure records.
+ *
+ * libphal api is used for creating deconfigure records, which includes
+ * update HWAS_STATE attribute to non functional with PLID information.
+ *
+ * @param[in] jsonCallouts - The array of JSON callouts, or an empty object.
+ * @param[in] plid - PLID value
+ */
+void createDeconfigRecords(const nlohmann::json& jsonCallouts,
+                           const uint32_t plid)
+{
+    using namespace openpower::phal::pdbg;
+
+    if (jsonCallouts.empty())
+    {
+        return;
+    }
+
+    if (!jsonCallouts.is_array())
+    {
+        log<level::ERR>("Deconfig: Callout JSON isn't an array");
+        return;
+    }
+    for (const auto& _callout : jsonCallouts)
+    {
+        try
+        {
+            // Check Callout data conatains Guarded requests.
+            if (!_callout.contains("Deconfigured"))
+            {
+                continue;
+            }
+
+            if (!_callout.at("Deconfigured").get<bool>())
+            {
+                continue;
+            }
+
+            if (!_callout.contains("EntityPath"))
+            {
+                log<level::ERR>(
+                    "Deconfig: Callout data missing EntityPath information");
+                continue;
+            }
+            using EntityPath = std::vector<uint8_t>;
+            auto entityPath = _callout.at("EntityPath").get<EntityPath>();
+            log<level::INFO>("Deconfig: adding deconfigure record");
+            // convert to libphal required format.
+            ATTR_PHYS_BIN_PATH_Type physBinPath;
+            std::copy(entityPath.begin(), entityPath.end(), physBinPath);
+            // libphal api to deconfigure the target
+            if (!pdbg_targets_init(NULL))
+            {
+                log<level::ERR>("pdbg_targets_init failed, skipping deconfig "
+                                "record update");
+                return;
+            }
+            openpower::phal::pdbg::deconfigureTgt(physBinPath, plid);
+        }
+        catch (const std::exception& e)
+        {
+            log<level::INFO>(
+                fmt::format(
+                    "Deconfig: Failed to create records, exception:({})",
+                    e.what())
+                    .c_str());
+        }
+    }
+}
+
 void createServiceActions(const nlohmann::json& jsonCallouts,
                           const std::string& path,
-                          const DataInterfaceBase& dataIface)
+                          const DataInterfaceBase& dataIface,
+                          const uint32_t plid)
 {
     // Create Guard records.
     createGuardRecords(jsonCallouts, path, dataIface);
+    // Create Deconfigure records.
+    createDeconfigRecords(jsonCallouts, plid);
 }
+
 } // namespace phal
 } // namespace pels
 } // namespace openpower
diff --git a/extensions/openpower-pels/phal_service_actions.hpp b/extensions/openpower-pels/phal_service_actions.hpp
index 84a700e..8d8652c 100644
--- a/extensions/openpower-pels/phal_service_actions.hpp
+++ b/extensions/openpower-pels/phal_service_actions.hpp
@@ -21,10 +21,12 @@
  * @param[in] jsonCallouts - The array of JSON callouts, or an empty object.
  * @param[in] path - The BMC error log object path
  * @param[in] dataIface - The DataInterface object
+ * @param[in] plid -  the PLID
  */
 void createServiceActions(const nlohmann::json& jsonCallouts,
                           const std::string& path,
-                          const DataInterfaceBase& dataIface);
+                          const DataInterfaceBase& dataIface,
+                          const uint32_t plid);
 } // namespace phal
 } // namespace pels
 } // namespace openpower