PEL: Add support for raw symbolic FRUs and procs

Allow the FRUIdentity and Callout objects to take the raw maintenance
procedure and symbolic FRU names as opposed to just the PEL message
registry names.  This will allow the values to come from sources
besides the registry, such as the device tree used by PHAL.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I4171fb7128ae1b1b5e3e635f7f95b7f7df7c6638
diff --git a/extensions/openpower-pels/callout.cpp b/extensions/openpower-pels/callout.cpp
index a477803..4ddb897 100644
--- a/extensions/openpower-pels/callout.cpp
+++ b/extensions/openpower-pels/callout.cpp
@@ -94,8 +94,8 @@
     _size = flattenedSize();
 }
 
-Callout::Callout(CalloutPriority priority,
-                 const std::string& procedureFromRegistry)
+Callout::Callout(CalloutPriority priority, const std::string& procedure,
+                 CalloutValueType type)
 {
     _flags = calloutType | fruIdentIncluded;
 
@@ -103,14 +103,14 @@
 
     _locationCodeSize = 0;
 
-    _fruIdentity = std::make_unique<FRUIdentity>(procedureFromRegistry);
+    _fruIdentity = std::make_unique<FRUIdentity>(procedure, type);
 
     _size = flattenedSize();
 }
 
-Callout::Callout(CalloutPriority priority,
-                 const std::string& symbolicFRUFromRegistry,
-                 const std::string& locationCode, bool trustedLocationCode)
+Callout::Callout(CalloutPriority priority, const std::string& symbolicFRU,
+                 CalloutValueType type, const std::string& locationCode,
+                 bool trustedLocationCode)
 {
     _flags = calloutType | fruIdentIncluded;
 
@@ -118,8 +118,8 @@
 
     setLocationCode(locationCode);
 
-    _fruIdentity = std::make_unique<FRUIdentity>(symbolicFRUFromRegistry,
-                                                 trustedLocationCode);
+    _fruIdentity =
+        std::make_unique<FRUIdentity>(symbolicFRU, type, trustedLocationCode);
 
     _size = flattenedSize();
 }
diff --git a/extensions/openpower-pels/callout.hpp b/extensions/openpower-pels/callout.hpp
index fda0024..1bfe9c8 100644
--- a/extensions/openpower-pels/callout.hpp
+++ b/extensions/openpower-pels/callout.hpp
@@ -87,10 +87,43 @@
      * out a maintenance procedure.
      *
      * @param[in] priority - The priority of the callout
+     * @param[in] procedure - The maintenance procedure name
+     * @param[in] type - If the procedure is the raw name or the registry name
+     */
+    Callout(CalloutPriority priority, const std::string& procedure,
+            CalloutValueType type);
+
+    /**
+     * @brief Constructor
+     *
+     * Creates the objects with a FRUIdentity substructure that calls
+     * out a maintenance procedure.
+     *
+     * @param[in] priority - The priority of the callout
      * @param[in] procedureFromRegistry - The maintenance procedure name
      *                                    as defined in the message registry.
      */
