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