blob: 1b9290d7413542211f4825d66f4188a15d018eae [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 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600436 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000437 // Notify PIM
438 common::utility::callPIM(move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600439}
440
SunnySrivastava198443306542020-04-01 02:50:20 -0500441void EditorImpl::expandLocationCode(const std::string& locationCodeType)
442{
443 std::string propertyFCorTM{};
444 std::string propertySE{};
445
446 if (locationCodeType == "fcs")
447 {
448 propertyFCorTM =
449 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
450 propertySE =
451 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
452 }
453 else if (locationCodeType == "mts")
454 {
455 propertyFCorTM =
456 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
457 propertySE =
458 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
459 }
460
461 const nlohmann::json& groupFRUS =
462 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000463 inventory::ObjectMap objects;
464
SunnySrivastava198443306542020-04-01 02:50:20 -0500465 for (const auto& itemFRUS : groupFRUS.items())
466 {
467 const std::vector<nlohmann::json>& groupEEPROM =
468 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
469 for (const auto& itemEEPROM : groupEEPROM)
470 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000471 inventory::PropertyMap prop;
472 inventory::InterfaceMap interfaces;
473 const auto& objectPath = itemEEPROM["inventoryPath"];
474 sdbusplus::message::object_path object(objectPath);
475
SunnySrivastava198443306542020-04-01 02:50:20 -0500476 // check if the given item implements location code interface
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000477 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
SunnySrivastava198443306542020-04-01 02:50:20 -0500478 itemEEPROM["extraInterfaces"].end())
479 {
480 const std::string& unexpandedLocationCode =
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000481 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
SunnySrivastava198443306542020-04-01 02:50:20 -0500482 ["LocationCode"]
483 .get_ref<const nlohmann::json::string_t&>();
484 std::size_t idx = unexpandedLocationCode.find(locationCodeType);
485 if (idx != std::string::npos)
486 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000487 std::string expandedLocationCode(unexpandedLocationCode);
SunnySrivastava198443306542020-04-01 02:50:20 -0500488
489 if (locationCodeType == "fcs")
490 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000491 expandedLocationCode.replace(
SunnySrivastava198443306542020-04-01 02:50:20 -0500492 idx, 3,
493 propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
494 }
495 else if (locationCodeType == "mts")
496 {
497 std::replace(propertyFCorTM.begin(),
498 propertyFCorTM.end(), '-', '.');
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000499 expandedLocationCode.replace(
SunnySrivastava198443306542020-04-01 02:50:20 -0500500 idx, 3, propertyFCorTM + "." + propertySE);
501 }
502
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000503 // update the DBUS interface COM as well as XYZ path
504 prop.emplace("LocationCode", expandedLocationCode);
505 // TODO depricate this com.ibm interface later
506 interfaces.emplace(IBM_LOCATION_CODE_INF, prop);
507 interfaces.emplace(XYZ_LOCATION_CODE_INF, move(prop));
SunnySrivastava198443306542020-04-01 02:50:20 -0500508 }
509 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000510 objects.emplace(move(object), move(interfaces));
SunnySrivastava198443306542020-04-01 02:50:20 -0500511 }
512 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000513 // Notify PIM
514 common::utility::callPIM(move(objects));
SunnySrivastava198443306542020-04-01 02:50:20 -0500515}
516
Alpana Kumari920408d2020-05-14 00:07:03 -0500517string EditorImpl::getSysPathForThisFruType(const string& moduleObjPath,
518 const string& fruType)
519{
520 string fruVpdPath;
521
522 // get all FRUs list
523 for (const auto& eachFru : jsonFile["frus"].items())
524 {
525 bool moduleObjPathMatched = false;
526 bool expectedFruFound = false;
527
528 for (const auto& eachInventory : eachFru.value())
529 {
530 const auto& thisObjectPath = eachInventory["inventoryPath"];
531
532 // "type" exists only in CPU module and FRU
533 if (eachInventory.find("type") != eachInventory.end())
534 {
535 // If inventory type is fruAndModule then set flag
536 if (eachInventory["type"] == fruType)
537 {
538 expectedFruFound = true;
539 }
540 }
541
542 if (thisObjectPath == moduleObjPath)
543 {
544 moduleObjPathMatched = true;
545 }
546 }
547
548 // If condition satisfies then collect this sys path and exit
549 if (expectedFruFound && moduleObjPathMatched)
550 {
551 fruVpdPath = eachFru.key();
552 break;
553 }
554 }
555
556 return fruVpdPath;
557}
558
559void EditorImpl::getVpdPathForCpu()
560{
561 isCI = false;
562 // keep a backup In case we need it later
563 inventory::Path vpdFilePathBackup = vpdFilePath;
564
565 // TODO 1:Temp hardcoded list. create it dynamically.
566 std::vector<std::string> commonIntVINIKwds = {"PN", "SN", "DR"};
567 std::vector<std::string> commonIntVR10Kwds = {"DC"};
568 std::unordered_map<std::string, std::vector<std::string>>
569 commonIntRecordsList = {{"VINI", commonIntVINIKwds},
570 {"VR10", commonIntVR10Kwds}};
571
572 // If requested Record&Kw is one among CI, then update 'FRU' type sys
573 // path, SPI2
574 unordered_map<std::string, vector<string>>::const_iterator isCommonInt =
575 commonIntRecordsList.find(thisRecord.recName);
576
577 if ((isCommonInt != commonIntRecordsList.end()) &&
578 (find(isCommonInt->second.begin(), isCommonInt->second.end(),
579 thisRecord.recKWd) != isCommonInt->second.end()))
580 {
581 isCI = true;
582 vpdFilePath = getSysPathForThisFruType(objPath, "fruAndModule");
583 }
584 else
585 {
586 for (const auto& eachFru : jsonFile["frus"].items())
587 {
588 for (const auto& eachInventory : eachFru.value())
589 {
590 if (eachInventory.find("type") != eachInventory.end())
591 {
592 const auto& thisObjectPath = eachInventory["inventoryPath"];
593 if ((eachInventory["type"] == "moduleOnly") &&
594 (eachInventory.value("inheritEI", true)) &&
595 (thisObjectPath == static_cast<string>(objPath)))
596 {
597 vpdFilePath = eachFru.key();
598 }
599 }
600 }
601 }
602 }
603 // If it is not a CPU fru then go ahead with default vpdFilePath from
604 // fruMap
605 if (vpdFilePath.empty())
606 {
607 vpdFilePath = vpdFilePathBackup;
608 }
609}
610
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530611void EditorImpl::updateKeyword(const Binary& kwdData, const bool& updCache)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600612{
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500613 startOffset = 0;
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500614#ifndef ManagerTest
Alpana Kumari920408d2020-05-14 00:07:03 -0500615
616 getVpdPathForCpu();
617
Alpana Kumari920408d2020-05-14 00:07:03 -0500618 // check if offset present?
619 for (const auto& item : jsonFile["frus"][vpdFilePath])
620 {
621 if (item.find("offset") != item.end())
622 {
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500623 startOffset = item["offset"];
Alpana Kumari920408d2020-05-14 00:07:03 -0500624 }
625 }
626
627 // TODO: Figure out a better way to get max possible VPD size.
628 Binary completeVPDFile;
629 completeVPDFile.resize(65504);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600630 vpdFileStream.open(vpdFilePath,
631 std::ios::in | std::ios::out | std::ios::binary);
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500632
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500633 vpdFileStream.seekg(startOffset, ios_base::cur);
Alpana Kumari920408d2020-05-14 00:07:03 -0500634 vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]), 65504);
635 completeVPDFile.resize(vpdFileStream.gcount());
636 vpdFileStream.clear(std::ios_base::eofbit);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600637
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500638 vpdFile = completeVPDFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500639
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500640#else
Alpana Kumari920408d2020-05-14 00:07:03 -0500641
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500642 Binary completeVPDFile = vpdFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500643
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500644#endif
645 if (vpdFile.empty())
646 {
647 throw std::runtime_error("Invalid File");
648 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500649 auto iterator = vpdFile.cbegin();
650 std::advance(iterator, IPZ_DATA_START);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600651
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500652 Byte vpdType = *iterator;
653 if (vpdType == KW_VAL_PAIR_START_TAG)
654 {
PriyangaRamasamy33c61c22021-04-06 11:15:57 -0500655 ParserInterface* Iparser = ParserFactory::getParser(completeVPDFile);
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500656 IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600657
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500658 try
659 {
660 if (ipzParser == nullptr)
661 {
662 throw std::runtime_error("Invalid cast");
663 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500664
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500665 ipzParser->processHeader();
666 delete ipzParser;
667 ipzParser = nullptr;
668 // ParserFactory::freeParser(Iparser);
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500669
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500670 // process VTOC for PTT rkwd
671 readVTOC();
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500672
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500673 // check record for keywrod
674 checkRecordForKwd();
675
676 // update the data to the file
677 updateData(kwdData);
678
679 // update the ECC data for the record once data has been updated
680 updateRecordECC();
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530681
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530682 if (updCache)
683 {
PriyangaRamasamyc0d1c0a2021-04-16 09:45:06 -0500684#ifndef ManagerTest
PriyangaRamasamyc0a534f2020-08-24 21:29:18 +0530685 // update the cache once data has been updated
686 updateCache();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500687#endif
PriyangaRamasamyc0d1c0a2021-04-16 09:45:06 -0500688 }
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500689 }
690 catch (const std::exception& e)
691 {
692 if (ipzParser != nullptr)
693 {
694 delete ipzParser;
695 }
696 throw std::runtime_error(e.what());
697 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500698 return;
699 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600700}
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600701} // namespace editor
702} // namespace manager
703} // namespace vpd
704} // namespace openpower