1 #pragma once 2 3 #include "config.h" 4 5 #include "libpldm/fru.h" 6 #include "libpldm/pdr.h" 7 8 #include "fru_parser.hpp" 9 #include "pldmd/handler.hpp" 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 uint16_t rsi = 0; 159 uint16_t numRecs = 0; 160 uint8_t padBytes = 0; 161 std::vector<uint8_t> table; 162 uint32_t checksum = 0; 163 bool isBuilt = false; 164 165 fru_parser::FruParser parser; 166 pldm_pdr* pdrRepo; 167 pldm_entity_association_tree* entityTree; 168 pldm_entity_association_tree* bmcEntityTree; 169 170 std::map<dbus::ObjectPath, pldm_entity_node*> objToEntityNode{}; 171 172 /** @brief populateRecord builds the FRU records for an instance of FRU and 173 * updates the FRU table with the FRU records. 174 * 175 * @param[in] interfaces - D-Bus interfaces and the associated property 176 * values for the FRU 177 * @param[in] recordInfos - FRU record info to build the FRU records 178 * @param[in/out] entity - PLDM entity corresponding to FRU instance 179 */ 180 void populateRecords(const dbus::InterfaceMap& interfaces, 181 const fru_parser::FruRecordInfos& recordInfos, 182 const pldm_entity& entity); 183 184 /** @brief Associate sensor/effecter to FRU entity 185 */ 186 dbus::AssociatedEntityMap associatedEntityMap; 187 }; 188 189 namespace fru 190 { 191 192 class Handler : public CmdHandler 193 { 194 195 public: 196 Handler(const std::string& configPath, 197 const std::filesystem::path& fruMasterJsonPath, pldm_pdr* pdrRepo, 198 pldm_entity_association_tree* entityTree, 199 pldm_entity_association_tree* bmcEntityTree) : 200 impl(configPath, fruMasterJsonPath, pdrRepo, entityTree, bmcEntityTree) 201 { 202 handlers.emplace(PLDM_GET_FRU_RECORD_TABLE_METADATA, 203 [this](const pldm_msg* request, size_t payloadLength) { 204 return this->getFRURecordTableMetadata( 205 request, payloadLength); 206 }); 207 208 handlers.emplace(PLDM_GET_FRU_RECORD_TABLE, 209 [this](const pldm_msg* request, size_t payloadLength) { 210 return this->getFRURecordTable(request, 211 payloadLength); 212 }); 213 handlers.emplace(PLDM_GET_FRU_RECORD_BY_OPTION, 214 [this](const pldm_msg* request, size_t payloadLength) { 215 return this->getFRURecordByOption(request, 216 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