blob: 7d0c4d724d1d36682767d79f7a9505bfb244c42f [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));
40 l_errCode = 0;
41 }
42
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053043 if (dbusUtility::isChassisPowerOn())
44 {
45 // At power on, less number of FRU(s) needs collection. we can scale
46 // down the threads to reduce CPU utilization.
Souvik Royc1171732025-10-16 09:27:38 +000047 m_worker = std::make_shared<Worker>(
48 INVENTORY_JSON_DEFAULT, constants::VALUE_1, l_vpdCollectionMode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053049 }
50 else
51 {
52 // Initialize with default configuration
Souvik Royc1171732025-10-16 09:27:38 +000053 m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT,
54 constants::MAX_THREADS,
55 l_vpdCollectionMode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053056 }
57
58 // Set up minimal things that is needed before bus name is claimed.
Sunny Srivastava78a50422025-04-25 11:17:56 +053059 performInitialSetup();
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053060
61 if (!m_sysCfgJsonObj.empty() &&
Rekha Aparna196e3082025-09-08 20:40:35 -050062 jsonUtility::isBackupAndRestoreRequired(m_sysCfgJsonObj, l_errCode))
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053063 {
64 try
65 {
66 m_backupAndRestoreObj =
67 std::make_shared<BackupAndRestore>(m_sysCfgJsonObj);
68 }
69 catch (const std::exception& l_ex)
70 {
71 logging::logMessage("Back up and restore instantiation failed. {" +
72 std::string(l_ex.what()) + "}");
73
74 EventLogger::createSyncPel(
75 EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
76 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
77 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
78 }
79 }
Rekha Aparna196e3082025-09-08 20:40:35 -050080 else if (l_errCode)
81 {
82 logging::logMessage(
83 "Failed to check if backup & restore required. Error : " +
Rekha Aparnac6159a22025-10-09 12:20:20 +053084 commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna196e3082025-09-08 20:40:35 -050085 }
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053086
Anupama B Rc7565ed2025-06-19 02:08:39 -050087 // Instantiate Listener object
Anupama B R56e45372025-06-19 12:54:44 -050088 m_eventListener = std::make_shared<Listener>(m_worker, m_asioConnection);
89 m_eventListener->registerAssetTagChangeCallback();
90 m_eventListener->registerHostStateChangeCallback();
Souvik Roy5c3a1562025-07-02 01:39:44 -050091 m_eventListener->registerPresenceChangeCallback();
Anupama B Rc7565ed2025-06-19 02:08:39 -050092
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053093 // Instantiate GpioMonitor class
94 m_gpioMonitor =
95 std::make_shared<GpioMonitor>(m_sysCfgJsonObj, m_worker, m_ioContext);
96}
97
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +053098void IbmHandler::SetTimerToDetectVpdCollectionStatus()
99{
100 // Keeping max retry for 2 minutes. TODO: Make it configurable based on
101 // system type.
102 static constexpr auto MAX_RETRY = 12;
103
104 static boost::asio::steady_timer l_timer(*m_ioContext);
105 static uint8_t l_timerRetry = 0;
106
107 auto l_asyncCancelled = l_timer.expires_after(std::chrono::seconds(10));
108
109 (l_asyncCancelled == 0)
110 ? logging::logMessage("Collection Timer started")
111 : logging::logMessage("Collection Timer re-started");
112
113 l_timer.async_wait([this](const boost::system::error_code& ec) {
114 if (ec == boost::asio::error::operation_aborted)
115 {
116 throw std::runtime_error(
117 "Timer to detect thread collection status was aborted");
118 }
119
120 if (ec)
121 {
122 throw std::runtime_error(
123 "Timer to detect thread collection failed");
124 }
125
126 if (m_worker->isAllFruCollectionDone())
127 {
128 // cancel the timer
129 l_timer.cancel();
130 processFailedEeproms();
131
132 // update VPD for powerVS system.
133 ConfigurePowerVsSystem();
134
135 std::cout << "m_worker->isSystemVPDOnDBus() completed" << std::endl;
Anupama B Rda9806b2025-08-29 02:41:10 -0500136 m_progressInterface->set_property(
137 "Status", std::string(constants::vpdCollectionCompleted));
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530138
139 if (m_backupAndRestoreObj)
140 {
141 m_backupAndRestoreObj->backupAndRestore();
142 }
Souvik Roy3d4af4a2025-06-23 04:45:27 -0500143
144 if (m_eventListener)
145 {
146 m_eventListener->registerCorrPropCallBack();
147 }
Souvik Roya5e18b82025-09-25 05:59:56 +0000148
149 // terminate collection logger
150 m_logger->terminateVpdCollectionLogging();
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530151 }
152 else
153 {
154 auto l_threadCount = m_worker->getActiveThreadCount();
155 if (l_timerRetry == MAX_RETRY)
156 {
157 l_timer.cancel();
158 logging::logMessage("Taking too long. Active thread = " +
159 std::to_string(l_threadCount));
Souvik Roya5e18b82025-09-25 05:59:56 +0000160
161 // terminate collection logger
162 m_logger->terminateVpdCollectionLogging();
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530163 }
164 else
165 {
166 l_timerRetry++;
167 logging::logMessage("Collection is in progress for [" +
168 std::to_string(l_threadCount) + "] FRUs.");
169
170 SetTimerToDetectVpdCollectionStatus();
171 }
172 }
173 });
174}
175
176void IbmHandler::checkAndUpdatePowerVsVpd(
177 const nlohmann::json& i_powerVsJsonObj,
178 std::vector<std::string>& o_failedPathList)
179{
180 for (const auto& [l_fruPath, l_recJson] : i_powerVsJsonObj.items())
181 {
182 nlohmann::json l_sysCfgJsonObj{};
183 if (m_worker.get() != nullptr)
184 {
185 l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
186 }
187
188 // The utility method will handle emty JSON case. No explicit
189 // handling required here.
Rekha Aparna017567a2025-08-13 02:07:06 -0500190 uint16_t l_errCode = 0;
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530191 auto l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
Rekha Aparna017567a2025-08-13 02:07:06 -0500192 l_sysCfgJsonObj, l_fruPath, l_errCode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530193
194 // Mark it as failed if inventory path not found in JSON.
195 if (l_inventoryPath.empty())
196 {
Rekha Aparna017567a2025-08-13 02:07:06 -0500197 if (l_errCode)
198 {
199 logging::logMessage(
200 "Failed to get inventory object path from JSON for FRU [" +
Rekha Aparnac6159a22025-10-09 12:20:20 +0530201 l_fruPath +
202 "], error : " + commonUtility::getErrCodeMsg(l_errCode));
Rekha Aparna017567a2025-08-13 02:07:06 -0500203 }
204
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530205 o_failedPathList.push_back(l_fruPath);
206 continue;
207 }
208
209 // check if the FRU is present
210 if (!dbusUtility::isInventoryPresent(l_inventoryPath))
211 {
212 logging::logMessage(
213 "Inventory not present, skip updating part number. Path: " +
214 l_inventoryPath);
215 continue;
216 }
217
218 // check if the FRU needs CCIN check before updating PN.
219 if (l_recJson.contains("CCIN"))
220 {
Rekha Aparna80b674f2025-10-27 01:27:27 -0500221 l_errCode = 0;
222
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530223 const auto& l_ccinFromDbus =
Rekha Aparna80b674f2025-10-27 01:27:27 -0500224 vpdSpecificUtility::getCcinFromDbus(l_inventoryPath, l_errCode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530225
226 // Not an ideal situation as CCIN can't be empty.
227 if (l_ccinFromDbus.empty())
228 {
Rekha Aparna80b674f2025-10-27 01:27:27 -0500229 if (l_errCode)
230 {
231 m_logger->logMessage(
232 "Failed to get CCIN value from DBus, error : " +
233 commonUtility::getErrCodeMsg(l_errCode));
234 }
235
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530236 o_failedPathList.push_back(l_fruPath);
237 continue;
238 }
239
240 std::vector<std::string> l_ccinListFromJson = l_recJson["CCIN"];
241
242 if (find(l_ccinListFromJson.begin(), l_ccinListFromJson.end(),
243 l_ccinFromDbus) == l_ccinListFromJson.end())
244 {
245 // Don't update PN in this case.
246 continue;
247 }
248 }
249
250 for (const auto& [l_recordName, l_kwdJson] : l_recJson.items())
251 {
252 // Record name can't be CCIN, skip processing as it is there for PN
253 // update based on CCIN check.
254 if (l_recordName == constants::kwdCCIN)
255 {
256 continue;
257 }
258
259 for (const auto& [l_kwdName, l_kwdValue] : l_kwdJson.items())
260 {
261 // Is value of type array.
262 if (!l_kwdValue.is_array())
263 {
264 o_failedPathList.push_back(l_fruPath);
265 continue;
266 }
267
268 // Get current FRU Part number.
269 auto l_retVal = dbusUtility::readDbusProperty(
270 constants::pimServiceName, l_inventoryPath,
271 constants::viniInf, constants::kwdFN);
272
273 auto l_ptrToFn = std::get_if<types::BinaryVector>(&l_retVal);
274
275 if (!l_ptrToFn)
276 {
277 o_failedPathList.push_back(l_fruPath);
278 continue;
279 }
280
281 types::BinaryVector l_binaryKwdValue =
282 l_kwdValue.get<types::BinaryVector>();
283 if (l_binaryKwdValue == (*l_ptrToFn))
284 {
285 continue;
286 }
287
288 // Update part number only if required.
289 std::shared_ptr<Parser> l_parserObj =
290 std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
291 if (l_parserObj->updateVpdKeyword(std::make_tuple(
292 l_recordName, l_kwdName, l_binaryKwdValue)) ==
293 constants::FAILURE)
294 {
295 o_failedPathList.push_back(l_fruPath);
296 continue;
297 }
298
299 // update the Asset interface Spare part number explicitly.
300 if (!dbusUtility::callPIM(types::ObjectMap{
301 {l_inventoryPath,
302 {{constants::assetInf,
303 {{"SparePartNumber",
304 std::string(l_binaryKwdValue.begin(),
305 l_binaryKwdValue.end())}}}}}}))
306 {
307 logging::logMessage(
308 "Updating Spare Part Number under Asset interface failed for path [" +
309 l_inventoryPath + "]");
310 }
311
312 // Just needed for logging.
313 std::string l_initialPartNum((*l_ptrToFn).begin(),
314 (*l_ptrToFn).end());
315 std::string l_finalPartNum(l_binaryKwdValue.begin(),
316 l_binaryKwdValue.end());
317 logging::logMessage(
318 "FRU Part number updated for path [" + l_inventoryPath +
319 "]" + "From [" + l_initialPartNum + "]" + " to [" +
320 l_finalPartNum + "]");
321 }
322 }
323 }
324}
325
326void IbmHandler::ConfigurePowerVsSystem()
327{
328 std::vector<std::string> l_failedPathList;
329 try
330 {
331 types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
332 if (l_imValue.empty())
333 {
334 throw DbusException("Invalid IM value read from Dbus");
335 }
336
Rekha Aparnaed09af82025-10-22 20:34:41 -0500337 uint16_t l_errCode = 0;
338 if (!vpdSpecificUtility::isPowerVsConfiguration(l_imValue, l_errCode))
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530339 {
340 // TODO: Should booting be blocked in case of some
341 // misconfigurations?
Rekha Aparnaed09af82025-10-22 20:34:41 -0500342 if (l_errCode)
343 {
344 logging::logMessage(
345 "Failed to check if the system is powerVs Configuration, error : " +
346 commonUtility::getErrCodeMsg(l_errCode));
347 }
348
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530349 return;
350 }
351
352 const nlohmann::json& l_powerVsJsonObj =
Rekha Aparnaadf85262025-09-09 00:41:00 -0500353 jsonUtility::getPowerVsJson(l_imValue, l_errCode);
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530354
355 if (l_powerVsJsonObj.empty())
356 {
Rekha Aparnac6159a22025-10-09 12:20:20 +0530357 throw std::runtime_error("PowerVS Json not found. Error : " +
358 commonUtility::getErrCodeMsg(l_errCode));
Sunny Srivastavac74c8ef2025-04-16 12:45:27 +0530359 }
360
361 checkAndUpdatePowerVsVpd(l_powerVsJsonObj, l_failedPathList);
362
363 if (!l_failedPathList.empty())
364 {
365 throw std::runtime_error(
366 "Part number update failed for following paths: ");
367 }
368 }
369 catch (const std::exception& l_ex)
370 {
371 // TODO log appropriate PEL
372 }
373}
374
375void IbmHandler::processFailedEeproms()
376{
377 if (m_worker.get() != nullptr)
378 {
379 // TODO:
380 // - iterate through list of EEPROMs for which thread creation has
381 // failed
382 // - For each failed EEPROM, trigger VPD collection
383 m_worker->getFailedEepromPaths().clear();
384 }
385}
Sunny Srivastava380efbb2025-04-25 10:28:30 +0530386
Sunny Srivastava78a50422025-04-25 11:17:56 +0530387void IbmHandler::enableMuxChips()
388{
389 if (m_sysCfgJsonObj.empty())
390 {
391 // config JSON should not be empty at this point of execution.
392 throw std::runtime_error("Config JSON is empty. Can't enable muxes");
393 return;
394 }
395
396 if (!m_sysCfgJsonObj.contains("muxes"))
397 {
398 logging::logMessage("No mux defined for the system in config JSON");
399 return;
400 }
401
402 // iterate over each MUX detail and enable them.
403 for (const auto& item : m_sysCfgJsonObj["muxes"])
404 {
405 if (item.contains("holdidlepath"))
406 {
407 std::string cmd = "echo 0 > ";
408 cmd += item["holdidlepath"];
409
410 logging::logMessage("Enabling mux with command = " + cmd);
411
412 commonUtility::executeCmd(cmd);
413 continue;
414 }
415
416 logging::logMessage(
417 "Mux Entry does not have hold idle path. Can't enable the mux");
418 }
419}
420
421void IbmHandler::performInitialSetup()
422{
423 try
424 {
Anupama B R281e2d42025-05-05 10:05:13 -0500425 if (m_worker.get() == nullptr)
426 {
427 throw std::runtime_error(
428 "Worker object not found. Can't perform initial setup.");
429 }
430
431 m_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
Sunny Srivastava78a50422025-04-25 11:17:56 +0530432 if (!dbusUtility::isChassisPowerOn())
433 {
Anupama B R281e2d42025-05-05 10:05:13 -0500434 m_worker->setDeviceTreeAndJson();
435
436 // Since the above function setDeviceTreeAndJson can change the json
437 // which is used, we would need to reacquire the json object again
438 // here.
Sunny Srivastava78a50422025-04-25 11:17:56 +0530439 m_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
440 }
441
Anupama B R95083d42025-10-27 04:54:58 -0500442 // Update BMC postion for RBMC prototype system
443 // Ignore BMC position update in case of any error
444 uint16_t l_errCode = 0;
Anupama B R657aaa82025-10-30 04:12:24 -0500445 if (isRbmcPrototypeSystem(l_errCode))
Anupama B R95083d42025-10-27 04:54:58 -0500446 {
Anupama B R657aaa82025-10-30 04:12:24 -0500447 size_t l_bmcPosition = std::numeric_limits<size_t>::max();
448 checkAndUpdateBmcPosition(l_bmcPosition);
Anupama B R95083d42025-10-27 04:54:58 -0500449
Anupama B R657aaa82025-10-30 04:12:24 -0500450 if (dbusUtility::callPIM(types::ObjectMap{
451 {sdbusplus::message::object_path(constants::systemInvPath),
452 {{constants::rbmcPositionInterface,
453 {{"Position", l_bmcPosition}}}}}}))
454 {
455 m_logger->logMessage(
456 "Updating BMC position failed for path [" +
457 std::string(constants::systemInvPath) +
458 "], bmc position: " + std::to_string(l_bmcPosition));
459
460 // ToDo: Check is PEL required
461 }
462 }
463 else if (l_errCode != 0)
464 {
465 m_logger->logMessage(
466 "Unable to determine whether system is RBMC system or not, reason: " +
467 commonUtility::getErrCodeMsg(l_errCode));
Anupama B R95083d42025-10-27 04:54:58 -0500468 }
469
Sunny Srivastava78a50422025-04-25 11:17:56 +0530470 // Enable all mux which are used for connecting to the i2c on the
471 // pcie slots for pcie cards. These are not enabled by kernel due to
472 // an issue seen with Castello cards, where the i2c line hangs on a
473 // probe.
474 enableMuxChips();
475
476 // Nothing needs to be done. Service restarted or BMC re-booted for
477 // some reason at system power on.
Sunny Srivastava78a50422025-04-25 11:17:56 +0530478 }
479 catch (const std::exception& l_ex)
480 {
Anupama B R4c65fcd2025-09-01 08:09:00 -0500481 m_worker->setCollectionStatusProperty(SYSTEM_VPD_FILE_PATH,
482 constants::vpdCollectionFailed);
Sunny Srivastava78a50422025-04-25 11:17:56 +0530483 // Any issue in system's inital set up is handled in this catch. Error
484 // will not propogate to manager.
485 EventLogger::createSyncPel(
486 EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
487 __FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
488 std::nullopt, std::nullopt, std::nullopt, std::nullopt);
489 }
490}
491
Anupama B R7127ab42025-06-26 01:39:08 -0500492void IbmHandler::collectAllFruVpd()
493{
Souvik Roya5e18b82025-09-25 05:59:56 +0000494 // initialize VPD collection logger
495 m_logger->initiateVpdCollectionLogging();
496
Anupama B R7127ab42025-06-26 01:39:08 -0500497 // Setting status to "InProgress", before trigeering VPD collection.
Anupama B Rda9806b2025-08-29 02:41:10 -0500498 m_progressInterface->set_property(
499 "Status", std::string(constants::vpdCollectionInProgress));
Anupama B R7127ab42025-06-26 01:39:08 -0500500 m_worker->collectFrusFromJson();
501 SetTimerToDetectVpdCollectionStatus();
502}
Anupama B R95083d42025-10-27 04:54:58 -0500503
Anupama B R657aaa82025-10-30 04:12:24 -0500504bool IbmHandler::isRbmcPrototypeSystem(uint16_t& o_errCode) const noexcept
Anupama B R95083d42025-10-27 04:54:58 -0500505{
Anupama B R657aaa82025-10-30 04:12:24 -0500506 types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
507 if (l_imValue.empty())
508 {
509 o_errCode = error_code::DBUS_FAILURE;
510 return false;
511 }
512
513 if (constants::rbmcPrototypeSystemImValue == l_imValue)
514 {
515 return true;
516 }
Anupama B R95083d42025-10-27 04:54:58 -0500517
518 return false;
519}
520
Anupama B R657aaa82025-10-30 04:12:24 -0500521void IbmHandler::checkAndUpdateBmcPosition(size_t& o_bmcPosition) const noexcept
Anupama B R95083d42025-10-27 04:54:58 -0500522{
Anupama B R657aaa82025-10-30 04:12:24 -0500523 if (m_worker.get() == nullptr)
524 {
525 m_logger->logMessage("Worker object not found");
526 return;
527 }
Anupama B R95083d42025-10-27 04:54:58 -0500528
Anupama B R657aaa82025-10-30 04:12:24 -0500529 const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
530 if (l_sysCfgJsonObj.empty())
531 {
532 m_logger->logMessage(
533 "System config JSON is empty, unable to find BMC position");
534 return;
535 }
536
537 uint16_t l_errCode = 0;
538 std::string l_motherboardEepromPath = jsonUtility::getFruPathFromJson(
539 l_sysCfgJsonObj, constants::systemVpdInvPath, l_errCode);
540
541 if (!l_motherboardEepromPath.empty())
542 {
543 o_bmcPosition = constants::VALUE_1;
544 std::error_code l_ec;
545 if (std::filesystem::exists(l_motherboardEepromPath, l_ec))
546 {
547 o_bmcPosition = constants::VALUE_0;
548 }
549 }
550 else if (l_errCode)
551 {
552 m_logger->logMessage("Unable to determine BMC position, reason: " +
553 commonUtility::getErrCodeMsg(l_errCode));
554 }
555 else
556 {
557 m_logger->logMessage("Unable to determine BMC position, as FRU path[" +
558 std::string(constants::systemVpdInvPath) +
559 "], not found in the system config JSON.");
560 }
Anupama B R95083d42025-10-27 04:54:58 -0500561}
Sunny Srivastava867ee752025-04-15 12:24:23 +0530562} // namespace vpd