Add support for clock callout resolutions

Signed-off-by: Zane Shelley <zshelle@us.ibm.com>
Change-Id: I67f02a2fafaa63a0bafaa1116150da35ef4dece1
diff --git a/analyzer/callout.hpp b/analyzer/callout.hpp
index cee3dd1..51cf4ed 100644
--- a/analyzer/callout.hpp
+++ b/analyzer/callout.hpp
@@ -110,6 +110,39 @@
 
 inline const Procedure Procedure::NEXTLVL{"NEXTLVL"};
 
+/** @brief Container class for clock callout service actions. */
+class ClockType
+{
+  public:
+    /** Oscillator reference clock 0. */
+    static const ClockType OSC_REF_CLOCK_0;
+
+    /** Oscillator reference clock 1. */
+    static const ClockType OSC_REF_CLOCK_1;
+
+  private:
+    /**
+     * @brief Constructor from components.
+     * @param i_string The string representation of the procedure used for
+     *                 callouts.
+     */
+    explicit ClockType(const std::string& i_string) : iv_string(i_string) {}
+
+  private:
+    /** The string representation of the procedure used for callouts. */
+    const std::string iv_string;
+
+  public:
+    /** iv_string accessor */
+    std::string getString() const
+    {
+        return iv_string;
+    }
+};
+
+inline const ClockType ClockType::OSC_REF_CLOCK_0{"OSC_REF_CLOCK_0"};
+inline const ClockType ClockType::OSC_REF_CLOCK_1{"OSC_REF_CLOCK_1"};
+
 } // namespace callout
 
 } // namespace analyzer