-    Callout(CalloutPriority priority, const std::string& procedureFromRegistry);
+    Callout(CalloutPriority priority,
+            const std::string& procedureFromRegistry) :
+        Callout(priority, procedureFromRegistry, CalloutValueType::registryName)
+    {
+    }
+
+    /**
+     * @brief Constructor
+     *
+     * Creates the objects with a FRUIdentity substructure that calls
+     * out a symbolic FRU.
+     *
+     * @param[in] priority - The priority of the callout
+     * @param[in] symbolicFRU - The symbolic FRU name
+     * @param[in] type - If the FRU is the raw name or the registry name
+     * @param[in] locationCode - The location code of the callout
+     * @param[in] trustedLocationCode - If the location is trusted
+     */
+    Callout(CalloutPriority priority, const std::string& symbolicFRU,
+            CalloutValueType type, const std::string& locationCode,
+            bool trustedLocationCode);
 
     /**
      * @brief Constructor
@@ -106,7 +139,12 @@
      */
     Callout(CalloutPriority priority,
             const std::string& symbolicFRUFromRegistry,
-            const std::string& locationCode, bool trustedLocationCode);
+            const std::string& locationCode, bool trustedLocationCode) :
+        Callout(priority, symbolicFRUFromRegistry,
+                CalloutValueType::registryName, locationCode,
+                trustedLocationCode)
+    {
+    }
 
     /**
      * @brief Returns the size of this object when flattened into a PEL
diff --git a/extensions/openpower-pels/fru_identity.cpp b/extensions/openpower-pels/fru_identity.cpp
index 6d06237..d6a2968 100644
--- a/extensions/openpower-pels/fru_identity.cpp
+++ b/extensions/openpower-pels/fru_identity.cpp
@@ -17,6 +17,8 @@
 
 #include "pel_values.hpp"
 
+#include <fmt/format.h>
+
 #include <phosphor-logging/log.hpp>
 
 using namespace phosphor::logging;
@@ -106,23 +108,23 @@
     _size = flattenedSize();
 }
 
-FRUIdentity::FRUIdentity(const std::string& procedureFromRegistry)
+FRUIdentity::FRUIdentity(const std::string& procedure, CalloutValueType type)
 {
     _type = substructureType;
     _flags = maintenanceProc;
 
-    setMaintenanceProcedure(procedureFromRegistry);
+    setMaintenanceProcedure(procedure, type);
 
     _size = flattenedSize();
 }
 
-FRUIdentity::FRUIdentity(const std::string& symbolicFRUFromRegistry,
+FRUIdentity::FRUIdentity(const std::string& fru, CalloutValueType type,
                          bool trustedLocationCode)
 {
     _type = substructureType;
     _flags = (trustedLocationCode) ? symbolicFRUTrustedLocCode : symbolicFRU;
 
-    setSymbolicFRU(symbolicFRUFromRegistry);
+    setSymbolicFRU(fru, type);
 
     _size = flattenedSize();
 }
@@ -238,45 +240,63 @@
     fillArray(serialNumber, _sn);
 }
 
-void FRUIdentity::setMaintenanceProcedure(
-    const std::string& procedureFromRegistry)
+void FRUIdentity::setMaintenanceProcedure(const std::string& procedure,
+                                          CalloutValueType type)
 {
     _flags |= maintProcSupplied;
     _flags &= ~pnSupplied;
 
-    if (pel_values::maintenanceProcedures.count(procedureFromRegistry))
+    if (type == CalloutValueType::registryName)
     {
-        fillArray(pel_values::maintenanceProcedures.at(procedureFromRegistry),
-                  _pnOrProcedureID);
+        if (pel_values::maintenanceProcedures.count(procedure))
+        {
+            fillArray(pel_values::maintenanceProcedures.at(procedure),
+                      _pnOrProcedureID);
+        }
+        else
+        {
+            log<level::ERR>(
+                fmt::format("Invalid maintenance procedure {}", procedure)
+                    .c_str());
+            strncpy(_pnOrProcedureID.data(), "INVALID",
+                    _pnOrProcedureID.size());
+        }
     }
     else
     {
-        log<level::ERR>("Invalid maintenance procedure",
-                        entry("PROCEDURE=%s", procedureFromRegistry.c_str()));
-        strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size());
+        fillArray(procedure, _pnOrProcedureID);
     }
 
     // ensure null terminated
     _pnOrProcedureID.back() = 0;
 }
 
-void FRUIdentity::setSymbolicFRU(const std::string& symbolicFRUFromRegistry)
+void FRUIdentity::setSymbolicFRU(const std::string& symbolicFRU,
+                                 CalloutValueType type)
 {
 
     // Treat this has a HW callout.
     _flags |= pnSupplied;
     _flags &= ~maintProcSupplied;
 
-    if (pel_values::symbolicFRUs.count(symbolicFRUFromRegistry))
+    if (type == CalloutValueType::registryName)
     {
-        fillArray(pel_values::symbolicFRUs.at(symbolicFRUFromRegistry),
-                  _pnOrProcedureID);
+        if (pel_values::symbolicFRUs.count(symbolicFRU))
+        {
+            fillArray(pel_values::symbolicFRUs.at(symbolicFRU),
+                      _pnOrProcedureID);
+        }
+        else
+        {
+            log<level::ERR>("Invalid symbolic FRU",
+                            entry("FRU=%s", symbolicFRU.c_str()));
+            strncpy(_pnOrProcedureID.data(), "INVALID",
+                    _pnOrProcedureID.size());
+        }
     }
     else
     {
-        log<level::ERR>("Invalid symbolic FRU",
-                        entry("FRU=%s", symbolicFRUFromRegistry.c_str()));
-        strncpy(_pnOrProcedureID.data(), "INVALID", _pnOrProcedureID.size());
+        fillArray(symbolicFRU, _pnOrProcedureID);
     }
 
     // ensure null terminated
diff --git a/extensions/openpower-pels/fru_identity.hpp b/extensions/openpower-pels/fru_identity.hpp
index e5eb864..e911b13 100644
--- a/extensions/openpower-pels/fru_identity.hpp
+++ b/extensions/openpower-pels/fru_identity.hpp
@@ -13,6 +13,16 @@
 {
 
 /**
+ * @brief Specifies if the incoming maintenance procedure or
+ *        symbolic FRU is the registry name or the raw name.
+ */
+enum class CalloutValueType
+{
+    raw,
+    registryName
+};
+
+/**
  * @class FRUIdentity
  *
  * This represents the FRU Identity substructure in the
@@ -92,7 +102,20 @@
      * @param[in] procedureFromRegistry - The maintenance procedure name
      *                                    as defined in the message registry.
      */
