diff options
-rw-r--r-- | Makefile.am | 3 | ||||
-rw-r--r-- | read_fru_data.cpp | 118 | ||||
-rw-r--r-- | read_fru_data.hpp | 22 |
3 files changed, 142 insertions, 1 deletions
diff --git a/Makefile.am b/Makefile.am index f2d3bb0..0379037 100644 --- a/Makefile.am +++ b/Makefile.am @@ -50,7 +50,8 @@ libapphandler_la_SOURCES = \ inventory-sensor-gen.cpp \ fru-read-gen.cpp \ selutility.cpp \ - ipmi_fru_info_area.cpp + ipmi_fru_info_area.cpp \ + read_fru_data.cpp libapphandler_la_LDFLAGS = $(SYSTEMD_LIBS) $(libmapper_LIBS) $(PHOSPHOR_LOGGING_LIBS) $(PHOSPHOR_DBUS_INTERFACES_LIBS) -lstdc++fs -version-info 0:0:0 -shared libapphandler_la_CXXFLAGS = $(SYSTEMD_CFLAGS) $(libmapper_CFLAGS) $(PHOSPHOR_LOGGING_CFLAGS) $(PHOSPHOR_DBUS_INTERFACES_CFLAGS) diff --git a/read_fru_data.cpp b/read_fru_data.cpp new file mode 100644 index 0000000..5388926 --- /dev/null +++ b/read_fru_data.cpp @@ -0,0 +1,118 @@ +#include <map> +#include <phosphor-logging/elog-errors.hpp> +#include "xyz/openbmc_project/Common/error.hpp" +#include "read_fru_data.hpp" +#include "fruread.hpp" +#include "host-ipmid/ipmid-api.h" +#include "utils.hpp" + +extern const FruMap frus; + +namespace ipmi +{ +namespace fru +{ +using namespace phosphor::logging; +using InternalFailure = + sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; + +static constexpr auto INV_INTF = "xyz.openbmc_project.Inventory.Manager"; +static constexpr auto OBJ_PATH = "/xyz/openbmc_project/inventory"; +static constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties"; + +namespace cache +{ + //User initiate read FRU info area command followed by + //FRU read command. Also data is read in small chunks of + //the specified offset and count. + //Caching the data which will be invalidated when ever there + //is a change in FRU properties. + FRUAreaMap fruMap; +} +/** + * @brief Read the property value from Inventory + * + * @param[in] bus dbus + * @param[in] intf Interface + * @param[in] propertyName Name of the property + * @param[in] path Object path + * @return property value + */ +std::string readProperty(const std::string& intf, + const std::string& propertyName, + const std::string& path) +{ + sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()}; + auto service = ipmi::getService(bus, INV_INTF, OBJ_PATH); + std::string objPath = OBJ_PATH + path; + auto method = bus.new_method_call(service.c_str(), + objPath.c_str(), + PROP_INTF, + "Get"); + method.append(intf, propertyName); + auto reply = bus.call(method); + if (reply.is_method_error()) + { + //If property is not found simply return empty value + log<level::INFO>("Property value not set", + entry("Property=%s", propertyName), + entry("Path=%s", objPath)); + return {}; + } + sdbusplus::message::variant<std::string> property; + reply.read(property); + std::string value = + sdbusplus::message::variant_ns::get<std::string>(property); + return value; +} + +/** + * @brief Read FRU property values from Inventory + * + * @param[in] fruNum FRU id + * @return populate FRU Inventory data + */ +FruInventoryData readDataFromInventory(const FRUId& fruNum) +{ + auto iter = frus.find(fruNum); + if (iter == frus.end()) + { + log<level::ERR>("Unsupported FRU ID ",entry("FRUID=%d", fruNum)); + elog<InternalFailure>(); + } + + FruInventoryData data; + auto& instanceList = iter->second; + for (auto& instance : instanceList) + { + for (auto& interfaceList : instance.second) + { + for (auto& properties : interfaceList.second) + { + decltype(auto) pdata = properties.second; + auto value = readProperty( + interfaceList.first, properties.first, + instance.first); + data[pdata.section].emplace(properties.first, value); + } + } + } + return data; +} + +const FruAreaData& getFruAreaData(const FRUId& fruNum) +{ + auto iter = cache::fruMap.find(fruNum); + if (iter != cache::fruMap.end()) + { + return iter->second; + } + auto invData = readDataFromInventory(fruNum); + + //Build area info based on inventory data + FruAreaData newdata = buildFruAreaData(std::move(invData)); + cache::fruMap.emplace(fruNum, std::move(newdata)); + return cache::fruMap.at(fruNum); +} +} //fru +} //ipmi diff --git a/read_fru_data.hpp b/read_fru_data.hpp new file mode 100644 index 0000000..f536cf2 --- /dev/null +++ b/read_fru_data.hpp @@ -0,0 +1,22 @@ +#pragma once +#include <string> +#include <sdbusplus/bus.hpp> +#include "ipmi_fru_info_area.hpp" + +namespace ipmi +{ +namespace fru +{ +using FRUId = uint8_t; +using FRUAreaMap = std::map<FRUId, FruAreaData>; +/** + * @brief Get fru area data as per IPMI specification + * + * @param[in] fruNum FRU ID + * + * @return FRU area data as per IPMI specification + */ +const FruAreaData& getFruAreaData(const FRUId& fruNum); + +} //fru +} //ipmi |