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