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