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