blob: 9447ca93ad137f01e87f470b59c99d98524d8bc4 [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"
SunnySrivastava19849d4f1122020-08-26 02:41:46 -05006#include "vpd_exceptions.hpp"
Patrick Venturec83c4dc2018-11-01 16:29:18 -07007
8#include <algorithm>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -06009#include <exception>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070010#include <iomanip>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060011#include <iostream>
12#include <iterator>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070013#include <sstream>
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -060014#include <tuple>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070015#include <unordered_map>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060016
Alpana Kumaric0aeac32019-11-28 05:20:10 -060017#include "vpdecc/vpdecc.h"
18
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060019namespace openpower
20{
21namespace vpd
22{
23namespace parser
24{
SunnySrivastava198419be6d32020-03-03 07:21:45 -060025using namespace openpower::vpd::constants;
SunnySrivastava19849d4f1122020-08-26 02:41:46 -050026using namespace openpower::vpd::exceptions;
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060027
Patrick Venturec83c4dc2018-11-01 16:29:18 -070028static const std::unordered_map<std::string, Record> supportedRecords = {
29 {"VINI", Record::VINI}, {"OPFR", Record::OPFR}, {"OSYS", Record::OSYS}};
Deepak Kodihallia1143462016-11-24 06:28:45 -060030
Patrick Venturec83c4dc2018-11-01 16:29:18 -070031static const std::unordered_map<std::string, internal::KeywordInfo>
32 supportedKeywords = {
33 {"DR", std::make_tuple(record::Keyword::DR, keyword::Encoding::ASCII)},
34 {"PN", std::make_tuple(record::Keyword::PN, keyword::Encoding::ASCII)},
35 {"SN", std::make_tuple(record::Keyword::SN, keyword::Encoding::ASCII)},
36 {"CC", std::make_tuple(record::Keyword::CC, keyword::Encoding::ASCII)},
37 {"HW", std::make_tuple(record::Keyword::HW, keyword::Encoding::RAW)},
38 {"B1", std::make_tuple(record::Keyword::B1, keyword::Encoding::B1)},
39 {"VN", std::make_tuple(record::Keyword::VN, keyword::Encoding::ASCII)},
George Liuee79ca82019-07-12 11:05:33 +080040 {"MB", std::make_tuple(record::Keyword::MB, keyword::Encoding::MB)},
Patrick Venturec83c4dc2018-11-01 16:29:18 -070041 {"MM", std::make_tuple(record::Keyword::MM, keyword::Encoding::ASCII)},
42 {"UD", std::make_tuple(record::Keyword::UD, keyword::Encoding::UD)},
43 {"VP", std::make_tuple(record::Keyword::VP, keyword::Encoding::ASCII)},
44 {"VS", std::make_tuple(record::Keyword::VS, keyword::Encoding::ASCII)},
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -060045};
46
Alpana Kumaric0aeac32019-11-28 05:20:10 -060047namespace
48{
49constexpr auto toHex(size_t c)
50{
51 constexpr auto map = "0123456789abcdef";
52 return map[c];
53}
54} // namespace
55
56/*readUInt16LE: Read 2 bytes LE data*/
57static LE2ByteData readUInt16LE(Binary::const_iterator iterator)
58{
59 LE2ByteData lowByte = *iterator;
60 LE2ByteData highByte = *(iterator + 1);
61 lowByte |= (highByte << 8);
62 return lowByte;
63}
64
65RecordOffset Impl::getVtocOffset() const
66{
67 auto vpdPtr = vpd.cbegin();
68 std::advance(vpdPtr, offsets::VTOC_PTR);
69 // Get VTOC Offset
70 auto vtocOffset = readUInt16LE(vpdPtr);
71
72 return vtocOffset;
73}
74
75#ifdef IPZ_PARSER
Alpana Kumaric0aeac32019-11-28 05:20:10 -060076int Impl::vhdrEccCheck() const
77{
78 int rc = eccStatus::SUCCESS;
79 auto vpdPtr = vpd.cbegin();
80
81 auto l_status =
82 vpdecc_check_data(const_cast<uint8_t*>(&vpdPtr[offsets::VHDR_RECORD]),
83 lengths::VHDR_RECORD_LENGTH,
84 const_cast<uint8_t*>(&vpdPtr[offsets::VHDR_ECC]),
85 lengths::VHDR_ECC_LENGTH);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -050086
Alpana Kumaric0aeac32019-11-28 05:20:10 -060087 if (l_status != VPD_ECC_OK)
88 {
89 rc = eccStatus::FAILED;
90 }
91
92 return rc;
93}
94
95int Impl::vtocEccCheck() const
96{
97 int rc = eccStatus::SUCCESS;
98 // Use another pointer to get ECC information from VHDR,
99 // actual pointer is pointing to VTOC data
100
101 auto vpdPtr = vpd.cbegin();
102
103 // Get VTOC Offset
104 auto vtocOffset = getVtocOffset();
105
106 // Get the VTOC Length
107 std::advance(vpdPtr, offsets::VTOC_PTR + sizeof(RecordOffset));
108 auto vtocLength = readUInt16LE(vpdPtr);
109
110 // Get the ECC Offset
111 std::advance(vpdPtr, sizeof(RecordLength));
112 auto vtocECCOffset = readUInt16LE(vpdPtr);
113
114 // Get the ECC length
115 std::advance(vpdPtr, sizeof(ECCOffset));
116 auto vtocECCLength = readUInt16LE(vpdPtr);
117
118 // Reset pointer to start of the vpd,
119 // so that Offset will point to correct address
120 vpdPtr = vpd.cbegin();
121 auto l_status = vpdecc_check_data(
122 const_cast<uint8_t*>(&vpdPtr[vtocOffset]), vtocLength,
123 const_cast<uint8_t*>(&vpdPtr[vtocECCOffset]), vtocECCLength);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500124
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600125 if (l_status != VPD_ECC_OK)
126 {
127 rc = eccStatus::FAILED;
128 }
129
130 return rc;
131}
132
133int Impl::recordEccCheck(Binary::const_iterator iterator) const
134{
135 int rc = eccStatus::SUCCESS;
136
137 auto recordOffset = readUInt16LE(iterator);
138
139 std::advance(iterator, sizeof(RecordOffset));
140 auto recordLength = readUInt16LE(iterator);
141
142 std::advance(iterator, sizeof(RecordLength));
143 auto eccOffset = readUInt16LE(iterator);
144
145 std::advance(iterator, sizeof(ECCOffset));
146 auto eccLength = readUInt16LE(iterator);
147
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500148 if (eccLength == 0 || eccOffset == 0)
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600149 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500150 throw(VpdEccException("Could not find ECC's offset or Length"));
151 }
152
153 if (recordOffset == 0 || recordLength == 0)
154 {
155 throw(VpdDataException(
156 "Could not find VPD record offset or VPD record length"));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600157 }
158
159 auto vpdPtr = vpd.cbegin();
160
161 auto l_status = vpdecc_check_data(
162 const_cast<uint8_t*>(&vpdPtr[recordOffset]), recordLength,
163 const_cast<uint8_t*>(&vpdPtr[eccOffset]), eccLength);
164 if (l_status != VPD_ECC_OK)
165 {
166 rc = eccStatus::FAILED;
167 }
168
169 return rc;
170}
171#endif
172
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600173void Impl::checkHeader() const
174{
175 if (vpd.empty() || (lengths::RECORD_MIN > vpd.size()))
176 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500177 throw(VpdDataException("Malformed VPD"));
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600178 }
179 else
180 {
181 auto iterator = vpd.cbegin();
182 std::advance(iterator, offsets::VHDR);
183 auto stop = std::next(iterator, lengths::RECORD_NAME);
184 std::string record(iterator, stop);
185 if ("VHDR" != record)
186 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500187 throw(VpdDataException("VHDR record not found"));
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600188 }
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600189
190#ifdef IPZ_PARSER
191 // Check ECC
192 int rc = eccStatus::FAILED;
193 rc = vhdrEccCheck();
194 if (rc != eccStatus::SUCCESS)
195 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500196 throw(VpdEccException("ERROR: VHDR ECC check Failed"));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600197 }
198#endif
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600199 }
200}
201
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600202std::size_t Impl::readTOC(Binary::const_iterator& iterator) const
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600203{
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600204 // The offset to VTOC could be 1 or 2 bytes long
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600205 RecordOffset vtocOffset = getVtocOffset();
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600206
207 // Got the offset to VTOC, skip past record header and keyword header
208 // to get to the record name.
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700209 std::advance(iterator, vtocOffset + sizeof(RecordId) + sizeof(RecordSize) +
210 // Skip past the RT keyword, which contains
211 // the record name.
212 lengths::KW_NAME + sizeof(KwSize));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600213
214 auto stop = std::next(iterator, lengths::RECORD_NAME);
215 std::string record(iterator, stop);
216 if ("VTOC" != record)
217 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500218 throw(VpdDataException("VTOC record not found"));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600219 }
220
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600221#ifdef IPZ_PARSER
222 // Check ECC
223 int rc = eccStatus::FAILED;
224 rc = vtocEccCheck();
225 if (rc != eccStatus::SUCCESS)
226 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500227 throw(VpdEccException("ERROR: VTOC ECC check Failed"));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600228 }
229#endif
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600230 // VTOC record name is good, now read through the TOC, stored in the PT
231 // PT keyword; vpdBuffer is now pointing at the first character of the
232 // name 'VTOC', jump to PT data.
233 // Skip past record name and KW name, 'PT'
234 std::advance(iterator, lengths::RECORD_NAME + lengths::KW_NAME);
235 // Note size of PT
236 std::size_t ptLen = *iterator;
237 // Skip past PT size
238 std::advance(iterator, sizeof(KwSize));
239
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600240 // length of PT keyword
241 return ptLen;
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600242}
243
244internal::OffsetList Impl::readPT(Binary::const_iterator iterator,
245 std::size_t ptLength) const
246{
247 internal::OffsetList offsets{};
248
249 auto end = iterator;
250 std::advance(end, ptLength);
251
252 // Look at each entry in the PT keyword. In the entry,
253 // we care only about the record offset information.
254 while (iterator < end)
255 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500256#ifdef IPZ_PARSER
257 auto iteratorToRecName = iterator;
258#endif
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600259 // Skip record name and record type
260 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
261
262 // Get record offset
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600263 auto offset = readUInt16LE(iterator);
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600264 offsets.push_back(offset);
265
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600266#ifdef IPZ_PARSER
267 // Verify the ECC for this Record
268 int rc = recordEccCheck(iterator);
269
270 if (rc != eccStatus::SUCCESS)
271 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500272 std::string recordName(iteratorToRecName,
273 iteratorToRecName + lengths::RECORD_NAME);
274
275 std::string errorMsg =
276 std::string("ERROR: ECC check did not pass for the Record:") +
277 recordName;
278 throw(VpdEccException(errorMsg));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600279 }
280#endif
281
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600282 // Jump record size, record length, ECC offset and ECC length
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600283 std::advance(iterator, sizeof(RecordOffset) + sizeof(RecordLength) +
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700284 sizeof(ECCOffset) + sizeof(ECCLength));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600285 }
286
287 return offsets;
288}
289
Deepak Kodihallia1143462016-11-24 06:28:45 -0600290void Impl::processRecord(std::size_t recordOffset)
291{
292 // Jump to record name
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700293 auto nameOffset = recordOffset + sizeof(RecordId) + sizeof(RecordSize) +
Deepak Kodihallia1143462016-11-24 06:28:45 -0600294 // Skip past the RT keyword, which contains
295 // the record name.
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700296 lengths::KW_NAME + sizeof(KwSize);
Deepak Kodihallia1143462016-11-24 06:28:45 -0600297 // Get record name
298 auto iterator = vpd.cbegin();
299 std::advance(iterator, nameOffset);
300
301 std::string name(iterator, iterator + lengths::RECORD_NAME);
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600302
Alpana Kumari26a74af2019-09-10 23:53:58 -0500303#ifndef IPZ_PARSER
Deepak Kodihallia1143462016-11-24 06:28:45 -0600304 if (supportedRecords.end() != supportedRecords.find(name))
305 {
Alpana Kumari26a74af2019-09-10 23:53:58 -0500306#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600307 // If it's a record we're interested in, proceed to find
308 // contained keywords and their values.
309 std::advance(iterator, lengths::RECORD_NAME);
Alpana Kumari26a74af2019-09-10 23:53:58 -0500310
311#ifdef IPZ_PARSER
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600312
Alpana Kumari26a74af2019-09-10 23:53:58 -0500313 // Reverse back to RT Kw, in ipz vpd, to Read RT KW & value
314 std::advance(iterator, -(lengths::KW_NAME + sizeof(KwSize) +
315 lengths::RECORD_NAME));
316#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600317 auto kwMap = readKeywords(iterator);
318 // Add entry for this record (and contained keyword:value pairs)
319 // to the parsed vpd output.
320 out.emplace(std::move(name), std::move(kwMap));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600321
Alpana Kumari26a74af2019-09-10 23:53:58 -0500322#ifndef IPZ_PARSER
Deepak Kodihallia1143462016-11-24 06:28:45 -0600323 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500324#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600325}
326
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600327std::string Impl::readKwData(const internal::KeywordInfo& keyword,
328 std::size_t dataLength,
329 Binary::const_iterator iterator)
330{
Santosh Puranikbd011b22020-01-23 04:05:25 -0600331 using namespace openpower::vpd;
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600332 switch (std::get<keyword::Encoding>(keyword))
333 {
334 case keyword::Encoding::ASCII:
335 {
336 auto stop = std::next(iterator, dataLength);
337 return std::string(iterator, stop);
338 }
339
340 case keyword::Encoding::RAW:
341 {
342 auto stop = std::next(iterator, dataLength);
343 std::string data(iterator, stop);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700344 std::string result{};
345 std::for_each(data.cbegin(), data.cend(), [&result](size_t c) {
346 result += toHex(c >> 4);
347 result += toHex(c & 0x0F);
348 });
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600349 return result;
350 }
351
George Liuee79ca82019-07-12 11:05:33 +0800352 case keyword::Encoding::MB:
353 {
354 // MB is BuildDate, represent as
355 // 1997-01-01-08:30:00
356 // <year>-<month>-<day>-<hour>:<min>:<sec>
357 auto stop = std::next(iterator, MB_LEN_BYTES);
358 std::string data(iterator, stop);
359 std::string result;
360 result.reserve(MB_LEN_BYTES);
361 auto strItr = data.cbegin();
362 std::advance(strItr, 1);
363 std::for_each(strItr, data.cend(), [&result](size_t c) {
364 result += toHex(c >> 4);
365 result += toHex(c & 0x0F);
366 });
367
368 result.insert(MB_YEAR_END, 1, '-');
369 result.insert(MB_MONTH_END, 1, '-');
370 result.insert(MB_DAY_END, 1, '-');
371 result.insert(MB_HOUR_END, 1, ':');
372 result.insert(MB_MIN_END, 1, ':');
373
374 return result;
375 }
376
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600377 case keyword::Encoding::B1:
378 {
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700379 // B1 is MAC address, represent as AA:BB:CC:DD:EE:FF
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600380 auto stop = std::next(iterator, MAC_ADDRESS_LEN_BYTES);
381 std::string data(iterator, stop);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700382 std::string result{};
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600383 auto strItr = data.cbegin();
384 size_t firstDigit = *strItr;
385 result += toHex(firstDigit >> 4);
386 result += toHex(firstDigit & 0x0F);
387 std::advance(strItr, 1);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700388 std::for_each(strItr, data.cend(), [&result](size_t c) {
389 result += ":";
390 result += toHex(c >> 4);
391 result += toHex(c & 0x0F);
392 });
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600393 return result;
394 }
395
Dinesh Chinaric576b482017-07-17 16:34:10 -0500396 case keyword::Encoding::UD:
397 {
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700398 // UD, the UUID info, represented as
399 // 123e4567-e89b-12d3-a456-426655440000
Dinesh Chinaric576b482017-07-17 16:34:10 -0500400 //<time_low>-<time_mid>-<time hi and version>
401 //-<clock_seq_hi_and_res clock_seq_low>-<48 bits node id>
402 auto stop = std::next(iterator, UUID_LEN_BYTES);
403 std::string data(iterator, stop);
404 std::string result{};
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700405 std::for_each(data.cbegin(), data.cend(), [&result](size_t c) {
406 result += toHex(c >> 4);
407 result += toHex(c & 0x0F);
408 });
Dinesh Chinaric576b482017-07-17 16:34:10 -0500409 result.insert(UUID_TIME_LOW_END, 1, '-');
410 result.insert(UUID_TIME_MID_END, 1, '-');
411 result.insert(UUID_TIME_HIGH_END, 1, '-');
412 result.insert(UUID_CLK_SEQ_END, 1, '-');
413
414 return result;
415 }
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600416 default:
417 break;
418 }
419
420 return {};
421}
422
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600423internal::KeywordMap Impl::readKeywords(Binary::const_iterator iterator)
424{
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700425 internal::KeywordMap map{};
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600426 while (true)
427 {
428 // Note keyword name
429 std::string kw(iterator, iterator + lengths::KW_NAME);
430 if (LAST_KW == kw)
431 {
432 // We're done
433 break;
434 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500435 // Check if the Keyword is '#kw'
436 char kwNameStart = *iterator;
437
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600438 // Jump past keyword name
439 std::advance(iterator, lengths::KW_NAME);
Alpana Kumari26a74af2019-09-10 23:53:58 -0500440
441 std::size_t length;
442 std::size_t lengthHighByte;
443 if (POUND_KW == kwNameStart)
444 {
445 // Note keyword data length
446 length = *iterator;
447 lengthHighByte = *(iterator + 1);
448 length |= (lengthHighByte << 8);
449
450 // Jump past 2Byte keyword length
451 std::advance(iterator, sizeof(PoundKwSize));
452 }
453 else
454 {
455 // Note keyword data length
456 length = *iterator;
457
458 // Jump past keyword length
459 std::advance(iterator, sizeof(KwSize));
460 }
461
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600462 // Pointing to keyword data now
Alpana Kumari26a74af2019-09-10 23:53:58 -0500463#ifndef IPZ_PARSER
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600464 if (supportedKeywords.end() != supportedKeywords.find(kw))
465 {
466 // Keyword is of interest to us
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700467 std::string data = readKwData((supportedKeywords.find(kw))->second,
468 length, iterator);
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600469 map.emplace(std::move(kw), std::move(data));
470 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500471
472#else
473 // support all the Keywords
474 auto stop = std::next(iterator, length);
475 std::string kwdata(iterator, stop);
476 map.emplace(std::move(kw), std::move(kwdata));
477
478#endif
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600479 // Jump past keyword data length
480 std::advance(iterator, length);
481 }
482
483 return map;
484}
485
Deepak Kodihalli174caf62016-11-25 05:41:19 -0600486Store Impl::run()
487{
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500488 // Check if the VHDR record is present
489 checkHeader();
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500490
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500491 auto iterator = vpd.cbegin();
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500492
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500493 // Read the table of contents record
494 std::size_t ptLen = readTOC(iterator);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500495
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500496 // Read the table of contents record, to get offsets
497 // to other records.
498 auto offsets = readPT(iterator, ptLen);
499 for (const auto& offset : offsets)
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500500 {
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500501 processRecord(offset);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500502 }
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500503 // Return a Store object, which has interfaces to
504 // access parsed VPD by record:keyword
505 return Store(std::move(out));
Deepak Kodihalli174caf62016-11-25 05:41:19 -0600506}
507
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600508void Impl::checkVPDHeader()
509{
510 // Check if the VHDR record is present and is valid
511 checkHeader();
512}
513
Priyanga Ramasamy28079c82021-10-07 16:30:51 -0500514std::string Impl::readKwFromHw(const std::string& record,
515 const std::string& keyword)
516{
517 // Check if the VHDR record is present
518 checkHeader();
519
520 auto iterator = vpd.cbegin();
521
522 // Read the table of contents record
523 std::size_t ptLen = readTOC(iterator);
524
525 // Read the table of contents record, to get offsets
526 // to other records.
527 auto offsets = readPT(iterator, ptLen);
528 for (const auto& offset : offsets)
529 {
530 // Jump to record name
531 auto nameOffset = offset + sizeof(RecordId) + sizeof(RecordSize) +
532 // Skip past the RT keyword, which contains
533 // the record name.
534 lengths::KW_NAME + sizeof(KwSize);
535 // Get record name
536 auto iterator = vpd.cbegin();
537 std::advance(iterator, nameOffset);
538
539 std::string name(iterator, iterator + lengths::RECORD_NAME);
540 if (name != record)
541 {
542 continue;
543 }
544 else
545 {
546 processRecord(offset);
547 const auto& itr = out.find(record);
548 if (itr != out.end())
549 {
550 const auto& kwValItr = (itr->second).find(keyword);
551 if (kwValItr != (itr->second).end())
552 {
553 return kwValItr->second;
554 }
555 else
556 {
557 return "";
558 }
559 }
560 }
561 }
562 return "";
563}
564
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600565} // namespace parser
566} // namespace vpd
Priyanga Ramasamy28079c82021-10-07 16:30:51 -0500567} // namespace openpower