Get inventory list using expanded location code
This commit implements api to get inventory list with respect to
a given location code in expanded format.
In case no inventory is found at the given location or location code
is not correct, corresponding error is returned to the caller.
Tested on simics.
This api is under com.ibm.vpd.Manager interface. So vpd-manager app
needs to be running for this api to work.
Sample command for simics:
busctl call com.ibm.VPD.Manager /com/ibm/VPD/Manager com.ibm.VPD.Manager
GetFRUsByUnexpandedLocationCode sq <location_code> <node_number>
Signed-off-by: Sunny Srivastava <sunnsr25@in.ibm.com>
Change-Id: Ifa47d73a64338cbd228b5be1346027c69695612a
diff --git a/const.hpp b/const.hpp
index fc93468..c2ff5b3 100644
--- a/const.hpp
+++ b/const.hpp
@@ -43,6 +43,9 @@
constexpr uint8_t KW_VAL_PAIR_START_TAG = 0x84;
constexpr uint8_t RECORD_END_TAG = 0x78;
constexpr int UNEXP_LOCATION_CODE_MIN_LENGTH = 4;
+constexpr uint8_t EXP_LOCATIN_CODE_MIN_LENGTH = 17;
+static constexpr auto SE_KWD_LENGTH = 7;
+static constexpr auto INVALID_NODE_NUMBER = -1;
namespace lengths
{
diff --git a/types.hpp b/types.hpp
index 0c02fd9..d48b317 100644
--- a/types.hpp
+++ b/types.hpp
@@ -39,6 +39,7 @@
using LocationCode = std::string;
using LocationCodeMap = std::unordered_multimap<LocationCode, Path>;
using ListOfPaths = std::vector<sdbusplus::message::object_path>;
+using NodeNumber = uint16_t;
using namespace std::string_literals;
constexpr auto pimPath = "/xyz/openbmc_project/inventory";
constexpr auto pimIntf = "xyz.openbmc_project.Inventory.Manager";
diff --git a/vpd-manager/manager.cpp b/vpd-manager/manager.cpp
index 347aade..3d8462c 100644
--- a/vpd-manager/manager.cpp
+++ b/vpd-manager/manager.cpp
@@ -129,21 +129,22 @@
}
ListOfPaths
- Manager::getFRUsByUnexpandedLocationCode(const std::string locationCode,
- const uint16_t nodeNumber)
+ Manager::getFRUsByUnexpandedLocationCode(const LocationCode locationCode,
+ const NodeNumber nodeNumber)
{
ReaderImpl read;
return read.getFrusAtLocation(locationCode, nodeNumber, fruLocationCode);
}
ListOfPaths
- Manager::getFRUsByExpandedLocationCode(const std::string locationCode)
+ Manager::getFRUsByExpandedLocationCode(const LocationCode locationCode)
{
- // implement the interface
+ ReaderImpl read;
+ return read.getFRUsByExpandedLocationCode(locationCode, fruLocationCode);
}
-std::string Manager::getExpandedLocationCode(const std::string locationCode,
- const uint16_t nodeNumber)
+LocationCode Manager::getExpandedLocationCode(const LocationCode locationCode,
+ const NodeNumber nodeNumber)
{
ReaderImpl read;
return read.getExpandedLocationCode(locationCode, nodeNumber,
diff --git a/vpd-manager/reader_impl.cpp b/vpd-manager/reader_impl.cpp
index a40aa44..f1b5c6b 100644
--- a/vpd-manager/reader_impl.cpp
+++ b/vpd-manager/reader_impl.cpp
@@ -29,9 +29,10 @@
using Argument = xyz::openbmc_project::Common::InvalidArgument;
using LocationNotFound = sdbusplus::com::ibm::VPD::Error::LocationNotFound;
-bool ReaderImpl::isValidLocationCode(const std::string& locationCode) const
+bool ReaderImpl::isValidLocationCode(const LocationCode& locationCode) const
{
if ((locationCode.length() < UNEXP_LOCATION_CODE_MIN_LENGTH) ||
+ (locationCode[0] != 'U') ||
((locationCode.find("fcs", 1, 3) == std::string::npos) &&
(locationCode.find("mts", 1, 3) == std::string::npos)))
{
@@ -41,8 +42,8 @@
return true;
}
-std::string ReaderImpl::getExpandedLocationCode(
- const std::string& locationCode, const uint16_t& nodeNumber,
+LocationCode ReaderImpl::getExpandedLocationCode(
+ const LocationCode& locationCode, const NodeNumber& nodeNumber,
const LocationCodeMap& frusLocationCode) const
{
if (!isValidLocationCode(locationCode))
@@ -69,10 +70,11 @@
}
ListOfPaths
- ReaderImpl::getFrusAtLocation(const std::string& locationCode,
- const uint16_t& nodeNumber,
+ ReaderImpl::getFrusAtLocation(const LocationCode& locationCode,
+ const NodeNumber& nodeNumber,
const LocationCodeMap& frusLocationCode) const
{
+ // TODO:Implementation related to node number
if (!isValidLocationCode(locationCode))
{
// argument is not valid
@@ -102,6 +104,106 @@
return inventoryPaths;
}
+std::tuple<LocationCode, NodeNumber>
+ ReaderImpl::getCollapsedLocationCode(const LocationCode& locationCode) const
+{
+ // Location code should always start with U and fulfil minimum length
+ // criteria.
+ if (locationCode[0] != 'U' ||
+ locationCode.length() < EXP_LOCATIN_CODE_MIN_LENGTH)
+ {
+ elog<InvalidArgument>(Argument::ARGUMENT_NAME("LOCATIONCODE"),
+ Argument::ARGUMENT_VALUE(locationCode.c_str()));
+ }
+
+ std::string fc =
+ readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VCEN", "FC");
+
+ // get the first part of expanded location code to check for FC or TM
+ std::string firstKeyword = locationCode.substr(1, 4);
+
+ LocationCode unexpandedLocationCode{};
+ NodeNumber nodeNummber = INVALID_NODE_NUMBER;
+
+ // check if this value matches the value of FC kwd
+ if (fc.substr(0, 4) ==
+ firstKeyword) // implies this is Ufcs format location code
+ {
+ // period(.) should be there in expanded location code to seggregate FC,
+ // Node number and SE values.
+ size_t nodeStartPos = locationCode.find('.');
+ if (nodeStartPos == std::string::npos)
+ {
+ elog<InvalidArgument>(
+ Argument::ARGUMENT_NAME("LOCATIONCODE"),
+ Argument::ARGUMENT_VALUE(locationCode.c_str()));
+ }
+
+ // second period(.) should be there to end the node details in non
+ // system location code
+ size_t nodeEndPos = locationCode.find('.', nodeStartPos + 1);
+ if (nodeEndPos == std::string::npos)
+ {
+ elog<InvalidArgument>(
+ Argument::ARGUMENT_NAME("LOCATIONCODE"),
+ Argument::ARGUMENT_VALUE(locationCode.c_str()));
+ }
+
+ // skip 3 for '.ND'
+ nodeNummber = std::stoi(locationCode.substr(
+ nodeStartPos + 3, (nodeEndPos - nodeStartPos - 3)));
+
+ // confirm if there are other details apart FC, Node number and SE in
+ // location code
+ if (locationCode.length() > EXP_LOCATIN_CODE_MIN_LENGTH)
+ {
+ unexpandedLocationCode =
+ locationCode[0] + (std::string) "fcs" +
+ locationCode.substr(nodeEndPos + 1 + SE_KWD_LENGTH,
+ std::string::npos);
+ }
+ else
+ {
+ unexpandedLocationCode = "Ufcs";
+ }
+ }
+ else
+ {
+ // read TM kwd value
+ std::string tm =
+ readBusProperty(SYSTEM_OBJECT, "com.ibm.ipzvpd.VSYS", "TM");
+
+ // check if the substr matches to TM kwd
+ if (tm.substr(0, 4) ==
+ firstKeyword) // implies this is Umts format of location code
+ {
+ // system location code will not have any other details and node
+ // number
+ unexpandedLocationCode = "Umts";
+ }
+ // it does not belong to either "fcs" or "mts"
+ else
+ {
+ elog<InvalidArgument>(
+ Argument::ARGUMENT_NAME("LOCATIONCODE"),
+ Argument::ARGUMENT_VALUE(locationCode.c_str()));
+ }
+ }
+
+ return std::make_tuple(unexpandedLocationCode, nodeNummber);
+}
+
+ListOfPaths ReaderImpl::getFRUsByExpandedLocationCode(
+ const inventory::LocationCode& locationCode,
+ const inventory::LocationCodeMap& frusLocationCode) const
+{
+ std::tuple<LocationCode, NodeNumber> locationAndNodePair =
+ getCollapsedLocationCode(locationCode);
+
+ return getFrusAtLocation(std::get<0>(locationAndNodePair),
+ std::get<1>(locationAndNodePair),
+ frusLocationCode);
+}
} // namespace reader
} // namespace manager
} // namespace vpd
diff --git a/vpd-manager/reader_impl.hpp b/vpd-manager/reader_impl.hpp
index 465f414..dab8b8e 100644
--- a/vpd-manager/reader_impl.hpp
+++ b/vpd-manager/reader_impl.hpp
@@ -32,18 +32,29 @@
* code.
* @return Expanded location code.
*/
- std::string getExpandedLocationCode(
- const std::string& locationCode, const uint16_t& nodeNumber,
+ inventory::LocationCode getExpandedLocationCode(
+ const inventory::LocationCode& locationCode,
+ const inventory::NodeNumber& nodeNumber,
const inventory::LocationCodeMap& frusLocationCode) const;
- /** @brief An api to get list of all the FRUs at the given location code
+ /** @brief An API to get list of all the FRUs at the given location code
* @param[in] - location code in unexpanded format
* @param[in] - node number
* @param[in] - mapping of location code and Inventory path
* @return list of Inventory paths at the given location
*/
inventory::ListOfPaths getFrusAtLocation(
- const std::string& locationCode, const uint16_t& nodeNumber,
+ const inventory::LocationCode& locationCode,
+ const inventory::NodeNumber& nodeNumber,
+ const inventory::LocationCodeMap& frusLocationCode) const;
+
+ /** @brief An API to get list of all the FRUs at the given location code
+ * @param[in] - location code in unexpanded format
+ * @param[in] - mapping of location code and Inventory path
+ * @return list of Inventory paths at the given location
+ */
+ inventory::ListOfPaths getFRUsByExpandedLocationCode(
+ const inventory::LocationCode& locationCode,
const inventory::LocationCodeMap& frusLocationCode) const;
private:
@@ -51,7 +62,16 @@
* @param[in] - location code
* @return true/false based on validity check
*/
- bool isValidLocationCode(const std::string& locationCode) const;
+ bool isValidLocationCode(const inventory::LocationCode& locationCode) const;
+
+ /** @brief An API to split expanded location code to its un-expanded
+ * format as represented in VPD JSON and the node number.
+ * @param[in] Location code in expanded format.
+ * @return Location code in un-expanded format and its node number.
+ */
+ std::tuple<inventory::LocationCode, inventory::NodeNumber>
+ getCollapsedLocationCode(
+ const inventory::LocationCode& locationCode) const;
}; // class ReaderImpl