Eliminate expensive DBus transaction in Get Device ID

Get Device ID incurred some performance issues at boot time because of
blocking IPMI function calls. This change focuses on using local file
content instead of making DBus calls. It eliminates reading the FRU
contents at boot as the dominant mode, which take quite some time to
complete.

Tested:
Used high_resolution_clock function calls to collect the run time from
start to finish of the ipmiAppGetDeviceId function. Rebooted the
system multiple times, and ran "ipmitool mc info" in a loop 60 times.
Before the change the function could take upwards of 6 seconds to
complete.
After the change the worst case observed was just over 1 second.

Change-Id: Ia8ebd8e21a1b3e2f77e50bdfdd7272dfe51a56ea
Signed-off-by: Johnathan Mantey <johnathanx.mantey@intel.com>
diff --git a/src/appcommands.cpp b/src/appcommands.cpp
index 8fc0d30..9b75cb8 100644
--- a/src/appcommands.cpp
+++ b/src/appcommands.cpp
@@ -243,17 +243,19 @@
         uint8_t id;
         uint8_t revision;
         uint8_t fw[2];
-        uint8_t ipmiVer;
+        uint8_t ipmiVer = 2;
         uint8_t addnDevSupport;
         uint24_t manufId;
         uint16_t prodId;
         uint32_t aux;
     } devId;
     static bool dev_id_initialized = false;
-    static bool defaultActivationSetting = true;
+    static bool defaultActivationSetting = false;
     const char* filename = "/usr/share/ipmi-providers/dev_id.json";
+    const char* prodIdFilename = "/var/cache/private/prodID";
     constexpr auto ipmiDevIdStateShift = 7;
     constexpr auto ipmiDevIdFw1Mask = ~(1 << ipmiDevIdStateShift);
+    constexpr auto ipmiDevIdBusy = (1 << ipmiDevIdStateShift);
 
     if (!dev_id_initialized)
     {
@@ -297,9 +299,6 @@
             }
         }
 
-        // IPMI Spec version 2.0
-        devId.ipmiVer = 2;
-
         std::ifstream devIdFile(filename);
         if (devIdFile.is_open())
         {
@@ -310,32 +309,6 @@
                 devId.revision = data.value("revision", 0);
                 devId.addnDevSupport = data.value("addn_dev_support", 0);
                 devId.manufId = data.value("manuf_id", 0);
-
-                try
-                {
-                    auto busp = getSdBus();
-                    const ipmi::DbusObjectInfo& object = ipmi::getDbusObject(
-                        *busp, "xyz.openbmc_project.Inventory.Item.Board",
-                        "/xyz/openbmc_project/inventory/system/board/",
-                        "Baseboard");
-                    const ipmi::Value& propValue = ipmi::getDbusProperty(
-                        *busp, object.second, object.first,
-                        "xyz.openbmc_project.Inventory.Item.Board",
-                        "ProductId");
-                    devId.prodId =
-                        static_cast<uint8_t>(std::get<uint64_t>(propValue));
-                    dev_id_initialized = true;
-                }
-                catch (std::exception& e)
-                {
-                    // For any exception send out platform id as 0,
-                    // and make sure to re-query the device id.
-                    dev_id_initialized = false;
-                    devId.prodId = 0;
-                }
-
-                // Set the availablitity of the BMC.
-                defaultActivationSetting = data.value("availability", true);
             }
             else
             {
@@ -348,13 +321,34 @@
             Log::log<Log::level::ERR>("Device ID file not found");
             return ipmi::responseUnspecifiedError();
         }
+
+        // Determine the Product ID. Using the DBus system is painfully slow at
+        // boot time. Avoid using DBus to get the Product ID. The Product ID is
+        // stored in a non-volatile file now. The /usr/bin/checkFru.sh script,
+        // run during bootup, will populate the productIdFile.
+        std::fstream prodIdFile(prodIdFilename);
+        if (prodIdFile.is_open())
+        {
+            std::string id = "0x00";
+            char* end;
+            prodIdFile.getline(&id[0], id.size() + 1);
+            devId.prodId = std::strtol(&id[0], &end, 0);
+            dev_id_initialized = true;
+        }
+        else
+        {
+            // For any exception send out platform id as 0,
+            // and make sure to re-query the device id.
+            dev_id_initialized = false;
+            devId.prodId = 0;
+        }
     }
 
     // Set availability to the actual current BMC state
     devId.fw[0] &= ipmiDevIdFw1Mask;
     if (!getCurrentBmcStateWithFallback(defaultActivationSetting))
     {
-        devId.fw[0] |= (1 << ipmiDevIdStateShift);
+        devId.fw[0] |= ipmiDevIdBusy;
     }
 
     return ipmi::responseSuccess(