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 Get pldm entity by the object path 154 * 155 * @param[in] intfMaps - D-Bus interfaces and the associated property 156 * values for the FRU 157 * 158 * @return pldm_entity 159 */ 160 std::optional<pldm_entity> getEntityByObjectPath( 161 const dbus::InterfaceMap& intfMaps); 162 163 /** @brief Update pldm entity to association tree 164 * 165 * @param[in] objects - std::map The object value tree 166 * @param[in] path - Object path 167 * 168 * Ex: Input path = 169 * "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0" 170 * 171 * Get the parent class in turn and store it in a temporary vector 172 * 173 * Output tmpObjPaths = { 174 * "/xyz/openbmc_project/inventory/system", 175 * "/xyz/openbmc_project/inventory/system/chassis/", 176 * "/xyz/openbmc_project/inventory/system/chassis/motherboard", 177 * "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"} 178 * 179 */ 180 void updateAssociationTree(const dbus::ObjectValueTree& objects, 181 const std::string& path); 182 183 /* @brief Method to populate the firmware version ID 184 * 185 * @return firmware version ID 186 */ 187 std::string populatefwVersion(); 188 189 /* @brief Method to resize the table 190 * 191 * @return resized table 192 */ 193 std::vector<uint8_t> tableResize(); 194 195 /* @brief set FRU Record Table 196 * 197 * @param[in] fruData - the data of the fru 198 * 199 * @return PLDM completion code 200 */ 201 int setFRUTable(const std::vector<uint8_t>& fruData); 202 203 /* @brief Method to set the oem platform handler in fru handler class 204 * 205 * @param[in] handler - oem fru handler 206 */ setOemFruHandler(pldm::responder::oem_fru::Handler * handler)207 inline void setOemFruHandler(pldm::responder::oem_fru::Handler* handler) 208 { 209 oemFruHandler = handler; 210 } 211 212 private: nextRSI()213 uint16_t nextRSI() 214 { 215 return ++rsi; 216 } 217 nextRecordHandle()218 uint32_t nextRecordHandle() 219 { 220 return ++rh; 221 } 222 223 uint32_t rh = 0; 224 uint16_t rsi = 0; 225 uint16_t numRecs = 0; 226 uint8_t padBytes = 0; 227 std::vector<uint8_t> table; 228 uint32_t checksum = 0; 229 bool isBuilt = false; 230 231 fru_parser::FruParser parser; 232 pldm_pdr* pdrRepo; 233 pldm_entity_association_tree* entityTree; 234 pldm_entity_association_tree* bmcEntityTree; 235 pldm::responder::oem_fru::Handler* oemFruHandler = nullptr; 236 dbus::ObjectValueTree objects; 237 238 std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{}; 239 240 /** @brief populateRecord builds the FRU records for an instance of FRU and 241 * updates the FRU table with the FRU records. 242 * 243 * @param[in] interfaces - D-Bus interfaces and the associated property 244 * values for the FRU 245 * @param[in] recordInfos - FRU record info to build the FRU records 246 * @param[in/out] entity - PLDM entity corresponding to FRU instance 247 */ 248 void populateRecords(const dbus::InterfaceMap& interfaces, 249 const fru_parser::FruRecordInfos& recordInfos, 250 const pldm_entity& entity); 251 252 /** @brief Associate sensor/effecter to FRU entity 253 */ 254 dbus::AssociatedEntityMap associatedEntityMap; 255 }; 256 257 namespace fru 258 { 259 260 class Handler : public CmdHandler 261 { 262 public: Handler(const std::string & configPath,const std::filesystem::path & fruMasterJsonPath,pldm_pdr * pdrRepo,pldm_entity_association_tree * entityTree,pldm_entity_association_tree * bmcEntityTree)263 Handler(const std::string& configPath, 264 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 265 pldm_entity_association_tree* entityTree, 266 pldm_entity_association_tree* bmcEntityTree) : 267 impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree) 268 { 269 handlers.emplace( 270 PLDM_GET_FRU_RECORD_TABLE_METADATA, 271 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 272 return this->getFRURecordTableMetadata(request, payloadLength); 273 }); 274 handlers.emplace( 275 PLDM_GET_FRU_RECORD_TABLE, 276 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 277 return this->getFRURecordTable(request, payloadLength); 278 }); 279 handlers.emplace( 280 PLDM_GET_FRU_RECORD_BY_OPTION, 281 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 282 return this->getFRURecordByOption(request, payloadLength); 283 }); 284 handlers.emplace( 285 PLDM_SET_FRU_RECORD_TABLE, 286 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 287 return this->setFRURecordTable(request, payloadLength); 288 }); 289 } 290 291 /** @brief Handler for Get FRURecordTableMetadata 292 * 293 * @param[in] request - Request message payload 294 * @param[in] payloadLength - Request payload length 295 * 296 * @return PLDM response message 297 */ 298 Response getFRURecordTableMetadata(const pldm_msg* request, 299 size_t payloadLength); 300 301 /** @brief Handler for GetFRURecordTable 302 * 303 * @param[in] request - Request message payload 304 * @param[in] payloadLength - Request payload length 305 * 306 * @return PLDM response message 307 */ 308 Response getFRURecordTable(const pldm_msg* request, size_t payloadLength); 309 310 /** @brief Build FRU table is bnot already built 311 * 312 */ buildFRUTable()313 void buildFRUTable() 314 { 315 impl.buildFRUTable(); 316 } 317 318 /** @brief Get std::map associated with the entity 319 * key: object path 320 * value: pldm_entity 321 * 322 * @return std::map<ObjectPath, pldm_entity> 323 */ getAssociateEntityMap() const324 const pldm::responder::dbus::AssociatedEntityMap& getAssociateEntityMap() 325 const 326 { 327 return impl.getAssociateEntityMap(); 328 } 329 330 /** @brief Handler for GetFRURecordByOption 331 * 332 * @param[in] request - Request message payload 333 * @param[in] payloadLength - Request payload length 334 * 335 * @return PLDM response message 336 */ 337 Response getFRURecordByOption(const pldm_msg* request, 338 size_t payloadLength); 339 340 /** @brief Handler for SetFRURecordTable 341 * 342 * @param[in] request - Request message 343 * @param[in] payloadLength - Request payload length 344 * 345 * @return PLDM response message 346 */ 347 Response setFRURecordTable(const pldm_msg* request, size_t payloadLength); 348 349 /* @brief Method to set the oem platform handler in fru handler class 350 * 351 * @param[in] handler - oem fru handler 352 */ setOemFruHandler(pldm::responder::oem_fru::Handler * handler)353 void setOemFruHandler(pldm::responder::oem_fru::Handler* handler) 354 { 355 impl.setOemFruHandler(handler); 356 } 357 358 using Table = std::vector<uint8_t>; 359 360 private: 361 FruImpl impl; 362 }; 363 364 } // namespace fru 365 366 } // namespace responder 367 368 } // namespace pldm 369