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(PLDM_GET_FRU_RECORD_TABLE_METADATA, 236 [this](const pldm_msg* request, size_t payloadLength) { 237 return this->getFRURecordTableMetadata(request, payloadLength); 238 }); 239 240 handlers.emplace(PLDM_GET_FRU_RECORD_TABLE, 241 [this](const pldm_msg* request, size_t payloadLength) { 242 return this->getFRURecordTable(request, payloadLength); 243 }); 244 handlers.emplace(PLDM_GET_FRU_RECORD_BY_OPTION, 245 [this](const pldm_msg* request, size_t payloadLength) { 246 return this->getFRURecordByOption(request, payloadLength); 247 }); 248 } 249 250 /** @brief Handler for Get FRURecordTableMetadata 251 * 252 * @param[in] request - Request message payload 253 * @param[in] payloadLength - Request payload length 254 * 255 * @return PLDM response message 256 */ 257 Response getFRURecordTableMetadata(const pldm_msg* request, 258 size_t payloadLength); 259 260 /** @brief Handler for GetFRURecordTable 261 * 262 * @param[in] request - Request message payload 263 * @param[in] payloadLength - Request payload length 264 * 265 * @return PLDM response message 266 */ 267 Response getFRURecordTable(const pldm_msg* request, size_t payloadLength); 268 269 /** @brief Build FRU table is bnot already built 270 * 271 */ 272 void buildFRUTable() 273 { 274 impl.buildFRUTable(); 275 } 276 277 /** @brief Get std::map associated with the entity 278 * key: object path 279 * value: pldm_entity 280 * 281 * @return std::map<ObjectPath, pldm_entity> 282 */ 283 const pldm::responder::dbus::AssociatedEntityMap& 284 getAssociateEntityMap() const 285 { 286 return impl.getAssociateEntityMap(); 287 } 288 289 /** @brief Handler for GetFRURecordByOption 290 * 291 * @param[in] request - Request message payload 292 * @param[in] payloadLength - Request payload length 293 * 294 * @return PLDM response message 295 */ 296 Response getFRURecordByOption(const pldm_msg* request, 297 size_t payloadLength); 298 299 private: 300 FruImpl impl; 301 }; 302 303 } // namespace fru 304 305 } // namespace responder 306 307 } // namespace pldm 308