blob: fa3f0645827e010e7f1a98abd1e1f72eb535b702 [file] [log] [blame]
#include "config.h"
#include "ibm_handler.hpp"
#include "configuration.hpp"
#include "listener.hpp"
#include "parser.hpp"
#include <utility/common_utility.hpp>
#include <utility/dbus_utility.hpp>
#include <utility/json_utility.hpp>
#include <utility/vpd_specific_utility.hpp>
namespace vpd
{
IbmHandler::IbmHandler(
std::shared_ptr<Worker>& o_worker,
std::shared_ptr<BackupAndRestore>& o_backupAndRestoreObj,
const std::shared_ptr<sdbusplus::asio::dbus_interface>& i_iFace,
const std::shared_ptr<sdbusplus::asio::dbus_interface>& i_progressiFace,
const std::shared_ptr<boost::asio::io_context>& i_ioCon,
const std::shared_ptr<sdbusplus::asio::connection>& i_asioConnection) :
m_worker(o_worker), m_backupAndRestoreObj(o_backupAndRestoreObj),
m_interface(i_iFace), m_progressInterface(i_progressiFace),
m_ioContext(i_ioCon), m_asioConnection(i_asioConnection),
m_logger(Logger::getLoggerInstance())
{
uint16_t l_errCode{0};
// check VPD collection mode
const auto l_vpdCollectionMode =
commonUtility::isFieldModeEnabled()
? types::VpdCollectionMode::DEFAULT_MODE
: commonUtility::getVpdCollectionMode(l_errCode);
if (l_errCode)
{
m_logger->logMessage(
"Error while trying to read VPD collection mode: " +
commonUtility::getErrCodeMsg(l_errCode));
}
if (dbusUtility::isChassisPowerOn())
{
// At power on, less number of FRU(s) needs collection. we can scale
// down the threads to reduce CPU utilization.
m_worker = std::make_shared<Worker>(
INVENTORY_JSON_DEFAULT, constants::VALUE_1, l_vpdCollectionMode);
}
else
{
// Initialize with default configuration
m_worker = std::make_shared<Worker>(INVENTORY_JSON_DEFAULT,
constants::MAX_THREADS,
l_vpdCollectionMode);
}
// Set up minimal things that is needed before bus name is claimed.
performInitialSetup();
// If the object is created, implies back up and restore took place in
// system VPD flow.
if ((m_backupAndRestoreObj == nullptr) && !m_sysCfgJsonObj.empty() &&
jsonUtility::isBackupAndRestoreRequired(m_sysCfgJsonObj, l_errCode))
{
try
{
m_backupAndRestoreObj =
std::make_shared<BackupAndRestore>(m_sysCfgJsonObj);
}
catch (const std::exception& l_ex)
{
logging::logMessage("Back up and restore instantiation failed. {" +
std::string(l_ex.what()) + "}");
EventLogger::createSyncPel(
EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
__FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
std::nullopt, std::nullopt, std::nullopt, std::nullopt);
}
}
else if (l_errCode)
{
logging::logMessage(
"Failed to check if backup & restore required. Error : " +
commonUtility::getErrCodeMsg(l_errCode));
}
// Instantiate Listener object
m_eventListener = std::make_shared<Listener>(m_worker, m_asioConnection);
m_eventListener->registerAssetTagChangeCallback();
m_eventListener->registerHostStateChangeCallback();
m_eventListener->registerPresenceChangeCallback();
// Instantiate GpioMonitor class
m_gpioMonitor =
std::make_shared<GpioMonitor>(m_sysCfgJsonObj, m_worker, m_ioContext);
}
void IbmHandler::SetTimerToDetectVpdCollectionStatus()
{
// Keeping max retry for 2 minutes. TODO: Make it configurable based on
// system type.
static constexpr auto MAX_RETRY = 12;
static boost::asio::steady_timer l_timer(*m_ioContext);
static uint8_t l_timerRetry = 0;
auto l_asyncCancelled = l_timer.expires_after(std::chrono::seconds(10));
(l_asyncCancelled == 0)
? logging::logMessage("Collection Timer started")
: logging::logMessage("Collection Timer re-started");
l_timer.async_wait([this](const boost::system::error_code& ec) {
if (ec == boost::asio::error::operation_aborted)
{
throw std::runtime_error(
"Timer to detect thread collection status was aborted");
}
if (ec)
{
throw std::runtime_error(
"Timer to detect thread collection failed");
}
if (m_worker->isAllFruCollectionDone())
{
// cancel the timer
l_timer.cancel();
processFailedEeproms();
// update VPD for powerVS system.
ConfigurePowerVsSystem();
std::cout << "m_worker->isSystemVPDOnDBus() completed" << std::endl;
m_progressInterface->set_property(
"Status", std::string(constants::vpdCollectionCompleted));
if (m_backupAndRestoreObj)
{
m_backupAndRestoreObj->backupAndRestore();
}
if (m_eventListener)
{
// Check if system config JSON specifies
// correlatedPropertiesJson
if (m_sysCfgJsonObj.contains("correlatedPropertiesConfigPath"))
{
// register correlated properties callback with specific
// correlated properties JSON
m_eventListener->registerCorrPropCallBack(
m_sysCfgJsonObj["correlatedPropertiesConfigPath"]);
}
else
{
m_logger->logMessage(
"Correlated properties JSON path is not defined in system config JSON. Correlated properties listener is disabled.");
}
}
#ifdef ENABLE_FILE_LOGGING
// terminate collection logger
m_logger->terminateVpdCollectionLogging();
#endif
}
else
{
auto l_threadCount = m_worker->getActiveThreadCount();
if (l_timerRetry == MAX_RETRY)
{
l_timer.cancel();
logging::logMessage("Taking too long. Active thread = " +
std::to_string(l_threadCount));
#ifdef ENABLE_FILE_LOGGING
// terminate collection logger
m_logger->terminateVpdCollectionLogging();
#endif
}
else
{
l_timerRetry++;
logging::logMessage("Collection is in progress for [" +
std::to_string(l_threadCount) + "] FRUs.");
SetTimerToDetectVpdCollectionStatus();
}
}
});
}
void IbmHandler::checkAndUpdatePowerVsVpd(
const nlohmann::json& i_powerVsJsonObj,
std::vector<std::string>& o_failedPathList)
{
for (const auto& [l_fruPath, l_recJson] : i_powerVsJsonObj.items())
{
nlohmann::json l_sysCfgJsonObj{};
if (m_worker.get() != nullptr)
{
l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
}
// The utility method will handle emty JSON case. No explicit
// handling required here.
uint16_t l_errCode = 0;
auto l_inventoryPath = jsonUtility::getInventoryObjPathFromJson(
l_sysCfgJsonObj, l_fruPath, l_errCode);
// Mark it as failed if inventory path not found in JSON.
if (l_inventoryPath.empty())
{
if (l_errCode)
{
logging::logMessage(
"Failed to get inventory object path from JSON for FRU [" +
l_fruPath +
"], error : " + commonUtility::getErrCodeMsg(l_errCode));
}
o_failedPathList.push_back(l_fruPath);
continue;
}
// check if the FRU is present
if (!dbusUtility::isInventoryPresent(l_inventoryPath))
{
logging::logMessage(
"Inventory not present, skip updating part number. Path: " +
l_inventoryPath);
continue;
}
// check if the FRU needs CCIN check before updating PN.
if (l_recJson.contains("CCIN"))
{
const auto& l_ccinFromDbus =
vpdSpecificUtility::getCcinFromDbus(l_inventoryPath, l_errCode);
// Not an ideal situation as CCIN can't be empty.
if (l_ccinFromDbus.empty())
{
if (l_errCode)
{
m_logger->logMessage(
"Failed to get CCIN value from DBus, error : " +
commonUtility::getErrCodeMsg(l_errCode));
}
o_failedPathList.push_back(l_fruPath);
continue;
}
std::vector<std::string> l_ccinListFromJson = l_recJson["CCIN"];
if (find(l_ccinListFromJson.begin(), l_ccinListFromJson.end(),
l_ccinFromDbus) == l_ccinListFromJson.end())
{
// Don't update PN in this case.
continue;
}
}
for (const auto& [l_recordName, l_kwdJson] : l_recJson.items())
{
// Record name can't be CCIN, skip processing as it is there for PN
// update based on CCIN check.
if (l_recordName == constants::kwdCCIN)
{
continue;
}
for (const auto& [l_kwdName, l_kwdValue] : l_kwdJson.items())
{
// Is value of type array.
if (!l_kwdValue.is_array())
{
o_failedPathList.push_back(l_fruPath);
continue;
}
// Get current FRU Part number.
auto l_retVal = dbusUtility::readDbusProperty(
constants::pimServiceName, l_inventoryPath,
constants::viniInf, constants::kwdFN);
auto l_ptrToFn = std::get_if<types::BinaryVector>(&l_retVal);
if (!l_ptrToFn)
{
o_failedPathList.push_back(l_fruPath);
continue;
}
types::BinaryVector l_binaryKwdValue =
l_kwdValue.get<types::BinaryVector>();
if (l_binaryKwdValue == (*l_ptrToFn))
{
continue;
}
// Update part number only if required.
std::shared_ptr<Parser> l_parserObj =
std::make_shared<Parser>(l_fruPath, l_sysCfgJsonObj);
if (l_parserObj->updateVpdKeyword(std::make_tuple(
l_recordName, l_kwdName, l_binaryKwdValue)) ==
constants::FAILURE)
{
o_failedPathList.push_back(l_fruPath);
continue;
}
// update the Asset interface Spare part number explicitly.
if (!dbusUtility::callPIM(types::ObjectMap{
{l_inventoryPath,
{{constants::assetInf,
{{"SparePartNumber",
std::string(l_binaryKwdValue.begin(),
l_binaryKwdValue.end())}}}}}}))
{
logging::logMessage(
"Updating Spare Part Number under Asset interface failed for path [" +
l_inventoryPath + "]");
}
// Just needed for logging.
std::string l_initialPartNum((*l_ptrToFn).begin(),
(*l_ptrToFn).end());
std::string l_finalPartNum(l_binaryKwdValue.begin(),
l_binaryKwdValue.end());
logging::logMessage(
"FRU Part number updated for path [" + l_inventoryPath +
"]" + "From [" + l_initialPartNum + "]" + " to [" +
l_finalPartNum + "]");
}
}
}
}
void IbmHandler::ConfigurePowerVsSystem()
{
std::vector<std::string> l_failedPathList;
try
{
types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
if (l_imValue.empty())
{
throw DbusException("Invalid IM value read from Dbus");
}
uint16_t l_errCode = 0;
if (!vpdSpecificUtility::isPowerVsConfiguration(l_imValue, l_errCode))
{
// TODO: Should booting be blocked in case of some
// misconfigurations?
if (l_errCode)
{
logging::logMessage(
"Failed to check if the system is powerVs Configuration, error : " +
commonUtility::getErrCodeMsg(l_errCode));
}
return;
}
const nlohmann::json& l_powerVsJsonObj =
jsonUtility::getPowerVsJson(l_imValue, l_errCode);
if (l_powerVsJsonObj.empty())
{
throw std::runtime_error("PowerVS Json not found. Error : " +
commonUtility::getErrCodeMsg(l_errCode));
}
checkAndUpdatePowerVsVpd(l_powerVsJsonObj, l_failedPathList);
if (!l_failedPathList.empty())
{
throw std::runtime_error(
"Part number update failed for following paths: ");
}
}
catch (const std::exception& l_ex)
{
// TODO log appropriate PEL
}
}
void IbmHandler::processFailedEeproms()
{
if (m_worker.get() != nullptr)
{
// TODO:
// - iterate through list of EEPROMs for which thread creation has
// failed
// - For each failed EEPROM, trigger VPD collection
m_worker->getFailedEepromPaths().clear();
}
}
void IbmHandler::enableMuxChips()
{
if (m_sysCfgJsonObj.empty())
{
// config JSON should not be empty at this point of execution.
throw std::runtime_error("Config JSON is empty. Can't enable muxes");
return;
}
if (!m_sysCfgJsonObj.contains("muxes"))
{
logging::logMessage("No mux defined for the system in config JSON");
return;
}
// iterate over each MUX detail and enable them.
for (const auto& item : m_sysCfgJsonObj["muxes"])
{
if (item.contains("holdidlepath"))
{
std::string cmd = "echo 0 > ";
cmd += item["holdidlepath"];
logging::logMessage("Enabling mux with command = " + cmd);
commonUtility::executeCmd(cmd);
continue;
}
logging::logMessage(
"Mux Entry does not have hold idle path. Can't enable the mux");
}
}
void IbmHandler::getSystemJson(std::string& o_systemJson,
const types::VPDMapVariant& i_parsedVpdMap)
{
if (auto l_pVal = std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
{
uint16_t l_errCode = 0;
std::string l_hwKWdValue =
vpdSpecificUtility::getHWVersion(*l_pVal, l_errCode);
if (l_hwKWdValue.empty())
{
if (l_errCode)
{
throw DataException("Failed to fetch HW value. Reason: " +
commonUtility::getErrCodeMsg(l_errCode));
}
throw DataException("HW value fetched is empty.");
}
const std::string& l_imKwdValue =
vpdSpecificUtility::getIMValue(*l_pVal, l_errCode);
if (l_imKwdValue.empty())
{
if (l_errCode)
{
throw DataException("Failed to fetch IM value. Reason: " +
commonUtility::getErrCodeMsg(l_errCode));
}
throw DataException("IM value fetched is empty.");
}
auto l_itrToIM = config::systemType.find(l_imKwdValue);
if (l_itrToIM == config::systemType.end())
{
throw DataException("IM keyword does not map to any system type");
}
const types::HWVerList l_hwVersionList = l_itrToIM->second.second;
if (!l_hwVersionList.empty())
{
transform(l_hwKWdValue.begin(), l_hwKWdValue.end(),
l_hwKWdValue.begin(), ::toupper);
auto l_itrToHW =
std::find_if(l_hwVersionList.begin(), l_hwVersionList.end(),
[&l_hwKWdValue](const auto& l_aPair) {
return l_aPair.first == l_hwKWdValue;
});
if (l_itrToHW != l_hwVersionList.end())
{
if (!(*l_itrToHW).second.empty())
{
o_systemJson += (*l_itrToIM).first + "_" +
(*l_itrToHW).second + ".json";
}
else
{
o_systemJson += (*l_itrToIM).first + ".json";
}
return;
}
}
o_systemJson += l_itrToIM->second.first + ".json";
return;
}
throw DataException(
"Invalid VPD type returned from Parser. Can't get system JSON.");
}
static void setEnvAndReboot(const std::string& i_key,
const std::string& i_value)
{
// set env and reboot and break.
commonUtility::executeCmd("/sbin/fw_setenv", i_key, i_value);
logging::logMessage("Rebooting BMC to pick up new device tree");
// make dbus call to reboot
auto l_bus = sdbusplus::bus::new_default_system();
auto l_method = l_bus.new_method_call(
"org.freedesktop.systemd1", "/org/freedesktop/systemd1",
"org.freedesktop.systemd1.Manager", "Reboot");
l_bus.call_noreply(l_method);
}
static std::string readFitConfigValue()
{
std::vector<std::string> l_output =
commonUtility::executeCmd("/sbin/fw_printenv");
std::string l_fitConfigValue;
for (const auto& l_entry : l_output)
{
auto l_pos = l_entry.find("=");
auto l_key = l_entry.substr(0, l_pos);
if (l_key != "fitconfig")
{
continue;
}
if (l_pos + 1 < l_entry.size())
{
l_fitConfigValue = l_entry.substr(l_pos + 1);
}
}
return l_fitConfigValue;
}
bool IbmHandler::isBackupOnCache()
{
try
{
uint16_t l_errCode = 0;
std::string l_backupAndRestoreCfgFilePath =
m_sysCfgJsonObj.value("backupRestoreConfigPath", "");
if (l_backupAndRestoreCfgFilePath.empty())
{
m_logger->logMessage(
"backupRestoreConfigPath is not found in JSON. Can't determne the backup path.");
return false;
}
nlohmann::json l_backupAndRestoreCfgJsonObj =
jsonUtility::getParsedJson(l_backupAndRestoreCfgFilePath,
l_errCode);
if (l_backupAndRestoreCfgJsonObj.empty() || l_errCode)
{
m_logger->logMessage(
"JSON parsing failed for file [ " +
std::string(l_backupAndRestoreCfgFilePath) +
" ], error : " + commonUtility::getErrCodeMsg(l_errCode));
return false;
}
// check if either of "source" or "destination" has inventory path.
// this indicates that this sytem has System VPD on hardware
// and other copy on D-Bus (BMC cache).
if (!l_backupAndRestoreCfgJsonObj.empty() &&
((l_backupAndRestoreCfgJsonObj.contains("source") &&
l_backupAndRestoreCfgJsonObj["source"].contains(
"inventoryPath")) ||
(l_backupAndRestoreCfgJsonObj.contains("destination") &&
l_backupAndRestoreCfgJsonObj["destination"].contains(
"inventoryPath"))))
{
return true;
}
}
catch (const std::exception& l_ex)
{
m_logger->logMessage(
"Exception while checking for backup on cache. Reason:" +
std::string(l_ex.what()));
}
// In case of any failure/ambiguity. Don't perform back up and restore.
return false;
}
void IbmHandler::performBackupAndRestore(types::VPDMapVariant& io_srcVpdMap)
{
try
{
m_backupAndRestoreObj =
std::make_shared<BackupAndRestore>(m_sysCfgJsonObj);
auto [l_srcVpdVariant,
l_dstVpdVariant] = m_backupAndRestoreObj->backupAndRestore();
// ToDo: Revisit is this check is required or not.
if (auto l_srcVpdMap = std::get_if<types::IPZVpdMap>(&l_srcVpdVariant);
l_srcVpdMap && !(*l_srcVpdMap).empty())
{
io_srcVpdMap = std::move(l_srcVpdVariant);
}
}
catch (const std::exception& l_ex)
{
EventLogger::createSyncPel(
EventLogger::getErrorType(l_ex), types::SeverityType::Warning,
__FILE__, __FUNCTION__, 0,
std::string(
"Exception caught while backup and restore VPD keyword's.") +
EventLogger::getErrorMsg(l_ex),
std::nullopt, std::nullopt, std::nullopt, std::nullopt);
}
}
void IbmHandler::setDeviceTreeAndJson()
{
// JSON is madatory for processing of this API.
if (m_sysCfgJsonObj.empty())
{
throw JsonException("System config JSON is empty", m_sysCfgJsonObj);
}
// parse system VPD
auto l_parsedVpdMap = m_worker->parseVpdFile(SYSTEM_VPD_FILE_PATH);
// Implies it is default JSON.
std::string l_systemJson{JSON_ABSOLUTE_PATH_PREFIX};
// get system JSON as per the system configuration.
getSystemJson(l_systemJson, l_parsedVpdMap);
if (!l_systemJson.compare(JSON_ABSOLUTE_PATH_PREFIX))
{
throw DataException(
"No system JSON found corresponding to IM read from VPD.");
}
uint16_t l_errCode = 0;
// re-parse the JSON once appropriate JSON has been selected.
m_sysCfgJsonObj = jsonUtility::getParsedJson(l_systemJson, l_errCode);
if (l_errCode)
{
throw(JsonException(
"JSON parsing failed for file [ " + l_systemJson +
" ], error : " + commonUtility::getErrCodeMsg(l_errCode),
l_systemJson));
}
m_worker->setCollectionStatusProperty(SYSTEM_VPD_FILE_PATH,
constants::vpdCollectionInProgress);
std::string l_devTreeFromJson;
if (m_sysCfgJsonObj.contains("devTree"))
{
l_devTreeFromJson = m_sysCfgJsonObj["devTree"];
if (l_devTreeFromJson.empty())
{
EventLogger::createSyncPel(
types::ErrorType::JsonFailure, types::SeverityType::Error,
__FILE__, __FUNCTION__, 0,
"Mandatory value for device tree missing from JSON[" +
l_systemJson + "]",
std::nullopt, std::nullopt, std::nullopt, std::nullopt);
}
}
auto l_fitConfigVal = readFitConfigValue();
if (l_devTreeFromJson.empty() ||
l_fitConfigVal.find(l_devTreeFromJson) != std::string::npos)
{ // Skipping setting device tree as either devtree info is missing from
// Json or it is rightly set.
m_worker->setJsonSymbolicLink(l_systemJson);
const std::string& l_systemVpdInvPath =
jsonUtility::getInventoryObjPathFromJson(
m_sysCfgJsonObj, SYSTEM_VPD_FILE_PATH, l_errCode);
if (l_systemVpdInvPath.empty())
{
if (l_errCode)
{
throw JsonException(
"System vpd inventory path not found in JSON. Reason:" +
commonUtility::getErrCodeMsg(l_errCode),
INVENTORY_JSON_SYM_LINK);
}
throw JsonException("System vpd inventory path is missing in JSON",
INVENTORY_JSON_SYM_LINK);
}
// TODO: for backward compatibility this should also support motherboard
// interface.
std::vector<std::string> l_interfaceList{
constants::motherboardInterface};
const types::MapperGetObject& l_sysVpdObjMap =
dbusUtility::getObjectMap(l_systemVpdInvPath, l_interfaceList);
if (!l_sysVpdObjMap.empty())
{
if (isBackupOnCache() && jsonUtility::isBackupAndRestoreRequired(
m_sysCfgJsonObj, l_errCode))
{
performBackupAndRestore(l_parsedVpdMap);
}
else if (l_errCode)
{
logging::logMessage(
"Failed to check if backup and restore required. Reason : " +
commonUtility::getErrCodeMsg(l_errCode));
}
}
// proceed to publish system VPD.
m_worker->publishSystemVPD(l_parsedVpdMap);
m_worker->setCollectionStatusProperty(
SYSTEM_VPD_FILE_PATH, constants::vpdCollectionCompleted);
return;
}
setEnvAndReboot("fitconfig", l_devTreeFromJson);
exit(EXIT_SUCCESS);
}
void IbmHandler::performInitialSetup()
{
try
{
if (m_worker.get() == nullptr)
{
throw std::runtime_error(
"Worker object not found. Can't perform initial setup.");
}
m_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
if (!dbusUtility::isChassisPowerOn())
{
setDeviceTreeAndJson();
}
// Update BMC postion for RBMC prototype system
// Ignore BMC position update in case of any error
uint16_t l_errCode = 0;
if (isRbmcPrototypeSystem(l_errCode))
{
size_t l_bmcPosition = std::numeric_limits<size_t>::max();
checkAndUpdateBmcPosition(l_bmcPosition);
if (dbusUtility::callPIM(types::ObjectMap{
{sdbusplus::message::object_path(constants::systemInvPath),
{{constants::rbmcPositionInterface,
{{"Position", l_bmcPosition}}}}}}))
{
m_logger->logMessage(
"Updating BMC position failed for path [" +
std::string(constants::systemInvPath) +
"], bmc position: " + std::to_string(l_bmcPosition));
// ToDo: Check is PEL required
}
}
else if (l_errCode != 0)
{
m_logger->logMessage(
"Unable to determine whether system is RBMC system or not, reason: " +
commonUtility::getErrCodeMsg(l_errCode));
}
// Enable all mux which are used for connecting to the i2c on the
// pcie slots for pcie cards. These are not enabled by kernel due to
// an issue seen with Castello cards, where the i2c line hangs on a
// probe.
enableMuxChips();
// Nothing needs to be done. Service restarted or BMC re-booted for
// some reason at system power on.
}
catch (const std::exception& l_ex)
{
m_worker->setCollectionStatusProperty(SYSTEM_VPD_FILE_PATH,
constants::vpdCollectionFailed);
// Any issue in system's inital set up is handled in this catch. Error
// will not propogate to manager.
EventLogger::createSyncPel(
EventLogger::getErrorType(l_ex), types::SeverityType::Critical,
__FILE__, __FUNCTION__, 0, EventLogger::getErrorMsg(l_ex),
std::nullopt, std::nullopt, std::nullopt, std::nullopt);
}
}
void IbmHandler::collectAllFruVpd()
{
// Setting status to "InProgress", before trigeering VPD collection.
m_progressInterface->set_property(
"Status", std::string(constants::vpdCollectionInProgress));
m_worker->collectFrusFromJson();
SetTimerToDetectVpdCollectionStatus();
}
bool IbmHandler::isRbmcPrototypeSystem(uint16_t& o_errCode) const noexcept
{
types::BinaryVector l_imValue = dbusUtility::getImFromDbus();
if (l_imValue.empty())
{
o_errCode = error_code::DBUS_FAILURE;
return false;
}
if (constants::rbmcPrototypeSystemImValue == l_imValue)
{
return true;
}
return false;
}
void IbmHandler::checkAndUpdateBmcPosition(size_t& o_bmcPosition) const noexcept
{
if (m_worker.get() == nullptr)
{
m_logger->logMessage("Worker object not found");
return;
}
const nlohmann::json& l_sysCfgJsonObj = m_worker->getSysCfgJsonObj();
if (l_sysCfgJsonObj.empty())
{
m_logger->logMessage(
"System config JSON is empty, unable to find BMC position");
return;
}
uint16_t l_errCode = 0;
std::string l_motherboardEepromPath = jsonUtility::getFruPathFromJson(
l_sysCfgJsonObj, constants::systemVpdInvPath, l_errCode);
if (!l_motherboardEepromPath.empty())
{
o_bmcPosition = constants::VALUE_1;
std::error_code l_ec;
if (std::filesystem::exists(l_motherboardEepromPath, l_ec))
{
o_bmcPosition = constants::VALUE_0;
}
}
else if (l_errCode)
{
m_logger->logMessage("Unable to determine BMC position, reason: " +
commonUtility::getErrCodeMsg(l_errCode));
}
else
{
m_logger->logMessage("Unable to determine BMC position, as FRU path[" +
std::string(constants::systemVpdInvPath) +
"], not found in the system config JSON.");
}
}
} // namespace vpd