Guard support for PELs

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: Ib32a3ccbf165bb9a541fa37fcdaf9da4c8e63f81
diff --git a/analyzer/create_pel.cpp b/analyzer/create_pel.cpp
index 64463b2..9295dca 100644
--- a/analyzer/create_pel.cpp
+++ b/analyzer/create_pel.cpp
@@ -26,6 +26,7 @@
 {
     FFDC_SIGNATURES    = 0x01,
     FFDC_REGISTER_DUMP = 0x02,
+    FFDC_GUARD         = 0x03,
 
     // For the callout section, the value of '0xCA' is required per the
     // phosphor-logging openpower-pel extention spec.
@@ -109,6 +110,24 @@
 
 //------------------------------------------------------------------------------
 
+void __addGuardList(const ServiceData& i_servData,
+                    std::vector<util::FFDCFile>& io_userDataFiles)
+{
+    // Get the JSON output for the guard list.
+    nlohmann::json json;
+    i_servData.getGuardList(json);
+
+    // Create a new entry for the user data section containing the guard list.
+    io_userDataFiles.emplace_back(util::FFDCFormat::JSON, FFDC_GUARD,
+                                  FFDC_VERSION1);
+
+    // Use a file stream to write the JSON to file.
+    std::ofstream o{io_userDataFiles.back().getPath()};
+    o << json;
+}
+
+//------------------------------------------------------------------------------
+
 void __captureSignatureList(const libhei::IsolationData& i_isoData,
                             std::vector<util::FFDCFile>& io_userDataFiles)
 {
@@ -278,6 +297,9 @@
     // Add the list of callouts to the PEL.
     __addCalloutList(i_servData, userDataFiles);
 
+    // Add the list of guard requests to the PEL.
+    __addGuardList(i_servData, userDataFiles);
+
     // Capture the complete signature list.
     __captureSignatureList(i_isoData, userDataFiles);
 
diff --git a/analyzer/service_data.hpp b/analyzer/service_data.hpp
index eff85d8..560fc72 100644
--- a/analyzer/service_data.hpp
+++ b/analyzer/service_data.hpp
@@ -149,6 +149,54 @@
 };
 
 /**
+ * @brief A service event requiring hardware to be guarded.
+ */
+class Guard
+{
+  public:
+    /** Supported guard types. */
+    enum Type
+    {
+        NONE,      ///< Do not guard
+        FATAL,     ///< Guard on fatal error (cannot recover resource)
+        NON_FATAL, ///< Guard on non-fatal error (can recover resource)
+    };
+
+  public:
+    /**
+     * @brief Constructor from components.
+     * @param i_path The hardware path to guard.
+     * @param i_type The guard type.
+     */
+    Guard(const std::string& i_path, Type i_type) :
+        iv_path(i_path), iv_type(i_type)
+    {}
+
+  private:
+    /** The hardware path to guard. */
+    const std::string iv_path;
+
+    /** The guard type. */
+    const Type iv_type;
+
+  public:
+    void getJson(nlohmann::json& j) const
+    {
+        // clang-format off
+        static const std::map<Type, std::string> m =
+        {
+            {NONE,      "NONE"},
+            {FATAL,     "FATAL"},
+            {NON_FATAL, "NON_FATAL"},
+        };
+        // clang-format on
+
+        nlohmann::json c = {{"Path", iv_path}, {"Type", m.at(iv_type)}};
+        j.emplace_back(c);
+    }
+};
+
+/**
  * @brief Data regarding required service actions based on the hardware error
  *        analysis.
  */
@@ -171,13 +219,24 @@
     /** The list of callouts that will be added to a PEL. */
     std::vector<std::shared_ptr<Callout>> iv_calloutList;
 
+    /** The list of hardware guard requests. Some information will be added to
+     * the PEL, but the actual guard record will be created after submitting the
+     * PEL. */
+    std::vector<std::shared_ptr<Guard>> iv_guardList;
+
   public:
-    /** Add a callout to the callout list. */
+    /** Add a callout to the list. */
     void addCallout(const std::shared_ptr<Callout>& i_callout)
     {
         iv_calloutList.push_back(i_callout);
     }
 
+    /** Add a guard request to the list. */
+    void addGuard(const std::shared_ptr<Guard>& i_guard)
+    {
+        iv_guardList.push_back(i_guard);
+    }
+
     /**
      * @brief Iterates the callout list and returns the json attached to each
      *        callout in the list.
@@ -192,6 +251,21 @@
             c->getJson(o_json);
         }
     }
+
+    /**
+     * @brief Iterates the guard list and returns the json attached to each
+     *        guard request in the list.
+     * @param o_json The returned json data.
+     */
+    void getGuardList(nlohmann::json& o_json) const
+    {
+        o_json.clear(); // Ensure we are starting with a clean list.
+
+        for (const auto& g : iv_guardList)
+        {
+            g->getJson(o_json);
+        }
+    }
 };
 
 } // namespace analyzer