xref: /openbmc/pldm/platform-mc/terminus.hpp (revision b6d3943d0deca9e61826370f69c1309007a5a4aa)
1 #pragma once
2 
3 #include "libpldm/fru.h"
4 #include "libpldm/platform.h"
5 
6 #include "common/types.hpp"
7 #include "dbus_impl_fru.hpp"
8 #include "numeric_sensor.hpp"
9 #include "requester/handler.hpp"
10 #include "terminus.hpp"
11 
12 #include <sdbusplus/server/object.hpp>
13 #include <sdeventplus/event.hpp>
14 
15 #include <algorithm>
16 #include <bitset>
17 #include <string>
18 #include <tuple>
19 #include <utility>
20 #include <vector>
21 
22 namespace pldm
23 {
24 namespace platform_mc
25 {
26 
27 using ContainerID = uint16_t;
28 using EntityInstanceNumber = uint16_t;
29 using EntityName = std::string;
30 using EntityType = uint16_t;
31 using SensorId = uint16_t;
32 using SensorCnt = uint8_t;
33 using NameLanguageTag = std::string;
34 using SensorName = std::string;
35 using SensorAuxiliaryNames = std::tuple<
36     SensorId, SensorCnt,
37     std::vector<std::vector<std::pair<NameLanguageTag, SensorName>>>>;
38 
39 /** @struct EntityKey
40  *
41  *  EntityKey uniquely identifies the PLDM entity and a combination of Entity
42  *  Type, Entity Instance Number, Entity Container ID
43  *
44  */
45 struct EntityKey
46 {
47     EntityType type;                  //!< Entity type
48     EntityInstanceNumber instanceIdx; //!< Entity instance number
49     ContainerID containerId;          //!< Entity container ID
50 
operator ==pldm::platform_mc::EntityKey51     bool operator==(const EntityKey& e) const
52     {
53         return ((type == e.type) && (instanceIdx == e.instanceIdx) &&
54                 (containerId == e.containerId));
55     }
56 };
57 
58 using AuxiliaryNames = std::vector<std::pair<NameLanguageTag, std::string>>;
59 using EntityKey = struct EntityKey;
60 using EntityAuxiliaryNames = std::tuple<EntityKey, AuxiliaryNames>;
61 
62 /**
63  * @brief Terminus
64  *
65  * Terminus class holds the TID, supported PLDM Type or PDRs which are needed by
66  * other manager class for sensor monitoring and control.
67  */
68 class Terminus
69 {
70   public:
71     Terminus(pldm_tid_t tid, uint64_t supportedPLDMTypes);
72 
73     /** @brief Check if the terminus supports the PLDM type message
74      *
75      *  @param[in] type - PLDM Type
76      *  @return support state - True if support, otherwise False
77      */
78     bool doesSupportType(uint8_t type);
79 
80     /** @brief Check if the terminus supports the PLDM command message
81      *
82      *  @param[in] type - PLDM Type
83      *  @param[in] command - PLDM command
84      *  @return support state - True if support, otherwise False
85      */
86     bool doesSupportCommand(uint8_t type, uint8_t command);
87 
88     /** @brief Set the supported PLDM commands for terminus
89      *
90      *  @param[in] cmds - bit mask of the supported PLDM commands
91      *  @return success state - True if success, otherwise False
92      */
setSupportedCommands(const std::vector<uint8_t> & cmds)93     bool setSupportedCommands(const std::vector<uint8_t>& cmds)
94     {
95         const size_t expectedSize =
96             PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
97         if (cmds.empty() || cmds.size() != expectedSize)
98         {
99             lg2::error(
100                 "setSupportedCommands received invalid bit mask size. Expected: {EXPECTED}, Received: {RECEIVED}",
101                 "EXPECTED", expectedSize, "RECEIVED", cmds.size());
102             return false;
103         }
104 
105         /* Assign Vector supportedCmds by Vector cmds */
106         supportedCmds.resize(cmds.size());
107         std::copy(cmds.begin(), cmds.begin() + cmds.size(),
108                   supportedCmds.begin());
109 
110         return true;
111     }
112 
113     /** @brief Set the PLDM supported type version for terminus
114      *
115      *  @param[in] type - PLDM supported types
116      *  @param[in] version - PLDM supported type version
117      *  @return success state - True if success, otherwise False
118      */
setSupportedTypeVersions(const uint8_t type,const ver32_t version)119     inline bool setSupportedTypeVersions(const uint8_t type,
120                                          const ver32_t version)
121     {
122         if (type > PLDM_MAX_TYPES || type >= supportedTypeVersions.size())
123         {
124             return false;
125         }
126         supportedTypeVersions[type] = version;
127 
128         return true;
129     }
130 
131     /** @brief Parse the PDRs stored in the member variable, pdrs.
132      */
133     void parseTerminusPDRs();
134 
135     /** @brief The getter to return terminus's TID */
getTid()136     pldm_tid_t getTid()
137     {
138         return tid;
139     }
140 
141     /** @brief The getter to get terminus's mctp medium */
getTerminusName()142     std::optional<std::string_view> getTerminusName()
143     {
144         if (terminusName.empty())
145         {
146             return std::nullopt;
147         }
148         return terminusName;
149     }
150 
151     /** @brief Parse record data from FRU table
152      *
153      *  @param[in] fruData - pointer to FRU record table
154      *  @param[in] fruLen - FRU table length
155      */
156     void updateInventoryWithFru(const uint8_t* fruData, const size_t fruLen);
157 
158     /** @brief A list of PDRs fetched from Terminus */
159     std::vector<std::vector<uint8_t>> pdrs{};
160 
161     /** @brief A flag to indicate if terminus has been initialized */
162     bool initialized = false;
163 
164     /** @brief maximum message buffer size the terminus can send and receive */
165     uint16_t maxBufferSize;
166 
167     /** @brief This value indicates the event messaging styles supported by the
168      *         terminus
169      */
170     bitfield8_t synchronyConfigurationSupported;
171 
172     /** @brief A list of numericSensors */
173     std::vector<std::shared_ptr<NumericSensor>> numericSensors{};
174 
175     /** @brief The flag indicates that the terminus FIFO contains a large
176      *         message that will require a multipart transfer via the
177      *         PollForPlatformEvent command
178      */
179     bool pollEvent;
180 
181     /** @brief The sensor id is used in pollForPlatformMessage command */
182     uint16_t pollEventId;
183 
184     /** @brief The dataTransferHandle from `pldmMessagePollEvent` event and will
185      *         be used as `dataTransferHandle` for pollForPlatformMessage
186      *         command.
187      */
188     uint32_t pollDataTransferHandle;
189 
190     /** @brief Get Sensor Auxiliary Names by sensorID
191      *
192      *  @param[in] id - sensor ID
193      *  @return sensor auxiliary names
194      */
195     std::shared_ptr<SensorAuxiliaryNames> getSensorAuxiliaryNames(SensorId id);
196 
197     /** @brief Get Numeric Sensor Object by sensorID
198      *
199      *  @param[in] id - sensor ID
200      *
201      *  @return sensor object
202      */
203     std::shared_ptr<NumericSensor> getSensorObject(SensorId id);
204 
205   private:
206     /** @brief Find the Terminus Name from the Entity Auxiliary name list
207      *         The Entity Auxiliary name list is entityAuxiliaryNamesTbl.
208      *  @return terminus name in string option
209      */
210     std::optional<std::string_view> findTerminusName();
211 
212     /** @brief Construct the NumericSensor sensor class for the PLDM sensor.
213      *         The NumericSensor class will handle create D-Bus object path,
214      *         provide the APIs to update sensor value, threshold...
215      *
216      *  @param[in] pdr - the numeric sensor PDR info
217      */
218     void addNumericSensor(
219         const std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr);
220 
221     /** @brief Parse the numeric sensor PDRs
222      *
223      *  @param[in] pdrData - the response PDRs from GetPDR command
224      *  @return pointer to numeric sensor info struct
225      */
226     std::shared_ptr<pldm_numeric_sensor_value_pdr>
227         parseNumericSensorPDR(const std::vector<uint8_t>& pdrData);
228 
229     /** @brief Parse the sensor Auxiliary name PDRs
230      *
231      *  @param[in] pdrData - the response PDRs from GetPDR command
232      *  @return pointer to sensor Auxiliary name info struct
233      */
234     std::shared_ptr<SensorAuxiliaryNames>
235         parseSensorAuxiliaryNamesPDR(const std::vector<uint8_t>& pdrData);
236 
237     /** @brief Parse the Entity Auxiliary name PDRs
238      *
239      *  @param[in] pdrData - the response PDRs from GetPDR command
240      *  @return pointer to Entity Auxiliary name info struct
241      */
242     std::shared_ptr<EntityAuxiliaryNames>
243         parseEntityAuxiliaryNamesPDR(const std::vector<uint8_t>& pdrData);
244 
245     /** @brief Construct the NumericSensor sensor class for the compact numeric
246      *         PLDM sensor.
247      *
248      *  @param[in] pdr - the compact numeric sensor PDR info
249      */
250     void addCompactNumericSensor(
251         const std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr);
252 
253     /** @brief Parse the compact numeric sensor PDRs
254      *
255      *  @param[in] pdrData - the response PDRs from GetPDR command
256      *  @return pointer to compact numeric sensor info struct
257      */
258     std::shared_ptr<pldm_compact_numeric_sensor_pdr>
259         parseCompactNumericSensorPDR(const std::vector<uint8_t>& pdrData);
260 
261     /** @brief Parse the sensor Auxiliary name from compact numeric sensor PDRs
262      *
263      *  @param[in] pdrData - the response PDRs from GetPDR command
264      *  @return pointer to sensor Auxiliary name info struct
265      */
266     std::shared_ptr<SensorAuxiliaryNames>
267         parseCompactNumericSensorNames(const std::vector<uint8_t>& pdrData);
268 
269     /** @brief Create the terminus inventory path to
270      *         /xyz/openbmc_project/inventory/Item/Board/.
271      *
272      *  @param[in] tName - the terminus name
273      *  @return true/false: True if there is no error in creating inventory path
274      *
275      */
276     bool createInventoryPath(std::string tName);
277 
278     /* @brief The terminus's TID */
279     pldm_tid_t tid;
280 
281     /* @brief The supported PLDM command types of the terminus */
282     std::bitset<64> supportedTypes;
283 
284     /** @brief Store supported PLDM commands of a terminus
285      *         Maximum number of PLDM Type is PLDM_MAX_TYPES
286      *         Maximum number of PLDM command for each type is
287      *         PLDM_MAX_CMDS_PER_TYPE.
288      *         Each uint8_t can store the supported state of 8 PLDM commands.
289      *         Size of supportedCmds will be
290      *         PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8).
291      */
292     std::vector<uint8_t> supportedCmds;
293 
294     /* @brief The PLDM supported type version */
295     std::map<uint8_t, ver32_t> supportedTypeVersions;
296 
297     /* @brief Sensor Auxiliary Name list */
298     std::vector<std::shared_ptr<SensorAuxiliaryNames>>
299         sensorAuxiliaryNamesTbl{};
300 
301     /* @brief Entity Auxiliary Name list */
302     std::vector<std::shared_ptr<EntityAuxiliaryNames>>
303         entityAuxiliaryNamesTbl{};
304 
305     /** @brief Terminus name */
306     EntityName terminusName{};
307     /* @brief The pointer of inventory D-Bus interface for the terminus */
308     std::unique_ptr<pldm::dbus_api::PldmEntityReq> inventoryItemBoardInft =
309         nullptr;
310 
311     /* @brief Inventory D-Bus object path of the terminus */
312     std::string inventoryPath;
313 };
314 } // namespace platform_mc
315 } // namespace pldm
316