blob: 900e0e871432aa5797230f188df97b2692fbb589 [file] [log] [blame]
Patrick Venturec83c4dc2018-11-01 16:29:18 -07001#include "impl.hpp"
2
SunnySrivastava198419be6d32020-03-03 07:21:45 -06003#include "const.hpp"
Patrick Venturec83c4dc2018-11-01 16:29:18 -07004#include "defines.hpp"
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05005#include "ibm_vpd_utils.hpp"
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -05006#include "types.hpp"
SunnySrivastava19849d4f1122020-08-26 02:41:46 -05007#include "vpd_exceptions.hpp"
Patrick Venturec83c4dc2018-11-01 16:29:18 -07008
9#include <algorithm>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060010#include <exception>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070011#include <iomanip>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060012#include <iostream>
13#include <iterator>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070014#include <sstream>
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -060015#include <tuple>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070016#include <unordered_map>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060017
Alpana Kumaric0aeac32019-11-28 05:20:10 -060018#include "vpdecc/vpdecc.h"
19
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060020namespace openpower
21{
22namespace vpd
23{
24namespace parser
25{
SunnySrivastava198419be6d32020-03-03 07:21:45 -060026using namespace openpower::vpd::constants;
SunnySrivastava19849d4f1122020-08-26 02:41:46 -050027using namespace openpower::vpd::exceptions;
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060028
Patrick Venturec83c4dc2018-11-01 16:29:18 -070029static const std::unordered_map<std::string, Record> supportedRecords = {
30 {"VINI", Record::VINI}, {"OPFR", Record::OPFR}, {"OSYS", Record::OSYS}};
Deepak Kodihallia1143462016-11-24 06:28:45 -060031
Patrick Venturec83c4dc2018-11-01 16:29:18 -070032static const std::unordered_map<std::string, internal::KeywordInfo>
33 supportedKeywords = {
34 {"DR", std::make_tuple(record::Keyword::DR, keyword::Encoding::ASCII)},
35 {"PN", std::make_tuple(record::Keyword::PN, keyword::Encoding::ASCII)},
36 {"SN", std::make_tuple(record::Keyword::SN, keyword::Encoding::ASCII)},
37 {"CC", std::make_tuple(record::Keyword::CC, keyword::Encoding::ASCII)},
38 {"HW", std::make_tuple(record::Keyword::HW, keyword::Encoding::RAW)},
39 {"B1", std::make_tuple(record::Keyword::B1, keyword::Encoding::B1)},
40 {"VN", std::make_tuple(record::Keyword::VN, keyword::Encoding::ASCII)},
George Liuee79ca82019-07-12 11:05:33 +080041 {"MB", std::make_tuple(record::Keyword::MB, keyword::Encoding::MB)},
Patrick Venturec83c4dc2018-11-01 16:29:18 -070042 {"MM", std::make_tuple(record::Keyword::MM, keyword::Encoding::ASCII)},
43 {"UD", std::make_tuple(record::Keyword::UD, keyword::Encoding::UD)},
44 {"VP", std::make_tuple(record::Keyword::VP, keyword::Encoding::ASCII)},
45 {"VS", std::make_tuple(record::Keyword::VS, keyword::Encoding::ASCII)},
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -060046};
47
Alpana Kumaric0aeac32019-11-28 05:20:10 -060048namespace
49{
50constexpr auto toHex(size_t c)
51{
52 constexpr auto map = "0123456789abcdef";
53 return map[c];
54}
55} // namespace
56
57/*readUInt16LE: Read 2 bytes LE data*/
58static LE2ByteData readUInt16LE(Binary::const_iterator iterator)
59{
60 LE2ByteData lowByte = *iterator;
61 LE2ByteData highByte = *(iterator + 1);
62 lowByte |= (highByte << 8);
63 return lowByte;
64}
65
66RecordOffset Impl::getVtocOffset() const
67{
68 auto vpdPtr = vpd.cbegin();
69 std::advance(vpdPtr, offsets::VTOC_PTR);
70 // Get VTOC Offset
71 auto vtocOffset = readUInt16LE(vpdPtr);
72
73 return vtocOffset;
74}
75
76#ifdef IPZ_PARSER
Alpana Kumaric0aeac32019-11-28 05:20:10 -060077int Impl::vhdrEccCheck() const
78{
79 int rc = eccStatus::SUCCESS;
80 auto vpdPtr = vpd.cbegin();
81
82 auto l_status =
83 vpdecc_check_data(const_cast<uint8_t*>(&vpdPtr[offsets::VHDR_RECORD]),
84 lengths::VHDR_RECORD_LENGTH,
85 const_cast<uint8_t*>(&vpdPtr[offsets::VHDR_ECC]),
86 lengths::VHDR_ECC_LENGTH);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -050087
Alpana Kumaric0aeac32019-11-28 05:20:10 -060088 if (l_status != VPD_ECC_OK)
89 {
90 rc = eccStatus::FAILED;
91 }
92
93 return rc;
94}
95
96int Impl::vtocEccCheck() const
97{
98 int rc = eccStatus::SUCCESS;
99 // Use another pointer to get ECC information from VHDR,
100 // actual pointer is pointing to VTOC data
101
102 auto vpdPtr = vpd.cbegin();
103
104 // Get VTOC Offset
105 auto vtocOffset = getVtocOffset();
106
107 // Get the VTOC Length
108 std::advance(vpdPtr, offsets::VTOC_PTR + sizeof(RecordOffset));
109 auto vtocLength = readUInt16LE(vpdPtr);
110
111 // Get the ECC Offset
112 std::advance(vpdPtr, sizeof(RecordLength));
113 auto vtocECCOffset = readUInt16LE(vpdPtr);
114
115 // Get the ECC length
116 std::advance(vpdPtr, sizeof(ECCOffset));
117 auto vtocECCLength = readUInt16LE(vpdPtr);
118
119 // Reset pointer to start of the vpd,
120 // so that Offset will point to correct address
121 vpdPtr = vpd.cbegin();
122 auto l_status = vpdecc_check_data(
123 const_cast<uint8_t*>(&vpdPtr[vtocOffset]), vtocLength,
124 const_cast<uint8_t*>(&vpdPtr[vtocECCOffset]), vtocECCLength);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500125
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600126 if (l_status != VPD_ECC_OK)
127 {
128 rc = eccStatus::FAILED;
129 }
130
131 return rc;
132}
133
134int Impl::recordEccCheck(Binary::const_iterator iterator) const
135{
136 int rc = eccStatus::SUCCESS;
137
138 auto recordOffset = readUInt16LE(iterator);
139
140 std::advance(iterator, sizeof(RecordOffset));
141 auto recordLength = readUInt16LE(iterator);
142
143 std::advance(iterator, sizeof(RecordLength));
144 auto eccOffset = readUInt16LE(iterator);
145
146 std::advance(iterator, sizeof(ECCOffset));
147 auto eccLength = readUInt16LE(iterator);
148
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500149 if (eccLength == 0 || eccOffset == 0)
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600150 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500151 throw(VpdEccException("Could not find ECC's offset or Length."));
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500152 }
153
154 if (recordOffset == 0 || recordLength == 0)
155 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500156 throw(VpdDataException("Could not find VPD record offset or VPD record "
157 "length."));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600158 }
159
160 auto vpdPtr = vpd.cbegin();
161
162 auto l_status = vpdecc_check_data(
163 const_cast<uint8_t*>(&vpdPtr[recordOffset]), recordLength,
164 const_cast<uint8_t*>(&vpdPtr[eccOffset]), eccLength);
165 if (l_status != VPD_ECC_OK)
166 {
167 rc = eccStatus::FAILED;
168 }
169
170 return rc;
171}
172#endif
173
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600174void Impl::checkHeader() const
175{
176 if (vpd.empty() || (lengths::RECORD_MIN > vpd.size()))
177 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500178 throw(VpdDataException("Malformed VPD"));
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600179 }
180 else
181 {
182 auto iterator = vpd.cbegin();
183 std::advance(iterator, offsets::VHDR);
184 auto stop = std::next(iterator, lengths::RECORD_NAME);
185 std::string record(iterator, stop);
186 if ("VHDR" != record)
187 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500188 throw(VpdDataException("VHDR record not found"));
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600189 }
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600190
191#ifdef IPZ_PARSER
192 // Check ECC
193 int rc = eccStatus::FAILED;
194 rc = vhdrEccCheck();
195 if (rc != eccStatus::SUCCESS)
196 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500197 throw(VpdEccException("ERROR: VHDR ECC check Failed"));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600198 }
199#endif
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600200 }
201}
202
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600203std::size_t Impl::readTOC(Binary::const_iterator& iterator) const
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600204{
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600205 // The offset to VTOC could be 1 or 2 bytes long
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600206 RecordOffset vtocOffset = getVtocOffset();
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600207
208 // Got the offset to VTOC, skip past record header and keyword header
209 // to get to the record name.
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700210 std::advance(iterator, vtocOffset + sizeof(RecordId) + sizeof(RecordSize) +
211 // Skip past the RT keyword, which contains
212 // the record name.
213 lengths::KW_NAME + sizeof(KwSize));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600214
215 auto stop = std::next(iterator, lengths::RECORD_NAME);
216 std::string record(iterator, stop);
217 if ("VTOC" != record)
218 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500219 throw(VpdDataException("VTOC record not found"));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600220 }
221
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600222#ifdef IPZ_PARSER
223 // Check ECC
224 int rc = eccStatus::FAILED;
225 rc = vtocEccCheck();
226 if (rc != eccStatus::SUCCESS)
227 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500228 throw(VpdEccException("ERROR: VTOC ECC check Failed"));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600229 }
230#endif
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600231 // VTOC record name is good, now read through the TOC, stored in the PT
232 // PT keyword; vpdBuffer is now pointing at the first character of the
233 // name 'VTOC', jump to PT data.
234 // Skip past record name and KW name, 'PT'
235 std::advance(iterator, lengths::RECORD_NAME + lengths::KW_NAME);
236 // Note size of PT
237 std::size_t ptLen = *iterator;
238 // Skip past PT size
239 std::advance(iterator, sizeof(KwSize));
240
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600241 // length of PT keyword
242 return ptLen;
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600243}
244
245internal::OffsetList Impl::readPT(Binary::const_iterator iterator,
246 std::size_t ptLength) const
247{
248 internal::OffsetList offsets{};
249
250 auto end = iterator;
251 std::advance(end, ptLength);
252
253 // Look at each entry in the PT keyword. In the entry,
254 // we care only about the record offset information.
255 while (iterator < end)
256 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500257#ifdef IPZ_PARSER
258 auto iteratorToRecName = iterator;
259#endif
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600260 // Skip record name and record type
261 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
262
263 // Get record offset
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600264 auto offset = readUInt16LE(iterator);
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600265 offsets.push_back(offset);
266
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600267#ifdef IPZ_PARSER
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500268 std::string recordName(iteratorToRecName,
269 iteratorToRecName + lengths::RECORD_NAME);
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600270
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500271 try
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600272 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500273 // Verify the ECC for this Record
274 int rc = recordEccCheck(iterator);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500275
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500276 if (rc != eccStatus::SUCCESS)
277 {
278 std::string errorMsg =
279 std::string("ERROR: ECC check did not pass.");
280 throw(VpdEccException(errorMsg));
281 }
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600282 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500283 catch (const VpdEccException& ex)
284 {
285 std::string errMsg =
286 std::string{ex.what()} + " Record: " + recordName;
287
288 inventory::PelAdditionalData additionalData{};
289 additionalData.emplace("DESCRIPTION", errMsg);
290 additionalData.emplace("CALLOUT_INVENTORY_PATH", inventoryPath);
291 createPEL(additionalData, PelSeverity::WARNING,
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500292 errIntfForEccCheckFail, nullptr);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500293 }
294 catch (const VpdDataException& ex)
295 {
296 std::string errMsg =
297 std::string{ex.what()} + " Record: " + recordName;
298
299 inventory::PelAdditionalData additionalData{};
300 additionalData.emplace("DESCRIPTION", errMsg);
301 additionalData.emplace("CALLOUT_INVENTORY_PATH", inventoryPath);
302 createPEL(additionalData, PelSeverity::WARNING,
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500303 errIntfForInvalidVPD, nullptr);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500304 }
305
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600306#endif
307
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600308 // Jump record size, record length, ECC offset and ECC length
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600309 std::advance(iterator, sizeof(RecordOffset) + sizeof(RecordLength) +
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700310 sizeof(ECCOffset) + sizeof(ECCLength));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600311 }
312
313 return offsets;
314}
315
Deepak Kodihallia1143462016-11-24 06:28:45 -0600316void Impl::processRecord(std::size_t recordOffset)
317{
318 // Jump to record name
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700319 auto nameOffset = recordOffset + sizeof(RecordId) + sizeof(RecordSize) +
Deepak Kodihallia1143462016-11-24 06:28:45 -0600320 // Skip past the RT keyword, which contains
321 // the record name.
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700322 lengths::KW_NAME + sizeof(KwSize);
Deepak Kodihallia1143462016-11-24 06:28:45 -0600323 // Get record name
324 auto iterator = vpd.cbegin();
325 std::advance(iterator, nameOffset);
326
327 std::string name(iterator, iterator + lengths::RECORD_NAME);
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600328
Alpana Kumari26a74af2019-09-10 23:53:58 -0500329#ifndef IPZ_PARSER
Deepak Kodihallia1143462016-11-24 06:28:45 -0600330 if (supportedRecords.end() != supportedRecords.find(name))
331 {
Alpana Kumari26a74af2019-09-10 23:53:58 -0500332#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600333 // If it's a record we're interested in, proceed to find
334 // contained keywords and their values.
335 std::advance(iterator, lengths::RECORD_NAME);
Alpana Kumari26a74af2019-09-10 23:53:58 -0500336
337#ifdef IPZ_PARSER
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600338
Alpana Kumari26a74af2019-09-10 23:53:58 -0500339 // Reverse back to RT Kw, in ipz vpd, to Read RT KW & value
340 std::advance(iterator, -(lengths::KW_NAME + sizeof(KwSize) +
341 lengths::RECORD_NAME));
342#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600343 auto kwMap = readKeywords(iterator);
344 // Add entry for this record (and contained keyword:value pairs)
345 // to the parsed vpd output.
346 out.emplace(std::move(name), std::move(kwMap));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600347
Alpana Kumari26a74af2019-09-10 23:53:58 -0500348#ifndef IPZ_PARSER
Deepak Kodihallia1143462016-11-24 06:28:45 -0600349 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500350#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600351}
352
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600353std::string Impl::readKwData(const internal::KeywordInfo& keyword,
354 std::size_t dataLength,
355 Binary::const_iterator iterator)
356{
Santosh Puranikbd011b22020-01-23 04:05:25 -0600357 using namespace openpower::vpd;
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600358 switch (std::get<keyword::Encoding>(keyword))
359 {
360 case keyword::Encoding::ASCII:
361 {
362 auto stop = std::next(iterator, dataLength);
363 return std::string(iterator, stop);
364 }
365
366 case keyword::Encoding::RAW:
367 {
368 auto stop = std::next(iterator, dataLength);
369 std::string data(iterator, stop);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700370 std::string result{};
371 std::for_each(data.cbegin(), data.cend(), [&result](size_t c) {
372 result += toHex(c >> 4);
373 result += toHex(c & 0x0F);
374 });
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600375 return result;
376 }
377
George Liuee79ca82019-07-12 11:05:33 +0800378 case keyword::Encoding::MB:
379 {
380 // MB is BuildDate, represent as
381 // 1997-01-01-08:30:00
382 // <year>-<month>-<day>-<hour>:<min>:<sec>
383 auto stop = std::next(iterator, MB_LEN_BYTES);
384 std::string data(iterator, stop);
385 std::string result;
386 result.reserve(MB_LEN_BYTES);
387 auto strItr = data.cbegin();
388 std::advance(strItr, 1);
389 std::for_each(strItr, data.cend(), [&result](size_t c) {
390 result += toHex(c >> 4);
391 result += toHex(c & 0x0F);
392 });
393
394 result.insert(MB_YEAR_END, 1, '-');
395 result.insert(MB_MONTH_END, 1, '-');
396 result.insert(MB_DAY_END, 1, '-');
397 result.insert(MB_HOUR_END, 1, ':');
398 result.insert(MB_MIN_END, 1, ':');
399
400 return result;
401 }
402
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600403 case keyword::Encoding::B1:
404 {
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700405 // B1 is MAC address, represent as AA:BB:CC:DD:EE:FF
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600406 auto stop = std::next(iterator, MAC_ADDRESS_LEN_BYTES);
407 std::string data(iterator, stop);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700408 std::string result{};
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600409 auto strItr = data.cbegin();
410 size_t firstDigit = *strItr;
411 result += toHex(firstDigit >> 4);
412 result += toHex(firstDigit & 0x0F);
413 std::advance(strItr, 1);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700414 std::for_each(strItr, data.cend(), [&result](size_t c) {
415 result += ":";
416 result += toHex(c >> 4);
417 result += toHex(c & 0x0F);
418 });
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600419 return result;
420 }
421
Dinesh Chinaric576b482017-07-17 16:34:10 -0500422 case keyword::Encoding::UD:
423 {
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700424 // UD, the UUID info, represented as
425 // 123e4567-e89b-12d3-a456-426655440000
Dinesh Chinaric576b482017-07-17 16:34:10 -0500426 //<time_low>-<time_mid>-<time hi and version>
427 //-<clock_seq_hi_and_res clock_seq_low>-<48 bits node id>
428 auto stop = std::next(iterator, UUID_LEN_BYTES);
429 std::string data(iterator, stop);
430 std::string result{};
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700431 std::for_each(data.cbegin(), data.cend(), [&result](size_t c) {
432 result += toHex(c >> 4);
433 result += toHex(c & 0x0F);
434 });
Dinesh Chinaric576b482017-07-17 16:34:10 -0500435 result.insert(UUID_TIME_LOW_END, 1, '-');
436 result.insert(UUID_TIME_MID_END, 1, '-');
437 result.insert(UUID_TIME_HIGH_END, 1, '-');
438 result.insert(UUID_CLK_SEQ_END, 1, '-');
439
440 return result;
441 }
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600442 default:
443 break;
444 }
445
446 return {};
447}
448
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600449internal::KeywordMap Impl::readKeywords(Binary::const_iterator iterator)
450{
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700451 internal::KeywordMap map{};
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600452 while (true)
453 {
454 // Note keyword name
455 std::string kw(iterator, iterator + lengths::KW_NAME);
456 if (LAST_KW == kw)
457 {
458 // We're done
459 break;
460 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500461 // Check if the Keyword is '#kw'
462 char kwNameStart = *iterator;
463
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600464 // Jump past keyword name
465 std::advance(iterator, lengths::KW_NAME);
Alpana Kumari26a74af2019-09-10 23:53:58 -0500466
467 std::size_t length;
468 std::size_t lengthHighByte;
469 if (POUND_KW == kwNameStart)
470 {
471 // Note keyword data length
472 length = *iterator;
473 lengthHighByte = *(iterator + 1);
474 length |= (lengthHighByte << 8);
475
476 // Jump past 2Byte keyword length
477 std::advance(iterator, sizeof(PoundKwSize));
478 }
479 else
480 {
481 // Note keyword data length
482 length = *iterator;
483
484 // Jump past keyword length
485 std::advance(iterator, sizeof(KwSize));
486 }
487
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600488 // Pointing to keyword data now
Alpana Kumari26a74af2019-09-10 23:53:58 -0500489#ifndef IPZ_PARSER
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600490 if (supportedKeywords.end() != supportedKeywords.find(kw))
491 {
492 // Keyword is of interest to us
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700493 std::string data = readKwData((supportedKeywords.find(kw))->second,
494 length, iterator);
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600495 map.emplace(std::move(kw), std::move(data));
496 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500497
498#else
499 // support all the Keywords
500 auto stop = std::next(iterator, length);
501 std::string kwdata(iterator, stop);
502 map.emplace(std::move(kw), std::move(kwdata));
503
504#endif
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600505 // Jump past keyword data length
506 std::advance(iterator, length);
507 }
508
509 return map;
510}
511
Deepak Kodihalli174caf62016-11-25 05:41:19 -0600512Store Impl::run()
513{
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500514 // Check if the VHDR record is present
515 checkHeader();
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500516
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500517 auto iterator = vpd.cbegin();
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500518
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500519 // Read the table of contents record
520 std::size_t ptLen = readTOC(iterator);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500521
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500522 // Read the table of contents record, to get offsets
523 // to other records.
524 auto offsets = readPT(iterator, ptLen);
525 for (const auto& offset : offsets)
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500526 {
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500527 processRecord(offset);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500528 }
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500529 // Return a Store object, which has interfaces to
530 // access parsed VPD by record:keyword
531 return Store(std::move(out));
Deepak Kodihalli174caf62016-11-25 05:41:19 -0600532}
533
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600534void Impl::checkVPDHeader()
535{
536 // Check if the VHDR record is present and is valid
537 checkHeader();
538}
539
Priyanga Ramasamy28079c82021-10-07 16:30:51 -0500540std::string Impl::readKwFromHw(const std::string& record,
541 const std::string& keyword)
542{
543 // Check if the VHDR record is present
544 checkHeader();
545
546 auto iterator = vpd.cbegin();
547
548 // Read the table of contents record
549 std::size_t ptLen = readTOC(iterator);
550
551 // Read the table of contents record, to get offsets
552 // to other records.
553 auto offsets = readPT(iterator, ptLen);
554 for (const auto& offset : offsets)
555 {
556 // Jump to record name
557 auto nameOffset = offset + sizeof(RecordId) + sizeof(RecordSize) +
558 // Skip past the RT keyword, which contains
559 // the record name.
560 lengths::KW_NAME + sizeof(KwSize);
561 // Get record name
562 auto iterator = vpd.cbegin();
563 std::advance(iterator, nameOffset);
564
565 std::string name(iterator, iterator + lengths::RECORD_NAME);
566 if (name != record)
567 {
568 continue;
569 }
570 else
571 {
572 processRecord(offset);
573 const auto& itr = out.find(record);
574 if (itr != out.end())
575 {
576 const auto& kwValItr = (itr->second).find(keyword);
577 if (kwValItr != (itr->second).end())
578 {
579 return kwValItr->second;
580 }
581 else
582 {
583 return "";
584 }
585 }
586 }
587 }
588 return "";
589}
590
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600591} // namespace parser
592} // namespace vpd
Priyanga Ramasamy28079c82021-10-07 16:30:51 -0500593} // namespace openpower