Publish DRAM Manufacturer ID

The commit publishes DRAM manufacturer ID over D-Bus.

Dependent PDI commit:
https://gerrit.openbmc.org/c/openbmc/phosphor-dbus-interfaces/+/71554

Change-Id: I8acb8f311c83cfcbbd7cadc24e2e226f15824069
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
diff --git a/vpd-parser/isdimm_vpd_parser.cpp b/vpd-parser/isdimm_vpd_parser.cpp
index 96b9274..589dd68 100644
--- a/vpd-parser/isdimm_vpd_parser.cpp
+++ b/vpd-parser/isdimm_vpd_parser.cpp
@@ -38,6 +38,8 @@
 static constexpr auto SPD_JEDEC_DDR4_SDRAM_ADDR_OFFSET = 5;
 static constexpr auto SPD_JEDEC_DDR4_DRAM_PRI_PACKAGE_OFFSET = 6;
 static constexpr auto SPD_JEDEC_DDR4_DRAM_MODULE_ORG_OFFSET = 12;
+static constexpr auto SPD_JEDEC_DDR4_DRAM_MANUFACTURER_ID_OFFSET = 320;
+static constexpr auto SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH = 2;
 
 // DDR5 JEDEC specification constants
 static constexpr auto SPD_JEDEC_DDR5_SUB_CHANNELS_PER_DIMM = 235;
@@ -58,6 +60,7 @@
 static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_MASK = 0x1F;
 static constexpr auto SPD_JEDEC_DDR5_RANK_MIX = 234;
 static constexpr auto SPD_JEDEC_DDR5_RANK_MIX_SYMMETRICAL_MASK = 0x40;
+static constexpr auto SPD_JEDEC_DDR5_DRAM_MANUFACTURER_ID_OFFSET = 552;
 
 auto isdimmVpdParser::getDDR4DimmCapacity(Binary::const_iterator& iterator)
 {
@@ -220,6 +223,25 @@
     return ccin;
 }
 
+auto isdimmVpdParser::getDDR4ManufacturerId()
+{
+    Binary mfgId(SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH);
+
+    if (memVpd.size() < (SPD_JEDEC_DDR4_DRAM_MANUFACTURER_ID_OFFSET +
+                         SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH))
+    {
+        std::cout
+            << "VPD length is less than the offset of Manufacturer ID. Can't fetch it"
+            << std::endl;
+        return mfgId;
+    }
+
+    std::copy_n((memVpd.cbegin() + SPD_JEDEC_DDR4_DRAM_MANUFACTURER_ID_OFFSET),
+                SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH, mfgId.begin());
+
+    return mfgId;
+}
+
 auto isdimmVpdParser::getDDR5DimmCapacity(Binary::const_iterator& iterator)
 {
     // dummy implementation to be updated when required
@@ -284,6 +306,25 @@
     return ccin;
 }
 
+auto isdimmVpdParser::getDDR5ManufacturerId()
+{
+    Binary mfgId(SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH);
+
+    if (memVpd.size() < (SPD_JEDEC_DDR5_DRAM_MANUFACTURER_ID_OFFSET +
+                         SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH))
+    {
+        std::cout
+            << "VPD length is less than the offset of Manufacturer ID. Can't fetch it"
+            << std::endl;
+        return mfgId;
+    }
+
+    std::copy_n((memVpd.cbegin() + SPD_JEDEC_DDR5_DRAM_MANUFACTURER_ID_OFFSET),
+                SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH, mfgId.begin());
+
+    return mfgId;
+}
+
 kwdVpdMap isdimmVpdParser::readKeywords(Binary::const_iterator& iterator)
 {
     inventory::KeywordVpdMap keywordValueMap{};
@@ -307,6 +348,8 @@
         auto ccin = getDDR5CCIN(partNumber);
         keywordValueMap.emplace("CC", move(ccin));
         keywordValueMap.emplace("PN", move(partNumber));
+        auto mfgID = getDDR5ManufacturerId();
+        keywordValueMap.emplace("DI", move(mfgID));
     }
     else if ((iterator[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
              constants::SPD_DRAM_TYPE_DDR4)
@@ -326,12 +369,15 @@
         auto fruNumber = getDDR4FruNumber(partNumber, iterator);
         auto serialNumber = getDDR4SerialNumber(iterator);
         auto ccin = getDDR4CCIN(fruNumber);
+        auto mfgID = getDDR4ManufacturerId();
+
         // PN value is made same as FN value
         auto displayPartNumber = fruNumber;
         keywordValueMap.emplace("PN", move(displayPartNumber));
         keywordValueMap.emplace("FN", move(fruNumber));
         keywordValueMap.emplace("SN", move(serialNumber));
         keywordValueMap.emplace("CC", move(ccin));
+        keywordValueMap.emplace("DI", move(mfgID));
     }
     return keywordValueMap;
 }
diff --git a/vpd-parser/isdimm_vpd_parser.hpp b/vpd-parser/isdimm_vpd_parser.hpp
index c8105f4..8270884 100644
--- a/vpd-parser/isdimm_vpd_parser.hpp
+++ b/vpd-parser/isdimm_vpd_parser.hpp
@@ -99,6 +99,13 @@
     auto getDDR4CCIN(const std::string& partNumber);
 
     /**
+     * @brief The function fetches manufacturer's ID of DIMM.
+     *
+     * @return manufacturer ID.
+     */
+    auto getDDR4ManufacturerId();
+
+    /**
      * @brief This function calculates DIMM size from SPD
      *
      * @param[in] iterator - iterator to buffer containing SPD
@@ -138,6 +145,13 @@
      */
     auto getDDR5CCIN(const std::string& partNumber);
 
+    /**
+     * @brief The function fetches manufacturer's ID of DIMM.
+     *
+     * @return manufacturer ID.
+     */
+    auto getDDR5ManufacturerId();
+
     // vdp file to be parsed
     const Binary& memVpd;
 };
diff --git a/vpd-parser/memory_vpd_parser.cpp b/vpd-parser/memory_vpd_parser.cpp
index ea45792..c141da9 100644
--- a/vpd-parser/memory_vpd_parser.cpp
+++ b/vpd-parser/memory_vpd_parser.cpp
@@ -42,6 +42,8 @@
 
 static constexpr auto PRIMARY_BUS_WIDTH_32_BITS = 32;
 static constexpr auto PRIMARY_BUS_WIDTH_UNUSED = 0;
+static constexpr auto DRAM_MANUFACTURER_ID_OFFSET = 0x228;
+static constexpr auto DRAM_MANUFACTURER_ID_LENGTH = 0x02;
 
 bool memoryVpdParser::checkValidValue(uint8_t l_ByteValue, uint8_t shift,
                                       uint8_t minValue, uint8_t maxValue)
@@ -364,10 +366,15 @@
     advance(iterator, SERIAL_NUM_LEN);
     Binary ccin(iterator, iterator + CCIN_LEN);
 
+    Binary mfgId(DRAM_MANUFACTURER_ID_LENGTH);
+    std::copy_n((memVpd.cbegin() + DRAM_MANUFACTURER_ID_OFFSET),
+                DRAM_MANUFACTURER_ID_LENGTH, mfgId.begin());
+
     map.emplace("FN", partNumber);
     map.emplace("PN", move(partNumber));
     map.emplace("SN", move(serialNumber));
     map.emplace("CC", move(ccin));
+    map.emplace("DI", move(mfgId));
 
     return map;
 }