blob: 3608002d35c2888d310785bc0d78423c69e50f75 [file] [log] [blame]
Chicago Duan184f6022020-04-17 11:30:49 +08001#include "softoff.hpp"
2
Dung Cao3d03f3f2023-09-07 06:51:33 +00003#include "common/instance_id.hpp"
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +10004#include "common/transport.hpp"
Chicago Duan184f6022020-04-17 11:30:49 +08005#include "common/utils.hpp"
6
George Liuc453e162022-12-21 17:16:23 +08007#include <libpldm/entity.h>
8#include <libpldm/platform.h>
George Liuc453e162022-12-21 17:16:23 +08009#include <libpldm/state_set.h>
10
Riya Dixit49cfb132023-03-02 04:26:53 -060011#include <phosphor-logging/lg2.hpp>
Chicago Duan184f6022020-04-17 11:30:49 +080012#include <sdbusplus/bus.hpp>
13#include <sdeventplus/clock.hpp>
George Liua2767e62021-02-24 18:53:34 +080014#include <sdeventplus/exception.hpp>
Chicago Duan184f6022020-04-17 11:30:49 +080015#include <sdeventplus/source/io.hpp>
16#include <sdeventplus/source/time.hpp>
17
18#include <array>
Sagar Srinivas4d99c312024-03-28 06:50:13 -050019#include <filesystem>
20#include <fstream>
Chicago Duan184f6022020-04-17 11:30:49 +080021
Riya Dixit49cfb132023-03-02 04:26:53 -060022PHOSPHOR_LOG2_USING;
23
Chicago Duan184f6022020-04-17 11:30:49 +080024namespace pldm
25{
Chicago Duan184f6022020-04-17 11:30:49 +080026using namespace sdeventplus;
27using namespace sdeventplus::source;
Sagar Srinivas4d99c312024-03-28 06:50:13 -050028namespace fs = std::filesystem;
Chicago Duan184f6022020-04-17 11:30:49 +080029constexpr auto clockId = sdeventplus::ClockId::RealTime;
30using Clock = Clock<clockId>;
31using Timer = Time<clockId>;
32
Zach Clarke98c51b2021-06-08 11:29:06 -050033using sdbusplus::exception::SdBusError;
34
35// Shutdown effecter terminus ID, set when we look up the effecter
36pldm::pdr::TerminusID TID = 0;
37
Chicago Duan184f6022020-04-17 11:30:49 +080038namespace sdbusRule = sdbusplus::bus::match::rules;
39
Manojkiran Eda3fcfaa12024-02-26 15:17:58 +053040SoftPowerOff::SoftPowerOff(sdbusplus::bus_t& bus, sd_event* event,
41 pldm::InstanceIdDb& instanceIdDb) :
Patrick Williams16c2a0a2024-08-16 15:20:59 -040042 bus(bus), timer(event), instanceIdDb(instanceIdDb)
Chicago Duan184f6022020-04-17 11:30:49 +080043{
Sagar Srinivas4d99c312024-03-28 06:50:13 -050044 auto jsonData = parseConfig();
45
46 if (jsonData.is_discarded())
47 {
Riya Dixit087a7512024-04-06 14:28:08 -050048 error("Failed to parse softoff config JSON file");
Sagar Srinivas4d99c312024-03-28 06:50:13 -050049 return;
50 }
51
Manojkiran Eda31a78442021-09-12 15:18:25 +053052 getHostState();
Chicago Duan184f6022020-04-17 11:30:49 +080053 if (hasError || completed)
54 {
55 return;
56 }
Sagar Srinivas4d99c312024-03-28 06:50:13 -050057 const std::vector<Json> emptyJsonList{};
58 auto entries = jsonData.value("entries", emptyJsonList);
59 for (const auto& entry : entries)
60 {
61 TID = entry.value("tid", 0);
62 pldm::pdr::EntityType entityType = entry.value("entityType", 0);
63 pldm::pdr::StateSetId stateSetId = entry.value("stateSetId", 0);
Chicago Duan184f6022020-04-17 11:30:49 +080064
Sagar Srinivas4d99c312024-03-28 06:50:13 -050065 bool effecterFound = getEffecterID(entityType, stateSetId);
66 if (effecterFound)
67 {
68 auto rc = getSensorInfo(entityType, stateSetId);
69 if (rc != PLDM_SUCCESS)
70 {
Riya Dixit087a7512024-04-06 14:28:08 -050071 error("Failed to get Sensor PDRs, response code '{RC}'", "RC",
Riya Dixit1e5c81e2024-05-03 07:54:00 -050072 lg2::hex, rc);
Sagar Srinivas4d99c312024-03-28 06:50:13 -050073 hasError = true;
74 return;
75 }
76 break;
77 }
78 else
79 {
80 continue;
81 }
Chicago Duan184f6022020-04-17 11:30:49 +080082 }
83
84 // Matches on the pldm StateSensorEvent signal
85 pldmEventSignal = std::make_unique<sdbusplus::bus::match_t>(
86 bus,
87 sdbusRule::type::signal() + sdbusRule::member("StateSensorEvent") +
88 sdbusRule::path("/xyz/openbmc_project/pldm") +
89 sdbusRule::interface("xyz.openbmc_project.PLDM.Event"),
90 std::bind(std::mem_fn(&SoftPowerOff::hostSoftOffComplete), this,
91 std::placeholders::_1));
92}
93
94int SoftPowerOff::getHostState()
95{
96 try
97 {
98 pldm::utils::PropertyValue propertyValue =
99 pldm::utils::DBusHandler().getDbusPropertyVariant(
100 "/xyz/openbmc_project/state/host0", "CurrentHostState",
101 "xyz.openbmc_project.State.Host");
102
Andrew Geissler5b5fa432021-01-22 16:27:24 -0600103 if ((std::get<std::string>(propertyValue) !=
104 "xyz.openbmc_project.State.Host.HostState.Running") &&
105 (std::get<std::string>(propertyValue) !=
106 "xyz.openbmc_project.State.Host.HostState.TransitioningToOff"))
Chicago Duan184f6022020-04-17 11:30:49 +0800107 {
108 // Host state is not "Running", this app should return success
109 completed = true;
110 return PLDM_SUCCESS;
111 }
112 }
113 catch (const std::exception& e)
114 {
Riya Dixit087a7512024-04-06 14:28:08 -0500115 error(
116 "PLDM remote terminus soft off. Can't get current remote terminus state, error - {ERROR}",
117 "ERROR", e);
Chicago Duan184f6022020-04-17 11:30:49 +0800118 hasError = true;
119 return PLDM_ERROR;
120 }
121
122 return PLDM_SUCCESS;
123}
124
Patrick Williams84b790c2022-07-22 19:26:56 -0500125void SoftPowerOff::hostSoftOffComplete(sdbusplus::message_t& msg)
Chicago Duan184f6022020-04-17 11:30:49 +0800126{
127 pldm::pdr::TerminusID msgTID;
128 pldm::pdr::SensorID msgSensorID;
129 pldm::pdr::SensorOffset msgSensorOffset;
130 pldm::pdr::EventState msgEventState;
131 pldm::pdr::EventState msgPreviousEventState;
132
133 // Read the msg and populate each variable
134 msg.read(msgTID, msgSensorID, msgSensorOffset, msgEventState,
135 msgPreviousEventState);
136
137 if (msgSensorID == sensorID && msgSensorOffset == sensorOffset &&
Zach Clarke98c51b2021-06-08 11:29:06 -0500138 msgEventState == PLDM_SW_TERM_GRACEFUL_SHUTDOWN && msgTID == TID)
Chicago Duan184f6022020-04-17 11:30:49 +0800139 {
140 // Receive Graceful shutdown completion event message. Disable the timer
141 auto rc = timer.stop();
142 if (rc < 0)
143 {
Riya Dixit087a7512024-04-06 14:28:08 -0500144 error(
145 "Failure to STOP the timer of PLDM soft off, response code '{RC}'",
146 "RC", rc);
Chicago Duan184f6022020-04-17 11:30:49 +0800147 }
148
149 // This marks the completion of pldm soft power off.
150 completed = true;
151 }
152}
153
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500154Json SoftPowerOff::parseConfig()
155{
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400156 fs::path softoffConfigJson(
157 fs::path(SOFTOFF_CONFIG_JSON) / "softoff_config.json");
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500158
159 if (!fs::exists(softoffConfigJson) || fs::is_empty(softoffConfigJson))
160 {
Riya Dixit087a7512024-04-06 14:28:08 -0500161 error(
162 "Failed to parse softoff config JSON file '{PATH}', file does not exist",
163 "PATH", softoffConfigJson);
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500164 return PLDM_ERROR;
165 }
166
167 std::ifstream jsonFile(softoffConfigJson);
168 return Json::parse(jsonFile);
169}
170
171bool SoftPowerOff::getEffecterID(pldm::pdr::EntityType& entityType,
172 pldm::pdr::StateSetId& stateSetId)
Chicago Duan184f6022020-04-17 11:30:49 +0800173{
174 auto& bus = pldm::utils::DBusHandler::getBus();
Chicago Duan184f6022020-04-17 11:30:49 +0800175 try
176 {
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500177 std::vector<std::vector<uint8_t>> response{};
178 auto method = bus.new_method_call(
Chicago Duan184f6022020-04-17 11:30:49 +0800179 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
180 "xyz.openbmc_project.PLDM.PDR", "FindStateEffecterPDR");
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500181 method.append(TID, entityType, stateSetId);
182 auto responseMsg = bus.call(method, dbusTimeout);
Chicago Duan184f6022020-04-17 11:30:49 +0800183
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500184 responseMsg.read(response);
185 if (response.size())
Chicago Duan184f6022020-04-17 11:30:49 +0800186 {
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500187 for (auto& rep : response)
Chicago Duan184f6022020-04-17 11:30:49 +0800188 {
Pavithra Barithaya3c8b3e32025-01-30 10:45:51 +0530189 auto softoffPdr = new (rep.data()) pldm_state_effecter_pdr;
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500190 effecterID = softoffPdr->effecter_id;
Chicago Duan184f6022020-04-17 11:30:49 +0800191 }
192 }
193 else
194 {
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500195 return false;
Chicago Duan184f6022020-04-17 11:30:49 +0800196 }
197 }
Patrick Williams84b790c2022-07-22 19:26:56 -0500198 catch (const sdbusplus::exception_t& e)
Chicago Duan184f6022020-04-17 11:30:49 +0800199 {
Riya Dixit087a7512024-04-06 14:28:08 -0500200 error("Failed to get softPowerOff PDR, error - {ERROR}", "ERROR", e);
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500201 return false;
Chicago Duan184f6022020-04-17 11:30:49 +0800202 }
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500203 return true;
Chicago Duan184f6022020-04-17 11:30:49 +0800204}
205
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500206int SoftPowerOff::getSensorInfo(pldm::pdr::EntityType& entityType,
207 pldm::pdr::StateSetId& stateSetId)
Chicago Duan184f6022020-04-17 11:30:49 +0800208{
Chicago Duan184f6022020-04-17 11:30:49 +0800209 try
210 {
211 auto& bus = pldm::utils::DBusHandler::getBus();
212 std::vector<std::vector<uint8_t>> Response{};
213 auto method = bus.new_method_call(
214 "xyz.openbmc_project.PLDM", "/xyz/openbmc_project/pldm",
215 "xyz.openbmc_project.PLDM.PDR", "FindStateSensorPDR");
Sagar Srinivas4d99c312024-03-28 06:50:13 -0500216 method.append(TID, entityType, stateSetId);
Chicago Duan184f6022020-04-17 11:30:49 +0800217
vkaverap@in.ibm.com91a092f2023-09-18 23:39:44 -0500218 auto ResponseMsg = bus.call(method, dbusTimeout);
Chicago Duan184f6022020-04-17 11:30:49 +0800219
220 ResponseMsg.read(Response);
221
222 if (Response.size() == 0)
223 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600224 error("No sensor PDR has been found that matches the criteria");
Chicago Duan184f6022020-04-17 11:30:49 +0800225 return PLDM_ERROR;
226 }
227
ThuBaNguyen499a29d2023-05-30 06:32:06 +0700228 pldm_state_sensor_pdr* pdr = nullptr;
Chicago Duan184f6022020-04-17 11:30:49 +0800229 for (auto& rep : Response)
230 {
Pavithra Barithaya3c8b3e32025-01-30 10:45:51 +0530231 pdr = new (rep.data()) pldm_state_sensor_pdr;
Manojkiran Eda31a78442021-09-12 15:18:25 +0530232 if (!pdr)
233 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600234 error("Failed to get state sensor PDR.");
Manojkiran Eda31a78442021-09-12 15:18:25 +0530235 return PLDM_ERROR;
236 }
Manojkiran Edabcf91ac2021-03-14 13:50:48 +0530237 }
238
Chicago Duan184f6022020-04-17 11:30:49 +0800239 sensorID = pdr->sensor_id;
240
241 auto compositeSensorCount = pdr->composite_sensor_count;
242 auto possibleStatesStart = pdr->possible_states;
243
244 for (auto offset = 0; offset < compositeSensorCount; offset++)
245 {
Pavithra Barithaya3c8b3e32025-01-30 10:45:51 +0530246 auto possibleStates = new (possibleStatesStart)
247 state_sensor_possible_states;
Chicago Duan184f6022020-04-17 11:30:49 +0800248 auto setId = possibleStates->state_set_id;
249 auto possibleStateSize = possibleStates->possible_states_size;
250
251 if (setId == PLDM_STATE_SET_SW_TERMINATION_STATUS)
252 {
253 sensorOffset = offset;
254 break;
255 }
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400256 possibleStatesStart +=
257 possibleStateSize + sizeof(setId) + sizeof(possibleStateSize);
Chicago Duan184f6022020-04-17 11:30:49 +0800258 }
259 }
Patrick Williams84b790c2022-07-22 19:26:56 -0500260 catch (const sdbusplus::exception_t& e)
Chicago Duan184f6022020-04-17 11:30:49 +0800261 {
Riya Dixit087a7512024-04-06 14:28:08 -0500262 error("Failed to get state sensor PDR during soft-off, error - {ERROR}",
263 "ERROR", e);
Chicago Duan184f6022020-04-17 11:30:49 +0800264 return PLDM_ERROR;
265 }
266
267 return PLDM_SUCCESS;
268}
269
270int SoftPowerOff::hostSoftOff(sdeventplus::Event& event)
271{
272 constexpr uint8_t effecterCount = 1;
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +1000273 PldmTransport pldmTransport{};
Chicago Duan184f6022020-04-17 11:30:49 +0800274 uint8_t instanceID;
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +1000275 uint8_t mctpEID;
Chicago Duan184f6022020-04-17 11:30:49 +0800276
277 mctpEID = pldm::utils::readHostEID();
Dung Cao3d03f3f2023-09-07 06:51:33 +0000278 // TODO: fix mapping to work around OpenBMC ecosystem deficiencies
279 pldm_tid_t pldmTID = static_cast<pldm_tid_t>(mctpEID);
Chicago Duan184f6022020-04-17 11:30:49 +0800280
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400281 std::array<uint8_t,
282 sizeof(pldm_msg_hdr) + sizeof(effecterID) +
283 sizeof(effecterCount) + sizeof(set_effecter_state_field)>
Chicago Duan184f6022020-04-17 11:30:49 +0800284 requestMsg{};
Pavithra Barithaya3c8b3e32025-01-30 10:45:51 +0530285 auto request = new (requestMsg.data()) pldm_msg;
Chicago Duan184f6022020-04-17 11:30:49 +0800286 set_effecter_state_field stateField{
287 PLDM_REQUEST_SET, PLDM_SW_TERM_GRACEFUL_SHUTDOWN_REQUESTED};
Dung Cao3d03f3f2023-09-07 06:51:33 +0000288 instanceID = instanceIdDb.next(pldmTID);
Chicago Duan184f6022020-04-17 11:30:49 +0800289 auto rc = encode_set_state_effecter_states_req(
290 instanceID, effecterID, effecterCount, &stateField, request);
291 if (rc != PLDM_SUCCESS)
292 {
Dung Cao3d03f3f2023-09-07 06:51:33 +0000293 instanceIdDb.free(pldmTID, instanceID);
Riya Dixit087a7512024-04-06 14:28:08 -0500294 error(
295 "Failed to encode set state effecter states request message, response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500296 "RC", lg2::hex, rc);
Chicago Duan184f6022020-04-17 11:30:49 +0800297 return PLDM_ERROR;
298 }
299
Chicago Duan184f6022020-04-17 11:30:49 +0800300 // Add a timer to the event loop, default 30s.
Patrick Williamsa6756622023-10-20 11:19:15 -0500301 auto timerCallback = [=, this](Timer& /*source*/,
302 Timer::TimePoint /*time*/) mutable {
Chicago Duan184f6022020-04-17 11:30:49 +0800303 if (!responseReceived)
304 {
Dung Cao3d03f3f2023-09-07 06:51:33 +0000305 instanceIdDb.free(pldmTID, instanceID);
Riya Dixit49cfb132023-03-02 04:26:53 -0600306 error(
Riya Dixit087a7512024-04-06 14:28:08 -0500307 "PLDM soft off failed, can't get the response for the PLDM request msg. Time out! Exit the pldm-softpoweroff");
Chicago Duan184f6022020-04-17 11:30:49 +0800308 exit(-1);
309 }
310 return;
311 };
312 Timer time(event, (Clock(event).now() + std::chrono::seconds{30}),
313 std::chrono::seconds{1}, std::move(timerCallback));
314
315 // Add a callback to handle EPOLLIN on fd
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400316 auto callback = [=, &pldmTransport,
317 this](IO& io, int fd, uint32_t revents) mutable {
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +1000318 if (fd != pldmTransport.getEventSource())
319 {
320 return;
321 }
322
Chicago Duan184f6022020-04-17 11:30:49 +0800323 if (!(revents & EPOLLIN))
324 {
325 return;
326 }
327
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +1000328 void* responseMsg = nullptr;
Chicago Duan184f6022020-04-17 11:30:49 +0800329 size_t responseMsgSize{};
Dung Cao3d03f3f2023-09-07 06:51:33 +0000330 pldm_tid_t srcTID = pldmTID;
Chicago Duan184f6022020-04-17 11:30:49 +0800331
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +1000332 auto rc = pldmTransport.recvMsg(pldmTID, responseMsg, responseMsgSize);
Chicago Duan184f6022020-04-17 11:30:49 +0800333 if (rc)
334 {
Riya Dixit087a7512024-04-06 14:28:08 -0500335 error(
336 "Failed to receive pldm data during soft-off, response code '{RC}'",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500337 "RC", rc);
Chicago Duan184f6022020-04-17 11:30:49 +0800338 return;
339 }
340
Patrick Williams16c2a0a2024-08-16 15:20:59 -0400341 std::unique_ptr<void, decltype(std::free)*> responseMsgPtr{
342 responseMsg, std::free};
Chicago Duan184f6022020-04-17 11:30:49 +0800343
344 // We've got the response meant for the PLDM request msg that was
345 // sent out
346 io.set_enabled(Enabled::Off);
Pavithra Barithaya3c8b3e32025-01-30 10:45:51 +0530347 auto response = new (responseMsgPtr.get()) pldm_msg;
Dung Cao3d03f3f2023-09-07 06:51:33 +0000348
349 if (srcTID != pldmTID ||
350 !pldm_msg_hdr_correlate_response(&request->hdr, &response->hdr))
351 {
352 /* This isn't the response we were looking for */
353 return;
354 }
355
356 /* We have the right response, release the instance ID and process */
357 io.set_enabled(Enabled::Off);
358 instanceIdDb.free(pldmTID, instanceID);
359
George Liu9915d022021-12-21 14:04:31 +0800360 if (response->payload[0] != PLDM_SUCCESS)
361 {
Riya Dixit087a7512024-04-06 14:28:08 -0500362 error("Getting the wrong response, response code '{RC}'", "RC",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500363 response->payload[0]);
George Liu9915d022021-12-21 14:04:31 +0800364 exit(-1);
365 }
Chicago Duan184f6022020-04-17 11:30:49 +0800366
367 responseReceived = true;
368
369 // Start Timer
370 using namespace std::chrono;
371 auto timeMicroseconds =
372 duration_cast<microseconds>(seconds(SOFTOFF_TIMEOUT_SECONDS));
373
374 auto ret = startTimer(timeMicroseconds);
375 if (ret < 0)
376 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600377 error(
Riya Dixit087a7512024-04-06 14:28:08 -0500378 "Failure to start remote terminus soft off wait timer, Exit the pldm-softpoweroff with response code:{NUM}",
379 "NUM", ret);
Chicago Duan184f6022020-04-17 11:30:49 +0800380 exit(-1);
381 }
382 else
383 {
Riya Dixit49cfb132023-03-02 04:26:53 -0600384 error(
Riya Dixit087a7512024-04-06 14:28:08 -0500385 "Timer started waiting for remote terminus soft off, timeout in sec '{TIMEOUT_SEC}'",
Riya Dixit49cfb132023-03-02 04:26:53 -0600386 "TIMEOUT_SEC", SOFTOFF_TIMEOUT_SECONDS);
Chicago Duan184f6022020-04-17 11:30:49 +0800387 }
388 return;
389 };
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +1000390 IO io(event, pldmTransport.getEventSource(), EPOLLIN, std::move(callback));
Chicago Duan184f6022020-04-17 11:30:49 +0800391
Rashmica Gupta1ed5f7a2023-05-22 13:56:42 +1000392 // Asynchronously send the PLDM request
393 rc = pldmTransport.sendMsg(pldmTID, requestMsg.data(), requestMsg.size());
Sampa Misra9f8d2b02021-03-24 08:33:14 +0000394 if (0 > rc)
Chicago Duan184f6022020-04-17 11:30:49 +0800395 {
Dung Cao3d03f3f2023-09-07 06:51:33 +0000396 instanceIdDb.free(pldmTID, instanceID);
Riya Dixit49cfb132023-03-02 04:26:53 -0600397 error(
Riya Dixit087a7512024-04-06 14:28:08 -0500398 "Failed to send message/receive response, response code '{RC}' and error - {ERROR}",
Riya Dixit1e5c81e2024-05-03 07:54:00 -0500399 "RC", rc, "ERROR", errno);
Chicago Duan184f6022020-04-17 11:30:49 +0800400 return PLDM_ERROR;
401 }
402
403 // Time out or soft off complete
404 while (!isCompleted() && !isTimerExpired())
405 {
406 try
407 {
408 event.run(std::nullopt);
409 }
410 catch (const sdeventplus::SdEventError& e)
411 {
Dung Cao3d03f3f2023-09-07 06:51:33 +0000412 instanceIdDb.free(pldmTID, instanceID);
Riya Dixit49cfb132023-03-02 04:26:53 -0600413 error(
Riya Dixit087a7512024-04-06 14:28:08 -0500414 "Failed to process request while remote terminus soft off, error - {ERROR}",
415 "ERROR", e);
Chicago Duan184f6022020-04-17 11:30:49 +0800416 return PLDM_ERROR;
417 }
418 }
419
420 return PLDM_SUCCESS;
421}
422
423int SoftPowerOff::startTimer(const std::chrono::microseconds& usec)
424{
425 return timer.start(usec);
426}
427} // namespace pldm