DD2:  Enable Dimms

This commit checks for the chip version , if it is DD2 or higher then bind the device driver
for all the Dimms(supported in vpd json)

Test-
Tested on HW with DD2 processor.
rain135bmc
root@rain135bmc:/sys/bus/i2c/drivers/at24# ls
0-0051   10-0050  6-0053   7-0050   8-0050   8-0051   9-0050   bind     uevent   unbind

===================after execution============================================================

root@rain135bmc:/sys/bus/i2c/drivers/at24# ls
0-0051    111-0050  311-0050  6-0053    8-0050    9-0050    uevent
10-0050   202-0050  402-0050  7-0050    8-0051    bind      unbind

root@rain135bmc:/sys/bus/i2c/devices# ls
0-0020   11-0051  4-0049   5-0051   7-0040   8-0011   9-004d   i2c-110  i2c-14   i2c-203  i2c-300  i2c-4    i2c-417
0-0051   13-0050  4-004a   6-0048   7-0048   8-0032   9-0050   i2c-111  i2c-15   i2c-210  i2c-301  i2c-402  i2c-5
10-004c  14-0050  4-0050   6-004a   7-0050   8-0048   i2c-0    i2c-112  i2c-16   i2c-211  i2c-310  i2c-403  i2c-6
10-004d  15-0050  4-0051   6-004b   7-0051   8-004a   i2c-1    i2c-113  i2c-17   i2c-214  i2c-311  i2c-410  i2c-7
10-0050  3-0061   4-0052   6-0050   7-0052   8-0050   i2c-10   i2c-114  i2c-18   i2c-215  i2c-312  i2c-411  i2c-8
11-0048  3-0068   5-0048   6-0051   7-0061   8-0051   i2c-100  i2c-115  i2c-19   i2c-216  i2c-313  i2c-414  i2c-9
11-0049  3-0069   5-0049   6-0052   7-0076   8-0061   i2c-101  i2c-12   i2c-2    i2c-217  i2c-314  i2c-415
11-0050  4-0048   5-0050   6-0053   7-1062   9-004c   i2c-11   i2c-13   i2c-202  i2c-3    i2c-315  i2c-416
root@rain135bmc:/sys/bus/i2c/devices#

===================Executing patch============================================================

root@rain135bmc:/tmp# ./ibm-read-vpd -f /sys/bus/spi/drivers/at25/spi12.0/eeprom

===================after execution============================================================

root@rain71bmc:/sys/bus/i2c/devices# ls
0-0020    111-0050  214-0050  313-0050  411-0050  6-0050    8-0011    i2c-10    i2c-14    i2c-215   i2c-4     i2c-8
0-0051    112-0050  215-0050  314-0050  414-0050  6-0051    8-0032    i2c-100   i2c-15    i2c-216   i2c-402   i2c-9
10-004c   113-0050  216-0050  315-0050  415-0050  6-0052    8-0048    i2c-101   i2c-16    i2c-217   i2c-403
10-004d   114-0050  217-0050  4-0048    416-0050  6-0053    8-004a    i2c-11    i2c-17    i2c-3     i2c-410
10-0050   115-0050  3-0061    4-0049    417-0050  7-0040    8-0050    i2c-110   i2c-18    i2c-300   i2c-411
100-0050  13-0050   3-0068    4-004a    5-0048    7-0048    8-0051    i2c-111   i2c-19    i2c-301   i2c-414
101-0050  14-0050   3-0069    4-0050    5-0049    7-0050    8-0061    i2c-112   i2c-2     i2c-310   i2c-415
11-0048   15-0050   300-0050  4-0051    5-0050    7-0051    9-004c    i2c-113   i2c-202   i2c-311   i2c-416
11-0049   202-0050  301-0050  4-0052    5-0051    7-0052    9-004d    i2c-114   i2c-203   i2c-312   i2c-417
11-0050   203-0050  310-0050  402-0050  6-0048    7-0061    9-0050    i2c-115   i2c-210   i2c-313   i2c-5
11-0051   210-0050  311-0050  403-0050  6-004a    7-0076    i2c-0     i2c-12    i2c-211   i2c-314   i2c-6
110-0050  211-0050  312-0050  410-0050  6-004b    7-1062    i2c-1     i2c-13    i2c-214   i2c-315   i2c-7
root@rain135bmc:/sys/bus/i2c/devices#
Also, vpd got collected for all these Dimms-

