1 #pragma once 2 3 #include "fru_parser.hpp" 4 #include "libpldmresponder/pdr_utils.hpp" 5 #include "oem_handler.hpp" 6 #include "pldmd/handler.hpp" 7 8 #include <libpldm/fru.h> 9 #include <libpldm/pdr.h> 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 std::vector<uint64_t>, std::vector<std::string>>; 31 using PropertyMap = std::map<Property, Value>; 32 using InterfaceMap = std::map<Interface, PropertyMap>; 33 using ObjectValueTree = std::map<sdbusplus::message::object_path, InterfaceMap>; 34 using ObjectPath = std::string; 35 using AssociatedEntityMap = std::map<ObjectPath, pldm_entity>; 36 37 } // namespace dbus 38 39 /** @class FruImpl 40 * 41 * @brief Builds the PLDM FRU table containing the FRU records 42 */ 43 class FruImpl 44 { 45 public: 46 /* @brief Header size for FRU record, it includes the FRU record set 47 * identifier, FRU record type, Number of FRU fields, Encoding type 48 * of FRU fields 49 */ 50 static constexpr size_t recHeaderSize = 51 sizeof(struct pldm_fru_record_data_format) - 52 sizeof(struct pldm_fru_record_tlv); 53 54 /** @brief Constructor for FruImpl, the configPath is consumed to build the 55 * FruParser object. 56 * 57 * @param[in] configPath - path to the directory containing config files 58 * for PLDM FRU 59 * @param[in] fruMasterJsonPath - path to the file containing the FRU D-Bus 60 * Lookup Map 61 * @param[in] pdrRepo - opaque pointer to PDR repository 62 * @param[in] entityTree - opaque pointer to the entity association tree 63 * @param[in] bmcEntityTree - opaque pointer to bmc's entity association 64 * tree 65 * @param[in] oemFruHandler - OEM fru handler 66 */ FruImpl(const std::string & configPath,const std::filesystem::path & fruMasterJsonPath,pldm_pdr * pdrRepo,pldm_entity_association_tree * entityTree,pldm_entity_association_tree * bmcEntityTree)67 FruImpl(const std::string& configPath, 68 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 69 pldm_entity_association_tree* entityTree, 70 pldm_entity_association_tree* bmcEntityTree) : 71 parser(configPath, fruMasterJsonPath), pdrRepo(pdrRepo), 72 entityTree(entityTree), bmcEntityTree(bmcEntityTree) 73 {} 74 75 /** @brief Total length of the FRU table in bytes, this includes the pad 76 * bytes and the checksum. 77 * 78 * @return size of the FRU table 79 */ size() const80 uint32_t size() const 81 { 82 return table.size(); 83 } 84 85 /** @brief The checksum of the contents of the FRU table 86 * 87 * @return checksum 88 */ checkSum() const89 uint32_t checkSum() const 90 { 91 return checksum; 92 } 93 94 /** @brief Number of record set identifiers in the FRU tables 95 * 96 * @return number of record set identifiers 97 */ numRSI() const98 uint16_t numRSI() const 99 { 100 return rsi; 101 } 102 103 /** @brief The number of FRU records in the table 104 * 105 * @return number of FRU records 106 */ numRecords() const107 uint16_t numRecords() const 108 { 109 return numRecs; 110 } 111 112 /** @brief Get the FRU table 113 * 114 * @param[out] - Populate response with the FRU table 115 */ 116 void getFRUTable(Response& response); 117 118 /** @brief Get the Fru Table MetaData 119 * 120 */ 121 void getFRURecordTableMetadata(); 122 123 /** @brief Get FRU Record Table By Option 124 * @param[out] response - Populate response with the FRU table got by 125 * options 126 * @param[in] fruTableHandle - The fru table handle 127 * @param[in] recordSetIdentifer - The record set identifier 128 * @param[in] recordType - The record type 129 * @param[in] fieldType - The field type 130 */ 131 int getFRURecordByOption(Response& response, uint16_t fruTableHandle, 132 uint16_t recordSetIdentifer, uint8_t recordType, 133 uint8_t fieldType); 134 135 /** @brief FRU table is built by processing the D-Bus inventory namespace 136 * based on the config files for FRU. The table is populated based 137 * on the isBuilt flag. 138 */ 139 void buildFRUTable(); 140 141 /** @brief Get std::map associated with the entity 142 * key: object path 143 * value: pldm_entity 144 * 145 * @return std::map<ObjectPath, pldm_entity> 146 */ 147 inline const pldm::responder::dbus::AssociatedEntityMap& getAssociateEntityMap() const148 getAssociateEntityMap() const 149 { 150 return associatedEntityMap; 151 } 152 153 /* @brief Method to set the oem platform handler in FRU handler class 154 * 155 * @param[in] handler - oem platform handler 156 */ setOemPlatformHandler(pldm::responder::oem_platform::Handler * handler)157 inline void setOemPlatformHandler( 158 pldm::responder::oem_platform::Handler* handler) 159 { 160 oemPlatformHandler = handler; 161 } 162 163 /** @brief Get pldm entity by the object path 164 * 165 * @param[in] intfMaps - D-Bus interfaces and the associated property 166 * values for the FRU 167 * 168 * @return pldm_entity 169 */ 170 std::optional<pldm_entity> getEntityByObjectPath( 171 const dbus::InterfaceMap& intfMaps); 172 173 /** @brief Update pldm entity to association tree 174 * 175 * @param[in] objects - std::map The object value tree 176 * @param[in] path - Object path 177 * 178 * Ex: Input path = 179 * "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0" 180 * 181 * Get the parent class in turn and store it in a temporary vector 182 * 183 * Output tmpObjPaths = { 184 * "/xyz/openbmc_project/inventory/system", 185 * "/xyz/openbmc_project/inventory/system/chassis/", 186 * "/xyz/openbmc_project/inventory/system/chassis/motherboard", 187 * "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"} 188 * 189 */ 190 void updateAssociationTree(const dbus::ObjectValueTree& objects, 191 const std::string& path); 192 193 /* @brief Method to populate the firmware version ID 194 * 195 * @return firmware version ID 196 */ 197 std::string populatefwVersion(); 198 199 /* @brief Method to resize the table 200 * 201 * @return resized table 202 */ 203 std::vector<uint8_t> tableResize(); 204 205 /* @brief set FRU Record Table 206 * 207 * @param[in] fruData - the data of the fru 208 * 209 * @return PLDM completion code 210 */ 211 int setFRUTable(const std::vector<uint8_t>& fruData); 212 213 /* @brief Method to set the oem platform handler in fru handler class 214 * 215 * @param[in] handler - oem fru handler 216 */ setOemFruHandler(pldm::responder::oem_fru::Handler * handler)217 inline void setOemFruHandler(pldm::responder::oem_fru::Handler* handler) 218 { 219 oemFruHandler = handler; 220 } 221 222 private: nextRSI()223 uint16_t nextRSI() 224 { 225 return ++rsi; 226 } 227 nextRecordHandle()228 uint32_t nextRecordHandle() 229 { 230 return ++rh; 231 } 232 233 uint32_t rh = 0; 234 uint16_t rsi = 0; 235 uint16_t numRecs = 0; 236 uint8_t padBytes = 0; 237 std::vector<uint8_t> table; 238 uint32_t checksum = 0; 239 bool isBuilt = false; 240 241 fru_parser::FruParser parser; 242 pldm_pdr* pdrRepo; 243 pldm_entity_association_tree* entityTree; 244 pldm_entity_association_tree* bmcEntityTree; 245 pldm::responder::oem_fru::Handler* oemFruHandler = nullptr; 246 dbus::ObjectValueTree objects; 247 248 /** @OEM platform handler */ 249 pldm::responder::oem_platform::Handler* oemPlatformHandler; 250 251 std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{}; 252 253 /** @brief populateRecord builds the FRU records for an instance of FRU and 254 * updates the FRU table with the FRU records. 255 * 256 * @param[in] interfaces - D-Bus interfaces and the associated property 257 * values for the FRU 258 * @param[in] recordInfos - FRU record info to build the FRU records 259 * @param[in/out] entity - PLDM entity corresponding to FRU instance 260 */ 261 void populateRecords(const dbus::InterfaceMap& interfaces, 262 const fru_parser::FruRecordInfos& recordInfos, 263 const pldm_entity& entity); 264 265 /** @brief Add hotplug record that was modified or added to the PDR entry 266 * HotPlug is a feature where a FRU can be removed or added when 267 * the system is running, without needing it to power off. 268 * 269 * @param[in] pdrEntry - PDR record structure in PDR repository 270 * 271 * @return record handle of added or modified hotplug record 272 */ 273 uint32_t addHotPlugRecord(pldm::responder::pdr_utils::PdrEntry pdrEntry); 274 275 /** @brief Deletes a FRU record from record set table. 276 * @param[in] rsi - the FRU Record Set Identifier 277 * 278 * @return 279 */ 280 void deleteFRURecord(uint16_t rsi); 281 282 /** @brief Associate sensor/effecter to FRU entity 283 */ 284 dbus::AssociatedEntityMap associatedEntityMap; 285 }; 286 287 namespace fru 288 { 289 290 class Handler : public CmdHandler 291 { 292 public: Handler(const std::string & configPath,const std::filesystem::path & fruMasterJsonPath,pldm_pdr * pdrRepo,pldm_entity_association_tree * entityTree,pldm_entity_association_tree * bmcEntityTree)293 Handler(const std::string& configPath, 294 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 295 pldm_entity_association_tree* entityTree, 296 pldm_entity_association_tree* bmcEntityTree) : 297 impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree) 298 { 299 handlers.emplace( 300 PLDM_GET_FRU_RECORD_TABLE_METADATA, 301 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 302 return this->getFRURecordTableMetadata(request, payloadLength); 303 }); 304 handlers.emplace( 305 PLDM_GET_FRU_RECORD_TABLE, 306 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 307 return this->getFRURecordTable(request, payloadLength); 308 }); 309 handlers.emplace( 310 PLDM_GET_FRU_RECORD_BY_OPTION, 311 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 312 return this->getFRURecordByOption(request, payloadLength); 313 }); 314 handlers.emplace( 315 PLDM_SET_FRU_RECORD_TABLE, 316 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 317 return this->setFRURecordTable(request, payloadLength); 318 }); 319 } 320 321 /** @brief Handler for Get FRURecordTableMetadata 322 * 323 * @param[in] request - Request message payload 324 * @param[in] payloadLength - Request payload length 325 * 326 * @return PLDM response message 327 */ 328 Response getFRURecordTableMetadata(const pldm_msg* request, 329 size_t payloadLength); 330 331 /** @brief Handler for GetFRURecordTable 332 * 333 * @param[in] request - Request message payload 334 * @param[in] payloadLength - Request payload length 335 * 336 * @return PLDM response message 337 */ 338 Response getFRURecordTable(const pldm_msg* request, size_t payloadLength); 339 340 /** @brief Build FRU table is bnot already built 341 * 342 */ buildFRUTable()343 void buildFRUTable() 344 { 345 impl.buildFRUTable(); 346 } 347 348 /** @brief Get std::map associated with the entity 349 * key: object path 350 * value: pldm_entity 351 * 352 * @return std::map<ObjectPath, pldm_entity> 353 */ getAssociateEntityMap() const354 const pldm::responder::dbus::AssociatedEntityMap& getAssociateEntityMap() 355 const 356 { 357 return impl.getAssociateEntityMap(); 358 } 359 360 /* @brief Method to set the oem platform handler in host pdr handler class 361 * 362 * @param[in] handler - oem platform handler 363 */ setOemPlatformHandler(pldm::responder::oem_platform::Handler * handler)364 void setOemPlatformHandler(pldm::responder::oem_platform::Handler* handler) 365 { 366 return impl.setOemPlatformHandler(handler); 367 } 368 369 /** @brief Handler for GetFRURecordByOption 370 * 371 * @param[in] request - Request message payload 372 * @param[in] payloadLength - Request payload length 373 * 374 * @return PLDM response message 375 */ 376 Response getFRURecordByOption(const pldm_msg* request, 377 size_t payloadLength); 378 379 /** @brief Handler for SetFRURecordTable 380 * 381 * @param[in] request - Request message 382 * @param[in] payloadLength - Request payload length 383 * 384 * @return PLDM response message 385 */ 386 Response setFRURecordTable(const pldm_msg* request, size_t payloadLength); 387 388 /* @brief Method to set the oem platform handler in fru handler class 389 * 390 * @param[in] handler - oem fru handler 391 */ setOemFruHandler(pldm::responder::oem_fru::Handler * handler)392 void setOemFruHandler(pldm::responder::oem_fru::Handler* handler) 393 { 394 impl.setOemFruHandler(handler); 395 } 396 397 using Table = std::vector<uint8_t>; 398 399 private: 400 FruImpl impl; 401 }; 402 403 } // namespace fru 404 405 } // namespace responder 406 407 } // namespace pldm 408