xref: /openbmc/pldm/libpldmresponder/fru.hpp (revision aac7db3aaddbb0c70b62090397c6184adebfebb5)
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 Method to set the oem platform handler in FRU handler class
154      *
155      * @param[in] handler - oem platform handler
156      */
setOemPlatformHandler(pldm::responder::oem_platform::Handler * handler)157     inline void setOemPlatformHandler(
158         pldm::responder::oem_platform::Handler* handler)
159     {
160         oemPlatformHandler = handler;
161     }
162 
163     /** @brief Get pldm entity by the object path
164      *
165      *  @param[in] intfMaps - D-Bus interfaces and the associated property
166      *                        values for the FRU
167      *
168      *  @return pldm_entity
169      */
170     std::optional<pldm_entity> getEntityByObjectPath(
171         const dbus::InterfaceMap& intfMaps);
172 
173     /** @brief Update pldm entity to association tree
174      *
175      *  @param[in] objects - std::map The object value tree
176      *  @param[in] path    - Object path
177      *
178      *  Ex: Input path =
179      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"
180      *
181      *  Get the parent class in turn and store it in a temporary vector
182      *
183      *  Output tmpObjPaths = {
184      *  "/xyz/openbmc_project/inventory/system",
185      *  "/xyz/openbmc_project/inventory/system/chassis/",
186      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard",
187      *  "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"}
188      *
189      */
190     void updateAssociationTree(const dbus::ObjectValueTree& objects,
191                                const std::string& path);
192 
193     /* @brief Method to populate the firmware version ID
194      *
195      * @return firmware version ID
196      */
197     std::string populatefwVersion();
198 
199     /* @brief Method to resize the table
200      *
201      * @return resized table
202      */
203     std::vector<uint8_t> tableResize();
204 
205     /* @brief set FRU Record Table
206      *
207      * @param[in] fruData - the data of the fru
208      *
209      * @return PLDM completion code
210      */
211     int setFRUTable(const std::vector<uint8_t>& fruData);
212 
213     /* @brief Method to set the oem platform handler in fru handler class
214      *
215      * @param[in] handler - oem fru handler
216      */
setOemFruHandler(pldm::responder::oem_fru::Handler * handler)217     inline void setOemFruHandler(pldm::responder::oem_fru::Handler* handler)
218     {
219         oemFruHandler = handler;
220     }
221 
222   private:
nextRSI()223     uint16_t nextRSI()
224     {
225         return ++rsi;
226     }
227 
nextRecordHandle()228     uint32_t nextRecordHandle()
229     {
230         return ++rh;
231     }
232 
233     uint32_t rh = 0;
234     uint16_t rsi = 0;
235     uint16_t numRecs = 0;
236     uint8_t padBytes = 0;
237     std::vector<uint8_t> table;
238     uint32_t checksum = 0;
239     bool isBuilt = false;
240 
241     fru_parser::FruParser parser;
242     pldm_pdr* pdrRepo;
243     pldm_entity_association_tree* entityTree;
244     pldm_entity_association_tree* bmcEntityTree;
245     pldm::responder::oem_fru::Handler* oemFruHandler = nullptr;
246     dbus::ObjectValueTree objects;
247 
248     /** @OEM platform handler */
249     pldm::responder::oem_platform::Handler* oemPlatformHandler;
250 
251     std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{};
252 
253     /** @brief populateRecord builds the FRU records for an instance of FRU and
254      *         updates the FRU table with the FRU records.
255      *
256      *  @param[in] interfaces - D-Bus interfaces and the associated property
257      *                          values for the FRU
258      *  @param[in] recordInfos - FRU record info to build the FRU records
259      *  @param[in/out] entity - PLDM entity corresponding to FRU instance
260      */
261     void populateRecords(const dbus::InterfaceMap& interfaces,
262                          const fru_parser::FruRecordInfos& recordInfos,
263                          const pldm_entity& entity);
264 
265     /** @brief Add hotplug record that was modified or added to the PDR entry
266      *  HotPlug is a feature where a FRU can be removed or added when
267      *  the system is running, without needing it to power off.
268      *
269      *  @param[in] pdrEntry - PDR record structure in PDR repository
270      *
271      *  @return record handle of added or modified hotplug record
272      */
273     uint32_t addHotPlugRecord(pldm::responder::pdr_utils::PdrEntry pdrEntry);
274 
275     /** @brief Deletes a FRU record from record set table.
276      *  @param[in] rsi - the FRU Record Set Identifier
277      *
278      *  @return
279      */
280     void deleteFRURecord(uint16_t rsi);
281 
282     /** @brief Associate sensor/effecter to FRU entity
283      */
284     dbus::AssociatedEntityMap associatedEntityMap;
285 };
286 
287 namespace fru
288 {
289 
290 class Handler : public CmdHandler
291 {
292   public:
Handler(const std::string & configPath,const std::filesystem::path & fruMasterJsonPath,pldm_pdr * pdrRepo,pldm_entity_association_tree * entityTree,pldm_entity_association_tree * bmcEntityTree)293     Handler(const std::string& configPath,
294             const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
295             pldm_entity_association_tree* entityTree,
296             pldm_entity_association_tree* bmcEntityTree) :
297         impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree)
298     {
299         handlers.emplace(
300             PLDM_GET_FRU_RECORD_TABLE_METADATA,
301             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
302                 return this->getFRURecordTableMetadata(request, payloadLength);
303             });
304         handlers.emplace(
305             PLDM_GET_FRU_RECORD_TABLE,
306             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
307                 return this->getFRURecordTable(request, payloadLength);
308             });
309         handlers.emplace(
310             PLDM_GET_FRU_RECORD_BY_OPTION,
311             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
312                 return this->getFRURecordByOption(request, payloadLength);
313             });
314         handlers.emplace(
315             PLDM_SET_FRU_RECORD_TABLE,
316             [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) {
317                 return this->setFRURecordTable(request, payloadLength);
318             });
319     }
320 
321     /** @brief Handler for Get FRURecordTableMetadata
322      *
323      *  @param[in] request - Request message payload
324      *  @param[in] payloadLength - Request payload length
325      *
326      *  @return PLDM response message
327      */
328     Response getFRURecordTableMetadata(const pldm_msg* request,
329                                        size_t payloadLength);
330 
331     /** @brief Handler for GetFRURecordTable
332      *
333      *  @param[in] request - Request message payload
334      *  @param[in] payloadLength - Request payload length
335      *
336      *  @return PLDM response message
337      */
338     Response getFRURecordTable(const pldm_msg* request, size_t payloadLength);
339 
340     /** @brief Build FRU table is bnot already built
341      *
342      */
buildFRUTable()343     void buildFRUTable()
344     {
345         impl.buildFRUTable();
346     }
347 
348     /** @brief Get std::map associated with the entity
349      *         key: object path
350      *         value: pldm_entity
351      *
352      *  @return std::map<ObjectPath, pldm_entity>
353      */
getAssociateEntityMap() const354     const pldm::responder::dbus::AssociatedEntityMap& getAssociateEntityMap()
355         const
356     {
357         return impl.getAssociateEntityMap();
358     }
359 
360     /* @brief Method to set the oem platform  handler in host pdr handler class
361      *
362      * @param[in] handler - oem platform handler
363      */
setOemPlatformHandler(pldm::responder::oem_platform::Handler * handler)364     void setOemPlatformHandler(pldm::responder::oem_platform::Handler* handler)
365     {
366         return impl.setOemPlatformHandler(handler);
367     }
368 
369     /** @brief Handler for GetFRURecordByOption
370      *
371      *  @param[in] request - Request message payload
372      *  @param[in] payloadLength - Request payload length
373      *
374      *  @return PLDM response message
375      */
376     Response getFRURecordByOption(const pldm_msg* request,
377                                   size_t payloadLength);
378 
379     /** @brief Handler for SetFRURecordTable
380      *
381      *  @param[in] request - Request message
382      *  @param[in] payloadLength - Request payload length
383      *
384      *  @return PLDM response message
385      */
386     Response setFRURecordTable(const pldm_msg* request, size_t payloadLength);
387 
388     /* @brief Method to set the oem platform handler in fru handler class
389      *
390      * @param[in] handler - oem fru handler
391      */
setOemFruHandler(pldm::responder::oem_fru::Handler * handler)392     void setOemFruHandler(pldm::responder::oem_fru::Handler* handler)
393     {
394         impl.setOemFruHandler(handler);
395     }
396 
397     using Table = std::vector<uint8_t>;
398 
399   private:
400     FruImpl impl;
401 };
402 
403 } // namespace fru
404 
405 } // namespace responder
406 
407 } // namespace pldm
408