xref: /openbmc/pldm/libpldmresponder/fru.hpp (revision 16c2a0a0)
1 #pragma once
2 
3 #include "fru_parser.hpp"
4 #include "libpldmresponder/pdr_utils.hpp"
5 #include "oem_handler.hpp"
6 #include "pldmd/handler.hpp"
7 
8 #include <libpldm/fru.h>
9 #include <libpldm/pdr.h>
10 
11 #include <sdbusplus/message.hpp>
12 
13 #include <map>
14 #include <string>
15 #include <variant>
16 #include <vector>
17 
18 namespace pldm
19 {
20 
21 namespace responder
22 {
23 
24 namespace dbus
25 {
26 
27 using Value = std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t,
28                            int64_t, uint64_t, double, std::string,
29                            std::vector<uint8_t>, std::vector<std::string>>;
30 using PropertyMap = std::map<Property, Value>;
31 using InterfaceMap = std::map<Interface, PropertyMap>;
32 using ObjectValueTree = std::map<sdbusplus::message::object_path, InterfaceMap>;
33 using ObjectPath = std::string;
34 using AssociatedEntityMap = std::map<ObjectPath, pldm_entity>;
35 
36 } // namespace dbus
37 
38 /** @class FruImpl
39  *
40  *  @brief Builds the PLDM FRU table containing the FRU records
41  */
42 class FruImpl
43 {
44   public:
45     /* @brief Header size for FRU record, it includes the FRU record set
46      *        identifier, FRU record type, Number of FRU fields, Encoding type
47      *        of FRU fields
48      */
49     static constexpr size_t recHeaderSize =
50         sizeof(struct pldm_fru_record_data_format) -
51         sizeof(struct pldm_fru_record_tlv);
52 
53     /** @brief Constructor for FruImpl, the configPath is consumed to build the
54      *         FruParser object.
55      *
56      *  @param[in] configPath - path to the directory containing config files
57      *                          for PLDM FRU
58      *  @param[in] fruMasterJsonPath - path to the file containing the FRU D-Bus
59      *                                 Lookup Map
60      *  @param[in] pdrRepo - opaque pointer to PDR repository
61      *  @param[in] entityTree - opaque pointer to the entity association tree
62      *  @param[in] bmcEntityTree - opaque pointer to bmc's entity association
63      *                             tree
64      *  @param[in] oemFruHandler - OEM fru handler
65      */
FruImpl(const std::string & configPath,const std::filesystem::path & fruMasterJsonPath,pldm_pdr * pdrRepo,pldm_entity_association_tree * entityTree,pldm_entity_association_tree * bmcEntityTree)66     FruImpl(const std::string& configPath,
67             const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
68             pldm_entity_association_tree* entityTree,
69             pldm_entity_association_tree* bmcEntityTree) :
70         parser(configPath, fruMasterJsonPath), pdrRepo(pdrRepo),
71         entityTree(entityTree), bmcEntityTree(bmcEntityTree)
72     {}
73 
74     /** @brief Total length of the FRU table in bytes, this includes the pad
75      *         bytes and the checksum.
76      *
77      *  @return size of the FRU table
78      */
size() const79     uint32_t size() const
80     {
81         return table.size();
82     }
83 
84     /** @brief The checksum of the contents of the FRU table
85      *
86      *  @return checksum
87      */
checkSum() const88     uint32_t checkSum() const
89     {
90         return checksum;
91     }
92 
93     /** @brief Number of record set identifiers in the FRU tables
94      *
95      *  @return number of record set identifiers
96      */
numRSI() const97     uint16_t numRSI() const
98     {
99         return rsi;
100     }
101 
102     /** @brief The number of FRU records in the table
103      *
104      *  @return number of FRU records
105      */
numRecords() const106     uint16_t numRecords() const
107     {
108         return numRecs;
109     }
110 
111     /** @brief Get the FRU table
112      *
113      *  @param[out] - Populate response with the FRU table
114      */
115     void getFRUTable(Response& response);
116 
117     /** @brief Get the Fru Table MetaData
118      *
119      */
120     void getFRURecordTableMetadata();
121 
122     /** @brief Get FRU Record Table By Option
123      *  @param[out] response - Populate response with the FRU table got by
124      *                         options
125      *  @param[in] fruTableHandle - The fru table handle
126      *  @param[in] recordSetIdentifer - The record set identifier
127      *  @param[in] recordType - The record type
128      *  @param[in] fieldType - The field type
129      */
130     int getFRURecordByOption(Response& response, uint16_t fruTableHandle,
131                              uint16_t recordSetIdentifer, uint8_t recordType,
132                              uint8_t fieldType);
133 
134     /** @brief FRU table is built by processing the D-Bus inventory namespace
135      *         based on the config files for FRU. The table is populated based
136      *         on the isBuilt flag.
137      */
138     void buildFRUTable();
139 
140     /** @brief Get std::map associated with the entity
141      *         key: object path
142      *         value: pldm_entity
143      *
144      *  @return std::map<ObjectPath, pldm_entity>
145      */
146     inline const pldm::responder::dbus::AssociatedEntityMap&
getAssociateEntityMap() const147         getAssociateEntityMap() const
148     {
149         return associatedEntityMap;
150     }
151 
152     /** @brief Get pldm entity by the object path
153      *
154      *  @param[in] intfMaps - D-Bus interfaces and the associated property
155      *                        values for the FRU
156      *
157      *  @return pldm_entity
158      */
159     std::optional<pldm_entity>
160         getEntityByObjectPath(const dbus::InterfaceMap& intfMaps);
161 
162     /** @brief Update pldm entity to association tree
163      *
164      *  @param[in] objects - std::map The object value tree
165      *  @param[in] path    - Object path
166      *
167      *  Ex: Input path =
168      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"
169      *
170      *  Get the parent class in turn and store it in a temporary vector
171      *
172      *  Output tmpObjPaths = {
173      *  "/xyz/openbmc_project/inventory/system",
174      *  "/xyz/openbmc_project/inventory/system/chassis/",
175      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard",
176      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"}
177      *
178      */
179     void updateAssociationTree(const dbus::ObjectValueTree& objects,
180                                const std::string& path);
181 
182     /* @brief Method to populate the firmware version ID
183      *
184      * @return firmware version ID
185      */
186     std::string populatefwVersion();
187 
188     /* @brief Method to resize the table
189      *
190      * @return resized table
191      */
192     std::vector<uint8_t> tableResize();
193 
194     /* @brief set FRU Record Table
195      *
196      * @param[in] fruData - the data of the fru
197      *
198      * @return PLDM completion code
199      */
200     int setFRUTable(const std::vector<uint8_t>& fruData);
201 
202     /* @brief Method to set the oem platform handler in fru handler class
203      *
204      * @param[in] handler - oem fru handler
205      */
setOemFruHandler(pldm::responder::oem_fru::Handler * handler)206     inline void setOemFruHandler(pldm::responder::oem_fru::Handler* handler)
207     {
208         oemFruHandler = handler;
209     }
210 
211   private:
nextRSI()212     uint16_t nextRSI()
213     {
214         return ++rsi;
215     }
216 
nextRecordHandle()217     uint32_t nextRecordHandle()
218     {
219         return ++rh;
220     }
221 
222     uint32_t rh = 0;
223     uint16_t rsi = 0;
224     uint16_t numRecs = 0;
225     uint8_t padBytes = 0;
226     std::vector<uint8_t> table;
227     uint32_t checksum = 0;
228     bool isBuilt = false;
229 
230     fru_parser::FruParser parser;
231     pldm_pdr* pdrRepo;
232     pldm_entity_association_tree* entityTree;
233     pldm_entity_association_tree* bmcEntityTree;
234     pldm::responder::oem_fru::Handler* oemFruHandler = nullptr;
235     dbus::ObjectValueTree objects;
236 
237     std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{};
238 
239     /** @brief populateRecord builds the FRU records for an instance of FRU and
240      *         updates the FRU table with the FRU records.
241      *
242      *  @param[in] interfaces - D-Bus interfaces and the associated property
243      *                          values for the FRU
244      *  @param[in] recordInfos - FRU record info to build the FRU records
245      *  @param[in/out] entity - PLDM entity corresponding to FRU instance
246      */
247     void populateRecords(const dbus::InterfaceMap& interfaces,
248                          const fru_parser::FruRecordInfos& recordInfos,
249                          const pldm_entity& entity);
250 
251     /** @brief Associate sensor/effecter to FRU entity
252      */
253     dbus::AssociatedEntityMap associatedEntityMap;
254 };
255 
256 namespace fru
257 {
258 
259 class Handler : public CmdHandler
260 {
261   public:
Handler(const std::string & configPath,const std::filesystem::path & fruMasterJsonPath,pldm_pdr * pdrRepo,pldm_entity_association_tree * entityTree,pldm_entity_association_tree * bmcEntityTree)262     Handler(const std::string& configPath,
263             const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
264             pldm_entity_association_tree* entityTree,
265             pldm_entity_association_tree* bmcEntityTree) :
266         impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree)
267     {
268         handlers.emplace(
269             PLDM_GET_FRU_RECORD_TABLE_METADATA,
270             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
271                 return this->getFRURecordTableMetadata(request, payloadLength);
272             });
273         handlers.emplace(
274             PLDM_GET_FRU_RECORD_TABLE,
275             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
276                 return this->getFRURecordTable(request, payloadLength);
277             });
278         handlers.emplace(
279             PLDM_GET_FRU_RECORD_BY_OPTION,
280             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
281                 return this->getFRURecordByOption(request, payloadLength);
282             });
283         handlers.emplace(
284             PLDM_SET_FRU_RECORD_TABLE,
285             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
286                 return this->setFRURecordTable(request, payloadLength);
287             });
288     }
289 
290     /** @brief Handler for Get FRURecordTableMetadata
291      *
292      *  @param[in] request - Request message payload
293      *  @param[in] payloadLength - Request payload length
294      *
295      *  @return PLDM response message
296      */
297     Response getFRURecordTableMetadata(const pldm_msg* request,
298                                        size_t payloadLength);
299 
300     /** @brief Handler for GetFRURecordTable
301      *
302      *  @param[in] request - Request message payload
303      *  @param[in] payloadLength - Request payload length
304      *
305      *  @return PLDM response message
306      */
307     Response getFRURecordTable(const pldm_msg* request, size_t payloadLength);
308 
309     /** @brief Build FRU table is bnot already built
310      *
311      */
buildFRUTable()312     void buildFRUTable()
313     {
314         impl.buildFRUTable();
315     }
316 
317     /** @brief Get std::map associated with the entity
318      *         key: object path
319      *         value: pldm_entity
320      *
321      *  @return std::map<ObjectPath, pldm_entity>
322      */
323     const pldm::responder::dbus::AssociatedEntityMap&
getAssociateEntityMap() const324         getAssociateEntityMap() const
325     {
326         return impl.getAssociateEntityMap();
327     }
328 
329     /** @brief Handler for GetFRURecordByOption
330      *
331      *  @param[in] request - Request message payload
332      *  @param[in] payloadLength - Request payload length
333      *
334      *  @return PLDM response message
335      */
336     Response getFRURecordByOption(const pldm_msg* request,
337                                   size_t payloadLength);
338 
339     /** @brief Handler for SetFRURecordTable
340      *
341      *  @param[in] request - Request message
342      *  @param[in] payloadLength - Request payload length
343      *
344      *  @return PLDM response message
345      */
346     Response setFRURecordTable(const pldm_msg* request, size_t payloadLength);
347 
348     /* @brief Method to set the oem platform handler in fru handler class
349      *
350      * @param[in] handler - oem fru handler
351      */
setOemFruHandler(pldm::responder::oem_fru::Handler * handler)352     void setOemFruHandler(pldm::responder::oem_fru::Handler* handler)
353     {
354         impl.setOemFruHandler(handler);
355     }
356 
357     using Table = std::vector<uint8_t>;
358 
359   private:
360     FruImpl impl;
361 };
362 
363 } // namespace fru
364 
365 } // namespace responder
366 
367 } // namespace pldm
368