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