blob: 255e2c554679edec7abdc7d58b1402b390e6d95e [file] [log] [blame]
Shawn McCarney906cc3f2024-02-01 13:33:06 -06001/**
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
Shawn McCarney906cc3f2024-02-01 13:33:06 -060021#include <phosphor-logging/lg2.hpp>
22#include <sdbusplus/bus.hpp>
23#include <sdbusplus/exception.hpp>
24
25#include <cstdint>
Shawn McCarneye4fef0f2024-04-05 17:56:09 -050026#include <format>
Shawn McCarney906cc3f2024-02-01 13:33:06 -060027#include <map>
28#include <memory>
29#include <string>
30#include <vector>
31
32namespace phosphor::power::sequencer
33{
34
35using namespace sdbusplus::xyz::openbmc_project::Logging::server;
36using PMBusBase = phosphor::pmbus::PMBusBase;
37using 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 */
45class 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>
126 createPMBus(uint8_t bus, uint16_t address,
127 const std::string& driverName = "",
128 size_t instance = 0) = 0;
Shawn McCarneye4fef0f2024-04-05 17:56:09 -0500129
130 /**
131 * Clear any cached data.
132 *
133 * Some data may be cached for performance reasons, such as hardware
134 * presence. Clearing the cache results in the latest data being obtained
135 * by a subsequent method calls.
136 */
137 virtual void clearCache() = 0;
Shawn McCarney906cc3f2024-02-01 13:33:06 -0600138};
139
140/**
141 * @class BMCServices
142 *
143 * Implementation of the Services interface using standard BMC system services.
144 */
145class BMCServices : public Services
146{
147 public:
148 // Specify which compiler-generated methods we want
149 BMCServices() = delete;
150 BMCServices(const BMCServices&) = delete;
151 BMCServices(BMCServices&&) = delete;
152 BMCServices& operator=(const BMCServices&) = delete;
153 BMCServices& operator=(BMCServices&&) = delete;
154 virtual ~BMCServices() = default;
155
156 /**
157 * Constructor.
158 *
159 * @param bus D-Bus bus object
160 */
161 explicit BMCServices(sdbusplus::bus_t& bus) : bus{bus} {}
162
163 /** @copydoc Services::getBus() */
164 virtual sdbusplus::bus_t& getBus() override
165 {
166 return bus;
167 }
168
169 /** @copydoc Services::logErrorMsg() */
170 virtual void logErrorMsg(const std::string& message) override
171 {
172 lg2::error(message.c_str());
173 }
174
175 /** @copydoc Services::logInfoMsg() */
176 virtual void logInfoMsg(const std::string& message) override
177 {
178 lg2::info(message.c_str());
179 }
180
181 /** @copydoc Services::logError() */
182 virtual void
183 logError(const std::string& message, Entry::Level severity,
184 std::map<std::string, std::string>& additionalData) override;
185
186 /** @copydoc Services::isPresent() */
187 virtual bool isPresent(const std::string& inventoryPath) override;
188
189 /** @copydoc Services::getGPIOValues() */
190 virtual std::vector<int>
191 getGPIOValues(const std::string& chipLabel) override;
192
193 /** @copydoc Services::createPMBus() */
194 virtual std::unique_ptr<PMBusBase>
195 createPMBus(uint8_t bus, uint16_t address,
196 const std::string& driverName = "",
197 size_t instance = 0) override
198 {
Shawn McCarneye4fef0f2024-04-05 17:56:09 -0500199 std::string path = std::format("/sys/bus/i2c/devices/{}-{:04x}", bus,
Shawn McCarney906cc3f2024-02-01 13:33:06 -0600200 address);
201 return std::make_unique<PMBus>(path, driverName, instance);
202 }
203
Shawn McCarneye4fef0f2024-04-05 17:56:09 -0500204 /** @copydoc Services::clearCache() */
205 virtual void clearCache() override
206 {
207 presenceCache.clear();
208 }
209
Shawn McCarney906cc3f2024-02-01 13:33:06 -0600210 private:
211 /**
212 * Returns whether the specified D-Bus exception is one of the expected
213 * types that can be thrown if hardware is not present.
214 *
215 * @return true if exception type is expected, false otherwise
216 */
217 bool isExpectedException(const sdbusplus::exception_t& e);
218
219 /**
220 * D-Bus bus object.
221 */
222 sdbusplus::bus_t& bus;
Shawn McCarneye4fef0f2024-04-05 17:56:09 -0500223
224 /**
225 * Cached presence data.
226 *
227 * Map from inventory paths to presence values.
228 */
229 std::map<std::string, bool> presenceCache{};
Shawn McCarney906cc3f2024-02-01 13:33:06 -0600230};
231
232} // namespace phosphor::power::sequencer