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 Method to populate the firmware version ID 145 * 146 * @return firmware version ID 147 */ 148 std::string populatefwVersion(); 149 150 private: 151 uint16_t nextRSI() 152 { 153 return ++rsi; 154 } 155 156 uint32_t nextRecordHandle() 157 { 158 return ++rh; 159 } 160 161 uint32_t rh = 0; 162 uint16_t rsi = 0; 163 uint16_t numRecs = 0; 164 uint8_t padBytes = 0; 165 std::vector<uint8_t> table; 166 uint32_t checksum = 0; 167 bool isBuilt = false; 168 169 fru_parser::FruParser parser; 170 pldm_pdr* pdrRepo; 171 pldm_entity_association_tree* entityTree; 172 pldm_entity_association_tree* bmcEntityTree; 173 174 std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{}; 175 176 /** @brief populateRecord builds the FRU records for an instance of FRU and 177 * updates the FRU table with the FRU records. 178 * 179 * @param[in] interfaces - D-Bus interfaces and the associated property 180 * values for the FRU 181 * @param[in] recordInfos - FRU record info to build the FRU records 182 * @param[in/out] entity - PLDM entity corresponding to FRU instance 183 */ 184 void populateRecords(const dbus::InterfaceMap& interfaces, 185 const fru_parser::FruRecordInfos& recordInfos, 186 const pldm_entity& entity); 187 188 /** @brief Associate sensor/effecter to FRU entity 189 */ 190 dbus::AssociatedEntityMap associatedEntityMap; 191 }; 192 193 namespace fru 194 { 195 196 class Handler : public CmdHandler 197 { 198 public: 199 Handler(const std::string& configPath, 200 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 201 pldm_entity_association_tree* entityTree, 202 pldm_entity_association_tree* bmcEntityTree) : 203 impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree) 204 { 205 handlers.emplace(PLDM_GET_FRU_RECORD_TABLE_METADATA, 206 [this](const pldm_msg* request, size_t payloadLength) { 207 return this->getFRURecordTableMetadata(request, payloadLength); 208 }); 209 210 handlers.emplace(PLDM_GET_FRU_RECORD_TABLE, 211 [this](const pldm_msg* request, size_t payloadLength) { 212 return this->getFRURecordTable(request, payloadLength); 213 }); 214 handlers.emplace(PLDM_GET_FRU_RECORD_BY_OPTION, 215 [this](const pldm_msg* request, size_t payloadLength) { 216 return this->getFRURecordByOption(request, payloadLength); 217 }); 218 } 219 220 /** @brief Handler for Get FRURecordTableMetadata 221 * 222 * @param[in] request - Request message payload 223 * @param[in] payloadLength - Request payload length 224 * 225 * @return PLDM response message 226 */ 227 Response getFRURecordTableMetadata(const pldm_msg* request, 228 size_t payloadLength); 229 230 /** @brief Handler for GetFRURecordTable 231 * 232 * @param[in] request - Request message payload 233 * @param[in] payloadLength - Request payload length 234 * 235 * @return PLDM response message 236 */ 237 Response getFRURecordTable(const pldm_msg* request, size_t payloadLength); 238 239 /** @brief Build FRU table is bnot already built 240 * 241 */ 242 void buildFRUTable() 243 { 244 impl.buildFRUTable(); 245 } 246 247 /** @brief Get std::map associated with the entity 248 * key: object path 249 * value: pldm_entity 250 * 251 * @return std::map<ObjectPath, pldm_entity> 252 */ 253 const pldm::responder::dbus::AssociatedEntityMap& 254 getAssociateEntityMap() const 255 { 256 return impl.getAssociateEntityMap(); 257 } 258 259 /** @brief Handler for GetFRURecordByOption 260 * 261 * @param[in] request - Request message payload 262 * @param[in] payloadLength - Request payload length 263 * 264 * @return PLDM response message 265 */ 266 Response getFRURecordByOption(const pldm_msg* request, 267 size_t payloadLength); 268 269 private: 270 FruImpl impl; 271 }; 272 273 } // namespace fru 274 275 } // namespace responder 276 277 } // namespace pldm 278