PASS 2 Planar support for vpd parser

The system has two planar passes - Pass1 & Pass2 Planars.
Pass1 Planar a buffer connects all pcie cards, Whereas
Pass2 Planar has mux connection established for pcie card selection.

ibm-read-vpd picks up the right deviceTree and json
(either 2UPass1/2UPass2/4UPass1/4UPass2)
based on the HW and IM kw of the planar.

Test-
tested on Rainier 2U simics

root@rainier:/tmp# ./ibm-read-vpd  -f /tmp/systemVpd
imKeyword- 50001001, HW - 0001
Processing with this JSON - /usr/share/vpd/50001001_v1.json

root@rainier:/tmp# ./ibm-read-vpd  -f /tmp/systemVpd
imKeyword- 50001001, HW - 0011
Processing with this JSON - /usr/share/vpd/50001001_v2.json

root@rainier:/tmp# ./ibm-read-vpd  -f /tmp/systemVpd
imKeyword- 50001000, HW - 0011
Processing with this JSON - /usr/share/vpd/50001000_v2.json

root@rainier:/tmp# ./ibm-read-vpd  -f /tmp/systemVpd
imKeyword- 50001000, HW - 0001
Processing with this JSON - /usr/share/vpd/50001000_v1.json
root@rainier:/tmp#

Signed-off-by: Alpana Kumari <alpankum@in.ibm.com>
Change-Id: I36de12d9697039e61e6ad569e1e119f001e782f6
diff --git a/ibm_vpd_utils.cpp b/ibm_vpd_utils.cpp
index 6577969..15e3116 100644
--- a/ibm_vpd_utils.cpp
+++ b/ibm_vpd_utils.cpp
@@ -318,5 +318,107 @@
     return vpdType::INVALID_VPD_FORMAT;
 }
 
+const string getIM(const Parsed& vpdMap)
+{
+    Binary imVal;
+    auto property = vpdMap.find("VSBP");
+    if (property != vpdMap.end())
+    {
+        auto kw = (property->second).find("IM");
+        if (kw != (property->second).end())
+        {
+            copy(kw->second.begin(), kw->second.end(), back_inserter(imVal));
+        }
+    }
+
+    ostringstream oss;
+    for (auto& i : imVal)
+    {
+        oss << setw(2) << setfill('0') << hex << static_cast<int>(i);
+    }
+
+    return oss.str();
+}
+
+const string getHW(const Parsed& vpdMap)
+{
+    Binary hwVal;
+    auto prop = vpdMap.find("VINI");
+    if (prop != vpdMap.end())
+    {
+        auto kw = (prop->second).find("HW");
+        if (kw != (prop->second).end())
+        {
+            copy(kw->second.begin(), kw->second.end(), back_inserter(hwVal));
+        }
+    }
+
+    ostringstream hwString;
+    for (auto& i : hwVal)
+    {
+        hwString << setw(2) << setfill('0') << hex << static_cast<int>(i);
+    }
+
+    return hwString.str();
+}
+
+string getSystemsJson(const Parsed& vpdMap)
+{
+    string jsonPath = "/usr/share/vpd/";
+    string jsonName{};
+
+    ifstream systemJson(SYSTEM_JSON);
+    if (!systemJson)
+    {
+        throw((VpdJsonException("Failed to access Json path", SYSTEM_JSON)));
+    }
+
+    try
+    {
+        auto js = json::parse(systemJson);
+
+        const string hwKeyword = getHW(vpdMap);
+        const string imKeyword = getIM(vpdMap);
+
+        if (js.find("system") == js.end())
+        {
+            throw runtime_error("Invalid systems Json");
+        }
+
+        if (js["system"].find(imKeyword) == js["system"].end())
+        {
+            throw runtime_error(
+                "Invalid system. This system type is not present "
+                "in the systemsJson. IM: " +
+                imKeyword);
+        }
+
+        if ((js["system"][imKeyword].find("constraint") !=
+             js["system"][imKeyword].end()) &&
+            (hwKeyword == js["system"][imKeyword]["constraint"]["HW"]))
+        {
+            jsonName = js["system"][imKeyword]["constraint"]["json"];
+        }
+        else if (js["system"][imKeyword].find("default") !=
+                 js["system"][imKeyword].end())
+        {
+            jsonName = js["system"][imKeyword]["default"];
+        }
+        else
+        {
+            throw runtime_error(
+                "Bad System json. Neither constraint nor default found");
+        }
+
+        jsonPath += jsonName;
+    }
+
+    catch (json::parse_error& ex)
+    {
+        throw(VpdJsonException("Json Parsing failed", SYSTEM_JSON));
+    }
+    return jsonPath;
+}
+
 } // namespace vpd
-} // namespace openpower
+} // namespace openpower
\ No newline at end of file