PEL: Look for callouts in an FFDC JSON file

The PEL constructor takes a list of files that should be added as
UserData sections for FFDC.  If one of those files has its format set to
JSON, and its subtype set to 0xCA, this will mean it contains a JSON
array of callouts to add to the PEL.

This commit will look for that type and subtype, and then pass the
callout JSON through to the SRC class.  A future commit will add the
callouts from the JSON to the PEL.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: Iec0ca0ad0ae11cc957b8fda880d97116f342d72d
diff --git a/extensions/openpower-pels/pel.cpp b/extensions/openpower-pels/pel.cpp
index 85ab741..2391e52 100644
--- a/extensions/openpower-pels/pel.cpp
+++ b/extensions/openpower-pels/pel.cpp
@@ -42,6 +42,7 @@
 using namespace phosphor::logging;
 
 constexpr auto unknownValue = "Unknown";
+constexpr uint8_t jsonCalloutSubtype = 0xCA;
 
 PEL::PEL(const message::Entry& regEntry, uint32_t obmcLogID, uint64_t timestamp,
          phosphor::logging::Entry::Level severity,
@@ -49,12 +50,29 @@
          const DataInterfaceBase& dataIface)
 {
     std::map<std::string, std::vector<std::string>> debugData;
+    nlohmann::json callouts;
 
     _ph = std::make_unique<PrivateHeader>(regEntry.componentID, obmcLogID,
                                           timestamp);
     _uh = std::make_unique<UserHeader>(regEntry, severity, dataIface);
 
-    auto src = std::make_unique<SRC>(regEntry, additionalData, dataIface);
+    // Extract any callouts embedded in an FFDC file.
+    if (!ffdcFiles.empty())
+    {
+        try
+        {
+            callouts = getCalloutJSON(ffdcFiles);
+        }
+        catch (const std::exception& e)
+        {
+            debugData.emplace("FFDC file JSON callouts error",
+                              std::vector<std::string>{e.what()});
+        }
+    }
+
+    auto src =
+        std::make_unique<SRC>(regEntry, additionalData, callouts, dataIface);
+
     if (!src->getDebugData().empty())
     {
         // Something didn't go as planned
@@ -413,6 +431,32 @@
     return true;
 }
 
+nlohmann::json PEL::getCalloutJSON(const PelFFDC& ffdcFiles)
+{
+    nlohmann::json callouts;
+
+    for (const auto& file : ffdcFiles)
+    {
+        if ((file.format == UserDataFormat::json) &&
+            (file.subType == jsonCalloutSubtype))
+        {
+            auto data = util::readFD(file.fd);
+            if (data.empty())
+            {
+                throw std::runtime_error{
+                    "Could not get data from JSON callout file descriptor"};
+            }
+
+            std::string jsonString{data.begin(), data.begin() + data.size()};
+
+            callouts = nlohmann::json::parse(jsonString);
+            break;
+        }
+    }
+
+    return callouts;
+}
+
 namespace util
 {