xref: /openbmc/pldm/libpldmresponder/fru.hpp (revision a4a96162)
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 
35 } // namespace dbus
36 
37 /** @class FruImpl
38  *
39  *  @brief Builds the PLDM FRU table containing the FRU records
40  */
41 class FruImpl
42 {
43   public:
44     /* @brief Header size for FRU record, it includes the FRU record set
45      *        identifier, FRU record type, Number of FRU fields, Encoding type
46      *        of FRU fields
47      */
48     static constexpr size_t recHeaderSize =
49         sizeof(struct pldm_fru_record_data_format) -
50         sizeof(struct pldm_fru_record_tlv);
51 
52     /** @brief Constructor for FruImpl, the configPath is consumed to build the
53      *         FruParser object.
54      *
55      *  @param[in] configPath - path to the directory containing config files
56      *                          for PLDM FRU
57      *  @param[in] pdrRepo - opaque pointer to PDR repository
58      *  @param[in] entityTree - opaque pointer to the entity association tree
59      */
60     FruImpl(const std::string& configPath, pldm_pdr* pdrRepo,
61             pldm_entity_association_tree* entityTree) :
62         parser(configPath),
63         pdrRepo(pdrRepo), entityTree(entityTree)
64     {}
65 
66     /** @brief Total length of the FRU table in bytes, this excludes the pad
67      *         bytes and the checksum.
68      *
69      *  @return size of the FRU table
70      */
71     uint32_t size() const
72     {
73         return table.size() - padBytes;
74     }
75 
76     /** @brief The checksum of the contents of the FRU table
77      *
78      *  @return checksum
79      */
80     uint32_t checkSum() const
81     {
82         return checksum;
83     }
84 
85     /** @brief Number of record set identifiers in the FRU tables
86      *
87      *  @return number of record set identifiers
88      */
89     uint16_t numRSI() const
90     {
91         return rsi;
92     }
93 
94     /** @brief The number of FRU records in the table
95      *
96      *  @return number of FRU records
97      */
98     uint16_t numRecords() const
99     {
100         return numRecs;
101     }
102 
103     /** @brief Get the FRU table
104      *
105      *  @param[out] - Populate response with the FRU table
106      */
107     void getFRUTable(Response& response);
108 
109     /** @brief Get FRU Record Table By Option
110      *  @param[out] response - Populate response with the FRU table got by
111      *                         options
112      *  @param[in] fruTableHandle - The fru table handle
113      *  @param[in] recordSetIdentifer - The record set identifier
114      *  @param[in] recordType - The record type
115      *  @param[in] fieldType - The field type
116      */
117     int getFRURecordByOption(Response& response, uint16_t fruTableHandle,
118                              uint16_t recordSetIdentifer, uint8_t recordType,
119                              uint8_t fieldType);
120 
121     /** @brief FRU table is built by processing the D-Bus inventory namespace
122      *         based on the config files for FRU. The table is populated based
123      *         on the isBuilt flag.
124      */
125     void buildFRUTable();
126 
127   private:
128     uint16_t nextRSI()
129     {
130         return ++rsi;
131     }
132 
133     uint16_t rsi = 0;
134     uint16_t numRecs = 0;
135     uint8_t padBytes = 0;
136     std::vector<uint8_t> table;
137     uint32_t checksum = 0;
138     bool isBuilt = false;
139 
140     fru_parser::FruParser parser;
141     pldm_pdr* pdrRepo;
142     pldm_entity_association_tree* entityTree;
143 
144     std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{};
145 
146     /** @brief populateRecord builds the FRU records for an instance of FRU and
147      *         updates the FRU table with the FRU records.
148      *
149      *  @param[in] interfaces - D-Bus interfaces and the associated property
150      *                          values for the FRU
151      *  @param[in] recordInfos - FRU record info to build the FRU records
152      *  @param[in/out] entity - PLDM entity corresponding to FRU instance
153      */
154     void populateRecords(const pldm::responder::dbus::InterfaceMap& interfaces,
155                          const fru_parser::FruRecordInfos& recordInfos,
156                          const pldm_entity& entity);
157 };
158 
159 namespace fru
160 {
161 
162 class Handler : public CmdHandler
163 {
164 
165   public:
166     Handler(const std::string& configPath, pldm_pdr* pdrRepo,
167             pldm_entity_association_tree* entityTree) :
168         impl(configPath, pdrRepo, entityTree)
169     {
170         handlers.emplace(PLDM_GET_FRU_RECORD_TABLE_METADATA,
171                          [this](const pldm_msg* request, size_t payloadLength) {
172                              return this->getFRURecordTableMetadata(
173                                  request, payloadLength);
174                          });
175 
176         handlers.emplace(PLDM_GET_FRU_RECORD_TABLE,
177                          [this](const pldm_msg* request, size_t payloadLength) {
178                              return this->getFRURecordTable(request,
179                                                             payloadLength);
180                          });
181         handlers.emplace(PLDM_GET_FRU_RECORD_BY_OPTION,
182                          [this](const pldm_msg* request, size_t payloadLength) {
183                              return this->getFRURecordByOption(request,
184                                                                payloadLength);
185                          });
186     }
187 
188     /** @brief Handler for Get FRURecordTableMetadata
189      *
190      *  @param[in] request - Request message payload
191      *  @param[in] payloadLength - Request payload length
192      *
193      *  @return PLDM response message
194      */
195     Response getFRURecordTableMetadata(const pldm_msg* request,
196                                        size_t payloadLength);
197 
198     /** @brief Handler for GetFRURecordTable
199      *
200      *  @param[in] request - Request message payload
201      *  @param[in] payloadLength - Request payload length
202      *
203      *  @return PLDM response message
204      */
205     Response getFRURecordTable(const pldm_msg* request, size_t payloadLength);
206 
207     /** @brief Build FRU table is bnot already built
208      *
209      */
210     void buildFRUTable()
211     {
212         impl.buildFRUTable();
213     }
214 
215     /** @brief Handler for GetFRURecordByOption
216      *
217      *  @param[in] request - Request message payload
218      *  @param[in] payloadLength - Request payload length
219      *
220      *  @return PLDM response message
221      */
222     Response getFRURecordByOption(const pldm_msg* request,
223                                   size_t payloadLength);
224 
225   private:
226     FruImpl impl;
227 };
228 
229 } // namespace fru
230 
231 } // namespace responder
232 
233 } // namespace pldm
234