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