1 /** 2 * Copyright © 2024 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 #pragma once 17 18 #include "pmbus.hpp" 19 #include "xyz/openbmc_project/Logging/Entry/server.hpp" 20 21 #include <phosphor-logging/lg2.hpp> 22 #include <sdbusplus/bus.hpp> 23 #include <sdbusplus/exception.hpp> 24 25 #include <cstdint> 26 #include <format> 27 #include <map> 28 #include <memory> 29 #include <string> 30 #include <vector> 31 32 namespace phosphor::power::sequencer 33 { 34 35 using namespace sdbusplus::xyz::openbmc_project::Logging::server; 36 using PMBusBase = phosphor::pmbus::PMBusBase; 37 using PMBus = phosphor::pmbus::PMBus; 38 39 /** 40 * @class Services 41 * 42 * Abstract base class that provides an interface to system services like error 43 * logging and the journal. 44 */ 45 class Services 46 { 47 public: 48 // Specify which compiler-generated methods we want 49 Services() = default; 50 Services(const Services&) = delete; 51 Services(Services&&) = delete; 52 Services& operator=(const Services&) = delete; 53 Services& operator=(Services&&) = delete; 54 virtual ~Services() = default; 55 56 /** 57 * Returns the D-Bus bus object. 58 * 59 * @return D-Bus bus 60 */ 61 virtual sdbusplus::bus_t& getBus() = 0; 62 63 /** 64 * Logs an error message in the system journal. 65 * 66 * @param message message to log 67 */ 68 virtual void logErrorMsg(const std::string& message) = 0; 69 70 /** 71 * Logs an informational message in the system journal. 72 * 73 * @param message message to log 74 */ 75 virtual void logInfoMsg(const std::string& message) = 0; 76 77 /** 78 * Logs an error. 79 * 80 * If logging fails, a message is written to the system journal but an 81 * exception is not thrown. 82 * 83 * @param message Message property of the error log entry 84 * @param severity Severity property of the error log entry 85 * @param additionalData AdditionalData property of the error log entry 86 */ 87 virtual void 88 logError(const std::string& message, Entry::Level severity, 89 std::map<std::string, std::string>& additionalData) = 0; 90 91 /** 92 * Returns whether the hardware with the specified inventory path is 93 * present. 94 * 95 * Throws an exception if an error occurs while obtaining the presence 96 * value. 97 * 98 * @param inventoryPath D-Bus inventory path of the hardware 99 * @return true if hardware is present, false otherwise 100 */ 101 virtual bool isPresent(const std::string& inventoryPath) = 0; 102 103 /** 104 * Reads all the GPIO values on the chip with the specified label. 105 * 106 * Throws an exception if an error occurs while obtaining the values. 107 * 108 * @param chipLabel label identifying the chip with the GPIOs 109 * @return GPIO values 110 */ 111 virtual std::vector<int> getGPIOValues(const std::string& chipLabel) = 0; 112 113 /** 114 * Creates object for communicating with a PMBus device by reading and 115 * writing sysfs files. 116 * 117 * Throws an exception if an error occurs. 118 * 119 * @param bus I2C bus 120 * @param address I2C address 121 * @param driverName Device driver name 122 * @param instance Chip instance number 123 * @return object for communicating with PMBus device 124 */ 125 virtual std::unique_ptr<PMBusBase> createPMBus( 126 uint8_t bus, uint16_t address, const std::string& driverName = "", 127 size_t instance = 0) = 0; 128 129 /** 130 * Creates a BMC dump. 131 */ 132 virtual void createBMCDump() = 0; 133 134 /** 135 * Clear any cached data. 136 * 137 * Some data may be cached for performance reasons, such as hardware 138 * presence. Clearing the cache results in the latest data being obtained 139 * by a subsequent method calls. 140 */ 141 virtual void clearCache() = 0; 142 }; 143 144 /** 145 * @class BMCServices 146 * 147 * Implementation of the Services interface using standard BMC system services. 148 */ 149 class BMCServices : public Services 150 { 151 public: 152 // Specify which compiler-generated methods we want 153 BMCServices() = delete; 154 BMCServices(const BMCServices&) = delete; 155 BMCServices(BMCServices&&) = delete; 156 BMCServices& operator=(const BMCServices&) = delete; 157 BMCServices& operator=(BMCServices&&) = delete; 158 virtual ~BMCServices() = default; 159 160 /** 161 * Constructor. 162 * 163 * @param bus D-Bus bus object 164 */ BMCServices(sdbusplus::bus_t & bus)165 explicit BMCServices(sdbusplus::bus_t& bus) : bus{bus} {} 166 167 /** @copydoc Services::getBus() */ getBus()168 virtual sdbusplus::bus_t& getBus() override 169 { 170 return bus; 171 } 172 173 /** @copydoc Services::logErrorMsg() */ logErrorMsg(const std::string & message)174 virtual void logErrorMsg(const std::string& message) override 175 { 176 lg2::error(message.c_str()); 177 } 178 179 /** @copydoc Services::logInfoMsg() */ logInfoMsg(const std::string & message)180 virtual void logInfoMsg(const std::string& message) override 181 { 182 lg2::info(message.c_str()); 183 } 184 185 /** @copydoc Services::logError() */ 186 virtual void 187 logError(const std::string& message, Entry::Level severity, 188 std::map<std::string, std::string>& additionalData) override; 189 190 /** @copydoc Services::isPresent() */ 191 virtual bool isPresent(const std::string& inventoryPath) override; 192 193 /** @copydoc Services::getGPIOValues() */ 194 virtual std::vector<int> 195 getGPIOValues(const std::string& chipLabel) override; 196 197 /** @copydoc Services::createPMBus() */ createPMBus(uint8_t bus,uint16_t address,const std::string & driverName="",size_t instance=0)198 virtual std::unique_ptr<PMBusBase> createPMBus( 199 uint8_t bus, uint16_t address, const std::string& driverName = "", 200 size_t instance = 0) override 201 { 202 std::string path = 203 std::format("/sys/bus/i2c/devices/{}-{:04x}", bus, address); 204 return std::make_unique<PMBus>(path, driverName, instance); 205 } 206 207 /** @copydoc Services::createBMCDump() */ 208 virtual void createBMCDump() override; 209 210 /** @copydoc Services::clearCache() */ clearCache()211 virtual void clearCache() override 212 { 213 presenceCache.clear(); 214 } 215 216 private: 217 /** 218 * Returns whether the specified D-Bus exception is one of the expected 219 * types that can be thrown if hardware is not present. 220 * 221 * @return true if exception type is expected, false otherwise 222 */ 223 bool isExpectedException(const sdbusplus::exception_t& e); 224 225 /** 226 * D-Bus bus object. 227 */ 228 sdbusplus::bus_t& bus; 229 230 /** 231 * Cached presence data. 232 * 233 * Map from inventory paths to presence values. 234 */ 235 std::map<std::string, bool> presenceCache{}; 236 }; 237 238 } // namespace phosphor::power::sequencer 239