blob: 1ce495c674caa85dcc8e45590227362ebab97632 [file] [log] [blame]
Alpana Kumaria00936f2020-04-14 07:15:46 -05001#include "memory_vpd_parser.hpp"
2
3#include <iostream>
4#include <numeric>
5#include <string>
6
7namespace openpower
8{
9namespace vpd
10{
11namespace memory
12{
13namespace parser
14{
15using namespace inventory;
Alpana Kumaria00936f2020-04-14 07:15:46 -050016using namespace constants;
17using namespace std;
SunnySrivastava1984e12b1812020-05-26 02:23:11 -050018using namespace openpower::vpd::parser;
Alpana Kumaria00936f2020-04-14 07:15:46 -050019
Alpana Kumari3ab26a72021-04-05 19:09:19 +000020static constexpr auto MEM_BYTE_4 = 4;
21static constexpr auto MEM_BYTE_6 = 6;
22static constexpr auto MEM_BYTE_12 = 12;
23static constexpr auto MEM_BYTE_13 = 13;
24static constexpr auto JEDEC_SDRAM_CAP_MASK = 0x0F;
25static constexpr auto JEDEC_PRI_BUS_WIDTH_MASK = 0x07;
26static constexpr auto JEDEC_SDRAM_WIDTH_MASK = 0x07;
27static constexpr auto JEDEC_NUM_RANKS_MASK = 0x38;
28static constexpr auto JEDEC_DIE_COUNT_MASK = 0x70;
29static constexpr auto JEDEC_SINGLE_LOAD_STACK = 0x02;
30static constexpr auto JEDEC_SIGNAL_LOADING_MASK = 0x03;
31
32static constexpr auto JEDEC_SDRAMCAP_MULTIPLIER = 256;
33static constexpr auto JEDEC_PRI_BUS_WIDTH_MULTIPLIER = 8;
34static constexpr auto JEDEC_SDRAM_WIDTH_MULTIPLIER = 4;
35static constexpr auto JEDEC_SDRAMCAP_RESERVED = 6;
36static constexpr auto JEDEC_RESERVED_BITS = 3;
37static constexpr auto JEDEC_DIE_COUNT_RIGHT_SHIFT = 4;
38
39auto memoryVpdParser::getDimmSize(Binary::const_iterator iterator)
40{
41 size_t tmp = 0, dimmSize = 0;
42
43 size_t sdramCap = 1, priBusWid = 1, sdramWid = 1, logicalRanksPerDimm = 1;
44 Byte dieCount = 1;
45
46 // NOTE: This calculation is Only for DDR4
47
48 // Calculate SDRAM capacity
49 tmp = iterator[MEM_BYTE_4] & JEDEC_SDRAM_CAP_MASK;
50 /* Make sure the bits are not Reserved */
51 if (tmp > JEDEC_SDRAMCAP_RESERVED)
52 {
53 cerr << "Bad data in vpd byte 4. Can't calculate SDRAM capacity and so "
54 "dimm size.\n ";
55 return dimmSize;
56 }
57
58 sdramCap = (sdramCap << tmp) * JEDEC_SDRAMCAP_MULTIPLIER;
59
60 /* Calculate Primary bus width */
61 tmp = iterator[MEM_BYTE_13] & JEDEC_PRI_BUS_WIDTH_MASK;
62 if (tmp > JEDEC_RESERVED_BITS)
63 {
64 cerr << "Bad data in vpd byte 13. Can't calculate primary bus width "
65 "and so dimm size.\n ";
66 return dimmSize;
67 }
68 priBusWid = (priBusWid << tmp) * JEDEC_PRI_BUS_WIDTH_MULTIPLIER;
69
70 /* Calculate SDRAM width */
71 tmp = iterator[MEM_BYTE_12] & JEDEC_SDRAM_WIDTH_MASK;
72 if (tmp > JEDEC_RESERVED_BITS)
73 {
74 cerr << "Bad data in vpd byte 12. Can't calculate SDRAM width and so "
75 "dimm size.\n ";
76 return dimmSize;
77 }
78 sdramWid = (sdramWid << tmp) * JEDEC_SDRAM_WIDTH_MULTIPLIER;
79
80 tmp = iterator[MEM_BYTE_6] & JEDEC_SIGNAL_LOADING_MASK;
81
82 if (tmp == JEDEC_SINGLE_LOAD_STACK)
83 {
84 // Fetch die count
85 tmp = iterator[MEM_BYTE_6] & JEDEC_DIE_COUNT_MASK;
86 tmp >>= JEDEC_DIE_COUNT_RIGHT_SHIFT;
87 dieCount = tmp + 1;
88 }
89
90 /* Calculate Number of ranks */
91 tmp = iterator[MEM_BYTE_12] & JEDEC_NUM_RANKS_MASK;
92 tmp >>= JEDEC_RESERVED_BITS;
93
94 if (tmp > JEDEC_RESERVED_BITS)
95 {
96 cerr << "Can't calculate number of ranks. Invalid data found.\n ";
97 return dimmSize;
98 }
99 logicalRanksPerDimm = (tmp + 1) * dieCount;
100
101 dimmSize = (sdramCap / JEDEC_PRI_BUS_WIDTH_MULTIPLIER) *
102 (priBusWid / sdramWid) * logicalRanksPerDimm;
103
104 return dimmSize;
105}
106
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500107kwdVpdMap memoryVpdParser::readKeywords(Binary::const_iterator iterator)
Alpana Kumaria00936f2020-04-14 07:15:46 -0500108{
109 KeywordVpdMap map{};
110
Alpana Kumari3ab26a72021-04-05 19:09:19 +0000111 // collect Dimm size value
112 auto dimmSize = getDimmSize(iterator);
113 if (!dimmSize)
114 {
115 cerr << "Error: Calculated dimm size is 0.";
116 }
117
118 map.emplace("MemorySizeInKB", dimmSize);
119 // point the iterator to DIMM data and skip "11S"
120 advance(iterator, MEMORY_VPD_DATA_START + 3);
Alpana Kumari80f15342020-06-09 07:41:02 -0500121 Binary partNumber(iterator, iterator + PART_NUM_LEN);
Alpana Kumaria00936f2020-04-14 07:15:46 -0500122
123 advance(iterator, PART_NUM_LEN);
Alpana Kumari80f15342020-06-09 07:41:02 -0500124 Binary serialNumber(iterator, iterator + SERIAL_NUM_LEN);
Alpana Kumaria00936f2020-04-14 07:15:46 -0500125
126 advance(iterator, SERIAL_NUM_LEN);
Alpana Kumari80f15342020-06-09 07:41:02 -0500127 Binary ccin(iterator, iterator + CCIN_LEN);
Alpana Kumaria00936f2020-04-14 07:15:46 -0500128
Santosh Puranikc68bb912022-07-29 20:15:54 +0530129 map.emplace("FN", partNumber);
Alpana Kumaria00936f2020-04-14 07:15:46 -0500130 map.emplace("PN", move(partNumber));
131 map.emplace("SN", move(serialNumber));
132 map.emplace("CC", move(ccin));
133
134 return map;
135}
136
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500137variant<kwdVpdMap, Store> memoryVpdParser::parse()
Alpana Kumaria00936f2020-04-14 07:15:46 -0500138{
Alpana Kumaria00936f2020-04-14 07:15:46 -0500139 // Read the data and return the map
140 auto iterator = memVpd.cbegin();
Alpana Kumaria00936f2020-04-14 07:15:46 -0500141 auto vpdDataMap = readKeywords(iterator);
142
143 return vpdDataMap;
144}
145
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500146std::string memoryVpdParser::getInterfaceName() const
147{
148 return memVpdInf;
149}
150
Alpana Kumaria00936f2020-04-14 07:15:46 -0500151} // namespace parser
152} // namespace memory
153} // namespace vpd
154} // namespace openpower