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