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