blob: f4d1e4281be730b1b27339fb0e58dd446f392df8 [file] [log] [blame]
Patrick Venturec83c4dc2018-11-01 16:29:18 -07001#include "impl.hpp"
2
3#include "defines.hpp"
Santosh Puranikbd011b22020-01-23 04:05:25 -06004#include "utils.hpp"
Patrick Venturec83c4dc2018-11-01 16:29:18 -07005
6#include <algorithm>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -06007#include <exception>
Patrick Venturec83c4dc2018-11-01 16:29:18 -07008#include <iomanip>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -06009#include <iostream>
10#include <iterator>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070011#include <sstream>
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -060012#include <tuple>
Patrick Venturec83c4dc2018-11-01 16:29:18 -070013#include <unordered_map>
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060014
Alpana Kumaric0aeac32019-11-28 05:20:10 -060015#include "vpdecc/vpdecc.h"
16
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060017namespace openpower
18{
19namespace vpd
20{
21namespace parser
22{
23
Patrick Venturec83c4dc2018-11-01 16:29:18 -070024static const std::unordered_map<std::string, Record> supportedRecords = {
25 {"VINI", Record::VINI}, {"OPFR", Record::OPFR}, {"OSYS", Record::OSYS}};
Deepak Kodihallia1143462016-11-24 06:28:45 -060026
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -060027static constexpr auto MAC_ADDRESS_LEN_BYTES = 6;
Deepak Kodihalli683bf722016-11-24 06:50:43 -060028static constexpr auto LAST_KW = "PF";
Alpana Kumari26a74af2019-09-10 23:53:58 -050029static constexpr auto POUND_KW = '#';
Dinesh Chinaric576b482017-07-17 16:34:10 -050030static constexpr auto UUID_LEN_BYTES = 16;
31static constexpr auto UUID_TIME_LOW_END = 8;
32static constexpr auto UUID_TIME_MID_END = 13;
33static constexpr auto UUID_TIME_HIGH_END = 18;
34static constexpr auto UUID_CLK_SEQ_END = 23;
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -060035
George Liuee79ca82019-07-12 11:05:33 +080036static constexpr auto MB_RESULT_LEN = 19;
37static constexpr auto MB_LEN_BYTES = 8;
38static constexpr auto MB_YEAR_END = 4;
39static constexpr auto MB_MONTH_END = 7;
40static constexpr auto MB_DAY_END = 10;
41static constexpr auto MB_HOUR_END = 13;
42static constexpr auto MB_MIN_END = 16;
43
Patrick Venturec83c4dc2018-11-01 16:29:18 -070044static const std::unordered_map<std::string, internal::KeywordInfo>
45 supportedKeywords = {
46 {"DR", std::make_tuple(record::Keyword::DR, keyword::Encoding::ASCII)},
47 {"PN", std::make_tuple(record::Keyword::PN, keyword::Encoding::ASCII)},
48 {"SN", std::make_tuple(record::Keyword::SN, keyword::Encoding::ASCII)},
49 {"CC", std::make_tuple(record::Keyword::CC, keyword::Encoding::ASCII)},
50 {"HW", std::make_tuple(record::Keyword::HW, keyword::Encoding::RAW)},
51 {"B1", std::make_tuple(record::Keyword::B1, keyword::Encoding::B1)},
52 {"VN", std::make_tuple(record::Keyword::VN, keyword::Encoding::ASCII)},
George Liuee79ca82019-07-12 11:05:33 +080053 {"MB", std::make_tuple(record::Keyword::MB, keyword::Encoding::MB)},
Patrick Venturec83c4dc2018-11-01 16:29:18 -070054 {"MM", std::make_tuple(record::Keyword::MM, keyword::Encoding::ASCII)},
55 {"UD", std::make_tuple(record::Keyword::UD, keyword::Encoding::UD)},
56 {"VP", std::make_tuple(record::Keyword::VP, keyword::Encoding::ASCII)},
57 {"VS", std::make_tuple(record::Keyword::VS, keyword::Encoding::ASCII)},
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -060058};
59
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060060namespace offsets
61{
62
63enum Offsets
64{
Deepak Kodihalli023112f2016-11-22 22:02:14 -060065 VHDR = 17,
66 VHDR_TOC_ENTRY = 29,
67 VTOC_PTR = 35,
Alpana Kumaric0aeac32019-11-28 05:20:10 -060068 VTOC_DATA = 13,
69 VHDR_ECC = 0,
70 VHDR_RECORD = 11
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060071};
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060072}
73
74namespace lengths
75{
76
77enum Lengths
78{
79 RECORD_NAME = 4,
Deepak Kodihalli023112f2016-11-22 22:02:14 -060080 KW_NAME = 2,
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060081 RECORD_MIN = 44,
Alpana Kumaric0aeac32019-11-28 05:20:10 -060082 VTOC_RECORD_LENGTH = 14,
83 VHDR_ECC_LENGTH = 11,
84 VHDR_RECORD_LENGTH = 44,
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060085};
Deepak Kodihalli810c9de2016-11-22 11:42:51 -060086}
87
Alpana Kumaric0aeac32019-11-28 05:20:10 -060088namespace eccStatus
89{
90enum Status
91{
92 SUCCESS = 0,
93 FAILED = -1,
94};
95}
96
97namespace
98{
99constexpr auto toHex(size_t c)
100{
101 constexpr auto map = "0123456789abcdef";
102 return map[c];
103}
104} // namespace
105
106/*readUInt16LE: Read 2 bytes LE data*/
107static LE2ByteData readUInt16LE(Binary::const_iterator iterator)
108{
109 LE2ByteData lowByte = *iterator;
110 LE2ByteData highByte = *(iterator + 1);
111 lowByte |= (highByte << 8);
112 return lowByte;
113}
114
115RecordOffset Impl::getVtocOffset() const
116{
117 auto vpdPtr = vpd.cbegin();
118 std::advance(vpdPtr, offsets::VTOC_PTR);
119 // Get VTOC Offset
120 auto vtocOffset = readUInt16LE(vpdPtr);
121
122 return vtocOffset;
123}
124
125#ifdef IPZ_PARSER
126
127int Impl::vhdrEccCheck() const
128{
129 int rc = eccStatus::SUCCESS;
130 auto vpdPtr = vpd.cbegin();
131
132 auto l_status =
133 vpdecc_check_data(const_cast<uint8_t*>(&vpdPtr[offsets::VHDR_RECORD]),
134 lengths::VHDR_RECORD_LENGTH,
135 const_cast<uint8_t*>(&vpdPtr[offsets::VHDR_ECC]),
136 lengths::VHDR_ECC_LENGTH);
137 if (l_status != VPD_ECC_OK)
138 {
139 rc = eccStatus::FAILED;
140 }
141
142 return rc;
143}
144
145int Impl::vtocEccCheck() const
146{
147 int rc = eccStatus::SUCCESS;
148 // Use another pointer to get ECC information from VHDR,
149 // actual pointer is pointing to VTOC data
150
151 auto vpdPtr = vpd.cbegin();
152
153 // Get VTOC Offset
154 auto vtocOffset = getVtocOffset();
155
156 // Get the VTOC Length
157 std::advance(vpdPtr, offsets::VTOC_PTR + sizeof(RecordOffset));
158 auto vtocLength = readUInt16LE(vpdPtr);
159
160 // Get the ECC Offset
161 std::advance(vpdPtr, sizeof(RecordLength));
162 auto vtocECCOffset = readUInt16LE(vpdPtr);
163
164 // Get the ECC length
165 std::advance(vpdPtr, sizeof(ECCOffset));
166 auto vtocECCLength = readUInt16LE(vpdPtr);
167
168 // Reset pointer to start of the vpd,
169 // so that Offset will point to correct address
170 vpdPtr = vpd.cbegin();
171 auto l_status = vpdecc_check_data(
172 const_cast<uint8_t*>(&vpdPtr[vtocOffset]), vtocLength,
173 const_cast<uint8_t*>(&vpdPtr[vtocECCOffset]), vtocECCLength);
174 if (l_status != VPD_ECC_OK)
175 {
176 rc = eccStatus::FAILED;
177 }
178
179 return rc;
180}
181
182int Impl::recordEccCheck(Binary::const_iterator iterator) const
183{
184 int rc = eccStatus::SUCCESS;
185
186 auto recordOffset = readUInt16LE(iterator);
187
188 std::advance(iterator, sizeof(RecordOffset));
189 auto recordLength = readUInt16LE(iterator);
190
191 std::advance(iterator, sizeof(RecordLength));
192 auto eccOffset = readUInt16LE(iterator);
193
194 std::advance(iterator, sizeof(ECCOffset));
195 auto eccLength = readUInt16LE(iterator);
196
197 if (eccLength == 0 || eccOffset == 0 || recordOffset == 0 ||
198 recordLength == 0)
199 {
200 throw std::runtime_error("Something went wrong. Could't find Record's "
201 "OR its ECC's offset and Length");
202 }
203
204 auto vpdPtr = vpd.cbegin();
205
206 auto l_status = vpdecc_check_data(
207 const_cast<uint8_t*>(&vpdPtr[recordOffset]), recordLength,
208 const_cast<uint8_t*>(&vpdPtr[eccOffset]), eccLength);
209 if (l_status != VPD_ECC_OK)
210 {
211 rc = eccStatus::FAILED;
212 }
213
214 return rc;
215}
216#endif
217
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600218void Impl::checkHeader() const
219{
220 if (vpd.empty() || (lengths::RECORD_MIN > vpd.size()))
221 {
222 throw std::runtime_error("Malformed VPD");
223 }
224 else
225 {
226 auto iterator = vpd.cbegin();
227 std::advance(iterator, offsets::VHDR);
228 auto stop = std::next(iterator, lengths::RECORD_NAME);
229 std::string record(iterator, stop);
230 if ("VHDR" != record)
231 {
232 throw std::runtime_error("VHDR record not found");
233 }
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600234
235#ifdef IPZ_PARSER
236 // Check ECC
237 int rc = eccStatus::FAILED;
238 rc = vhdrEccCheck();
239 if (rc != eccStatus::SUCCESS)
240 {
241 throw std::runtime_error("ERROR: VHDR ECC check Failed");
242 }
243#endif
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600244 }
245}
246
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600247internal::OffsetList Impl::readTOC() const
248{
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700249 internal::OffsetList offsets{};
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600250
251 // The offset to VTOC could be 1 or 2 bytes long
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600252 RecordOffset vtocOffset = getVtocOffset();
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600253
254 // Got the offset to VTOC, skip past record header and keyword header
255 // to get to the record name.
256 auto iterator = vpd.cbegin();
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700257 std::advance(iterator, vtocOffset + sizeof(RecordId) + sizeof(RecordSize) +
258 // Skip past the RT keyword, which contains
259 // the record name.
260 lengths::KW_NAME + sizeof(KwSize));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600261
262 auto stop = std::next(iterator, lengths::RECORD_NAME);
263 std::string record(iterator, stop);
264 if ("VTOC" != record)
265 {
266 throw std::runtime_error("VTOC record not found");
267 }
268
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600269#ifdef IPZ_PARSER
270 // Check ECC
271 int rc = eccStatus::FAILED;
272 rc = vtocEccCheck();
273 if (rc != eccStatus::SUCCESS)
274 {
275 throw std::runtime_error("ERROR: VTOC ECC check Failed");
276 }
277#endif
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600278 // VTOC record name is good, now read through the TOC, stored in the PT
279 // PT keyword; vpdBuffer is now pointing at the first character of the
280 // name 'VTOC', jump to PT data.
281 // Skip past record name and KW name, 'PT'
282 std::advance(iterator, lengths::RECORD_NAME + lengths::KW_NAME);
283 // Note size of PT
284 std::size_t ptLen = *iterator;
285 // Skip past PT size
286 std::advance(iterator, sizeof(KwSize));
287
288 // vpdBuffer is now pointing to PT data
289 return readPT(iterator, ptLen);
290}
291
292internal::OffsetList Impl::readPT(Binary::const_iterator iterator,
293 std::size_t ptLength) const
294{
295 internal::OffsetList offsets{};
296
297 auto end = iterator;
298 std::advance(end, ptLength);
299
300 // Look at each entry in the PT keyword. In the entry,
301 // we care only about the record offset information.
302 while (iterator < end)
303 {
304 // Skip record name and record type
305 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
306
307 // Get record offset
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600308 auto offset = readUInt16LE(iterator);
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600309 offsets.push_back(offset);
310
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600311#ifdef IPZ_PARSER
312 // Verify the ECC for this Record
313 int rc = recordEccCheck(iterator);
314
315 if (rc != eccStatus::SUCCESS)
316 {
317 throw std::runtime_error(
318 "ERROR: ECC check for one of the Record did not Pass.");
319 }
320#endif
321
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600322 // Jump record size, record length, ECC offset and ECC length
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600323 std::advance(iterator, sizeof(RecordOffset) + sizeof(RecordLength) +
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700324 sizeof(ECCOffset) + sizeof(ECCLength));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600325 }
326
327 return offsets;
328}
329
Deepak Kodihallia1143462016-11-24 06:28:45 -0600330void Impl::processRecord(std::size_t recordOffset)
331{
332 // Jump to record name
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700333 auto nameOffset = recordOffset + sizeof(RecordId) + sizeof(RecordSize) +
Deepak Kodihallia1143462016-11-24 06:28:45 -0600334 // Skip past the RT keyword, which contains
335 // the record name.
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700336 lengths::KW_NAME + sizeof(KwSize);
Deepak Kodihallia1143462016-11-24 06:28:45 -0600337 // Get record name
338 auto iterator = vpd.cbegin();
339 std::advance(iterator, nameOffset);
340
341 std::string name(iterator, iterator + lengths::RECORD_NAME);
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600342
Alpana Kumari26a74af2019-09-10 23:53:58 -0500343#ifndef IPZ_PARSER
Deepak Kodihallia1143462016-11-24 06:28:45 -0600344 if (supportedRecords.end() != supportedRecords.find(name))
345 {
Alpana Kumari26a74af2019-09-10 23:53:58 -0500346#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600347 // If it's a record we're interested in, proceed to find
348 // contained keywords and their values.
349 std::advance(iterator, lengths::RECORD_NAME);
Alpana Kumari26a74af2019-09-10 23:53:58 -0500350
351#ifdef IPZ_PARSER
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600352
Alpana Kumari26a74af2019-09-10 23:53:58 -0500353 // Reverse back to RT Kw, in ipz vpd, to Read RT KW & value
354 std::advance(iterator, -(lengths::KW_NAME + sizeof(KwSize) +
355 lengths::RECORD_NAME));
356#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600357 auto kwMap = readKeywords(iterator);
358 // Add entry for this record (and contained keyword:value pairs)
359 // to the parsed vpd output.
360 out.emplace(std::move(name), std::move(kwMap));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600361
Alpana Kumari26a74af2019-09-10 23:53:58 -0500362#ifndef IPZ_PARSER
Deepak Kodihallia1143462016-11-24 06:28:45 -0600363 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500364#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600365}
366
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600367std::string Impl::readKwData(const internal::KeywordInfo& keyword,
368 std::size_t dataLength,
369 Binary::const_iterator iterator)
370{
Santosh Puranikbd011b22020-01-23 04:05:25 -0600371 using namespace openpower::vpd;
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600372 switch (std::get<keyword::Encoding>(keyword))
373 {
374 case keyword::Encoding::ASCII:
375 {
376 auto stop = std::next(iterator, dataLength);
377 return std::string(iterator, stop);
378 }
379
380 case keyword::Encoding::RAW:
381 {
382 auto stop = std::next(iterator, dataLength);
383 std::string data(iterator, stop);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700384 std::string result{};
385 std::for_each(data.cbegin(), data.cend(), [&result](size_t c) {
386 result += toHex(c >> 4);
387 result += toHex(c & 0x0F);
388 });
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600389 return result;
390 }
391
George Liuee79ca82019-07-12 11:05:33 +0800392 case keyword::Encoding::MB:
393 {
394 // MB is BuildDate, represent as
395 // 1997-01-01-08:30:00
396 // <year>-<month>-<day>-<hour>:<min>:<sec>
397 auto stop = std::next(iterator, MB_LEN_BYTES);
398 std::string data(iterator, stop);
399 std::string result;
400 result.reserve(MB_LEN_BYTES);
401 auto strItr = data.cbegin();
402 std::advance(strItr, 1);
403 std::for_each(strItr, data.cend(), [&result](size_t c) {
404 result += toHex(c >> 4);
405 result += toHex(c & 0x0F);
406 });
407
408 result.insert(MB_YEAR_END, 1, '-');
409 result.insert(MB_MONTH_END, 1, '-');
410 result.insert(MB_DAY_END, 1, '-');
411 result.insert(MB_HOUR_END, 1, ':');
412 result.insert(MB_MIN_END, 1, ':');
413
414 return result;
415 }
416
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600417 case keyword::Encoding::B1:
418 {
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700419 // B1 is MAC address, represent as AA:BB:CC:DD:EE:FF
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600420 auto stop = std::next(iterator, MAC_ADDRESS_LEN_BYTES);
421 std::string data(iterator, stop);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700422 std::string result{};
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600423 auto strItr = data.cbegin();
424 size_t firstDigit = *strItr;
425 result += toHex(firstDigit >> 4);
426 result += toHex(firstDigit & 0x0F);
427 std::advance(strItr, 1);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700428 std::for_each(strItr, data.cend(), [&result](size_t c) {
429 result += ":";
430 result += toHex(c >> 4);
431 result += toHex(c & 0x0F);
432 });
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600433 return result;
434 }
435
Dinesh Chinaric576b482017-07-17 16:34:10 -0500436 case keyword::Encoding::UD:
437 {
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700438 // UD, the UUID info, represented as
439 // 123e4567-e89b-12d3-a456-426655440000
Dinesh Chinaric576b482017-07-17 16:34:10 -0500440 //<time_low>-<time_mid>-<time hi and version>
441 //-<clock_seq_hi_and_res clock_seq_low>-<48 bits node id>
442 auto stop = std::next(iterator, UUID_LEN_BYTES);
443 std::string data(iterator, stop);
444 std::string result{};
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700445 std::for_each(data.cbegin(), data.cend(), [&result](size_t c) {
446 result += toHex(c >> 4);
447 result += toHex(c & 0x0F);
448 });
Dinesh Chinaric576b482017-07-17 16:34:10 -0500449 result.insert(UUID_TIME_LOW_END, 1, '-');
450 result.insert(UUID_TIME_MID_END, 1, '-');
451 result.insert(UUID_TIME_HIGH_END, 1, '-');
452 result.insert(UUID_CLK_SEQ_END, 1, '-');
453
454 return result;
455 }
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600456 default:
457 break;
458 }
459
460 return {};
461}
462
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600463internal::KeywordMap Impl::readKeywords(Binary::const_iterator iterator)
464{
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700465 internal::KeywordMap map{};
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600466 while (true)
467 {
468 // Note keyword name
469 std::string kw(iterator, iterator + lengths::KW_NAME);
470 if (LAST_KW == kw)
471 {
472 // We're done
473 break;
474 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500475 // Check if the Keyword is '#kw'
476 char kwNameStart = *iterator;
477
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600478 // Jump past keyword name
479 std::advance(iterator, lengths::KW_NAME);
Alpana Kumari26a74af2019-09-10 23:53:58 -0500480
481 std::size_t length;
482 std::size_t lengthHighByte;
483 if (POUND_KW == kwNameStart)
484 {
485 // Note keyword data length
486 length = *iterator;
487 lengthHighByte = *(iterator + 1);
488 length |= (lengthHighByte << 8);
489
490 // Jump past 2Byte keyword length
491 std::advance(iterator, sizeof(PoundKwSize));
492 }
493 else
494 {
495 // Note keyword data length
496 length = *iterator;
497
498 // Jump past keyword length
499 std::advance(iterator, sizeof(KwSize));
500 }
501
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600502 // Pointing to keyword data now
Alpana Kumari26a74af2019-09-10 23:53:58 -0500503#ifndef IPZ_PARSER
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600504 if (supportedKeywords.end() != supportedKeywords.find(kw))
505 {
506 // Keyword is of interest to us
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700507 std::string data = readKwData((supportedKeywords.find(kw))->second,
508 length, iterator);
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600509 map.emplace(std::move(kw), std::move(data));
510 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500511
512#else
513 // support all the Keywords
514 auto stop = std::next(iterator, length);
515 std::string kwdata(iterator, stop);
516 map.emplace(std::move(kw), std::move(kwdata));
517
518#endif
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600519 // Jump past keyword data length
520 std::advance(iterator, length);
521 }
522
523 return map;
524}
525
Deepak Kodihalli174caf62016-11-25 05:41:19 -0600526Store Impl::run()
527{
528 // Check if the VHDR record is present
529 checkHeader();
530
531 // Read the table of contents record, to get offsets
532 // to other records.
533 auto offsets = readTOC();
534 for (const auto& offset : offsets)
535 {
536 processRecord(offset);
537 }
Deepak Kodihalli174caf62016-11-25 05:41:19 -0600538 // Return a Store object, which has interfaces to
539 // access parsed VPD by record:keyword
540 return Store(std::move(out));
541}
542
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600543} // namespace parser
544} // namespace vpd
545} // namespace openpower