ibm-read-vpd: Enable skipping VPD read if host is powered ON

This commit keys off of a JSON attribute on the FRU that enables the
parser code to skip reading VPD when the host is powered ON.

On IBM systems, certain FRU VPD is inaccessible to the BMC when the host
is powered ON. This commit enables us to skip such FRUs.

It relies on the xyz.openbmc_project.State.Chassis.CurrentPowerState
property to determine the host power state.

Tested: Tested on Rainier simulation model by manually setting the above
property and ensuring that VPD reads are skipped if the FRU contains
the "powerOffOnly" key in the JSON.

Signed-off-by: Santosh Puranik <santosh.puranik@in.ibm.com>
Change-Id: Iaa55d32f7b3641fa0fd41dbd79620dbff2b1673a
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index 83e2cd2..6241188 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -41,6 +41,34 @@
     {EVEREST, "conf@aspeed-bmc-ibm-everest.dtb"}};
 
 /**
+ * @brief Returns the power state for chassis0
+ */
+static auto getPowerState()
+{
+    // TODO: How do we handle multiple chassis?
+    string powerState{};
+    auto bus = sdbusplus::bus::new_default();
+    auto properties =
+        bus.new_method_call("xyz.openbmc_project.State.Chassis",
+                            "/xyz/openbmc_project/state/chassis0",
+                            "org.freedesktop.DBus.Properties", "Get");
+    properties.append("xyz.openbmc_project.State.Chassis");
+    properties.append("CurrentPowerState");
+    auto result = bus.call(properties);
+    if (!result.is_method_error())
+    {
+        variant<string> val;
+        result.read(val);
+        if (auto pVal = get_if<string>(&val))
+        {
+            powerState = *pVal;
+        }
+    }
+    cout << "Power state is: " << powerState << endl;
+    return powerState;
+}
+
+/**
  * @brief Expands location codes
  */
 static auto expandLocationCode(const string& unexpanded, const Parsed& vpdMap,
@@ -630,6 +658,16 @@
         }
 
         baseFruInventoryPath = js["frus"][file][0]["inventoryPath"];
+        // Check if we can read the VPD file based on the power state
+        if (js["frus"][file].at(0).value("powerOffOnly", false))
+        {
+            if ("xyz.openbmc_project.State.Chassis.PowerState.On" ==
+                getPowerState())
+            {
+                cout << "This VPD cannot be read when power is ON" << endl;
+                return 0;
+            }
+        }
 
         Binary vpdVector = getVpdDataInVector(js, file);
         ParserInterface* parser = ParserFactory::getParser(move(vpdVector));