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