blob: a4be32c501128439ad1215fef5d09fa149f93b7f [file] [log] [blame]
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05001#include "config.h"
2
3#include "manager.hpp"
4
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -05005#include "constants.hpp"
6#include "exceptions.hpp"
7#include "logger.hpp"
8#include "parser.hpp"
9#include "parser_factory.hpp"
10#include "parser_interface.hpp"
Rekha Aparnaffdff312025-03-25 01:10:56 -050011#include "single_fab.hpp"
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050012#include "types.hpp"
13#include "utility/dbus_utility.hpp"
14#include "utility/json_utility.hpp"
15#include "utility/vpd_specific_utility.hpp"
16
17#include <boost/asio/steady_timer.hpp>
18#include <sdbusplus/bus/match.hpp>
19#include <sdbusplus/message.hpp>
20
21namespace vpd
22{
23Manager::Manager(
24 const std::shared_ptr<boost::asio::io_context>& ioCon,
25 const std::shared_ptr<sdbusplus::asio::dbus_interface>& iFace,
26 const std::shared_ptr<sdbusplus::asio::connection>& asioConnection) :
27 m_ioContext(ioCon), m_interface(iFace), m_asioConnection(asioConnection)
28{
Jinu Joy Thomas3419f5d2025-04-09 04:04:18 -050029#ifdef IBM_SYSTEM
Rekha Aparnaffdff312025-03-25 01:10:56 -050030 if (!dbusUtility::isChassisPowerOn())
31 {
32 SingleFab l_singleFab;
33 const int& l_rc = l_singleFab.singleFabImOverride();
34
35 if (l_rc == constants::FAILURE)
36 {
37 throw std::runtime_error(
38 std::string(__FUNCTION__) +
39 " : Found an invalid system configuration. Needs manual intervention. BMC is being quiesced.");
40 }
41 }
42#endif
43
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050044 try
45 {
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -050046 // For backward compatibility. Should be depricated.
47 iFace->register_method(
48 "WriteKeyword",
49 [this](const sdbusplus::message::object_path i_path,
50 const std::string i_recordName, const std::string i_keyword,
51 const types::BinaryVector i_value) -> int {
52 return this->updateKeyword(
53 i_path, std::make_tuple(i_recordName, i_keyword, i_value));
54 });
55
56 // Register methods under com.ibm.VPD.Manager interface
57 iFace->register_method(
58 "UpdateKeyword",
59 [this](const types::Path i_vpdPath,
60 const types::WriteVpdParams i_paramsToWriteData) -> int {
61 return this->updateKeyword(i_vpdPath, i_paramsToWriteData);
62 });
63
64 iFace->register_method(
65 "WriteKeywordOnHardware",
66 [this](const types::Path i_fruPath,
67 const types::WriteVpdParams i_paramsToWriteData) -> int {
68 return this->updateKeywordOnHardware(i_fruPath,
69 i_paramsToWriteData);
70 });
71
72 iFace->register_method(
73 "ReadKeyword",
74 [this](const types::Path i_fruPath,
75 const types::ReadVpdParams i_paramsToReadData)
76 -> types::DbusVariantType {
77 return this->readKeyword(i_fruPath, i_paramsToReadData);
78 });
79
80 iFace->register_method(
81 "CollectFRUVPD",
82 [this](const sdbusplus::message::object_path& i_dbusObjPath) {
83 this->collectSingleFruVpd(i_dbusObjPath);
84 });
85
86 iFace->register_method(
87 "deleteFRUVPD",
88 [this](const sdbusplus::message::object_path& i_dbusObjPath) {
89 this->deleteSingleFruVpd(i_dbusObjPath);
90 });
91
92 iFace->register_method(
93 "GetExpandedLocationCode",
94 [this](const std::string& i_unexpandedLocationCode,
95 uint16_t& i_nodeNumber) -> std::string {
96 return this->getExpandedLocationCode(i_unexpandedLocationCode,
97 i_nodeNumber);
98 });
99
100 iFace->register_method("GetFRUsByExpandedLocationCode",
101 [this](const std::string& i_expandedLocationCode)
102 -> types::ListOfPaths {
103 return this->getFrusByExpandedLocationCode(
104 i_expandedLocationCode);
105 });
106
107 iFace->register_method(
108 "GetFRUsByUnexpandedLocationCode",
109 [this](const std::string& i_unexpandedLocationCode,
110 uint16_t& i_nodeNumber) -> types::ListOfPaths {
111 return this->getFrusByUnexpandedLocationCode(
112 i_unexpandedLocationCode, i_nodeNumber);
113 });
114
115 iFace->register_method(
116 "GetHardwarePath",
117 [this](const sdbusplus::message::object_path& i_dbusObjPath)
118 -> std::string { return this->getHwPath(i_dbusObjPath); });
119
120 iFace->register_method("PerformVPDRecollection", [this]() {
121 this->performVpdRecollection();
122 });
123
Anupama B R7127ab42025-06-26 01:39:08 -0500124 iFace->register_method("CollectAllFRUVPD", [this]() -> bool {
125 return this->collectAllFruVpd();
126 });
127
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500128 // Indicates FRU VPD collection for the system has not started.
129 iFace->register_property_rw<std::string>(
130 "CollectionStatus", sdbusplus::vtable::property_::emits_change,
Souvik Roya6832472025-05-22 13:18:12 -0500131 [this](const std::string& l_currStatus, const auto&) {
Souvik Roy251d85e2025-05-26 04:30:30 -0500132 if (m_vpdCollectionStatus != l_currStatus)
133 {
134 m_vpdCollectionStatus = l_currStatus;
135 m_interface->signal_property("CollectionStatus");
136 }
Souvik Roya6832472025-05-22 13:18:12 -0500137 return true;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500138 },
139 [this](const auto&) { return m_vpdCollectionStatus; });
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530140
141 // If required, instantiate OEM specific handler here.
142#ifdef IBM_SYSTEM
143 m_ibmHandler = std::make_shared<IbmHandler>(
144 m_worker, m_backupAndRestoreObj, m_interface, m_ioContext,
145 m_asioConnection);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530146#else
147 m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT);
148 m_interface->set_property("CollectionStatus", std::string("Completed"));
149#endif
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500150 }
151 catch (const std::exception& e)
152 {
153 logging::logMessage(
Sunny Srivastava4c509c22025-03-25 12:43:40 +0530154 "Manager class instantiation failed. " + std::string(e.what()));
155
156 vpd::EventLogger::createSyncPel(
157 vpd::EventLogger::getErrorType(e), vpd::types::SeverityType::Error,
158 __FILE__, __FUNCTION__, 0, vpd::EventLogger::getErrorMsg(e),
159 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500160 }
161}
162
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500163int Manager::updateKeyword(const types::Path i_vpdPath,
164 const types::WriteVpdParams i_paramsToWriteData)
165{
166 if (i_vpdPath.empty())
167 {
168 logging::logMessage("Given VPD path is empty.");
169 return -1;
170 }
171
172 types::Path l_fruPath;
173 nlohmann::json l_sysCfgJsonObj{};
174
175 if (m_worker.get() != nullptr)
176 {
177 l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
178
179 // Get the EEPROM path
180 if (!l_sysCfgJsonObj.empty())
181 {
RekhaAparna017fea9f52025-02-17 04:14:02 -0600182 l_fruPath =
183 jsonUtility::getFruPathFromJson(l_sysCfgJsonObj, i_vpdPath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500184 }
185 }
186
187 if (l_fruPath.empty())
188 {
189 l_fruPath = i_vpdPath;
190 }
191
192 try
193 {
194 std::shared_ptr<Parser> l_parserObj =
195 std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
Souvik Roy9b0b0fd2025-08-08 05:20:23 +0000196
197 types::DbusVariantType l_updatedValue;
198 auto l_rc =
199 l_parserObj->updateVpdKeyword(i_paramsToWriteData, l_updatedValue);
Anupama B R8dedd1e2025-03-24 07:43:47 -0500200
201 if (l_rc != constants::FAILURE && m_backupAndRestoreObj)
202 {
203 if (m_backupAndRestoreObj->updateKeywordOnPrimaryOrBackupPath(
204 l_fruPath, i_paramsToWriteData) < constants::VALUE_0)
205 {
206 logging::logMessage(
207 "Write success, but backup and restore failed for file[" +
208 l_fruPath + "]");
209 }
210 }
Souvik Roy2ee8a212025-04-24 02:37:59 -0500211
Souvik Roy9b0b0fd2025-08-08 05:20:23 +0000212 types::WriteVpdParams l_writeParams;
213 types::BinaryVector l_valueToUpdate;
214
215 if (const types::IpzData* l_ipzData =
216 std::get_if<types::IpzData>(&i_paramsToWriteData))
217 {
218 if (const types::BinaryVector* l_val =
219 std::get_if<types::BinaryVector>(&l_updatedValue))
220 {
221 l_valueToUpdate = *l_val;
222 }
223 else
224 {
225 l_valueToUpdate = std::get<2>(*l_ipzData);
226 }
227 l_writeParams =
228 std::make_tuple(std::get<0>(*l_ipzData),
229 std::get<1>(*l_ipzData), l_valueToUpdate);
230 }
231 else if (const types::KwData* l_kwData =
232 std::get_if<types::KwData>(&i_paramsToWriteData))
233 {
234 if (const types::BinaryVector* l_val =
235 std::get_if<types::BinaryVector>(&l_updatedValue))
236 {
237 l_valueToUpdate = *l_val;
238 }
239 else
240 {
241 l_valueToUpdate = std::get<1>(*l_kwData);
242 }
243
244 l_writeParams =
245 std::make_tuple(std::get<0>(*l_kwData), l_valueToUpdate);
246 }
247
Souvik Roy2ee8a212025-04-24 02:37:59 -0500248 // update keyword in inherited FRUs
249 if (l_rc != constants::FAILURE)
250 {
251 vpdSpecificUtility::updateKwdOnInheritedFrus(
Souvik Roy9b0b0fd2025-08-08 05:20:23 +0000252 l_fruPath, l_writeParams, l_sysCfgJsonObj);
Souvik Roy2ee8a212025-04-24 02:37:59 -0500253 }
254
Souvik Roy96ebe962025-04-29 04:01:07 -0500255 // update common interface(s) properties
256 if (l_rc != constants::FAILURE)
257 {
258 vpdSpecificUtility::updateCiPropertyOfInheritedFrus(
Souvik Roy9b0b0fd2025-08-08 05:20:23 +0000259 l_fruPath, l_writeParams, l_sysCfgJsonObj);
Souvik Roy96ebe962025-04-29 04:01:07 -0500260 }
261
Anupama B R8dedd1e2025-03-24 07:43:47 -0500262 return l_rc;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500263 }
264 catch (const std::exception& l_exception)
265 {
266 // TODO:: error log needed
267 logging::logMessage("Update keyword failed for file[" + i_vpdPath +
268 "], reason: " + std::string(l_exception.what()));
269 return -1;
270 }
271}
272
273int Manager::updateKeywordOnHardware(
274 const types::Path i_fruPath,
275 const types::WriteVpdParams i_paramsToWriteData) noexcept
276{
277 try
278 {
279 if (i_fruPath.empty())
280 {
281 throw std::runtime_error("Given FRU path is empty");
282 }
283
284 nlohmann::json l_sysCfgJsonObj{};
285
286 if (m_worker.get() != nullptr)
287 {
288 l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
289 }
290
291 std::shared_ptr<Parser> l_parserObj =
292 std::make_shared<Parser>(i_fruPath, l_sysCfgJsonObj);
293 return l_parserObj->updateVpdKeywordOnHardware(i_paramsToWriteData);
294 }
295 catch (const std::exception& l_exception)
296 {
297 EventLogger::createAsyncPel(
298 types::ErrorType::InvalidEeprom, types::SeverityType::Informational,
299 __FILE__, __FUNCTION__, 0,
300 "Update keyword on hardware failed for file[" + i_fruPath +
301 "], reason: " + std::string(l_exception.what()),
302 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
303
304 return constants::FAILURE;
305 }
306}
307
308types::DbusVariantType Manager::readKeyword(
309 const types::Path i_fruPath, const types::ReadVpdParams i_paramsToReadData)
310{
311 try
312 {
313 nlohmann::json l_jsonObj{};
314
315 if (m_worker.get() != nullptr)
316 {
317 l_jsonObj = m_worker->getSysCfgJsonObj();
318 }
319
320 std::error_code ec;
321
322 // Check if given path is filesystem path
323 if (!std::filesystem::exists(i_fruPath, ec) && (ec))
324 {
325 throw std::runtime_error(
326 "Given file path " + i_fruPath + " not found.");
327 }
328
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500329 std::shared_ptr<vpd::Parser> l_parserObj =
330 std::make_shared<vpd::Parser>(i_fruPath, l_jsonObj);
331
332 std::shared_ptr<vpd::ParserInterface> l_vpdParserInstance =
333 l_parserObj->getVpdParserInstance();
334
335 return (
336 l_vpdParserInstance->readKeywordFromHardware(i_paramsToReadData));
337 }
338 catch (const std::exception& e)
339 {
340 logging::logMessage(
341 e.what() + std::string(". VPD manager read operation failed for ") +
342 i_fruPath);
343 throw types::DeviceError::ReadFailure();
344 }
345}
346
347void Manager::collectSingleFruVpd(
348 const sdbusplus::message::object_path& i_dbusObjPath)
349{
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530350 if (m_vpdCollectionStatus != "Completed")
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500351 {
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530352 logging::logMessage(
353 "Currently VPD CollectionStatus is not completed. Cannot perform single FRU VPD collection for " +
354 std::string(i_dbusObjPath));
355 return;
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500356 }
Priyanga Ramasamy46b73d92025-01-09 10:52:07 -0600357
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530358 if (m_worker.get() != nullptr)
359 {
360 m_worker->collectSingleFruVpd(i_dbusObjPath);
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500361 }
362}
363
364void Manager::deleteSingleFruVpd(
365 const sdbusplus::message::object_path& i_dbusObjPath)
366{
367 try
368 {
369 if (std::string(i_dbusObjPath).empty())
370 {
371 throw std::runtime_error(
372 "Given DBus object path is empty. Aborting FRU VPD deletion.");
373 }
374
375 if (m_worker.get() == nullptr)
376 {
377 throw std::runtime_error(
378 "Worker object not found, can't perform FRU VPD deletion for: " +
379 std::string(i_dbusObjPath));
380 }
381
382 m_worker->deleteFruVpd(std::string(i_dbusObjPath));
383 }
384 catch (const std::exception& l_ex)
385 {
386 // TODO: Log PEL
387 logging::logMessage(l_ex.what());
388 }
389}
390
391bool Manager::isValidUnexpandedLocationCode(
392 const std::string& i_unexpandedLocationCode)
393{
394 if ((i_unexpandedLocationCode.length() <
395 constants::UNEXP_LOCATION_CODE_MIN_LENGTH) ||
396 ((i_unexpandedLocationCode.compare(0, 4, "Ufcs") !=
397 constants::STR_CMP_SUCCESS) &&
398 (i_unexpandedLocationCode.compare(0, 4, "Umts") !=
399 constants::STR_CMP_SUCCESS)) ||
400 ((i_unexpandedLocationCode.length() >
401 constants::UNEXP_LOCATION_CODE_MIN_LENGTH) &&
402 (i_unexpandedLocationCode.find("-") != 4)))
403 {
404 return false;
405 }
406
407 return true;
408}
409
410std::string Manager::getExpandedLocationCode(
411 const std::string& i_unexpandedLocationCode,
412 [[maybe_unused]] const uint16_t i_nodeNumber)
413{
414 if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
415 {
416 phosphor::logging::elog<types::DbusInvalidArgument>(
417 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
418 types::InvalidArgument::ARGUMENT_VALUE(
419 i_unexpandedLocationCode.c_str()));
420 }
421
422 const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
423 if (!l_sysCfgJsonObj.contains("frus"))
424 {
425 logging::logMessage("Missing frus tag in system config JSON");
426 }
427
428 const nlohmann::json& l_listOfFrus =
429 l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
430
431 for (const auto& l_frus : l_listOfFrus.items())
432 {
433 for (const auto& l_aFru : l_frus.value())
434 {
435 if (l_aFru["extraInterfaces"].contains(
436 constants::locationCodeInf) &&
437 l_aFru["extraInterfaces"][constants::locationCodeInf].value(
438 "LocationCode", "") == i_unexpandedLocationCode)
439 {
440 return std::get<std::string>(dbusUtility::readDbusProperty(
441 l_aFru["serviceName"], l_aFru["inventoryPath"],
442 constants::locationCodeInf, "LocationCode"));
443 }
444 }
445 }
446 phosphor::logging::elog<types::DbusInvalidArgument>(
447 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
448 types::InvalidArgument::ARGUMENT_VALUE(
449 i_unexpandedLocationCode.c_str()));
450}
451
452types::ListOfPaths Manager::getFrusByUnexpandedLocationCode(
453 const std::string& i_unexpandedLocationCode,
454 [[maybe_unused]] const uint16_t i_nodeNumber)
455{
456 types::ListOfPaths l_inventoryPaths;
457
458 if (!isValidUnexpandedLocationCode(i_unexpandedLocationCode))
459 {
460 phosphor::logging::elog<types::DbusInvalidArgument>(
461 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
462 types::InvalidArgument::ARGUMENT_VALUE(
463 i_unexpandedLocationCode.c_str()));
464 }
465
466 const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
467 if (!l_sysCfgJsonObj.contains("frus"))
468 {
469 logging::logMessage("Missing frus tag in system config JSON");
470 }
471
472 const nlohmann::json& l_listOfFrus =
473 l_sysCfgJsonObj["frus"].get_ref<const nlohmann::json::object_t&>();
474
475 for (const auto& l_frus : l_listOfFrus.items())
476 {
477 for (const auto& l_aFru : l_frus.value())
478 {
479 if (l_aFru["extraInterfaces"].contains(
480 constants::locationCodeInf) &&
481 l_aFru["extraInterfaces"][constants::locationCodeInf].value(
482 "LocationCode", "") == i_unexpandedLocationCode)
483 {
484 l_inventoryPaths.push_back(
485 l_aFru.at("inventoryPath")
486 .get_ref<const nlohmann::json::string_t&>());
487 }
488 }
489 }
490
491 if (l_inventoryPaths.empty())
492 {
493 phosphor::logging::elog<types::DbusInvalidArgument>(
494 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
495 types::InvalidArgument::ARGUMENT_VALUE(
496 i_unexpandedLocationCode.c_str()));
497 }
498
499 return l_inventoryPaths;
500}
501
Patrick Williams43fedab2025-02-03 14:28:05 -0500502std::string Manager::getHwPath(
503 const sdbusplus::message::object_path& i_dbusObjPath)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500504{
505 // Dummy code to supress unused variable warning. To be removed.
506 logging::logMessage(std::string(i_dbusObjPath));
507
508 return std::string{};
509}
510
511std::tuple<std::string, uint16_t> Manager::getUnexpandedLocationCode(
512 const std::string& i_expandedLocationCode)
513{
514 /**
515 * Location code should always start with U and fulfil minimum length
516 * criteria.
517 */
518 if (i_expandedLocationCode[0] != 'U' ||
519 i_expandedLocationCode.length() <
520 constants::EXP_LOCATION_CODE_MIN_LENGTH)
521 {
522 phosphor::logging::elog<types::DbusInvalidArgument>(
523 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
524 types::InvalidArgument::ARGUMENT_VALUE(
525 i_expandedLocationCode.c_str()));
526 }
527
528 std::string l_fcKwd;
529
530 auto l_fcKwdValue = dbusUtility::readDbusProperty(
531 "xyz.openbmc_project.Inventory.Manager",
532 "/xyz/openbmc_project/inventory/system/chassis/motherboard",
533 "com.ibm.ipzvpd.VCEN", "FC");
534
535 if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_fcKwdValue))
536 {
537 l_fcKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
538 }
539
540 // Get the first part of expanded location code to check for FC or TM.
541 std::string l_firstKwd = i_expandedLocationCode.substr(1, 4);
542
543 std::string l_unexpandedLocationCode{};
544 uint16_t l_nodeNummber = constants::INVALID_NODE_NUMBER;
545
546 // Check if this value matches the value of FC keyword.
547 if (l_fcKwd.substr(0, 4) == l_firstKwd)
548 {
549 /**
550 * Period(.) should be there in expanded location code to seggregate
551 * FC, node number and SE values.
552 */
553 size_t l_nodeStartPos = i_expandedLocationCode.find('.');
554 if (l_nodeStartPos == std::string::npos)
555 {
556 phosphor::logging::elog<types::DbusInvalidArgument>(
557 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
558 types::InvalidArgument::ARGUMENT_VALUE(
559 i_expandedLocationCode.c_str()));
560 }
561
562 size_t l_nodeEndPos =
563 i_expandedLocationCode.find('.', l_nodeStartPos + 1);
564 if (l_nodeEndPos == std::string::npos)
565 {
566 phosphor::logging::elog<types::DbusInvalidArgument>(
567 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
568 types::InvalidArgument::ARGUMENT_VALUE(
569 i_expandedLocationCode.c_str()));
570 }
571
572 // Skip 3 bytes for '.ND'
573 l_nodeNummber = std::stoi(i_expandedLocationCode.substr(
574 l_nodeStartPos + 3, (l_nodeEndPos - l_nodeStartPos - 3)));
575
576 /**
577 * Confirm if there are other details apart FC, node number and SE
578 * in location code
579 */
580 if (i_expandedLocationCode.length() >
581 constants::EXP_LOCATION_CODE_MIN_LENGTH)
582 {
583 l_unexpandedLocationCode =
584 i_expandedLocationCode[0] + std::string("fcs") +
585 i_expandedLocationCode.substr(
586 l_nodeEndPos + 1 + constants::SE_KWD_LENGTH,
587 std::string::npos);
588 }
589 else
590 {
591 l_unexpandedLocationCode = "Ufcs";
592 }
593 }
594 else
595 {
596 std::string l_tmKwd;
597 // Read TM keyword value.
598 auto l_tmKwdValue = dbusUtility::readDbusProperty(
599 "xyz.openbmc_project.Inventory.Manager",
600 "/xyz/openbmc_project/inventory/system/chassis/motherboard",
601 "com.ibm.ipzvpd.VSYS", "TM");
602
603 if (auto l_kwdValue = std::get_if<types::BinaryVector>(&l_tmKwdValue))
604 {
605 l_tmKwd.assign(l_kwdValue->begin(), l_kwdValue->end());
606 }
607
608 // Check if the substr matches to TM keyword value.
609 if (l_tmKwd.substr(0, 4) == l_firstKwd)
610 {
611 /**
612 * System location code will not have node number and any other
613 * details.
614 */
615 l_unexpandedLocationCode = "Umts";
616 }
617 // The given location code is neither "fcs" or "mts".
618 else
619 {
620 phosphor::logging::elog<types::DbusInvalidArgument>(
621 types::InvalidArgument::ARGUMENT_NAME("LOCATIONCODE"),
622 types::InvalidArgument::ARGUMENT_VALUE(
623 i_expandedLocationCode.c_str()));
624 }
625 }
626
627 return std::make_tuple(l_unexpandedLocationCode, l_nodeNummber);
628}
629
630types::ListOfPaths Manager::getFrusByExpandedLocationCode(
631 const std::string& i_expandedLocationCode)
632{
633 std::tuple<std::string, uint16_t> l_locationAndNodePair =
634 getUnexpandedLocationCode(i_expandedLocationCode);
635
636 return getFrusByUnexpandedLocationCode(std::get<0>(l_locationAndNodePair),
637 std::get<1>(l_locationAndNodePair));
638}
639
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500640void Manager::performVpdRecollection()
641{
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530642 if (m_worker.get() != nullptr)
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500643 {
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530644 m_worker->performVpdRecollection();
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500645 }
646}
Anupama B R7127ab42025-06-26 01:39:08 -0500647
648bool Manager::collectAllFruVpd() const noexcept
649{
650 try
651 {
652 types::SeverityType l_severityType;
653 if (m_vpdCollectionStatus == "NotStarted")
654 {
655 l_severityType = types::SeverityType::Informational;
656 }
657 else if (m_vpdCollectionStatus == "Completed" ||
658 m_vpdCollectionStatus == "Failure")
659 {
660 l_severityType = types::SeverityType::Warning;
661 }
662 else
663 {
664 throw std::runtime_error(
665 "Invalid collection status " + m_vpdCollectionStatus +
666 ". Aborting all FRUs VPD collection.");
667 }
668
669 EventLogger::createSyncPel(
670 types::ErrorType::FirmwareError, l_severityType, __FILE__,
671 __FUNCTION__, 0, "Collect all FRUs VPD is requested.", std::nullopt,
672 std::nullopt, std::nullopt, std::nullopt);
673
Anupama B Rb6787bf2025-07-16 01:36:53 -0500674// ToDo: Handle with OEM interface
675#ifdef IBM_SYSTEM
Anupama B R7127ab42025-06-26 01:39:08 -0500676 if (m_ibmHandler.get() != nullptr)
677 {
678 m_ibmHandler->collectAllFruVpd();
679 return true;
680 }
681 else
682 {
683 throw std::runtime_error(
684 "Not found any OEM handler to collect all FRUs VPD.");
685 }
Anupama B Rb6787bf2025-07-16 01:36:53 -0500686#endif
Anupama B R7127ab42025-06-26 01:39:08 -0500687 }
688 catch (const std::exception& l_ex)
689 {
690 EventLogger::createSyncPel(
691 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
692 __FILE__, __FUNCTION__, 0, std::string(l_ex.what()), std::nullopt,
693 std::nullopt, std::nullopt, std::nullopt);
694 }
695 return false;
696}
Sunny Srivastavafa5e4d32023-03-12 11:59:49 -0500697} // namespace vpd