blob: 57fed6067481a45ef7e84d8dec91427ccaaad3c6 [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
Alpana Kumari414d5ae2021-03-04 21:06:35 +00005#include "common_utility.hpp"
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05006#include "ibm_vpd_utils.hpp"
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05007#include "ipz_parser.hpp"
8#include "parser_factory.hpp"
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06009
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060010#include "vpdecc/vpdecc.h"
11
SunnySrivastava1984e12b1812020-05-26 02:23:11 -050012using namespace openpower::vpd::parser::interface;
13using namespace openpower::vpd::constants;
14using namespace openpower::vpd::parser::factory;
15using namespace openpower::vpd::ipz::parser;
16
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060017namespace openpower
18{
19namespace vpd
20{
21namespace manager
22{
23namespace editor
24{
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060025
26void EditorImpl::checkPTForRecord(Binary::const_iterator& iterator,
27 Byte ptLength)
28{
29 // auto iterator = ptRecord.cbegin();
30 auto end = std::next(iterator, ptLength + 1);
31
32 // Look at each entry in the PT keyword for the record name
33 while (iterator < end)
34 {
35 auto stop = std::next(iterator, lengths::RECORD_NAME);
36 std::string record(iterator, stop);
37
38 if (record == thisRecord.recName)
39 {
40 // Skip record name and record type
41 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
42
43 // Get record offset
44 thisRecord.recOffset = readUInt16LE(iterator);
45
46 // pass the record offset length to read record length
47 std::advance(iterator, lengths::RECORD_OFFSET);
48 thisRecord.recSize = readUInt16LE(iterator);
49
50 std::advance(iterator, lengths::RECORD_LENGTH);
51 thisRecord.recECCoffset = readUInt16LE(iterator);
52
53 ECCLength len;
54 std::advance(iterator, lengths::RECORD_ECC_OFFSET);
55 len = readUInt16LE(iterator);
56 thisRecord.recECCLength = len;
57
58 // once we find the record we don't need to look further
59 return;
60 }
61 else
62 {
63 // Jump the record
64 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType) +
65 sizeof(RecordOffset) +
66 sizeof(RecordLength) +
67 sizeof(ECCOffset) + sizeof(ECCLength));
68 }
69 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060070 // imples the record was not found
71 throw std::runtime_error("Record not found");
72}
73
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050074void EditorImpl::updateData(const Binary& kwdData)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060075{
76 std::size_t lengthToUpdate = kwdData.size() <= thisRecord.kwdDataLength
77 ? kwdData.size()
78 : thisRecord.kwdDataLength;
79
80 auto iteratorToNewdata = kwdData.cbegin();
81 auto end = iteratorToNewdata;
82 std::advance(end, lengthToUpdate);
83
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050084 // update data in file buffer as it will be needed to update ECC
85 // avoiding extra stream operation here
86 auto iteratorToKWdData = vpdFile.begin();
87 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
88 std::copy(iteratorToNewdata, end, iteratorToKWdData);
89
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -050090#ifdef ManagerTest
91 auto startItr = vpdFile.begin();
92 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
93 auto endItr = startItr;
94 std::advance(endItr, thisRecord.kwdDataLength);
95
96 Binary updatedData(startItr, endItr);
97 if (updatedData == kwdData)
98 {
99 throw std::runtime_error("Data updated successfully");
100 }
101#else
102
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500103 // update data in EEPROM as well. As we will not write complete file back
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500104 vpdFileStream.seekp(startOffset + thisRecord.kwDataOffset, std::ios::beg);
Alpana Kumari920408d2020-05-14 00:07:03 -0500105
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500106 iteratorToNewdata = kwdData.cbegin();
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600107 std::copy(iteratorToNewdata, end,
108 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500109
110 // get a hold to new data in case encoding is needed
111 thisRecord.kwdUpdatedData.resize(thisRecord.kwdDataLength);
112 auto itrToKWdData = vpdFile.cbegin();
113 std::advance(itrToKWdData, thisRecord.kwDataOffset);
114 auto kwdDataEnd = itrToKWdData;
115 std::advance(kwdDataEnd, thisRecord.kwdDataLength);
116 std::copy(itrToKWdData, kwdDataEnd, thisRecord.kwdUpdatedData.begin());
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500117#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600118}
119
120void EditorImpl::checkRecordForKwd()
121{
122 RecordOffset recOffset = thisRecord.recOffset;
123
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500124 // Amount to skip for record ID, size, and the RT keyword
125 constexpr auto skipBeg = sizeof(RecordId) + sizeof(RecordSize) +
126 lengths::KW_NAME + sizeof(KwSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600127
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500128 auto iterator = vpdFile.cbegin();
129 std::advance(iterator, recOffset + skipBeg + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600130
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500131 auto end = iterator;
132 std::advance(end, thisRecord.recSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600133 std::size_t dataLength = 0;
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500134
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600135 while (iterator < end)
136 {
137 // Note keyword name
138 std::string kw(iterator, iterator + lengths::KW_NAME);
139
140 // Check if the Keyword starts with '#'
141 char kwNameStart = *iterator;
142 std::advance(iterator, lengths::KW_NAME);
143
144 // if keyword starts with #
145 if (POUND_KW == kwNameStart)
146 {
147 // Note existing keyword data length
148 dataLength = readUInt16LE(iterator);
149
150 // Jump past 2Byte keyword length + data
151 std::advance(iterator, sizeof(PoundKwSize));
152 }
153 else
154 {
155 // Note existing keyword data length
156 dataLength = *iterator;
157
158 // Jump past keyword length and data
159 std::advance(iterator, sizeof(KwSize));
160 }
161
162 if (thisRecord.recKWd == kw)
163 {
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500164 thisRecord.kwDataOffset = std::distance(vpdFile.cbegin(), iterator);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600165 thisRecord.kwdDataLength = dataLength;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600166 return;
167 }
168
169 // jump the data of current kwd to point to next kwd name
170 std::advance(iterator, dataLength);
171 }
172
173 throw std::runtime_error("Keyword not found");
174}
175
176void EditorImpl::updateRecordECC()
177{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500178 auto itrToRecordData = vpdFile.cbegin();
179 std::advance(itrToRecordData, thisRecord.recOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600180
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500181 auto itrToRecordECC = vpdFile.cbegin();
182 std::advance(itrToRecordECC, thisRecord.recECCoffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600183
184 auto l_status = vpdecc_create_ecc(
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500185 const_cast<uint8_t*>(&itrToRecordData[0]), thisRecord.recSize,
186 const_cast<uint8_t*>(&itrToRecordECC[0]), &thisRecord.recECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600187 if (l_status != VPD_ECC_OK)
188 {
189 throw std::runtime_error("Ecc update failed");
190 }
191
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500192 auto end = itrToRecordECC;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600193 std::advance(end, thisRecord.recECCLength);
194
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500195#ifndef ManagerTest
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500196 vpdFileStream.seekp(startOffset + thisRecord.recECCoffset, std::ios::beg);
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500197 std::copy(itrToRecordECC, end,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600198 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500199#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600200}
201
202auto EditorImpl::getValue(offsets::Offsets offset)
203{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500204 auto itr = vpdFile.cbegin();
205 std::advance(itr, offset);
206 LE2ByteData lowByte = *itr;
207 LE2ByteData highByte = *(itr + 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600208 lowByte |= (highByte << 8);
209
210 return lowByte;
211}
212
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500213void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
214 Binary::const_iterator& itrToECCData,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600215 RecordLength recLength, ECCLength eccLength)
216{
217 auto l_status =
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500218 vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
219 const_cast<uint8_t*>(&itrToECCData[0]), eccLength);
220
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600221 if (l_status != VPD_ECC_OK)
222 {
223 throw std::runtime_error("Ecc check failed for VTOC");
224 }
225}
226
227void EditorImpl::readVTOC()
228{
229 // read VTOC offset
230 RecordOffset tocOffset = getValue(offsets::VTOC_PTR);
231
232 // read VTOC record length
233 RecordLength tocLength = getValue(offsets::VTOC_REC_LEN);
234
235 // read TOC ecc offset
236 ECCOffset tocECCOffset = getValue(offsets::VTOC_ECC_OFF);
237
238 // read TOC ecc length
239 ECCLength tocECCLength = getValue(offsets::VTOC_ECC_LEN);
240
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500241 auto itrToRecord = vpdFile.cbegin();
242 std::advance(itrToRecord, tocOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600243
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500244 auto iteratorToECC = vpdFile.cbegin();
245 std::advance(iteratorToECC, tocECCOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600246
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500247 // validate ecc for the record
248 checkECC(itrToRecord, iteratorToECC, tocLength, tocECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600249
250 // to get to the record name.
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500251 std::advance(itrToRecord, sizeof(RecordId) + sizeof(RecordSize) +
252 // Skip past the RT keyword, which contains
253 // the record name.
254 lengths::KW_NAME + sizeof(KwSize));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600255
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500256 std::string recordName(itrToRecord, itrToRecord + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600257
258 if ("VTOC" != recordName)
259 {
260 throw std::runtime_error("VTOC record not found");
261 }
262
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600263 // jump to length of PT kwd
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500264 std::advance(itrToRecord, lengths::RECORD_NAME + lengths::KW_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600265
266 // Note size of PT
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500267 Byte ptLen = *itrToRecord;
268 std::advance(itrToRecord, 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600269
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500270 checkPTForRecord(itrToRecord, ptLen);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600271}
272
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600273template <typename T>
274void EditorImpl::makeDbusCall(const std::string& object,
275 const std::string& interface,
276 const std::string& property,
277 const std::variant<T>& data)
278{
279 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500280 auto properties =
281 bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
282 "org.freedesktop.DBus.Properties", "Set");
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600283 properties.append(interface);
284 properties.append(property);
285 properties.append(data);
286
287 auto result = bus.call(properties);
288
289 if (result.is_method_error())
290 {
291 throw std::runtime_error("bus call failed");
292 }
293}
294
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600295void EditorImpl::processAndUpdateCI(const std::string& objectPath)
296{
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000297 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600298 for (auto& commonInterface : jsonFile["commonInterfaces"].items())
299 {
300 for (auto& ciPropertyList : commonInterface.value().items())
301 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600302 if (ciPropertyList.value().type() ==
303 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600304 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600305 if ((ciPropertyList.value().value("recordName", "") ==
306 thisRecord.recName) &&
307 (ciPropertyList.value().value("keywordName", "") ==
308 thisRecord.recKWd))
309 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000310 inventory::PropertyMap prop;
311 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600312 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
313 thisRecord.kwdUpdatedData.end());
314
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000315 prop.emplace(ciPropertyList.key(), move(kwdData));
316 interfaces.emplace(commonInterface.key(), move(prop));
317 objects.emplace(objectPath, move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600318 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600319 }
320 }
321 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000322 // Notify PIM
323 common::utility::callPIM(move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600324}
325
326void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
327 const inventory::Path& objPath)
328{
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000329 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600330 for (const auto& extraInterface : Inventory["extraInterfaces"].items())
331 {
332 if (extraInterface.value() != NULL)
333 {
334 for (const auto& eiPropertyList : extraInterface.value().items())
335 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600336 if (eiPropertyList.value().type() ==
337 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600338 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600339 if ((eiPropertyList.value().value("recordName", "") ==
340 thisRecord.recName) &&
341 ((eiPropertyList.value().value("keywordName", "") ==
342 thisRecord.recKWd)))
343 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000344 inventory::PropertyMap prop;
345 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600346 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
347 thisRecord.kwdUpdatedData.end());
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000348 encodeKeyword(kwdData, eiPropertyList.value().value(
349 "encoding", ""));
350
351 prop.emplace(eiPropertyList.key(), move(kwdData));
352 interfaces.emplace(extraInterface.key(), move(prop));
353 objects.emplace(objPath, move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600354 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600355 }
356 }
357 }
358 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000359 // Notify PIM
360 common::utility::callPIM(move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600361}
362
363void EditorImpl::updateCache()
364{
365 const std::vector<nlohmann::json>& groupEEPROM =
366 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
367
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000368 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600369 // iterate through all the inventories for this file path
370 for (const auto& singleInventory : groupEEPROM)
371 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000372 inventory::PropertyMap prop;
373 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600374 // by default inherit property is true
375 bool isInherit = true;
Alpana Kumari920408d2020-05-14 00:07:03 -0500376 bool isInheritEI = true;
377 bool isCpuModuleOnly = false;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600378
379 if (singleInventory.find("inherit") != singleInventory.end())
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600380 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600381 isInherit = singleInventory["inherit"].get<bool>();
382 }
383
Alpana Kumari920408d2020-05-14 00:07:03 -0500384 if (singleInventory.find("inheritEI") != singleInventory.end())
385 {
386 isInheritEI = singleInventory["inheritEI"].get<bool>();
387 }
388
389 // "type" exists only in CPU module and FRU
390 if (singleInventory.find("type") != singleInventory.end())
391 {
392 if (singleInventory["type"] == "moduleOnly")
393 {
394 isCpuModuleOnly = true;
395 }
396 }
397
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600398 if (isInherit)
399 {
400 // update com interface
Alpana Kumari920408d2020-05-14 00:07:03 -0500401 // For CPU- update com interface only when isCI true
402 if ((!isCpuModuleOnly) || (isCpuModuleOnly && isCI))
403 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000404 prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
405 interfaces.emplace(
Alpana Kumari920408d2020-05-14 00:07:03 -0500406 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000407 move(prop));
408 objects.emplace(
409 (singleInventory["inventoryPath"].get<std::string>()),
410 move(interfaces));
Alpana Kumari920408d2020-05-14 00:07:03 -0500411 }
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600412
413 // process Common interface
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600414 processAndUpdateCI(singleInventory["inventoryPath"]
415 .get_ref<const nlohmann::json::string_t&>());
416 }
417
Alpana Kumari920408d2020-05-14 00:07:03 -0500418 if (isInheritEI)
419 {
420 if (isCpuModuleOnly)
421 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000422 prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
423 interfaces.emplace(
Alpana Kumari920408d2020-05-14 00:07:03 -0500424 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000425 move(prop));
426 objects.emplace(
427 (singleInventory["inventoryPath"].get<std::string>()),
428 move(interfaces));
Alpana Kumari920408d2020-05-14 00:07:03 -0500429 }
430
431 // process extra interfaces
432 processAndUpdateEI(singleInventory,
433 singleInventory["inventoryPath"]
434 .get_ref<const nlohmann::json::string_t&>());
435 }
Sunny Srivastava26d6c142021-11-03 15:19:02 -0500436
437 // check if we need to copy some specific records in this case.
438 if (singleInventory.find("copyRecords") != singleInventory.end())
439 {
440 if (find(singleInventory["copyRecords"].begin(),
441 singleInventory["copyRecords"].end(),
442 thisRecord.recName) !=
443 singleInventory["copyRecords"].end())
444 {
445 prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
446 interfaces.emplace(
447 (IPZ_INTERFACE + std::string{"."} + thisRecord.recName),
448 move(prop));
449 objects.emplace(
450 (singleInventory["inventoryPath"].get<std::string>()),
451 move(interfaces));
452 }
453 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600454 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000455 // Notify PIM
456 common::utility::callPIM(move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600457}
458
SunnySrivastava198443306542020-04-01 02:50:20 -0500459void EditorImpl::expandLocationCode(const std::string& locationCodeType)
460{
461 std::string propertyFCorTM{};
462 std::string propertySE{};
463
464 if (locationCodeType == "fcs")
465 {
466 propertyFCorTM =
467 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
468 propertySE =
469 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
470 }
471 else if (locationCodeType == "mts")
472 {
473 propertyFCorTM =
474 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
475 propertySE =
476 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
477 }
478
479 const nlohmann::json& groupFRUS =
480 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000481 inventory::ObjectMap objects;
482
SunnySrivastava198443306542020-04-01 02:50:20 -0500483 for (const auto& itemFRUS : groupFRUS.items())
484 {
485 const std::vector<nlohmann::json>& groupEEPROM =
486 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
487 for (const auto& itemEEPROM : groupEEPROM)
488 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000489 inventory::PropertyMap prop;
490 inventory::InterfaceMap interfaces;
491 const auto& objectPath = itemEEPROM["inventoryPath"];
492 sdbusplus::message::object_path object(objectPath);
493
SunnySrivastava198443306542020-04-01 02:50:20 -0500494 // check if the given item implements location code interface
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000495 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
SunnySrivastava198443306542020-04-01 02:50:20 -0500496 itemEEPROM["extraInterfaces"].end())
497 {
498 const std::string& unexpandedLocationCode =
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000499 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
SunnySrivastava198443306542020-04-01 02:50:20 -0500500 ["LocationCode"]
501 .get_ref<const nlohmann::json::string_t&>();
502 std::size_t idx = unexpandedLocationCode.find(locationCodeType);
503 if (idx != std::string::npos)
504 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000505 std::string expandedLocationCode(unexpandedLocationCode);
SunnySrivastava198443306542020-04-01 02:50:20 -0500506
507 if (locationCodeType == "fcs")
508 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000509 expandedLocationCode.replace(
SunnySrivastava198443306542020-04-01 02:50:20 -0500510 idx, 3,
511 propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
512 }
513 else if (locationCodeType == "mts")
514 {
515 std::replace(propertyFCorTM.begin(),
516 propertyFCorTM.end(), '-', '.');
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000517 expandedLocationCode.replace(
SunnySrivastava198443306542020-04-01 02:50:20 -0500518 idx, 3, propertyFCorTM + "." + propertySE);
519 }
520
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000521 // update the DBUS interface COM as well as XYZ path
522 prop.emplace("LocationCode", expandedLocationCode);
523 // TODO depricate this com.ibm interface later
524 interfaces.emplace(IBM_LOCATION_CODE_INF, prop);
525 interfaces.emplace(XYZ_LOCATION_CODE_INF, move(prop));
SunnySrivastava198443306542020-04-01 02:50:20 -0500526 }
527 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000528 objects.emplace(move(object), move(interfaces));
SunnySrivastava198443306542020-04-01 02:50:20 -0500529 }
530 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000531 // Notify PIM
532 common::utility::callPIM(move(objects));
SunnySrivastava198443306542020-04-01 02:50:20 -0500533}
534
Alpana Kumari920408d2020-05-14 00:07:03 -0500535string EditorImpl::getSysPathForThisFruType(const string& moduleObjPath,
536 const string& fruType)
537{
538 string fruVpdPath;
539
540 // get all FRUs list
541 for (const auto& eachFru : jsonFile["frus"].items())
542 {
543 bool moduleObjPathMatched = false;
544 bool expectedFruFound = false;
545
546 for (const auto& eachInventory : eachFru.value())
547 {
548 const auto& thisObjectPath = eachInventory["inventoryPath"];
549
550 // "type" exists only in CPU module and FRU
551 if (eachInventory.find("type") != eachInventory.end())
552 {
553 // If inventory type is fruAndModule then set flag
554 if (eachInventory["type"] == fruType)
555 {
556 expectedFruFound = true;
557 }
558 }
559
560 if (thisObjectPath == moduleObjPath)
561 {
562 moduleObjPathMatched = true;
563 }
564 }
565
566 // If condition satisfies then collect this sys path and exit
567 if (expectedFruFound && moduleObjPathMatched)
568 {
569 fruVpdPath = eachFru.key();
570 break;
571 }
572 }
573
574 return fruVpdPath;
575}
576
577void EditorImpl::getVpdPathForCpu()
578{
579 isCI = false;
580 // keep a backup In case we need it later
581 inventory::Path vpdFilePathBackup = vpdFilePath;
582
583 // TODO 1:Temp hardcoded list. create it dynamically.
584 std::vector<std::string> commonIntVINIKwds = {"PN", "SN", "DR"};
585 std::vector<std::string> commonIntVR10Kwds = {"DC"};
586 std::unordered_map<std::string, std::vector<std::string>>
587 commonIntRecordsList = {{"VINI", commonIntVINIKwds},
588 {"VR10", commonIntVR10Kwds}};
589
590 // If requested Record&Kw is one among CI, then update 'FRU' type sys
591 // path, SPI2
592 unordered_map<std::string, vector<string>>::const_iterator isCommonInt =
593 commonIntRecordsList.find(thisRecord.recName);
594
595 if ((isCommonInt != commonIntRecordsList.end()) &&
596 (find(isCommonInt->second.begin(), isCommonInt->second.end(),
597 thisRecord.recKWd) != isCommonInt->second.end()))
598 {
599 isCI = true;
600 vpdFilePath = getSysPathForThisFruType(objPath, "fruAndModule");
601 }
602 else
603 {
604 for (const auto& eachFru : jsonFile["frus"].items())
605 {
606 for (const auto& eachInventory : eachFru.value())
607 {
608 if (eachInventory.find("type") != eachInventory.end())
609 {
610 const auto& thisObjectPath = eachInventory["inventoryPath"];
611 if ((eachInventory["type"] == "moduleOnly") &&
612 (eachInventory.value("inheritEI", true)) &&
613 (thisObjectPath == static_cast<string>(objPath)))
614 {
615 vpdFilePath = eachFru.key();
616 }
617 }
618 }
619 }
620 }
621 // If it is not a CPU fru then go ahead with default vpdFilePath from
622 // fruMap
623 if (vpdFilePath.empty())
624 {
625 vpdFilePath = vpdFilePathBackup;
626 }
627}
628
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530629void EditorImpl::updateKeyword(const Binary& kwdData, const bool& updCache)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600630{
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500631 startOffset = 0;
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500632#ifndef ManagerTest
Alpana Kumari920408d2020-05-14 00:07:03 -0500633
634 getVpdPathForCpu();
635
Alpana Kumari920408d2020-05-14 00:07:03 -0500636 // check if offset present?
637 for (const auto& item : jsonFile["frus"][vpdFilePath])
638 {
639 if (item.find("offset") != item.end())
640 {
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500641 startOffset = item["offset"];
Alpana Kumari920408d2020-05-14 00:07:03 -0500642 }
643 }
644
645 // TODO: Figure out a better way to get max possible VPD size.
646 Binary completeVPDFile;
647 completeVPDFile.resize(65504);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600648 vpdFileStream.open(vpdFilePath,
649 std::ios::in | std::ios::out | std::ios::binary);
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500650
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500651 vpdFileStream.seekg(startOffset, ios_base::cur);
Alpana Kumari920408d2020-05-14 00:07:03 -0500652 vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]), 65504);
653 completeVPDFile.resize(vpdFileStream.gcount());
654 vpdFileStream.clear(std::ios_base::eofbit);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600655
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500656 vpdFile = completeVPDFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500657
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500658#else
Alpana Kumari920408d2020-05-14 00:07:03 -0500659
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500660 Binary completeVPDFile = vpdFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500661
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500662#endif
663 if (vpdFile.empty())
664 {
665 throw std::runtime_error("Invalid File");
666 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500667 auto iterator = vpdFile.cbegin();
668 std::advance(iterator, IPZ_DATA_START);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600669
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500670 Byte vpdType = *iterator;
671 if (vpdType == KW_VAL_PAIR_START_TAG)
672 {
PriyangaRamasamy33c61c22021-04-06 11:15:57 -0500673 ParserInterface* Iparser = ParserFactory::getParser(completeVPDFile);
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500674 IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600675
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500676 try
677 {
678 if (ipzParser == nullptr)
679 {
680 throw std::runtime_error("Invalid cast");
681 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500682
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500683 ipzParser->processHeader();
684 delete ipzParser;
685 ipzParser = nullptr;
686 // ParserFactory::freeParser(Iparser);
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500687
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500688 // process VTOC for PTT rkwd
689 readVTOC();
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500690
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500691 // check record for keywrod
692 checkRecordForKwd();
693
694 // update the data to the file
695 updateData(kwdData);
696
697 // update the ECC data for the record once data has been updated
698 updateRecordECC();
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530699
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530700 if (updCache)
701 {
PriyangaRamasamyc0d1c0a2021-04-16 09:45:06 -0500702#ifndef ManagerTest
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530703 // update the cache once data has been updated
704 updateCache();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500705#endif
PriyangaRamasamyc0d1c0a2021-04-16 09:45:06 -0500706 }
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500707 }
708 catch (const std::exception& e)
709 {
710 if (ipzParser != nullptr)
711 {
712 delete ipzParser;
713 }
714 throw std::runtime_error(e.what());
715 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500716 return;
717 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600718}
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600719} // namespace editor
720} // namespace manager
721} // namespace vpd
722} // namespace openpower