1 #pragma once 2 3 #include "config.h" 4 5 #include "fru_parser.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 = 28 std::variant<bool, uint8_t, int16_t, uint16_t, int32_t, uint32_t, int64_t, 29 uint64_t, double, std::string, std::vector<uint8_t>>; 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 */ 65 FruImpl(const std::string& configPath, 66 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 67 pldm_entity_association_tree* entityTree, 68 pldm_entity_association_tree* bmcEntityTree) : 69 parser(configPath, fruMasterJsonPath), 70 pdrRepo(pdrRepo), entityTree(entityTree), bmcEntityTree(bmcEntityTree) 71 {} 72 73 /** @brief Total length of the FRU table in bytes, this excludes the pad 74 * bytes and the checksum. 75 * 76 * @return size of the FRU table 77 */ 78 uint32_t size() const 79 { 80 return table.size() - padBytes; 81 } 82 83 /** @brief The checksum of the contents of the FRU table 84 * 85 * @return checksum 86 */ 87 uint32_t checkSum() const 88 { 89 return checksum; 90 } 91 92 /** @brief Number of record set identifiers in the FRU tables 93 * 94 * @return number of record set identifiers 95 */ 96 uint16_t numRSI() const 97 { 98 return rsi; 99 } 100 101 /** @brief The number of FRU records in the table 102 * 103 * @return number of FRU records 104 */ 105 uint16_t numRecords() const 106 { 107 return numRecs; 108 } 109 110 /** @brief Get the FRU table 111 * 112 * @param[out] - Populate response with the FRU table 113 */ 114 void getFRUTable(Response& response); 115 116 /** @brief Get FRU Record Table By Option 117 * @param[out] response - Populate response with the FRU table got by 118 * options 119 * @param[in] fruTableHandle - The fru table handle 120 * @param[in] recordSetIdentifer - The record set identifier 121 * @param[in] recordType - The record type 122 * @param[in] fieldType - The field type 123 */ 124 int getFRURecordByOption(Response& response, uint16_t fruTableHandle, 125 uint16_t recordSetIdentifer, uint8_t recordType, 126 uint8_t fieldType); 127 128 /** @brief FRU table is built by processing the D-Bus inventory namespace 129 * based on the config files for FRU. The table is populated based 130 * on the isBuilt flag. 131 */ 132 void buildFRUTable(); 133 134 /** @brief Get std::map associated with the entity 135 * key: object path 136 * value: pldm_entity 137 * 138 * @return std::map<ObjectPath, pldm_entity> 139 */ 140 inline const pldm::responder::dbus::AssociatedEntityMap& 141 getAssociateEntityMap() const 142 { 143 return associatedEntityMap; 144 } 145 146 /* @brief Method to populate the firmware version ID 147 * 148 * @return firmware version ID 149 */ 150 std::string populatefwVersion(); 151 152 private: 153 uint16_t nextRSI() 154 { 155 return ++rsi; 156 } 157 158 uint32_t nextRecordHandle() 159 { 160 return ++rh; 161 } 162 163 uint32_t rh = 0; 164 uint16_t rsi = 0; 165 uint16_t numRecs = 0; 166 uint8_t padBytes = 0; 167 std::vector<uint8_t> table; 168 uint32_t checksum = 0; 169 bool isBuilt = false; 170 171 fru_parser::FruParser parser; 172 pldm_pdr* pdrRepo; 173 pldm_entity_association_tree* entityTree; 174 pldm_entity_association_tree* bmcEntityTree; 175 176 std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{}; 177 178 /** @brief populateRecord builds the FRU records for an instance of FRU and 179 * updates the FRU table with the FRU records. 180 * 181 * @param[in] interfaces - D-Bus interfaces and the associated property 182 * values for the FRU 183 * @param[in] recordInfos - FRU record info to build the FRU records 184 * @param[in/out] entity - PLDM entity corresponding to FRU instance 185 */ 186 void populateRecords(const dbus::InterfaceMap& interfaces, 187 const fru_parser::FruRecordInfos& recordInfos, 188 const pldm_entity& entity); 189 190 /** @brief Associate sensor/effecter to FRU entity 191 */ 192 dbus::AssociatedEntityMap associatedEntityMap; 193 }; 194 195 namespace fru 196 { 197 198 class Handler : public CmdHandler 199 { 200 public: 201 Handler(const std::string& configPath, 202 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 203 pldm_entity_association_tree* entityTree, 204 pldm_entity_association_tree* bmcEntityTree) : 205 impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree) 206 { 207 handlers.emplace(PLDM_GET_FRU_RECORD_TABLE_METADATA, 208 [this](const pldm_msg* request, size_t payloadLength) { 209 return this->getFRURecordTableMetadata( 210 request, payloadLength); 211 }); 212 213 handlers.emplace(PLDM_GET_FRU_RECORD_TABLE, 214 [this](const pldm_msg* request, size_t payloadLength) { 215 return this->getFRURecordTable(request, 216 payloadLength); 217 }); 218 handlers.emplace(PLDM_GET_FRU_RECORD_BY_OPTION, 219 [this](const pldm_msg* request, size_t payloadLength) { 220 return this->getFRURecordByOption(request, 221 payloadLength); 222 }); 223 } 224 225 /** @brief Handler for Get FRURecordTableMetadata 226 * 227 * @param[in] request - Request message payload 228 * @param[in] payloadLength - Request payload length 229 * 230 * @return PLDM response message 231 */ 232 Response getFRURecordTableMetadata(const pldm_msg* request, 233 size_t payloadLength); 234 235 /** @brief Handler for GetFRURecordTable 236 * 237 * @param[in] request - Request message payload 238 * @param[in] payloadLength - Request payload length 239 * 240 * @return PLDM response message 241 */ 242 Response getFRURecordTable(const pldm_msg* request, size_t payloadLength); 243 244 /** @brief Build FRU table is bnot already built 245 * 246 */ 247 void buildFRUTable() 248 { 249 impl.buildFRUTable(); 250 } 251 252 /** @brief Get std::map associated with the entity 253 * key: object path 254 * value: pldm_entity 255 * 256 * @return std::map<ObjectPath, pldm_entity> 257 */ 258 const pldm::responder::dbus::AssociatedEntityMap& 259 getAssociateEntityMap() const 260 { 261 return impl.getAssociateEntityMap(); 262 } 263 264 /** @brief Handler for GetFRURecordByOption 265 * 266 * @param[in] request - Request message payload 267 * @param[in] payloadLength - Request payload length 268 * 269 * @return PLDM response message 270 */ 271 Response getFRURecordByOption(const pldm_msg* request, 272 size_t payloadLength); 273 274 private: 275 FruImpl impl; 276 }; 277 278 } // namespace fru 279 280 } // namespace responder 281 282 } // namespace pldm 283