root@rain135c:/tmp# busctl introspect  xyz.openbmc_project.Inventory.Manager  /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm22| grep -e MemorySizeInKB -e  Present -e PrettyName -e Model  -e PartNumber  -e SerialNumber
.Model                                                property  s         "327A"                                   emits-change writable
.PartNumber                                           property  s         "78P6574"                                emits-change writable
.SerialNumber                                         property  s         "YH30MS04N004"                           emits-change writable
.SparePartNumber                                      property  s         ""                                       emits-change writable
.SubModel                                             property  s         ""                                       emits-change writable
.Present                                              property  b         true                                     emits-change writable
.PrettyName                                           property  s         "Memory DIMM"                            emits-change writable
.MemorySizeInKB                                       property  u         33554432                                 emits-change writable

root@rain135c:/tmp# busctl introspect  xyz.openbmc_project.Inventory.Manager  /xyz/openbmc_project/inventory/system/chassis/motherboard/dimm31| grep -e MemorySizeInKB -e  Present -e PrettyName -e Model  -e PartNumber  -e SerialNumber
.Model                                                property  s         "327A"                                   emits-change writable
.PartNumber                                           property  s         "78P6574"                                emits-change writable
.SerialNumber                                         property  s         "YH301T9CH022"                           emits-change writable
.SparePartNumber                                      property  s         ""                                       emits-change writable
.SubModel                                             property  s         ""                                       emits-change writable
.Present                                              property  b         true                                     emits-change writable
.PrettyName                                           property  s         "Memory DIMM"                            emits-change writable
.MemorySizeInKB                                       property  u         33554432                                 emits-change writable
root@rain135c:/tmp#

Change-Id: Iab1b099fe0352c08327e70aa8c2e33fc213cc40f
Signed-off-by: Alpana Kumari <alpankum@in.ibm.com>
diff --git a/ibm_vpd_app.cpp b/ibm_vpd_app.cpp
index bb0088f..b7de1a6 100644
--- a/ibm_vpd_app.cpp
+++ b/ibm_vpd_app.cpp
@@ -14,6 +14,7 @@
 
 #include <CLI/CLI.hpp>
 #include <algorithm>
+#include <boost/algorithm/string.hpp>
 #include <cstdarg>
 #include <exception>
 #include <filesystem>
@@ -23,6 +24,7 @@
 #include <iterator>
 #include <nlohmann/json.hpp>
 #include <phosphor-logging/log.hpp>
+#include <regex>
 
 using namespace std;
 using namespace openpower::vpd;
@@ -175,7 +177,6 @@
             {
                 Binary vec(get_if<Binary>(&kwVal.second)->begin(),
                            get_if<Binary>(&kwVal.second)->end());
-
                 prop.emplace(move(kw), move(vec));
             }
             else
