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 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