blob: c24cc0f64571d93437fdb23c95729a98cc4e1fac [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
Patrick Williamsc78d8872023-05-10 07:50:56 -05005#include "vpdecc/vpdecc.h"
6
Alpana Kumari414d5ae2021-03-04 21:06:35 +00007#include "common_utility.hpp"
Sunny Srivastava6c71c9d2021-04-15 04:43:54 -05008#include "ibm_vpd_utils.hpp"
SunnySrivastava1984e12b1812020-05-26 02:23:11 -05009#include "ipz_parser.hpp"
10#include "parser_factory.hpp"
Priyanga Ramasamyc99a0b02022-06-08 14:53:39 -050011#include "vpd_exceptions.hpp"
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060012
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -050013#include <phosphor-logging/elog-errors.hpp>
14#include <xyz/openbmc_project/Common/error.hpp>
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
Patrick Williams08dc31c2024-08-16 15:21:06 -040068 std::advance(iterator,
69 lengths::RECORD_NAME + sizeof(RecordType) +
70 sizeof(RecordOffset) + sizeof(RecordLength) +
71 sizeof(ECCOffset) + sizeof(ECCLength));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060072 }
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>
Patrick Williams08dc31c2024-08-16 15:21:06 -0400314void EditorImpl::makeDbusCall(
315 const std::string& object, const std::string& interface,
316 const std::string& property, const std::variant<T>& data)
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600317{
318 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500319 auto properties =
320 bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
321 "org.freedesktop.DBus.Properties", "Set");
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600322 properties.append(interface);
323 properties.append(property);
324 properties.append(data);
325
326 auto result = bus.call(properties);
327
328 if (result.is_method_error())
329 {
330 throw std::runtime_error("bus call failed");
331 }
332}
333
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600334void EditorImpl::processAndUpdateCI(const std::string& objectPath)
335{
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000336 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600337 for (auto& commonInterface : jsonFile["commonInterfaces"].items())
338 {
339 for (auto& ciPropertyList : commonInterface.value().items())
340 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600341 if (ciPropertyList.value().type() ==
342 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600343 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600344 if ((ciPropertyList.value().value("recordName", "") ==
345 thisRecord.recName) &&
346 (ciPropertyList.value().value("keywordName", "") ==
347 thisRecord.recKWd))
348 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000349 inventory::PropertyMap prop;
350 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600351 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
352 thisRecord.kwdUpdatedData.end());
353
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500354 prop.emplace(ciPropertyList.key(), std::move(kwdData));
355 interfaces.emplace(commonInterface.key(), std::move(prop));
356 objects.emplace(objectPath, std::move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600357 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600358 }
359 }
360 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000361 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500362 common::utility::callPIM(std::move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600363}
364
365void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
366 const inventory::Path& objPath)
367{
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000368 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600369 for (const auto& extraInterface : Inventory["extraInterfaces"].items())
370 {
371 if (extraInterface.value() != NULL)
372 {
373 for (const auto& eiPropertyList : extraInterface.value().items())
374 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600375 if (eiPropertyList.value().type() ==
376 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600377 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600378 if ((eiPropertyList.value().value("recordName", "") ==
379 thisRecord.recName) &&
380 ((eiPropertyList.value().value("keywordName", "") ==
381 thisRecord.recKWd)))
382 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000383 inventory::PropertyMap prop;
384 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600385 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
386 thisRecord.kwdUpdatedData.end());
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000387 encodeKeyword(kwdData, eiPropertyList.value().value(
388 "encoding", ""));
389
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500390 prop.emplace(eiPropertyList.key(), std::move(kwdData));
391 interfaces.emplace(extraInterface.key(),
392 std::move(prop));
393 objects.emplace(objPath, std::move(interfaces));
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600394 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600395 }
396 }
397 }
398 }
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000399 // Notify PIM
Priyanga Ramasamye0084322022-09-27 06:28:33 -0500400 common::utility::callPIM(std::move(objects));
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600401}
402
403void EditorImpl::updateCache()
404{
405 const std::vector<nlohmann::json>& groupEEPROM =
406 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
407
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000408 inventory::ObjectMap objects;
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600409 // iterate through all the inventories for this file path
410 for (const auto& singleInventory : groupEEPROM)
411 {
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000412 inventory::PropertyMap prop;
413 inventory::InterfaceMap interfaces;
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600414 // by default inherit property is true
415 bool isInherit = true;
416
417 if (singleInventory.find("inherit") != singleInventory.end())
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600418 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600419 isInherit = singleInventory["inherit"].get<bool>();
420 }
421
422 if (isInherit)
423 {
Priyanga Ramasamy5629fbc2023-03-01 08:17:19 -0600424 prop.emplace(getDbusNameForThisKw(thisRecord.recKWd),
425 thisRecord.kwdUpdatedData);
Santosh Puranik32c46502022-02-10 08:55:07 +0530426 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 {
Patrick Williams08dc31c2024-08-16 15:21:06 -0400472 propertyFCorTM =
473 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
474 propertySE =
475 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
SunnySrivastava198443306542020-04-01 02:50:20 -0500476 }
477 else if (locationCodeType == "mts")
478 {
Patrick Williams08dc31c2024-08-16 15:21:06 -0400479 propertyFCorTM =
480 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
481 propertySE =
482 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
SunnySrivastava198443306542020-04-01 02:50:20 -0500483 }
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);
Manojkiran Edaaf921752024-06-17 15:10:21 +0530529 // TODO deprecate this com.ibm interface later
Alpana Kumari414d5ae2021-03-04 21:06:35 +0000530 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 Binary completeVPDFile;
Patrick Williams08dc31c2024-08-16 15:21:06 -0400604 vpdFileStream.exceptions(
605 std::ifstream::badbit | std::ifstream::failbit);
jinuthomas45d54972023-07-03 04:36:29 -0500606 try
607 {
608 vpdFileStream.open(vpdFilePath,
609 std::ios::in | std::ios::out | std::ios::binary);
Priyanga Ramasamy4170bda2023-07-19 09:25:36 +0000610
Patrick Williams08dc31c2024-08-16 15:21:06 -0400611 auto vpdFileSize =
612 std::min(std::filesystem::file_size(vpdFilePath), MAX_VPD_SIZE);
Priyanga Ramasamy4170bda2023-07-19 09:25:36 +0000613 if (vpdFileSize == 0)
614 {
615 std::cerr << "File size is 0 for " << vpdFilePath << std::endl;
616 throw std::runtime_error("File size is 0.");
617 }
618
619 completeVPDFile.resize(vpdFileSize);
jinuthomas45d54972023-07-03 04:36:29 -0500620 vpdFileStream.seekg(startOffset, std::ios_base::cur);
621 vpdFileStream.read(reinterpret_cast<char*>(&completeVPDFile[0]),
Priyanga Ramasamy4170bda2023-07-19 09:25:36 +0000622 vpdFileSize);
jinuthomas45d54972023-07-03 04:36:29 -0500623 vpdFileStream.clear(std::ios_base::eofbit);
624 }
Priyanga Ramasamy4170bda2023-07-19 09:25:36 +0000625 catch (const std::system_error& fail)
jinuthomas45d54972023-07-03 04:36:29 -0500626 {
627 std::cerr << "Exception in file handling [" << vpdFilePath
628 << "] error : " << fail.what();
629 std::cerr << "Stream file size = " << vpdFileStream.gcount()
630 << std::endl;
631 throw;
632 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500633 vpdFile = completeVPDFile;
634
635 if (objPath.empty() &&
636 jsonFile["frus"].find(vpdFilePath) != jsonFile["frus"].end())
637 {
638 objPath = jsonFile["frus"][vpdFilePath][0]["inventoryPath"]
639 .get_ref<const nlohmann::json::string_t&>();
640 }
Alpana Kumari920408d2020-05-14 00:07:03 -0500641
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500642#else
Alpana Kumari920408d2020-05-14 00:07:03 -0500643
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500644 Binary completeVPDFile = vpdFile;
Alpana Kumari920408d2020-05-14 00:07:03 -0500645
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500646#endif
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500647 if (vpdFile.empty())
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500648 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500649 throw std::runtime_error("Invalid File");
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500650 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500651 auto iterator = vpdFile.cbegin();
652 std::advance(iterator, IPZ_DATA_START);
653
654 Byte vpdType = *iterator;
655 if (vpdType == KW_VAL_PAIR_START_TAG)
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500656 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500657 // objPath should be empty only in case of test run.
girik18bb9852022-11-16 05:48:13 -0600658 ParserInterface* Iparser = ParserFactory::getParser(
659 completeVPDFile, objPath, vpdFilePath, startOffset);
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500660 IpzVpdParser* ipzParser = dynamic_cast<IpzVpdParser*>(Iparser);
661
662 try
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500663 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500664 if (ipzParser == nullptr)
665 {
666 throw std::runtime_error("Invalid cast");
667 }
668
669 ipzParser->processHeader();
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500670 delete ipzParser;
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500671 ipzParser = nullptr;
672 // ParserFactory::freeParser(Iparser);
673
674 // process VTOC for PTT rkwd
675 readVTOC();
676
677 // check record for keywrod
678 checkRecordForKwd();
679
girik18bb9852022-11-16 05:48:13 -0600680 // Check Data before updating
681 checkRecordData();
682
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500683 // update the data to the file
684 updateData(kwdData);
685
686 // update the ECC data for the record once data has been updated
687 updateRecordECC();
688
689 if (updCache)
690 {
691#ifndef ManagerTest
692 // update the cache once data has been updated
693 updateCache();
694#endif
695 }
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500696 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500697 catch (const std::exception& e)
698 {
699 if (ipzParser != nullptr)
700 {
701 delete ipzParser;
702 }
703 throw std::runtime_error(e.what());
704 }
705
706#ifndef ManagerTest
707 // Once VPD data and Ecc update is done, disable BMC boot guard.
708 disableRebootGuard();
709#endif
710
711 return;
SunnySrivastava1984e12b1812020-05-26 02:23:11 -0500712 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500713 else
714 {
715 throw openpower::vpd::exceptions::VpdDataException(
716 "Could not find start tag in VPD " + vpdFilePath);
717 }
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500718 }
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500719 catch (const std::exception& e)
Priyanga Ramasamyc99a0b02022-06-08 14:53:39 -0500720 {
Sunny Srivastavaf31a91b2022-06-09 08:11:29 -0500721#ifndef ManagerTest
722 // Disable reboot guard.
723 disableRebootGuard();
724#endif
725
726 throw std::runtime_error(e.what());
Priyanga Ramasamyc99a0b02022-06-08 14:53:39 -0500727 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600728}
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600729} // namespace editor
730} // namespace manager
731} // namespace vpd
Patrick Williamsc78d8872023-05-10 07:50:56 -0500732} // namespace openpower