yosemitev2: Multi-host information displayed in OCP debug-card

This implementation is going to display the following info
in OCP debug card.
1) FRU details
2) ME status
which is support for the Facebook Yosemitev2 platform.

Tested: information frame value of FRU info displayed in the
OCP debug card with multi-host Yosemitev2 platform.

Signed-off-by: Karthikeyan Pasupathi <pkarthikeyan1509@gmail.com>
Change-Id: I7cf042af9bcd295b90df4044d37b186e1086ae79
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index 7a6653b..65c3adf 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -89,6 +89,7 @@
     CMD_OEM_Q_GET_DRIVE_INFO = 0x15,
 };
 
+#define BMC_POS 0
 #define SIZE_CPU_PPIN 8
 #define SIZE_BOOT_ORDER 6
 #define BOOT_MODE_UEFI 0x01
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 55fcbf1..b604957 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -47,6 +47,7 @@
 
 using namespace phosphor::logging;
 
+size_t getSelectorPosition();
 static void registerOEMFunctions() __attribute__((constructor));
 sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid/api.h
 static constexpr size_t maxFRUStringLength = 0x3F;
@@ -365,50 +366,82 @@
 // return code: 0 successful
 int8_t getFruData(std::string& data, std::string& name)
 {
-    std::string objpath = "/xyz/openbmc_project/FruDevice";
-    std::string intf = "xyz.openbmc_project.FruDeviceManager";
-    std::string service = getService(dbus, intf, objpath);
-    ObjectValueTree valueTree = getManagedObjects(dbus, service, "/");
-    if (valueTree.empty())
+    size_t pos;
+    static constexpr const auto depth = 0;
+    std::vector<std::string> paths;
+    std::string machinePath;
+    std::string baseBoard = "Baseboard";
+
+    bool platform = isMultiHostPlatform();
+    if (platform == true)
+    {
+        pos = getSelectorPosition();
+    }
+
+    sd_bus* bus = NULL;
+    int ret = sd_bus_default_system(&bus);
+    if (ret < 0)
     {
         phosphor::logging::log<phosphor::logging::level::ERR>(
-            "No object implements interface",
-            phosphor::logging::entry("INTF=%s", intf.c_str()));
+            "Failed to connect to system bus",
+            phosphor::logging::entry("ERRNO=0x%X", -ret));
+        sd_bus_unref(bus);
+        return -1;
+    }
+    sdbusplus::bus::bus dbus(bus);
+    auto mapperCall = dbus.new_method_call("xyz.openbmc_project.ObjectMapper",
+                                           "/xyz/openbmc_project/object_mapper",
+                                           "xyz.openbmc_project.ObjectMapper",
+                                           "GetSubTreePaths");
+    static constexpr std::array<const char*, 1> interface = {
+        "xyz.openbmc_project.Inventory.Decorator.Asset"};
+    mapperCall.append("/xyz/openbmc_project/inventory/", depth, interface);
+
+    try
+    {
+        auto reply = dbus.call(mapperCall);
+        reply.read(paths);
+    }
+    catch (sdbusplus::exception_t& e)
+    {
+        phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
         return -1;
     }
 
-    for (const auto& item : valueTree)
+    for (const auto& path : paths)
     {
-        auto interface = item.second.find("xyz.openbmc_project.FruDevice");
-        if (interface == item.second.end())
+        if (platform == true)
         {
-            continue;
-        }
-
-        auto property = interface->second.find(name.c_str());
-        if (property == interface->second.end())
-        {
-            continue;
-        }
-
-        try
-        {
-            Value variant = property->second;
-            std::string& result = std::get<std::string>(variant);
-            if (result.size() > maxFRUStringLength)
+            if (pos == BMC_POS)
             {
-                phosphor::logging::log<phosphor::logging::level::ERR>(
-                    "FRU serial number exceed maximum length");
-                return -1;
+                machinePath = baseBoard;
             }
-            data = result;
-            return 0;
+            else
+            {
+                machinePath = "_" + std::to_string(pos);
+            }
         }
-        catch (const std::bad_variant_access& e)
+        else
         {
-            phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
-            return -1;
+            machinePath = baseBoard;
         }
+
+        auto found = path.find(machinePath);
+        if (found == -1)
+        {
+            continue;
+        }
+
+        std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
+        std::string service = getService(
+            *dbus, "xyz.openbmc_project.Inventory.Decorator.Asset", path);
+
+        auto Value = ipmi::getDbusProperty(
+            *dbus, service, path,
+            "xyz.openbmc_project.Inventory.Decorator.Asset", name);
+
+        data = std::get<std::string>(Value);
+        return 0;
     }
     return -1;
 }