@@ -755,6 +756,107 @@
 }
 
 /**
+ * @brief This checks for is this FRU a processor
+ *        And if yes, then checks for is this primary
+ *
+ * @param[in] js- vpd json to get the information about this FRU
+ * @param[in] filePath- FRU vpd
+ *
+ * @return true/false
+ */
+bool isThisPrimaryProcessor(nlohmann::json& js, const string& filePath)
+{
+    bool isProcessor = false;
+    bool isPrimary = false;
+
+    for (const auto& item : js["frus"][filePath])
+    {
+        if (item.find("extraInterfaces") != item.end())
+        {
+            for (const auto& eI : item["extraInterfaces"].items())
+            {
+                if (eI.key().find("Inventory.Item.Cpu") != string::npos)
+                {
+                    isProcessor = true;
+                }
+            }
+        }
+
+        if (isProcessor)
+        {
+            string cpuType = item.value("cpuType", "");
+            if (cpuType == "primary")
+            {
+                isPrimary = true;
+            }
+        }
+    }
+
+    return (isProcessor && isPrimary);
+}
+
+/**
+ * @brief This finds DIMM vpd in vpd json and enables them by binding the device
+ *        driver
+ * @param[in] js- vpd json to iterate through and take action if it is DIMM
+ */
+void doEnableAllDimms(nlohmann::json& js)
+{
+    // iterate over each fru
+    for (const auto& eachFru : js["frus"].items())
+    {
+        // skip the driver binding if eeprom already exists
+        if (fs::exists(eachFru.key()))
+        {
+            continue;
+        }
+
+        for (const auto& eachInventory : eachFru.value())
+        {
+            if (eachInventory.find("extraInterfaces") != eachInventory.end())
+            {
+                for (const auto& eI : eachInventory["extraInterfaces"].items())
+                {
+                    if (eI.key().find("Inventory.Item.Dimm") != string::npos)
+                    {
+                        string dimmVpd = eachFru.key();
+                        // fetch it from
+                        // "/sys/bus/i2c/drivers/at24/414-0050/eeprom"
+
+                        regex matchPatern("([0-9]+-[0-9]{4})");
+                        smatch matchFound;
+                        if (regex_search(dimmVpd, matchFound, matchPatern))
+                        {
+                            vector<string> i2cReg;
+                            boost::split(i2cReg, matchFound.str(0),
+                                         boost::is_any_of("-"));
+
+                            // remove 0s from begining
+                            const regex pattern("^0+(?!$)");
+                            for (auto& i : i2cReg)
+                            {
+                                i = regex_replace(i, pattern, "");
+                            }
+
+                            if (i2cReg.size() == 2)
+                            {
+                                // echo 24c32 0x50 >
+                                // /sys/bus/i2c/devices/i2c-16/new_device
+                                string cmnd = "echo 24c32 0x" + i2cReg[1] +
+                                              " > /sys/bus/i2c/devices/i2c-" +
+                                              i2cReg[0] + "/new_device";
+
+                                executeCmd(cmnd);
+                            }
+                        }
+                    }
+                }
+            }
+        }
+    }
+}
+
+/**
  * @brief Populate Dbus.
  * This method invokes all the populateInterface functions
  * and notifies PIM about dbus object.
@@ -798,6 +900,23 @@
                 log<level::ERR>("No object path found");
             }
         }
+        else
+        {
+            // check if it is processor vpd.
+            auto isPrimaryCpu = isThisPrimaryProcessor(js, filePath);
+
+            if (isPrimaryCpu)
+            {
+                auto ddVersion = getKwVal(vpdMap, "CRP0", "DD");
+
+                auto chipVersion = atoi(ddVersion.substr(1, 2).c_str());
+
+                if (chipVersion >= 2)
+                {
+                    doEnableAllDimms(js);
+                }
+            }
+        }
     }
 
     for (const auto& item : js["frus"][filePath])
diff --git a/ibm_vpd_utils.cpp b/ibm_vpd_utils.cpp
index 9b5530e..b8af0ed 100644
--- a/ibm_vpd_utils.cpp
+++ b/ibm_vpd_utils.cpp
@@ -543,5 +543,27 @@
     badVpdFileStream.write(reinterpret_cast<const char*>(vpdVector.data()),
                            vpdVector.size());
 }
+
+const string getKwVal(const Parsed& vpdMap, const string& rec,
+                      const string& kwd)
+{
+    string kwVal{};
+
+    auto findRec = vpdMap.find(rec);
+
+    // check if record is found in map we got by parser
+    if (findRec != vpdMap.end())
+    {
+        auto findKwd = findRec->second.find(kwd);
+
+        if (findKwd != findRec->second.end())
+        {
+            kwVal = findKwd->second;
+        }
+    }
+
+    return kwVal;
+}
+
 } // namespace vpd
 } // namespace openpower
\ No newline at end of file
diff --git a/ibm_vpd_utils.hpp b/ibm_vpd_utils.hpp
index 8983985..8cedafb 100644
--- a/ibm_vpd_utils.hpp
+++ b/ibm_vpd_utils.hpp
@@ -209,5 +209,20 @@
  * @param[in] vpdVector - bad vpd vector
  */
 void dumpBadVpd(const std::string& file, const Binary& vpdVector);
+
+/*
+ * @brief This function fetches the value for given keyword in the given record
+ *        from vpd data and returns this value.
+ *
+ * @param[in] vpdMap - vpd to find out the data
+ * @param[in] rec - Record under which desired keyword exists
+ * @param[in] kwd - keyword to read the data from
+ *
+ * @returns keyword value if record/keyword combination found
+ *          empty string if record or keyword is not found.
+ */
+const string getKwVal(const Parsed& vpdMap, const string& rec,
+                      const string& kwd);
+
 } // namespace vpd
 } // namespace openpower
\ No newline at end of file