blob: e5d698aa21e1cde6a6398de7f712eb20e714f6fe [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
SunnySrivastava19846d8314d2020-05-15 09:34:58 -05005#include "parser.hpp"
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06006#include "utils.hpp"
7
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06008#include "vpdecc/vpdecc.h"
9
10namespace openpower
11{
12namespace vpd
13{
14namespace manager
15{
16namespace editor
17{
18using namespace openpower::vpd::constants;
19
20void EditorImpl::checkPTForRecord(Binary::const_iterator& iterator,
21 Byte ptLength)
22{
23 // auto iterator = ptRecord.cbegin();
24 auto end = std::next(iterator, ptLength + 1);
25
26 // Look at each entry in the PT keyword for the record name
27 while (iterator < end)
28 {
29 auto stop = std::next(iterator, lengths::RECORD_NAME);
30 std::string record(iterator, stop);
31
32 if (record == thisRecord.recName)
33 {
34 // Skip record name and record type
35 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
36
37 // Get record offset
38 thisRecord.recOffset = readUInt16LE(iterator);
39
40 // pass the record offset length to read record length
41 std::advance(iterator, lengths::RECORD_OFFSET);
42 thisRecord.recSize = readUInt16LE(iterator);
43
44 std::advance(iterator, lengths::RECORD_LENGTH);
45 thisRecord.recECCoffset = readUInt16LE(iterator);
46
47 ECCLength len;
48 std::advance(iterator, lengths::RECORD_ECC_OFFSET);
49 len = readUInt16LE(iterator);
50 thisRecord.recECCLength = len;
51
52 // once we find the record we don't need to look further
53 return;
54 }
55 else
56 {
57 // Jump the record
58 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType) +
59 sizeof(RecordOffset) +
60 sizeof(RecordLength) +
61 sizeof(ECCOffset) + sizeof(ECCLength));
62 }
63 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060064 // imples the record was not found
65 throw std::runtime_error("Record not found");
66}
67
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050068void EditorImpl::updateData(const Binary& kwdData)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060069{
70 std::size_t lengthToUpdate = kwdData.size() <= thisRecord.kwdDataLength
71 ? kwdData.size()
72 : thisRecord.kwdDataLength;
73
74 auto iteratorToNewdata = kwdData.cbegin();
75 auto end = iteratorToNewdata;
76 std::advance(end, lengthToUpdate);
77
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050078 // update data in file buffer as it will be needed to update ECC
79 // avoiding extra stream operation here
80 auto iteratorToKWdData = vpdFile.begin();
81 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
82 std::copy(iteratorToNewdata, end, iteratorToKWdData);
83
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -050084#ifdef ManagerTest
85 auto startItr = vpdFile.begin();
86 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
87 auto endItr = startItr;
88 std::advance(endItr, thisRecord.kwdDataLength);
89
90 Binary updatedData(startItr, endItr);
91 if (updatedData == kwdData)
92 {
93 throw std::runtime_error("Data updated successfully");
94 }
95#else
96
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050097 // update data in EEPROM as well. As we will not write complete file back
Alpana Kumari920408d2020-05-14 00:07:03 -050098 vpdFileStream.seekp(offset + thisRecord.kwDataOffset, std::ios::beg);
99
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500100 iteratorToNewdata = kwdData.cbegin();
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600101 std::copy(iteratorToNewdata, end,
102 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500103
104 // get a hold to new data in case encoding is needed
105 thisRecord.kwdUpdatedData.resize(thisRecord.kwdDataLength);
106 auto itrToKWdData = vpdFile.cbegin();
107 std::advance(itrToKWdData, thisRecord.kwDataOffset);
108 auto kwdDataEnd = itrToKWdData;
109 std::advance(kwdDataEnd, thisRecord.kwdDataLength);
110 std::copy(itrToKWdData, kwdDataEnd, thisRecord.kwdUpdatedData.begin());
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500111#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600112}
113
114void EditorImpl::checkRecordForKwd()
115{
116 RecordOffset recOffset = thisRecord.recOffset;
117
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500118 // Amount to skip for record ID, size, and the RT keyword
119 constexpr auto skipBeg = sizeof(RecordId) + sizeof(RecordSize) +
120 lengths::KW_NAME + sizeof(KwSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600121
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500122 auto iterator = vpdFile.cbegin();
123 std::advance(iterator, recOffset + skipBeg + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600124
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500125 auto end = iterator;
126 std::advance(end, thisRecord.recSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600127 std::size_t dataLength = 0;
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500128
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600129 while (iterator < end)
130 {
131 // Note keyword name
132 std::string kw(iterator, iterator + lengths::KW_NAME);
133
134 // Check if the Keyword starts with '#'
135 char kwNameStart = *iterator;
136 std::advance(iterator, lengths::KW_NAME);
137
138 // if keyword starts with #
139 if (POUND_KW == kwNameStart)
140 {
141 // Note existing keyword data length
142 dataLength = readUInt16LE(iterator);
143
144 // Jump past 2Byte keyword length + data
145 std::advance(iterator, sizeof(PoundKwSize));
146 }
147 else
148 {
149 // Note existing keyword data length
150 dataLength = *iterator;
151
152 // Jump past keyword length and data
153 std::advance(iterator, sizeof(KwSize));
154 }
155
156 if (thisRecord.recKWd == kw)
157 {
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500158 thisRecord.kwDataOffset = std::distance(vpdFile.cbegin(), iterator);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600159 thisRecord.kwdDataLength = dataLength;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600160 return;
161 }
162
163 // jump the data of current kwd to point to next kwd name
164 std::advance(iterator, dataLength);
165 }
166
167 throw std::runtime_error("Keyword not found");
168}
169
170void EditorImpl::updateRecordECC()
171{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500172 auto itrToRecordData = vpdFile.cbegin();
173 std::advance(itrToRecordData, thisRecord.recOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600174
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500175 auto itrToRecordECC = vpdFile.cbegin();
176 std::advance(itrToRecordECC, thisRecord.recECCoffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600177
178 auto l_status = vpdecc_create_ecc(
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500179 const_cast<uint8_t*>(&itrToRecordData[0]), thisRecord.recSize,
180 const_cast<uint8_t*>(&itrToRecordECC[0]), &thisRecord.recECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600181 if (l_status != VPD_ECC_OK)
182 {
183 throw std::runtime_error("Ecc update failed");
184 }
185
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500186 auto end = itrToRecordECC;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600187 std::advance(end, thisRecord.recECCLength);
188
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500189#ifndef ManagerTest
Alpana Kumari920408d2020-05-14 00:07:03 -0500190 vpdFileStream.seekp(offset + thisRecord.recECCoffset, std::ios::beg);
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500191 std::copy(itrToRecordECC, end,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600192 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500193#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600194}
195
196auto EditorImpl::getValue(offsets::Offsets offset)
197{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500198 auto itr = vpdFile.cbegin();
199 std::advance(itr, offset);
200 LE2ByteData lowByte = *itr;
201 LE2ByteData highByte = *(itr + 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600202 lowByte |= (highByte << 8);
203
204 return lowByte;
205}
206
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500207void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
208 Binary::const_iterator& itrToECCData,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600209 RecordLength recLength, ECCLength eccLength)
210{
211 auto l_status =
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500212 vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
213 const_cast<uint8_t*>(&itrToECCData[0]), eccLength);
214
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600215 if (l_status != VPD_ECC_OK)
216 {
217 throw std::runtime_error("Ecc check failed for VTOC");
218 }
219}
220
221void EditorImpl::readVTOC()
222{
223 // read VTOC offset
224 RecordOffset tocOffset = getValue(offsets::VTOC_PTR);
225
226 // read VTOC record length
227 RecordLength tocLength = getValue(offsets::VTOC_REC_LEN);
228
229 // read TOC ecc offset
230 ECCOffset tocECCOffset = getValue(offsets::VTOC_ECC_OFF);
231
232 // read TOC ecc length
233 ECCLength tocECCLength = getValue(offsets::VTOC_ECC_LEN);
234
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500235 auto itrToRecord = vpdFile.cbegin();
236 std::advance(itrToRecord, tocOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600237
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500238 auto iteratorToECC = vpdFile.cbegin();
239 std::advance(iteratorToECC, tocECCOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600240
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500241 // validate ecc for the record
242 checkECC(itrToRecord, iteratorToECC, tocLength, tocECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600243
244 // to get to the record name.
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500245 std::advance(itrToRecord, sizeof(RecordId) + sizeof(RecordSize) +
246 // Skip past the RT keyword, which contains
247 // the record name.
248 lengths::KW_NAME + sizeof(KwSize));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600249
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500250 std::string recordName(itrToRecord, itrToRecord + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600251
252 if ("VTOC" != recordName)
253 {
254 throw std::runtime_error("VTOC record not found");
255 }
256
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600257 // jump to length of PT kwd
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500258 std::advance(itrToRecord, lengths::RECORD_NAME + lengths::KW_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600259
260 // Note size of PT
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500261 Byte ptLen = *itrToRecord;
262 std::advance(itrToRecord, 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600263
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500264 checkPTForRecord(itrToRecord, ptLen);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600265}
266
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600267template <typename T>
268void EditorImpl::makeDbusCall(const std::string& object,
269 const std::string& interface,
270 const std::string& property,
271 const std::variant<T>& data)
272{
273 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500274 auto properties =
275 bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
276 "org.freedesktop.DBus.Properties", "Set");
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600277 properties.append(interface);
278 properties.append(property);
279 properties.append(data);
280
281 auto result = bus.call(properties);
282
283 if (result.is_method_error())
284 {
285 throw std::runtime_error("bus call failed");
286 }
287}
288
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600289void EditorImpl::processAndUpdateCI(const std::string& objectPath)
290{
291 for (auto& commonInterface : jsonFile["commonInterfaces"].items())
292 {
293 for (auto& ciPropertyList : commonInterface.value().items())
294 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600295 if (ciPropertyList.value().type() ==
296 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600297 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600298 if ((ciPropertyList.value().value("recordName", "") ==
299 thisRecord.recName) &&
300 (ciPropertyList.value().value("keywordName", "") ==
301 thisRecord.recKWd))
302 {
303 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
304 thisRecord.kwdUpdatedData.end());
305
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500306 makeDbusCall<std::string>((INVENTORY_PATH + objectPath),
307 commonInterface.key(),
308 ciPropertyList.key(), kwdData);
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600309 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600310 }
311 }
312 }
313}
314
315void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
316 const inventory::Path& objPath)
317{
318 for (const auto& extraInterface : Inventory["extraInterfaces"].items())
319 {
320 if (extraInterface.value() != NULL)
321 {
322 for (const auto& eiPropertyList : extraInterface.value().items())
323 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600324 if (eiPropertyList.value().type() ==
325 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600326 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600327 if ((eiPropertyList.value().value("recordName", "") ==
328 thisRecord.recName) &&
329 ((eiPropertyList.value().value("keywordName", "") ==
330 thisRecord.recKWd)))
331 {
332 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
333 thisRecord.kwdUpdatedData.end());
334 makeDbusCall<std::string>(
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500335 (INVENTORY_PATH + objPath), extraInterface.key(),
336 eiPropertyList.key(),
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600337 encodeKeyword(kwdData, eiPropertyList.value().value(
338 "encoding", "")));
339 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600340 }
341 }
342 }
343 }
344}
345
346void EditorImpl::updateCache()
347{
348 const std::vector<nlohmann::json>& groupEEPROM =
349 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
350
351 // iterate through all the inventories for this file path
352 for (const auto& singleInventory : groupEEPROM)
353 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600354 // by default inherit property is true
355 bool isInherit = true;
Alpana Kumari920408d2020-05-14 00:07:03 -0500356 bool isInheritEI = true;
357 bool isCpuModuleOnly = false;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600358
359 if (singleInventory.find("inherit") != singleInventory.end())
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600360 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600361 isInherit = singleInventory["inherit"].get<bool>();
362 }
363
Alpana Kumari920408d2020-05-14 00:07:03 -0500364 if (singleInventory.find("inheritEI") != singleInventory.end())
365 {
366 isInheritEI = singleInventory["inheritEI"].get<bool>();
367 }
368
369 // "type" exists only in CPU module and FRU
370 if (singleInventory.find("type") != singleInventory.end())
371 {
372 if (singleInventory["type"] == "moduleOnly")
373 {
374 isCpuModuleOnly = true;
375 }
376 }
377
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600378 if (isInherit)
379 {
380 // update com interface
Alpana Kumari920408d2020-05-14 00:07:03 -0500381 // For CPU- update com interface only when isCI true
382 if ((!isCpuModuleOnly) || (isCpuModuleOnly && isCI))
383 {
384 makeDbusCall<Binary>(
385 (INVENTORY_PATH +
386 singleInventory["inventoryPath"].get<std::string>()),
387 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
388 thisRecord.recKWd, thisRecord.kwdUpdatedData);
389 }
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600390
391 // process Common interface
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600392 processAndUpdateCI(singleInventory["inventoryPath"]
393 .get_ref<const nlohmann::json::string_t&>());
394 }
395
Alpana Kumari920408d2020-05-14 00:07:03 -0500396 if (isInheritEI)
397 {
398 if (isCpuModuleOnly)
399 {
400 makeDbusCall<Binary>(
401 (INVENTORY_PATH +
402 singleInventory["inventoryPath"].get<std::string>()),
403 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
404 thisRecord.recKWd, thisRecord.kwdUpdatedData);
405 }
406
407 // process extra interfaces
408 processAndUpdateEI(singleInventory,
409 singleInventory["inventoryPath"]
410 .get_ref<const nlohmann::json::string_t&>());
411 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600412 }
413}
414
SunnySrivastava198443306542020-04-01 02:50:20 -0500415void EditorImpl::expandLocationCode(const std::string& locationCodeType)
416{
417 std::string propertyFCorTM{};
418 std::string propertySE{};
419
420 if (locationCodeType == "fcs")
421 {
422 propertyFCorTM =
423 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
424 propertySE =
425 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
426 }
427 else if (locationCodeType == "mts")
428 {
429 propertyFCorTM =
430 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
431 propertySE =
432 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
433 }
434
435 const nlohmann::json& groupFRUS =
436 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
437 for (const auto& itemFRUS : groupFRUS.items())
438 {
439 const std::vector<nlohmann::json>& groupEEPROM =
440 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
441 for (const auto& itemEEPROM : groupEEPROM)
442 {
443 // check if the given item implements location code interface
444 if (itemEEPROM["extraInterfaces"].find(LOCATION_CODE_INF) !=
445 itemEEPROM["extraInterfaces"].end())
446 {
447 const std::string& unexpandedLocationCode =
448 itemEEPROM["extraInterfaces"][LOCATION_CODE_INF]
449 ["LocationCode"]
450 .get_ref<const nlohmann::json::string_t&>();
451 std::size_t idx = unexpandedLocationCode.find(locationCodeType);
452 if (idx != std::string::npos)
453 {
454 std::string expandedLoctionCode(unexpandedLocationCode);
455
456 if (locationCodeType == "fcs")
457 {
458 expandedLoctionCode.replace(
459 idx, 3,
460 propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
461 }
462 else if (locationCodeType == "mts")
463 {
464 std::replace(propertyFCorTM.begin(),
465 propertyFCorTM.end(), '-', '.');
466 expandedLoctionCode.replace(
467 idx, 3, propertyFCorTM + "." + propertySE);
468 }
469
470 // update the DBUS interface
471 makeDbusCall<std::string>(
472 (INVENTORY_PATH +
473 itemEEPROM["inventoryPath"]
474 .get_ref<const nlohmann::json::string_t&>()),
475 LOCATION_CODE_INF, "LocationCode", expandedLoctionCode);
476 }
477 }
478 }
479 }
480}
481
Alpana Kumari920408d2020-05-14 00:07:03 -0500482string EditorImpl::getSysPathForThisFruType(const string& moduleObjPath,
483 const string& fruType)
484{
485 string fruVpdPath;
486
487 // get all FRUs list
488 for (const auto& eachFru : jsonFile["frus"].items())
489 {
490 bool moduleObjPathMatched = false;
491 bool expectedFruFound = false;
492
493 for (const auto& eachInventory : eachFru.value())
494 {
495 const auto& thisObjectPath = eachInventory["inventoryPath"];
496
497 // "type" exists only in CPU module and FRU
498 if (eachInventory.find("type") != eachInventory.end())
499 {
500 // If inventory type is fruAndModule then set flag
501 if (eachInventory["type"] == fruType)
502 {
503 expectedFruFound = true;
504 }
505 }
506
507 if (thisObjectPath == moduleObjPath)
508 {
509 moduleObjPathMatched = true;
510 }
511 }
512
513 // If condition satisfies then collect this sys path and exit
514 if (expectedFruFound && moduleObjPathMatched)
515 {
516 fruVpdPath = eachFru.key();
517 break;
518 }
519 }
520
521 return fruVpdPath;
522}
523
524void EditorImpl::getVpdPathForCpu()
525{
526 isCI = false;
527 // keep a backup In case we need it later
528 inventory::Path vpdFilePathBackup = vpdFilePath;
529
530 // TODO 1:Temp hardcoded list. create it dynamically.
531 std::vector<std::string> commonIntVINIKwds = {"PN", "SN", "DR"};
532 std::vector<std::string> commonIntVR10Kwds = {"DC"};
533 std::unordered_map<std::string, std::vector<std::string>>
534 commonIntRecordsList = {{"VINI", commonIntVINIKwds},
535 {"VR10", commonIntVR10Kwds}};
536
537 // If requested Record&Kw is one among CI, then update 'FRU' type sys
538 // path, SPI2
539 unordered_map<std::string, vector<string>>::const_iterator isCommonInt =
540 commonIntRecordsList.find(thisRecord.recName);
541
542 if ((isCommonInt != commonIntRecordsList.end()) &&
543 (find(isCommonInt->second.begin(), isCommonInt->second.end(),
544 thisRecord.recKWd) != isCommonInt->second.end()))
545 {
546 isCI = true;
547 vpdFilePath = getSysPathForThisFruType(objPath, "fruAndModule");
548 }
549 else
550 {
551 for (const auto& eachFru : jsonFile["frus"].items())
552 {
553 for (const auto& eachInventory : eachFru.value())
554 {
555 if (eachInventory.find("type") != eachInventory.end())
556 {
557 const auto& thisObjectPath = eachInventory["inventoryPath"];
558 if ((eachInventory["type"] == "moduleOnly") &&
559 (eachInventory.value("inheritEI", true)) &&
560 (thisObjectPath == static_cast<string>(objPath)))
561 {
562 vpdFilePath = eachFru.key();
563 }
564 }
565 }
566 }
567 }
568 // If it is not a CPU fru then go ahead with default vpdFilePath from
569 // fruMap
570 if (vpdFilePath.empty())
571 {
572 vpdFilePath = vpdFilePathBackup;
573 }
574}
575
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600576void EditorImpl::updateKeyword(const Binary& kwdData)
577{
Alpana Kumari920408d2020-05-14 00:07:03 -0500578 offset = 0;
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500579#ifndef ManagerTest
Alpana Kumari920408d2020-05-14 00:07:03 -0500580
581 getVpdPathForCpu();
582
583 uint32_t offset = 0;
584 // check if offset present?
585 for (const auto& item : jsonFile["frus"][vpdFilePath])
586 {
587 if (item.find("offset") != item.end())
588 {
589 offset = item["offset"];
590 }
591 }
592
593 // TODO: Figure out a better way to get max possible VPD size.
594 Binary completeVPDFile;
595 completeVPDFile.resize(65504);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600596 vpdFileStream.open(vpdFilePath,
597 std::ios::in | std::ios::out | std::ios::binary);
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500598
Alpana Kumari920408d2020-05-14 00:07:03 -0500599 vpdFileStream.seekg(offset, ios_base::cur);
600 vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]), 65504);
601 completeVPDFile.resize(vpdFileStream.gcount());
602 vpdFileStream.clear(std::ios_base::eofbit);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600603
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500604 vpdFile = completeVPDFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500605
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500606#else
Alpana Kumari920408d2020-05-14 00:07:03 -0500607
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500608 Binary completeVPDFile = vpdFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500609
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500610#endif
611 if (vpdFile.empty())
612 {
613 throw std::runtime_error("Invalid File");
614 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500615 auto iterator = vpdFile.cbegin();
616 std::advance(iterator, IPZ_DATA_START);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600617
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500618 Byte vpdType = *iterator;
619 if (vpdType == KW_VAL_PAIR_START_TAG)
620 {
621 openpower::vpd::keyword::editor::processHeader(
622 std::move(completeVPDFile));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600623
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500624 // process VTOC for PTT rkwd
625 readVTOC();
626
627 // check record for keywrod
628 checkRecordForKwd();
629
630 // update the data to the file
631 updateData(kwdData);
632
633 // update the ECC data for the record once data has been updated
634 updateRecordECC();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500635#ifndef ManagerTest
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600636 // update the cache once data has been updated
637 updateCache();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500638#endif
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500639 return;
640 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600641}
642
643} // namespace editor
644} // namespace manager
645} // namespace vpd
646} // namespace openpower