1f085d91dSPatrick Venture /* 2f085d91dSPatrick Venture * Copyright 2019 Google Inc. 3f085d91dSPatrick Venture * 4f085d91dSPatrick Venture * Licensed under the Apache License, Version 2.0 (the "License"); 5f085d91dSPatrick Venture * you may not use this file except in compliance with the License. 6f085d91dSPatrick Venture * You may obtain a copy of the License at 7f085d91dSPatrick Venture * 8f085d91dSPatrick Venture * http://www.apache.org/licenses/LICENSE-2.0 9f085d91dSPatrick Venture * 10f085d91dSPatrick Venture * Unless required by applicable law or agreed to in writing, software 11f085d91dSPatrick Venture * distributed under the License is distributed on an "AS IS" BASIS, 12f085d91dSPatrick Venture * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13f085d91dSPatrick Venture * See the License for the specific language governing permissions and 14f085d91dSPatrick Venture * limitations under the License. 15f085d91dSPatrick Venture */ 16f085d91dSPatrick Venture 17f085d91dSPatrick Venture #include "handler.hpp" 18f085d91dSPatrick Venture 19d2037c6aSPatrick Venture #include "errors.hpp" 20d2037c6aSPatrick Venture 21d2037c6aSPatrick Venture #include <ipmid/api.h> 22d2037c6aSPatrick Venture 23bb90d4fdSPatrick Venture #include <cinttypes> 24d2037c6aSPatrick Venture #include <cstdio> 25d2037c6aSPatrick Venture #include <filesystem> 26d2037c6aSPatrick Venture #include <fstream> 27*aa374120SPatrick Venture #include <phosphor-logging/log.hpp> 28*aa374120SPatrick Venture #include <sdbusplus/bus.hpp> 29d2037c6aSPatrick Venture #include <sstream> 30d2037c6aSPatrick Venture #include <string> 31d2037c6aSPatrick Venture #include <tuple> 32d2037c6aSPatrick Venture 33f085d91dSPatrick Venture // The phosphor-host-ipmi daemon requires a configuration that maps 34f085d91dSPatrick Venture // the if_name to the IPMI LAN channel. However, that doesn't strictly 35f085d91dSPatrick Venture // define which is meant to be used for NCSI. 36f085d91dSPatrick Venture #ifndef NCSI_IPMI_CHANNEL 37f085d91dSPatrick Venture #define NCSI_IPMI_CHANNEL 1 38f085d91dSPatrick Venture #endif 39f085d91dSPatrick Venture 40f085d91dSPatrick Venture #ifndef NCSI_IF_NAME 41f085d91dSPatrick Venture #define NCSI_IF_NAME eth0 42f085d91dSPatrick Venture #endif 43f085d91dSPatrick Venture 44f085d91dSPatrick Venture // To deal with receiving a string without quotes. 45f085d91dSPatrick Venture #define QUOTE(name) #name 46f085d91dSPatrick Venture #define STR(macro) QUOTE(macro) 47f085d91dSPatrick Venture #define NCSI_IF_NAME_STR STR(NCSI_IF_NAME) 48f085d91dSPatrick Venture 49f085d91dSPatrick Venture namespace google 50f085d91dSPatrick Venture { 51f085d91dSPatrick Venture namespace ipmi 52f085d91dSPatrick Venture { 53d2037c6aSPatrick Venture namespace fs = std::filesystem; 54f085d91dSPatrick Venture 55f085d91dSPatrick Venture std::tuple<std::uint8_t, std::string> Handler::getEthDetails() const 56f085d91dSPatrick Venture { 57f085d91dSPatrick Venture return std::make_tuple(NCSI_IPMI_CHANNEL, NCSI_IF_NAME_STR); 58f085d91dSPatrick Venture } 59f085d91dSPatrick Venture 60d2037c6aSPatrick Venture std::int64_t Handler::getRxPackets(const std::string& name) const 61d2037c6aSPatrick Venture { 62d2037c6aSPatrick Venture std::ostringstream opath; 63d2037c6aSPatrick Venture opath << "/sys/class/net/" << name << "/statistics/rx_packets"; 64d2037c6aSPatrick Venture std::string path = opath.str(); 65d2037c6aSPatrick Venture 66d2037c6aSPatrick Venture // Minor sanity & security check (of course, I'm less certain if unicode 67d2037c6aSPatrick Venture // comes into play here. 68d2037c6aSPatrick Venture // 69d2037c6aSPatrick Venture // Basically you can't easily inject ../ or /../ into the path below. 70d2037c6aSPatrick Venture if (name.find("/") != std::string::npos) 71d2037c6aSPatrick Venture { 72d2037c6aSPatrick Venture std::fprintf(stderr, "Invalid or illegal name: '%s'\n", name.c_str()); 73d2037c6aSPatrick Venture throw IpmiException(IPMI_CC_INVALID_FIELD_REQUEST); 74d2037c6aSPatrick Venture } 75d2037c6aSPatrick Venture 76d2037c6aSPatrick Venture std::error_code ec; 77d2037c6aSPatrick Venture if (!fs::exists(path, ec)) 78d2037c6aSPatrick Venture { 79d2037c6aSPatrick Venture std::fprintf(stderr, "Path: '%s' doesn't exist.\n", path.c_str()); 80d2037c6aSPatrick Venture throw IpmiException(IPMI_CC_INVALID_FIELD_REQUEST); 81d2037c6aSPatrick Venture } 82d2037c6aSPatrick Venture // We're uninterested in the state of ec. 83d2037c6aSPatrick Venture 84d2037c6aSPatrick Venture int64_t count = 0; 85d2037c6aSPatrick Venture std::ifstream ifs; 86d2037c6aSPatrick Venture ifs.exceptions(std::ifstream::failbit); 87d2037c6aSPatrick Venture try 88d2037c6aSPatrick Venture { 89d2037c6aSPatrick Venture ifs.open(path); 90d2037c6aSPatrick Venture ifs >> count; 91d2037c6aSPatrick Venture } 92d2037c6aSPatrick Venture catch (std::ios_base::failure& fail) 93d2037c6aSPatrick Venture { 94d2037c6aSPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 95d2037c6aSPatrick Venture } 96d2037c6aSPatrick Venture 97d2037c6aSPatrick Venture return count; 98d2037c6aSPatrick Venture } 99d2037c6aSPatrick Venture 100bb90d4fdSPatrick Venture VersionTuple Handler::getCpldVersion(unsigned int id) const 101bb90d4fdSPatrick Venture { 102bb90d4fdSPatrick Venture std::ostringstream opath; 103bb90d4fdSPatrick Venture opath << "/run/cpld" << id << ".version"; 104bb90d4fdSPatrick Venture // Check for file 105bb90d4fdSPatrick Venture 106bb90d4fdSPatrick Venture std::error_code ec; 107bb90d4fdSPatrick Venture if (!fs::exists(opath.str(), ec)) 108bb90d4fdSPatrick Venture { 109bb90d4fdSPatrick Venture std::fprintf(stderr, "Path: '%s' doesn't exist.\n", 110bb90d4fdSPatrick Venture opath.str().c_str()); 111bb90d4fdSPatrick Venture throw IpmiException(IPMI_CC_INVALID_FIELD_REQUEST); 112bb90d4fdSPatrick Venture } 113bb90d4fdSPatrick Venture // We're uninterested in the state of ec. 114bb90d4fdSPatrick Venture 115bb90d4fdSPatrick Venture // If file exists, read. 116bb90d4fdSPatrick Venture std::ifstream ifs; 117bb90d4fdSPatrick Venture ifs.exceptions(std::ifstream::failbit); 118bb90d4fdSPatrick Venture std::string value; 119bb90d4fdSPatrick Venture try 120bb90d4fdSPatrick Venture { 121bb90d4fdSPatrick Venture ifs.open(opath.str()); 122bb90d4fdSPatrick Venture ifs >> value; 123bb90d4fdSPatrick Venture } 124bb90d4fdSPatrick Venture catch (std::ios_base::failure& fail) 125bb90d4fdSPatrick Venture { 126bb90d4fdSPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 127bb90d4fdSPatrick Venture } 128bb90d4fdSPatrick Venture 129bb90d4fdSPatrick Venture // If value parses as expected, return version. 130bb90d4fdSPatrick Venture VersionTuple version = std::make_tuple(0, 0, 0, 0); 131bb90d4fdSPatrick Venture 132bb90d4fdSPatrick Venture int num_fields = 133bb90d4fdSPatrick Venture std::sscanf(value.c_str(), "%" SCNu8 ".%" SCNu8 ".%" SCNu8 ".%" SCNu8, 134bb90d4fdSPatrick Venture &std::get<0>(version), &std::get<1>(version), 135bb90d4fdSPatrick Venture &std::get<2>(version), &std::get<3>(version)); 136bb90d4fdSPatrick Venture if (num_fields == 0) 137bb90d4fdSPatrick Venture { 138bb90d4fdSPatrick Venture std::fprintf(stderr, "Invalid version.\n"); 139bb90d4fdSPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 140bb90d4fdSPatrick Venture } 141bb90d4fdSPatrick Venture 142bb90d4fdSPatrick Venture return version; 143bb90d4fdSPatrick Venture } 144bb90d4fdSPatrick Venture 145*aa374120SPatrick Venture static constexpr auto TIME_DELAY_FILENAME = "/run/psu_timedelay"; 146*aa374120SPatrick Venture static constexpr auto SYSTEMD_SERVICE = "org.freedesktop.systemd1"; 147*aa374120SPatrick Venture static constexpr auto SYSTEMD_ROOT = "/org/freedesktop/systemd1"; 148*aa374120SPatrick Venture static constexpr auto SYSTEMD_INTERFACE = "org.freedesktop.systemd1.Manager"; 149*aa374120SPatrick Venture static constexpr auto PSU_HARDRESET_TARGET = "gbmc-psu-hardreset.target"; 150*aa374120SPatrick Venture 151*aa374120SPatrick Venture void Handler::psuResetDelay(std::uint32_t delay) const 152*aa374120SPatrick Venture { 153*aa374120SPatrick Venture using namespace phosphor::logging; 154*aa374120SPatrick Venture 155*aa374120SPatrick Venture std::ofstream ofs; 156*aa374120SPatrick Venture ofs.open(TIME_DELAY_FILENAME, std::ofstream::out); 157*aa374120SPatrick Venture if (!ofs.good()) 158*aa374120SPatrick Venture { 159*aa374120SPatrick Venture std::fprintf(stderr, "Unable to open file for output.\n"); 160*aa374120SPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 161*aa374120SPatrick Venture } 162*aa374120SPatrick Venture 163*aa374120SPatrick Venture ofs << "PSU_HARDRESET_DELAY=" << delay << std::endl; 164*aa374120SPatrick Venture if (ofs.fail()) 165*aa374120SPatrick Venture { 166*aa374120SPatrick Venture std::fprintf(stderr, "Write failed\n"); 167*aa374120SPatrick Venture ofs.close(); 168*aa374120SPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 169*aa374120SPatrick Venture } 170*aa374120SPatrick Venture 171*aa374120SPatrick Venture // Write succeeded, please continue. 172*aa374120SPatrick Venture ofs.flush(); 173*aa374120SPatrick Venture ofs.close(); 174*aa374120SPatrick Venture 175*aa374120SPatrick Venture auto bus = sdbusplus::bus::new_default(); 176*aa374120SPatrick Venture auto method = bus.new_method_call(SYSTEMD_SERVICE, SYSTEMD_ROOT, 177*aa374120SPatrick Venture SYSTEMD_INTERFACE, "StartUnit"); 178*aa374120SPatrick Venture 179*aa374120SPatrick Venture method.append(PSU_HARDRESET_TARGET); 180*aa374120SPatrick Venture method.append("replace"); 181*aa374120SPatrick Venture 182*aa374120SPatrick Venture try 183*aa374120SPatrick Venture { 184*aa374120SPatrick Venture bus.call_noreply(method); 185*aa374120SPatrick Venture } 186*aa374120SPatrick Venture catch (const sdbusplus::exception::SdBusError& ex) 187*aa374120SPatrick Venture { 188*aa374120SPatrick Venture log<level::ERR>("Failed to call PSU hard reset"); 189*aa374120SPatrick Venture throw IpmiException(IPMI_CC_UNSPECIFIED_ERROR); 190*aa374120SPatrick Venture } 191*aa374120SPatrick Venture } 192*aa374120SPatrick Venture 193f085d91dSPatrick Venture Handler handlerImpl; 194f085d91dSPatrick Venture 195f085d91dSPatrick Venture } // namespace ipmi 196f085d91dSPatrick Venture } // namespace google 197