xref: /openbmc/pldm/libpldmresponder/fru.hpp (revision 963c0fdf)
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      */
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             pldm::responder::oem_fru::Handler* oemFruHandler) :
71         parser(configPath, fruMasterJsonPath),
72         pdrRepo(pdrRepo), entityTree(entityTree), bmcEntityTree(bmcEntityTree),
73         oemFruHandler(oemFruHandler)
74     {}
75 
76     /** @brief Total length of the FRU table in bytes, this includes the pad
77      *         bytes and the checksum.
78      *
79      *  @return size of the FRU table
80      */
81     uint32_t size() const
82     {
83         return table.size();
84     }
85 
86     /** @brief The checksum of the contents of the FRU table
87      *
88      *  @return checksum
89      */
90     uint32_t checkSum() const
91     {
92         return checksum;
93     }
94 
95     /** @brief Number of record set identifiers in the FRU tables
96      *
97      *  @return number of record set identifiers
98      */
99     uint16_t numRSI() const
100     {
101         return rsi;
102     }
103 
104     /** @brief The number of FRU records in the table
105      *
106      *  @return number of FRU records
107      */
108     uint16_t numRecords() const
109     {
110         return numRecs;
111     }
112 
113     /** @brief Get the FRU table
114      *
115      *  @param[out] - Populate response with the FRU table
116      */
117     void getFRUTable(Response& response);
118 
119     /** @brief Get the Fru Table MetaData
120      *
121      */
122     void getFRURecordTableMetadata();
123 
124     /** @brief Get FRU Record Table By Option
125      *  @param[out] response - Populate response with the FRU table got by
126      *                         options
127      *  @param[in] fruTableHandle - The fru table handle
128      *  @param[in] recordSetIdentifer - The record set identifier
129      *  @param[in] recordType - The record type
130      *  @param[in] fieldType - The field type
131      */
132     int getFRURecordByOption(Response& response, uint16_t fruTableHandle,
133                              uint16_t recordSetIdentifer, uint8_t recordType,
134                              uint8_t fieldType);
135 
136     /** @brief FRU table is built by processing the D-Bus inventory namespace
137      *         based on the config files for FRU. The table is populated based
138      *         on the isBuilt flag.
139      */
140     void buildFRUTable();
141 
142     /** @brief Get std::map associated with the entity
143      *         key: object path
144      *         value: pldm_entity
145      *
146      *  @return std::map<ObjectPath, pldm_entity>
147      */
148     inline const pldm::responder::dbus::AssociatedEntityMap&
149         getAssociateEntityMap() const
150     {
151         return associatedEntityMap;
152     }
153 
154     /** @brief Get pldm entity by the object path
155      *
156      *  @param[in] intfMaps - D-Bus interfaces and the associated property
157      *                        values for the FRU
158      *
159      *  @return pldm_entity
160      */
161     std::optional<pldm_entity>
162         getEntityByObjectPath(const dbus::InterfaceMap& intfMaps);
163 
164     /** @brief Update pldm entity to association tree
165      *
166      *  @param[in] objects - std::map The object value tree
167      *  @param[in] path    - Object path
168      *
169      *  Ex: Input path =
170      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"
171      *
172      *  Get the parent class in turn and store it in a temporary vector
173      *
174      *  Output tmpObjPaths = {
175      *  "/xyz/openbmc_project/inventory/system",
176      *  "/xyz/openbmc_project/inventory/system/chassis/",
177      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard",
178      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"}
179      *
180      */
181     void updateAssociationTree(const dbus::ObjectValueTree& objects,
182                                const std::string& path);
183 
184     /* @brief Method to populate the firmware version ID
185      *
186      * @return firmware version ID
187      */
188     std::string populatefwVersion();
189 
190     /* @brief Method to resize the table
191      *
192      * @return resized table
193      */
194     std::vector<uint8_t> tableResize();
195 
196     /* @brief set FRU Record Table
197      *
198      * @param[in] fruData - the data of the fru
199      *
200      * @return PLDM completion code
201      */
202     int setFRUTable(const std::vector<uint8_t>& fruData);
203 
204   private:
205     uint16_t nextRSI()
206     {
207         return ++rsi;
208     }
209 
210     uint32_t nextRecordHandle()
211     {
212         return ++rh;
213     }
214 
215     uint32_t rh = 0;
216     uint16_t rsi = 0;
217     uint16_t numRecs = 0;
218     uint8_t padBytes = 0;
219     std::vector<uint8_t> table;
220     uint32_t checksum = 0;
221     bool isBuilt = false;
222 
223     fru_parser::FruParser parser;
224     pldm_pdr* pdrRepo;
225     pldm_entity_association_tree* entityTree;
226     pldm_entity_association_tree* bmcEntityTree;
227     pldm::responder::oem_fru::Handler* oemFruHandler;
228     dbus::ObjectValueTree objects;
229 
230     std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{};
231 
232     /** @brief populateRecord builds the FRU records for an instance of FRU and
233      *         updates the FRU table with the FRU records.
234      *
235      *  @param[in] interfaces - D-Bus interfaces and the associated property
236      *                          values for the FRU
237      *  @param[in] recordInfos - FRU record info to build the FRU records
238      *  @param[in/out] entity - PLDM entity corresponding to FRU instance
239      */
240     void populateRecords(const dbus::InterfaceMap& interfaces,
241                          const fru_parser::FruRecordInfos& recordInfos,
242                          const pldm_entity& entity);
243 
244     /** @brief Associate sensor/effecter to FRU entity
245      */
246     dbus::AssociatedEntityMap associatedEntityMap;
247 };
248 
249 namespace fru
250 {
251 
252 class Handler : public CmdHandler
253 {
254   public:
255     Handler(const std::string& configPath,
256             const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
257             pldm_entity_association_tree* entityTree,
258             pldm_entity_association_tree* bmcEntityTree,
259             pldm::responder::oem_fru::Handler* oemFruHandler) :
260         impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree,
261              oemFruHandler)
262     {
263         handlers.emplace(
264             PLDM_GET_FRU_RECORD_TABLE_METADATA,
265             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
266             return this->getFRURecordTableMetadata(request, payloadLength);
267         });
268         handlers.emplace(
269             PLDM_GET_FRU_RECORD_TABLE,
270             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
271             return this->getFRURecordTable(request, payloadLength);
272         });
273         handlers.emplace(
274             PLDM_GET_FRU_RECORD_BY_OPTION,
275             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
276             return this->getFRURecordByOption(request, payloadLength);
277         });
278         handlers.emplace(
279             PLDM_SET_FRU_RECORD_TABLE,
280             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
281             return this->setFRURecordTable(request, payloadLength);
282         });
283     }
284 
285     /** @brief Handler for Get FRURecordTableMetadata
286      *
287      *  @param[in] request - Request message payload
288      *  @param[in] payloadLength - Request payload length
289      *
290      *  @return PLDM response message
291      */
292     Response getFRURecordTableMetadata(const pldm_msg* request,
293                                        size_t payloadLength);
294 
295     /** @brief Handler for GetFRURecordTable
296      *
297      *  @param[in] request - Request message payload
298      *  @param[in] payloadLength - Request payload length
299      *
300      *  @return PLDM response message
301      */
302     Response getFRURecordTable(const pldm_msg* request, size_t payloadLength);
303 
304     /** @brief Build FRU table is bnot already built
305      *
306      */
307     void buildFRUTable()
308     {
309         impl.buildFRUTable();
310     }
311 
312     /** @brief Get std::map associated with the entity
313      *         key: object path
314      *         value: pldm_entity
315      *
316      *  @return std::map<ObjectPath, pldm_entity>
317      */
318     const pldm::responder::dbus::AssociatedEntityMap&
319         getAssociateEntityMap() const
320     {
321         return impl.getAssociateEntityMap();
322     }
323 
324     /** @brief Handler for GetFRURecordByOption
325      *
326      *  @param[in] request - Request message payload
327      *  @param[in] payloadLength - Request payload length
328      *
329      *  @return PLDM response message
330      */
331     Response getFRURecordByOption(const pldm_msg* request,
332                                   size_t payloadLength);
333 
334     /** @brief Handler for SetFRURecordTable
335      *
336      *  @param[in] request - Request message
337      *  @param[in] payloadLength - Request payload length
338      *
339      *  @return PLDM response message
340      */
341     Response setFRURecordTable(const pldm_msg* request, size_t payloadLength);
342 
343     using Table = std::vector<uint8_t>;
344 
345   private:
346     FruImpl impl;
347 };
348 
349 } // namespace fru
350 
351 } // namespace responder
352 
353 } // namespace pldm
354