PEL: Use 'Notify' when setting Functional prop

Use phosphor-inventory-manager's Notify method when setting the
Functional property based on PEL callouts.

Using the method will have PIM persist the functional value so it isn't
lost after a reboot, unlike a regular property set call.

Signed-off-by: Matt Spinler <spinler@us.ibm.com>
Change-Id: If94f788a91fa4668b1297e2d265beb72318d4666
diff --git a/extensions/openpower-pels/data_interface.cpp b/extensions/openpower-pels/data_interface.cpp
index 1c51167..98b8f31 100644
--- a/extensions/openpower-pels/data_interface.cpp
+++ b/extensions/openpower-pels/data_interface.cpp
@@ -46,6 +46,7 @@
 constexpr auto biosConfigMgr = "xyz.openbmc_project.BIOSConfigManager";
 constexpr auto bootRawProgress = "xyz.openbmc_project.State.Boot.Raw";
 constexpr auto pldm = "xyz.openbmc_project.PLDM";
+constexpr auto inventoryManager = "xyz.openbmc_project.Inventory.Manager";
 } // namespace service_name
 
 namespace object_path
@@ -104,6 +105,7 @@
 constexpr auto invFan = "xyz.openbmc_project.Inventory.Item.Fan";
 constexpr auto invPowerSupply =
     "xyz.openbmc_project.Inventory.Item.PowerSupply";
+constexpr auto inventoryManager = "xyz.openbmc_project.Inventory.Manager";
 } // namespace interface
 
 using namespace sdbusplus::server::xyz::openbmc_project::state::boot;
@@ -559,13 +561,22 @@
 void DataInterface::setFunctional(const std::string& objectPath,
                                   bool value) const
 {
-    DBusValue variant = value;
-    auto service = getService(objectPath, interface::operationalStatus);
+    DBusPropertyMap prop{{"Functional", value}};
+    DBusInterfaceMap iface{{interface::operationalStatus, prop}};
 
-    auto method = _bus.new_method_call(service.c_str(), objectPath.c_str(),
-                                       interface::dbusProperty, "Set");
+    // PIM takes a relative path like /system/chassis so remove
+    // /xyz/openbmc_project/inventory if present.
+    std::string path{objectPath};
+    if (path.starts_with(object_path::baseInv))
+    {
+        path = objectPath.substr(strlen(object_path::baseInv));
+    }
+    DBusObjectMap object{{path, iface}};
 
-    method.append(interface::operationalStatus, "Functional", variant);
+    auto method = _bus.new_method_call(service_name::inventoryManager,
+                                       object_path::baseInv,
+                                       interface::inventoryManager, "Notify");
+    method.append(std::move(object));
     _bus.call(method, dbusTimeout);
 }
 
diff --git a/extensions/openpower-pels/dbus_types.hpp b/extensions/openpower-pels/dbus_types.hpp
index 8e9797e..142ee46 100644
--- a/extensions/openpower-pels/dbus_types.hpp
+++ b/extensions/openpower-pels/dbus_types.hpp
@@ -1,5 +1,7 @@
 #pragma once
 
+#include <sdbusplus/message.hpp>
+
 #include <cstdint>
 #include <map>
 #include <string>
@@ -30,6 +32,8 @@
 using DBusPathList = std::vector<DBusPath>;
 using DBusPropertyMap = std::map<DBusProperty, DBusValue>;
 using DBusInterfaceMap = std::map<DBusInterface, DBusPropertyMap>;
+using DBusObjectMap =
+    std::map<sdbusplus::message::object_path, DBusInterfaceMap>;
 using DBusSubTree =
     std::map<DBusPath, std::map<DBusService, DBusInterfaceList>>;