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