PEL: Create SRC FRU callout for inventory path

When a BMC application creates an event log with the
CALLOUT_INVENTORY_PATH=<FRU inventory path> entry in the AdditionalData
property, create a FRU callout section for that FRU in the SRC.

Obtain the location code, part number, serial number, and CCIN VPD
keyword for that FRU to add to the callout.  If these aren't available,
as detected by catching an sdbusplus exception, create a callout with a
'no VPD for FRU' maintenance procedure instead.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: I0d6680d87c325703df9e2a6d2e2715b18498fabc
diff --git a/extensions/openpower-pels/src.cpp b/extensions/openpower-pels/src.cpp
index 8d2fd0b..b15c777 100644
--- a/extensions/openpower-pels/src.cpp
+++ b/extensions/openpower-pels/src.cpp
@@ -120,7 +120,7 @@
 
     _asciiString = std::make_unique<src::AsciiString>(regEntry);
 
-    // TODO: add callouts using the Callouts object
+    addCallouts(additionalData, dataIface);
 
     _size = baseSRCSize;
     _size += _callouts ? _callouts->flattenedSize() : 0;
@@ -502,5 +502,49 @@
     return ps;
 }
 
+void SRC::addCallouts(const AdditionalData& additionalData,
+                      const DataInterfaceBase& dataIface)
+{
+    auto item = additionalData.getValue("CALLOUT_INVENTORY_PATH");
+    if (item)
+    {
+        addInventoryCallout(*item, dataIface);
+    }
+
+    // TODO: CALLOUT_DEVICE_PATH
+}
+
+void SRC::addInventoryCallout(const std::string& inventoryPath,
+                              const DataInterfaceBase& dataIface)
+{
+    std::string locCode;
+    std::string fn;
+    std::string ccin;
+    std::string sn;
+    std::unique_ptr<src::Callout> callout;
+
+    createCalloutsObject();
+
+    try
+    {
+        dataIface.getHWCalloutFields(inventoryPath, locCode, fn, ccin, sn);
+
+        callout = std::make_unique<src::Callout>(CalloutPriority::high, locCode,
+                                                 fn, ccin, sn);
+    }
+    catch (const SdBusError& e)
+    {
+        log<level::INFO>("No VPD found for FRU callout",
+                         entry("PATH=%s", inventoryPath.c_str()));
+
+        // Use the 'NoVPDforFRU' maintenance procedure instead
+        callout = std::make_unique<src::Callout>(CalloutPriority::high,
+                                                 MaintProcedure::noVPDforFRU);
+    }
+
+    _callouts->addCallout(std::move(callout));
+
+} // namespace pels
+
 } // namespace pels
 } // namespace openpower