blob: 426dd7b0229b4e64675e6249560efda3c82a31bd [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"
Priyanga Ramasamyc99a0b02022-06-08 14:53:39 -05009#include "vpd_exceptions.hpp"
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060010
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -050011#include <phosphor-logging/elog-errors.hpp>
12#include <xyz/openbmc_project/Common/error.hpp>
13
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060014#include "vpdecc/vpdecc.h"
15
SunnySrivastava1984e12b1812020-05-26 02:23:11 -050016using namespace openpower::vpd::parser::interface;
17using namespace openpower::vpd::constants;
18using namespace openpower::vpd::parser::factory;
19using namespace openpower::vpd::ipz::parser;
20
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060021namespace openpower
22{
23namespace vpd
24{
25namespace manager
26{
27namespace editor
28{
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060029
30void EditorImpl::checkPTForRecord(Binary::const_iterator& iterator,
31 Byte ptLength)
32{
33 // auto iterator = ptRecord.cbegin();
34 auto end = std::next(iterator, ptLength + 1);
35
36 // Look at each entry in the PT keyword for the record name
37 while (iterator < end)
38 {
39 auto stop = std::next(iterator, lengths::RECORD_NAME);
40 std::string record(iterator, stop);
41
42 if (record == thisRecord.recName)
43 {
44 // Skip record name and record type
45 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
46
47 // Get record offset
48 thisRecord.recOffset = readUInt16LE(iterator);
49
50 // pass the record offset length to read record length
51 std::advance(iterator, lengths::RECORD_OFFSET);
52 thisRecord.recSize = readUInt16LE(iterator);
53
54 std::advance(iterator, lengths::RECORD_LENGTH);
55 thisRecord.recECCoffset = readUInt16LE(iterator);
56
57 ECCLength len;
58 std::advance(iterator, lengths::RECORD_ECC_OFFSET);
59 len = readUInt16LE(iterator);
60 thisRecord.recECCLength = len;
61
62 // once we find the record we don't need to look further
63 return;
64 }
65 else
66 {
67 // Jump the record
68 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType) +
69 sizeof(RecordOffset) +
70 sizeof(RecordLength) +
71 sizeof(ECCOffset) + sizeof(ECCLength));
72 }
73 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060074 // imples the record was not found
75 throw std::runtime_error("Record not found");
76}
77
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050078void EditorImpl::updateData(const Binary& kwdData)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060079{
80 std::size_t lengthToUpdate = kwdData.size() <= thisRecord.kwdDataLength
81 ? kwdData.size()
82 : thisRecord.kwdDataLength;
83
84 auto iteratorToNewdata = kwdData.cbegin();
85 auto end = iteratorToNewdata;
86 std::advance(end, lengthToUpdate);
87
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050088 // update data in file buffer as it will be needed to update ECC
89 // avoiding extra stream operation here
90 auto iteratorToKWdData = vpdFile.begin();
91 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
92 std::copy(iteratorToNewdata, end, iteratorToKWdData);
93
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -050094#ifdef ManagerTest
95 auto startItr = vpdFile.begin();
96 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
97 auto endItr = startItr;
98 std::advance(endItr, thisRecord.kwdDataLength);
99
100 Binary updatedData(startItr, endItr);
101 if (updatedData == kwdData)
102 {
103 throw std::runtime_error("Data updated successfully");
104 }
105#else
106
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500107 // update data in EEPROM as well. As we will not write complete file back
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500108 vpdFileStream.seekp(startOffset + thisRecord.kwDataOffset, std::ios::beg);
Alpana Kumari920408d2020-05-14 00:07:03 -0500109
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500110 iteratorToNewdata = kwdData.cbegin();
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600111 std::copy(iteratorToNewdata, end,
112 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500113
114 // get a hold to new data in case encoding is needed
115 thisRecord.kwdUpdatedData.resize(thisRecord.kwdDataLength);
116 auto itrToKWdData = vpdFile.cbegin();
117 std::advance(itrToKWdData, thisRecord.kwDataOffset);
118 auto kwdDataEnd = itrToKWdData;
119 std::advance(kwdDataEnd, thisRecord.kwdDataLength);
120 std::copy(itrToKWdData, kwdDataEnd, thisRecord.kwdUpdatedData.begin());
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500121#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600122}
123
124void EditorImpl::checkRecordForKwd()
125{
126 RecordOffset recOffset = thisRecord.recOffset;
127
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500128 // Amount to skip for record ID, size, and the RT keyword
129 constexpr auto skipBeg = sizeof(RecordId) + sizeof(RecordSize) +
130 lengths::KW_NAME + sizeof(KwSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600131
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500132 auto iterator = vpdFile.cbegin();
133 std::advance(iterator, recOffset + skipBeg + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600134
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500135 auto end = iterator;
136 std::advance(end, thisRecord.recSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600137 std::size_t dataLength = 0;
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500138
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600139 while (iterator < end)
140 {
141 // Note keyword name
142 std::string kw(iterator, iterator + lengths::KW_NAME);
143
144 // Check if the Keyword starts with '#'
145 char kwNameStart = *iterator;
146 std::advance(iterator, lengths::KW_NAME);
147
148 // if keyword starts with #
149 if (POUND_KW == kwNameStart)
150 {
151 // Note existing keyword data length
152 dataLength = readUInt16LE(iterator);
153
154 // Jump past 2Byte keyword length + data
155 std::advance(iterator, sizeof(PoundKwSize));
156 }
157 else
158 {
159 // Note existing keyword data length
160 dataLength = *iterator;
161
162 // Jump past keyword length and data
163 std::advance(iterator, sizeof(KwSize));
164 }
165
166 if (thisRecord.recKWd == kw)
167 {
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500168 thisRecord.kwDataOffset = std::distance(vpdFile.cbegin(), iterator);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600169 thisRecord.kwdDataLength = dataLength;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600170 return;
171 }
172
173 // jump the data of current kwd to point to next kwd name
174 std::advance(iterator, dataLength);
175 }
176
177 throw std::runtime_error("Keyword not found");
178}
179
180void EditorImpl::updateRecordECC()
181{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500182 auto itrToRecordData = vpdFile.cbegin();
183 std::advance(itrToRecordData, thisRecord.recOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600184
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500185 auto itrToRecordECC = vpdFile.cbegin();
186 std::advance(itrToRecordECC, thisRecord.recECCoffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600187
188 auto l_status = vpdecc_create_ecc(
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500189 const_cast<uint8_t*>(&itrToRecordData[0]), thisRecord.recSize,
190 const_cast<uint8_t*>(&itrToRecordECC[0]), &thisRecord.recECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600191 if (l_status != VPD_ECC_OK)
192 {
193 throw std::runtime_error("Ecc update failed");
194 }
195
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500196 auto end = itrToRecordECC;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600197 std::advance(end, thisRecord.recECCLength);
198
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500199#ifndef ManagerTest
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500200 vpdFileStream.seekp(startOffset + thisRecord.recECCoffset, std::ios::beg);
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500201 std::copy(itrToRecordECC, end,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600202 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500203#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600204}
205
206auto EditorImpl::getValue(offsets::Offsets offset)
207{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500208 auto itr = vpdFile.cbegin();
209 std::advance(itr, offset);
210 LE2ByteData lowByte = *itr;
211 LE2ByteData highByte = *(itr + 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600212 lowByte |= (highByte << 8);
213
214 return lowByte;
215}
216
girik18bb9852022-11-16 05:48:13 -0600217void EditorImpl::checkRecordData()
218{
219 auto itrToRecordData = vpdFile.cbegin();
220 std::advance(itrToRecordData, thisRecord.recOffset);
221
222 auto itrToRecordECC = vpdFile.cbegin();
223 std::advance(itrToRecordECC, thisRecord.recECCoffset);
224
225 checkECC(itrToRecordData, itrToRecordECC, thisRecord.recSize,
226 thisRecord.recECCLength);
227}
228
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500229void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
230 Binary::const_iterator& itrToECCData,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600231 RecordLength recLength, ECCLength eccLength)
232{
233 auto l_status =
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500234 vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
235 const_cast<uint8_t*>(&itrToECCData[0]), eccLength);
236
girik18bb9852022-11-16 05:48:13 -0600237 if (l_status == VPD_ECC_CORRECTABLE_DATA)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600238 {
girik18bb9852022-11-16 05:48:13 -0600239 try
240 {
241 if (vpdFileStream.is_open())
242 {
243 vpdFileStream.seekp(startOffset + thisRecord.recOffset,
244 std::ios::beg);
245 auto end = itrToRecData;
246 std::advance(end, recLength);
247 std::copy(itrToRecData, end,
248 std::ostreambuf_iterator<char>(vpdFileStream));
249 }
250 else
251 {
252 throw std::runtime_error("Ecc correction failed");
253 }
254 }
255 catch (const std::fstream::failure& e)
256 {
257 std::cout << "Error while operating on file with exception";
258 throw std::runtime_error("Ecc correction failed");
259 }
260 }
261 else if (l_status != VPD_ECC_OK)
262 {
263 throw std::runtime_error("Ecc check failed");
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600264 }
265}
266
267void EditorImpl::readVTOC()
268{
269 // read VTOC offset
270 RecordOffset tocOffset = getValue(offsets::VTOC_PTR);
271
272 // read VTOC record length
273 RecordLength tocLength = getValue(offsets::VTOC_REC_LEN);
274
275 // read TOC ecc offset
276 ECCOffset tocECCOffset = getValue(offsets::VTOC_ECC_OFF);
277
278 // read TOC ecc length
279 ECCLength tocECCLength = getValue(offsets::VTOC_ECC_LEN);
280
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500281 auto itrToRecord = vpdFile.cbegin();
282 std::advance(itrToRecord, tocOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600283
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500284 auto iteratorToECC = vpdFile.cbegin();
285 std::advance(iteratorToECC, tocECCOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600286
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500287 // validate ecc for the record
288 checkECC(itrToRecord, iteratorToECC, tocLength, tocECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600289
290 // to get to the record name.
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500291 std::advance(itrToRecord, sizeof(RecordId) + sizeof(RecordSize) +
292 // Skip past the RT keyword, which contains
293 // the record name.
294 lengths::KW_NAME + sizeof(KwSize));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600295
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500296 std::string recordName(itrToRecord, itrToRecord + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600297
298 if ("VTOC" != recordName)
299 {
300 throw std::runtime_error("VTOC record not found");
301 }
302
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600303 // jump to length of PT kwd
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500304 std::advance(itrToRecord, lengths::RECORD_NAME + lengths::KW_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600305
306 // Note size of PT
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500307 Byte ptLen = *itrToRecord;
308 std::advance(itrToRecord, 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600309
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500310 checkPTForRecord(itrToRecord, ptLen);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600311}
312
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600313template <typename T>
314void EditorImpl::makeDbusCall(const std::string& object,
315 const std::string& interface,
316 const std::string& property,
317 const std::variant<T>& data)
318{
319 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500320 auto properties =
321 bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
322 "org.freedesktop.DBus.Properties", "Set");
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600323 properties.append(interface);
324 properties.append(property);
325 properties.append(data);
326
327 auto result = bus.call(properties);
328
329 if (result.is_method_error())
330 {
331 throw std::runtime_error("bus call failed");
332 }
333}
334
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600335void EditorImpl::processAndUpdateCI(const std::string& objectPath)
336{
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000337 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600338 for (auto& commonInterface : jsonFile["commonInterfaces"].items())
339 {
340 for (auto& ciPropertyList : commonInterface.value().items())
341 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600342 if (ciPropertyList.value().type() ==
343 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600344 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600345 if ((ciPropertyList.value().value("recordName", "") ==
346 thisRecord.recName) &&
347 (ciPropertyList.value().value("keywordName", "") ==
348 thisRecord.recKWd))
349 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000350 inventory::PropertyMap prop;
351 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600352 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
353 thisRecord.kwdUpdatedData.end());
354
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500355 prop.emplace(ciPropertyList.key(), std::move(kwdData));
356 interfaces.emplace(commonInterface.key(), std::move(prop));
357 objects.emplace(objectPath, std::move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600358 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600359 }
360 }
361 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000362 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500363 common::utility::callPIM(std::move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600364}
365
366void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
367 const inventory::Path& objPath)
368{
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000369 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600370 for (const auto& extraInterface : Inventory["extraInterfaces"].items())
371 {
372 if (extraInterface.value() != NULL)
373 {
374 for (const auto& eiPropertyList : extraInterface.value().items())
375 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600376 if (eiPropertyList.value().type() ==
377 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600378 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600379 if ((eiPropertyList.value().value("recordName", "") ==
380 thisRecord.recName) &&
381 ((eiPropertyList.value().value("keywordName", "") ==
382 thisRecord.recKWd)))
383 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000384 inventory::PropertyMap prop;
385 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600386 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
387 thisRecord.kwdUpdatedData.end());
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000388 encodeKeyword(kwdData, eiPropertyList.value().value(
389 "encoding", ""));
390
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500391 prop.emplace(eiPropertyList.key(), std::move(kwdData));
392 interfaces.emplace(extraInterface.key(),
393 std::move(prop));
394 objects.emplace(objPath, std::move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600395 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600396 }
397 }
398 }
399 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000400 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500401 common::utility::callPIM(std::move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600402}
403
404void EditorImpl::updateCache()
405{
406 const std::vector<nlohmann::json>& groupEEPROM =
407 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
408
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000409 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600410 // iterate through all the inventories for this file path
411 for (const auto& singleInventory : groupEEPROM)
412 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000413 inventory::PropertyMap prop;
414 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600415 // by default inherit property is true
416 bool isInherit = true;
417
418 if (singleInventory.find("inherit") != singleInventory.end())
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600419 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600420 isInherit = singleInventory["inherit"].get<bool>();
421 }
422
423 if (isInherit)
424 {
Santosh Puranik32c46502022-02-10 08:55:07 +0530425 prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
426 interfaces.emplace(
427 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500428 std::move(prop));
Santosh Puranik32c46502022-02-10 08:55:07 +0530429 objects.emplace(
430 (singleInventory["inventoryPath"].get<std::string>()),
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500431 std::move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600432
433 // process Common interface
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600434 processAndUpdateCI(singleInventory["inventoryPath"]
435 .get_ref<const nlohmann::json::string_t&>());
436 }
437
Santosh Puranik32c46502022-02-10 08:55:07 +0530438 // process extra interfaces
439 processAndUpdateEI(singleInventory,
440 singleInventory["inventoryPath"]
441 .get_ref<const nlohmann::json::string_t&>());
Sunny Srivastava26d6c142021-11-03 15:19:02 -0500442
443 // check if we need to copy some specific records in this case.
444 if (singleInventory.find("copyRecords") != singleInventory.end())
445 {
446 if (find(singleInventory["copyRecords"].begin(),
447 singleInventory["copyRecords"].end(),
448 thisRecord.recName) !=
449 singleInventory["copyRecords"].end())
450 {
451 prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
452 interfaces.emplace(
453 (IPZ_INTERFACE + std::string{"."} + thisRecord.recName),
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500454 std::move(prop));
Sunny Srivastava26d6c142021-11-03 15:19:02 -0500455 objects.emplace(
456 (singleInventory["inventoryPath"].get<std::string>()),
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500457 std::move(interfaces));
Sunny Srivastava26d6c142021-11-03 15:19:02 -0500458 }
459 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600460 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000461 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500462 common::utility::callPIM(std::move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600463}
464
SunnySrivastava198443306542020-04-01 02:50:20 -0500465void EditorImpl::expandLocationCode(const std::string& locationCodeType)
466{
467 std::string propertyFCorTM{};
468 std::string propertySE{};
469
470 if (locationCodeType == "fcs")
471 {
472 propertyFCorTM =
473 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
474 propertySE =
475 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
476 }
477 else if (locationCodeType == "mts")
478 {
479 propertyFCorTM =
480 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
481 propertySE =
482 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
483 }
484
485 const nlohmann::json& groupFRUS =
486 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000487 inventory::ObjectMap objects;
488
SunnySrivastava198443306542020-04-01 02:50:20 -0500489 for (const auto& itemFRUS : groupFRUS.items())
490 {
491 const std::vector<nlohmann::json>& groupEEPROM =
492 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
493 for (const auto& itemEEPROM : groupEEPROM)
494 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000495 inventory::PropertyMap prop;
496 inventory::InterfaceMap interfaces;
497 const auto& objectPath = itemEEPROM["inventoryPath"];
498 sdbusplus::message::object_path object(objectPath);
499
SunnySrivastava198443306542020-04-01 02:50:20 -0500500 // check if the given item implements location code interface
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000501 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
SunnySrivastava198443306542020-04-01 02:50:20 -0500502 itemEEPROM["extraInterfaces"].end())
503 {
504 const std::string& unexpandedLocationCode =
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000505 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
SunnySrivastava198443306542020-04-01 02:50:20 -0500506 ["LocationCode"]
507 .get_ref<const nlohmann::json::string_t&>();
508 std::size_t idx = unexpandedLocationCode.find(locationCodeType);
509 if (idx != std::string::npos)
510 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000511 std::string expandedLocationCode(unexpandedLocationCode);
SunnySrivastava198443306542020-04-01 02:50:20 -0500512
513 if (locationCodeType == "fcs")
514 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000515 expandedLocationCode.replace(
SunnySrivastava198443306542020-04-01 02:50:20 -0500516 idx, 3,
517 propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
518 }
519 else if (locationCodeType == "mts")
520 {
521 std::replace(propertyFCorTM.begin(),
522 propertyFCorTM.end(), '-', '.');
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000523 expandedLocationCode.replace(
SunnySrivastava198443306542020-04-01 02:50:20 -0500524 idx, 3, propertyFCorTM + "." + propertySE);
525 }
526
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000527 // update the DBUS interface COM as well as XYZ path
528 prop.emplace("LocationCode", expandedLocationCode);
529 // TODO depricate this com.ibm interface later
530 interfaces.emplace(IBM_LOCATION_CODE_INF, prop);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500531 interfaces.emplace(XYZ_LOCATION_CODE_INF, std::move(prop));
SunnySrivastava198443306542020-04-01 02:50:20 -0500532 }
533 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500534 objects.emplace(std::move(object), std::move(interfaces));
SunnySrivastava198443306542020-04-01 02:50:20 -0500535 }
536 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000537 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500538 common::utility::callPIM(std::move(objects));
SunnySrivastava198443306542020-04-01 02:50:20 -0500539}
540
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500541#ifndef ManagerTest
542static void enableRebootGuard()
543{
544 try
545 {
546 auto bus = sdbusplus::bus::new_default();
547 auto method = bus.new_method_call(
548 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
549 "org.freedesktop.systemd1.Manager", "StartUnit");
550 method.append("reboot-guard-enable.service", "replace");
551 bus.call_noreply(method);
552 }
Patrick Williams7a975f02022-12-07 03:19:53 -0600553 catch (const sdbusplus::exception_t& e)
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500554 {
555 std::string errMsg =
556 "Bus call to enable BMC reboot failed for reason: ";
557 errMsg += e.what();
558
559 throw std::runtime_error(errMsg);
560 }
561}
562
563static void disableRebootGuard()
564{
565 try
566 {
567 auto bus = sdbusplus::bus::new_default();
568 auto method = bus.new_method_call(
569 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
570 "org.freedesktop.systemd1.Manager", "StartUnit");
571 method.append("reboot-guard-disable.service", "replace");
572 bus.call_noreply(method);
573 }
Patrick Williams7a975f02022-12-07 03:19:53 -0600574 catch (const sdbusplus::exception_t& e)
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500575 {
576 using namespace phosphor::logging;
577 using InternalFailure =
578 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
579
580 std::string errMsg =
581 "Bus call to disable BMC reboot failed for reason: ";
582 errMsg += e.what();
583
584 log<level::ERR>("Disable boot guard failed");
585 elog<InternalFailure>();
586
587 throw std::runtime_error(errMsg);
588 }
589}
590#endif
591
Santosh Puranika0b23912022-02-10 13:37:09 +0530592void EditorImpl::updateKeyword(const Binary& kwdData, uint32_t offset,
593 const bool& updCache)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600594{
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500595 try
596 {
597 startOffset = offset;
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500598#ifndef ManagerTest
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500599 // Restrict BMC from rebooting when VPD is being written. This will
600 // prevent any data/ECC corruption in case BMC reboots while VPD update.
601 enableRebootGuard();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500602
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500603 // TODO: Figure out a better way to get max possible VPD size.
604 Binary completeVPDFile;
605 completeVPDFile.resize(65504);
606 vpdFileStream.open(vpdFilePath,
607 std::ios::in | std::ios::out | std::ios::binary);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600608
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500609 vpdFileStream.seekg(startOffset, std::ios_base::cur);
610 vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]), 65504);
611 completeVPDFile.resize(vpdFileStream.gcount());
612 vpdFileStream.clear(std::ios_base::eofbit);
613
614 vpdFile = completeVPDFile;
615
616 if (objPath.empty() &&
617 jsonFile["frus"].find(vpdFilePath) != jsonFile["frus"].end())
618 {
619 objPath = jsonFile["frus"][vpdFilePath][0]["inventoryPath"]
620 .get_ref<const nlohmann::json::string_t&>();
621 }
Alpana Kumari920408d2020-05-14 00:07:03 -0500622
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500623#else
Alpana Kumari920408d2020-05-14 00:07:03 -0500624
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500625 Binary completeVPDFile = vpdFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500626
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500627#endif
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500628 if (vpdFile.empty())
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500629 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500630 throw std::runtime_error("Invalid File");
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500631 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500632 auto iterator = vpdFile.cbegin();
633 std::advance(iterator, IPZ_DATA_START);
634
635 Byte vpdType = *iterator;
636 if (vpdType == KW_VAL_PAIR_START_TAG)
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500637 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500638 // objPath should be empty only in case of test run.
girik18bb9852022-11-16 05:48:13 -0600639 ParserInterface* Iparser = ParserFactory::getParser(
640 completeVPDFile, objPath, vpdFilePath, startOffset);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500641 IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
642
643 try
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500644 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500645 if (ipzParser == nullptr)
646 {
647 throw std::runtime_error("Invalid cast");
648 }
649
650 ipzParser->processHeader();
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500651 delete ipzParser;
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500652 ipzParser = nullptr;
653 // ParserFactory::freeParser(Iparser);
654
655 // process VTOC for PTT rkwd
656 readVTOC();
657
658 // check record for keywrod
659 checkRecordForKwd();
660
girik18bb9852022-11-16 05:48:13 -0600661 // Check Data before updating
662 checkRecordData();
663
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500664 // update the data to the file
665 updateData(kwdData);
666
667 // update the ECC data for the record once data has been updated
668 updateRecordECC();
669
670 if (updCache)
671 {
672#ifndef ManagerTest
673 // update the cache once data has been updated
674 updateCache();
675#endif
676 }
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500677 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500678 catch (const std::exception& e)
679 {
680 if (ipzParser != nullptr)
681 {
682 delete ipzParser;
683 }
684 throw std::runtime_error(e.what());
685 }
686
687#ifndef ManagerTest
688 // Once VPD data and Ecc update is done, disable BMC boot guard.
689 disableRebootGuard();
690#endif
691
692 return;
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500693 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500694 else
695 {
696 throw openpower::vpd::exceptions::VpdDataException(
697 "Could not find start tag in VPD " + vpdFilePath);
698 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500699 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500700 catch (const std::exception& e)
Priyanga Ramasamyc99a0b02022-06-08 14:53:39 -0500701 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500702#ifndef ManagerTest
703 // Disable reboot guard.
704 disableRebootGuard();
705#endif
706
707 throw std::runtime_error(e.what());
Priyanga Ramasamyc99a0b02022-06-08 14:53:39 -0500708 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600709}
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600710} // namespace editor
711} // namespace manager
712} // namespace vpd
Santosh Puranik32c46502022-02-10 08:55:07 +0530713} // namespace openpower