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