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