xref: /openbmc/phosphor-host-ipmid/read_fru_data.cpp (revision 1318a5ed36cfd41335e687b54db1c17c0dde8f45)
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