1 #include "keyword_vpd_parser.hpp"
2
3 #include "const.hpp"
4
5 #include <iostream>
6 #include <numeric>
7 #include <string>
8
9 using namespace openpower::vpd::constants;
10 using namespace openpower::vpd::inventory;
11 using namespace std;
12 using namespace openpower::vpd;
13
14 namespace vpd
15 {
16 namespace keyword
17 {
18 namespace parser
19 {
20
parse()21 variant<KeywordVpdMap, store> KeywordVpdParser::parse()
22 {
23 int kwVpdType;
24
25 validateLargeResourceIdentifierString();
26
27 kwVpdType = validateTheTypeOfKwVpd();
28
29 auto kwValMap = kwValParser();
30
31 // Do not process these two functions for bono type VPD
32 if (!kwVpdType)
33 {
34 validateSmallResourceTypeEnd();
35
36 validateChecksum();
37 }
38
39 validateSmallResourceTypeLastEnd();
40
41 #ifdef DEBUG_KW_VPD
42 cerr << '\n' << " KW " << '\t' << " VALUE " << '\n';
43 for (const auto& it : kwValMap)
44 {
45 cerr << '\n' << " " << it->first << '\t';
46 copy((it->second).begin(), (it->second).end(),
47 ostream_iterator<int>(cout << hex, " "));
48 }
49 #endif
50
51 return kwValMap;
52 }
53
validateLargeResourceIdentifierString()54 void KeywordVpdParser::validateLargeResourceIdentifierString()
55 {
56 kwVpdIterator = keywordVpdVector.begin();
57
58 // Check for large resource type identifier string
59 if (*kwVpdIterator != KW_VPD_START_TAG)
60 {
61 throw std::runtime_error(
62 "Invalid Large resource type Identifier String");
63 }
64
65 itrOutOfBoundCheck(1);
66 advance(kwVpdIterator, sizeof(KW_VPD_START_TAG));
67 }
68
validateTheTypeOfKwVpd()69 int KeywordVpdParser::validateTheTypeOfKwVpd()
70 {
71 size_t dataSize = getKwDataSize();
72
73 itrOutOfBoundCheck(TWO_BYTES + dataSize);
74
75 #ifdef DEBUG_KW_VPD
76 auto dsDeb = dataSize;
77 auto itDeb = kwVpdIterator + TWO_BYTES;
78 std::cout << '\n' << '\t';
79 while (dsDeb != 0)
80 {
81 std::cout << *itDeb;
82 itDeb++;
83 dsDeb--;
84 }
85 std::cout << '\n';
86 #endif
87
88 // +TWO_BYTES is the description's size byte
89 std::advance(kwVpdIterator, TWO_BYTES + dataSize);
90
91 int kwVpdType = 0;
92 // Check for invalid vendor defined large resource type
93 if (*kwVpdIterator != KW_VAL_PAIR_START_TAG)
94 {
95 if (*kwVpdIterator != ALT_KW_VAL_PAIR_START_TAG)
96 {
97 throw std::runtime_error("Invalid Keyword Value Pair Start Tag");
98 }
99 // Bono vpd referred as 1
100 kwVpdType = 1;
101 }
102 return kwVpdType;
103 }
104
kwValParser()105 KeywordVpdMap KeywordVpdParser::kwValParser()
106 {
107 int totalSize = 0;
108 KeywordVpdMap kwValMap;
109
110 checkSumStart = kwVpdIterator;
111
112 itrOutOfBoundCheck(1);
113 kwVpdIterator++;
114
115 // Get the total length of all keyword value pairs
116 totalSize = getKwDataSize();
117
118 if (totalSize == 0)
119 {
120 throw std::runtime_error("Badly formed keyword VPD data");
121 }
122
123 itrOutOfBoundCheck(TWO_BYTES);
124 std::advance(kwVpdIterator, TWO_BYTES);
125
126 // Parse the keyword-value and store the pairs in map
127 while (totalSize > 0)
128 {
129 std::string kwStr(kwVpdIterator, kwVpdIterator + TWO_BYTES);
130
131 totalSize -= TWO_BYTES;
132 itrOutOfBoundCheck(TWO_BYTES);
133 std::advance(kwVpdIterator, TWO_BYTES);
134
135 size_t kwSize = *kwVpdIterator;
136
137 itrOutOfBoundCheck(1);
138 kwVpdIterator++;
139
140 std::vector<uint8_t> valVec(kwVpdIterator, kwVpdIterator + kwSize);
141
142 itrOutOfBoundCheck(kwSize);
143 std::advance(kwVpdIterator, kwSize);
144
145 totalSize -= kwSize + 1;
146
147 kwValMap.emplace(std::make_pair(std::move(kwStr), std::move(valVec)));
148 }
149
150 checkSumEnd = kwVpdIterator - 1;
151
152 return kwValMap;
153 }
154
validateSmallResourceTypeEnd()155 void KeywordVpdParser::validateSmallResourceTypeEnd()
156 {
157 // Check for small resource type end tag
158 if (*kwVpdIterator != KW_VAL_PAIR_END_TAG)
159 {
160 throw std::runtime_error("Invalid Small resource type End");
161 }
162 }
163
validateChecksum()164 void KeywordVpdParser::validateChecksum()
165 {
166 uint8_t checkSum = 0;
167
168 // Checksum calculation
169 checkSum = std::accumulate(checkSumStart, checkSumEnd + 1, checkSum);
170 checkSum = ~checkSum + 1;
171
172 if (checkSum != *(kwVpdIterator + 1))
173 {
174 throw std::runtime_error("Invalid Check sum");
175 }
176 #ifdef DEBUG_KW_VPD
177 std::cout << "\nCHECKSUM : " << std::hex << static_cast<int>(checkSum)
178 << std::endl;
179 #endif
180
181 itrOutOfBoundCheck(TWO_BYTES);
182 std::advance(kwVpdIterator, TWO_BYTES);
183 }
184
validateSmallResourceTypeLastEnd()185 void KeywordVpdParser::validateSmallResourceTypeLastEnd()
186 {
187 // Check for small resource type last end of data
188 if (*kwVpdIterator != KW_VPD_END_TAG)
189 {
190 throw std::runtime_error(
191 "Invalid Small resource type Last End Of Data");
192 }
193 }
194
getKwDataSize()195 size_t KeywordVpdParser::getKwDataSize()
196 {
197 return (*(kwVpdIterator + 1) << 8 | *kwVpdIterator);
198 }
199
itrOutOfBoundCheck(uint8_t incVar)200 void KeywordVpdParser::itrOutOfBoundCheck(uint8_t incVar)
201 {
202 if ((std::distance(keywordVpdVector.begin(), kwVpdIterator + incVar)) >
203 std::distance(keywordVpdVector.begin(), keywordVpdVector.end()))
204 {
205 throw std::runtime_error("Badly formed VPD data");
206 }
207 }
208
getInterfaceName() const209 std::string KeywordVpdParser::getInterfaceName() const
210 {
211 return kwdVpdInf;
212 }
213
214 } // namespace parser
215 } // namespace keyword
216 } // namespace vpd
217