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 excludes 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() - padBytes; 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 FRU Record Table By Option 115 * @param[out] response - Populate response with the FRU table got by 116 * options 117 * @param[in] fruTableHandle - The fru table handle 118 * @param[in] recordSetIdentifer - The record set identifier 119 * @param[in] recordType - The record type 120 * @param[in] fieldType - The field type 121 */ 122 int getFRURecordByOption(Response& response, uint16_t fruTableHandle, 123 uint16_t recordSetIdentifer, uint8_t recordType, 124 uint8_t fieldType); 125 126 /** @brief FRU table is built by processing the D-Bus inventory namespace 127 * based on the config files for FRU. The table is populated based 128 * on the isBuilt flag. 129 */ 130 void buildFRUTable(); 131 132 /** @brief Get std::map associated with the entity 133 * key: object path 134 * value: pldm_entity 135 * 136 * @return std::map<ObjectPath, pldm_entity> 137 */ 138 inline const pldm::responder::dbus::AssociatedEntityMap& 139 getAssociateEntityMap() const 140 { 141 return associatedEntityMap; 142 } 143 144 /** @brief Get pldm entity by the object path 145 * 146 * @param[in] intfMaps - D-Bus interfaces and the associated property 147 * values for the FRU 148 * 149 * @return pldm_entity 150 */ 151 std::optional<pldm_entity> 152 getEntityByObjectPath(const dbus::InterfaceMap& intfMaps); 153 154 /** @brief Update pldm entity to association tree 155 * 156 * @param[in] objects - std::map The object value tree 157 * @param[in] path - Object path 158 * 159 * Ex: Input path = 160 * "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0" 161 * 162 * Get the parent class in turn and store it in a temporary vector 163 * 164 * Output tmpObjPaths = { 165 * "/xyz/openbmc_project/inventory/system", 166 * "/xyz/openbmc_project/inventory/system/chassis/", 167 * "/xyz/openbmc_project/inventory/system/chassis/motherboard", 168 * "/xyz/openbmc_project/inventory/system/chassis/motherboard/powersupply0"} 169 * 170 */ 171 void updateAssociationTree(const dbus::ObjectValueTree& objects, 172 const std::string& path); 173 174 /* @brief Method to populate the firmware version ID 175 * 176 * @return firmware version ID 177 */ 178 std::string populatefwVersion(); 179 180 private: 181 uint16_t nextRSI() 182 { 183 return ++rsi; 184 } 185 186 uint32_t nextRecordHandle() 187 { 188 return ++rh; 189 } 190 191 uint32_t rh = 0; 192 uint16_t rsi = 0; 193 uint16_t numRecs = 0; 194 uint8_t padBytes = 0; 195 std::vector<uint8_t> table; 196 uint32_t checksum = 0; 197 bool isBuilt = false; 198 199 fru_parser::FruParser parser; 200 pldm_pdr* pdrRepo; 201 pldm_entity_association_tree* entityTree; 202 pldm_entity_association_tree* bmcEntityTree; 203 204 std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{}; 205 206 /** @brief populateRecord builds the FRU records for an instance of FRU and 207 * updates the FRU table with the FRU records. 208 * 209 * @param[in] interfaces - D-Bus interfaces and the associated property 210 * values for the FRU 211 * @param[in] recordInfos - FRU record info to build the FRU records 212 * @param[in/out] entity - PLDM entity corresponding to FRU instance 213 */ 214 void populateRecords(const dbus::InterfaceMap& interfaces, 215 const fru_parser::FruRecordInfos& recordInfos, 216 const pldm_entity& entity); 217 218 /** @brief Associate sensor/effecter to FRU entity 219 */ 220 dbus::AssociatedEntityMap associatedEntityMap; 221 }; 222 223 namespace fru 224 { 225 226 class Handler : public CmdHandler 227 { 228 public: 229 Handler(const std::string& configPath, 230 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 231 pldm_entity_association_tree* entityTree, 232 pldm_entity_association_tree* bmcEntityTree) : 233 impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree) 234 { 235 handlers.emplace( 236 PLDM_GET_FRU_RECORD_TABLE_METADATA, 237 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 238 return this->getFRURecordTableMetadata(request, payloadLength); 239 }); 240 handlers.emplace( 241 PLDM_GET_FRU_RECORD_TABLE, 242 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 243 return this->getFRURecordTable(request, payloadLength); 244 }); 245 handlers.emplace( 246 PLDM_GET_FRU_RECORD_BY_OPTION, 247 [this](pldm_tid_t, const pldm_msg* request, size_t payloadLength) { 248 return this->getFRURecordByOption(request, payloadLength); 249 }); 250 } 251 252 /** @brief Handler for Get FRURecordTableMetadata 253 * 254 * @param[in] request - Request message payload 255 * @param[in] payloadLength - Request payload length 256 * 257 * @return PLDM response message 258 */ 259 Response getFRURecordTableMetadata(const pldm_msg* request, 260 size_t payloadLength); 261 262 /** @brief Handler for GetFRURecordTable 263 * 264 * @param[in] request - Request message payload 265 * @param[in] payloadLength - Request payload length 266 * 267 * @return PLDM response message 268 */ 269 Response getFRURecordTable(const pldm_msg* request, size_t payloadLength); 270 271 /** @brief Build FRU table is bnot already built 272 * 273 */ 274 void buildFRUTable() 275 { 276 impl.buildFRUTable(); 277 } 278 279 /** @brief Get std::map associated with the entity 280 * key: object path 281 * value: pldm_entity 282 * 283 * @return std::map<ObjectPath, pldm_entity> 284 */ 285 const pldm::responder::dbus::AssociatedEntityMap& 286 getAssociateEntityMap() const 287 { 288 return impl.getAssociateEntityMap(); 289 } 290 291 /** @brief Handler for GetFRURecordByOption 292 * 293 * @param[in] request - Request message payload 294 * @param[in] payloadLength - Request payload length 295 * 296 * @return PLDM response message 297 */ 298 Response getFRURecordByOption(const pldm_msg* request, 299 size_t payloadLength); 300 301 private: 302 FruImpl impl; 303 }; 304 305 } // namespace fru 306 307 } // namespace responder 308 309 } // namespace pldm 310