bmc-reset: add support to write a cfam

A future commit requires this support so refactor the getCFAM a bit to
move some shared code to a common function and add putCFAM

Tested:
- Verified the putCFAM worked as expected when called on p10bmc hardware

Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
Change-Id: I349505aa19bf0164a2f01d133a47298fabbf3299
diff --git a/procedures/phal/common_utils.cpp b/procedures/phal/common_utils.cpp
index 708df40..6f2995e 100644
--- a/procedures/phal/common_utils.cpp
+++ b/procedures/phal/common_utils.cpp
@@ -82,42 +82,106 @@
     }
 }
 
-uint32_t getCFAM(struct pdbg_target* procTarget, const uint32_t reg,
-                 uint32_t& val)
+pdbg_target* getFsiTarget(struct pdbg_target* procTarget)
 {
-    auto procIdx = pdbg_target_index(procTarget);
-    char path[16];
-    sprintf(path, "/proc%d/pib", procIdx);
 
-    pdbg_target* pibTarget = pdbg_target_from_path(nullptr, path);
-    if (nullptr == pibTarget)
+    struct pdbg_target* fsiTarget = nullptr;
+    pdbg_for_each_target("fsi", procTarget, fsiTarget)
     {
-        log<level::ERR>("pib path of target not found",
-                        entry("TARGET_PATH=%s", path));
-        return -1;
+        // grab first one we find
+        break;
+    }
+    if (!fsiTarget)
+    {
+        log<level::ERR>(
+            "fsi path of target not found",
+            entry("PROC_TARGET_PATH=%s", pdbg_target_path(procTarget)));
+        return nullptr;
     }
 
+    return fsiTarget;
+}
+
+uint32_t probeTarget(struct pdbg_target* procTarget)
+{
+    struct pdbg_target* pibTarget = nullptr;
+    pdbg_for_each_target("pib", procTarget, pibTarget)
+    {
+        // grab first one we find
+        break;
+    }
+    if (!pibTarget)
+    {
+        log<level::ERR>(
+            "pib path of target not found",
+            entry("PROC_TARGET_PATH=%s", pdbg_target_path(procTarget)));
+        return -1;
+    }
     // probe PIB and ensure it's enabled
     if (PDBG_TARGET_ENABLED != pdbg_target_probe(pibTarget))
     {
-        log<level::ERR>("probe on pib target failed");
+        log<level::ERR>(
+            "probe on pib target failed",
+            entry("PIB_TARGET_PATH=%s", pdbg_target_path(pibTarget)));
         return -1;
     }
+    return 0;
+}
 
-    // now build FSI path and read the input reg
-    sprintf(path, "/proc%d/fsi", procIdx);
-    pdbg_target* fsiTarget = pdbg_target_from_path(nullptr, path);
+uint32_t getCFAM(struct pdbg_target* procTarget, const uint32_t reg,
+                 uint32_t& val)
+{
+
+    pdbg_target* fsiTarget = getFsiTarget(procTarget);
     if (nullptr == fsiTarget)
     {
-        log<level::ERR>("fsi path or target not found");
+        log<level::ERR>("getCFAM: fsi path or target not found");
         return -1;
     }
 
-    auto rc = fsi_read(fsiTarget, reg, &val);
+    auto rc = probeTarget(procTarget);
     if (rc)
     {
-        log<level::ERR>("failed to read input cfam", entry("RC=%u", rc),
-                        entry("CFAM=0x%X", reg), entry("TARGET_PATH=%s", path));
+        // probe function logged details to journal
+        return rc;
+    }
+
+    rc = fsi_read(fsiTarget, reg, &val);
+    if (rc)
+    {
+        log<level::ERR>(
+            "failed to read input cfam", entry("RC=%u", rc),
+            entry("CFAM=0x%X", reg),
+            entry("FSI_TARGET_PATH=%s", pdbg_target_path(fsiTarget)));
+        return rc;
+    }
+    return 0;
+}
+
+uint32_t putCFAM(struct pdbg_target* procTarget, const uint32_t reg,
+                 const uint32_t val)
+{
+    pdbg_target* fsiTarget = getFsiTarget(procTarget);
+    if (nullptr == fsiTarget)
+    {
+        log<level::ERR>("putCFAM: fsi path or target not found");
+        return -1;
+    }
+
+    auto rc = probeTarget(procTarget);
+    if (rc)
+    {
+        // probe function logged details to journal
+        return rc;
+    }
+
+    rc = fsi_write(fsiTarget, reg, val);
+    if (rc)
+    {
+        log<level::ERR>(
+            "failed to write input cfam", entry("RC=%u", rc),
+            entry("CFAM=0x%X", reg),
+            entry("FSI_TARGET_PATH=%s", pdbg_target_path(fsiTarget)));
         return rc;
     }
     return 0;
diff --git a/procedures/phal/common_utils.hpp b/procedures/phal/common_utils.hpp
index 2d9d57b..277272c 100644
--- a/procedures/phal/common_utils.hpp
+++ b/procedures/phal/common_utils.hpp
@@ -25,7 +25,7 @@
 /**
  *  @brief  Check if primary processor or not
  *
- *  @param[in] procTarget - Target to check if primary or not
+ *  @param[in] procTarget - Processor target to check if primary or not
  *
  *  @return True/False
  */
@@ -34,7 +34,7 @@
 /**
  *  @brief  Read the input CFAM register
  *
- *  @param[in]  procTarget - The Target to perform the operation on
+ *  @param[in]  procTarget - Processor target to perform the operation on
  *  @param[in]  reg - The register address to read
  *  @param[out] val - The value read from the register
  *
@@ -43,5 +43,38 @@
 uint32_t getCFAM(struct pdbg_target* procTarget, const uint32_t reg,
                  uint32_t& val);
 
+/**
+ *  @brief  Write the input CFAM register
+ *
+ *  @param[in]  procTarget - Processor target to perform the operation on
+ *  @param[in]  reg - The register address to write
+ *  @param[out] val - The value to write to the register
+ *
+ *  @return 0 on success, non-0 on failure
+ */
+uint32_t putCFAM(struct pdbg_target* procTarget, const uint32_t reg,
+                 const uint32_t val);
+
+/**
+ *  @brief  Helper function to find FSI target needed for FSI operations
+ *
+ *  @param[in]  procTarget - Processor target to find the FSI target on
+ *
+ *  @return Valid pointer to FSI target on success, nullptr on failure
+ */
+pdbg_target* getFsiTarget(struct pdbg_target* procTarget);
+
+/**
+ *  @brief  Helper function to probe the processor target
+ *
+ *  The probe call only has to happen once per application start so ensure
+ *  this function only probes once no matter how many times it's called.
+ *
+ *  @param[in]  procTarget - Processor target to probe
+ *
+ *  @return 0 on success, non-0 on failure
+ */
+uint32_t probeTarget(struct pdbg_target* procTarget);
+
 } // namespace phal
 } // namespace openpower