-    FRUIdentity(const std::string& procedureFromRegistry);
+    FRUIdentity(const std::string& procedureFromRegistry) :
+        FRUIdentity(procedureFromRegistry, CalloutValueType::registryName)
+    {
+    }
+
+    /**
+     * @brief Constructor
+     *
+     * Creates the object with a maintenance procedure callout.
+     *
+     * @param[in] procedure - The maintenance procedure name.
+     * @param[in] type - If the procedure is the raw name or the registry name.
+     */
+    FRUIdentity(const std::string& procedure, CalloutValueType type);
 
     /**
      * @brief Constructor
@@ -105,6 +128,23 @@
      *                                  can be trusted to be correct.
      */
     FRUIdentity(const std::string& symbolicFRUFromRegistry,
+                bool trustedLocationCode) :
+        FRUIdentity(symbolicFRUFromRegistry, CalloutValueType::registryName,
+                    trustedLocationCode)
+    {
+    }
+
+    /**
+     * @brief Constructor
+     *
+     * Creates the object with a symbolic FRU callout.
+     *
+     * @param[in] fru - The symbolic FRU name.
+     * @param[in] type - If the FRU is the raw name or the registry name.
+     * @param[in] trustedLocationCode - If this FRU callout's location code
+     *                                  can be trusted to be correct.
+     */
+    FRUIdentity(const std::string& fru, CalloutValueType type,
                 bool trustedLocationCode);
 
     /**
@@ -245,20 +285,23 @@
      *        field.  This is in the same field as the part
      *        number since they are mutually exclusive.
      *
-     * @param procedureFromRegistry - The procedure name as defined in
-     *                                the PEL message registry.
+     * @param procedure - The procedure name.
+     * @param[in] type - If the procedure is the raw name or
+     *                   the registry name.
      */
-    void setMaintenanceProcedure(const std::string& procedureFromRegistry);
+    void setMaintenanceProcedure(const std::string& procedure,
+                                 CalloutValueType type);
 
     /**
      * @brief Sets the 8 character null terminated symbolic FRU
      *        field.  This is in the same field as the part
      *        number since they are mutually exclusive.
      *
-     * @param[in] symbolicFRUFromRegistry - The symbolic FRU name as
-     *                                      defined in the message registry.
+     * @param[in] symbolicFRU - The symbolic FRU name.
+     * @param[in] type - If the FRU is the raw name or
+     *                   the registry name.
      */
