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