Implement support for POZ FFDC with multiple FFDC packets

This commit implements support for POZ FFDC, where multiple FFDC packets
can be returned after executing an SBE chip-op. This differs from the
processor SBE chip-op, which typically returns only a single FFDC packet
upon a chip-op failure.

Key aspects of the implementation:
- Each FFDC packet is associated with a unique SLID id, allowing for the
  identification of separate and unrelated FFDC packets within the
collection.
- Each unique SLID is treated as an independent PEL, ensuring that each
  FFDC packet is logged separately.
- FFDC data may be present even if the chip-op completes successfully.
  In such cases, PELs are logged, but the chip-op is not considered a
  failure.

Tests:
  Testing the proc FFDC to make sure no regression
  Testing POZ FFDC and making sure multiple PELs are logged
  Testing FFDC with chip-op success

Change-Id: I8c70bc8df9249c5b9841baef7b5dbe0a6f22e08d
Signed-off-by: Dhruvaraj Subhashchandran <dhruvaraj@in.ibm.com>
diff --git a/dump/create_pel.cpp b/dump/create_pel.cpp
index f6b15ee..7f79fa5 100644
--- a/dump/create_pel.cpp
+++ b/dump/create_pel.cpp
@@ -1,6 +1,7 @@
 #include "create_pel.hpp"
 
 #include "dump_utils.hpp"
+#include "sbe_consts.hpp"
 
 #include <fcntl.h>
 #include <libekb.H>
@@ -26,12 +27,14 @@
 {
 
 using namespace phosphor::logging;
+using namespace openpower::dump::SBE;
 constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging";
 constexpr auto loggingInterface = "xyz.openbmc_project.Logging.Create";
 constexpr auto opLoggingInterface = "org.open_power.Logging.PEL";
 
 uint32_t createSbeErrorPEL(const std::string& event, const sbeError_t& sbeError,
-                           const FFDCData& ffdcData, const Severity severity)
+                           const FFDCData& ffdcData, const Severity severity,
+                           const std::optional<PELFFDCInfo>& pelFFDCInfoOpt)
 {
     uint32_t plid = 0;
     std::unordered_map<std::string, std::string> additionalData = {
@@ -46,27 +49,24 @@
         additionalData.emplace(data);
     }
 
-    std::vector<std::tuple<
-        sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat,
-        uint8_t, uint8_t, sdbusplus::message::unix_fd>>
-        pelFFDCInfo;
-
-    // get SBE ffdc file descriptor
-    auto fd = sbeError.getFd();
+    PELFFDCInfo pelFFDCInfo;
+    if (pelFFDCInfoOpt)
+    {
+        pelFFDCInfo = *pelFFDCInfoOpt;
+    }
 
     // Negative fd value indicates error case or invalid file
     // No need of special processing , just log error with additional ffdc.
-    if (fd > 0)
+    else if (sbeError.getFd() > 0)
     {
         // Refer phosphor-logging/extensions/openpower-pels/README.md section
         // "Self Boot Engine(SBE) First Failure Data Capture(FFDC) Support"
         // for details of related to createPEL with SBE FFDC information
         // usin g CreateWithFFDCFiles api.
-        pelFFDCInfo.emplace_back(
-            std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
-                                Create::FFDCFormat::Custom,
-                            static_cast<uint8_t>(0xCB),
-                            static_cast<uint8_t>(0x01), sbeError.getFd()));
+        pelFFDCInfo.emplace_back(std::make_tuple(
+            sdbusplus::xyz::openbmc_project::Logging::server::Create::
+                FFDCFormat::Custom,
+            FFDC_FORMAT_SUBTYPE, FFDC_FORMAT_VERSION, sbeError.getFd()));
     }
     try
     {
@@ -106,6 +106,48 @@
     return plid;
 }
 
+openpower::dump::pel::Severity convertSeverityToEnum(uint8_t severity)
+{
+    switch (severity)
+    {
+        case openpower::phal::FAPI2_ERRL_SEV_RECOVERED:
+            return openpower::dump::pel::Severity::Informational;
+        case openpower::phal::FAPI2_ERRL_SEV_PREDICTIVE:
+            return openpower::dump::pel::Severity::Warning;
+        case openpower::phal::FAPI2_ERRL_SEV_UNRECOVERABLE:
+            return openpower::dump::pel::Severity::Error;
+        default:
+            return openpower::dump::pel::Severity::Error;
+    }
+}
+
+void processFFDCPackets(const openpower::phal::sbeError_t& sbeError,
+                        const std::string& event,
+                        openpower::dump::pel::FFDCData& pelAdditionalData)
+{
+    const auto& ffdcFileList = sbeError.getFfdcFileList();
+    for (const auto& [slid, ffdcTuple] : ffdcFileList)
+    {
+        uint8_t severity;
+        int fd;
+        std::filesystem::path path;
+        std::tie(severity, fd, path) = ffdcTuple;
+
+        Severity logSeverity = convertSeverityToEnum(severity);
+
+        PELFFDCInfo pelFFDCInfo;
+        pelFFDCInfo.emplace_back(
+            std::make_tuple(sdbusplus::xyz::openbmc_project::Logging::server::
+                                Create::FFDCFormat::Custom,
+                            FFDC_FORMAT_SUBTYPE, FFDC_FORMAT_VERSION, fd));
+
+        auto logId = openpower::dump::pel::createSbeErrorPEL(
+            event, sbeError, pelAdditionalData, logSeverity);
+        lg2::info("Logged PEL {PELID} for SLID {SLID}", "PELID", logId, "SLID",
+                  slid);
+    }
+}
+
 FFDCFile::FFDCFile(const json& pHALCalloutData) :
     calloutData(pHALCalloutData.dump()),
     calloutFile("/tmp/phalPELCalloutsJson.XXXXXX"), fileFD(-1)