-    void setSymbolicFRU(const std::string& symbolicFRUFromRegistry);
+    void setSymbolicFRU(const std::string& symbolicFRU, CalloutValueType type);
 
     /**
      * @brief The callout substructure type field. Will be "ID".
diff --git a/test/openpower-pels/Makefile.include b/test/openpower-pels/Makefile.include
index ee7f99f..b4c6a01 100644
--- a/test/openpower-pels/Makefile.include
+++ b/test/openpower-pels/Makefile.include
@@ -252,6 +252,7 @@
 fru_identity_test_CXXFLAGS = $(test_cxxflags)
 fru_identity_test_LDADD = \
 	$(test_ldadd) \
+	$(FMT_LIBS) \
 	$(top_builddir)/extensions/openpower-pels/fru_identity.o \
 	$(top_builddir)/extensions/openpower-pels/pel_values.o
 fru_identity_test_LDFLAGS = $(test_ldflags)
@@ -280,6 +281,7 @@
 src_callout_test_LDADD = \
 	$(test_ldadd) \
 	$(pel_test_utils_ldadd) \
+	$(FMT_LIBS) \
 	$(top_builddir)/extensions/openpower-pels/callout.o \
 	$(top_builddir)/extensions/openpower-pels/fru_identity.o \
 	$(top_builddir)/extensions/openpower-pels/mru.o \
@@ -295,6 +297,7 @@
 src_callouts_test_LDADD = \
 	$(test_ldadd) \
 	$(pel_test_utils_ldadd) \
+	$(FMT_LIBS) \
 	$(top_builddir)/extensions/openpower-pels/callout.o \
 	$(top_builddir)/extensions/openpower-pels/callouts.o \
 	$(top_builddir)/extensions/openpower-pels/fru_identity.o \
@@ -311,18 +314,7 @@
 src_test_LDADD = \
 	$(test_ldadd) \
 	$(pel_test_utils_ldadd) \
-	$(top_builddir)/extensions/openpower-pels/ascii_string.o \
-	$(top_builddir)/extensions/openpower-pels/callout.o \
-	$(top_builddir)/extensions/openpower-pels/callouts.o \
-	$(top_builddir)/extensions/openpower-pels/device_callouts.o \
-	$(top_builddir)/extensions/openpower-pels/fru_identity.o \
-	$(top_builddir)/extensions/openpower-pels/json_utils.o \
-	$(top_builddir)/extensions/openpower-pels/mru.o \
-	$(top_builddir)/extensions/openpower-pels/mtms.o \
-	$(top_builddir)/extensions/openpower-pels/pce_identity.o \
-	$(top_builddir)/extensions/openpower-pels/pel_values.o \
-	$(top_builddir)/extensions/openpower-pels/registry.o \
-	$(top_builddir)/extensions/openpower-pels/src.o
+	$(pel_objects)
 src_test_LDFLAGS = $(test_ldflags)
 
 extended_user_header_test_SOURCES = \
@@ -332,20 +324,7 @@
 extended_user_header_test_LDADD = \
 	$(test_ldadd) \
 	$(pel_test_utils_ldadd) \
-	$(top_builddir)/extensions/openpower-pels/ascii_string.o \
-	$(top_builddir)/extensions/openpower-pels/callout.o \
-	$(top_builddir)/extensions/openpower-pels/callouts.o \
-	$(top_builddir)/extensions/openpower-pels/device_callouts.o \
-	$(top_builddir)/extensions/openpower-pels/data_interface.o \
-	$(top_builddir)/extensions/openpower-pels/extended_user_header.o \
-	$(top_builddir)/extensions/openpower-pels/fru_identity.o \
-	$(top_builddir)/extensions/openpower-pels/json_utils.o \
-	$(top_builddir)/extensions/openpower-pels/mru.o \
-	$(top_builddir)/extensions/openpower-pels/mtms.o \
-	$(top_builddir)/extensions/openpower-pels/pel_values.o \
-	$(top_builddir)/extensions/openpower-pels/pce_identity.o \
-	$(top_builddir)/extensions/openpower-pels/registry.o \
-	$(top_builddir)/extensions/openpower-pels/src.o
+	$(pel_objects)
 extended_user_header_test_LDFLAGS = $(test_ldflags)
 
 pel_rules_test_SOURCES = %reldir%/pel_rules_test.cpp
diff --git a/test/openpower-pels/fru_identity_test.cpp b/test/openpower-pels/fru_identity_test.cpp
index b13bf3f..116fe4d 100644
--- a/test/openpower-pels/fru_identity_test.cpp
+++ b/test/openpower-pels/fru_identity_test.cpp
@@ -201,6 +201,12 @@
         EXPECT_FALSE(fru.getCCIN());
         EXPECT_FALSE(fru.getSN());
     }
+
+    {
+        // Raw maintenance procedure
+        FRUIdentity fru{"BMCSPXXLONG", CalloutValueType::raw};
+        EXPECT_EQ(fru.getMaintProc().value(), "BMCSPXX");
+    }
 }
 
 // Test the constructor that takes in a symbolic FRU.
@@ -263,4 +269,11 @@
         EXPECT_FALSE(fru.getCCIN());
         EXPECT_FALSE(fru.getSN());
     }
+
+    // Raw symbolic FRU
+    {
+        FRUIdentity fru{"SOMEFRULONG", CalloutValueType::raw, false};
+
+        EXPECT_EQ(fru.getPN().value(), "SOMEFRU");
+    }
 }
diff --git a/test/openpower-pels/src_callout_test.cpp b/test/openpower-pels/src_callout_test.cpp
index 74c396c..fa93111 100644
--- a/test/openpower-pels/src_callout_test.cpp
+++ b/test/openpower-pels/src_callout_test.cpp
@@ -317,6 +317,13 @@
 
     auto& newFRU = newCallout.fruIdentity();
     EXPECT_EQ(newFRU->getMaintProc().value(), fru->getMaintProc().value());
+
+    // Use raw procedure value
+
+    Callout rawCallout{CalloutPriority::medium, "BMCSPXX",
+                       CalloutValueType::raw};
+    auto& rawFRU = rawCallout.fruIdentity();
+    EXPECT_EQ(rawFRU->getMaintProc().value(), "BMCSPXX");
 }
 
 // Create a callout object by passing in the symbolic FRU to add.
@@ -384,4 +391,16 @@
                   FRUIdentity::symbolicFRUTrustedLocCode);
         EXPECT_EQ(fru->getPN().value(), "SVCDOCS");
     }
+
+    // symbolic FRU with raw FRU value
+    {
+        {
+            Callout callout{CalloutPriority::high, "SYMBFRU",
+                            CalloutValueType::raw, "", false};
+
+            auto& fru = callout.fruIdentity();
+
+            EXPECT_EQ(fru->getPN().value(), "SYMBFRU");
+        }
+    }
 }