diff --git a/analyzer/ras-data/data/ras-data-p10-10.json b/analyzer/ras-data/data/ras-data-p10-10.json
index 8bc89bc..e0303ae 100644
--- a/analyzer/ras-data/data/ras-data-p10-10.json
+++ b/analyzer/ras-data/data/ras-data-p10-10.json
@@ -59,11 +59,11 @@
         "pau7": [ { "type": "callout_unit", "name": "pau7", "priority": "MED", "guard": true } ],
 
         "rcs_osc_error_0": [
-            { "type": "callout_clock", "position": 0, "priority": "HIGH", "guard": true },
+            { "type": "callout_clock", "name": "OSC_REF_CLOCK_0", "priority": "HIGH", "guard": true },
             { "type": "action", "name": "self_L" }
         ],
         "rcs_osc_error_1": [
-            { "type": "callout_clock", "position": 1, "priority": "HIGH", "guard": true },
+            { "type": "callout_clock", "name": "OSC_REF_CLOCK_1", "priority": "HIGH", "guard": true },
             { "type": "action", "name": "self_L" }
         ],
         "pll_unlock_0": [
diff --git a/analyzer/ras-data/data/ras-data-p10-20.json b/analyzer/ras-data/data/ras-data-p10-20.json
index 1295ba5..7ae692b 100644
--- a/analyzer/ras-data/data/ras-data-p10-20.json
+++ b/analyzer/ras-data/data/ras-data-p10-20.json
@@ -59,11 +59,11 @@
         "pau7": [ { "type": "callout_unit", "name": "pau7", "priority": "MED", "guard": true } ],
 
         "rcs_osc_error_0": [
-            { "type": "callout_clock", "position": 0, "priority": "HIGH", "guard": true },
+            { "type": "callout_clock", "name": "OSC_REF_CLOCK_0", "priority": "HIGH", "guard": true },
             { "type": "action", "name": "self_L" }
         ],
         "rcs_osc_error_1": [
-            { "type": "callout_clock", "position": 1, "priority": "HIGH", "guard": true },
+            { "type": "callout_clock", "name": "OSC_REF_CLOCK_1", "priority": "HIGH", "guard": true },
             { "type": "action", "name": "self_L" }
         ],
         "pll_unlock_0": [
diff --git a/analyzer/ras-data/ras-data-definition.md b/analyzer/ras-data/ras-data-definition.md
index 6603494..2538230 100644
--- a/analyzer/ras-data/ras-data-definition.md
+++ b/analyzer/ras-data/ras-data-definition.md
@@ -169,10 +169,17 @@
 | Keyword  | Description                                                       |
 |----------|-------------------------------------------------------------------|
 | type     | value (string): `callout_clock`                                   |
-| position | value (integer): 0 or 1                                           |
+| name     | See `clock type` table below.                                     |
 | priority | See `priority` table above.                                       |
 | guard    | See `guard` table above.                                          |
 
+Supported clock types:
+
+| Clock Type      | Description                                                |
+|-----------------|------------------------------------------------------------|
+| OSC_REF_CLOCK_0 | Oscillator reference clock 0                               |
+| OSC_REF_CLOCK_1 | Oscillator reference clock 1                               |
+
 #### 5.1.7) action type `callout_procedure`
 
 This will request to callout a service procedure.
@@ -180,7 +187,7 @@
 | Keyword  | Description                                                       |
 |----------|-------------------------------------------------------------------|
 | type     | value (string): `callout_procedure`                               |
-| name     | The `procedures` table below.                                     |
+| name     | See `procedures` table below.                                     |
 | priority | See `priority` table above.                                       |
 
 Supported procedures:
@@ -197,7 +204,7 @@
 | Keyword  | Description                                                       |
 |----------|-------------------------------------------------------------------|
 | type     | value (string): `callout_part`                                    |
-| name     | The `parts` table below.                                          |
+| name     | See `parts` table below.                                          |
 | priority | See `priority` table above.                                       |
 
 Supported parts:
diff --git a/analyzer/ras-data/ras-data-parser.cpp b/analyzer/ras-data/ras-data-parser.cpp
index 559a947..d59c289 100644
--- a/analyzer/ras-data/ras-data-parser.cpp
+++ b/analyzer/ras-data/ras-data-parser.cpp
@@ -185,13 +185,20 @@
         }
         else if ("callout_clock" == type)
         {
-            auto position = a.at("position").get<unsigned int>();
+            auto name     = a.at("name").get<std::string>();
             auto priority = a.at("priority").get<std::string>();
             auto guard    = a.at("guard").get<bool>();
 
-            // TODO
-            trace::inf("callout_clock: position=%u priority=%s guard=%c",
-                       position, priority.c_str(), guard ? 'T' : 'F');
+            // clang-format off
+            static const std::map<std::string, callout::ClockType> m =
+            {
+                {"OSC_REF_CLOCK_0", callout::ClockType::OSC_REF_CLOCK_0},
+                {"OSC_REF_CLOCK_1", callout::ClockType::OSC_REF_CLOCK_1},
+            };
+            // clang-format on
+
+            o_list->push(std::make_shared<ClockCalloutResolution>(
+                m.at(name), getPriority(priority), guard));
         }
         else if ("callout_procedure" == type)
         {
diff --git a/analyzer/ras-data/schema/ras-data-schema-v01.json b/analyzer/ras-data/schema/ras-data-schema-v01.json
index 05f18cc..9ec7150 100644
--- a/analyzer/ras-data/schema/ras-data-schema-v01.json
+++ b/analyzer/ras-data/schema/ras-data-schema-v01.json
@@ -158,13 +158,13 @@
                                     }
                                 },
                                 "then": {
-                                    "required": [ "priority", "guard", "position" ],
-                                    "not": { "required": [ "name" ] },
+                                    "required": [ "name", "priority", "guard" ],
                                     "properties": {
-                                        "position": {
-                                            "type": "integer",
-                                            "minimum": 0,
-                                            "maximum": 1
+                                        "name": {
+                                            "enum": [
+                                                "OSC_REF_CLOCK_0",
+                                                "OSC_REF_CLOCK_1"
+                                            ]
                                         }
                                     }
                                 }
diff --git a/analyzer/resolution.cpp b/analyzer/resolution.cpp
index a20be83..354ccbc 100644
--- a/analyzer/resolution.cpp
+++ b/analyzer/resolution.cpp
@@ -49,6 +49,43 @@
 
 //------------------------------------------------------------------------------
 
+void ClockCalloutResolution::resolve(ServiceData& io_sd) const
+{
+    // Add the callout to the service data.
+    // TODO: For P10, the callout is simply the backplane. There isn't a devtree
+    //       object for this, yet. So will need to hardcode the location code
+    //       for now. In the future, we will need a mechanism to make this data
+    //       driven.
+    nlohmann::json callout;
+    callout["LocationCode"] = "P0";
+    callout["Priority"]     = iv_priority.getUserDataString();
+    io_sd.addCallout(callout);
+
+    // Add the guard info to the service data.
+    // TODO: Still waiting for clock targets to be defined in the device tree.
+    //       For get the processor path for the FFDC.
+    // static const std::map<callout::ClockType, std::string> m = {
+    //     {callout::ClockType::OSC_REF_CLOCK_0, ""},
+    //     {callout::ClockType::OSC_REF_CLOCK_1, ""},
+    // };
+    // auto target = std::string{util::pdbg::getPath(m.at(iv_clockType))};
+    // auto guardPath = util::pdbg::getPhysDevPath(target);
+    // Guard guard = io_sd.addGuard(guardPath, iv_guard);
+    auto target    = util::pdbg::getTrgt(io_sd.getRootCause().getChip());
+    auto guardPath = util::pdbg::getPhysDevPath(target);
+
+    // Add the callout FFDC to the service data.
+    nlohmann::json ffdc;
+    ffdc["Callout Type"] = "Clock Callout";
+    ffdc["Clock Type"]   = iv_clockType.getString();
+    ffdc["Target"]       = guardPath;
+    ffdc["Priority"]     = iv_priority.getRegistryString();
+    ffdc["Guard Type"]   = ""; // TODO: guard.getString();
+    io_sd.addCalloutFFDC(ffdc);
+}
+
+//------------------------------------------------------------------------------
+
 void ProcedureCalloutResolution::resolve(ServiceData& io_sd) const
 {
     // Add the actual callout to the service data.
diff --git a/analyzer/resolution.hpp b/analyzer/resolution.hpp
index 44638be..1574d04 100644
--- a/analyzer/resolution.hpp
+++ b/analyzer/resolution.hpp
@@ -56,6 +56,36 @@
     void resolve(ServiceData& io_sd) const override;
 };
 
+/** @brief Resolves a clock callout service event. */
+class ClockCalloutResolution : public Resolution
+{
+  public:
+    /**
+     * @brief Constructor from components.
+     * @param i_clockType The clock type.
+     * @param i_priority  The callout priority.
+     * @param i_guard     The guard type for this callout.
+     */
+    ClockCalloutResolution(const callout::ClockType& i_clockType,
+                           const callout::Priority& i_priority, bool i_guard) :
+        iv_clockType(i_clockType),
+        iv_priority(i_priority), iv_guard(i_guard)
+    {}
+
+  private:
+    /** The clock type. */
+    const callout::ClockType iv_clockType;
+
+    /** The callout priority. */
+    const callout::Priority iv_priority;
+
+    /** True, if guard is required. False, otherwise. */
+    const bool iv_guard;
+
+  public:
+    void resolve(ServiceData& io_sd) const override;
+};
+
 /** @brief Resolves a procedure callout service event. */
 class ProcedureCalloutResolution : public Resolution
 {