1 /**
2  * Copyright © 2016 IBM Corporation
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *     http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 #include "config.h"
17 
18 #include "softoff.hpp"
19 
20 #include <systemd/sd-event.h>
21 
22 #include <phosphor-logging/elog-errors.hpp>
23 #include <phosphor-logging/elog.hpp>
24 #include <sdbusplus/timer.hpp>
25 #include <xyz/openbmc_project/State/Host/error.hpp>
26 
27 // Return -1 on any errors to ensure we follow the calling targets OnFailure=
28 // path
29 int main(int argc, char** argv)
30 {
31     using namespace phosphor::logging;
32 
33     // systemd event handler
34     sd_event* events = nullptr;
35 
36     // Get a handle to system dbus.
37     auto bus = sdbusplus::bus::new_default();
38 
39     // Add systemd object manager.
40     sdbusplus::server::manager::manager(bus, SOFTOFF_OBJPATH);
41 
42     // sd_event object
43     auto r = sd_event_default(&events);
44     if (r < 0)
45     {
46         log<level::ERR>("Failure to create sd_event handler",
47                         entry("ERRNO=0x%X", -r));
48         return -1;
49     }
50 
51     // Attach the bus to sd_event to service user requests
52     bus.attach_event(events, SD_EVENT_PRIORITY_NORMAL);
53 
54     // Claim the bus. Delaying it until sending SMS_ATN may result
55     // in a race condition between this available and IPMI trying to send
56     // message as a response to ack from host.
57     bus.request_name(SOFTOFF_BUSNAME);
58 
59     // Create the SoftPowerOff object.
60     phosphor::ipmi::SoftPowerOff powerObj(bus, events, SOFTOFF_OBJPATH);
61 
62     // Wait for client requests until this application has processed
63     // at least one successful SoftPowerOff or we timed out
64     while (!powerObj.isCompleted() && !powerObj.isTimerExpired())
65     {
66         // -1 denotes wait for ever
67         r = sd_event_run(events, (uint64_t)-1);
68         if (r < 0)
69         {
70             log<level::ERR>("Failure in processing request",
71                             entry("ERRNO=0x%X", -r));
72             return -1;
73         }
74     }
75 
76     // Log an error if we timed out after getting Ack for SMS_ATN and before
77     // getting the Host Shutdown response
78     if (powerObj.isTimerExpired() &&
79         (powerObj.responseReceived() ==
80          phosphor::ipmi::Base::SoftPowerOff::HostResponse::SoftOffReceived))
81     {
82         using error =
83             sdbusplus::xyz::openbmc_project::State::Host::Error::SoftOffTimeout;
84         using errorMetadata = xyz::openbmc_project::State::Host::SoftOffTimeout;
85         report<error>(prev_entry<errorMetadata::TIMEOUT_IN_MSEC>());
86         return -1;
87     }
88 
89     // Cleanup the event handler
90     events = sd_event_unref(events);
91 
92     return 0;
93 }
94