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 <systemd/sd-event.h>
17 #include <phosphor-logging/elog.hpp>
18 #include <phosphor-logging/elog-errors.hpp>
19 #include <xyz/openbmc_project/State/Host/error.hpp>
20 #include "softoff.hpp"
21 #include "config.h"
22 #include "timer.hpp"
23 
24 int main(int argc, char** argv)
25 {
26     using namespace phosphor::logging;
27 
28     // systemd event handler
29     sd_event* events = nullptr;
30 
31     // Get a handle to system dbus.
32     auto bus = sdbusplus::bus::new_default();
33 
34     // Add systemd object manager.
35     sdbusplus::server::manager::manager(bus, SOFTOFF_OBJPATH);
36 
37     // sd_event object. StateManager wants that this applicatin return '0'
38     // always.
39     auto r = sd_event_default(&events);
40     if (r < 0)
41     {
42         log<level::ERR>("Failure to create sd_event handler",
43                 entry("ERROR=%s", strerror(-r)));
44         return 0;
45     }
46 
47     // Attach the bus to sd_event to service user requests
48     bus.attach_event(events, SD_EVENT_PRIORITY_NORMAL);
49 
50     // Claim the bus. Delaying it until sending SMS_ATN may result
51     // in a race condition between this available and IPMI trying to send
52     // message as a reponse to ack from host.
53     bus.request_name(SOFTOFF_BUSNAME);
54 
55     // Create the SoftPowerOff object.
56     phosphor::ipmi::SoftPowerOff powerObj(bus, events, SOFTOFF_OBJPATH);
57 
58     // Wait for client requests until this application has processed
59     // at least one successful SoftPowerOff or we timed out
60     while(!powerObj.isCompleted() && !powerObj.isTimerExpired())
61     {
62         // -1 denotes wait for ever
63         r = sd_event_run(events, (uint64_t)-1);
64         if (r < 0)
65         {
66             log<level::ERR>("Failure in processing request",
67                     entry("ERROR=%s", strerror(-r)));
68             break;
69         }
70     }
71 
72     // Log an error if we timed out after getting Ack for SMS_ATN and before
73     // getting the Host Shutdown response
74     if(powerObj.isTimerExpired() && (powerObj.responseReceived() ==
75             phosphor::ipmi::Base::SoftPowerOff::HostResponse::SoftOffReceived))
76     {
77         try
78         {
79             elog<sdbusplus::xyz::openbmc_project::State
80                     ::Host::Error::SoftOffTimeout>(
81                  prev_entry<phosphor::logging::xyz::openbmc_project::State
82                     ::Host::SoftOffTimeout::TIMEOUT_IN_MSEC>());
83         }
84         catch (sdbusplus::xyz::openbmc_project::State::Host::Error
85                     ::SoftOffTimeout& elog)
86         {
87             commit(elog.name());
88         }
89     }
90 
91     // Cleanup the event handler
92     events = sd_event_unref(events);
93 
94     return 0;
95 }
96