blob: b9104f0afd3735c2d72ebcbd77cac1f13ad0a381 [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
SunnySrivastava19846d8314d2020-05-15 09:34:58 -05005#include "parser.hpp"
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06006#include "utils.hpp"
7
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -06008#include "vpdecc/vpdecc.h"
9
10namespace openpower
11{
12namespace vpd
13{
14namespace manager
15{
16namespace editor
17{
18using namespace openpower::vpd::constants;
19
20void EditorImpl::checkPTForRecord(Binary::const_iterator& iterator,
21 Byte ptLength)
22{
23 // auto iterator = ptRecord.cbegin();
24 auto end = std::next(iterator, ptLength + 1);
25
26 // Look at each entry in the PT keyword for the record name
27 while (iterator < end)
28 {
29 auto stop = std::next(iterator, lengths::RECORD_NAME);
30 std::string record(iterator, stop);
31
32 if (record == thisRecord.recName)
33 {
34 // Skip record name and record type
35 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType));
36
37 // Get record offset
38 thisRecord.recOffset = readUInt16LE(iterator);
39
40 // pass the record offset length to read record length
41 std::advance(iterator, lengths::RECORD_OFFSET);
42 thisRecord.recSize = readUInt16LE(iterator);
43
44 std::advance(iterator, lengths::RECORD_LENGTH);
45 thisRecord.recECCoffset = readUInt16LE(iterator);
46
47 ECCLength len;
48 std::advance(iterator, lengths::RECORD_ECC_OFFSET);
49 len = readUInt16LE(iterator);
50 thisRecord.recECCLength = len;
51
52 // once we find the record we don't need to look further
53 return;
54 }
55 else
56 {
57 // Jump the record
58 std::advance(iterator, lengths::RECORD_NAME + sizeof(RecordType) +
59 sizeof(RecordOffset) +
60 sizeof(RecordLength) +
61 sizeof(ECCOffset) + sizeof(ECCLength));
62 }
63 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060064 // imples the record was not found
65 throw std::runtime_error("Record not found");
66}
67
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050068void EditorImpl::updateData(const Binary& kwdData)
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -060069{
70 std::size_t lengthToUpdate = kwdData.size() <= thisRecord.kwdDataLength
71 ? kwdData.size()
72 : thisRecord.kwdDataLength;
73
74 auto iteratorToNewdata = kwdData.cbegin();
75 auto end = iteratorToNewdata;
76 std::advance(end, lengthToUpdate);
77
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050078 // update data in file buffer as it will be needed to update ECC
79 // avoiding extra stream operation here
80 auto iteratorToKWdData = vpdFile.begin();
81 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
82 std::copy(iteratorToNewdata, end, iteratorToKWdData);
83
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -050084#ifdef ManagerTest
85 auto startItr = vpdFile.begin();
86 std::advance(iteratorToKWdData, thisRecord.kwDataOffset);
87 auto endItr = startItr;
88 std::advance(endItr, thisRecord.kwdDataLength);
89
90 Binary updatedData(startItr, endItr);
91 if (updatedData == kwdData)
92 {
93 throw std::runtime_error("Data updated successfully");
94 }
95#else
96
SunnySrivastava19846d8314d2020-05-15 09:34:58 -050097 // update data in EEPROM as well. As we will not write complete file back
98 vpdFileStream.seekg(thisRecord.kwDataOffset, std::ios::beg);
99 iteratorToNewdata = kwdData.cbegin();
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600100 std::copy(iteratorToNewdata, end,
101 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500102
103 // get a hold to new data in case encoding is needed
104 thisRecord.kwdUpdatedData.resize(thisRecord.kwdDataLength);
105 auto itrToKWdData = vpdFile.cbegin();
106 std::advance(itrToKWdData, thisRecord.kwDataOffset);
107 auto kwdDataEnd = itrToKWdData;
108 std::advance(kwdDataEnd, thisRecord.kwdDataLength);
109 std::copy(itrToKWdData, kwdDataEnd, thisRecord.kwdUpdatedData.begin());
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500110#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600111}
112
113void EditorImpl::checkRecordForKwd()
114{
115 RecordOffset recOffset = thisRecord.recOffset;
116
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500117 // Amount to skip for record ID, size, and the RT keyword
118 constexpr auto skipBeg = sizeof(RecordId) + sizeof(RecordSize) +
119 lengths::KW_NAME + sizeof(KwSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600120
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500121 auto iterator = vpdFile.cbegin();
122 std::advance(iterator, recOffset + skipBeg + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600123
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500124 auto end = iterator;
125 std::advance(end, thisRecord.recSize);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600126 std::size_t dataLength = 0;
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500127
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600128 while (iterator < end)
129 {
130 // Note keyword name
131 std::string kw(iterator, iterator + lengths::KW_NAME);
132
133 // Check if the Keyword starts with '#'
134 char kwNameStart = *iterator;
135 std::advance(iterator, lengths::KW_NAME);
136
137 // if keyword starts with #
138 if (POUND_KW == kwNameStart)
139 {
140 // Note existing keyword data length
141 dataLength = readUInt16LE(iterator);
142
143 // Jump past 2Byte keyword length + data
144 std::advance(iterator, sizeof(PoundKwSize));
145 }
146 else
147 {
148 // Note existing keyword data length
149 dataLength = *iterator;
150
151 // Jump past keyword length and data
152 std::advance(iterator, sizeof(KwSize));
153 }
154
155 if (thisRecord.recKWd == kw)
156 {
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500157 thisRecord.kwDataOffset = std::distance(vpdFile.cbegin(), iterator);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600158 thisRecord.kwdDataLength = dataLength;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600159 return;
160 }
161
162 // jump the data of current kwd to point to next kwd name
163 std::advance(iterator, dataLength);
164 }
165
166 throw std::runtime_error("Keyword not found");
167}
168
169void EditorImpl::updateRecordECC()
170{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500171 auto itrToRecordData = vpdFile.cbegin();
172 std::advance(itrToRecordData, thisRecord.recOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600173
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500174 auto itrToRecordECC = vpdFile.cbegin();
175 std::advance(itrToRecordECC, thisRecord.recECCoffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600176
177 auto l_status = vpdecc_create_ecc(
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500178 const_cast<uint8_t*>(&itrToRecordData[0]), thisRecord.recSize,
179 const_cast<uint8_t*>(&itrToRecordECC[0]), &thisRecord.recECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600180 if (l_status != VPD_ECC_OK)
181 {
182 throw std::runtime_error("Ecc update failed");
183 }
184
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500185 auto end = itrToRecordECC;
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600186 std::advance(end, thisRecord.recECCLength);
187
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500188#ifndef ManagerTest
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500189 vpdFileStream.seekp(thisRecord.recECCoffset, std::ios::beg);
190 std::copy(itrToRecordECC, end,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600191 std::ostreambuf_iterator<char>(vpdFileStream));
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500192#endif
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600193}
194
195auto EditorImpl::getValue(offsets::Offsets offset)
196{
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500197 auto itr = vpdFile.cbegin();
198 std::advance(itr, offset);
199 LE2ByteData lowByte = *itr;
200 LE2ByteData highByte = *(itr + 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600201 lowByte |= (highByte << 8);
202
203 return lowByte;
204}
205
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500206void EditorImpl::checkECC(Binary::const_iterator& itrToRecData,
207 Binary::const_iterator& itrToECCData,
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600208 RecordLength recLength, ECCLength eccLength)
209{
210 auto l_status =
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500211 vpdecc_check_data(const_cast<uint8_t*>(&itrToRecData[0]), recLength,
212 const_cast<uint8_t*>(&itrToECCData[0]), eccLength);
213
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600214 if (l_status != VPD_ECC_OK)
215 {
216 throw std::runtime_error("Ecc check failed for VTOC");
217 }
218}
219
220void EditorImpl::readVTOC()
221{
222 // read VTOC offset
223 RecordOffset tocOffset = getValue(offsets::VTOC_PTR);
224
225 // read VTOC record length
226 RecordLength tocLength = getValue(offsets::VTOC_REC_LEN);
227
228 // read TOC ecc offset
229 ECCOffset tocECCOffset = getValue(offsets::VTOC_ECC_OFF);
230
231 // read TOC ecc length
232 ECCLength tocECCLength = getValue(offsets::VTOC_ECC_LEN);
233
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500234 auto itrToRecord = vpdFile.cbegin();
235 std::advance(itrToRecord, tocOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600236
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500237 auto iteratorToECC = vpdFile.cbegin();
238 std::advance(iteratorToECC, tocECCOffset);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600239
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500240 // validate ecc for the record
241 checkECC(itrToRecord, iteratorToECC, tocLength, tocECCLength);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600242
243 // to get to the record name.
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500244 std::advance(itrToRecord, sizeof(RecordId) + sizeof(RecordSize) +
245 // Skip past the RT keyword, which contains
246 // the record name.
247 lengths::KW_NAME + sizeof(KwSize));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600248
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500249 std::string recordName(itrToRecord, itrToRecord + lengths::RECORD_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600250
251 if ("VTOC" != recordName)
252 {
253 throw std::runtime_error("VTOC record not found");
254 }
255
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600256 // jump to length of PT kwd
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500257 std::advance(itrToRecord, lengths::RECORD_NAME + lengths::KW_NAME);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600258
259 // Note size of PT
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500260 Byte ptLen = *itrToRecord;
261 std::advance(itrToRecord, 1);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600262
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500263 checkPTForRecord(itrToRecord, ptLen);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600264}
265
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600266template <typename T>
267void EditorImpl::makeDbusCall(const std::string& object,
268 const std::string& interface,
269 const std::string& property,
270 const std::variant<T>& data)
271{
272 auto bus = sdbusplus::bus::new_default();
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500273 auto properties =
274 bus.new_method_call(INVENTORY_MANAGER_SERVICE, object.c_str(),
275 "org.freedesktop.DBus.Properties", "Set");
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600276 properties.append(interface);
277 properties.append(property);
278 properties.append(data);
279
280 auto result = bus.call(properties);
281
282 if (result.is_method_error())
283 {
284 throw std::runtime_error("bus call failed");
285 }
286}
287
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600288void EditorImpl::processAndUpdateCI(const std::string& objectPath)
289{
290 for (auto& commonInterface : jsonFile["commonInterfaces"].items())
291 {
292 for (auto& ciPropertyList : commonInterface.value().items())
293 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600294 if (ciPropertyList.value().type() ==
295 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600296 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600297 if ((ciPropertyList.value().value("recordName", "") ==
298 thisRecord.recName) &&
299 (ciPropertyList.value().value("keywordName", "") ==
300 thisRecord.recKWd))
301 {
302 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
303 thisRecord.kwdUpdatedData.end());
304
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500305 makeDbusCall<std::string>((INVENTORY_PATH + objectPath),
306 commonInterface.key(),
307 ciPropertyList.key(), kwdData);
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600308 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600309 }
310 }
311 }
312}
313
314void EditorImpl::processAndUpdateEI(const nlohmann::json& Inventory,
315 const inventory::Path& objPath)
316{
317 for (const auto& extraInterface : Inventory["extraInterfaces"].items())
318 {
319 if (extraInterface.value() != NULL)
320 {
321 for (const auto& eiPropertyList : extraInterface.value().items())
322 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600323 if (eiPropertyList.value().type() ==
324 nlohmann::json::value_t::object)
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600325 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600326 if ((eiPropertyList.value().value("recordName", "") ==
327 thisRecord.recName) &&
328 ((eiPropertyList.value().value("keywordName", "") ==
329 thisRecord.recKWd)))
330 {
331 std::string kwdData(thisRecord.kwdUpdatedData.begin(),
332 thisRecord.kwdUpdatedData.end());
333 makeDbusCall<std::string>(
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500334 (INVENTORY_PATH + objPath), extraInterface.key(),
335 eiPropertyList.key(),
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600336 encodeKeyword(kwdData, eiPropertyList.value().value(
337 "encoding", "")));
338 }
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600339 }
340 }
341 }
342 }
343}
344
345void EditorImpl::updateCache()
346{
347 const std::vector<nlohmann::json>& groupEEPROM =
348 jsonFile["frus"][vpdFilePath].get_ref<const nlohmann::json::array_t&>();
349
350 // iterate through all the inventories for this file path
351 for (const auto& singleInventory : groupEEPROM)
352 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600353 // by default inherit property is true
354 bool isInherit = true;
355
356 if (singleInventory.find("inherit") != singleInventory.end())
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600357 {
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600358 isInherit = singleInventory["inherit"].get<bool>();
359 }
360
361 if (isInherit)
362 {
363 // update com interface
364 makeDbusCall<Binary>(
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500365 (INVENTORY_PATH +
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600366 singleInventory["inventoryPath"].get<std::string>()),
SunnySrivastava1984a7392592020-03-09 10:19:33 -0500367 (IPZ_INTERFACE + (std::string) "." + thisRecord.recName),
SunnySrivastava1984d076da82020-03-05 05:33:35 -0600368 thisRecord.recKWd, thisRecord.kwdUpdatedData);
369
370 // process Common interface
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600371 processAndUpdateCI(singleInventory["inventoryPath"]
372 .get_ref<const nlohmann::json::string_t&>());
373 }
374
375 // process extra interfaces
376 processAndUpdateEI(singleInventory,
377 singleInventory["inventoryPath"]
378 .get_ref<const nlohmann::json::string_t&>());
379 }
380}
381
SunnySrivastava198443306542020-04-01 02:50:20 -0500382void EditorImpl::expandLocationCode(const std::string& locationCodeType)
383{
384 std::string propertyFCorTM{};
385 std::string propertySE{};
386
387 if (locationCodeType == "fcs")
388 {
389 propertyFCorTM =
390 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
391 propertySE =
392 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "SE");
393 }
394 else if (locationCodeType == "mts")
395 {
396 propertyFCorTM =
397 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
398 propertySE =
399 readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "SE");
400 }
401
402 const nlohmann::json& groupFRUS =
403 jsonFile["frus"].get_ref<const nlohmann::json::object_t&>();
404 for (const auto& itemFRUS : groupFRUS.items())
405 {
406 const std::vector<nlohmann::json>& groupEEPROM =
407 itemFRUS.value().get_ref<const nlohmann::json::array_t&>();
408 for (const auto& itemEEPROM : groupEEPROM)
409 {
410 // check if the given item implements location code interface
411 if (itemEEPROM["extraInterfaces"].find(LOCATION_CODE_INF) !=
412 itemEEPROM["extraInterfaces"].end())
413 {
414 const std::string& unexpandedLocationCode =
415 itemEEPROM["extraInterfaces"][LOCATION_CODE_INF]
416 ["LocationCode"]
417 .get_ref<const nlohmann::json::string_t&>();
418 std::size_t idx = unexpandedLocationCode.find(locationCodeType);
419 if (idx != std::string::npos)
420 {
421 std::string expandedLoctionCode(unexpandedLocationCode);
422
423 if (locationCodeType == "fcs")
424 {
425 expandedLoctionCode.replace(
426 idx, 3,
427 propertyFCorTM.substr(0, 4) + ".ND0." + propertySE);
428 }
429 else if (locationCodeType == "mts")
430 {
431 std::replace(propertyFCorTM.begin(),
432 propertyFCorTM.end(), '-', '.');
433 expandedLoctionCode.replace(
434 idx, 3, propertyFCorTM + "." + propertySE);
435 }
436
437 // update the DBUS interface
438 makeDbusCall<std::string>(
439 (INVENTORY_PATH +
440 itemEEPROM["inventoryPath"]
441 .get_ref<const nlohmann::json::string_t&>()),
442 LOCATION_CODE_INF, "LocationCode", expandedLoctionCode);
443 }
444 }
445 }
446 }
447}
448
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600449void EditorImpl::updateKeyword(const Binary& kwdData)
450{
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500451
452#ifndef ManagerTest
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600453 vpdFileStream.open(vpdFilePath,
454 std::ios::in | std::ios::out | std::ios::binary);
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500455
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600456 if (!vpdFileStream)
457 {
458 throw std::runtime_error("unable to open vpd file to edit");
459 }
460
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500461 Binary completeVPDFile((std::istreambuf_iterator<char>(vpdFileStream)),
462 std::istreambuf_iterator<char>());
463 vpdFile = completeVPDFile;
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500464#else
465 Binary completeVPDFile = vpdFile;
466#endif
467 if (vpdFile.empty())
468 {
469 throw std::runtime_error("Invalid File");
470 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600471
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500472 auto iterator = vpdFile.cbegin();
473 std::advance(iterator, IPZ_DATA_START);
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600474
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500475 Byte vpdType = *iterator;
476 if (vpdType == KW_VAL_PAIR_START_TAG)
477 {
478 openpower::vpd::keyword::editor::processHeader(
479 std::move(completeVPDFile));
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600480
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500481 // process VTOC for PTT rkwd
482 readVTOC();
483
484 // check record for keywrod
485 checkRecordForKwd();
486
487 // update the data to the file
488 updateData(kwdData);
489
490 // update the ECC data for the record once data has been updated
491 updateRecordECC();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500492#ifndef ManagerTest
SunnySrivastava1984b421bfd2020-03-02 08:59:32 -0600493 // update the cache once data has been updated
494 updateCache();
SunnySrivastava1984a0d460e2020-06-03 07:49:26 -0500495#endif
SunnySrivastava19846d8314d2020-05-15 09:34:58 -0500496 return;
497 }
SunnySrivastava1984f6d541e2020-02-04 12:50:40 -0600498}
499
500} // namespace editor
501} // namespace manager
502} // namespace vpd
503} // namespace openpower