blob: b335c070a01523b0d7c9e8f50336f10651fc6524 [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;
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053024
25 validateLargeResourceIdentifierString();
26
27 kwVpdType = validateTheTypeOfKwVpd();
28
29 auto kwValMap = kwValParser();
30
Manojkiran Edaaf921752024-06-17 15:10:21 +053031 // Do not process these two functions for bono type VPD
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053032 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
54void KeywordVpdParser::validateLargeResourceIdentifierString()
55{
56 kwVpdIterator = keywordVpdVector.begin();
57
Manojkiran Edaaf921752024-06-17 15:10:21 +053058 // Check for large resource type identifier string
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +053059 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
69int 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
105KeywordVpdMap 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
155void 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
164void 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
185void 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
195size_t KeywordVpdParser::getKwDataSize()
196{
197 return (*(kwVpdIterator + 1) << 8 | *kwVpdIterator);
198}
199
200void KeywordVpdParser::itrOutOfBoundCheck(uint8_t incVar)
201{
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530202 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}
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500208
209std::string KeywordVpdParser::getInterfaceName() const
210{
211 return kwdVpdInf;
212}
213
PriyangaRamasamyabb87ed2019-11-19 17:25:35 +0530214} // namespace parser
215} // namespace keyword
216} // namespace vpd