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 */ 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 dbus::ObjectValueTree objects; 229 230 std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{}; 231 232 /** @brief populateRecord builds the FRU records for an instance of FRU and 233 * updates the FRU table with the FRU records. 234 * 235 * @param[in] interfaces - D-Bus interfaces and the associated property 236 * values for the FRU 237 * @param[in] recordInfos - FRU record info to build the FRU records 238 * @param[in/out] entity - PLDM entity corresponding to FRU instance 239 */ 240 void populateRecords(const dbus::InterfaceMap& interfaces, 241 const fru_parser::FruRecordInfos& recordInfos, 242 const pldm_entity& entity); 243 244 /** @brief Associate sensor/effecter to FRU entity 245 */ 246 dbus::AssociatedEntityMap associatedEntityMap; 247 }; 248 249 namespace fru 250 { 251 252 class Handler : public CmdHandler 253 { 254 public: 255 Handler(const std::string& configPath, 256 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 257 pldm_entity_association_tree* entityTree, 258 pldm_entity_association_tree* bmcEntityTree, 259 pldm::responder::oem_fru::Handler* oemFruHandler) : 260 impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree, 261 oemFruHandler) 262 { 263 handlers.emplace( 264 PLDM_GET_FRU_RECORD_TABLE_METADATA, 265 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 266 return this->getFRURecordTableMetadata(request, payloadLength); 267 }); 268 handlers.emplace( 269 PLDM_GET_FRU_RECORD_TABLE, 270 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 271 return this->getFRURecordTable(request, payloadLength); 272 }); 273 handlers.emplace( 274 PLDM_GET_FRU_RECORD_BY_OPTION, 275 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 276 return this->getFRURecordByOption(request, payloadLength); 277 }); 278 handlers.emplace( 279 PLDM_SET_FRU_RECORD_TABLE, 280 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 281 return this->setFRURecordTable(request, payloadLength); 282 }); 283 } 284 285 /** @brief Handler for Get FRURecordTableMetadata 286 * 287 * @param[in] request - Request message payload 288 * @param[in] payloadLength - Request payload length 289 * 290 * @return PLDM response message 291 */ 292 Response getFRURecordTableMetadata(const pldm_msg* request, 293 size_t payloadLength); 294 295 /** @brief Handler for GetFRURecordTable 296 * 297 * @param[in] request - Request message payload 298 * @param[in] payloadLength - Request payload length 299 * 300 * @return PLDM response message 301 */ 302 Response getFRURecordTable(const pldm_msg* request, size_t payloadLength); 303 304 /** @brief Build FRU table is bnot already built 305 * 306 */ 307 void buildFRUTable() 308 { 309 impl.buildFRUTable(); 310 } 311 312 /** @brief Get std::map associated with the entity 313 * key: object path 314 * value: pldm_entity 315 * 316 * @return std::map<ObjectPath, pldm_entity> 317 */ 318 const pldm::responder::dbus::AssociatedEntityMap& 319 getAssociateEntityMap() const 320 { 321 return impl.getAssociateEntityMap(); 322 } 323 324 /** @brief Handler for GetFRURecordByOption 325 * 326 * @param[in] request - Request message payload 327 * @param[in] payloadLength - Request payload length 328 * 329 * @return PLDM response message 330 */ 331 Response getFRURecordByOption(const pldm_msg* request, 332 size_t payloadLength); 333 334 /** @brief Handler for SetFRURecordTable 335 * 336 * @param[in] request - Request message 337 * @param[in] payloadLength - Request payload length 338 * 339 * @return PLDM response message 340 */ 341 Response setFRURecordTable(const pldm_msg* request, size_t payloadLength); 342 343 using Table = std::vector<uint8_t>; 344 345 private: 346 FruImpl impl; 347 }; 348 349 } // namespace fru 350 351 } // namespace responder 352 353 } // namespace pldm 354