10b02be92SPatrick Venture #include "read_fru_data.hpp"
20b02be92SPatrick Venture
30b02be92SPatrick Venture #include "fruread.hpp"
40b02be92SPatrick Venture
5e08fbffcSVernon Mauery #include <ipmid/api.hpp>
633250240SVernon Mauery #include <ipmid/types.hpp>
76a98fe7fSVernon Mauery #include <ipmid/utils.hpp>
80acf057fSMarri Devender Rao #include <phosphor-logging/elog-errors.hpp>
952591a9bSGeorge Liu #include <phosphor-logging/lg2.hpp>
104c008028SWilliam A. Kennington III #include <sdbusplus/message/types.hpp>
110b02be92SPatrick Venture #include <xyz/openbmc_project/Common/error.hpp>
120b02be92SPatrick Venture
13fbc6c9d7SPatrick Williams #include <algorithm>
14fbc6c9d7SPatrick Williams #include <map>
15fbc6c9d7SPatrick Williams
160acf057fSMarri Devender Rao extern const FruMap frus;
170acf057fSMarri Devender Rao namespace ipmi
180acf057fSMarri Devender Rao {
190acf057fSMarri Devender Rao namespace fru
200acf057fSMarri Devender Rao {
214c008028SWilliam A. Kennington III
220acf057fSMarri Devender Rao using namespace phosphor::logging;
230acf057fSMarri Devender Rao using InternalFailure =
24523e2d1bSWilly Tu sdbusplus::error::xyz::openbmc_project::common::InternalFailure;
254b0ddb68SLei YU std::unique_ptr<sdbusplus::bus::match_t> matchPtr
264b0ddb68SLei YU __attribute__((init_priority(101)));
270acf057fSMarri Devender Rao
280acf057fSMarri Devender Rao namespace cache
290acf057fSMarri Devender Rao {
300acf057fSMarri Devender Rao // User initiate read FRU info area command followed by
310acf057fSMarri Devender Rao // FRU read command. Also data is read in small chunks of
320acf057fSMarri Devender Rao // the specified offset and count.
330acf057fSMarri Devender Rao // Caching the data which will be invalidated when ever there
340acf057fSMarri Devender Rao // is a change in FRU properties.
350acf057fSMarri Devender Rao FRUAreaMap fruMap;
360b02be92SPatrick Venture } // namespace cache
370acf057fSMarri Devender Rao /**
3818aae1f7SMarri Devender Rao * @brief Read all the property value's for the specified interface
3918aae1f7SMarri Devender Rao * from Inventory.
400acf057fSMarri Devender Rao *
410acf057fSMarri Devender Rao * @param[in] intf Interface
420acf057fSMarri Devender Rao * @param[in] path Object path
4318aae1f7SMarri Devender Rao * @return map of properties
440acf057fSMarri Devender Rao */
readAllProperties(const std::string & intf,const std::string & path)4518aae1f7SMarri Devender Rao ipmi::PropertyMap readAllProperties(const std::string& intf,
460acf057fSMarri Devender Rao const std::string& path)
470acf057fSMarri Devender Rao {
4818aae1f7SMarri Devender Rao ipmi::PropertyMap properties;
495d82f474SPatrick Williams sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
50c26cc717SPatrick Venture std::string service;
51c26cc717SPatrick Venture std::string objPath;
52c26cc717SPatrick Venture
53c26cc717SPatrick Venture // Is the path the full dbus path?
54b118c4b3SKirill Pakhomov if (path.find(xyzPrefix) != std::string::npos)
55c26cc717SPatrick Venture {
56c26cc717SPatrick Venture service = ipmi::getService(bus, intf, path);
57c26cc717SPatrick Venture objPath = path;
58c26cc717SPatrick Venture }
59c26cc717SPatrick Venture else
60c26cc717SPatrick Venture {
61b118c4b3SKirill Pakhomov service = ipmi::getService(bus, invMgrInterface, invObjPath);
62b118c4b3SKirill Pakhomov objPath = invObjPath + path;
63c26cc717SPatrick Venture }
64c26cc717SPatrick Venture
650b02be92SPatrick Venture auto method = bus.new_method_call(service.c_str(), objPath.c_str(),
66b118c4b3SKirill Pakhomov propInterface, "GetAll");
6718aae1f7SMarri Devender Rao method.append(intf);
68c26cc717SPatrick Venture try
69c26cc717SPatrick Venture {
700acf057fSMarri Devender Rao auto reply = bus.call(method);
71c26cc717SPatrick Venture reply.read(properties);
72c26cc717SPatrick Venture }
735d82f474SPatrick Williams catch (const sdbusplus::exception_t& e)
740acf057fSMarri Devender Rao {
750acf057fSMarri Devender Rao // If property is not found simply return empty value
7652591a9bSGeorge Liu lg2::error("Error in reading property values: {ERROR}, path: {PATH}, "
7752591a9bSGeorge Liu "interface: {INTERFACE}",
7852591a9bSGeorge Liu "ERROR", e, "PATH", objPath, "INTERFACE", intf);
790acf057fSMarri Devender Rao }
80c26cc717SPatrick Venture
8118aae1f7SMarri Devender Rao return properties;
820acf057fSMarri Devender Rao }
830acf057fSMarri Devender Rao
processFruPropChange(sdbusplus::message_t & msg)845d82f474SPatrick Williams void processFruPropChange(sdbusplus::message_t& msg)
85908f7507SMarri Devender Rao {
86908f7507SMarri Devender Rao if (cache::fruMap.empty())
87908f7507SMarri Devender Rao {
88908f7507SMarri Devender Rao return;
89908f7507SMarri Devender Rao }
90908f7507SMarri Devender Rao std::string path = msg.get_path();
91908f7507SMarri Devender Rao // trim the object base path, if found at the beginning
92b118c4b3SKirill Pakhomov if (path.compare(0, strlen(invObjPath), invObjPath) == 0)
93908f7507SMarri Devender Rao {
94b118c4b3SKirill Pakhomov path.erase(0, strlen(invObjPath));
95908f7507SMarri Devender Rao }
96438fb795SPatrick Venture for (const auto& [fruId, instanceList] : frus)
97908f7507SMarri Devender Rao {
98369824e7SPatrick Williams auto found = std::find_if(
99369824e7SPatrick Williams instanceList.begin(), instanceList.end(),
100369824e7SPatrick Williams [&path](const auto& iter) { return (iter.path == path); });
101b0431c79SPatrick Venture
102b0431c79SPatrick Venture if (found != instanceList.end())
103908f7507SMarri Devender Rao {
104908f7507SMarri Devender Rao cache::fruMap.erase(fruId);
105908f7507SMarri Devender Rao break;
106908f7507SMarri Devender Rao }
107908f7507SMarri Devender Rao }
108908f7507SMarri Devender Rao }
109908f7507SMarri Devender Rao
110908f7507SMarri Devender Rao // register for fru property change
registerCallbackHandler()111908f7507SMarri Devender Rao int registerCallbackHandler()
112908f7507SMarri Devender Rao {
113908f7507SMarri Devender Rao if (matchPtr == nullptr)
114908f7507SMarri Devender Rao {
115908f7507SMarri Devender Rao using namespace sdbusplus::bus::match::rules;
1165d82f474SPatrick Williams sdbusplus::bus_t bus{ipmid_get_sd_bus_connection()};
117908f7507SMarri Devender Rao matchPtr = std::make_unique<sdbusplus::bus::match_t>(
118908f7507SMarri Devender Rao bus,
119b118c4b3SKirill Pakhomov path_namespace(invObjPath) + type::signal() +
120b118c4b3SKirill Pakhomov member("PropertiesChanged") + interface(propInterface),
121908f7507SMarri Devender Rao std::bind(processFruPropChange, std::placeholders::_1));
122908f7507SMarri Devender Rao }
123908f7507SMarri Devender Rao return 0;
124908f7507SMarri Devender Rao }
125908f7507SMarri Devender Rao
1260acf057fSMarri Devender Rao /**
1270acf057fSMarri Devender Rao * @brief Read FRU property values from Inventory
1280acf057fSMarri Devender Rao *
1290acf057fSMarri Devender Rao * @param[in] fruNum FRU id
1300acf057fSMarri Devender Rao * @return populate FRU Inventory data
1310acf057fSMarri Devender Rao */
readDataFromInventory(const FRUId & fruNum)1320acf057fSMarri Devender Rao FruInventoryData readDataFromInventory(const FRUId& fruNum)
1330acf057fSMarri Devender Rao {
1340acf057fSMarri Devender Rao auto iter = frus.find(fruNum);
1350acf057fSMarri Devender Rao if (iter == frus.end())
1360acf057fSMarri Devender Rao {
13752591a9bSGeorge Liu lg2::error("Unsupported FRU ID: {FRUID}", "FRUID", fruNum);
1380acf057fSMarri Devender Rao elog<InternalFailure>();
1390acf057fSMarri Devender Rao }
1400acf057fSMarri Devender Rao
1410acf057fSMarri Devender Rao FruInventoryData data;
1420acf057fSMarri Devender Rao auto& instanceList = iter->second;
1430acf057fSMarri Devender Rao for (auto& instance : instanceList)
1440acf057fSMarri Devender Rao {
14500330973SRatan Gupta for (auto& intf : instance.interfaces)
1460acf057fSMarri Devender Rao {
147*1318a5edSPatrick Williams ipmi::PropertyMap allProp =
148*1318a5edSPatrick Williams readAllProperties(intf.first, instance.path);
14918aae1f7SMarri Devender Rao for (auto& properties : intf.second)
1500acf057fSMarri Devender Rao {
15118aae1f7SMarri Devender Rao auto iter = allProp.find(properties.first);
15218aae1f7SMarri Devender Rao if (iter != allProp.end())
15318aae1f7SMarri Devender Rao {
1540b02be92SPatrick Venture data[properties.second.section].emplace(
15545e93cbaSPatrick Venture properties.second.property,
15645e93cbaSPatrick Venture std::move(
15745e93cbaSPatrick Venture std::get<std::string>(allProp[properties.first])));
15818aae1f7SMarri Devender Rao }
1590acf057fSMarri Devender Rao }
1600acf057fSMarri Devender Rao }
1610acf057fSMarri Devender Rao }
1620acf057fSMarri Devender Rao return data;
1630acf057fSMarri Devender Rao }
1640acf057fSMarri Devender Rao
getFruAreaData(const FRUId & fruNum)1650acf057fSMarri Devender Rao const FruAreaData& getFruAreaData(const FRUId& fruNum)
1660acf057fSMarri Devender Rao {
1670acf057fSMarri Devender Rao auto iter = cache::fruMap.find(fruNum);
1680acf057fSMarri Devender Rao if (iter != cache::fruMap.end())
1690acf057fSMarri Devender Rao {
1700acf057fSMarri Devender Rao return iter->second;
1710acf057fSMarri Devender Rao }
1720acf057fSMarri Devender Rao auto invData = readDataFromInventory(fruNum);
1730acf057fSMarri Devender Rao
1740acf057fSMarri Devender Rao // Build area info based on inventory data
1750acf057fSMarri Devender Rao FruAreaData newdata = buildFruAreaData(std::move(invData));
1760acf057fSMarri Devender Rao cache::fruMap.emplace(fruNum, std::move(newdata));
1770acf057fSMarri Devender Rao return cache::fruMap.at(fruNum);
1780acf057fSMarri Devender Rao }
1790b02be92SPatrick Venture } // namespace fru
1800b02be92SPatrick Venture } // namespace ipmi
181