openpower-pels: Create guard using libguard

Replace CreateWithEntityPath D-Bus method with guard library calls for
creating guard entries, as CreateWithEntityPath is not an approved dbus
method.

Tested and the guard record is created with the corresponding PEL id

```
before injecting the error
root@p10bmc:~# guard -l
No unresolved records to display

After injecting error, the guard is created using the PEL ID
root@p10bmc:~# guard -l
ID         | ERROR      | Type            | Path
0x00000001 | 0x5000592b | unrecoverable   | physical:sys-0/node-0/proc-0/eq-1/fc-0/core-0
root@p10bmc:~# peltool -l
{
    "0x5000592B": {
        "SRC":                  "BD13E510",
        "Message":              "Error Signature: 0x20DA0020 0x00000001 0x4D740407",
        "PLID":                 "0x5000592B",
        "CreatorID":            "BMC",
        "Subsystem":            "Processor Unit (CPU)",
        "Commit Time":          "10/17/2024 09:54:22",
        "Sev":                  "Unrecoverable Error",
        "CompID":               "bmc hw diags"
    }
}
```

Change-Id: I7531bce403206beaa119aea0a621e6b47d28ffd0
Signed-off-by: deepakala-k <deepakala.karthikeyan@ibm.com>
diff --git a/extensions/openpower-pels/data_interface.cpp b/extensions/openpower-pels/data_interface.cpp
index 84645b7..599b63f 100644
--- a/extensions/openpower-pels/data_interface.cpp
+++ b/extensions/openpower-pels/data_interface.cpp
@@ -95,7 +95,6 @@
     "xyz.openbmc_project.State.Decorator.OperationalStatus";
 constexpr auto logSetting = "xyz.openbmc_project.Logging.Settings";
 constexpr auto associationDef = "xyz.openbmc_project.Association.Definitions";
-constexpr auto hwIsolationCreate = "org.open_power.HardwareIsolation.Create";
 constexpr auto hwIsolationEntry = "xyz.openbmc_project.HardwareIsolation.Entry";
 constexpr auto association = "xyz.openbmc_project.Association";
 constexpr auto biosConfigMgr = "xyz.openbmc_project.BIOSConfig.Manager";
@@ -235,6 +234,15 @@
     {
 #ifdef PEL_ENABLE_PHAL
         initPHAL();
+        try
+        {
+            libguard::libguard_init(false);
+        }
+        catch (libguard::exception::GuardException& e)
+        {
+            lg2::error("Exception to init the guard {ERROR}", "ERROR",
+                       e.what());
+        }
 #endif
     }
     else
@@ -687,38 +695,20 @@
     return ret;
 }
 
+#ifdef PEL_ENABLE_PHAL
 void DataInterface::createGuardRecord(const std::vector<uint8_t>& binPath,
-                                      const std::string& type,
-                                      const std::string& logPath) const
+                                      GardType eGardType, uint32_t plid) const
 {
     try
     {
-        auto method = _bus.new_method_call(
-            service_name::hwIsolation, object_path::hwIsolation,
-            interface::hwIsolationCreate, "CreateWithEntityPath");
-        method.append(binPath, type, sdbusplus::message::object_path(logPath));
-        // Note: hw isolation "CreateWithEntityPath" got dependency on logging
-        // api's. Making d-bus call no reply type to avoid cyclic dependency.
-        // Added minimal timeout to catch initial failures.
-        // Need to revisit this design later to avoid cyclic dependency.
-        constexpr auto hwIsolationTimeout = 100000; // in micro seconds
-        _bus.call_noreply(method, hwIsolationTimeout);
+        libguard::create(binPath, plid, eGardType);
     }
-
-    catch (const sdbusplus::exception_t& e)
+    catch (libguard::exception::GuardException& e)
     {
-        std::string errName = e.name();
-        // SD_BUS_ERROR_TIMEOUT error is expected, due to PEL api dependency
-        // mentioned above. Ignoring the error.
-        if (errName != SD_BUS_ERROR_TIMEOUT)
-        {
-            lg2::error("GUARD D-Bus call exception. Path={PATH}, "
-                       "interface = {IFACE}, exception = {ERROR}",
-                       "PATH", object_path::hwIsolation, "IFACE",
-                       interface::hwIsolationCreate, "ERROR", e);
-        }
+        lg2::error("Exception to create the guard {ERROR}", "ERROR", e.what());
     }
 }
+#endif
 
 void DataInterface::createProgressSRC(
     const uint64_t& priSRC, const std::vector<uint8_t>& srcStruct) const
diff --git a/extensions/openpower-pels/data_interface.hpp b/extensions/openpower-pels/data_interface.hpp
index 93a0e47..bdf93c1 100644
--- a/extensions/openpower-pels/data_interface.hpp
+++ b/extensions/openpower-pels/data_interface.hpp
@@ -3,6 +3,11 @@
 #include "dbus_types.hpp"
 #include "dbus_watcher.hpp"
 
