1 /**
2  * Copyright © 2020 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 "ffdc_file.hpp"
19 #include "journal.hpp"
20 #include "phase_fault.hpp"
21 #include "xyz/openbmc_project/Logging/Create/server.hpp"
22 #include "xyz/openbmc_project/Logging/Entry/server.hpp"
23 
24 #include <sdbusplus/bus.hpp>
25 
26 #include <cstdint>
27 #include <map>
28 #include <string>
29 #include <tuple>
30 #include <vector>
31 
32 namespace phosphor::power::regulators
33 {
34 
35 using namespace sdbusplus::xyz::openbmc_project::Logging::server;
36 using FFDCTuple =
37     std::tuple<FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>;
38 
39 /**
40  * @class ErrorLogging
41  *
42  * Abstract base class that provides an error logging interface.
43  *
44  * The interface is used to create error logs.
45  */
46 class ErrorLogging
47 {
48   public:
49     // Specify which compiler-generated methods we want
50     ErrorLogging() = default;
51     ErrorLogging(const ErrorLogging&) = delete;
52     ErrorLogging(ErrorLogging&&) = delete;
53     ErrorLogging& operator=(const ErrorLogging&) = delete;
54     ErrorLogging& operator=(ErrorLogging&&) = delete;
55     virtual ~ErrorLogging() = default;
56 
57     /**
58      * Log a regulators configuration file error.
59      *
60      * This error is logged when the regulators configuration file could not be
61      * found, could not be read, or had invalid contents.
62      *
63      * @param severity severity level
64      * @param journal system journal
65      */
66     virtual void logConfigFileError(Entry::Level severity,
67                                     Journal& journal) = 0;
68 
69     /**
70      * Log a D-Bus error.
71      *
72      * This error is logged when D-Bus communication fails.
73      *
74      * @param severity severity level
75      * @param journal system journal
76      */
77     virtual void logDBusError(Entry::Level severity, Journal& journal) = 0;
78 
79     /**
80      * Log an I2C communication error.
81      *
82      * @param severity severity level
83      * @param journal system journal
84      * @param bus I2C bus in the form "/dev/i2c-X", where X is the 0-based bus
85      *            number
86      * @param addr 7 bit I2C address
87      * @param errorNumber errno value from the failed I2C operation
88      */
89     virtual void logI2CError(Entry::Level severity, Journal& journal,
90                              const std::string& bus, uint8_t addr,
91                              int errorNumber) = 0;
92 
93     /**
94      * Log an internal firmware error.
95      *
96      * @param severity severity level
97      * @param journal system journal
98      */
99     virtual void logInternalError(Entry::Level severity, Journal& journal) = 0;
100 
101     /**
102      * Log a phase fault error.
103      *
104      * This error is logged when a regulator has lost a redundant phase.
105      *
106      * @param severity severity level
107      * @param journal system journal
108      * @param type phase fault type
109      * @param inventoryPath D-Bus inventory path of the device where the error
110      *                      occurred
111      * @param additionalData additional error data (if any)
112      */
113     virtual void
114         logPhaseFault(Entry::Level severity, Journal& journal,
115                       PhaseFaultType type, const std::string& inventoryPath,
116                       std::map<std::string, std::string> additionalData) = 0;
117 
118     /**
119      * Log a PMBus error.
120      *
121      * This error is logged when the I2C communication was successful, but the
122      * PMBus value read is invalid or unsupported.
123      *
124      * @param severity severity level
125      * @param journal system journal
126      * @param inventoryPath D-Bus inventory path of the device where the error
127      *                      occurred
128      */
129     virtual void logPMBusError(Entry::Level severity, Journal& journal,
130                                const std::string& inventoryPath) = 0;
131 
132     /**
133      * Log a write verification error.
134      *
135      * This error is logged when a device register is written, read back, and
136      * the two values do not match.  This is also called a read-back error.
137      *
138      * @param severity severity level
139      * @param journal system journal
140      * @param inventoryPath D-Bus inventory path of the device where the error
141      *                      occurred
142      */
143     virtual void
144         logWriteVerificationError(Entry::Level severity, Journal& journal,
145                                   const std::string& inventoryPath) = 0;
146 };
147 
148 /**
149  * @class DBusErrorLogging
150  *
151  * Implementation of the ErrorLogging interface using D-Bus method calls.
152  */
153 class DBusErrorLogging : public ErrorLogging
154 {
155   public:
156     // Specify which compiler-generated methods we want
157     DBusErrorLogging() = delete;
158     DBusErrorLogging(const DBusErrorLogging&) = delete;
159     DBusErrorLogging(DBusErrorLogging&&) = delete;
160     DBusErrorLogging& operator=(const DBusErrorLogging&) = delete;
161     DBusErrorLogging& operator=(DBusErrorLogging&&) = delete;
162     virtual ~DBusErrorLogging() = default;
163 
164     /**
165      * Constructor.
166      *
167      * @param bus D-Bus bus object
168      */
DBusErrorLogging(sdbusplus::bus_t & bus)169     explicit DBusErrorLogging(sdbusplus::bus_t& bus) : bus{bus} {}
170 
171     /** @copydoc ErrorLogging::logConfigFileError() */
172     virtual void logConfigFileError(Entry::Level severity,
173                                     Journal& journal) override;
174 
175     /** @copydoc ErrorLogging::logDBusError() */
176     virtual void logDBusError(Entry::Level severity, Journal& journal) override;
177 
178     /** @copydoc ErrorLogging::logI2CError() */
179     virtual void logI2CError(Entry::Level severity, Journal& journal,
180                              const std::string& bus, uint8_t addr,
181                              int errorNumber) override;
182 
183     /** @copydoc ErrorLogging::logInternalError() */
184     virtual void logInternalError(Entry::Level severity,
185                                   Journal& journal) override;
186 
187     /** @copydoc ErrorLogging::logPhaseFault() */
188     virtual void logPhaseFault(
189         Entry::Level severity, Journal& journal, PhaseFaultType type,
190         const std::string& inventoryPath,
191         std::map<std::string, std::string> additionalData) override;
192 
193     /** @copydoc ErrorLogging::logPMBusError() */
194     virtual void logPMBusError(Entry::Level severity, Journal& journal,
195                                const std::string& inventoryPath) override;
196 
197     /** @copydoc ErrorLogging::logWriteVerificationError() */
198     virtual void
199         logWriteVerificationError(Entry::Level severity, Journal& journal,
200                                   const std::string& inventoryPath) override;
201 
202   private:
203     /**
204      * Create an FFDCFile object containing the specified lines of text data.
205      *
206      * Throws an exception if an error occurs.
207      *
208      * @param lines lines of text data to write to file
209      * @return FFDCFile object
210      */
211     FFDCFile createFFDCFile(const std::vector<std::string>& lines);
212 
213     /**
214      * Create FFDCFile objects containing debug data to store in the error log.
215      *
216      * If an error occurs, the error is written to the journal but an exception
217      * is not thrown.
218      *
219      * @param journal system journal
220      * @return vector of FFDCFile objects
221      */
222     std::vector<FFDCFile> createFFDCFiles(Journal& journal);
223 
224     /**
225      * Create FFDCTuple objects corresponding to the specified FFDC files.
226      *
227      * The D-Bus method to create an error log requires a vector of tuples to
228      * pass in the FFDC file information.
229      *
230      * @param files FFDC files
231      * @return vector of FFDCTuple objects
232      */
233     std::vector<FFDCTuple> createFFDCTuples(std::vector<FFDCFile>& files);
234 
235     /**
236      * Logs an error using the D-Bus CreateWithFFDCFiles method.
237      *
238      * If logging fails, a message is written to the journal but an exception is
239      * not thrown.
240      *
241      * @param message Message property of the error log entry
242      * @param severity Severity property of the error log entry
243      * @param additionalData AdditionalData property of the error log entry
244      * @param journal system journal
245      */
246     void logError(const std::string& message, Entry::Level severity,
247                   std::map<std::string, std::string>& additionalData,
248                   Journal& journal);
249 
250     /**
251      * Removes the specified FFDC files from the file system.
252      *
253      * Also clears the specified vector, removing the FFDCFile objects.
254      *
255      * If an error occurs, the error is written to the journal but an exception
256      * is not thrown.
257      *
258      * @param files FFDC files to remove
259      * @param journal system journal
260      */
261     void removeFFDCFiles(std::vector<FFDCFile>& files, Journal& journal);
262 
263     /**
264      * D-Bus bus object.
265      */
266     sdbusplus::bus_t& bus;
267 };
268 
269 } // namespace phosphor::power::regulators
270