16555e7efSjinuthomas #include "isdimm_vpd_parser.hpp"
26555e7efSjinuthomas 
36555e7efSjinuthomas #include <iostream>
46555e7efSjinuthomas #include <numeric>
56555e7efSjinuthomas #include <string>
66555e7efSjinuthomas 
76555e7efSjinuthomas namespace openpower
86555e7efSjinuthomas {
96555e7efSjinuthomas namespace vpd
106555e7efSjinuthomas {
115700b3c8Sjinuthomas namespace isdimm
126555e7efSjinuthomas {
136555e7efSjinuthomas namespace parser
146555e7efSjinuthomas {
156555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SDRAM_CAP_MASK = 0x0F;
166555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MASK = 0x07;
176555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SDRAM_WIDTH_MASK = 0x07;
186555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_NUM_RANKS_MASK = 0x38;
196555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_DIE_COUNT_MASK = 0x70;
206555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SINGLE_LOAD_STACK = 0x02;
216555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SIGNAL_LOADING_MASK = 0x03;
226555e7efSjinuthomas 
236555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SDRAMCAP_MULTIPLIER = 256;
246555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER = 8;
256555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SDRAM_WIDTH_MULTIPLIER = 4;
266555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SDRAMCAP_RESERVED = 8;
276555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_4_RESERVED_BITS = 4;
286555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_3_RESERVED_BITS = 3;
296555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_DIE_COUNT_RIGHT_SHIFT = 4;
306555e7efSjinuthomas 
316555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_MFG_ID_MSB_OFFSET = 321;
326555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_MFG_ID_LSB_OFFSET = 320;
336555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SN_BYTE0_OFFSET = 325;
346555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SN_BYTE1_OFFSET = 326;
356555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SN_BYTE2_OFFSET = 327;
366555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SN_BYTE3_OFFSET = 328;
376555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SDRAM_DENSITY_BANK_OFFSET = 4;
386555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_SDRAM_ADDR_OFFSET = 5;
396555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_DRAM_PRI_PACKAGE_OFFSET = 6;
406555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR4_DRAM_MODULE_ORG_OFFSET = 12;
41*172e74fdSSunny Srivastava static constexpr auto SPD_JEDEC_DDR4_DRAM_MANUFACTURER_ID_OFFSET = 320;
42*172e74fdSSunny Srivastava static constexpr auto SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH = 2;
436555e7efSjinuthomas 
446555e7efSjinuthomas // DDR5 JEDEC specification constants
456555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SUB_CHANNELS_PER_DIMM = 235;
466555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SUB_CHANNELS_PER_DIMM_MASK = 0x60;
476555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_PRI_BUS_WIDTH_PER_CHANNEL = 235;
486555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_PRI_BUS_WIDTH_PER_CHANNEL_MASK = 0x07;
496555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SDRAM_IO_WIDTH_SYM_ALL = 6;
506555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SDRAM_IO_WIDTH_ASYM_EVEN = 6;
516555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SDRAM_IO_WIDTH_ASYM_ODD = 10;
526555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SDRAM_IO_WIDTH_MASK = 0xE0;
536555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_DIE_PER_PKG_SYM_ALL = 4;
546555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_DIE_PER_PKG_ASYM_EVEN = 4;
556555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_DIE_PER_PKG_ASYM_ODD = 8;
566555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_DIE_PER_PKG_MASK = 0xE0;
576555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_SYM_ALL = 4;
586555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_ASYM_EVEN = 4;
596555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_ASYM_ODD = 8;
606555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_SDRAM_DENSITY_PER_DIE_MASK = 0x1F;
616555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_RANK_MIX = 234;
626555e7efSjinuthomas static constexpr auto SPD_JEDEC_DDR5_RANK_MIX_SYMMETRICAL_MASK = 0x40;
63*172e74fdSSunny Srivastava static constexpr auto SPD_JEDEC_DDR5_DRAM_MANUFACTURER_ID_OFFSET = 552;
646555e7efSjinuthomas 
getDDR4DimmCapacity(Binary::const_iterator & iterator)656555e7efSjinuthomas auto isdimmVpdParser::getDDR4DimmCapacity(Binary::const_iterator& iterator)
666555e7efSjinuthomas {
676555e7efSjinuthomas     size_t tmp = 0, dimmSize = 0;
686555e7efSjinuthomas 
696555e7efSjinuthomas     size_t sdramCap = 1, priBusWid = 1, sdramWid = 1, logicalRanksPerDimm = 1;
706555e7efSjinuthomas     Byte dieCount = 1;
716555e7efSjinuthomas 
726555e7efSjinuthomas     // NOTE: This calculation is Only for DDR4
736555e7efSjinuthomas 
746555e7efSjinuthomas     // Calculate SDRAM  capacity
756555e7efSjinuthomas     tmp = iterator[constants::SPD_BYTE_4] & SPD_JEDEC_DDR4_SDRAM_CAP_MASK;
766555e7efSjinuthomas     /* Make sure the bits are not Reserved */
776555e7efSjinuthomas     if (tmp >= SPD_JEDEC_DDR4_SDRAMCAP_RESERVED)
786555e7efSjinuthomas     {
796555e7efSjinuthomas         std::cerr
806555e7efSjinuthomas             << "Bad data in spd byte 4. Can't calculate SDRAM capacity and so "
816555e7efSjinuthomas                "dimm size.\n ";
826555e7efSjinuthomas         return dimmSize;
836555e7efSjinuthomas     }
846555e7efSjinuthomas 
856555e7efSjinuthomas     sdramCap = (sdramCap << tmp) * SPD_JEDEC_DDR4_SDRAMCAP_MULTIPLIER;
866555e7efSjinuthomas 
876555e7efSjinuthomas     /* Calculate Primary bus width */
886555e7efSjinuthomas     tmp = iterator[constants::SPD_BYTE_13] & SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MASK;
896555e7efSjinuthomas     if (tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS)
906555e7efSjinuthomas     {
916555e7efSjinuthomas         std::cerr
926555e7efSjinuthomas             << "Bad data in spd byte 13. Can't calculate primary bus width "
936555e7efSjinuthomas                "and so dimm size.\n ";
946555e7efSjinuthomas         return dimmSize;
956555e7efSjinuthomas     }
966555e7efSjinuthomas     priBusWid = (priBusWid << tmp) * SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER;
976555e7efSjinuthomas 
986555e7efSjinuthomas     /* Calculate SDRAM width */
996555e7efSjinuthomas     tmp = iterator[constants::SPD_BYTE_12] & SPD_JEDEC_DDR4_SDRAM_WIDTH_MASK;
1006555e7efSjinuthomas     if (tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS)
1016555e7efSjinuthomas     {
1026555e7efSjinuthomas         std::cerr
1036555e7efSjinuthomas             << "Bad data in vpd byte 12. Can't calculate SDRAM width and so "
1046555e7efSjinuthomas                "dimm size.\n ";
1056555e7efSjinuthomas         return dimmSize;
1066555e7efSjinuthomas     }
1076555e7efSjinuthomas     sdramWid = (sdramWid << tmp) * SPD_JEDEC_DDR4_SDRAM_WIDTH_MULTIPLIER;
1086555e7efSjinuthomas 
1096555e7efSjinuthomas     tmp = iterator[constants::SPD_BYTE_6] & SPD_JEDEC_DDR4_SIGNAL_LOADING_MASK;
1106555e7efSjinuthomas 
1116555e7efSjinuthomas     if (tmp == SPD_JEDEC_DDR4_SINGLE_LOAD_STACK)
1126555e7efSjinuthomas     {
1136555e7efSjinuthomas         // Fetch die count
1146555e7efSjinuthomas         tmp = iterator[constants::SPD_BYTE_6] & SPD_JEDEC_DDR4_DIE_COUNT_MASK;
1156555e7efSjinuthomas         tmp >>= SPD_JEDEC_DDR4_DIE_COUNT_RIGHT_SHIFT;
1166555e7efSjinuthomas         dieCount = tmp + 1;
1176555e7efSjinuthomas     }
1186555e7efSjinuthomas 
1196555e7efSjinuthomas     /* Calculate Number of ranks */
1206555e7efSjinuthomas     tmp = iterator[constants::SPD_BYTE_12] & SPD_JEDEC_DDR4_NUM_RANKS_MASK;
1216555e7efSjinuthomas     tmp >>= SPD_JEDEC_DDR4_3_RESERVED_BITS;
1226555e7efSjinuthomas 
1236555e7efSjinuthomas     if (tmp >= SPD_JEDEC_DDR4_4_RESERVED_BITS)
1246555e7efSjinuthomas     {
1256555e7efSjinuthomas         std::cerr << "Can't calculate number of ranks. Invalid data found.\n ";
1266555e7efSjinuthomas         return dimmSize;
1276555e7efSjinuthomas     }
1286555e7efSjinuthomas     logicalRanksPerDimm = (tmp + 1) * dieCount;
1296555e7efSjinuthomas 
1306555e7efSjinuthomas     dimmSize = (sdramCap / SPD_JEDEC_DDR4_PRI_BUS_WIDTH_MULTIPLIER) *
1316555e7efSjinuthomas                (priBusWid / sdramWid) * logicalRanksPerDimm;
1326555e7efSjinuthomas 
1336555e7efSjinuthomas     return dimmSize;
1346555e7efSjinuthomas }
1356555e7efSjinuthomas 
getDDR4PartNumber(Binary::const_iterator & iterator)1366555e7efSjinuthomas auto isdimmVpdParser::getDDR4PartNumber(Binary::const_iterator& iterator)
1376555e7efSjinuthomas {
1386555e7efSjinuthomas     char tmpPN[constants::PART_NUM_LEN + 1] = {'\0'};
1396555e7efSjinuthomas     sprintf(tmpPN, "%02X%02X%02X%X",
1406555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_SDRAM_DENSITY_BANK_OFFSET],
1416555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_SDRAM_ADDR_OFFSET],
1426555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_DRAM_PRI_PACKAGE_OFFSET],
1436555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_DRAM_MODULE_ORG_OFFSET] & 0x0F);
144d640f696Sjinuthomas     std::string partNumber(tmpPN, sizeof(tmpPN) - 1);
1456555e7efSjinuthomas     return partNumber;
1466555e7efSjinuthomas }
1476555e7efSjinuthomas 
getDDR4SerialNumber(Binary::const_iterator & iterator)1486555e7efSjinuthomas auto isdimmVpdParser::getDDR4SerialNumber(Binary::const_iterator& iterator)
1496555e7efSjinuthomas {
1506555e7efSjinuthomas     char tmpSN[constants::SERIAL_NUM_LEN + 1] = {'\0'};
1516555e7efSjinuthomas     sprintf(tmpSN, "%02X%02X%02X%02X%02X%02X",
1526555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_MFG_ID_MSB_OFFSET],
1536555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_MFG_ID_LSB_OFFSET],
1546555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_SN_BYTE0_OFFSET],
1556555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_SN_BYTE1_OFFSET],
1566555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_SN_BYTE2_OFFSET],
1576555e7efSjinuthomas             iterator[SPD_JEDEC_DDR4_SN_BYTE3_OFFSET]);
158d640f696Sjinuthomas     std::string serialNumber(tmpSN, sizeof(tmpSN) - 1);
1596555e7efSjinuthomas     return serialNumber;
1606555e7efSjinuthomas }
1616555e7efSjinuthomas 
getDDR4FruNumber(const std::string & partNumber,Binary::const_iterator & iterator)162680960e2Sjinuthomas auto isdimmVpdParser::getDDR4FruNumber(const std::string& partNumber,
163680960e2Sjinuthomas                                        Binary::const_iterator& iterator)
1646555e7efSjinuthomas {
1656555e7efSjinuthomas     // check for 128GB ISRDIMM not implemented
1666555e7efSjinuthomas     //(128GB 2RX4(8GX72) IS RDIMM 36*(16GBIT, 2H),1.2V 288PIN,1.2" ROHS) - NA
1676555e7efSjinuthomas 
168680960e2Sjinuthomas     // MTB Units is used in deciding the frequency of the DIMM
169680960e2Sjinuthomas     // This is applicable only for DDR4 specification
170680960e2Sjinuthomas     // 10 - DDR4-1600
171680960e2Sjinuthomas     // 9  - DDR4-1866
172680960e2Sjinuthomas     // 8  - DDR4-2133
173680960e2Sjinuthomas     // 7  - DDR4-2400
174680960e2Sjinuthomas     // 6  - DDR4-2666
175680960e2Sjinuthomas     // 5  - DDR4-3200
176680960e2Sjinuthomas     // pnFreqFnMap < tuple <partNumber, MTBUnits>, fruNumber>
177680960e2Sjinuthomas     static std::map<std::tuple<std::string, uint8_t>, std::string> pnFreqFnMap =
178680960e2Sjinuthomas         {{std::make_tuple("8421000", 6), "78P4191"},
179680960e2Sjinuthomas          {std::make_tuple("8421008", 6), "78P4192"},
180680960e2Sjinuthomas          {std::make_tuple("8529000", 6), "78P4197"},
181680960e2Sjinuthomas          {std::make_tuple("8529008", 6), "78P4198"},
182680960e2Sjinuthomas          {std::make_tuple("8529928", 6), "78P4199"},
183680960e2Sjinuthomas          {std::make_tuple("8529B28", 6), "78P4200"},
184680960e2Sjinuthomas          {std::make_tuple("8631928", 6), "78P6925"},
185680960e2Sjinuthomas          {std::make_tuple("8529000", 5), "78P7317"},
186680960e2Sjinuthomas          {std::make_tuple("8529008", 5), "78P7318"},
187680960e2Sjinuthomas          {std::make_tuple("8631008", 5), "78P6815"}};
1886555e7efSjinuthomas 
1896555e7efSjinuthomas     std::string fruNumber;
190680960e2Sjinuthomas     uint8_t mtbUnits = iterator[openpower::vpd::constants::SPD_BYTE_18] &
191680960e2Sjinuthomas                        openpower::vpd::constants::SPD_BYTE_MASK;
192680960e2Sjinuthomas     std::tuple<std::string, uint8_t> tup_key = {partNumber, mtbUnits};
193680960e2Sjinuthomas     auto itr = pnFreqFnMap.find(tup_key);
194680960e2Sjinuthomas     if (itr != pnFreqFnMap.end())
1956555e7efSjinuthomas     {
1966555e7efSjinuthomas         fruNumber = itr->second;
1976555e7efSjinuthomas     }
1986555e7efSjinuthomas     else
1996555e7efSjinuthomas     {
2006555e7efSjinuthomas         fruNumber = "FFFFFFF";
2016555e7efSjinuthomas     }
2026555e7efSjinuthomas     return fruNumber;
2036555e7efSjinuthomas }
2046555e7efSjinuthomas 
getDDR4CCIN(const std::string & fruNumber)205680960e2Sjinuthomas auto isdimmVpdParser::getDDR4CCIN(const std::string& fruNumber)
2066555e7efSjinuthomas {
2076555e7efSjinuthomas     static std::unordered_map<std::string, std::string> pnCCINMap = {
208680960e2Sjinuthomas         {"78P4191", "324D"}, {"78P4192", "324E"}, {"78P4197", "324E"},
209680960e2Sjinuthomas         {"78P4198", "324F"}, {"78P4199", "325A"}, {"78P4200", "324C"},
210680960e2Sjinuthomas         {"78P6925", "32BC"}, {"78P7317", "331A"}, {"78P7318", "331F"},
211680960e2Sjinuthomas         {"78P6815", "32BB"}};
2126555e7efSjinuthomas 
2136555e7efSjinuthomas     std::string ccin;
214680960e2Sjinuthomas     auto itr = pnCCINMap.find(fruNumber);
2156555e7efSjinuthomas     if (itr != pnCCINMap.end())
2166555e7efSjinuthomas     {
2176555e7efSjinuthomas         ccin = itr->second;
2186555e7efSjinuthomas     }
2196555e7efSjinuthomas     else
2206555e7efSjinuthomas     {
2216555e7efSjinuthomas         ccin = "XXXX";
2226555e7efSjinuthomas     }
2236555e7efSjinuthomas     return ccin;
2246555e7efSjinuthomas }
2256555e7efSjinuthomas 
getDDR4ManufacturerId()226*172e74fdSSunny Srivastava auto isdimmVpdParser::getDDR4ManufacturerId()
227*172e74fdSSunny Srivastava {
228*172e74fdSSunny Srivastava     Binary mfgId(SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH);
229*172e74fdSSunny Srivastava 
230*172e74fdSSunny Srivastava     if (memVpd.size() < (SPD_JEDEC_DDR4_DRAM_MANUFACTURER_ID_OFFSET +
231*172e74fdSSunny Srivastava                          SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH))
232*172e74fdSSunny Srivastava     {
233*172e74fdSSunny Srivastava         std::cout
234*172e74fdSSunny Srivastava             << "VPD length is less than the offset of Manufacturer ID. Can't fetch it"
235*172e74fdSSunny Srivastava             << std::endl;
236*172e74fdSSunny Srivastava         return mfgId;
237*172e74fdSSunny Srivastava     }
238*172e74fdSSunny Srivastava 
239*172e74fdSSunny Srivastava     std::copy_n((memVpd.cbegin() + SPD_JEDEC_DDR4_DRAM_MANUFACTURER_ID_OFFSET),
240*172e74fdSSunny Srivastava                 SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH, mfgId.begin());
241*172e74fdSSunny Srivastava 
242*172e74fdSSunny Srivastava     return mfgId;
243*172e74fdSSunny Srivastava }
244*172e74fdSSunny Srivastava 
getDDR5DimmCapacity(Binary::const_iterator & iterator)2456555e7efSjinuthomas auto isdimmVpdParser::getDDR5DimmCapacity(Binary::const_iterator& iterator)
2466555e7efSjinuthomas {
2476555e7efSjinuthomas     // dummy implementation to be updated when required
2486555e7efSjinuthomas     size_t dimmSize = 0;
2496555e7efSjinuthomas     (void)iterator;
2506555e7efSjinuthomas     return dimmSize;
2516555e7efSjinuthomas }
2526555e7efSjinuthomas 
getDDR5PartNumber(Binary::const_iterator & iterator)2536555e7efSjinuthomas auto isdimmVpdParser::getDDR5PartNumber(Binary::const_iterator& iterator)
2546555e7efSjinuthomas {
2556555e7efSjinuthomas     // dummy implementation to be updated when required
2566555e7efSjinuthomas     std::string partNumber;
2576555e7efSjinuthomas     (void)iterator;
2586555e7efSjinuthomas     partNumber = "0123456";
2596555e7efSjinuthomas     return partNumber;
2606555e7efSjinuthomas }
2616555e7efSjinuthomas 
getDDR5SerialNumber(Binary::const_iterator & iterator)2626555e7efSjinuthomas auto isdimmVpdParser::getDDR5SerialNumber(Binary::const_iterator& iterator)
2636555e7efSjinuthomas {
2646555e7efSjinuthomas     // dummy implementation to be updated when required
2656555e7efSjinuthomas     std::string serialNumber;
2666555e7efSjinuthomas     (void)iterator;
2676555e7efSjinuthomas     serialNumber = "444444444444";
2686555e7efSjinuthomas     return serialNumber;
2696555e7efSjinuthomas }
2706555e7efSjinuthomas 
getDDR5FruNumber(const std::string & partNumber)2716555e7efSjinuthomas auto isdimmVpdParser::getDDR5FruNumber(const std::string& partNumber)
2726555e7efSjinuthomas {
2736555e7efSjinuthomas     // dummy implementation to be updated when required
2746555e7efSjinuthomas     static std::unordered_map<std::string, std::string> pnFruMap = {
2756555e7efSjinuthomas         {"1234567", "XXXXXXX"}};
2766555e7efSjinuthomas 
2776555e7efSjinuthomas     std::string fruNumber;
2786555e7efSjinuthomas     auto itr = pnFruMap.find(partNumber);
2796555e7efSjinuthomas     if (itr != pnFruMap.end())
2806555e7efSjinuthomas     {
2816555e7efSjinuthomas         fruNumber = itr->second;
2826555e7efSjinuthomas     }
2836555e7efSjinuthomas     else
2846555e7efSjinuthomas     {
2856555e7efSjinuthomas         fruNumber = "FFFFFFF";
2866555e7efSjinuthomas     }
2876555e7efSjinuthomas     return fruNumber;
2886555e7efSjinuthomas }
2896555e7efSjinuthomas 
getDDR5CCIN(const std::string & partNumber)2906555e7efSjinuthomas auto isdimmVpdParser::getDDR5CCIN(const std::string& partNumber)
2916555e7efSjinuthomas {
2926555e7efSjinuthomas     // dummy implementation to be updated when required
2936555e7efSjinuthomas     static std::unordered_map<std::string, std::string> pnCCINMap = {
2946555e7efSjinuthomas         {"1234567", "XXXX"}};
2956555e7efSjinuthomas 
2966555e7efSjinuthomas     std::string ccin;
2976555e7efSjinuthomas     auto itr = pnCCINMap.find(partNumber);
2986555e7efSjinuthomas     if (itr != pnCCINMap.end())
2996555e7efSjinuthomas     {
3006555e7efSjinuthomas         ccin = itr->second;
3016555e7efSjinuthomas     }
3026555e7efSjinuthomas     else
3036555e7efSjinuthomas     {
3046555e7efSjinuthomas         ccin = "XXXX";
3056555e7efSjinuthomas     }
3066555e7efSjinuthomas     return ccin;
3076555e7efSjinuthomas }
3086555e7efSjinuthomas 
getDDR5ManufacturerId()309*172e74fdSSunny Srivastava auto isdimmVpdParser::getDDR5ManufacturerId()
310*172e74fdSSunny Srivastava {
311*172e74fdSSunny Srivastava     Binary mfgId(SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH);
312*172e74fdSSunny Srivastava 
313*172e74fdSSunny Srivastava     if (memVpd.size() < (SPD_JEDEC_DDR5_DRAM_MANUFACTURER_ID_OFFSET +
314*172e74fdSSunny Srivastava                          SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH))
315*172e74fdSSunny Srivastava     {
316*172e74fdSSunny Srivastava         std::cout
317*172e74fdSSunny Srivastava             << "VPD length is less than the offset of Manufacturer ID. Can't fetch it"
318*172e74fdSSunny Srivastava             << std::endl;
319*172e74fdSSunny Srivastava         return mfgId;
320*172e74fdSSunny Srivastava     }
321*172e74fdSSunny Srivastava 
322*172e74fdSSunny Srivastava     std::copy_n((memVpd.cbegin() + SPD_JEDEC_DDR5_DRAM_MANUFACTURER_ID_OFFSET),
323*172e74fdSSunny Srivastava                 SPD_JEDEC_DRAM_MANUFACTURER_ID_LENGTH, mfgId.begin());
324*172e74fdSSunny Srivastava 
325*172e74fdSSunny Srivastava     return mfgId;
326*172e74fdSSunny Srivastava }
327*172e74fdSSunny Srivastava 
readKeywords(Binary::const_iterator & iterator)3286555e7efSjinuthomas kwdVpdMap isdimmVpdParser::readKeywords(Binary::const_iterator& iterator)
3296555e7efSjinuthomas {
3306555e7efSjinuthomas     inventory::KeywordVpdMap keywordValueMap{};
3316555e7efSjinuthomas     if ((iterator[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
3326555e7efSjinuthomas         constants::SPD_DRAM_TYPE_DDR5)
3336555e7efSjinuthomas     {
334d640f696Sjinuthomas         size_t dimmSize = getDDR5DimmCapacity(iterator);
3356555e7efSjinuthomas         if (!dimmSize)
3366555e7efSjinuthomas         {
3376555e7efSjinuthomas             std::cerr << "Error: Calculated dimm size is 0.";
3386555e7efSjinuthomas         }
3396555e7efSjinuthomas         else
3406555e7efSjinuthomas         {
341d640f696Sjinuthomas             keywordValueMap.emplace("MemorySizeInKB", dimmSize);
3426555e7efSjinuthomas         }
3436555e7efSjinuthomas         auto partNumber = getDDR5PartNumber(iterator);
3446555e7efSjinuthomas         auto fruNumber = getDDR5FruNumber(partNumber);
3456555e7efSjinuthomas         keywordValueMap.emplace("FN", move(fruNumber));
3466555e7efSjinuthomas         auto serialNumber = getDDR5SerialNumber(iterator);
3476555e7efSjinuthomas         keywordValueMap.emplace("SN", move(serialNumber));
3486555e7efSjinuthomas         auto ccin = getDDR5CCIN(partNumber);
3496555e7efSjinuthomas         keywordValueMap.emplace("CC", move(ccin));
350d640f696Sjinuthomas         keywordValueMap.emplace("PN", move(partNumber));
351*172e74fdSSunny Srivastava         auto mfgID = getDDR5ManufacturerId();
352*172e74fdSSunny Srivastava         keywordValueMap.emplace("DI", move(mfgID));
3536555e7efSjinuthomas     }
3546555e7efSjinuthomas     else if ((iterator[constants::SPD_BYTE_2] & constants::SPD_BYTE_MASK) ==
3556555e7efSjinuthomas              constants::SPD_DRAM_TYPE_DDR4)
3566555e7efSjinuthomas     {
357d640f696Sjinuthomas         size_t dimmSize = getDDR4DimmCapacity(iterator);
3586555e7efSjinuthomas         if (!dimmSize)
3596555e7efSjinuthomas         {
3606555e7efSjinuthomas             std::cerr << "Error: Calculated dimm size is 0.";
3616555e7efSjinuthomas         }
3626555e7efSjinuthomas         else
3636555e7efSjinuthomas         {
364d640f696Sjinuthomas             keywordValueMap.emplace("MemorySizeInKB",
365d640f696Sjinuthomas                                     (dimmSize * constants::CONVERT_MB_TO_KB));
3666555e7efSjinuthomas         }
367d640f696Sjinuthomas 
3686555e7efSjinuthomas         auto partNumber = getDDR4PartNumber(iterator);
369680960e2Sjinuthomas         auto fruNumber = getDDR4FruNumber(partNumber, iterator);
3706555e7efSjinuthomas         auto serialNumber = getDDR4SerialNumber(iterator);
371680960e2Sjinuthomas         auto ccin = getDDR4CCIN(fruNumber);
372*172e74fdSSunny Srivastava         auto mfgID = getDDR4ManufacturerId();
373*172e74fdSSunny Srivastava 
3743da3a7b1SJinu Joy Thomas         // PN value is made same as FN value
3753da3a7b1SJinu Joy Thomas         auto displayPartNumber = fruNumber;
3763da3a7b1SJinu Joy Thomas         keywordValueMap.emplace("PN", move(displayPartNumber));
377d640f696Sjinuthomas         keywordValueMap.emplace("FN", move(fruNumber));
378d640f696Sjinuthomas         keywordValueMap.emplace("SN", move(serialNumber));
3796555e7efSjinuthomas         keywordValueMap.emplace("CC", move(ccin));
380*172e74fdSSunny Srivastava         keywordValueMap.emplace("DI", move(mfgID));
3816555e7efSjinuthomas     }
3826555e7efSjinuthomas     return keywordValueMap;
3836555e7efSjinuthomas }
3846555e7efSjinuthomas 
parse()3856555e7efSjinuthomas std::variant<kwdVpdMap, Store> isdimmVpdParser::parse()
3866555e7efSjinuthomas {
3876555e7efSjinuthomas     // Read the data and return the map
3886555e7efSjinuthomas     auto iterator = memVpd.cbegin();
3896555e7efSjinuthomas     auto vpdDataMap = readKeywords(iterator);
3906555e7efSjinuthomas 
3916555e7efSjinuthomas     return vpdDataMap;
3926555e7efSjinuthomas }
3936555e7efSjinuthomas 
3946555e7efSjinuthomas } // namespace parser
3955700b3c8Sjinuthomas } // namespace isdimm
3966555e7efSjinuthomas } // namespace vpd
3976555e7efSjinuthomas } // namespace openpower
398