+#ifdef PEL_ENABLE_PHAL
+#include <libguard/guard_interface.hpp>
+#include <libguard/include/guard_record.hpp>
+#endif
+
 #include <phosphor-logging/lg2.hpp>
 #include <sdbusplus/bus.hpp>
 #include <sdbusplus/bus/match.hpp>
@@ -12,6 +17,11 @@
 #include <fstream>
 #include <unordered_map>
 
+#ifdef PEL_ENABLE_PHAL
+using GardType = openpower::guard::GardType;
+namespace libguard = openpower::guard;
+#endif
+
 namespace openpower
 {
 namespace pels
@@ -443,16 +453,17 @@
     static std::pair<std::string, std::string>
         extractConnectorFromLocCode(const std::string& locationCode);
 
+#ifdef PEL_ENABLE_PHAL
     /**
      * @brief Create guard record
      *
      *  @param[in] binPath: phal devtree binary path used as key
-     *  @param[in] type: Guard type
-     *  @param[in] logPath: error log entry object path
+     *  @param[in] eGardType: Guard type enum value
+     *  @param[in] plid: Pel ID
      */
     virtual void createGuardRecord(const std::vector<uint8_t>& binPath,
-                                   const std::string& type,
-                                   const std::string& logPath) const = 0;
+                                   GardType eGardType, uint32_t plid) const = 0;
+#endif
 
     /**
      * @brief Create Progress SRC property on the boot progress
@@ -856,16 +867,17 @@
      */
     bool getQuiesceOnError() const override;
 
+#ifdef PEL_ENABLE_PHAL
     /**
      * @brief Create guard record
      *
      *  @param[in] binPath: phal devtree binary path used as key
-     *  @param[in] type: Guard type
-     *  @param[in] logPath: error log entry object path
+     *  @param[in] eGardType: Guard type enum value
+     *   @param[in] plid: pel id to be associated to the guard record
      */
     void createGuardRecord(const std::vector<uint8_t>& binPath,
-                           const std::string& type,
-                           const std::string& logPath) const override;
+                           GardType eGardType, uint32_t plid) const override;
+#endif
 
     /**
      * @brief Create Progress SRC property on the boot progress
diff --git a/extensions/openpower-pels/meson.build b/extensions/openpower-pels/meson.build
index db57568..cff4e68 100644
--- a/extensions/openpower-pels/meson.build
+++ b/extensions/openpower-pels/meson.build
@@ -32,6 +32,7 @@
         cpp.find_library('pdbg'),
         cpp.find_library('ekb'),
         cpp.find_library('phal'),
+        cpp.find_library('libguard'),
     ]
     extra_args += [
         '-DPEL_ENABLE_PHAL',
diff --git a/extensions/openpower-pels/pel.cpp b/extensions/openpower-pels/pel.cpp
index 8b635e5..9f09a01 100644
--- a/extensions/openpower-pels/pel.cpp
+++ b/extensions/openpower-pels/pel.cpp
@@ -34,6 +34,11 @@
 #ifdef PEL_ENABLE_PHAL
 #include "phal_service_actions.hpp"
 #include "sbe_ffdc_handler.hpp"
+
+#include <libguard/guard_interface.hpp>
+#include <libguard/include/guard_record.hpp>
+
+namespace libguard = openpower::guard;
 #endif
 
 #include <sys/stat.h>
@@ -175,8 +180,7 @@
 
 #ifdef PEL_ENABLE_PHAL
     auto path = std::string(OBJ_ENTRY) + '/' + std::to_string(obmcLogID);
-    openpower::pels::phal::createServiceActions(callouts, path, dataIface,
-                                                plid());
+    openpower::pels::phal::createServiceActions(callouts, 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 f40821e..f0a60e9 100644
--- a/extensions/openpower-pels/phal_service_actions.cpp
+++ b/extensions/openpower-pels/phal_service_actions.cpp
@@ -3,10 +3,14 @@
 #include <attributes_info.H>
 #include <libphal.H>
 
+#include <libguard/guard_interface.hpp>
+#include <libguard/include/guard_record.hpp>
 #include <phosphor-logging/lg2.hpp>
 
 #include <format>
 
+using GardType = openpower::guard::GardType;
+
 namespace openpower
 {
 namespace pels
@@ -15,34 +19,32 @@
 {
 
 /**
- * @brief Helper function to get EntrySeverity based on
- *        the given GardType
+ * @brief Helper function to get gard type based on
+ *        the given GardType string
  *
- * @param[in] guardType openpower gard type
+ * @param[in] guardTypeStr guard type enum value as a string
  *
- * @return EntrySeverity on success
+ * @return GardType on success
  *         Empty optional on failure
  */
