blob: a8bd694994190c3619edda199f5d59ee91c92119 [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 {
Santosh Puranikc04e1852022-12-20 11:13:22 +0530151 throw(VpdEccException(
152 "Could not find ECC's offset or Length for Record:"));
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500153 }
154
155 if (recordOffset == 0 || recordLength == 0)
156 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500157 throw(VpdDataException("Could not find VPD record offset or VPD record "
Santosh Puranikc04e1852022-12-20 11:13:22 +0530158 "length for Record:"));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600159 }
160
161 auto vpdPtr = vpd.cbegin();
162
163 auto l_status = vpdecc_check_data(
164 const_cast<uint8_t*>(&vpdPtr[recordOffset]), recordLength,
165 const_cast<uint8_t*>(&vpdPtr[eccOffset]), eccLength);
166 if (l_status != VPD_ECC_OK)
167 {
168 rc = eccStatus::FAILED;
169 }
170
171 return rc;
172}
173#endif
174
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600175void Impl::checkHeader() const
176{
177 if (vpd.empty() || (lengths::RECORD_MIN > vpd.size()))
178 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500179 throw(VpdDataException("Malformed VPD"));
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600180 }
181 else
182 {
183 auto iterator = vpd.cbegin();
184 std::advance(iterator, offsets::VHDR);
185 auto stop = std::next(iterator, lengths::RECORD_NAME);
186 std::string record(iterator, stop);
187 if ("VHDR" != record)
188 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500189 throw(VpdDataException("VHDR record not found"));
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600190 }
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600191
192#ifdef IPZ_PARSER
193 // Check ECC
194 int rc = eccStatus::FAILED;
195 rc = vhdrEccCheck();
196 if (rc != eccStatus::SUCCESS)
197 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500198 throw(VpdEccException("ERROR: VHDR ECC check Failed"));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600199 }
200#endif
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600201 }
202}
203
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600204std::size_t Impl::readTOC(Binary::const_iterator& iterator) const
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600205{
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600206 // The offset to VTOC could be 1 or 2 bytes long
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600207 RecordOffset vtocOffset = getVtocOffset();
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600208
209 // Got the offset to VTOC, skip past record header and keyword header
210 // to get to the record name.
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700211 std::advance(iterator, vtocOffset + sizeof(RecordId) + sizeof(RecordSize) +
212 // Skip past the RT keyword, which contains
213 // the record name.
214 lengths::KW_NAME + sizeof(KwSize));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600215
216 auto stop = std::next(iterator, lengths::RECORD_NAME);
217 std::string record(iterator, stop);
218 if ("VTOC" != record)
219 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500220 throw(VpdDataException("VTOC record not found"));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600221 }
222
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600223#ifdef IPZ_PARSER
224 // Check ECC
225 int rc = eccStatus::FAILED;
226 rc = vtocEccCheck();
227 if (rc != eccStatus::SUCCESS)
228 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500229 throw(VpdEccException("ERROR: VTOC ECC check Failed"));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600230 }
231#endif
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600232 // VTOC record name is good, now read through the TOC, stored in the PT
233 // PT keyword; vpdBuffer is now pointing at the first character of the
234 // name 'VTOC', jump to PT data.
235 // Skip past record name and KW name, 'PT'
236 std::advance(iterator, lengths::RECORD_NAME + lengths::KW_NAME);
237 // Note size of PT
238 std::size_t ptLen = *iterator;
239 // Skip past PT size
240 std::advance(iterator, sizeof(KwSize));
241
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600242 // length of PT keyword
243 return ptLen;
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600244}
245
246internal::OffsetList Impl::readPT(Binary::const_iterator iterator,
247 std::size_t ptLength) const
248{
249 internal::OffsetList offsets{};
250
251 auto end = iterator;
252 std::advance(end, ptLength);
253
254 // Look at each entry in the PT keyword. In the entry,
255 // we care only about the record offset information.
256 while (iterator < end)
257 {
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500258#ifdef IPZ_PARSER
259 auto iteratorToRecName = iterator;
260#endif
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600261 // Skip record name and record type
262 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
263
264 // Get record offset
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600265 auto offset = readUInt16LE(iterator);
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600266 offsets.push_back(offset);
267
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600268#ifdef IPZ_PARSER
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500269 std::string recordName(iteratorToRecName,
270 iteratorToRecName + lengths::RECORD_NAME);
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600271
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500272 try
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600273 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500274 // Verify the ECC for this Record
275 int rc = recordEccCheck(iterator);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500276
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500277 if (rc != eccStatus::SUCCESS)
278 {
279 std::string errorMsg =
Santosh Puranikc04e1852022-12-20 11:13:22 +0530280 std::string("ERROR: ECC check did not pass for the "
281 "Record:");
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500282 throw(VpdEccException(errorMsg));
283 }
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600284 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500285 catch (const VpdEccException& ex)
286 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500287 inventory::PelAdditionalData additionalData{};
Santosh Puranikc04e1852022-12-20 11:13:22 +0530288 additionalData.emplace("DESCRIPTION",
289 std::string{ex.what()} + recordName);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500290 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 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500296 inventory::PelAdditionalData additionalData{};
Santosh Puranikc04e1852022-12-20 11:13:22 +0530297 additionalData.emplace("DESCRIPTION",
298 std::string{ex.what()} + recordName);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500299 additionalData.emplace("CALLOUT_INVENTORY_PATH", inventoryPath);
300 createPEL(additionalData, PelSeverity::WARNING,
Sunny Srivastavaa2ddc962022-06-29 08:53:16 -0500301 errIntfForInvalidVPD, nullptr);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500302 }
303
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600304#endif
305
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600306 // Jump record size, record length, ECC offset and ECC length
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600307 std::advance(iterator, sizeof(RecordOffset) + sizeof(RecordLength) +
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700308 sizeof(ECCOffset) + sizeof(ECCLength));
Deepak Kodihalli023112f2016-11-22 22:02:14 -0600309 }
310
311 return offsets;
312}
313
Deepak Kodihallia1143462016-11-24 06:28:45 -0600314void Impl::processRecord(std::size_t recordOffset)
315{
316 // Jump to record name
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700317 auto nameOffset = recordOffset + sizeof(RecordId) + sizeof(RecordSize) +
Deepak Kodihallia1143462016-11-24 06:28:45 -0600318 // Skip past the RT keyword, which contains
319 // the record name.
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700320 lengths::KW_NAME + sizeof(KwSize);
Deepak Kodihallia1143462016-11-24 06:28:45 -0600321 // Get record name
322 auto iterator = vpd.cbegin();
323 std::advance(iterator, nameOffset);
324
325 std::string name(iterator, iterator + lengths::RECORD_NAME);
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600326
Alpana Kumari26a74af2019-09-10 23:53:58 -0500327#ifndef IPZ_PARSER
Deepak Kodihallia1143462016-11-24 06:28:45 -0600328 if (supportedRecords.end() != supportedRecords.find(name))
329 {
Alpana Kumari26a74af2019-09-10 23:53:58 -0500330#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600331 // If it's a record we're interested in, proceed to find
332 // contained keywords and their values.
333 std::advance(iterator, lengths::RECORD_NAME);
Alpana Kumari26a74af2019-09-10 23:53:58 -0500334
335#ifdef IPZ_PARSER
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600336
Alpana Kumari26a74af2019-09-10 23:53:58 -0500337 // Reverse back to RT Kw, in ipz vpd, to Read RT KW & value
338 std::advance(iterator, -(lengths::KW_NAME + sizeof(KwSize) +
339 lengths::RECORD_NAME));
340#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600341 auto kwMap = readKeywords(iterator);
342 // Add entry for this record (and contained keyword:value pairs)
343 // to the parsed vpd output.
344 out.emplace(std::move(name), std::move(kwMap));
Alpana Kumaric0aeac32019-11-28 05:20:10 -0600345
Alpana Kumari26a74af2019-09-10 23:53:58 -0500346#ifndef IPZ_PARSER
Deepak Kodihallia1143462016-11-24 06:28:45 -0600347 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500348#endif
Deepak Kodihallia1143462016-11-24 06:28:45 -0600349}
350
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600351std::string Impl::readKwData(const internal::KeywordInfo& keyword,
352 std::size_t dataLength,
353 Binary::const_iterator iterator)
354{
Santosh Puranikbd011b22020-01-23 04:05:25 -0600355 using namespace openpower::vpd;
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600356 switch (std::get<keyword::Encoding>(keyword))
357 {
358 case keyword::Encoding::ASCII:
359 {
360 auto stop = std::next(iterator, dataLength);
361 return std::string(iterator, stop);
362 }
363
364 case keyword::Encoding::RAW:
365 {
366 auto stop = std::next(iterator, dataLength);
367 std::string data(iterator, stop);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700368 std::string result{};
369 std::for_each(data.cbegin(), data.cend(), [&result](size_t c) {
370 result += toHex(c >> 4);
371 result += toHex(c & 0x0F);
372 });
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600373 return result;
374 }
375
George Liuee79ca82019-07-12 11:05:33 +0800376 case keyword::Encoding::MB:
377 {
378 // MB is BuildDate, represent as
379 // 1997-01-01-08:30:00
380 // <year>-<month>-<day>-<hour>:<min>:<sec>
381 auto stop = std::next(iterator, MB_LEN_BYTES);
382 std::string data(iterator, stop);
383 std::string result;
384 result.reserve(MB_LEN_BYTES);
385 auto strItr = data.cbegin();
386 std::advance(strItr, 1);
387 std::for_each(strItr, data.cend(), [&result](size_t c) {
388 result += toHex(c >> 4);
389 result += toHex(c & 0x0F);
390 });
391
392 result.insert(MB_YEAR_END, 1, '-');
393 result.insert(MB_MONTH_END, 1, '-');
394 result.insert(MB_DAY_END, 1, '-');
395 result.insert(MB_HOUR_END, 1, ':');
396 result.insert(MB_MIN_END, 1, ':');
397
398 return result;
399 }
400
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600401 case keyword::Encoding::B1:
402 {
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700403 // B1 is MAC address, represent as AA:BB:CC:DD:EE:FF
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600404 auto stop = std::next(iterator, MAC_ADDRESS_LEN_BYTES);
405 std::string data(iterator, stop);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700406 std::string result{};
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600407 auto strItr = data.cbegin();
408 size_t firstDigit = *strItr;
409 result += toHex(firstDigit >> 4);
410 result += toHex(firstDigit & 0x0F);
411 std::advance(strItr, 1);
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700412 std::for_each(strItr, data.cend(), [&result](size_t c) {
413 result += ":";
414 result += toHex(c >> 4);
415 result += toHex(c & 0x0F);
416 });
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600417 return result;
418 }
419
Dinesh Chinaric576b482017-07-17 16:34:10 -0500420 case keyword::Encoding::UD:
421 {
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700422 // UD, the UUID info, represented as
423 // 123e4567-e89b-12d3-a456-426655440000
Dinesh Chinaric576b482017-07-17 16:34:10 -0500424 //<time_low>-<time_mid>-<time hi and version>
425 //-<clock_seq_hi_and_res clock_seq_low>-<48 bits node id>
426 auto stop = std::next(iterator, UUID_LEN_BYTES);
427 std::string data(iterator, stop);
428 std::string result{};
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700429 std::for_each(data.cbegin(), data.cend(), [&result](size_t c) {
430 result += toHex(c >> 4);
431 result += toHex(c & 0x0F);
432 });
Dinesh Chinaric576b482017-07-17 16:34:10 -0500433 result.insert(UUID_TIME_LOW_END, 1, '-');
434 result.insert(UUID_TIME_MID_END, 1, '-');
435 result.insert(UUID_TIME_HIGH_END, 1, '-');
436 result.insert(UUID_CLK_SEQ_END, 1, '-');
437
438 return result;
439 }
Deepak Kodihalli4a475bd2016-11-24 07:08:20 -0600440 default:
441 break;
442 }
443
444 return {};
445}
446
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600447internal::KeywordMap Impl::readKeywords(Binary::const_iterator iterator)
448{
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700449 internal::KeywordMap map{};
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600450 while (true)
451 {
452 // Note keyword name
453 std::string kw(iterator, iterator + lengths::KW_NAME);
454 if (LAST_KW == kw)
455 {
456 // We're done
457 break;
458 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500459 // Check if the Keyword is '#kw'
460 char kwNameStart = *iterator;
461
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600462 // Jump past keyword name
463 std::advance(iterator, lengths::KW_NAME);
Alpana Kumari26a74af2019-09-10 23:53:58 -0500464
465 std::size_t length;
466 std::size_t lengthHighByte;
467 if (POUND_KW == kwNameStart)
468 {
469 // Note keyword data length
470 length = *iterator;
471 lengthHighByte = *(iterator + 1);
472 length |= (lengthHighByte << 8);
473
474 // Jump past 2Byte keyword length
475 std::advance(iterator, sizeof(PoundKwSize));
476 }
477 else
478 {
479 // Note keyword data length
480 length = *iterator;
481
482 // Jump past keyword length
483 std::advance(iterator, sizeof(KwSize));
484 }
485
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600486 // Pointing to keyword data now
Alpana Kumari26a74af2019-09-10 23:53:58 -0500487#ifndef IPZ_PARSER
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600488 if (supportedKeywords.end() != supportedKeywords.find(kw))
489 {
490 // Keyword is of interest to us
Patrick Venturec83c4dc2018-11-01 16:29:18 -0700491 std::string data = readKwData((supportedKeywords.find(kw))->second,
492 length, iterator);
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600493 map.emplace(std::move(kw), std::move(data));
494 }
Alpana Kumari26a74af2019-09-10 23:53:58 -0500495
496#else
497 // support all the Keywords
498 auto stop = std::next(iterator, length);
499 std::string kwdata(iterator, stop);
500 map.emplace(std::move(kw), std::move(kwdata));
501
502#endif
Deepak Kodihalli683bf722016-11-24 06:50:43 -0600503 // Jump past keyword data length
504 std::advance(iterator, length);
505 }
506
507 return map;
508}
509
Deepak Kodihalli174caf62016-11-25 05:41:19 -0600510Store Impl::run()
511{
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500512 // Check if the VHDR record is present
513 checkHeader();
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500514
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500515 auto iterator = vpd.cbegin();
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500516
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500517 // Read the table of contents record
518 std::size_t ptLen = readTOC(iterator);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500519
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500520 // Read the table of contents record, to get offsets
521 // to other records.
522 auto offsets = readPT(iterator, ptLen);
523 for (const auto& offset : offsets)
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500524 {
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500525 processRecord(offset);
SunnySrivastava19849d4f1122020-08-26 02:41:46 -0500526 }
SunnySrivastava1984a20be8e2020-08-26 02:00:50 -0500527 // Return a Store object, which has interfaces to
528 // access parsed VPD by record:keyword
529 return Store(std::move(out));
Deepak Kodihalli174caf62016-11-25 05:41:19 -0600530}
531
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600532void Impl::checkVPDHeader()
533{
534 // Check if the VHDR record is present and is valid
535 checkHeader();
536}
537
Priyanga Ramasamy28079c82021-10-07 16:30:51 -0500538std::string Impl::readKwFromHw(const std::string& record,
539 const std::string& keyword)
540{
541 // Check if the VHDR record is present
542 checkHeader();
543
544 auto iterator = vpd.cbegin();
545
546 // Read the table of contents record
547 std::size_t ptLen = readTOC(iterator);
548
549 // Read the table of contents record, to get offsets
550 // to other records.
551 auto offsets = readPT(iterator, ptLen);
552 for (const auto& offset : offsets)
553 {
554 // Jump to record name
555 auto nameOffset = offset + sizeof(RecordId) + sizeof(RecordSize) +
556 // Skip past the RT keyword, which contains
557 // the record name.
558 lengths::KW_NAME + sizeof(KwSize);
559 // Get record name
560 auto iterator = vpd.cbegin();
561 std::advance(iterator, nameOffset);
562
563 std::string name(iterator, iterator + lengths::RECORD_NAME);
564 if (name != record)
565 {
566 continue;
567 }
568 else
569 {
570 processRecord(offset);
571 const auto& itr = out.find(record);
572 if (itr != out.end())
573 {
574 const auto& kwValItr = (itr->second).find(keyword);
575 if (kwValItr != (itr->second).end())
576 {
577 return kwValItr->second;
578 }
579 else
580 {
581 return "";
582 }
583 }
584 }
585 }
586 return "";
587}
588
Deepak Kodihalli810c9de2016-11-22 11:42:51 -0600589} // namespace parser
590} // namespace vpd
Priyanga Ramasamy28079c82021-10-07 16:30:51 -0500591} // namespace openpower