xref: /openbmc/pldm/platform-mc/terminus.hpp (revision fe2527954be36a3013dc6b8c8ff13ae649bb58a6)
1 #pragma once
2 
3 #include "common/types.hpp"
4 #include "dbus_impl_fru.hpp"
5 #include "numeric_sensor.hpp"
6 #include "requester/handler.hpp"
7 #include "terminus.hpp"
8 
9 #include <libpldm/fru.h>
10 #include <libpldm/platform.h>
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              sdeventplus::Event& event);
73 
74     /** @brief Check if the terminus supports the PLDM type message
75      *
76      *  @param[in] type - PLDM Type
77      *  @return support state - True if support, otherwise False
78      */
79     bool doesSupportType(uint8_t type);
80 
81     /** @brief Check if the terminus supports the PLDM command message
82      *
83      *  @param[in] type - PLDM Type
84      *  @param[in] command - PLDM command
85      *  @return support state - True if support, otherwise False
86      */
87     bool doesSupportCommand(uint8_t type, uint8_t command);
88 
89     /** @brief Set the supported PLDM commands for terminus
90      *
91      *  @param[in] cmds - bit mask of the supported PLDM commands
92      *  @return success state - True if success, otherwise False
93      */
setSupportedCommands(const std::vector<uint8_t> & cmds)94     bool setSupportedCommands(const std::vector<uint8_t>& cmds)
95     {
96         const size_t expectedSize =
97             PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8);
98         if (cmds.empty() || cmds.size() != expectedSize)
99         {
100             lg2::error(
101                 "setSupportedCommands received invalid bit mask size. Expected: {EXPECTED}, Received: {RECEIVED}",
102                 "EXPECTED", expectedSize, "RECEIVED", cmds.size());
103             return false;
104         }
105 
106         /* Assign Vector supportedCmds by Vector cmds */
107         supportedCmds.resize(cmds.size());
108         std::copy(cmds.begin(), cmds.begin() + cmds.size(),
109                   supportedCmds.begin());
110 
111         return true;
112     }
113 
114     /** @brief Set the PLDM supported type version for terminus
115      *
116      *  @param[in] type - PLDM supported types
117      *  @param[in] version - PLDM supported type version
118      *  @return success state - True if success, otherwise False
119      */
setSupportedTypeVersions(const uint8_t type,const ver32_t version)120     inline bool setSupportedTypeVersions(const uint8_t type,
121                                          const ver32_t version)
122     {
123         if (type > PLDM_MAX_TYPES || type >= supportedTypeVersions.size())
124         {
125             return false;
126         }
127         supportedTypeVersions[type] = version;
128 
129         return true;
130     }
131 
132     /** @brief Parse the PDRs stored in the member variable, pdrs.
133      */
134     void parseTerminusPDRs();
135 
136     /** @brief The getter to return terminus's TID */
getTid()137     pldm_tid_t getTid()
138     {
139         return tid;
140     }
141 
142     /** @brief The getter to get terminus's mctp medium */
getTerminusName()143     std::optional<std::string_view> getTerminusName()
144     {
145         if (terminusName.empty())
146         {
147             return std::nullopt;
148         }
149         return terminusName;
150     }
151 
152     /** @brief Parse record data from FRU table
153      *
154      *  @param[in] fruData - pointer to FRU record table
155      *  @param[in] fruLen - FRU table length
156      */
157     void updateInventoryWithFru(const uint8_t* fruData, const size_t fruLen);
158 
159     /** @brief A list of PDRs fetched from Terminus */
160     std::vector<std::vector<uint8_t>> pdrs{};
161 
162     /** @brief A flag to indicate if terminus has been initialized */
163     bool initialized = false;
164 
165     /** @brief maximum message buffer size the terminus can send and receive */
166     uint16_t maxBufferSize;
167 
168     /** @brief This value indicates the event messaging styles supported by the
169      *         terminus
170      */
171     bitfield8_t synchronyConfigurationSupported;
172 
173     /** @brief A list of numericSensors */
174     std::vector<std::shared_ptr<NumericSensor>> numericSensors{};
175 
176     /** @brief The flag indicates that the terminus FIFO contains a large
177      *         message that will require a multipart transfer via the
178      *         PollForPlatformEvent command
179      */
180     bool pollEvent;
181 
182     /** @brief The sensor id is used in pollForPlatformMessage command */
183     uint16_t pollEventId;
184 
185     /** @brief The dataTransferHandle from `pldmMessagePollEvent` event and will
186      *         be used as `dataTransferHandle` for pollForPlatformMessage
187      *         command.
188      */
189     uint32_t pollDataTransferHandle;
190 
191     /** @brief Get Sensor Auxiliary Names by sensorID
192      *
193      *  @param[in] id - sensor ID
194      *  @return sensor auxiliary names
195      */
196     std::shared_ptr<SensorAuxiliaryNames> getSensorAuxiliaryNames(SensorId id);
197 
198     /** @brief Get Numeric Sensor Object by sensorID
199      *
200      *  @param[in] id - sensor ID
201      *
202      *  @return sensor object
203      */
204     std::shared_ptr<NumericSensor> getSensorObject(SensorId id);
205 
206   private:
207     /** @brief Find the Terminus Name from the Entity Auxiliary name list
208      *         The Entity Auxiliary name list is entityAuxiliaryNamesTbl.
209      *  @return terminus name in string option
210      */
211     std::optional<std::string_view> findTerminusName();
212 
213     /** @brief Construct the NumericSensor sensor class for the PLDM sensor.
214      *         The NumericSensor class will handle create D-Bus object path,
215      *         provide the APIs to update sensor value, threshold...
216      *
217      *  @param[in] pdr - the numeric sensor PDR info
218      */
219     void addNumericSensor(
220         const std::shared_ptr<pldm_numeric_sensor_value_pdr> pdr);
221 
222     /** @brief Parse the numeric sensor PDRs
223      *
224      *  @param[in] pdrData - the response PDRs from GetPDR command
225      *  @return pointer to numeric sensor info struct
226      */
227     std::shared_ptr<pldm_numeric_sensor_value_pdr> parseNumericSensorPDR(
228         const std::vector<uint8_t>& pdrData);
229 
230     /** @brief Parse the sensor Auxiliary name PDRs
231      *
232      *  @param[in] pdrData - the response PDRs from GetPDR command
233      *  @return pointer to sensor Auxiliary name info struct
234      */
235     std::shared_ptr<SensorAuxiliaryNames> parseSensorAuxiliaryNamesPDR(
236         const std::vector<uint8_t>& pdrData);
237 
238     /** @brief Parse the Entity Auxiliary name PDRs
239      *
240      *  @param[in] pdrData - the response PDRs from GetPDR command
241      *  @return pointer to Entity Auxiliary name info struct
242      */
243     std::shared_ptr<EntityAuxiliaryNames> parseEntityAuxiliaryNamesPDR(
244         const std::vector<uint8_t>& pdrData);
245 
246     /** @brief Construct the NumericSensor sensor class for the compact numeric
247      *         PLDM sensor.
248      *
249      *  @param[in] pdr - the compact numeric sensor PDR info
250      */
251     void addCompactNumericSensor(
252         const std::shared_ptr<pldm_compact_numeric_sensor_pdr> pdr);
253 
254     /** @brief Parse the compact numeric sensor PDRs
255      *
256      *  @param[in] pdrData - the response PDRs from GetPDR command
257      *  @return pointer to compact numeric sensor info struct
258      */
259     std::shared_ptr<pldm_compact_numeric_sensor_pdr>
260         parseCompactNumericSensorPDR(const std::vector<uint8_t>& pdrData);
261 
262     /** @brief Parse the sensor Auxiliary name from compact numeric sensor PDRs
263      *
264      *  @param[in] pdrData - the response PDRs from GetPDR command
265      *  @return pointer to sensor Auxiliary name info struct
266      */
267     std::shared_ptr<SensorAuxiliaryNames> parseCompactNumericSensorNames(
268         const std::vector<uint8_t>& pdrData);
269 
270     /** @brief Create the terminus inventory path to
271      *         /xyz/openbmc_project/inventory/Item/Board/.
272      *
273      *  @param[in] tName - the terminus name
274      *  @return true/false: True if there is no error in creating inventory path
275      *
276      */
277     bool createInventoryPath(std::string tName);
278 
279     /** @brief Get sensor names from Sensor Auxiliary Names PDRs
280      *
281      *  @param[in] sensorId - Sensor ID
282      *  @param[in] isEffecter - This is an effecter, not a sensor
283      *  @return vector of sensor name strings
284      *
285      */
286     std::vector<std::string> getSensorNames(const SensorId& sensorId);
287 
288     /** @brief Add the next sensor PDR to this terminus, iterated by
289      *         sensorPdrIt.
290      */
291     void addNextSensorFromPDRs();
292 
293     /* @brief The terminus's TID */
294     pldm_tid_t tid;
295 
296     /* @brief The supported PLDM command types of the terminus */
297     std::bitset<64> supportedTypes;
298 
299     /** @brief Store supported PLDM commands of a terminus
300      *         Maximum number of PLDM Type is PLDM_MAX_TYPES
301      *         Maximum number of PLDM command for each type is
302      *         PLDM_MAX_CMDS_PER_TYPE.
303      *         Each uint8_t can store the supported state of 8 PLDM commands.
304      *         Size of supportedCmds will be
305      *         PLDM_MAX_TYPES * (PLDM_MAX_CMDS_PER_TYPE / 8).
306      */
307     std::vector<uint8_t> supportedCmds;
308 
309     /* @brief The PLDM supported type version */
310     std::map<uint8_t, ver32_t> supportedTypeVersions;
311 
312     /* @brief Sensor Auxiliary Name list */
313     std::vector<std::shared_ptr<SensorAuxiliaryNames>>
314         sensorAuxiliaryNamesTbl{};
315 
316     /* @brief Entity Auxiliary Name list */
317     std::vector<std::shared_ptr<EntityAuxiliaryNames>>
318         entityAuxiliaryNamesTbl{};
319 
320     /** @brief Terminus name */
321     EntityName terminusName{};
322     /* @brief The pointer of inventory D-Bus interface for the terminus */
323     std::unique_ptr<pldm::dbus_api::PldmEntityReq> inventoryItemBoardInft =
324         nullptr;
325 
326     /* @brief Inventory D-Bus object path of the terminus */
327     std::string inventoryPath;
328 
329     /** @brief reference of main event loop of pldmd, primarily used to schedule
330      *  work
331      */
332     sdeventplus::Event& event;
333 
334     /** @brief The event source to defer sensor creation tasks to event loop*/
335     std::unique_ptr<sdeventplus::source::Defer> sensorCreationEvent;
336 
337     /** @brief Numeric Sensor PDR list */
338     std::vector<std::shared_ptr<pldm_numeric_sensor_value_pdr>>
339         numericSensorPdrs{};
340 
341     /** @brief Compact Numeric Sensor PDR list */
342     std::vector<std::shared_ptr<pldm_compact_numeric_sensor_pdr>>
343         compactNumericSensorPdrs{};
344 
345     /** @brief Iteration to loop through sensor PDRs when adding sensors */
346     SensorId sensorPdrIt = 0;
347 };
348 } // namespace platform_mc
349 } // namespace pldm
350