xref: /openbmc/openpower-hw-diags/util/pldm.cpp (revision a001020f)
1*a001020fSAndrew Jeffery #include <libpldm/oem/ibm/state_set.h>
2bb90afc7SBen Tyner #include <libpldm/platform.h>
3bb90afc7SBen Tyner #include <libpldm/pldm.h>
4bb90afc7SBen Tyner 
5bb90afc7SBen Tyner #include <util/dbus.hpp>
6bb90afc7SBen Tyner #include <util/trace.hpp>
7bb90afc7SBen Tyner 
8bb90afc7SBen Tyner namespace util
9bb90afc7SBen Tyner {
10bb90afc7SBen Tyner namespace pldm
11bb90afc7SBen Tyner {
12bb90afc7SBen Tyner /** @brief Send PLDM request
13bb90afc7SBen Tyner  *
14bb90afc7SBen Tyner  * @param[in] request - the request data
15bb90afc7SBen Tyner  * @param[in] mcptEid - the mctp endpoint ID
16bb90afc7SBen Tyner  * @param[out] pldmFd - pldm socket file descriptor
17bb90afc7SBen Tyner  *
18bb90afc7SBen Tyner  * @pre a mctp instance must have been
19bb90afc7SBen Tyner  * @return true if send is successful false otherwise
20bb90afc7SBen Tyner  */
sendPldm(const std::vector<uint8_t> & request,uint8_t mctpEid,int & pldmFd)21bb90afc7SBen Tyner bool sendPldm(const std::vector<uint8_t>& request, uint8_t mctpEid, int& pldmFd)
22bb90afc7SBen Tyner {
23bb90afc7SBen Tyner     // connect to socket
24bb90afc7SBen Tyner     pldmFd = pldm_open();
25bb90afc7SBen Tyner     if (-1 == pldmFd)
26bb90afc7SBen Tyner     {
27bb90afc7SBen Tyner         trace::err("failed to connect to pldm");
28bb90afc7SBen Tyner         return false;
29bb90afc7SBen Tyner     }
30bb90afc7SBen Tyner 
31bb90afc7SBen Tyner     // send PLDM request
32bb90afc7SBen Tyner     auto pldmRc = pldm_send(mctpEid, pldmFd, request.data(), request.size());
33bb90afc7SBen Tyner 
34bb90afc7SBen Tyner     trace::inf("sent pldm request");
35bb90afc7SBen Tyner 
36bb90afc7SBen Tyner     return pldmRc == PLDM_REQUESTER_SUCCESS ? true : false;
37bb90afc7SBen Tyner }
38bb90afc7SBen Tyner 
39bb90afc7SBen Tyner /** @brief Prepare a request for SetStateEffecterStates
40bb90afc7SBen Tyner  *
41bb90afc7SBen Tyner  *  @param[in] effecterId - the effecter ID
42bb90afc7SBen Tyner  *  @param[in] effecterCount - composite effecter count
43bb90afc7SBen Tyner  *  @param[in] stateIdPos - position of the state set
44bb90afc7SBen Tyner  *  @param[in] stateSetValue - the value to set the state
45bb90afc7SBen Tyner  *  @param[in] mcptEid - the MCTP endpoint ID
46bb90afc7SBen Tyner  *
47bb90afc7SBen Tyner  *  @return PLDM request message to be sent to host, empty message on error
48bb90afc7SBen Tyner  */
prepareSetEffecterReq(uint16_t effecterId,uint8_t effecterCount,uint8_t stateIdPos,uint8_t stateSetValue,uint8_t mctpEid)49bb90afc7SBen Tyner std::vector<uint8_t> prepareSetEffecterReq(uint16_t effecterId,
50bb90afc7SBen Tyner                                            uint8_t effecterCount,
51bb90afc7SBen Tyner                                            uint8_t stateIdPos,
52bb90afc7SBen Tyner                                            uint8_t stateSetValue,
53bb90afc7SBen Tyner                                            uint8_t mctpEid)
54bb90afc7SBen Tyner {
55bb90afc7SBen Tyner     // get mctp instance associated with the endpoint ID
56bb90afc7SBen Tyner     uint8_t mctpInstance;
57bb90afc7SBen Tyner     if (!util::dbus::getMctpInstance(mctpInstance, mctpEid))
58bb90afc7SBen Tyner     {
59bb90afc7SBen Tyner         return std::vector<uint8_t>();
60bb90afc7SBen Tyner     }
61bb90afc7SBen Tyner 
62bb90afc7SBen Tyner     // form the request message
63bb90afc7SBen Tyner     std::vector<uint8_t> request(
64bb90afc7SBen Tyner         sizeof(pldm_msg_hdr) + sizeof(effecterId) + sizeof(effecterCount) +
65bb90afc7SBen Tyner         (effecterCount * sizeof(set_effecter_state_field)));
66bb90afc7SBen Tyner 
67bb90afc7SBen Tyner     // encode the state data with the change we want to elicit
68bb90afc7SBen Tyner     std::vector<set_effecter_state_field> stateField;
69bb90afc7SBen Tyner     for (uint8_t effecterPos = 0; effecterPos < effecterCount; effecterPos++)
70bb90afc7SBen Tyner     {
71bb90afc7SBen Tyner         if (effecterPos == stateIdPos)
72bb90afc7SBen Tyner         {
73bb90afc7SBen Tyner             stateField.emplace_back(
74bb90afc7SBen Tyner                 set_effecter_state_field{PLDM_REQUEST_SET, stateSetValue});
75bb90afc7SBen Tyner         }
76bb90afc7SBen Tyner         else
77bb90afc7SBen Tyner         {
78bb90afc7SBen Tyner             stateField.emplace_back(
79bb90afc7SBen Tyner                 set_effecter_state_field{PLDM_NO_CHANGE, 0});
80bb90afc7SBen Tyner         }
81bb90afc7SBen Tyner     }
82bb90afc7SBen Tyner 
83bb90afc7SBen Tyner     // encode the message with state data
84bb90afc7SBen Tyner     auto requestMsg = reinterpret_cast<pldm_msg*>(request.data());
85bb90afc7SBen Tyner     auto rc = encode_set_state_effecter_states_req(
86bb90afc7SBen Tyner         mctpInstance, effecterId, effecterCount, stateField.data(), requestMsg);
87bb90afc7SBen Tyner 
88bb90afc7SBen Tyner     if (rc != PLDM_SUCCESS)
89bb90afc7SBen Tyner     {
90bb90afc7SBen Tyner         trace::err("encode set effecter states request failed");
91bb90afc7SBen Tyner         request.clear();
92bb90afc7SBen Tyner     }
93bb90afc7SBen Tyner 
94bb90afc7SBen Tyner     return request;
95bb90afc7SBen Tyner }
96bb90afc7SBen Tyner 
97bb90afc7SBen Tyner /** @brief Return map of sensor ID to SBE instance
98bb90afc7SBen Tyner  *
99bb90afc7SBen Tyner  *  @param[in] stateSetId - the state set ID of interest
100bb90afc7SBen Tyner  *  @param[out] sensorInstanceMap - map of sensor to SBE instance
101bb90afc7SBen Tyner  *  @param[out] sensorOffset - position of sensor with state set ID within map
102bb90afc7SBen Tyner  *
103bb90afc7SBen Tyner  *  @return true if sensor info is available false otherwise
104bb90afc7SBen Tyner  */
fetchSensorInfo(uint16_t stateSetId,std::map<uint16_t,unsigned int> & sensorInstanceMap,uint8_t & sensorOffset)105bb90afc7SBen Tyner bool fetchSensorInfo(uint16_t stateSetId,
106bb90afc7SBen Tyner                      std::map<uint16_t, unsigned int>& sensorInstanceMap,
107bb90afc7SBen Tyner                      uint8_t& sensorOffset)
108bb90afc7SBen Tyner {
109bb90afc7SBen Tyner     // get state sensor PDRs
110bb90afc7SBen Tyner     std::vector<std::vector<uint8_t>> pdrs{};
111bb90afc7SBen Tyner     if (!util::dbus::getStateSensorPdrs(pdrs, stateSetId))
112bb90afc7SBen Tyner     {
113bb90afc7SBen Tyner         return false;
114bb90afc7SBen Tyner     }
115bb90afc7SBen Tyner 
116bb90afc7SBen Tyner     // check for any PDRs available
117bb90afc7SBen Tyner     if (!pdrs.size())
118bb90afc7SBen Tyner     {
119bb90afc7SBen Tyner         trace::err("state sensor PDRs not present");
120bb90afc7SBen Tyner         return false;
121bb90afc7SBen Tyner     }
122bb90afc7SBen Tyner 
123bb90afc7SBen Tyner     // find the offset of specified sensor withing PDRs
124bb90afc7SBen Tyner     bool offsetFound = false;
125bb90afc7SBen Tyner     auto stateSensorPDR =
126bb90afc7SBen Tyner         reinterpret_cast<const pldm_state_sensor_pdr*>(pdrs.front().data());
127bb90afc7SBen Tyner     auto possibleStatesPtr = stateSensorPDR->possible_states;
128bb90afc7SBen Tyner 
129bb90afc7SBen Tyner     for (auto offset = 0; offset < stateSensorPDR->composite_sensor_count;
130bb90afc7SBen Tyner          offset++)
131bb90afc7SBen Tyner     {
132bb90afc7SBen Tyner         auto possibleStates =
133bb90afc7SBen Tyner             reinterpret_cast<const state_sensor_possible_states*>(
134bb90afc7SBen Tyner                 possibleStatesPtr);
135bb90afc7SBen Tyner 
136bb90afc7SBen Tyner         if (possibleStates->state_set_id == stateSetId)
137bb90afc7SBen Tyner         {
138bb90afc7SBen Tyner             sensorOffset = offset;
139bb90afc7SBen Tyner             offsetFound = true;
140bb90afc7SBen Tyner             break;
141bb90afc7SBen Tyner         }
142bb90afc7SBen Tyner         possibleStatesPtr += sizeof(possibleStates->state_set_id) +
143bb90afc7SBen Tyner                              sizeof(possibleStates->possible_states_size) +
144bb90afc7SBen Tyner                              possibleStates->possible_states_size;
145bb90afc7SBen Tyner     }
146bb90afc7SBen Tyner 
147bb90afc7SBen Tyner     if (!offsetFound)
148bb90afc7SBen Tyner     {
149bb90afc7SBen Tyner         trace::err("state sensor not found");
150bb90afc7SBen Tyner         return false;
151bb90afc7SBen Tyner     }
152bb90afc7SBen Tyner 
153bb90afc7SBen Tyner     // map sensor ID to equivelent 16 bit value
154bb90afc7SBen Tyner     std::map<uint32_t, uint16_t> entityInstMap{};
155bb90afc7SBen Tyner     for (auto& pdr : pdrs)
156bb90afc7SBen Tyner     {
157bb90afc7SBen Tyner         auto pdrPtr =
158bb90afc7SBen Tyner             reinterpret_cast<const pldm_state_sensor_pdr*>(pdr.data());
159bb90afc7SBen Tyner         uint32_t key = pdrPtr->sensor_id;
160bb90afc7SBen Tyner         entityInstMap.emplace(key, static_cast<uint16_t>(pdrPtr->sensor_id));
161bb90afc7SBen Tyner     }
162bb90afc7SBen Tyner 
163bb90afc7SBen Tyner     // map sensor ID to zero based SBE instance
164bb90afc7SBen Tyner     unsigned int position = 0;
16527dd6368SPatrick Williams     for (const auto& pair : entityInstMap)
166bb90afc7SBen Tyner     {
167bb90afc7SBen Tyner         sensorInstanceMap.emplace(pair.second, position);
168bb90afc7SBen Tyner         position++;
169bb90afc7SBen Tyner     }
170bb90afc7SBen Tyner 
171bb90afc7SBen Tyner     return true;
172bb90afc7SBen Tyner }
173bb90afc7SBen Tyner 
174bb90afc7SBen Tyner /** @brief Return map of SBE instance to effecter ID
175bb90afc7SBen Tyner  *
176bb90afc7SBen Tyner  *  @param[in] stateSetId - the state set ID of interest
177bb90afc7SBen Tyner  *  @param[out] instanceToEffecterMap - map of sbe instance to effecter ID
178bb90afc7SBen Tyner  *  @param[out] effecterCount - composite effecter count
179bb90afc7SBen Tyner  *  @param[out] stateIdPos - position of effecter with state set ID within map
180bb90afc7SBen Tyner  *
181bb90afc7SBen Tyner  *  @return true if effector info is available false otherwise
182bb90afc7SBen Tyner  */
fetchEffecterInfo(uint16_t stateSetId,std::map<unsigned int,uint16_t> & instanceToEffecterMap,uint8_t & effecterCount,uint8_t & stateIdPos)183bb90afc7SBen Tyner bool fetchEffecterInfo(uint16_t stateSetId,
184bb90afc7SBen Tyner                        std::map<unsigned int, uint16_t>& instanceToEffecterMap,
185bb90afc7SBen Tyner                        uint8_t& effecterCount, uint8_t& stateIdPos)
186bb90afc7SBen Tyner {
187bb90afc7SBen Tyner     // get state effecter PDRs
188bb90afc7SBen Tyner     std::vector<std::vector<uint8_t>> pdrs{};
189bb90afc7SBen Tyner     if (!util::dbus::getStateEffecterPdrs(pdrs, stateSetId))
190bb90afc7SBen Tyner     {
191bb90afc7SBen Tyner         return false;
192bb90afc7SBen Tyner     }
193bb90afc7SBen Tyner 
194bb90afc7SBen Tyner     // check for any PDRs available
195bb90afc7SBen Tyner     if (!pdrs.size())
196bb90afc7SBen Tyner     {
197bb90afc7SBen Tyner         trace::err("state effecter PDRs not present");
198bb90afc7SBen Tyner         return false;
199bb90afc7SBen Tyner     }
200bb90afc7SBen Tyner 
201bb90afc7SBen Tyner     // find the offset of specified effector within PDRs
202bb90afc7SBen Tyner     bool offsetFound = false;
203bb90afc7SBen Tyner     auto stateEffecterPDR =
204bb90afc7SBen Tyner         reinterpret_cast<const pldm_state_effecter_pdr*>(pdrs.front().data());
205bb90afc7SBen Tyner     auto possibleStatesPtr = stateEffecterPDR->possible_states;
206bb90afc7SBen Tyner 
207bb90afc7SBen Tyner     for (auto offset = 0; offset < stateEffecterPDR->composite_effecter_count;
208bb90afc7SBen Tyner          offset++)
209bb90afc7SBen Tyner     {
210bb90afc7SBen Tyner         auto possibleStates =
211bb90afc7SBen Tyner             reinterpret_cast<const state_effecter_possible_states*>(
212bb90afc7SBen Tyner                 possibleStatesPtr);
213bb90afc7SBen Tyner 
214bb90afc7SBen Tyner         if (possibleStates->state_set_id == stateSetId)
215bb90afc7SBen Tyner         {
216bb90afc7SBen Tyner             stateIdPos = offset;
217bb90afc7SBen Tyner             effecterCount = stateEffecterPDR->composite_effecter_count;
218bb90afc7SBen Tyner             offsetFound = true;
219bb90afc7SBen Tyner             break;
220bb90afc7SBen Tyner         }
221bb90afc7SBen Tyner         possibleStatesPtr += sizeof(possibleStates->state_set_id) +
222bb90afc7SBen Tyner                              sizeof(possibleStates->possible_states_size) +
223bb90afc7SBen Tyner                              possibleStates->possible_states_size;
224bb90afc7SBen Tyner     }
225bb90afc7SBen Tyner 
226bb90afc7SBen Tyner     if (!offsetFound)
227bb90afc7SBen Tyner     {
228bb90afc7SBen Tyner         trace::err("state set effecter not found");
229bb90afc7SBen Tyner         return false;
230bb90afc7SBen Tyner     }
231bb90afc7SBen Tyner 
232bb90afc7SBen Tyner     // map effecter ID to equivelent 16 bit value
233bb90afc7SBen Tyner     std::map<uint32_t, uint16_t> entityInstMap{};
234bb90afc7SBen Tyner     for (auto& pdr : pdrs)
235bb90afc7SBen Tyner     {
236bb90afc7SBen Tyner         auto pdrPtr =
237bb90afc7SBen Tyner             reinterpret_cast<const pldm_state_effecter_pdr*>(pdr.data());
238bb90afc7SBen Tyner         uint32_t key = pdrPtr->effecter_id;
239bb90afc7SBen Tyner         entityInstMap.emplace(key, static_cast<uint16_t>(pdrPtr->effecter_id));
240bb90afc7SBen Tyner     }
241bb90afc7SBen Tyner 
242bb90afc7SBen Tyner     // map zero based SBE instance to effecter ID
243bb90afc7SBen Tyner     unsigned int position = 0;
24427dd6368SPatrick Williams     for (const auto& pair : entityInstMap)
245bb90afc7SBen Tyner     {
246bb90afc7SBen Tyner         instanceToEffecterMap.emplace(position, pair.second);
247bb90afc7SBen Tyner         position++;
248bb90afc7SBen Tyner     }
249bb90afc7SBen Tyner 
250bb90afc7SBen Tyner     return true;
251bb90afc7SBen Tyner }
252bb90afc7SBen Tyner 
253bb90afc7SBen Tyner /**  @brief Reset SBE using HBRT PLDM interface */
hresetSbe(unsigned int sbeInstance)254bb90afc7SBen Tyner bool hresetSbe(unsigned int sbeInstance)
255bb90afc7SBen Tyner {
256bb90afc7SBen Tyner     trace::inf("requesting sbe hreset");
257bb90afc7SBen Tyner 
258bb90afc7SBen Tyner     // get effecter info
259bb90afc7SBen Tyner     std::map<unsigned int, uint16_t> sbeInstanceToEffecter;
260bb90afc7SBen Tyner     uint8_t SBEEffecterCount = 0;
261bb90afc7SBen Tyner     uint8_t sbeMaintenanceStatePosition = 0;
262bb90afc7SBen Tyner 
263bb90afc7SBen Tyner     if (!fetchEffecterInfo(PLDM_OEM_IBM_SBE_MAINTENANCE_STATE,
264bb90afc7SBen Tyner                            sbeInstanceToEffecter, SBEEffecterCount,
265bb90afc7SBen Tyner                            sbeMaintenanceStatePosition))
266bb90afc7SBen Tyner     {
267bb90afc7SBen Tyner         return false;
268bb90afc7SBen Tyner     }
269bb90afc7SBen Tyner 
270bb90afc7SBen Tyner     // find the state effecter ID for the given SBE instance
271bb90afc7SBen Tyner     auto effecterEntry = sbeInstanceToEffecter.find(sbeInstance);
272bb90afc7SBen Tyner     if (effecterEntry == sbeInstanceToEffecter.end())
273bb90afc7SBen Tyner     {
274bb90afc7SBen Tyner         trace::err("failed to find effecter for SBE");
275bb90afc7SBen Tyner         return false;
276bb90afc7SBen Tyner     }
277bb90afc7SBen Tyner 
278bb90afc7SBen Tyner     // create request to HRESET the SBE
279bb90afc7SBen Tyner     constexpr uint8_t hbrtMctpEid = 10; // HBRT MCTP EID
280bb90afc7SBen Tyner 
281bb90afc7SBen Tyner     auto request = prepareSetEffecterReq(
282bb90afc7SBen Tyner         effecterEntry->second, SBEEffecterCount, sbeMaintenanceStatePosition,
283bb90afc7SBen Tyner         SBE_RETRY_REQUIRED, hbrtMctpEid);
284bb90afc7SBen Tyner 
285bb90afc7SBen Tyner     if (request.empty())
286bb90afc7SBen Tyner     {
287bb90afc7SBen Tyner         trace::err("HRESET effecter request empty");
288bb90afc7SBen Tyner         return false;
289bb90afc7SBen Tyner     }
290bb90afc7SBen Tyner 
291bb90afc7SBen Tyner     // get sensor info for validating sensor change
292bb90afc7SBen Tyner     std::map<uint16_t, unsigned int> sensorToSbeInstance;
293bb90afc7SBen Tyner     uint8_t sbeSensorOffset = 0;
294bb90afc7SBen Tyner     if (!fetchSensorInfo(PLDM_OEM_IBM_SBE_HRESET_STATE, sensorToSbeInstance,
295bb90afc7SBen Tyner                          sbeSensorOffset))
296bb90afc7SBen Tyner     {
297bb90afc7SBen Tyner         return false;
298bb90afc7SBen Tyner     }
299bb90afc7SBen Tyner 
300bb90afc7SBen Tyner     // register signal change listener
301bb90afc7SBen Tyner     std::string hresetStatus = "requested";
302bb90afc7SBen Tyner     constexpr auto interface = "xyz.openbmc_project.PLDM.Event";
303bb90afc7SBen Tyner     constexpr auto path = "/xyz/openbmc_project/pldm";
304bb90afc7SBen Tyner     constexpr auto member = "StateSensorEvent";
305bb90afc7SBen Tyner 
306bb90afc7SBen Tyner     auto bus = sdbusplus::bus::new_default();
307bb90afc7SBen Tyner     std::unique_ptr<sdbusplus::bus::match_t> match =
308bb90afc7SBen Tyner         std::make_unique<sdbusplus::bus::match_t>(
309bb90afc7SBen Tyner             bus,
310bb90afc7SBen Tyner             sdbusplus::bus::match::rules::type::signal() +
311bb90afc7SBen Tyner                 sdbusplus::bus::match::rules::member(member) +
312bb90afc7SBen Tyner                 sdbusplus::bus::match::rules::path(path) +
313bb90afc7SBen Tyner                 sdbusplus::bus::match::rules::interface(interface),
314bb90afc7SBen Tyner             [&](auto& msg) {
315bb90afc7SBen Tyner         uint8_t sensorTid{};
316bb90afc7SBen Tyner         uint16_t sensorId{};
317bb90afc7SBen Tyner         uint8_t msgSensorOffset{};
318bb90afc7SBen Tyner         uint8_t eventState{};
319bb90afc7SBen Tyner         uint8_t previousEventState{};
320bb90afc7SBen Tyner 
321bb90afc7SBen Tyner         // get sensor event details
322bb90afc7SBen Tyner         msg.read(sensorTid, sensorId, msgSensorOffset, eventState,
323bb90afc7SBen Tyner                  previousEventState);
324bb90afc7SBen Tyner 
325bb90afc7SBen Tyner         // does sensor offset match?
326bb90afc7SBen Tyner         if (sbeSensorOffset == msgSensorOffset)
327bb90afc7SBen Tyner         {
328bb90afc7SBen Tyner             // does sensor ID match?
329bb90afc7SBen Tyner             auto sensorEntry = sensorToSbeInstance.find(sensorId);
330bb90afc7SBen Tyner             if (sensorEntry != sensorToSbeInstance.end())
331bb90afc7SBen Tyner             {
332bb90afc7SBen Tyner                 const uint8_t instance = sensorEntry->second;
333bb90afc7SBen Tyner 
334bb90afc7SBen Tyner                 // if instances matche check status
335bb90afc7SBen Tyner                 if (instance == sbeInstance)
336bb90afc7SBen Tyner                 {
33727dd6368SPatrick Williams                     if (eventState == static_cast<uint8_t>(SBE_HRESET_READY))
338bb90afc7SBen Tyner                     {
339bb90afc7SBen Tyner                         hresetStatus = "success";
340bb90afc7SBen Tyner                     }
341bb90afc7SBen Tyner                     else if (eventState ==
342bb90afc7SBen Tyner                              static_cast<uint8_t>(SBE_HRESET_FAILED))
343bb90afc7SBen Tyner                     {
344bb90afc7SBen Tyner                         hresetStatus = "fail";
345bb90afc7SBen Tyner                     }
346bb90afc7SBen Tyner                 }
347bb90afc7SBen Tyner             }
348bb90afc7SBen Tyner         }
349bb90afc7SBen Tyner     });
350bb90afc7SBen Tyner 
351bb90afc7SBen Tyner     // send request to issue hreset of sbe
352bb90afc7SBen Tyner     int pldmFd = -1; // mctp socket file descriptor
353bb90afc7SBen Tyner     if (!sendPldm(request, hbrtMctpEid, pldmFd))
354bb90afc7SBen Tyner     {
355bb90afc7SBen Tyner         trace::err("send pldm request failed");
356bb90afc7SBen Tyner         if (-1 != pldmFd)
357bb90afc7SBen Tyner         {
358bb90afc7SBen Tyner             close(pldmFd);
359bb90afc7SBen Tyner         }
360bb90afc7SBen Tyner         return false;
361bb90afc7SBen Tyner     }
362bb90afc7SBen Tyner 
363bb90afc7SBen Tyner     // keep track of elapsed time
364bb90afc7SBen Tyner     uint64_t timeRemaining = 60000000; // microseconds, 1 minute
365bb90afc7SBen Tyner     std::chrono::steady_clock::time_point begin =
366bb90afc7SBen Tyner         std::chrono::steady_clock::now();
367bb90afc7SBen Tyner 
368bb90afc7SBen Tyner     // wait for status update or timeout
369bb90afc7SBen Tyner     trace::inf("waiting on sbe hreset");
370bb90afc7SBen Tyner     while ("requested" == hresetStatus && 0 != timeRemaining)
371bb90afc7SBen Tyner     {
372bb90afc7SBen Tyner         bus.wait(timeRemaining);
373bb90afc7SBen Tyner         uint64_t timeElapsed =
374bb90afc7SBen Tyner             std::chrono::duration_cast<std::chrono::microseconds>(
375bb90afc7SBen Tyner                 std::chrono::steady_clock::now() - begin)
376bb90afc7SBen Tyner                 .count();
377bb90afc7SBen Tyner 
378bb90afc7SBen Tyner         timeRemaining =
379bb90afc7SBen Tyner             timeElapsed > timeRemaining ? 0 : timeRemaining - timeElapsed;
380bb90afc7SBen Tyner 
381bb90afc7SBen Tyner         bus.process_discard();
382bb90afc7SBen Tyner     }
383bb90afc7SBen Tyner 
384bb90afc7SBen Tyner     if (0 == timeRemaining)
385bb90afc7SBen Tyner     {
386bb90afc7SBen Tyner         trace::err("hreset timed out");
387bb90afc7SBen Tyner     }
388bb90afc7SBen Tyner 
389bb90afc7SBen Tyner     close(pldmFd); // close pldm socket
390bb90afc7SBen Tyner 
391bb90afc7SBen Tyner     return hresetStatus == "success" ? true : false;
392bb90afc7SBen Tyner }
393bb90afc7SBen Tyner 
394bb90afc7SBen Tyner } // namespace pldm
395bb90afc7SBen Tyner } // namespace util
396