blob: c7ff61b2742f0862629f0f3baeae9c2561ac9b6c [file] [log] [blame]
Patrick Venture0b02be92018-08-31 11:55:55 -07001#include "read_fru_data.hpp"
2
3#include "fruread.hpp"
4#include "types.hpp"
5#include "utils.hpp"
6
Patrick Venture46470a32018-09-07 19:26:25 -07007#include <host-ipmid/ipmid-api.h>
8
Marri Devender Rao0acf0572017-07-03 12:25:47 -05009#include <map>
10#include <phosphor-logging/elog-errors.hpp>
Patrick Venture0b02be92018-08-31 11:55:55 -070011#include <xyz/openbmc_project/Common/error.hpp>
12
Marri Devender Rao0acf0572017-07-03 12:25:47 -050013extern const FruMap frus;
Marri Devender Rao0acf0572017-07-03 12:25:47 -050014namespace ipmi
15{
16namespace fru
17{
18using namespace phosphor::logging;
19using InternalFailure =
Patrick Venture0b02be92018-08-31 11:55:55 -070020 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure;
Marri Devender Rao908f7502017-07-10 01:49:54 -050021std::unique_ptr<sdbusplus::bus::match_t> matchPtr(nullptr);
Marri Devender Rao0acf0572017-07-03 12:25:47 -050022
Patrick Venture0b02be92018-08-31 11:55:55 -070023static constexpr auto INV_INTF = "xyz.openbmc_project.Inventory.Manager";
24static constexpr auto OBJ_PATH = "/xyz/openbmc_project/inventory";
Marri Devender Rao0acf0572017-07-03 12:25:47 -050025static constexpr auto PROP_INTF = "org.freedesktop.DBus.Properties";
26
27namespace cache
28{
Patrick Venture0b02be92018-08-31 11:55:55 -070029// User initiate read FRU info area command followed by
30// FRU read command. Also data is read in small chunks of
31// the specified offset and count.
32// Caching the data which will be invalidated when ever there
33// is a change in FRU properties.
34FRUAreaMap fruMap;
35} // namespace cache
Marri Devender Rao0acf0572017-07-03 12:25:47 -050036/**
Marri Devender Rao18aae1f2017-07-26 00:33:26 -050037 * @brief Read all the property value's for the specified interface
38 * from Inventory.
Marri Devender Rao0acf0572017-07-03 12:25:47 -050039 *
Marri Devender Rao0acf0572017-07-03 12:25:47 -050040 * @param[in] intf Interface
Marri Devender Rao0acf0572017-07-03 12:25:47 -050041 * @param[in] path Object path
Marri Devender Rao18aae1f2017-07-26 00:33:26 -050042 * @return map of properties
Marri Devender Rao0acf0572017-07-03 12:25:47 -050043 */
Marri Devender Rao18aae1f2017-07-26 00:33:26 -050044ipmi::PropertyMap readAllProperties(const std::string& intf,
Patrick Venture0b02be92018-08-31 11:55:55 -070045 const std::string& path)
Marri Devender Rao0acf0572017-07-03 12:25:47 -050046{
Marri Devender Rao18aae1f2017-07-26 00:33:26 -050047 ipmi::PropertyMap properties;
Marri Devender Rao0acf0572017-07-03 12:25:47 -050048 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
49 auto service = ipmi::getService(bus, INV_INTF, OBJ_PATH);
50 std::string objPath = OBJ_PATH + path;
Patrick Venture0b02be92018-08-31 11:55:55 -070051 auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
52 PROP_INTF, "GetAll");
Marri Devender Rao18aae1f2017-07-26 00:33:26 -050053 method.append(intf);
Marri Devender Rao0acf0572017-07-03 12:25:47 -050054 auto reply = bus.call(method);
55 if (reply.is_method_error())
56 {
Patrick Venture0b02be92018-08-31 11:55:55 -070057 // If property is not found simply return empty value
Marri Devender Rao18aae1f2017-07-26 00:33:26 -050058 log<level::ERR>("Error in reading property values from inventory",
Joseph Reynolds510eb9c2018-05-30 11:51:28 -050059 entry("INTERFACE=%s", intf.c_str()),
60 entry("PATH=%s", objPath.c_str()));
Marri Devender Rao18aae1f2017-07-26 00:33:26 -050061 return properties;
Marri Devender Rao0acf0572017-07-03 12:25:47 -050062 }
Marri Devender Rao18aae1f2017-07-26 00:33:26 -050063 reply.read(properties);
64 return properties;
Marri Devender Rao0acf0572017-07-03 12:25:47 -050065}
66
Marri Devender Rao908f7502017-07-10 01:49:54 -050067void processFruPropChange(sdbusplus::message::message& msg)
68{
Patrick Venture0b02be92018-08-31 11:55:55 -070069 if (cache::fruMap.empty())
Marri Devender Rao908f7502017-07-10 01:49:54 -050070 {
71 return;
72 }
73 std::string path = msg.get_path();
Patrick Venture0b02be92018-08-31 11:55:55 -070074 // trim the object base path, if found at the beginning
Marri Devender Rao908f7502017-07-10 01:49:54 -050075 if (path.compare(0, strlen(OBJ_PATH), OBJ_PATH) == 0)
76 {
77 path.erase(0, strlen(OBJ_PATH));
78 }
79 for (auto& fru : frus)
80 {
81 bool found = false;
82 auto& fruId = fru.first;
83 auto& instanceList = fru.second;
84 for (auto& instance : instanceList)
85 {
Patrick Venture0b02be92018-08-31 11:55:55 -070086 if (instance.path == path)
Marri Devender Rao908f7502017-07-10 01:49:54 -050087 {
88 found = true;
89 break;
90 }
91 }
92 if (found)
93 {
94 cache::fruMap.erase(fruId);
95 break;
96 }
97 }
98}
99
Patrick Venture0b02be92018-08-31 11:55:55 -0700100// register for fru property change
Marri Devender Rao908f7502017-07-10 01:49:54 -0500101int registerCallbackHandler()
102{
Patrick Venture0b02be92018-08-31 11:55:55 -0700103 if (matchPtr == nullptr)
Marri Devender Rao908f7502017-07-10 01:49:54 -0500104 {
105 using namespace sdbusplus::bus::match::rules;
106 sdbusplus::bus::bus bus{ipmid_get_sd_bus_connection()};
107 matchPtr = std::make_unique<sdbusplus::bus::match_t>(
108 bus,
Patrick Venture0b02be92018-08-31 11:55:55 -0700109 path_namespace(OBJ_PATH) + type::signal() +
110 member("PropertiesChanged") + interface(PROP_INTF),
Marri Devender Rao908f7502017-07-10 01:49:54 -0500111 std::bind(processFruPropChange, std::placeholders::_1));
112 }
113 return 0;
114}
115
Marri Devender Rao0acf0572017-07-03 12:25:47 -0500116/**
117 * @brief Read FRU property values from Inventory
118 *
119 * @param[in] fruNum FRU id
120 * @return populate FRU Inventory data
121 */
122FruInventoryData readDataFromInventory(const FRUId& fruNum)
123{
124 auto iter = frus.find(fruNum);
125 if (iter == frus.end())
126 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700127 log<level::ERR>("Unsupported FRU ID ", entry("FRUID=%d", fruNum));
Marri Devender Rao0acf0572017-07-03 12:25:47 -0500128 elog<InternalFailure>();
129 }
130
131 FruInventoryData data;
132 auto& instanceList = iter->second;
133 for (auto& instance : instanceList)
134 {
Ratan Gupta00330972018-01-19 16:23:10 +0530135 for (auto& intf : instance.interfaces)
Marri Devender Rao0acf0572017-07-03 12:25:47 -0500136 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700137 ipmi::PropertyMap allProp =
138 readAllProperties(intf.first, instance.path);
Marri Devender Rao18aae1f2017-07-26 00:33:26 -0500139 for (auto& properties : intf.second)
Marri Devender Rao0acf0572017-07-03 12:25:47 -0500140 {
Marri Devender Rao18aae1f2017-07-26 00:33:26 -0500141 auto iter = allProp.find(properties.first);
142 if (iter != allProp.end())
143 {
Patrick Venture0b02be92018-08-31 11:55:55 -0700144 data[properties.second.section].emplace(
145 properties.first,
146 std::move(
147 allProp[properties.first].get<std::string>()));
Marri Devender Rao18aae1f2017-07-26 00:33:26 -0500148 }
Marri Devender Rao0acf0572017-07-03 12:25:47 -0500149 }
150 }
151 }
152 return data;
153}
154
155const FruAreaData& getFruAreaData(const FRUId& fruNum)
156{
157 auto iter = cache::fruMap.find(fruNum);
158 if (iter != cache::fruMap.end())
159 {
160 return iter->second;
161 }
162 auto invData = readDataFromInventory(fruNum);
163
Patrick Venture0b02be92018-08-31 11:55:55 -0700164 // Build area info based on inventory data
Marri Devender Rao0acf0572017-07-03 12:25:47 -0500165 FruAreaData newdata = buildFruAreaData(std::move(invData));
166 cache::fruMap.emplace(fruNum, std::move(newdata));
167 return cache::fruMap.at(fruNum);
168}
Patrick Venture0b02be92018-08-31 11:55:55 -0700169} // namespace fru
170} // namespace ipmi