-std::optional<EntrySeverity> getEntrySeverityType(const std::string& guardType)
+std::optional<GardType> getGardType(const std::string& guardTypeStr)
 {
-    if ((guardType == "GARD_Unrecoverable") || (guardType == "GARD_Fatal"))
+    const std::unordered_map<std::string, GardType> gardTypeMap = {
+        {"GARD_Fatal", GardType::GARD_Fatal},
+        {"GARD_User_Manual", GardType::GARD_User_Manual},
+        {"GARD_Predictive", GardType::GARD_Predictive},
+        {"GARD_Spare", GardType::GARD_Spare},
+        {"GARD_Unrecoverable", GardType::GARD_Unrecoverable},
+    };
+
+    auto it = gardTypeMap.find(guardTypeStr);
+    if (it != gardTypeMap.end())
     {
-        return EntrySeverity::Critical;
-    }
-    else if (guardType == "GARD_User_Manual")
-    {
-        return EntrySeverity::Manual;
-    }
-    else if (guardType == "GARD_Predictive")
-    {
-        return EntrySeverity::Warning;
+        return it->second;
     }
     else
     {
-        lg2::error(
-            "GUARD: Unsupported GuardType [{GUARD_TYPE}] was given to get the "
-            "hardware isolation entry severity type",
-            "GUARD_TYPE", guardType);
+        lg2::error("Invalid GardType ({GUARDTYPE})", "GUARDTYPE", guardTypeStr);
     }
     return std::nullopt;
 }
@@ -57,11 +59,10 @@
  * "Guarded": boolean, true to create gurad records.
  *
  * @param[in] jsonCallouts - The array of JSON callouts, or an empty object.
- * @param[in] path - The BMC error log object path
+ * @param[in] plid - The PEL ID to be associated with the guard
  * @param[in] dataIface - The DataInterface object
  */
-void createGuardRecords(const nlohmann::json& jsonCallouts,
-                        const std::string& path,
+void createGuardRecords(const nlohmann::json& jsonCallouts, uint32_t plid,
                         const DataInterfaceBase& dataIface)
 {
     if (jsonCallouts.empty())
@@ -100,33 +101,28 @@
             auto entityPath = _callout.at("EntityPath").get<EntityPath>();
 
             std::stringstream ss;
-            for (uint32_t a = 0; a < sizeof(ATTR_PHYS_BIN_PATH_Type); a++)
-            {
-                ss << " 0x" << std::hex << static_cast<int>(entityPath[a]);
-            }
+            std::ranges::for_each(entityPath, [&ss](const auto& ele) {
+                ss << std::format("{:02x} ", ele);
+            });
+
             std::string s = ss.str();
             lg2::info("GUARD: ({GUARD_TARGET})", "GUARD_TARGET", s);
 
             // Get Guard type
-            auto severity = EntrySeverity::Warning;
+            std::string guardTypeStr = "GARD_Predictive";
             if (!_callout.contains("GuardType"))
             {
-                lg2::error("GUARD: doesn't have Severity, setting to warning");
+                lg2::error(
+                    "GUARD: doesn't have Severity, setting to GARD_Predictive");
             }
             else
             {
-                auto guardType = _callout.at("GuardType").get<std::string>();
-                // convert GuardType to severity type.
-                auto sType = getEntrySeverityType(guardType);
-                if (sType.has_value())
-                {
-                    severity = sType.value();
-                }
+                guardTypeStr = _callout.at("GuardType").get<std::string>();
             }
-            // Create guard record
-            auto type = sdbusplus::xyz::openbmc_project::HardwareIsolation::
-                server::convertForMessage(severity);
-            dataIface.createGuardRecord(entityPath, type, path);
+
+            GardType eGuardType =
+                getGardType(guardTypeStr).value_or(GardType::GARD_Predictive);
+            dataIface.createGuardRecord(entityPath, eGuardType, plid);
         }
         catch (const std::exception& e)
         {
@@ -149,8 +145,7 @@
  * @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)
+void createDeconfigRecords(const nlohmann::json& jsonCallouts, uint32_t plid)
 {
     using namespace openpower::phal::pdbg;
 
@@ -204,12 +199,10 @@
 }
 
 void createServiceActions(const nlohmann::json& jsonCallouts,
-                          const std::string& path,
-                          const DataInterfaceBase& dataIface,
-                          const uint32_t plid)
+                          const DataInterfaceBase& dataIface, uint32_t plid)
 {
     // Create Guard records.
-    createGuardRecords(jsonCallouts, path, dataIface);
+    createGuardRecords(jsonCallouts, plid, dataIface);
     // Create Deconfigure records.
     createDeconfigRecords(jsonCallouts, plid);
 }
diff --git a/extensions/openpower-pels/phal_service_actions.hpp b/extensions/openpower-pels/phal_service_actions.hpp
index 8032663..0dcd1ff 100644
--- a/extensions/openpower-pels/phal_service_actions.hpp
+++ b/extensions/openpower-pels/phal_service_actions.hpp
@@ -12,21 +12,15 @@
 namespace phal
 {
 
-using EntrySeverity =
-    sdbusplus::server::xyz::openbmc_project::hardware_isolation::Entry::Type;
-
 /**
  * @brief Helper function to create service actions in the PEL
  *
  * @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 uint32_t plid);
+                          const DataInterfaceBase& dataIface, uint32_t plid);
 } // namespace phal
 } // namespace pels
 } // namespace openpower