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