blob: 4d81278c4b0eeeaeb58a0f8c4cfa4012944b4e45 [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
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500217void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
218 Binary::const_iterator& itrToECCData,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600219 RecordLength recLength, ECCLength eccLength)
220{
221 auto l_status =
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500222 vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
223 const_cast<uint8_t*>(&itrToECCData[0]), eccLength);
224
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600225 if (l_status != VPD_ECC_OK)
226 {
227 throw std::runtime_error("Ecc check failed for VTOC");
228 }
229}
230
231void EditorImpl::readVTOC()
232{
233 // read VTOC offset
234 RecordOffset tocOffset = getValue(offsets::VTOC_PTR);
235
236 // read VTOC record length
237 RecordLength tocLength = getValue(offsets::VTOC_REC_LEN);
238
239 // read TOC ecc offset
240 ECCOffset tocECCOffset = getValue(offsets::VTOC_ECC_OFF);
241
242 // read TOC ecc length
243 ECCLength tocECCLength = getValue(offsets::VTOC_ECC_LEN);
244
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500245 auto itrToRecord = vpdFile.cbegin();
246 std::advance(itrToRecord, tocOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600247
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500248 auto iteratorToECC = vpdFile.cbegin();
249 std::advance(iteratorToECC, tocECCOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600250
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500251 // validate ecc for the record
252 checkECC(itrToRecord, iteratorToECC, tocLength, tocECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600253
254 // to get to the record name.
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500255 std::advance(itrToRecord, sizeof(RecordId) + sizeof(RecordSize) +
256 // Skip past the RT keyword, which contains
257 // the record name.
258 lengths::KW_NAME + sizeof(KwSize));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600259
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500260 std::string recordName(itrToRecord, itrToRecord + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600261
262 if ("VTOC" != recordName)
263 {
264 throw std::runtime_error("VTOC record not found");
265 }
266
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600267 // jump to length of PT kwd
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500268 std::advance(itrToRecord, lengths::RECORD_NAME + lengths::KW_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600269
270 // Note size of PT
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500271 Byte ptLen = *itrToRecord;
272 std::advance(itrToRecord, 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600273
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500274 checkPTForRecord(itrToRecord, ptLen);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600275}
276
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600277template <typename T>
278void EditorImpl::makeDbusCall(const std::string& object,
279 const std::string& interface,
280 const std::string& property,
281 const std::variant<T>& data)
282{
283 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500284 auto properties =
285 bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
286 "org.freedesktop.DBus.Properties", "Set");
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600287 properties.append(interface);
288 properties.append(property);
289 properties.append(data);
290
291 auto result = bus.call(properties);
292
293 if (result.is_method_error())
294 {
295 throw std::runtime_error("bus call failed");
296 }
297}
298
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600299void EditorImpl::processAndUpdateCI(const std::string& objectPath)
300{
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000301 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600302 for (auto& commonInterface : jsonFile["commonInterfaces"].items())
303 {
304 for (auto& ciPropertyList : commonInterface.value().items())
305 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600306 if (ciPropertyList.value().type() ==
307 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600308 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600309 if ((ciPropertyList.value().value("recordName", "") ==
310 thisRecord.recName) &&
311 (ciPropertyList.value().value("keywordName", "") ==
312 thisRecord.recKWd))
313 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000314 inventory::PropertyMap prop;
315 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600316 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
317 thisRecord.kwdUpdatedData.end());
318
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500319 prop.emplace(ciPropertyList.key(), std::move(kwdData));
320 interfaces.emplace(commonInterface.key(), std::move(prop));
321 objects.emplace(objectPath, std::move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600322 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600323 }
324 }
325 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000326 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500327 common::utility::callPIM(std::move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600328}
329
330void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
331 const inventory::Path& objPath)
332{
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000333 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600334 for (const auto& extraInterface : Inventory["extraInterfaces"].items())
335 {
336 if (extraInterface.value() != NULL)
337 {
338 for (const auto& eiPropertyList : extraInterface.value().items())
339 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600340 if (eiPropertyList.value().type() ==
341 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600342 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600343 if ((eiPropertyList.value().value("recordName", "") ==
344 thisRecord.recName) &&
345 ((eiPropertyList.value().value("keywordName", "") ==
346 thisRecord.recKWd)))
347 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000348 inventory::PropertyMap prop;
349 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600350 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
351 thisRecord.kwdUpdatedData.end());
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000352 encodeKeyword(kwdData, eiPropertyList.value().value(
353 "encoding", ""));
354
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500355 prop.emplace(eiPropertyList.key(), std::move(kwdData));
356 interfaces.emplace(extraInterface.key(),
357 std::move(prop));
358 objects.emplace(objPath, std::move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600359 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600360 }
361 }
362 }
363 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000364 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500365 common::utility::callPIM(std::move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600366}
367
368void EditorImpl::updateCache()
369{
370 const std::vector<nlohmann::json>& groupEEPROM =
371 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
372
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000373 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600374 // iterate through all the inventories for this file path
375 for (const auto& singleInventory : groupEEPROM)
376 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000377 inventory::PropertyMap prop;
378 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600379 // by default inherit property is true
380 bool isInherit = true;
381
382 if (singleInventory.find("inherit") != singleInventory.end())
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600383 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600384 isInherit = singleInventory["inherit"].get<bool>();
385 }
386
387 if (isInherit)
388 {
Santosh Puranik32c46502022-02-10 08:55:07 +0530389 prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
390 interfaces.emplace(
391 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500392 std::move(prop));
Santosh Puranik32c46502022-02-10 08:55:07 +0530393 objects.emplace(
394 (singleInventory["inventoryPath"].get<std::string>()),
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500395 std::move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600396
397 // process Common interface
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600398 processAndUpdateCI(singleInventory["inventoryPath"]
399 .get_ref<const nlohmann::json::string_t&>());
400 }
401
Santosh Puranik32c46502022-02-10 08:55:07 +0530402 // process extra interfaces
403 processAndUpdateEI(singleInventory,
404 singleInventory["inventoryPath"]
405 .get_ref<const nlohmann::json::string_t&>());
Sunny Srivastava26d6c142021-11-03 15:19:02 -0500406
407 // check if we need to copy some specific records in this case.
408 if (singleInventory.find("copyRecords") != singleInventory.end())
409 {
410 if (find(singleInventory["copyRecords"].begin(),
411 singleInventory["copyRecords"].end(),
412 thisRecord.recName) !=
413 singleInventory["copyRecords"].end())
414 {
415 prop.emplace(thisRecord.recKWd, thisRecord.kwdUpdatedData);
416 interfaces.emplace(
417 (IPZ_INTERFACE + std::string{"."} + thisRecord.recName),
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500418 std::move(prop));
Sunny Srivastava26d6c142021-11-03 15:19:02 -0500419 objects.emplace(
420 (singleInventory["inventoryPath"].get<std::string>()),
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500421 std::move(interfaces));
Sunny Srivastava26d6c142021-11-03 15:19:02 -0500422 }
423 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600424 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000425 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500426 common::utility::callPIM(std::move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600427}
428
SunnySrivastava198443306542020-04-01 02:50:20 -0500429void EditorImpl::expandLocationCode(const std::string& locationCodeType)
430{
431 std::string propertyFCorTM{};
432 std::string propertySE{};
433
434 if (locationCodeType == "fcs")
435 {
436 propertyFCorTM =
437 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
438 propertySE =
439 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
440 }
441 else if (locationCodeType == "mts")
442 {
443 propertyFCorTM =
444 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
445 propertySE =
446 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
447 }
448
449 const nlohmann::json& groupFRUS =
450 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000451 inventory::ObjectMap objects;
452
SunnySrivastava198443306542020-04-01 02:50:20 -0500453 for (const auto& itemFRUS : groupFRUS.items())
454 {
455 const std::vector<nlohmann::json>& groupEEPROM =
456 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
457 for (const auto& itemEEPROM : groupEEPROM)
458 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000459 inventory::PropertyMap prop;
460 inventory::InterfaceMap interfaces;
461 const auto& objectPath = itemEEPROM["inventoryPath"];
462 sdbusplus::message::object_path object(objectPath);
463
SunnySrivastava198443306542020-04-01 02:50:20 -0500464 // check if the given item implements location code interface
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000465 if (itemEEPROM["extraInterfaces"].find(IBM_LOCATION_CODE_INF) !=
SunnySrivastava198443306542020-04-01 02:50:20 -0500466 itemEEPROM["extraInterfaces"].end())
467 {
468 const std::string& unexpandedLocationCode =
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000469 itemEEPROM["extraInterfaces"][IBM_LOCATION_CODE_INF]
SunnySrivastava198443306542020-04-01 02:50:20 -0500470 ["LocationCode"]
471 .get_ref<const nlohmann::json::string_t&>();
472 std::size_t idx = unexpandedLocationCode.find(locationCodeType);
473 if (idx != std::string::npos)
474 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000475 std::string expandedLocationCode(unexpandedLocationCode);
SunnySrivastava198443306542020-04-01 02:50:20 -0500476
477 if (locationCodeType == "fcs")
478 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000479 expandedLocationCode.replace(
SunnySrivastava198443306542020-04-01 02:50:20 -0500480 idx, 3,
481 propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
482 }
483 else if (locationCodeType == "mts")
484 {
485 std::replace(propertyFCorTM.begin(),
486 propertyFCorTM.end(), '-', '.');
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000487 expandedLocationCode.replace(
SunnySrivastava198443306542020-04-01 02:50:20 -0500488 idx, 3, propertyFCorTM + "." + propertySE);
489 }
490
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000491 // update the DBUS interface COM as well as XYZ path
492 prop.emplace("LocationCode", expandedLocationCode);
493 // TODO depricate this com.ibm interface later
494 interfaces.emplace(IBM_LOCATION_CODE_INF, prop);
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500495 interfaces.emplace(XYZ_LOCATION_CODE_INF, std::move(prop));
SunnySrivastava198443306542020-04-01 02:50:20 -0500496 }
497 }
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500498 objects.emplace(std::move(object), std::move(interfaces));
SunnySrivastava198443306542020-04-01 02:50:20 -0500499 }
500 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000501 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500502 common::utility::callPIM(std::move(objects));
SunnySrivastava198443306542020-04-01 02:50:20 -0500503}
504
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500505#ifndef ManagerTest
506static void enableRebootGuard()
507{
508 try
509 {
510 auto bus = sdbusplus::bus::new_default();
511 auto method = bus.new_method_call(
512 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
513 "org.freedesktop.systemd1.Manager", "StartUnit");
514 method.append("reboot-guard-enable.service", "replace");
515 bus.call_noreply(method);
516 }
Patrick Williams7a975f02022-12-07 03:19:53 -0600517 catch (const sdbusplus::exception_t& e)
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500518 {
519 std::string errMsg =
520 "Bus call to enable BMC reboot failed for reason: ";
521 errMsg += e.what();
522
523 throw std::runtime_error(errMsg);
524 }
525}
526
527static void disableRebootGuard()
528{
529 try
530 {
531 auto bus = sdbusplus::bus::new_default();
532 auto method = bus.new_method_call(
533 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
534 "org.freedesktop.systemd1.Manager", "StartUnit");
535 method.append("reboot-guard-disable.service", "replace");
536 bus.call_noreply(method);
537 }
Patrick Williams7a975f02022-12-07 03:19:53 -0600538 catch (const sdbusplus::exception_t& e)
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500539 {
540 using namespace phosphor::logging;
541 using InternalFailure =
542 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
543
544 std::string errMsg =
545 "Bus call to disable BMC reboot failed for reason: ";
546 errMsg += e.what();
547
548 log<level::ERR>("Disable boot guard failed");
549 elog<InternalFailure>();
550
551 throw std::runtime_error(errMsg);
552 }
553}
554#endif
555
Santosh Puranika0b23912022-02-10 13:37:09 +0530556void EditorImpl::updateKeyword(const Binary& kwdData, uint32_t offset,
557 const bool& updCache)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600558{
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500559 try
560 {
561 startOffset = offset;
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500562#ifndef ManagerTest
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500563 // Restrict BMC from rebooting when VPD is being written. This will
564 // prevent any data/ECC corruption in case BMC reboots while VPD update.
565 enableRebootGuard();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500566
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500567 // TODO: Figure out a better way to get max possible VPD size.
568 Binary completeVPDFile;
569 completeVPDFile.resize(65504);
570 vpdFileStream.open(vpdFilePath,
571 std::ios::in | std::ios::out | std::ios::binary);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600572
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500573 vpdFileStream.seekg(startOffset, std::ios_base::cur);
574 vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]), 65504);
575 completeVPDFile.resize(vpdFileStream.gcount());
576 vpdFileStream.clear(std::ios_base::eofbit);
577
578 vpdFile = completeVPDFile;
579
580 if (objPath.empty() &&
581 jsonFile["frus"].find(vpdFilePath) != jsonFile["frus"].end())
582 {
583 objPath = jsonFile["frus"][vpdFilePath][0]["inventoryPath"]
584 .get_ref<const nlohmann::json::string_t&>();
585 }
Alpana Kumari920408d2020-05-14 00:07:03 -0500586
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500587#else
Alpana Kumari920408d2020-05-14 00:07:03 -0500588
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500589 Binary completeVPDFile = vpdFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500590
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500591#endif
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500592 if (vpdFile.empty())
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500593 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500594 throw std::runtime_error("Invalid File");
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500595 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500596 auto iterator = vpdFile.cbegin();
597 std::advance(iterator, IPZ_DATA_START);
598
599 Byte vpdType = *iterator;
600 if (vpdType == KW_VAL_PAIR_START_TAG)
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500601 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500602 // objPath should be empty only in case of test run.
603 ParserInterface* Iparser =
604 ParserFactory::getParser(completeVPDFile, objPath);
605 IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
606
607 try
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500608 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500609 if (ipzParser == nullptr)
610 {
611 throw std::runtime_error("Invalid cast");
612 }
613
614 ipzParser->processHeader();
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500615 delete ipzParser;
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500616 ipzParser = nullptr;
617 // ParserFactory::freeParser(Iparser);
618
619 // process VTOC for PTT rkwd
620 readVTOC();
621
622 // check record for keywrod
623 checkRecordForKwd();
624
625 // update the data to the file
626 updateData(kwdData);
627
628 // update the ECC data for the record once data has been updated
629 updateRecordECC();
630
631 if (updCache)
632 {
633#ifndef ManagerTest
634 // update the cache once data has been updated
635 updateCache();
636#endif
637 }
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500638 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500639 catch (const std::exception& e)
640 {
641 if (ipzParser != nullptr)
642 {
643 delete ipzParser;
644 }
645 throw std::runtime_error(e.what());
646 }
647
648#ifndef ManagerTest
649 // Once VPD data and Ecc update is done, disable BMC boot guard.
650 disableRebootGuard();
651#endif
652
653 return;
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500654 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500655 else
656 {
657 throw openpower::vpd::exceptions::VpdDataException(
658 "Could not find start tag in VPD " + vpdFilePath);
659 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500660 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500661 catch (const std::exception& e)
Priyanga Ramasamyc99a0b02022-06-08 14:53:39 -0500662 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500663#ifndef ManagerTest
664 // Disable reboot guard.
665 disableRebootGuard();
666#endif
667
668 throw std::runtime_error(e.what());
Priyanga Ramasamyc99a0b02022-06-08 14:53:39 -0500669 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600670}
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600671} // namespace editor
672} // namespace manager
673} // namespace vpd
Santosh Puranik32c46502022-02-10 08:55:07 +0530674} // namespace openpower