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