blob: d9e193aaedaa4fafdcdb87a93038536531237253 [file] [log] [blame]
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +05301#include "config.h"
2
Sunny Srivastava867ee752025-04-15 12:24:23 +05303#include "ibm_handler.hpp"
4
Anupama B R56e45372025-06-19 12:54:44 -05005#include "listener.hpp"
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +05306#include "parser.hpp"
7
Sunny Srivastava78a50422025-04-25 11:17:56 +05308#include <utility/common_utility.hpp>
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +05309#include <utility/dbus_utility.hpp>
10#include <utility/json_utility.hpp>
11#include <utility/vpd_specific_utility.hpp>
12
Sunny Srivastava867ee752025-04-15 12:24:23 +053013namespace vpd
14{
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053015IbmHandler::IbmHandler(
16 std::shared_ptr<Worker>& o_worker,
17 std::shared_ptr<BackupAndRestore>& o_backupAndRestoreObj,
18 const std::shared_ptr<sdbusplus::asio::dbus_interface>& i_iFace,
Anupama B Rda9806b2025-08-29 02:41:10 -050019 const std::shared_ptr<sdbusplus::asio::dbus_interface>& i_progressiFace,
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053020 const std::shared_ptr<boost::asio::io_context>& i_ioCon,
21 const std::shared_ptr<sdbusplus::asio::connection>& i_asioConnection) :
22 m_worker(o_worker), m_backupAndRestoreObj(o_backupAndRestoreObj),
Anupama B Rda9806b2025-08-29 02:41:10 -050023 m_interface(i_iFace), m_progressInterface(i_progressiFace),
Souvik Roya5e18b82025-09-25 05:59:56 +000024 m_ioContext(i_ioCon), m_asioConnection(i_asioConnection),
25 m_logger(Logger::getLoggerInstance())
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053026{
Souvik Royc1171732025-10-16 09:27:38 +000027 uint16_t l_errCode{0};
28
29 // check VPD collection mode
30 const auto l_vpdCollectionMode =
31 commonUtility::isFieldModeEnabled()
32 ? types::VpdCollectionMode::DEFAULT_MODE
33 : commonUtility::getVpdCollectionMode(l_errCode);
34
35 if (l_errCode)
36 {
37 m_logger->logMessage(
38 "Error while trying to read VPD collection mode: " +
39 commonUtility::getErrCodeMsg(l_errCode));
Souvik Royc1171732025-10-16 09:27:38 +000040 }
41
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053042 if (dbusUtility::isChassisPowerOn())
43 {
44 // At power on, less number of FRU(s) needs collection. we can scale
45 // down the threads to reduce CPU utilization.
Souvik Royc1171732025-10-16 09:27:38 +000046 m_worker = std::make_shared<Worker>(
47 INVENTORY_JSON_DEFAULT, constants::VALUE_1, l_vpdCollectionMode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053048 }
49 else
50 {
51 // Initialize with default configuration
Souvik Royc1171732025-10-16 09:27:38 +000052 m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT,
53 constants::MAX_THREADS,
54 l_vpdCollectionMode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053055 }
56
57 // Set up minimal things that is needed before bus name is claimed.
Sunny Srivastava78a50422025-04-25 11:17:56 +053058 performInitialSetup();
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053059
60 if (!m_sysCfgJsonObj.empty() &&
Rekha Aparna196e3082025-09-08 20:40:35 -050061 jsonUtility::isBackupAndRestoreRequired(m_sysCfgJsonObj, l_errCode))
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053062 {
63 try
64 {
65 m_backupAndRestoreObj =
66 std::make_shared<BackupAndRestore>(m_sysCfgJsonObj);
67 }
68 catch (const std::exception& l_ex)
69 {
70 logging::logMessage("Back up and restore instantiation failed. {" +
71 std::string(l_ex.what()) + "}");
72
73 EventLogger::createSyncPel(
74 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
75 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
76 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
77 }
78 }
Rekha Aparna196e3082025-09-08 20:40:35 -050079 else if (l_errCode)
80 {
81 logging::logMessage(
82 "Failed to check if backup & restore required. Error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +053083 commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna196e3082025-09-08 20:40:35 -050084 }
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053085
Anupama B Rc7565ed2025-06-19 02:08:39 -050086 // Instantiate Listener object
Anupama B R56e45372025-06-19 12:54:44 -050087 m_eventListener = std::make_shared<Listener>(m_worker, m_asioConnection);
88 m_eventListener->registerAssetTagChangeCallback();
89 m_eventListener->registerHostStateChangeCallback();
Souvik Roy5c3a1562025-07-02 01:39:44 -050090 m_eventListener->registerPresenceChangeCallback();
Anupama B Rc7565ed2025-06-19 02:08:39 -050091
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053092 // Instantiate GpioMonitor class
93 m_gpioMonitor =
94 std::make_shared<GpioMonitor>(m_sysCfgJsonObj, m_worker, m_ioContext);
95}
96
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053097void IbmHandler::SetTimerToDetectVpdCollectionStatus()
98{
99 // Keeping max retry for 2 minutes. TODO: Make it configurable based on
100 // system type.
101 static constexpr auto MAX_RETRY = 12;
102
103 static boost::asio::steady_timer l_timer(*m_ioContext);
104 static uint8_t l_timerRetry = 0;
105
106 auto l_asyncCancelled = l_timer.expires_after(std::chrono::seconds(10));
107
108 (l_asyncCancelled == 0)
109 ? logging::logMessage("Collection Timer started")
110 : logging::logMessage("Collection Timer re-started");
111
112 l_timer.async_wait([this](const boost::system::error_code& ec) {
113 if (ec == boost::asio::error::operation_aborted)
114 {
115 throw std::runtime_error(
116 "Timer to detect thread collection status was aborted");
117 }
118
119 if (ec)
120 {
121 throw std::runtime_error(
122 "Timer to detect thread collection failed");
123 }
124
125 if (m_worker->isAllFruCollectionDone())
126 {
127 // cancel the timer
128 l_timer.cancel();
129 processFailedEeproms();
130
131 // update VPD for powerVS system.
132 ConfigurePowerVsSystem();
133
134 std::cout << "m_worker->isSystemVPDOnDBus() completed" << std::endl;
Anupama B Rda9806b2025-08-29 02:41:10 -0500135 m_progressInterface->set_property(
136 "Status", std::string(constants::vpdCollectionCompleted));
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530137
138 if (m_backupAndRestoreObj)
139 {
140 m_backupAndRestoreObj->backupAndRestore();
141 }
Souvik Roy3d4af4a2025-06-23 04:45:27 -0500142
143 if (m_eventListener)
144 {
Souvik Roy762cdab2025-11-04 13:07:56 +0000145 // Check if system config JSON specifies
146 // correlatedPropertiesJson
147 if (m_sysCfgJsonObj.contains("correlatedPropertiesConfigPath"))
148 {
149 // register correlated properties callback with specific
150 // correlated properties JSON
151 m_eventListener->registerCorrPropCallBack(
152 m_sysCfgJsonObj["correlatedPropertiesConfigPath"]);
153 }
154 else
155 {
156 m_logger->logMessage(
157 "Correlated properties JSON path is not defined in system config JSON. Correlated properties listener is disabled.");
158 }
Souvik Roy3d4af4a2025-06-23 04:45:27 -0500159 }
Alpana Kumari138489f2025-11-10 08:59:20 -0600160#ifdef ENABLE_FILE_LOGGING
Souvik Roya5e18b82025-09-25 05:59:56 +0000161 // terminate collection logger
162 m_logger->terminateVpdCollectionLogging();
Alpana Kumari138489f2025-11-10 08:59:20 -0600163#endif
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530164 }
165 else
166 {
167 auto l_threadCount = m_worker->getActiveThreadCount();
168 if (l_timerRetry == MAX_RETRY)
169 {
170 l_timer.cancel();
171 logging::logMessage("Taking too long. Active thread = " +
172 std::to_string(l_threadCount));
Alpana Kumari138489f2025-11-10 08:59:20 -0600173#ifdef ENABLE_FILE_LOGGING
Souvik Roya5e18b82025-09-25 05:59:56 +0000174 // terminate collection logger
175 m_logger->terminateVpdCollectionLogging();
Alpana Kumari138489f2025-11-10 08:59:20 -0600176#endif
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530177 }
178 else
179 {
180 l_timerRetry++;
181 logging::logMessage("Collection is in progress for [" +
182 std::to_string(l_threadCount) + "] FRUs.");
183
184 SetTimerToDetectVpdCollectionStatus();
185 }
186 }
187 });
188}
189
190void IbmHandler::checkAndUpdatePowerVsVpd(
191 const nlohmann::json& i_powerVsJsonObj,
192 std::vector<std::string>& o_failedPathList)
193{
194 for (const auto& [l_fruPath, l_recJson] : i_powerVsJsonObj.items())
195 {
196 nlohmann::json l_sysCfgJsonObj{};
197 if (m_worker.get() != nullptr)
198 {
199 l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
200 }
201
202 // The utility method will handle emty JSON case. No explicit
203 // handling required here.
Rekha Aparna017567a2025-08-13 02:07:06 -0500204 uint16_t l_errCode = 0;
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530205 auto l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
Rekha Aparna017567a2025-08-13 02:07:06 -0500206 l_sysCfgJsonObj, l_fruPath, l_errCode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530207
208 // Mark it as failed if inventory path not found in JSON.
209 if (l_inventoryPath.empty())
210 {
Rekha Aparna017567a2025-08-13 02:07:06 -0500211 if (l_errCode)
212 {
213 logging::logMessage(
214 "Failed to get inventory object path from JSON for FRU [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530215 l_fruPath +
216 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna017567a2025-08-13 02:07:06 -0500217 }
218
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530219 o_failedPathList.push_back(l_fruPath);
220 continue;
221 }
222
223 // check if the FRU is present
224 if (!dbusUtility::isInventoryPresent(l_inventoryPath))
225 {
226 logging::logMessage(
227 "Inventory not present, skip updating part number. Path: " +
228 l_inventoryPath);
229 continue;
230 }
231
232 // check if the FRU needs CCIN check before updating PN.
233 if (l_recJson.contains("CCIN"))
234 {
235 const auto& l_ccinFromDbus =
Rekha Aparna80b674f2025-10-27 01:27:27 -0500236 vpdSpecificUtility::getCcinFromDbus(l_inventoryPath, l_errCode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530237
238 // Not an ideal situation as CCIN can't be empty.
239 if (l_ccinFromDbus.empty())
240 {
Rekha Aparna80b674f2025-10-27 01:27:27 -0500241 if (l_errCode)
242 {
243 m_logger->logMessage(
244 "Failed to get CCIN value from DBus, error : " +
245 commonUtility::getErrCodeMsg(l_errCode));
246 }
247
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530248 o_failedPathList.push_back(l_fruPath);
249 continue;
250 }
251
252 std::vector<std::string> l_ccinListFromJson = l_recJson["CCIN"];
253
254 if (find(l_ccinListFromJson.begin(), l_ccinListFromJson.end(),
255 l_ccinFromDbus) == l_ccinListFromJson.end())
256 {
257 // Don't update PN in this case.
258 continue;
259 }
260 }
261
262 for (const auto& [l_recordName, l_kwdJson] : l_recJson.items())
263 {
264 // Record name can't be CCIN, skip processing as it is there for PN
265 // update based on CCIN check.
266 if (l_recordName == constants::kwdCCIN)
267 {
268 continue;
269 }
270
271 for (const auto& [l_kwdName, l_kwdValue] : l_kwdJson.items())
272 {
273 // Is value of type array.
274 if (!l_kwdValue.is_array())
275 {
276 o_failedPathList.push_back(l_fruPath);
277 continue;
278 }
279
280 // Get current FRU Part number.
281 auto l_retVal = dbusUtility::readDbusProperty(
282 constants::pimServiceName, l_inventoryPath,
283 constants::viniInf, constants::kwdFN);
284
285 auto l_ptrToFn = std::get_if<types::BinaryVector>(&l_retVal);
286
287 if (!l_ptrToFn)
288 {
289 o_failedPathList.push_back(l_fruPath);
290 continue;
291 }
292
293 types::BinaryVector l_binaryKwdValue =
294 l_kwdValue.get<types::BinaryVector>();
295 if (l_binaryKwdValue == (*l_ptrToFn))
296 {
297 continue;
298 }
299
300 // Update part number only if required.
301 std::shared_ptr<Parser> l_parserObj =
302 std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
303 if (l_parserObj->updateVpdKeyword(std::make_tuple(
304 l_recordName, l_kwdName, l_binaryKwdValue)) ==
305 constants::FAILURE)
306 {
307 o_failedPathList.push_back(l_fruPath);
308 continue;
309 }
310
311 // update the Asset interface Spare part number explicitly.
312 if (!dbusUtility::callPIM(types::ObjectMap{
313 {l_inventoryPath,
314 {{constants::assetInf,
315 {{"SparePartNumber",
316 std::string(l_binaryKwdValue.begin(),
317 l_binaryKwdValue.end())}}}}}}))
318 {
319 logging::logMessage(
320 "Updating Spare Part Number under Asset interface failed for path [" +
321 l_inventoryPath + "]");
322 }
323
324 // Just needed for logging.
325 std::string l_initialPartNum((*l_ptrToFn).begin(),
326 (*l_ptrToFn).end());
327 std::string l_finalPartNum(l_binaryKwdValue.begin(),
328 l_binaryKwdValue.end());
329 logging::logMessage(
330 "FRU Part number updated for path [" + l_inventoryPath +
331 "]" + "From [" + l_initialPartNum + "]" + " to [" +
332 l_finalPartNum + "]");
333 }
334 }
335 }
336}
337
338void IbmHandler::ConfigurePowerVsSystem()
339{
340 std::vector<std::string> l_failedPathList;
341 try
342 {
343 types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
344 if (l_imValue.empty())
345 {
346 throw DbusException("Invalid IM value read from Dbus");
347 }
348
Rekha Aparnaed09af82025-10-22 20:34:41 -0500349 uint16_t l_errCode = 0;
350 if (!vpdSpecificUtility::isPowerVsConfiguration(l_imValue, l_errCode))
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530351 {
352 // TODO: Should booting be blocked in case of some
353 // misconfigurations?
Rekha Aparnaed09af82025-10-22 20:34:41 -0500354 if (l_errCode)
355 {
356 logging::logMessage(
357 "Failed to check if the system is powerVs Configuration, error : " +
358 commonUtility::getErrCodeMsg(l_errCode));
359 }
360
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530361 return;
362 }
363
364 const nlohmann::json& l_powerVsJsonObj =
Rekha Aparnaadf85262025-09-09 00:41:00 -0500365 jsonUtility::getPowerVsJson(l_imValue, l_errCode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530366
367 if (l_powerVsJsonObj.empty())
368 {
Rekha Aparnac6159a22025-10-09 12:20:20 +0530369 throw std::runtime_error("PowerVS Json not found. Error : " +
370 commonUtility::getErrCodeMsg(l_errCode));
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530371 }
372
373 checkAndUpdatePowerVsVpd(l_powerVsJsonObj, l_failedPathList);
374
375 if (!l_failedPathList.empty())
376 {
377 throw std::runtime_error(
378 "Part number update failed for following paths: ");
379 }
380 }
381 catch (const std::exception& l_ex)
382 {
383 // TODO log appropriate PEL
384 }
385}
386
387void IbmHandler::processFailedEeproms()
388{
389 if (m_worker.get() != nullptr)
390 {
391 // TODO:
392 // - iterate through list of EEPROMs for which thread creation has
393 // failed
394 // - For each failed EEPROM, trigger VPD collection
395 m_worker->getFailedEepromPaths().clear();
396 }
397}
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530398
Sunny Srivastava78a50422025-04-25 11:17:56 +0530399void IbmHandler::enableMuxChips()
400{
401 if (m_sysCfgJsonObj.empty())
402 {
403 // config JSON should not be empty at this point of execution.
404 throw std::runtime_error("Config JSON is empty. Can't enable muxes");
405 return;
406 }
407
408 if (!m_sysCfgJsonObj.contains("muxes"))
409 {
410 logging::logMessage("No mux defined for the system in config JSON");
411 return;
412 }
413
414 // iterate over each MUX detail and enable them.
415 for (const auto& item : m_sysCfgJsonObj["muxes"])
416 {
417 if (item.contains("holdidlepath"))
418 {
419 std::string cmd = "echo 0 > ";
420 cmd += item["holdidlepath"];
421
422 logging::logMessage("Enabling mux with command = " + cmd);
423
424 commonUtility::executeCmd(cmd);
425 continue;
426 }
427
428 logging::logMessage(
429 "Mux Entry does not have hold idle path. Can't enable the mux");
430 }
431}
432
433void IbmHandler::performInitialSetup()
434{
435 try
436 {
Anupama B R281e2d42025-05-05 10:05:13 -0500437 if (m_worker.get() == nullptr)
438 {
439 throw std::runtime_error(
440 "Worker object not found. Can't perform initial setup.");
441 }
442
443 m_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
Sunny Srivastava78a50422025-04-25 11:17:56 +0530444 if (!dbusUtility::isChassisPowerOn())
445 {
Anupama B R281e2d42025-05-05 10:05:13 -0500446 m_worker->setDeviceTreeAndJson();
447
448 // Since the above function setDeviceTreeAndJson can change the json
449 // which is used, we would need to reacquire the json object again
450 // here.
Sunny Srivastava78a50422025-04-25 11:17:56 +0530451 m_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
452 }
453
Anupama B R95083d42025-10-27 04:54:58 -0500454 // Update BMC postion for RBMC prototype system
455 // Ignore BMC position update in case of any error
456 uint16_t l_errCode = 0;
Anupama B R657aaa82025-10-30 04:12:24 -0500457 if (isRbmcPrototypeSystem(l_errCode))
Anupama B R95083d42025-10-27 04:54:58 -0500458 {
Anupama B R657aaa82025-10-30 04:12:24 -0500459 size_t l_bmcPosition = std::numeric_limits<size_t>::max();
460 checkAndUpdateBmcPosition(l_bmcPosition);
Anupama B R95083d42025-10-27 04:54:58 -0500461
Anupama B R657aaa82025-10-30 04:12:24 -0500462 if (dbusUtility::callPIM(types::ObjectMap{
463 {sdbusplus::message::object_path(constants::systemInvPath),
464 {{constants::rbmcPositionInterface,
465 {{"Position", l_bmcPosition}}}}}}))
466 {
467 m_logger->logMessage(
468 "Updating BMC position failed for path [" +
469 std::string(constants::systemInvPath) +
470 "], bmc position: " + std::to_string(l_bmcPosition));
471
472 // ToDo: Check is PEL required
473 }
474 }
475 else if (l_errCode != 0)
476 {
477 m_logger->logMessage(
478 "Unable to determine whether system is RBMC system or not, reason: " +
479 commonUtility::getErrCodeMsg(l_errCode));
Anupama B R95083d42025-10-27 04:54:58 -0500480 }
481
Sunny Srivastava78a50422025-04-25 11:17:56 +0530482 // Enable all mux which are used for connecting to the i2c on the
483 // pcie slots for pcie cards. These are not enabled by kernel due to
484 // an issue seen with Castello cards, where the i2c line hangs on a
485 // probe.
486 enableMuxChips();
487
488 // Nothing needs to be done. Service restarted or BMC re-booted for
489 // some reason at system power on.
Sunny Srivastava78a50422025-04-25 11:17:56 +0530490 }
491 catch (const std::exception& l_ex)
492 {
Anupama B R4c65fcd2025-09-01 08:09:00 -0500493 m_worker->setCollectionStatusProperty(SYSTEM_VPD_FILE_PATH,
494 constants::vpdCollectionFailed);
Sunny Srivastava78a50422025-04-25 11:17:56 +0530495 // Any issue in system's inital set up is handled in this catch. Error
496 // will not propogate to manager.
497 EventLogger::createSyncPel(
498 EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
499 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
500 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
501 }
502}
503
Anupama B R7127ab42025-06-26 01:39:08 -0500504void IbmHandler::collectAllFruVpd()
505{
506 // Setting status to "InProgress", before trigeering VPD collection.
Anupama B Rda9806b2025-08-29 02:41:10 -0500507 m_progressInterface->set_property(
508 "Status", std::string(constants::vpdCollectionInProgress));
Anupama B R7127ab42025-06-26 01:39:08 -0500509 m_worker->collectFrusFromJson();
510 SetTimerToDetectVpdCollectionStatus();
511}
Anupama B R95083d42025-10-27 04:54:58 -0500512
Anupama B R657aaa82025-10-30 04:12:24 -0500513bool IbmHandler::isRbmcPrototypeSystem(uint16_t& o_errCode) const noexcept
Anupama B R95083d42025-10-27 04:54:58 -0500514{
Anupama B R657aaa82025-10-30 04:12:24 -0500515 types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
516 if (l_imValue.empty())
517 {
518 o_errCode = error_code::DBUS_FAILURE;
519 return false;
520 }
521
522 if (constants::rbmcPrototypeSystemImValue == l_imValue)
523 {
524 return true;
525 }
Anupama B R95083d42025-10-27 04:54:58 -0500526
527 return false;
528}
529
Anupama B R657aaa82025-10-30 04:12:24 -0500530void IbmHandler::checkAndUpdateBmcPosition(size_t& o_bmcPosition) const noexcept
Anupama B R95083d42025-10-27 04:54:58 -0500531{
Anupama B R657aaa82025-10-30 04:12:24 -0500532 if (m_worker.get() == nullptr)
533 {
534 m_logger->logMessage("Worker object not found");
535 return;
536 }
Anupama B R95083d42025-10-27 04:54:58 -0500537
Anupama B R657aaa82025-10-30 04:12:24 -0500538 const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
539 if (l_sysCfgJsonObj.empty())
540 {
541 m_logger->logMessage(
542 "System config JSON is empty, unable to find BMC position");
543 return;
544 }
545
546 uint16_t l_errCode = 0;
547 std::string l_motherboardEepromPath = jsonUtility::getFruPathFromJson(
548 l_sysCfgJsonObj, constants::systemVpdInvPath, l_errCode);
549
550 if (!l_motherboardEepromPath.empty())
551 {
552 o_bmcPosition = constants::VALUE_1;
553 std::error_code l_ec;
554 if (std::filesystem::exists(l_motherboardEepromPath, l_ec))
555 {
556 o_bmcPosition = constants::VALUE_0;
557 }
558 }
559 else if (l_errCode)
560 {
561 m_logger->logMessage("Unable to determine BMC position, reason: " +
562 commonUtility::getErrCodeMsg(l_errCode));
563 }
564 else
565 {
566 m_logger->logMessage("Unable to determine BMC position, as FRU path[" +
567 std::string(constants::systemVpdInvPath) +
568 "], not found in the system config JSON.");
569 }
Anupama B R95083d42025-10-27 04:54:58 -0500570}
Sunny Srivastava867ee752025-04-15 12:24:23 +0530571} // namespace vpd