smbios-mdr: Associate with the motherboard

The change associates the objects such as processor, memory and PCIe
slots published by smbios-mdr with the motherboard inventory object.
Presently objects paths created by smbios-mdr have the motherboard path
as the prefix -- "/xyz/openbmc_project/inventory/chassis/motherboard".
For machine with entity-manager dynamic stack, that hardcoded
motherboard path would probably not be the object path of the
motherboard.

We have implemented a DBus method in EM that can return the inventory
object path of the root board in the system. Such associations can be
assembled in Redfish resources can indicate the machine topology.

Tested:
DBus call on the Association interface of a CPU object.

busctl get-property xyz.openbmc_project.Smbios.MDR_V2 \
/xyz/openbmc_project/inventory/system/chassis/motherboard/cpu0 \
xyz.openbmc_project.Association.Definitions Associations
a(sss) 1 "chassis" "processors" \
"/xyz/openbmc_project/inventory/system/board/GSZ"

Signed-off-by: Jie Yang <jjy@google.com>
Change-Id: Ia95159a87c2ce5e69e90e622cf341a68e7db13d4
diff --git a/src/cpu.cpp b/src/cpu.cpp
index 5e96254..a5f39ee 100644
--- a/src/cpu.cpp
+++ b/src/cpu.cpp
@@ -169,6 +169,13 @@
     }
 
     characteristics(cpuInfo->characteristics); // offset 26h
+
+    if (!motherboardPath.empty())
+    {
+        std::vector<std::tuple<std::string, std::string, std::string>> assocs;
+        assocs.emplace_back("chassis", "processors", motherboardPath);
+        association::associations(assocs);
+    }
 }
 
 } // namespace smbios
diff --git a/src/dimm.cpp b/src/dimm.cpp
index 03b35f9..fa643b5 100644
--- a/src/dimm.cpp
+++ b/src/dimm.cpp
@@ -74,6 +74,13 @@
     memoryAttributes(memoryInfo->attributes);
     memoryConfiguredSpeedInMhz(memoryInfo->confClockSpeed);
 
+    if (!motherboardPath.empty())
+    {
+        std::vector<std::tuple<std::string, std::string, std::string>> assocs;
+        assocs.emplace_back("chassis", "memories", motherboardPath);
+        association::associations(assocs);
+    }
+
     return;
 }
 
diff --git a/src/mdrv2.cpp b/src/mdrv2.cpp
index 39890b3..75842fc 100644
--- a/src/mdrv2.cpp
+++ b/src/mdrv2.cpp
@@ -375,8 +375,24 @@
 
 void MDR_V2::systemInfoUpdate()
 {
-    cpus.clear();
+    std::string motherboardPath;
+    sdbusplus::message::message method =
+        bus.new_method_call("xyz.openbmc_project.EntityManager",
+                            "/xyz/openbmc_project/EntityManager",
+                            "xyz.openbmc_project.EntityManager", "ReScan");
+    try
+    {
+        sdbusplus::message::message reply = bus.call(method);
+        reply.read(motherboardPath);
+    }
+    catch (const sdbusplus::exception_t& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(
+            "Failed to query system motherboard",
+            phosphor::logging::entry("ERROR=%s", e.what()));
+    }
 
+    cpus.clear();
     int num = getTotalCpuSlot();
     if (num == -1)
     {
@@ -389,7 +405,8 @@
     {
         std::string path = cpuPath + std::to_string(index);
         cpus.emplace_back(std::make_unique<phosphor::smbios::Cpu>(
-            bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
+            bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage,
+            motherboardPath));
     }
 
 #ifdef DIMM_DBUS
@@ -408,7 +425,8 @@
     {
         std::string path = dimmPath + std::to_string(index);
         dimms.emplace_back(std::make_unique<phosphor::smbios::Dimm>(
-            bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
+            bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage,
+            motherboardPath));
     }
 
 #endif
@@ -426,7 +444,8 @@
     {
         std::string path = pciePath + std::to_string(index);
         pcies.emplace_back(std::make_unique<phosphor::smbios::Pcie>(
-            bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage));
+            bus, path, index, smbiosDir.dir[smbiosDirIndex].dataStorage,
+            motherboardPath));
     }
 
     system.reset();
diff --git a/src/pcieslot.cpp b/src/pcieslot.cpp
index 1b46407..0ea7a8b 100644
--- a/src/pcieslot.cpp
+++ b/src/pcieslot.cpp
@@ -48,6 +48,13 @@
 
     /* Pcie slot is embedded on the board. Always be true */
     Item::present(true);
+
+    if (!motherboardPath.empty())
+    {
+        std::vector<std::tuple<std::string, std::string, std::string>> assocs;
+        assocs.emplace_back("chassis", "pcie_slots", motherboardPath);
+        association::associations(assocs);
+    }
 }
 
 void Pcie::pcieGeneration(const uint8_t type)