1 #pragma once 2 3 #include "libpldm/base.h" 4 #include "libpldm/platform.h" 5 6 #include "common/types.hpp" 7 #include "common/utils.hpp" 8 #include "libpldmresponder/event_parser.hpp" 9 #include "libpldmresponder/pdr_utils.hpp" 10 #include "pldmd/dbus_impl_requester.hpp" 11 #include "requester/handler.hpp" 12 13 #include <sdeventplus/event.hpp> 14 #include <sdeventplus/source/event.hpp> 15 16 #include <deque> 17 #include <map> 18 #include <memory> 19 #include <vector> 20 21 using namespace pldm::dbus_api; 22 using namespace pldm::responder::events; 23 24 namespace pldm 25 { 26 27 using EntityType = uint16_t; 28 // vector which would hold the PDR record handle data returned by 29 // pldmPDRRepositoryChgEvent event data 30 using ChangeEntry = uint32_t; 31 using PDRRecordHandles = std::deque<ChangeEntry>; 32 33 /** @struct SensorEntry 34 * 35 * SensorEntry is a unique key which maps a sensorEventType request in the 36 * PlatformEventMessage command to a host sensor PDR. This struct is a key 37 * in a std::map, so implemented operator==and operator<. 38 */ 39 struct SensorEntry 40 { 41 pdr::TerminusID terminusID; 42 pdr::SensorID sensorID; 43 44 bool operator==(const SensorEntry& e) const 45 { 46 return ((terminusID == e.terminusID) && (sensorID == e.sensorID)); 47 } 48 49 bool operator<(const SensorEntry& e) const 50 { 51 return ((terminusID < e.terminusID) || 52 ((terminusID == e.terminusID) && (sensorID < e.sensorID))); 53 } 54 }; 55 56 /* @struct TerminusLocatorInfo 57 * Contains validity, eid, terminus_id and terminus handle 58 * of a terminus locator PDR. 59 */ 60 struct TlInfo 61 { 62 uint8_t valid; 63 uint8_t eid; 64 uint8_t tid; 65 uint16_t terminusHandle; 66 }; 67 68 using HostStateSensorMap = std::map<SensorEntry, pdr::SensorInfo>; 69 using PDRList = std::vector<std::vector<uint8_t>>; 70 71 /** @class HostPDRHandler 72 * @brief This class can fetch and process PDRs from host firmware 73 * @details Provides an API to fetch PDRs from the host firmware. Upon 74 * receiving the PDRs, they are stored into the BMC's primary PDR repo. 75 * Adjustments are made to entity association PDRs received from the host, 76 * because they need to be assimilated into the BMC's entity association 77 * tree. A PLDM event containing the record handles of the updated entity 78 * association PDRs is sent to the host. 79 */ 80 class HostPDRHandler 81 { 82 public: 83 HostPDRHandler() = delete; 84 HostPDRHandler(const HostPDRHandler&) = delete; 85 HostPDRHandler(HostPDRHandler&&) = delete; 86 HostPDRHandler& operator=(const HostPDRHandler&) = delete; 87 HostPDRHandler& operator=(HostPDRHandler&&) = delete; 88 ~HostPDRHandler() = default; 89 90 using TLPDRMap = std::map<pdr::TerminusHandle, pdr::TerminusID>; 91 92 /** @brief Constructor 93 * @param[in] mctp_fd - fd of MCTP communications socket 94 * @param[in] mctp_eid - MCTP EID of host firmware 95 * @param[in] event - reference of main event loop of pldmd 96 * @param[in] repo - pointer to BMC's primary PDR repo 97 * @param[in] eventsJsonDir - directory path which has the config JSONs 98 * @param[in] entityTree - Pointer to BMC and Host entity association tree 99 * @param[in] bmcEntityTree - pointer to BMC's entity association tree 100 * @param[in] requester - reference to Requester object 101 * @param[in] handler - PLDM request handler 102 */ 103 explicit HostPDRHandler( 104 int mctp_fd, uint8_t mctp_eid, sdeventplus::Event& event, 105 pldm_pdr* repo, const std::string& eventsJsonsDir, 106 pldm_entity_association_tree* entityTree, 107 pldm_entity_association_tree* bmcEntityTree, Requester& requester, 108 pldm::requester::Handler<pldm::requester::Request>* handler, 109 bool verbose = false); 110 111 /** @brief fetch PDRs from host firmware. See @class. 112 * @param[in] recordHandles - list of record handles pointing to host's 113 * PDRs that need to be fetched. 114 */ 115 116 void fetchPDR(PDRRecordHandles&& recordHandles); 117 118 /** @brief Send a PLDM event to host firmware containing a list of record 119 * handles of PDRs that the host firmware has to fetch. 120 * @param[in] pdrTypes - list of PDR types that need to be looked up in the 121 * BMC repo 122 * @param[in] eventDataFormat - format for PDRRepositoryChgEvent in DSP0248 123 */ 124 void sendPDRRepositoryChgEvent(std::vector<uint8_t>&& pdrTypes, 125 uint8_t eventDataFormat); 126 127 /** @brief Lookup host sensor info corresponding to requested SensorEntry 128 * 129 * @param[in] entry - TerminusID and SensorID 130 * 131 * @return SensorInfo corresponding to the input paramter SensorEntry 132 * throw std::out_of_range exception if not found 133 */ 134 const pdr::SensorInfo& lookupSensorInfo(const SensorEntry& entry) const 135 { 136 return sensorMap.at(entry); 137 } 138 139 /** @brief Handles state sensor event 140 * 141 * @param[in] entry - state sensor entry 142 * @param[in] state - event state 143 * 144 * @return PLDM completion code 145 */ 146 int handleStateSensorEvent(const StateSensorEntry& entry, 147 pdr::EventState state); 148 149 /** @brief Parse state sensor PDRs and populate the sensorMap lookup data 150 * structure 151 * 152 * @param[in] stateSensorPDRs - host state sensor PDRs 153 * @param[in] tlpdrInfo - terminus locator PDRs info 154 * 155 */ 156 void parseStateSensorPDRs(const PDRList& stateSensorPDRs, 157 const TLPDRMap& tlpdrInfo); 158 159 /** @brief this function sends a GetPDR request to Host firmware. 160 * And processes the PDRs based on type 161 * 162 * @param[in] - nextRecordHandle - the next record handle to ask for 163 */ 164 void getHostPDR(uint32_t nextRecordHandle = 0); 165 166 /** @brief set the Host state when pldmd starts 167 */ 168 void setHostState(); 169 170 /** @brief set HostSensorStates when pldmd starts or restarts 171 * and updates the D-Bus property 172 * @param[in] stateSensorPDRs - host state sensor PDRs 173 * @param[in] tlinfo - vector of struct TlInfo 174 */ 175 void setHostSensorState(const PDRList& stateSensorPDRs, 176 const std::vector<TlInfo>& tlinfo); 177 178 /** @brief check whether Host is running when pldmd starts 179 */ 180 bool isHostUp(); 181 182 private: 183 /** @brief deferred function to fetch PDR from Host, scheduled to work on 184 * the event loop. The PDR exchg with the host is async. 185 * @param[in] source - sdeventplus event source 186 */ 187 void _fetchPDR(sdeventplus::source::EventBase& source); 188 189 /** @brief Merge host firmware's entity association PDRs into BMC's 190 * @details A merge operation involves adding a pldm_entity under the 191 * appropriate parent, and updating container ids. 192 * @param[in] pdr - entity association pdr 193 */ 194 void mergeEntityAssociations(const std::vector<uint8_t>& pdr); 195 196 /** @brief Find parent of input entity type, from the entity association 197 * tree 198 * @param[in] type - PLDM entity type 199 * @param[out] parent - PLDM entity information of parent 200 * @return bool - true if parent found, false otherwise 201 */ 202 bool getParent(EntityType type, pldm_entity& parent); 203 204 /** @brief process the Host's PDR and add to BMC's PDR repo 205 * @param[in] eid - MCTP id of Host 206 * @param[in] response - response from Host for GetPDR 207 * @param[in] respMsgLen - response message length 208 */ 209 void processHostPDRs(mctp_eid_t eid, const pldm_msg* response, 210 size_t respMsgLen); 211 212 /** @brief send PDR Repo change after merging Host's PDR to BMC PDR repo 213 * @param[in] source - sdeventplus event source 214 */ 215 void _processPDRRepoChgEvent(sdeventplus::source::EventBase& source); 216 217 /** @brief fetch the next PDR based on the record handle sent by Host 218 * @param[in] nextRecordHandle - next record handle 219 * @param[in] source - sdeventplus event source 220 */ 221 void _processFetchPDREvent(uint32_t nextRecordHandle, 222 sdeventplus::source::EventBase& source); 223 224 /** @brief fd of MCTP communications socket */ 225 int mctp_fd; 226 /** @brief MCTP EID of host firmware */ 227 uint8_t mctp_eid; 228 /** @brief reference of main event loop of pldmd, primarily used to schedule 229 * work. 230 */ 231 sdeventplus::Event& event; 232 /** @brief pointer to BMC's primary PDR repo, host PDRs are added here */ 233 pldm_pdr* repo; 234 235 StateSensorHandler stateSensorHandler; 236 /** @brief Pointer to BMC's and Host's entity association tree */ 237 pldm_entity_association_tree* entityTree; 238 239 /** @brief Pointer to BMC's entity association tree */ 240 pldm_entity_association_tree* bmcEntityTree; 241 242 /** @brief reference to Requester object, primarily used to access API to 243 * obtain PLDM instance id. 244 */ 245 Requester& requester; 246 247 /** @brief PLDM request handler */ 248 pldm::requester::Handler<pldm::requester::Request>* handler; 249 250 /** @brief sdeventplus event source */ 251 std::unique_ptr<sdeventplus::source::Defer> pdrFetchEvent; 252 std::unique_ptr<sdeventplus::source::Defer> deferredFetchPDREvent; 253 std::unique_ptr<sdeventplus::source::Defer> deferredPDRRepoChgEvent; 254 255 /** @brief list of PDR record handles pointing to host's PDRs */ 256 PDRRecordHandles pdrRecordHandles; 257 /** @brief maps an entity type to parent pldm_entity from the BMC's entity 258 * association tree 259 */ 260 std::map<EntityType, pldm_entity> parents; 261 /** @brief D-Bus property changed signal match */ 262 std::unique_ptr<sdbusplus::bus::match::match> hostOffMatch; 263 264 /** @brief sensorMap is a lookup data structure that is build from the 265 * hostPDR that speeds up the lookup of <TerminusID, SensorID> in 266 * PlatformEventMessage command request. 267 */ 268 HostStateSensorMap sensorMap; 269 bool verbose; 270 271 /** @brief whether response received from Host */ 272 bool responseReceived; 273 /** @brief whether timed out waiting for a response from Host */ 274 bool timeOut; 275 /** @brief request message instance id */ 276 uint8_t insId; 277 }; 278 279 } // namespace pldm 280