xref: /openbmc/google-ipmi-sys/psu.cpp (revision 4d49ae6556305bdb33933ec9236c8d87284fb8e6)
1*4d49ae65SPatrick Venture /*
2*4d49ae65SPatrick Venture  * Copyright 2018 Google Inc.
3*4d49ae65SPatrick Venture  *
4*4d49ae65SPatrick Venture  * Licensed under the Apache License, Version 2.0 (the "License");
5*4d49ae65SPatrick Venture  * you may not use this file except in compliance with the License.
6*4d49ae65SPatrick Venture  * You may obtain a copy of the License at
7*4d49ae65SPatrick Venture  *
8*4d49ae65SPatrick Venture  *     http://www.apache.org/licenses/LICENSE-2.0
9*4d49ae65SPatrick Venture  *
10*4d49ae65SPatrick Venture  * Unless required by applicable law or agreed to in writing, software
11*4d49ae65SPatrick Venture  * distributed under the License is distributed on an "AS IS" BASIS,
12*4d49ae65SPatrick Venture  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*4d49ae65SPatrick Venture  * See the License for the specific language governing permissions and
14*4d49ae65SPatrick Venture  * limitations under the License.
15*4d49ae65SPatrick Venture  */
16*4d49ae65SPatrick Venture 
17*4d49ae65SPatrick Venture #include "psu.hpp"
18*4d49ae65SPatrick Venture 
19*4d49ae65SPatrick Venture #include "main.hpp"
20*4d49ae65SPatrick Venture 
21*4d49ae65SPatrick Venture #include <cstdint>
22*4d49ae65SPatrick Venture #include <fstream>
23*4d49ae65SPatrick Venture #include <phosphor-logging/log.hpp>
24*4d49ae65SPatrick Venture #include <sdbusplus/bus.hpp>
25*4d49ae65SPatrick Venture 
26*4d49ae65SPatrick Venture namespace google
27*4d49ae65SPatrick Venture {
28*4d49ae65SPatrick Venture namespace ipmi
29*4d49ae65SPatrick Venture {
30*4d49ae65SPatrick Venture 
31*4d49ae65SPatrick Venture using namespace phosphor::logging;
32*4d49ae65SPatrick Venture 
33*4d49ae65SPatrick Venture struct PsuResetRequest
34*4d49ae65SPatrick Venture {
35*4d49ae65SPatrick Venture     uint8_t subcommand;
36*4d49ae65SPatrick Venture     // Delay in seconds.
37*4d49ae65SPatrick Venture     uint32_t delay;
38*4d49ae65SPatrick Venture } __attribute__((packed));
39*4d49ae65SPatrick Venture 
40*4d49ae65SPatrick Venture static constexpr auto TIME_DELAY_FILENAME = "/run/psu_timedelay";
41*4d49ae65SPatrick Venture static constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1";
42*4d49ae65SPatrick Venture static constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1";
43*4d49ae65SPatrick Venture static constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager";
44*4d49ae65SPatrick Venture static constexpr auto PSU_HARDRESET_TARGET = "gbmc-psu-hardreset.target";
45*4d49ae65SPatrick Venture 
46*4d49ae65SPatrick Venture ipmi_ret_t PsuHardReset(const uint8_t* reqBuf, uint8_t* replyBuf,
47*4d49ae65SPatrick Venture                         size_t* dataLen)
48*4d49ae65SPatrick Venture {
49*4d49ae65SPatrick Venture     if ((*dataLen) < sizeof(struct PsuResetRequest))
50*4d49ae65SPatrick Venture     {
51*4d49ae65SPatrick Venture         fprintf(stderr, "Invalid command length: %lu\n", (*dataLen));
52*4d49ae65SPatrick Venture         return IPMI_CC_INVALID;
53*4d49ae65SPatrick Venture     }
54*4d49ae65SPatrick Venture 
55*4d49ae65SPatrick Venture     struct PsuResetRequest request;
56*4d49ae65SPatrick Venture     memcpy(&request, &reqBuf[0], sizeof(struct PsuResetRequest));
57*4d49ae65SPatrick Venture 
58*4d49ae65SPatrick Venture     std::ofstream ofs;
59*4d49ae65SPatrick Venture     ofs.open(TIME_DELAY_FILENAME, std::ofstream::out);
60*4d49ae65SPatrick Venture     if (!ofs.good())
61*4d49ae65SPatrick Venture     {
62*4d49ae65SPatrick Venture         fprintf(stderr, "Unable to open file for output.\n");
63*4d49ae65SPatrick Venture         return IPMI_CC_INVALID;
64*4d49ae65SPatrick Venture     }
65*4d49ae65SPatrick Venture 
66*4d49ae65SPatrick Venture     ofs << "PSU_HARDRESET_DELAY=" << request.delay << std::endl;
67*4d49ae65SPatrick Venture     if (ofs.fail())
68*4d49ae65SPatrick Venture     {
69*4d49ae65SPatrick Venture         fprintf(stderr, "Write failed\n");
70*4d49ae65SPatrick Venture         ofs.close();
71*4d49ae65SPatrick Venture         return IPMI_CC_INVALID;
72*4d49ae65SPatrick Venture     }
73*4d49ae65SPatrick Venture 
74*4d49ae65SPatrick Venture     // Write succeeded, please continue.
75*4d49ae65SPatrick Venture     ofs.flush();
76*4d49ae65SPatrick Venture     ofs.close();
77*4d49ae65SPatrick Venture 
78*4d49ae65SPatrick Venture     auto bus = sdbusplus::bus::new_default();
79*4d49ae65SPatrick Venture     auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT,
80*4d49ae65SPatrick Venture                                       SYSTEMD_INTERFACE, "StartUnit");
81*4d49ae65SPatrick Venture 
82*4d49ae65SPatrick Venture     method.append(PSU_HARDRESET_TARGET);
83*4d49ae65SPatrick Venture     method.append("replace");
84*4d49ae65SPatrick Venture 
85*4d49ae65SPatrick Venture     try
86*4d49ae65SPatrick Venture     {
87*4d49ae65SPatrick Venture         bus.call_noreply(method);
88*4d49ae65SPatrick Venture     }
89*4d49ae65SPatrick Venture     catch (const sdbusplus::exception::SdBusError& ex)
90*4d49ae65SPatrick Venture     {
91*4d49ae65SPatrick Venture         log<level::ERR>("Failed to call PSU hard reset");
92*4d49ae65SPatrick Venture         return IPMI_CC_INVALID;
93*4d49ae65SPatrick Venture     }
94*4d49ae65SPatrick Venture 
95*4d49ae65SPatrick Venture     replyBuf[0] = SysPsuHardReset;
96*4d49ae65SPatrick Venture     (*dataLen) = sizeof(uint8_t);
97*4d49ae65SPatrick Venture 
98*4d49ae65SPatrick Venture     return IPMI_CC_OK;
99*4d49ae65SPatrick Venture }
100*4d49ae65SPatrick Venture 
101*4d49ae65SPatrick Venture } // namespace ipmi
102*4d49ae65SPatrick Venture } // namespace google
103