xref: /openbmc/pldm/libpldmresponder/fru.hpp (revision c453e164)
1 #pragma once
2 
3 #include "config.h"
4 
5 #include "fru_parser.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 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      */
65     FruImpl(const std::string& configPath,
66             const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
67             pldm_entity_association_tree* entityTree,
68             pldm_entity_association_tree* bmcEntityTree) :
69         parser(configPath, fruMasterJsonPath),
70         pdrRepo(pdrRepo), entityTree(entityTree), bmcEntityTree(bmcEntityTree)
71     {}
72 
73     /** @brief Total length of the FRU table in bytes, this excludes the pad
74      *         bytes and the checksum.
75      *
76      *  @return size of the FRU table
77      */
78     uint32_t size() const
79     {
80         return table.size() - padBytes;
81     }
82 
83     /** @brief The checksum of the contents of the FRU table
84      *
85      *  @return checksum
86      */
87     uint32_t checkSum() const
88     {
89         return checksum;
90     }
91 
92     /** @brief Number of record set identifiers in the FRU tables
93      *
94      *  @return number of record set identifiers
95      */
96     uint16_t numRSI() const
97     {
98         return rsi;
99     }
100 
101     /** @brief The number of FRU records in the table
102      *
103      *  @return number of FRU records
104      */
105     uint16_t numRecords() const
106     {
107         return numRecs;
108     }
109 
110     /** @brief Get the FRU table
111      *
112      *  @param[out] - Populate response with the FRU table
113      */
114     void getFRUTable(Response& response);
115 
116     /** @brief Get FRU Record Table By Option
117      *  @param[out] response - Populate response with the FRU table got by
118      *                         options
119      *  @param[in] fruTableHandle - The fru table handle
120      *  @param[in] recordSetIdentifer - The record set identifier
121      *  @param[in] recordType - The record type
122      *  @param[in] fieldType - The field type
123      */
124     int getFRURecordByOption(Response& response, uint16_t fruTableHandle,
125                              uint16_t recordSetIdentifer, uint8_t recordType,
126                              uint8_t fieldType);
127 
128     /** @brief FRU table is built by processing the D-Bus inventory namespace
129      *         based on the config files for FRU. The table is populated based
130      *         on the isBuilt flag.
131      */
132     void buildFRUTable();
133 
134     /** @brief Get std::map associated with the entity
135      *         key: object path
136      *         value: pldm_entity
137      *
138      *  @return std::map<ObjectPath, pldm_entity>
139      */
140     inline const pldm::responder::dbus::AssociatedEntityMap&
141         getAssociateEntityMap() const
142     {
143         return associatedEntityMap;
144     }
145 
146     /* @brief Method to populate the firmware version ID
147      *
148      * @return firmware version ID
149      */
150     std::string populatefwVersion();
151 
152   private:
153     uint16_t nextRSI()
154     {
155         return ++rsi;
156     }
157 
158     uint32_t nextRecordHandle()
159     {
160         return ++rh;
161     }
162 
163     uint32_t rh = 0;
164     uint16_t rsi = 0;
165     uint16_t numRecs = 0;
166     uint8_t padBytes = 0;
167     std::vector<uint8_t> table;
168     uint32_t checksum = 0;
169     bool isBuilt = false;
170 
171     fru_parser::FruParser parser;
172     pldm_pdr* pdrRepo;
173     pldm_entity_association_tree* entityTree;
174     pldm_entity_association_tree* bmcEntityTree;
175 
176     std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{};
177 
178     /** @brief populateRecord builds the FRU records for an instance of FRU and
179      *         updates the FRU table with the FRU records.
180      *
181      *  @param[in] interfaces - D-Bus interfaces and the associated property
182      *                          values for the FRU
183      *  @param[in] recordInfos - FRU record info to build the FRU records
184      *  @param[in/out] entity - PLDM entity corresponding to FRU instance
185      */
186     void populateRecords(const dbus::InterfaceMap& interfaces,
187                          const fru_parser::FruRecordInfos& recordInfos,
188                          const pldm_entity& entity);
189 
190     /** @brief Associate sensor/effecter to FRU entity
191      */
192     dbus::AssociatedEntityMap associatedEntityMap;
193 };
194 
195 namespace fru
196 {
197 
198 class Handler : public CmdHandler
199 {
200   public:
201     Handler(const std::string& configPath,
202             const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo,
203             pldm_entity_association_tree* entityTree,
204             pldm_entity_association_tree* bmcEntityTree) :
205         impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree)
206     {
207         handlers.emplace(PLDM_GET_FRU_RECORD_TABLE_METADATA,
208                          [this](const pldm_msg* request, size_t payloadLength) {
209                              return this->getFRURecordTableMetadata(
210                                  request, payloadLength);
211                          });
212 
213         handlers.emplace(PLDM_GET_FRU_RECORD_TABLE,
214                          [this](const pldm_msg* request, size_t payloadLength) {
215                              return this->getFRURecordTable(request,
216                                                             payloadLength);
217                          });
218         handlers.emplace(PLDM_GET_FRU_RECORD_BY_OPTION,
219                          [this](const pldm_msg* request, size_t payloadLength) {
220                              return this->getFRURecordByOption(request,
221                                                                payloadLength);
222                          });
223     }
224 
225     /** @brief Handler for Get FRURecordTableMetadata
226      *
227      *  @param[in] request - Request message payload
228      *  @param[in] payloadLength - Request payload length
229      *
230      *  @return PLDM response message
231      */
232     Response getFRURecordTableMetadata(const pldm_msg* request,
233                                        size_t payloadLength);
234 
235     /** @brief Handler for GetFRURecordTable
236      *
237      *  @param[in] request - Request message payload
238      *  @param[in] payloadLength - Request payload length
239      *
240      *  @return PLDM response message
241      */
242     Response getFRURecordTable(const pldm_msg* request, size_t payloadLength);
243 
244     /** @brief Build FRU table is bnot already built
245      *
246      */
247     void buildFRUTable()
248     {
249         impl.buildFRUTable();
250     }
251 
252     /** @brief Get std::map associated with the entity
253      *         key: object path
254      *         value: pldm_entity
255      *
256      *  @return std::map<ObjectPath, pldm_entity>
257      */
258     const pldm::responder::dbus::AssociatedEntityMap&
259         getAssociateEntityMap() const
260     {
261         return impl.getAssociateEntityMap();
262     }
263 
264     /** @brief Handler for GetFRURecordByOption
265      *
266      *  @param[in] request - Request message payload
267      *  @param[in] payloadLength - Request payload length
268      *
269      *  @return PLDM response message
270      */
271     Response getFRURecordByOption(const pldm_msg* request,
272                                   size_t payloadLength);
273 
274   private:
275     FruImpl impl;
276 };
277 
278 } // namespace fru
279 
280 } // namespace responder
281 
282 } // namespace pldm
283