xref: /openbmc/pldm/softoff/softoff.cpp (revision 3c8b3e353728899e1c32827c1ade9f4b427006a9)
1184f6026SChicago Duan #include "softoff.hpp"
2184f6026SChicago Duan 
33d03f3faSDung Cao #include "common/instance_id.hpp"
41ed5f7a6SRashmica Gupta #include "common/transport.hpp"
5184f6026SChicago Duan #include "common/utils.hpp"
6184f6026SChicago Duan 
7c453e164SGeorge Liu #include <libpldm/entity.h>
8c453e164SGeorge Liu #include <libpldm/platform.h>
9c453e164SGeorge Liu #include <libpldm/state_set.h>
10c453e164SGeorge Liu 
1149cfb138SRiya Dixit #include <phosphor-logging/lg2.hpp>
12184f6026SChicago Duan #include <sdbusplus/bus.hpp>
13184f6026SChicago Duan #include <sdeventplus/clock.hpp>
14a2767e68SGeorge Liu #include <sdeventplus/exception.hpp>
15184f6026SChicago Duan #include <sdeventplus/source/io.hpp>
16184f6026SChicago Duan #include <sdeventplus/source/time.hpp>
17184f6026SChicago Duan 
18184f6026SChicago Duan #include <array>
194d99c311SSagar Srinivas #include <filesystem>
204d99c311SSagar Srinivas #include <fstream>
21184f6026SChicago Duan 
2249cfb138SRiya Dixit PHOSPHOR_LOG2_USING;
2349cfb138SRiya Dixit 
24184f6026SChicago Duan namespace pldm
25184f6026SChicago Duan {
26184f6026SChicago Duan using namespace sdeventplus;
27184f6026SChicago Duan using namespace sdeventplus::source;
284d99c311SSagar Srinivas namespace fs = std::filesystem;
29184f6026SChicago Duan constexpr auto clockId = sdeventplus::ClockId::RealTime;
30184f6026SChicago Duan using Clock = Clock<clockId>;
31184f6026SChicago Duan using Timer = Time<clockId>;
32184f6026SChicago Duan 
33e98c51b1SZach Clark using sdbusplus::exception::SdBusError;
34e98c51b1SZach Clark 
35e98c51b1SZach Clark // Shutdown effecter terminus ID, set when we look up the effecter
36e98c51b1SZach Clark pldm::pdr::TerminusID TID = 0;
37e98c51b1SZach Clark 
38184f6026SChicago Duan namespace sdbusRule = sdbusplus::bus::match::rules;
39184f6026SChicago Duan 
SoftPowerOff(sdbusplus::bus_t & bus,sd_event * event,pldm::InstanceIdDb & instanceIdDb)403fcfaa12SManojkiran Eda SoftPowerOff::SoftPowerOff(sdbusplus::bus_t& bus, sd_event* event,
413fcfaa12SManojkiran Eda                            pldm::InstanceIdDb& instanceIdDb) :
4216c2a0a0SPatrick Williams     bus(bus), timer(event), instanceIdDb(instanceIdDb)
43184f6026SChicago Duan {
444d99c311SSagar Srinivas     auto jsonData = parseConfig();
454d99c311SSagar Srinivas 
464d99c311SSagar Srinivas     if (jsonData.is_discarded())
474d99c311SSagar Srinivas     {
48087a751fSRiya Dixit         error("Failed to parse softoff config JSON file");
494d99c311SSagar Srinivas         return;
504d99c311SSagar Srinivas     }
514d99c311SSagar Srinivas 
5231a78447SManojkiran Eda     getHostState();
53184f6026SChicago Duan     if (hasError || completed)
54184f6026SChicago Duan     {
55184f6026SChicago Duan         return;
56184f6026SChicago Duan     }
574d99c311SSagar Srinivas     const std::vector<Json> emptyJsonList{};
584d99c311SSagar Srinivas     auto entries = jsonData.value("entries", emptyJsonList);
594d99c311SSagar Srinivas     for (const auto& entry : entries)
6029d22119STom Joseph     {
614d99c311SSagar Srinivas         TID = entry.value("tid", 0);
624d99c311SSagar Srinivas         pldm::pdr::EntityType entityType = entry.value("entityType", 0);
634d99c311SSagar Srinivas         pldm::pdr::StateSetId stateSetId = entry.value("stateSetId", 0);
64184f6026SChicago Duan 
654d99c311SSagar Srinivas         bool effecterFound = getEffecterID(entityType, stateSetId);
664d99c311SSagar Srinivas         if (effecterFound)
674d99c311SSagar Srinivas         {
684d99c311SSagar Srinivas             auto rc = getSensorInfo(entityType, stateSetId);
69184f6026SChicago Duan             if (rc != PLDM_SUCCESS)
70184f6026SChicago Duan             {
71087a751fSRiya Dixit                 error("Failed to get Sensor PDRs, response code '{RC}'", "RC",
721e5c81e0SRiya Dixit                       lg2::hex, rc);
73184f6026SChicago Duan                 hasError = true;
74184f6026SChicago Duan                 return;
75184f6026SChicago Duan             }
764d99c311SSagar Srinivas             break;
774d99c311SSagar Srinivas         }
784d99c311SSagar Srinivas         else
794d99c311SSagar Srinivas         {
804d99c311SSagar Srinivas             continue;
814d99c311SSagar Srinivas         }
824d99c311SSagar Srinivas     }
83184f6026SChicago Duan 
84184f6026SChicago Duan     // Matches on the pldm StateSensorEvent signal
85184f6026SChicago Duan     pldmEventSignal = std::make_unique<sdbusplus::bus::match_t>(
86184f6026SChicago Duan         bus,
87184f6026SChicago Duan         sdbusRule::type::signal() + sdbusRule::member("StateSensorEvent") +
88184f6026SChicago Duan             sdbusRule::path("/xyz/openbmc_project/pldm") +
89184f6026SChicago Duan             sdbusRule::interface("xyz.openbmc_project.PLDM.Event"),
90184f6026SChicago Duan         std::bind(std::mem_fn(&SoftPowerOff::hostSoftOffComplete), this,
91184f6026SChicago Duan                   std::placeholders::_1));
92184f6026SChicago Duan }
93184f6026SChicago Duan 
getHostState()94184f6026SChicago Duan int SoftPowerOff::getHostState()
95184f6026SChicago Duan {
96184f6026SChicago Duan     try
97184f6026SChicago Duan     {
98184f6026SChicago Duan         pldm::utils::PropertyValue propertyValue =
99184f6026SChicago Duan             pldm::utils::DBusHandler().getDbusPropertyVariant(
100184f6026SChicago Duan                 "/xyz/openbmc_project/state/host0", "CurrentHostState",
101184f6026SChicago Duan                 "xyz.openbmc_project.State.Host");
102184f6026SChicago Duan 
1035b5fa436SAndrew Geissler         if ((std::get<std::string>(propertyValue) !=
1045b5fa436SAndrew Geissler              "xyz.openbmc_project.State.Host.HostState.Running") &&
1055b5fa436SAndrew Geissler             (std::get<std::string>(propertyValue) !=
1065b5fa436SAndrew Geissler              "xyz.openbmc_project.State.Host.HostState.TransitioningToOff"))
107184f6026SChicago Duan         {
108184f6026SChicago Duan             // Host state is not "Running", this app should return success
109184f6026SChicago Duan             completed = true;
110184f6026SChicago Duan             return PLDM_SUCCESS;
111184f6026SChicago Duan         }
112184f6026SChicago Duan     }
113184f6026SChicago Duan     catch (const std::exception& e)
114184f6026SChicago Duan     {
115087a751fSRiya Dixit         error(
116087a751fSRiya Dixit             "PLDM remote terminus soft off. Can't get current remote terminus state, error - {ERROR}",
11758cbcaf2SKamalkumar Patel             "ERROR", e);
118184f6026SChicago Duan         hasError = true;
119184f6026SChicago Duan         return PLDM_ERROR;
120184f6026SChicago Duan     }
121184f6026SChicago Duan 
122184f6026SChicago Duan     return PLDM_SUCCESS;
123184f6026SChicago Duan }
124184f6026SChicago Duan 
hostSoftOffComplete(sdbusplus::message_t & msg)12584b790cbSPatrick Williams void SoftPowerOff::hostSoftOffComplete(sdbusplus::message_t& msg)
126184f6026SChicago Duan {
127184f6026SChicago Duan     pldm::pdr::TerminusID msgTID;
128184f6026SChicago Duan     pldm::pdr::SensorID msgSensorID;
129184f6026SChicago Duan     pldm::pdr::SensorOffset msgSensorOffset;
130184f6026SChicago Duan     pldm::pdr::EventState msgEventState;
131184f6026SChicago Duan     pldm::pdr::EventState msgPreviousEventState;
132184f6026SChicago Duan 
133184f6026SChicago Duan     // Read the msg and populate each variable
134184f6026SChicago Duan     msg.read(msgTID, msgSensorID, msgSensorOffset, msgEventState,
135184f6026SChicago Duan              msgPreviousEventState);
136184f6026SChicago Duan 
137184f6026SChicago Duan     if (msgSensorID == sensorID && msgSensorOffset == sensorOffset &&
138e98c51b1SZach Clark         msgEventState == PLDM_SW_TERM_GRACEFUL_SHUTDOWN && msgTID == TID)
139184f6026SChicago Duan     {
140184f6026SChicago Duan         // Receive Graceful shutdown completion event message. Disable the timer
141184f6026SChicago Duan         auto rc = timer.stop();
142184f6026SChicago Duan         if (rc < 0)
143184f6026SChicago Duan         {
144087a751fSRiya Dixit             error(
145087a751fSRiya Dixit                 "Failure to STOP the timer of PLDM soft off, response code '{RC}'",
146087a751fSRiya Dixit                 "RC", rc);
147184f6026SChicago Duan         }
148184f6026SChicago Duan 
149184f6026SChicago Duan         // This marks the completion of pldm soft power off.
150184f6026SChicago Duan         completed = true;
151184f6026SChicago Duan     }
152184f6026SChicago Duan }
153184f6026SChicago Duan 
parseConfig()1544d99c311SSagar Srinivas Json SoftPowerOff::parseConfig()
1554d99c311SSagar Srinivas {
15616c2a0a0SPatrick Williams     fs::path softoffConfigJson(
15716c2a0a0SPatrick Williams         fs::path(SOFTOFF_CONFIG_JSON) / "softoff_config.json");
1584d99c311SSagar Srinivas 
1594d99c311SSagar Srinivas     if (!fs::exists(softoffConfigJson) || fs::is_empty(softoffConfigJson))
1604d99c311SSagar Srinivas     {
161087a751fSRiya Dixit         error(
162087a751fSRiya Dixit             "Failed to parse softoff config JSON file '{PATH}', file does not exist",
163087a751fSRiya Dixit             "PATH", softoffConfigJson);
1644d99c311SSagar Srinivas         return PLDM_ERROR;
1654d99c311SSagar Srinivas     }
1664d99c311SSagar Srinivas 
1674d99c311SSagar Srinivas     std::ifstream jsonFile(softoffConfigJson);
1684d99c311SSagar Srinivas     return Json::parse(jsonFile);
1694d99c311SSagar Srinivas }
1704d99c311SSagar Srinivas 
getEffecterID(pldm::pdr::EntityType & entityType,pldm::pdr::StateSetId & stateSetId)1714d99c311SSagar Srinivas bool SoftPowerOff::getEffecterID(pldm::pdr::EntityType& entityType,
1724d99c311SSagar Srinivas                                  pldm::pdr::StateSetId& stateSetId)
173184f6026SChicago Duan {
174184f6026SChicago Duan     auto& bus = pldm::utils::DBusHandler::getBus();
175184f6026SChicago Duan     try
176184f6026SChicago Duan     {
1774d99c311SSagar Srinivas         std::vector<std::vector<uint8_t>> response{};
1784d99c311SSagar Srinivas         auto method = bus.new_method_call(
179184f6026SChicago Duan             "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
180184f6026SChicago Duan             "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
1814d99c311SSagar Srinivas         method.append(TID, entityType, stateSetId);
1824d99c311SSagar Srinivas         auto responseMsg = bus.call(method, dbusTimeout);
183184f6026SChicago Duan 
1844d99c311SSagar Srinivas         responseMsg.read(response);
1854d99c311SSagar Srinivas         if (response.size())
186184f6026SChicago Duan         {
1874d99c311SSagar Srinivas             for (auto& rep : response)
188184f6026SChicago Duan             {
189*3c8b3e35SPavithra Barithaya                 auto softoffPdr = new (rep.data()) pldm_state_effecter_pdr;
1904d99c311SSagar Srinivas                 effecterID = softoffPdr->effecter_id;
191184f6026SChicago Duan             }
192184f6026SChicago Duan         }
193184f6026SChicago Duan         else
194184f6026SChicago Duan         {
1954d99c311SSagar Srinivas             return false;
196184f6026SChicago Duan         }
197184f6026SChicago Duan     }
19884b790cbSPatrick Williams     catch (const sdbusplus::exception_t& e)
199184f6026SChicago Duan     {
200087a751fSRiya Dixit         error("Failed to get softPowerOff PDR, error - {ERROR}", "ERROR", e);
2014d99c311SSagar Srinivas         return false;
2024d99c311SSagar Srinivas     }
2034d99c311SSagar Srinivas     return true;
204184f6026SChicago Duan }
205184f6026SChicago Duan 
getSensorInfo(pldm::pdr::EntityType & entityType,pldm::pdr::StateSetId & stateSetId)2064d99c311SSagar Srinivas int SoftPowerOff::getSensorInfo(pldm::pdr::EntityType& entityType,
2074d99c311SSagar Srinivas                                 pldm::pdr::StateSetId& stateSetId)
208184f6026SChicago Duan {
209184f6026SChicago Duan     try
210184f6026SChicago Duan     {
211184f6026SChicago Duan         auto& bus = pldm::utils::DBusHandler::getBus();
212184f6026SChicago Duan         std::vector<std::vector<uint8_t>> Response{};
213184f6026SChicago Duan         auto method = bus.new_method_call(
214184f6026SChicago Duan             "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
215184f6026SChicago Duan             "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
2164d99c311SSagar Srinivas         method.append(TID, entityType, stateSetId);
217184f6026SChicago Duan 
21891a092f6Svkaverap@in.ibm.com         auto ResponseMsg = bus.call(method, dbusTimeout);
219184f6026SChicago Duan 
220184f6026SChicago Duan         ResponseMsg.read(Response);
221184f6026SChicago Duan 
222184f6026SChicago Duan         if (Response.size() == 0)
223184f6026SChicago Duan         {
22449cfb138SRiya Dixit             error("No sensor PDR has been found that matches the criteria");
225184f6026SChicago Duan             return PLDM_ERROR;
226184f6026SChicago Duan         }
227184f6026SChicago Duan 
228499a29ddSThuBaNguyen         pldm_state_sensor_pdr* pdr = nullptr;
229184f6026SChicago Duan         for (auto& rep : Response)
230184f6026SChicago Duan         {
231*3c8b3e35SPavithra Barithaya             pdr = new (rep.data()) pldm_state_sensor_pdr;
232bcf91accSManojkiran Eda             if (!pdr)
233bcf91accSManojkiran Eda             {
23449cfb138SRiya Dixit                 error("Failed to get state sensor PDR.");
235bcf91accSManojkiran Eda                 return PLDM_ERROR;
236bcf91accSManojkiran Eda             }
23731a78447SManojkiran Eda         }
238bcf91accSManojkiran Eda 
239184f6026SChicago Duan         sensorID = pdr->sensor_id;
240184f6026SChicago Duan 
241184f6026SChicago Duan         auto compositeSensorCount = pdr->composite_sensor_count;
242184f6026SChicago Duan         auto possibleStatesStart = pdr->possible_states;
243184f6026SChicago Duan 
244184f6026SChicago Duan         for (auto offset = 0; offset < compositeSensorCount; offset++)
245184f6026SChicago Duan         {
246*3c8b3e35SPavithra Barithaya             auto possibleStates = new (possibleStatesStart)
247*3c8b3e35SPavithra Barithaya                 state_sensor_possible_states;
248184f6026SChicago Duan             auto setId = possibleStates->state_set_id;
249184f6026SChicago Duan             auto possibleStateSize = possibleStates->possible_states_size;
250184f6026SChicago Duan 
251184f6026SChicago Duan             if (setId == PLDM_STATE_SET_SW_TERMINATION_STATUS)
252184f6026SChicago Duan             {
253184f6026SChicago Duan                 sensorOffset = offset;
254184f6026SChicago Duan                 break;
255184f6026SChicago Duan             }
25616c2a0a0SPatrick Williams             possibleStatesStart +=
25716c2a0a0SPatrick Williams                 possibleStateSize + sizeof(setId) + sizeof(possibleStateSize);
258184f6026SChicago Duan         }
259184f6026SChicago Duan     }
26084b790cbSPatrick Williams     catch (const sdbusplus::exception_t& e)
261184f6026SChicago Duan     {
262087a751fSRiya Dixit         error("Failed to get state sensor PDR during soft-off, error - {ERROR}",
263087a751fSRiya Dixit               "ERROR", e);
264184f6026SChicago Duan         return PLDM_ERROR;
265184f6026SChicago Duan     }
266184f6026SChicago Duan 
267184f6026SChicago Duan     return PLDM_SUCCESS;
268184f6026SChicago Duan }
269184f6026SChicago Duan 
hostSoftOff(sdeventplus::Event & event)270184f6026SChicago Duan int SoftPowerOff::hostSoftOff(sdeventplus::Event& event)
271184f6026SChicago Duan {
272184f6026SChicago Duan     constexpr uint8_t effecterCount = 1;
2731ed5f7a6SRashmica Gupta     PldmTransport pldmTransport{};
274184f6026SChicago Duan     uint8_t instanceID;
2751ed5f7a6SRashmica Gupta     uint8_t mctpEID;
276184f6026SChicago Duan 
277184f6026SChicago Duan     mctpEID = pldm::utils::readHostEID();
2783d03f3faSDung Cao     // TODO: fix mapping to work around OpenBMC ecosystem deficiencies
2793d03f3faSDung Cao     pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEID);
280184f6026SChicago Duan 
28116c2a0a0SPatrick Williams     std::array<uint8_t,
28216c2a0a0SPatrick Williams                sizeof(pldm_msg_hdr) + sizeof(effecterID) +
28316c2a0a0SPatrick Williams                    sizeof(effecterCount) + sizeof(set_effecter_state_field)>
284184f6026SChicago Duan         requestMsg{};
285*3c8b3e35SPavithra Barithaya     auto request = new (requestMsg.data()) pldm_msg;
286184f6026SChicago Duan     set_effecter_state_field stateField{
287184f6026SChicago Duan         PLDM_REQUEST_SET, PLDM_SW_TERM_GRACEFUL_SHUTDOWN_REQUESTED};
2883d03f3faSDung Cao     instanceID = instanceIdDb.next(pldmTID);
289184f6026SChicago Duan     auto rc = encode_set_state_effecter_states_req(
290184f6026SChicago Duan         instanceID, effecterID, effecterCount, &stateField, request);
291184f6026SChicago Duan     if (rc != PLDM_SUCCESS)
292184f6026SChicago Duan     {
2933d03f3faSDung Cao         instanceIdDb.free(pldmTID, instanceID);
294087a751fSRiya Dixit         error(
295087a751fSRiya Dixit             "Failed to encode set state effecter states request message, response code '{RC}'",
2961e5c81e0SRiya Dixit             "RC", lg2::hex, rc);
297184f6026SChicago Duan         return PLDM_ERROR;
298184f6026SChicago Duan     }
299184f6026SChicago Duan 
300184f6026SChicago Duan     // Add a timer to the event loop, default 30s.
301a675662cSPatrick Williams     auto timerCallback = [=, this](Timer& /*source*/,
302a675662cSPatrick Williams                                    Timer::TimePoint /*time*/) mutable {
303184f6026SChicago Duan         if (!responseReceived)
304184f6026SChicago Duan         {
3053d03f3faSDung Cao             instanceIdDb.free(pldmTID, instanceID);
30649cfb138SRiya Dixit             error(
307087a751fSRiya Dixit                 "PLDM soft off failed, can't get the response for the PLDM request msg. Time out! Exit the pldm-softpoweroff");
308184f6026SChicago Duan             exit(-1);
309184f6026SChicago Duan         }
310184f6026SChicago Duan         return;
311184f6026SChicago Duan     };
312184f6026SChicago Duan     Timer time(event, (Clock(event).now() + std::chrono::seconds{30}),
313184f6026SChicago Duan                std::chrono::seconds{1}, std::move(timerCallback));
314184f6026SChicago Duan 
315184f6026SChicago Duan     // Add a callback to handle EPOLLIN on fd
31616c2a0a0SPatrick Williams     auto callback = [=, &pldmTransport,
31716c2a0a0SPatrick Williams                      this](IO& io, int fd, uint32_t revents) mutable {
3181ed5f7a6SRashmica Gupta         if (fd != pldmTransport.getEventSource())
3191ed5f7a6SRashmica Gupta         {
3201ed5f7a6SRashmica Gupta             return;
3211ed5f7a6SRashmica Gupta         }
3221ed5f7a6SRashmica Gupta 
323184f6026SChicago Duan         if (!(revents & EPOLLIN))
324184f6026SChicago Duan         {
325184f6026SChicago Duan             return;
326184f6026SChicago Duan         }
327184f6026SChicago Duan 
3281ed5f7a6SRashmica Gupta         void* responseMsg = nullptr;
329184f6026SChicago Duan         size_t responseMsgSize{};
3303d03f3faSDung Cao         pldm_tid_t srcTID = pldmTID;
331184f6026SChicago Duan 
3321ed5f7a6SRashmica Gupta         auto rc = pldmTransport.recvMsg(pldmTID, responseMsg, responseMsgSize);
333184f6026SChicago Duan         if (rc)
334184f6026SChicago Duan         {
335087a751fSRiya Dixit             error(
336087a751fSRiya Dixit                 "Failed to receive pldm data during soft-off, response code '{RC}'",
3371e5c81e0SRiya Dixit                 "RC", rc);
338184f6026SChicago Duan             return;
339184f6026SChicago Duan         }
340184f6026SChicago Duan 
34116c2a0a0SPatrick Williams         std::unique_ptr<void, decltype(std::free)*> responseMsgPtr{
34216c2a0a0SPatrick Williams             responseMsg, std::free};
343184f6026SChicago Duan 
344184f6026SChicago Duan         // We've got the response meant for the PLDM request msg that was
345184f6026SChicago Duan         // sent out
346184f6026SChicago Duan         io.set_enabled(Enabled::Off);
347*3c8b3e35SPavithra Barithaya         auto response = new (responseMsgPtr.get()) pldm_msg;
3483d03f3faSDung Cao 
3493d03f3faSDung Cao         if (srcTID != pldmTID ||
3503d03f3faSDung Cao             !pldm_msg_hdr_correlate_response(&request->hdr, &response->hdr))
3513d03f3faSDung Cao         {
3523d03f3faSDung Cao             /* This isn't the response we were looking for */
3533d03f3faSDung Cao             return;
3543d03f3faSDung Cao         }
3553d03f3faSDung Cao 
3563d03f3faSDung Cao         /* We have the right response, release the instance ID and process */
3573d03f3faSDung Cao         io.set_enabled(Enabled::Off);
3583d03f3faSDung Cao         instanceIdDb.free(pldmTID, instanceID);
3593d03f3faSDung Cao 
3609915d022SGeorge Liu         if (response->payload[0] != PLDM_SUCCESS)
3619915d022SGeorge Liu         {
362087a751fSRiya Dixit             error("Getting the wrong response, response code '{RC}'", "RC",
3631e5c81e0SRiya Dixit                   response->payload[0]);
3649915d022SGeorge Liu             exit(-1);
3659915d022SGeorge Liu         }
366184f6026SChicago Duan 
367184f6026SChicago Duan         responseReceived = true;
368184f6026SChicago Duan 
369184f6026SChicago Duan         // Start Timer
370184f6026SChicago Duan         using namespace std::chrono;
371184f6026SChicago Duan         auto timeMicroseconds =
372184f6026SChicago Duan             duration_cast<microseconds>(seconds(SOFTOFF_TIMEOUT_SECONDS));
373184f6026SChicago Duan 
374184f6026SChicago Duan         auto ret = startTimer(timeMicroseconds);
375184f6026SChicago Duan         if (ret < 0)
376184f6026SChicago Duan         {
37749cfb138SRiya Dixit             error(
378087a751fSRiya Dixit                 "Failure to start remote terminus soft off wait timer, Exit the pldm-softpoweroff with response code:{NUM}",
379087a751fSRiya Dixit                 "NUM", ret);
380184f6026SChicago Duan             exit(-1);
381184f6026SChicago Duan         }
382184f6026SChicago Duan         else
383184f6026SChicago Duan         {
38449cfb138SRiya Dixit             error(
385087a751fSRiya Dixit                 "Timer started waiting for remote terminus soft off, timeout in sec '{TIMEOUT_SEC}'",
38649cfb138SRiya Dixit                 "TIMEOUT_SEC", SOFTOFF_TIMEOUT_SECONDS);
387184f6026SChicago Duan         }
388184f6026SChicago Duan         return;
389184f6026SChicago Duan     };
3901ed5f7a6SRashmica Gupta     IO io(event, pldmTransport.getEventSource(), EPOLLIN, std::move(callback));
391184f6026SChicago Duan 
3921ed5f7a6SRashmica Gupta     // Asynchronously send the PLDM request
3931ed5f7a6SRashmica Gupta     rc = pldmTransport.sendMsg(pldmTID, requestMsg.data(), requestMsg.size());
3949f8d2b0aSSampa Misra     if (0 > rc)
395184f6026SChicago Duan     {
3963d03f3faSDung Cao         instanceIdDb.free(pldmTID, instanceID);
39749cfb138SRiya Dixit         error(
398087a751fSRiya Dixit             "Failed to send message/receive response, response code '{RC}' and error - {ERROR}",
3991e5c81e0SRiya Dixit             "RC", rc, "ERROR", errno);
400184f6026SChicago Duan         return PLDM_ERROR;
401184f6026SChicago Duan     }
402184f6026SChicago Duan 
403184f6026SChicago Duan     // Time out or soft off complete
404184f6026SChicago Duan     while (!isCompleted() && !isTimerExpired())
405184f6026SChicago Duan     {
406184f6026SChicago Duan         try
407184f6026SChicago Duan         {
408184f6026SChicago Duan             event.run(std::nullopt);
409184f6026SChicago Duan         }
410184f6026SChicago Duan         catch (const sdeventplus::SdEventError& e)
411184f6026SChicago Duan         {
4123d03f3faSDung Cao             instanceIdDb.free(pldmTID, instanceID);
41349cfb138SRiya Dixit             error(
414087a751fSRiya Dixit                 "Failed to process request while remote terminus soft off, error - {ERROR}",
415087a751fSRiya Dixit                 "ERROR", e);
416184f6026SChicago Duan             return PLDM_ERROR;
417184f6026SChicago Duan         }
418184f6026SChicago Duan     }
419184f6026SChicago Duan 
420184f6026SChicago Duan     return PLDM_SUCCESS;
421184f6026SChicago Duan }
422184f6026SChicago Duan 
startTimer(const std::chrono::microseconds & usec)423184f6026SChicago Duan int SoftPowerOff::startTimer(const std::chrono::microseconds& usec)
424184f6026SChicago Duan {
425184f6026SChicago Duan     return timer.start(usec);
426184f6026SChicago Duan }
427184f6026SChicago Duan } // namespace pldm
428