Skip to content

Commit

Permalink
Create and update Asset tag for the system
Browse files Browse the repository at this point in the history
The commit creates and Asset tag for the system in case of first
time boot or factory reset situation and adds Asset tag inerface
under system inevntory path.

It also registers callback to detect any change in asset tag value
and calls PIM notify to persist the data.

Signed-off-by: Sunny Srivastava <[email protected]>
  • Loading branch information
SunnySrivastava1984 committed Nov 13, 2024
1 parent 5c0e0d3 commit dd6b211
Show file tree
Hide file tree
Showing 5 changed files with 175 additions and 0 deletions.
2 changes: 2 additions & 0 deletions include/constants.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -100,6 +100,7 @@ static constexpr auto SHIFT_BITS_5 = 5;

static constexpr auto ASCII_OF_SPACE = 32;

constexpr auto systemInvPath = "/xyz/openbmc_project/inventory/system";
constexpr auto pimPath = "/xyz/openbmc_project/inventory";
constexpr auto pimIntf = "xyz.openbmc_project.Inventory.Manager";
constexpr auto ipzVpdInf = "com.ibm.ipzvpd.";
Expand Down Expand Up @@ -134,6 +135,7 @@ constexpr auto biosConfigMgrInterface =
"xyz.openbmc_project.BIOSConfig.Manager";
constexpr auto systemVpdInvPath =
"/xyz/openbmc_project/inventory/system/chassis/motherboard";
constexpr auto assetTagInf = "xyz.openbmc_project.Inventory.Decorator.AssetTag";
static constexpr auto BD_YEAR_END = 4;
static constexpr auto BD_MONTH_END = 7;
static constexpr auto BD_DAY_END = 10;
Expand Down
12 changes: 12 additions & 0 deletions include/manager.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -219,6 +219,18 @@ class Manager
* @throw std::runtime_error
*/
void SetTimerToDetectVpdCollectionStatus();

/**
* @brief API to register callback for "assetTag" property change.
*/
void registerAssetChangeCallback();

/**
* @brief Callback API to be triggered on "assetTag"property change.
*
* @param[in] i_msg - The callback message.
*/
void assetTagCallback(sdbusplus::message_t& i_msg);
#endif

/**
Expand Down
11 changes: 11 additions & 0 deletions include/worker.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -445,6 +445,14 @@ class Worker
void processEnabledProperty(const std::string& i_inventoryObjPath,
types::InterfaceMap& io_interfaces);

/**
* @brief API to form asset tag value for the system.
*
* @param[in] i_parsedVpdMap - Parsed VPD map.
* @return - Formed asset tag string. Empty in case of any error.
*/
std::string getAssetTag(const types::VPDMapVariant& i_parsedVpdMap);

// Parsed JSON file.
nlohmann::json m_parsedJson{};

Expand All @@ -462,6 +470,9 @@ class Worker
// collection. It just states, if the VPD collection process is over or not.
bool m_isAllFruCollected = false;

// To distinguish the factory reset path.
bool m_isFactoryResetDone = false;

// Mutex to guard critical resource m_activeCollectionThreadCount.
std::mutex m_mutex;
};
Expand Down
61 changes: 61 additions & 0 deletions src/manager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,7 @@
#include "utility/vpd_specific_utility.hpp"

#include <boost/asio/steady_timer.hpp>
#include <sdbusplus/bus/match.hpp>
#include <sdbusplus/message.hpp>

