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