PEL: Generate HW callouts from the msg registry

Callouts that aren't procedures or symbolic FRUs can be defined in the
message registry.  Fill in the SRC code that creates these hardware
callout objects in this case.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I610c6c58b8672da283722c1d68b6dfdf28e480e3
diff --git a/extensions/openpower-pels/src.cpp b/extensions/openpower-pels/src.cpp
index d2e58d5..eb103bb 100644
--- a/extensions/openpower-pels/src.cpp
+++ b/extensions/openpower-pels/src.cpp
@@ -510,7 +510,7 @@
     auto item = additionalData.getValue("CALLOUT_INVENTORY_PATH");
     if (item)
     {
-        addInventoryCallout(*item, dataIface);
+        addInventoryCallout(*item, std::nullopt, std::nullopt, dataIface);
     }
 
     // TODO: CALLOUT_DEVICE_PATH
@@ -522,6 +522,8 @@
 }
 
 void SRC::addInventoryCallout(const std::string& inventoryPath,
+                              const std::optional<CalloutPriority>& priority,
+                              const std::optional<std::string>& locationCode,
                               const DataInterfaceBase& dataIface)
 {
     std::string locCode;
@@ -532,14 +534,24 @@
 
     try
     {
-        locCode = dataIface.getLocationCode(inventoryPath);
+        // Use the passed in location code if there otherwise look it up
+        if (locationCode)
+        {
+            locCode = *locationCode;
+        }
+        else
+        {
+            locCode = dataIface.getLocationCode(inventoryPath);
+        }
 
         try
         {
             dataIface.getHWCalloutFields(inventoryPath, fn, ccin, sn);
 
-            callout = std::make_unique<src::Callout>(CalloutPriority::high,
-                                                     locCode, fn, ccin, sn);
+            CalloutPriority p =
+                priority ? priority.value() : CalloutPriority::high;
+
+            callout = std::make_unique<src::Callout>(p, locCode, fn, ccin, sn);
         }
         catch (const SdBusError& e)
         {
@@ -596,10 +608,23 @@
                              const DataInterfaceBase& dataIface)
 {
     std::unique_ptr<src::Callout> callout;
-
-    // TODO: expand this location code.
     auto locCode = regCallout.locCode;
 
+    if (!locCode.empty())
+    {
+        try
+        {
+            locCode = dataIface.expandLocationCode(locCode, 0);
+        }
+        catch (const std::exception& e)
+        {
+            auto msg =
+                "Unable to expand location code " + locCode + ": " + e.what();
+            addDebugData(msg);
+            return;
+        }
+    }
+
     // Via the PEL values table, get the priority enum.
     // The schema will have validated the priority was a valid value.
     auto priorityIt =
@@ -631,7 +656,25 @@
     }
     else
     {
-        // TODO: HW callouts
+        // A hardware callout
+        std::string inventoryPath;
+
+        try
+        {
+            // Get the inventory item from the unexpanded location code
+            inventoryPath =
+                dataIface.getInventoryFromLocCode(regCallout.locCode, 0);
+        }
+        catch (const std::exception& e)
+        {
+            std::string msg =
+                "Unable to get inventory path from location code: " + locCode +
+                ": " + e.what();
+            addDebugData(msg);
+            return;
+        }
+
+        addInventoryCallout(inventoryPath, priority, locCode, dataIface);
     }
 
     if (callout)