namespace vpd
Expand All @@ -33,6 +34,9 @@ Manager::Manager(
// Set up minimal things that is needed before bus name is claimed.
m_worker->performInitialSetup();

// set callback to detect any asset tag change
registerAssetChangeCallback();

// set async timer to detect if system VPD is published on D-Bus.
SetTimerToDetectSVPDOnDbus();

Expand Down Expand Up @@ -116,6 +120,63 @@ Manager::Manager(
}

#ifdef IBM_SYSTEM
void Manager::registerAssetChangeCallback()
{
static std::shared_ptr<sdbusplus::bus::match_t> l_assetMatch =
std::make_shared<sdbusplus::bus::match_t>(
*m_asioConnection,
sdbusplus::bus::match::rules::propertiesChanged(
constants::systemInvPath, constants::assetTagInf),
[this](sdbusplus::message_t& l_msg) { assetTagCallback(l_msg); });
}

void Manager::assetTagCallback(sdbusplus::message_t& i_msg)
{
try
{
if (i_msg.is_method_error())
{
throw std::runtime_error(
"Error reading callback msg for asset tag.");
}

std::string l_objectPath;
types::PropertyMap l_propMap;
i_msg.read(l_objectPath, l_propMap);

const auto& l_itrToAssetTag = l_propMap.find("AssetTag");
if (l_itrToAssetTag != l_propMap.end())
{
if (auto l_assetTag =
std::get_if<std::string>(&(l_itrToAssetTag->second)))
{
// Call Notify to persist the AssetTag
types::ObjectMap l_objectMap = {
{sdbusplus::message::object_path(constants::systemInvPath),
{{constants::assetTagInf, {{"AssetTag", *l_assetTag}}}}}};

// Notify PIM
if (!dbusUtility::callPIM(move(l_objectMap)))
{
throw std::runtime_error(
"Call to PIM failed for asset tag update.");
}
}
}
else
{
throw std::runtime_error(
"Could not find asset tag in callback message.");
}
}
catch (const std::exception& l_ex)
{
// TODO: Log PEL with below description.
logging::logMessage("Asset tag callback update failed with error: " +
std::string(l_ex.what()));
}
}

void Manager::SetTimerToDetectSVPDOnDbus()
{
static boost::asio::steady_timer timer(*m_ioContext);
Expand Down
89 changes: 89 additions & 0 deletions src/worker.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -417,6 +417,8 @@ void Worker::setDeviceTreeAndJson()
ec.message());
}
}

m_isFactoryResetDone = true;
}

// JSON is madatory for processing of this API.
Expand Down Expand Up @@ -1101,13 +1103,100 @@ void Worker::populateDbus(const types::VPDMapVariant& parsedVpdMap,
}
}

std::string Worker::getAssetTag(const types::VPDMapVariant& i_parsedVpdMap)
{
std::string l_assetTag;

try
{
// system VPD will be in IPZ format.
if (auto l_parsedVpdMap =
std::get_if<types::IPZVpdMap>(&i_parsedVpdMap))
{
auto l_itrToVsys = (*l_parsedVpdMap).find(constants::recVSYS);
if (l_itrToVsys != (*l_parsedVpdMap).end())
{
std::string l_tmKwdValue;
vpdSpecificUtility::getKwVal(l_itrToVsys->second,
constants::kwdTM, l_tmKwdValue);

std::string l_seKwdValue;
vpdSpecificUtility::getKwVal(l_itrToVsys->second,
constants::kwdSE, l_seKwdValue);

l_assetTag = std::string{"Server-"} + l_tmKwdValue +
std::string{"-"} + l_seKwdValue;
}
else
{
throw std::runtime_error(
"VSYS record not found in parsed VPD map to extract Asset tag.");
}
}
else
{
throw std::runtime_error(
"Inavlid VPD type recieved to extract Asset tag.");
}
}
catch (const std::exception& l_ex)
{
// TODO:Log PEL with below description.
logging::logMessage("Asset tag can't be formed. Error = " +
std::string(l_ex.what()));
}

return l_assetTag;
}

void Worker::publishSystemVPD(const types::VPDMapVariant& parsedVpdMap)
{
types::ObjectMap objectInterfaceMap;

if (std::get_if<types::IPZVpdMap>(&parsedVpdMap))
{
populateDbus(parsedVpdMap, objectInterfaceMap, SYSTEM_VPD_FILE_PATH);

try
{
if (m_isFactoryResetDone)
{
const auto& l_assetTag = getAssetTag(parsedVpdMap);

if (!l_assetTag.empty())
{
auto l_itrToSystemPath =
objectInterfaceMap.find(sdbusplus::message::object_path(
constants::systemInvPath));
if (l_itrToSystemPath == objectInterfaceMap.end())
{
throw std::runtime_error(
"System Path not found in object map.");
}
else
{
types::PropertyMap l_assetTagProperty;
l_assetTagProperty.emplace("AssetTag", l_assetTag);

(l_itrToSystemPath->second)
.emplace(constants::assetTagInf,
std::move(l_assetTagProperty));
}
}
else
{
throw std::runtime_error("Asset tag string is empty.");
}
}
}
catch (const std::exception& l_ex)
{
// TODO Log PEL with below description
logging::logMessage(
"Asset tag update failed with following error: " +
std::string(l_ex.what()));
}

// Notify PIM
if (!dbusUtility::callPIM(move(objectInterfaceMap)))
{
Expand Down

0 comments on commit dd6b211

Please sign in to comment.