blob: a20cd44b33e04d3019b77253bb652ce0d74f26c6 [file] [log] [blame]
SunnySrivastava1984a7392592020-03-09 10:19:33 -05001#include "config.h"
2
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06003#include "editor_impl.hpp"
4
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05005#include "ipz_parser.hpp"
6#include "parser_factory.hpp"
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06007#include "utils.hpp"
8
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06009#include "vpdecc/vpdecc.h"
10
SunnySrivastava1984e12b1812020-05-26 02:23:11 -050011using namespace openpower::vpd::parser::interface;
12using namespace openpower::vpd::constants;
13using namespace openpower::vpd::parser::factory;
14using namespace openpower::vpd::ipz::parser;
15
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060016namespace openpower
17{
18namespace vpd
19{
20namespace manager
21{
22namespace editor
23{
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060024
25void EditorImpl::checkPTForRecord(Binary::const_iterator& iterator,
26 Byte ptLength)
27{
28 // auto iterator = ptRecord.cbegin();
29 auto end = std::next(iterator, ptLength + 1);
30
31 // Look at each entry in the PT keyword for the record name
32 while (iterator < end)
33 {
34 auto stop = std::next(iterator, lengths::RECORD_NAME);
35 std::string record(iterator, stop);
36
37 if (record == thisRecord.recName)
38 {
39 // Skip record name and record type
40 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
41
42 // Get record offset
43 thisRecord.recOffset = readUInt16LE(iterator);
44
45 // pass the record offset length to read record length
46 std::advance(iterator, lengths::RECORD_OFFSET);
47 thisRecord.recSize = readUInt16LE(iterator);
48
49 std::advance(iterator, lengths::RECORD_LENGTH);
50 thisRecord.recECCoffset = readUInt16LE(iterator);
51
52 ECCLength len;
53 std::advance(iterator, lengths::RECORD_ECC_OFFSET);
54 len = readUInt16LE(iterator);
55 thisRecord.recECCLength = len;
56
57 // once we find the record we don't need to look further
58 return;
59 }
60 else
61 {
62 // Jump the record
63 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType) +
64 sizeof(RecordOffset) +
65 sizeof(RecordLength) +
66 sizeof(ECCOffset) + sizeof(ECCLength));
67 }
68 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060069 // imples the record was not found
70 throw std::runtime_error("Record not found");
71}
72
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050073void EditorImpl::updateData(const Binary& kwdData)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060074{
75 std::size_t lengthToUpdate = kwdData.size() <= thisRecord.kwdDataLength
76 ? kwdData.size()
77 : thisRecord.kwdDataLength;
78
79 auto iteratorToNewdata = kwdData.cbegin();
80 auto end = iteratorToNewdata;
81 std::advance(end, lengthToUpdate);
82
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050083 // update data in file buffer as it will be needed to update ECC
84 // avoiding extra stream operation here
85 auto iteratorToKWdData = vpdFile.begin();
86 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
87 std::copy(iteratorToNewdata, end, iteratorToKWdData);
88
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -050089#ifdef ManagerTest
90 auto startItr = vpdFile.begin();
91 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
92 auto endItr = startItr;
93 std::advance(endItr, thisRecord.kwdDataLength);
94
95 Binary updatedData(startItr, endItr);
96 if (updatedData == kwdData)
97 {
98 throw std::runtime_error("Data updated successfully");
99 }
100#else
101
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500102 // update data in EEPROM as well. As we will not write complete file back
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500103 vpdFileStream.seekp(startOffset + thisRecord.kwDataOffset, std::ios::beg);
Alpana Kumari920408d2020-05-14 00:07:03 -0500104
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500105 iteratorToNewdata = kwdData.cbegin();
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600106 std::copy(iteratorToNewdata, end,
107 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500108
109 // get a hold to new data in case encoding is needed
110 thisRecord.kwdUpdatedData.resize(thisRecord.kwdDataLength);
111 auto itrToKWdData = vpdFile.cbegin();
112 std::advance(itrToKWdData, thisRecord.kwDataOffset);
113 auto kwdDataEnd = itrToKWdData;
114 std::advance(kwdDataEnd, thisRecord.kwdDataLength);
115 std::copy(itrToKWdData, kwdDataEnd, thisRecord.kwdUpdatedData.begin());
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500116#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600117}
118
119void EditorImpl::checkRecordForKwd()
120{
121 RecordOffset recOffset = thisRecord.recOffset;
122
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500123 // Amount to skip for record ID, size, and the RT keyword
124 constexpr auto skipBeg = sizeof(RecordId) + sizeof(RecordSize) +
125 lengths::KW_NAME + sizeof(KwSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600126
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500127 auto iterator = vpdFile.cbegin();
128 std::advance(iterator, recOffset + skipBeg + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600129
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500130 auto end = iterator;
131 std::advance(end, thisRecord.recSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600132 std::size_t dataLength = 0;
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500133
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600134 while (iterator < end)
135 {
136 // Note keyword name
137 std::string kw(iterator, iterator + lengths::KW_NAME);
138
139 // Check if the Keyword starts with '#'
140 char kwNameStart = *iterator;
141 std::advance(iterator, lengths::KW_NAME);
142
143 // if keyword starts with #
144 if (POUND_KW == kwNameStart)
145 {
146 // Note existing keyword data length
147 dataLength = readUInt16LE(iterator);
148
149 // Jump past 2Byte keyword length + data
150 std::advance(iterator, sizeof(PoundKwSize));
151 }
152 else
153 {
154 // Note existing keyword data length
155 dataLength = *iterator;
156
157 // Jump past keyword length and data
158 std::advance(iterator, sizeof(KwSize));
159 }
160
161 if (thisRecord.recKWd == kw)
162 {
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500163 thisRecord.kwDataOffset = std::distance(vpdFile.cbegin(), iterator);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600164 thisRecord.kwdDataLength = dataLength;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600165 return;
166 }
167
168 // jump the data of current kwd to point to next kwd name
169 std::advance(iterator, dataLength);
170 }
171
172 throw std::runtime_error("Keyword not found");
173}
174
175void EditorImpl::updateRecordECC()
176{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500177 auto itrToRecordData = vpdFile.cbegin();
178 std::advance(itrToRecordData, thisRecord.recOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600179
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500180 auto itrToRecordECC = vpdFile.cbegin();
181 std::advance(itrToRecordECC, thisRecord.recECCoffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600182
183 auto l_status = vpdecc_create_ecc(
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500184 const_cast<uint8_t*>(&itrToRecordData[0]), thisRecord.recSize,
185 const_cast<uint8_t*>(&itrToRecordECC[0]), &thisRecord.recECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600186 if (l_status != VPD_ECC_OK)
187 {
188 throw std::runtime_error("Ecc update failed");
189 }
190
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500191 auto end = itrToRecordECC;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600192 std::advance(end, thisRecord.recECCLength);
193
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500194#ifndef ManagerTest
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500195 vpdFileStream.seekp(startOffset + thisRecord.recECCoffset, std::ios::beg);
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500196 std::copy(itrToRecordECC, end,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600197 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500198#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600199}
200
201auto EditorImpl::getValue(offsets::Offsets offset)
202{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500203 auto itr = vpdFile.cbegin();
204 std::advance(itr, offset);
205 LE2ByteData lowByte = *itr;
206 LE2ByteData highByte = *(itr + 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600207 lowByte |= (highByte << 8);
208
209 return lowByte;
210}
211
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500212void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
213 Binary::const_iterator& itrToECCData,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600214 RecordLength recLength, ECCLength eccLength)
215{
216 auto l_status =
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500217 vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
218 const_cast<uint8_t*>(&itrToECCData[0]), eccLength);
219
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600220 if (l_status != VPD_ECC_OK)
221 {
222 throw std::runtime_error("Ecc check failed for VTOC");
223 }
224}
225
226void EditorImpl::readVTOC()
227{
228 // read VTOC offset
229 RecordOffset tocOffset = getValue(offsets::VTOC_PTR);
230
231 // read VTOC record length
232 RecordLength tocLength = getValue(offsets::VTOC_REC_LEN);
233
234 // read TOC ecc offset
235 ECCOffset tocECCOffset = getValue(offsets::VTOC_ECC_OFF);
236
237 // read TOC ecc length
238 ECCLength tocECCLength = getValue(offsets::VTOC_ECC_LEN);
239
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500240 auto itrToRecord = vpdFile.cbegin();
241 std::advance(itrToRecord, tocOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600242
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500243 auto iteratorToECC = vpdFile.cbegin();
244 std::advance(iteratorToECC, tocECCOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600245
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500246 // validate ecc for the record
247 checkECC(itrToRecord, iteratorToECC, tocLength, tocECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600248
249 // to get to the record name.
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500250 std::advance(itrToRecord, sizeof(RecordId) + sizeof(RecordSize) +
251 // Skip past the RT keyword, which contains
252 // the record name.
253 lengths::KW_NAME + sizeof(KwSize));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600254
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500255 std::string recordName(itrToRecord, itrToRecord + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600256
257 if ("VTOC" != recordName)
258 {
259 throw std::runtime_error("VTOC record not found");
260 }
261
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600262 // jump to length of PT kwd
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500263 std::advance(itrToRecord, lengths::RECORD_NAME + lengths::KW_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600264
265 // Note size of PT
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500266 Byte ptLen = *itrToRecord;
267 std::advance(itrToRecord, 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600268
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500269 checkPTForRecord(itrToRecord, ptLen);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600270}
271
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600272template <typename T>
273void EditorImpl::makeDbusCall(const std::string& object,
274 const std::string& interface,
275 const std::string& property,
276 const std::variant<T>& data)
277{
278 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500279 auto properties =
280 bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
281 "org.freedesktop.DBus.Properties", "Set");
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600282 properties.append(interface);
283 properties.append(property);
284 properties.append(data);
285
286 auto result = bus.call(properties);
287
288 if (result.is_method_error())
289 {
290 throw std::runtime_error("bus call failed");
291 }
292}
293
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600294void EditorImpl::processAndUpdateCI(const std::string& objectPath)
295{
296 for (auto& commonInterface : jsonFile["commonInterfaces"].items())
297 {
298 for (auto& ciPropertyList : commonInterface.value().items())
299 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600300 if (ciPropertyList.value().type() ==
301 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600302 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600303 if ((ciPropertyList.value().value("recordName", "") ==
304 thisRecord.recName) &&
305 (ciPropertyList.value().value("keywordName", "") ==
306 thisRecord.recKWd))
307 {
308 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
309 thisRecord.kwdUpdatedData.end());
310
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500311 makeDbusCall<std::string>((INVENTORY_PATH + objectPath),
312 commonInterface.key(),
313 ciPropertyList.key(), kwdData);
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600314 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600315 }
316 }
317 }
318}
319
320void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
321 const inventory::Path& objPath)
322{
323 for (const auto& extraInterface : Inventory["extraInterfaces"].items())
324 {
325 if (extraInterface.value() != NULL)
326 {
327 for (const auto& eiPropertyList : extraInterface.value().items())
328 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600329 if (eiPropertyList.value().type() ==
330 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600331 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600332 if ((eiPropertyList.value().value("recordName", "") ==
333 thisRecord.recName) &&
334 ((eiPropertyList.value().value("keywordName", "") ==
335 thisRecord.recKWd)))
336 {
337 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
338 thisRecord.kwdUpdatedData.end());
339 makeDbusCall<std::string>(
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500340 (INVENTORY_PATH + objPath), extraInterface.key(),
341 eiPropertyList.key(),
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600342 encodeKeyword(kwdData, eiPropertyList.value().value(
343 "encoding", "")));
344 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600345 }
346 }
347 }
348 }
349}
350
351void EditorImpl::updateCache()
352{
353 const std::vector<nlohmann::json>& groupEEPROM =
354 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
355
356 // iterate through all the inventories for this file path
357 for (const auto& singleInventory : groupEEPROM)
358 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600359 // by default inherit property is true
360 bool isInherit = true;
Alpana Kumari920408d2020-05-14 00:07:03 -0500361 bool isInheritEI = true;
362 bool isCpuModuleOnly = false;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600363
364 if (singleInventory.find("inherit") != singleInventory.end())
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600365 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600366 isInherit = singleInventory["inherit"].get<bool>();
367 }
368
Alpana Kumari920408d2020-05-14 00:07:03 -0500369 if (singleInventory.find("inheritEI") != singleInventory.end())
370 {
371 isInheritEI = singleInventory["inheritEI"].get<bool>();
372 }
373
374 // "type" exists only in CPU module and FRU
375 if (singleInventory.find("type") != singleInventory.end())
376 {
377 if (singleInventory["type"] == "moduleOnly")
378 {
379 isCpuModuleOnly = true;
380 }
381 }
382
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600383 if (isInherit)
384 {
385 // update com interface
Alpana Kumari920408d2020-05-14 00:07:03 -0500386 // For CPU- update com interface only when isCI true
387 if ((!isCpuModuleOnly) || (isCpuModuleOnly && isCI))
388 {
389 makeDbusCall<Binary>(
390 (INVENTORY_PATH +
391 singleInventory["inventoryPath"].get<std::string>()),
392 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
393 thisRecord.recKWd, thisRecord.kwdUpdatedData);
394 }
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600395
396 // process Common interface
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600397 processAndUpdateCI(singleInventory["inventoryPath"]
398 .get_ref<const nlohmann::json::string_t&>());
399 }
400
Alpana Kumari920408d2020-05-14 00:07:03 -0500401 if (isInheritEI)
402 {
403 if (isCpuModuleOnly)
404 {
405 makeDbusCall<Binary>(
406 (INVENTORY_PATH +
407 singleInventory["inventoryPath"].get<std::string>()),
408 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
409 thisRecord.recKWd, thisRecord.kwdUpdatedData);
410 }
411
412 // process extra interfaces
413 processAndUpdateEI(singleInventory,
414 singleInventory["inventoryPath"]
415 .get_ref<const nlohmann::json::string_t&>());
416 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600417 }
418}
419
SunnySrivastava198443306542020-04-01 02:50:20 -0500420void EditorImpl::expandLocationCode(const std::string& locationCodeType)
421{
422 std::string propertyFCorTM{};
423 std::string propertySE{};
424
425 if (locationCodeType == "fcs")
426 {
427 propertyFCorTM =
428 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
429 propertySE =
430 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
431 }
432 else if (locationCodeType == "mts")
433 {
434 propertyFCorTM =
435 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
436 propertySE =
437 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
438 }
439
440 const nlohmann::json& groupFRUS =
441 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
442 for (const auto& itemFRUS : groupFRUS.items())
443 {
444 const std::vector<nlohmann::json>& groupEEPROM =
445 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
446 for (const auto& itemEEPROM : groupEEPROM)
447 {
448 // check if the given item implements location code interface
449 if (itemEEPROM["extraInterfaces"].find(LOCATION_CODE_INF) !=
450 itemEEPROM["extraInterfaces"].end())
451 {
452 const std::string& unexpandedLocationCode =
453 itemEEPROM["extraInterfaces"][LOCATION_CODE_INF]
454 ["LocationCode"]
455 .get_ref<const nlohmann::json::string_t&>();
456 std::size_t idx = unexpandedLocationCode.find(locationCodeType);
457 if (idx != std::string::npos)
458 {
459 std::string expandedLoctionCode(unexpandedLocationCode);
460
461 if (locationCodeType == "fcs")
462 {
463 expandedLoctionCode.replace(
464 idx, 3,
465 propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
466 }
467 else if (locationCodeType == "mts")
468 {
469 std::replace(propertyFCorTM.begin(),
470 propertyFCorTM.end(), '-', '.');
471 expandedLoctionCode.replace(
472 idx, 3, propertyFCorTM + "." + propertySE);
473 }
474
475 // update the DBUS interface
476 makeDbusCall<std::string>(
477 (INVENTORY_PATH +
478 itemEEPROM["inventoryPath"]
479 .get_ref<const nlohmann::json::string_t&>()),
480 LOCATION_CODE_INF, "LocationCode", expandedLoctionCode);
481 }
482 }
483 }
484 }
485}
486
Alpana Kumari920408d2020-05-14 00:07:03 -0500487string EditorImpl::getSysPathForThisFruType(const string& moduleObjPath,
488 const string& fruType)
489{
490 string fruVpdPath;
491
492 // get all FRUs list
493 for (const auto& eachFru : jsonFile["frus"].items())
494 {
495 bool moduleObjPathMatched = false;
496 bool expectedFruFound = false;
497
498 for (const auto& eachInventory : eachFru.value())
499 {
500 const auto& thisObjectPath = eachInventory["inventoryPath"];
501
502 // "type" exists only in CPU module and FRU
503 if (eachInventory.find("type") != eachInventory.end())
504 {
505 // If inventory type is fruAndModule then set flag
506 if (eachInventory["type"] == fruType)
507 {
508 expectedFruFound = true;
509 }
510 }
511
512 if (thisObjectPath == moduleObjPath)
513 {
514 moduleObjPathMatched = true;
515 }
516 }
517
518 // If condition satisfies then collect this sys path and exit
519 if (expectedFruFound && moduleObjPathMatched)
520 {
521 fruVpdPath = eachFru.key();
522 break;
523 }
524 }
525
526 return fruVpdPath;
527}
528
529void EditorImpl::getVpdPathForCpu()
530{
531 isCI = false;
532 // keep a backup In case we need it later
533 inventory::Path vpdFilePathBackup = vpdFilePath;
534
535 // TODO 1:Temp hardcoded list. create it dynamically.
536 std::vector<std::string> commonIntVINIKwds = {"PN", "SN", "DR"};
537 std::vector<std::string> commonIntVR10Kwds = {"DC"};
538 std::unordered_map<std::string, std::vector<std::string>>
539 commonIntRecordsList = {{"VINI", commonIntVINIKwds},
540 {"VR10", commonIntVR10Kwds}};
541
542 // If requested Record&Kw is one among CI, then update 'FRU' type sys
543 // path, SPI2
544 unordered_map<std::string, vector<string>>::const_iterator isCommonInt =
545 commonIntRecordsList.find(thisRecord.recName);
546
547 if ((isCommonInt != commonIntRecordsList.end()) &&
548 (find(isCommonInt->second.begin(), isCommonInt->second.end(),
549 thisRecord.recKWd) != isCommonInt->second.end()))
550 {
551 isCI = true;
552 vpdFilePath = getSysPathForThisFruType(objPath, "fruAndModule");
553 }
554 else
555 {
556 for (const auto& eachFru : jsonFile["frus"].items())
557 {
558 for (const auto& eachInventory : eachFru.value())
559 {
560 if (eachInventory.find("type") != eachInventory.end())
561 {
562 const auto& thisObjectPath = eachInventory["inventoryPath"];
563 if ((eachInventory["type"] == "moduleOnly") &&
564 (eachInventory.value("inheritEI", true)) &&
565 (thisObjectPath == static_cast<string>(objPath)))
566 {
567 vpdFilePath = eachFru.key();
568 }
569 }
570 }
571 }
572 }
573 // If it is not a CPU fru then go ahead with default vpdFilePath from
574 // fruMap
575 if (vpdFilePath.empty())
576 {
577 vpdFilePath = vpdFilePathBackup;
578 }
579}
580
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600581void EditorImpl::updateKeyword(const Binary& kwdData)
582{
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500583 startOffset = 0;
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500584#ifndef ManagerTest
Alpana Kumari920408d2020-05-14 00:07:03 -0500585
586 getVpdPathForCpu();
587
Alpana Kumari920408d2020-05-14 00:07:03 -0500588 // check if offset present?
589 for (const auto& item : jsonFile["frus"][vpdFilePath])
590 {
591 if (item.find("offset") != item.end())
592 {
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500593 startOffset = item["offset"];
Alpana Kumari920408d2020-05-14 00:07:03 -0500594 }
595 }
596
597 // TODO: Figure out a better way to get max possible VPD size.
598 Binary completeVPDFile;
599 completeVPDFile.resize(65504);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600600 vpdFileStream.open(vpdFilePath,
601 std::ios::in | std::ios::out | std::ios::binary);
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500602
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500603 vpdFileStream.seekg(startOffset, ios_base::cur);
Alpana Kumari920408d2020-05-14 00:07:03 -0500604 vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]), 65504);
605 completeVPDFile.resize(vpdFileStream.gcount());
606 vpdFileStream.clear(std::ios_base::eofbit);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600607
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500608 vpdFile = completeVPDFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500609
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500610#else
Alpana Kumari920408d2020-05-14 00:07:03 -0500611
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500612 Binary completeVPDFile = vpdFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500613
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500614#endif
615 if (vpdFile.empty())
616 {
617 throw std::runtime_error("Invalid File");
618 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500619 auto iterator = vpdFile.cbegin();
620 std::advance(iterator, IPZ_DATA_START);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600621
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500622 Byte vpdType = *iterator;
623 if (vpdType == KW_VAL_PAIR_START_TAG)
624 {
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500625 ParserInterface* Iparser =
626 ParserFactory::getParser(std::move(completeVPDFile));
627 IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600628
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500629 try
630 {
631 if (ipzParser == nullptr)
632 {
633 throw std::runtime_error("Invalid cast");
634 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500635
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500636 ipzParser->processHeader();
637 delete ipzParser;
638 ipzParser = nullptr;
639 // ParserFactory::freeParser(Iparser);
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500640
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500641 // process VTOC for PTT rkwd
642 readVTOC();
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500643
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500644 // check record for keywrod
645 checkRecordForKwd();
646
647 // update the data to the file
648 updateData(kwdData);
649
650 // update the ECC data for the record once data has been updated
651 updateRecordECC();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500652#ifndef ManagerTest
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500653 // update the cache once data has been updated
654 updateCache();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500655#endif
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500656 }
657 catch (const std::exception& e)
658 {
659 if (ipzParser != nullptr)
660 {
661 delete ipzParser;
662 }
663 throw std::runtime_error(e.what());
664 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500665 return;
666 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600667}
668
669} // namespace editor
670} // namespace manager
671} // namespace vpd
672} // namespace openpower