diff --git a/src/usb-dbg.cpp b/src/usb-dbg.cpp
index 01c5455..3579ef1 100644
--- a/src/usb-dbg.cpp
+++ b/src/usb-dbg.cpp
@@ -866,17 +866,24 @@
     return 0;
 }
 
-static int getMeStatus(std::string& status)
+static int getMeStatus(std::string& status, size_t pos)
 {
     uint8_t cmd = 0x01;   // Get Device id command
     uint8_t netFn = 0x06; // Netfn for APP
     std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
     std::vector<uint8_t> cmdData;
 
+    uint8_t meAddr = meAddress;
+    bool platform = isMultiHostPlatform();
+    if (platform == true)
+    {
+        meAddr = ((pos - 1) << 2);
+    }
+
     auto method = bus->new_method_call("xyz.openbmc_project.Ipmi.Channel.Ipmb",
                                        "/xyz/openbmc_project/Ipmi/Channel/Ipmb",
                                        "org.openbmc.Ipmb", "sendRequest");
-    method.append(meAddress, netFn, lun, cmd, cmdData);
+    method.append(meAddr, netFn, lun, cmd, cmdData);
 
     auto reply = bus->call(method);
     if (reply.is_method_error())
@@ -916,10 +923,11 @@
     [[maybe_unused]] char* pres_dev = line_buff;
     [[maybe_unused]] size_t pos = plat_get_fru_sel();
     int ret;
-    std::string serialName = "BOARD_SERIAL_NUMBER";
-    std::string partName = "BOARD_PART_NUMBER";
+    std::string serialName = "SerialNumber";
+    std::string partName = "PartNumber";
     std::string verDel = "VERSION=";
     std::string verPath = "/etc/os-release";
+    size_t hostPosition;
 
     if (page == 1)
     {
@@ -929,7 +937,23 @@
         frame_info.init(FRAME_BUFF_SIZE);
         snprintf(frame_info.title, 32, "SYS_Info");
 
-        // FRU TBD:
+        bool platform = isMultiHostPlatform();
+        if (platform == true)
+        {
+            hostPosition = getSelectorPosition();
+        }
+
+        if (hostPosition == BMC_POSITION || INSTANCES == "0")
+        {
+            frame_info.append("FRU:spb", 0);
+        }
+        else if (hostPosition != BMC_POSITION && hostPosition <= MAX_HOST_POS)
+        {
+            std::string data = "FRU:slot" + std::to_string(hostPosition);
+            frame_info.append(data.c_str(), 0);
+        }
+
+        // FRU
         std::string data;
         frame_info.append("SN:", 0);
         if (getFruData(data, serialName) != 0)
@@ -969,25 +993,27 @@
             }
         }
 
-        // BIOS ver
-        std::string biosVer;
-        if (getBiosVer(biosVer) == 0)
+        if (hostPosition != BMC_POSITION)
         {
-            frame_info.append("BIOS_FW_ver:", 0);
-            frame_info.append(biosVer.c_str(), 1);
+            // BIOS ver
+            std::string biosVer;
+            if (getBiosVer(biosVer) == 0)
+            {
+                frame_info.append("BIOS_FW_ver:", 0);
+                frame_info.append(biosVer.c_str(), 1);
+            }
+            // ME status
+            std::string meStatus;
+            if (getMeStatus(meStatus, pos) != 0)
+            {
+                phosphor::logging::log<phosphor::logging::level::WARNING>(
+                    "Reading ME status failed");
+                meStatus = "unknown";
+            }
+            frame_info.append("ME_status:", 0);
+            frame_info.append(meStatus.c_str(), 1);
         }
 
-        // ME status
-        std::string meStatus;
-        if (getMeStatus(meStatus) != 0)
-        {
-            phosphor::logging::log<phosphor::logging::level::WARNING>(
-                "Reading ME status failed");
-            meStatus = "unknown";
-        }
-        frame_info.append("ME_status:", 0);
-        frame_info.append(meStatus.c_str(), 1);
-
         /* TBD: Board ID needs implementation */
         // Board ID