blob: e49d56bf2bcff8944b1b0f976c951ac2f35b0628 [file] [log] [blame]
Eddie James2f9f9bb2021-09-20 14:26:31 -05001#pragma once
2
3#include "config.h"
4
Chris Cain2ccc3f62022-10-05 14:40:07 -05005#include "file.hpp"
Eddie James2f9f9bb2021-09-20 14:26:31 -05006#include "occ_errors.hpp"
7
Chris Cain2ccc3f62022-10-05 14:40:07 -05008#include <systemd/sd-journal.h>
9
10#include <nlohmann/json.hpp>
11#include <xyz/openbmc_project/Logging/Create/server.hpp>
12
13using FFDCFormat =
14 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat;
15using FFDCFiles = std::vector<
16 std::tuple<FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>>;
17
Eddie James2f9f9bb2021-09-20 14:26:31 -050018namespace open_power
19{
20namespace occ
21{
22
Chris Cain2ccc3f62022-10-05 14:40:07 -050023/** @class FFDCFile
24 * @brief Represents a single file that will get opened when created and
25 * deleted when the object is destructed
26 */
27class FFDCFile
28{
29 public:
30 FFDCFile() = delete;
31 FFDCFile(const FFDCFile&) = delete;
32 FFDCFile& operator=(const FFDCFile&) = delete;
33 FFDCFile(FFDCFile&&) = delete;
34 FFDCFile& operator=(FFDCFile&&) = delete;
35
36 /**
37 * @brief Constructor
38 *
39 * Opens the file and saves the descriptor
40 *
41 * @param[in] name - The filename
42 */
43 explicit FFDCFile(const std::filesystem::path& name);
44
45 /**
46 * @brief Destructor - Deletes the file
47 */
48 ~FFDCFile()
49 {
50 std::filesystem::remove(_name);
51 }
52
53 /**
54 * @brief Returns the file descriptor
55 *
56 * @return int - The descriptor
57 */
58 int fd()
59 {
60 return _fd();
61 }
62
63 private:
64 /**
65 * @brief The file descriptor holder
66 */
67 FileDescriptor _fd;
68
69 /**
70 * @brief The filename
71 */
72 const std::filesystem::path _name;
73};
74
Eddie James2f9f9bb2021-09-20 14:26:31 -050075/** @class FFDC
76 * @brief Monitors for SBE FFDC availability
77 */
78class FFDC : public Error
79{
80 public:
81 FFDC() = delete;
82 FFDC(const FFDC&) = delete;
83 FFDC& operator=(const FFDC&) = delete;
84 FFDC(FFDC&&) = default;
85 FFDC& operator=(FFDC&&) = default;
86
87 /** @brief Constructs the FFDC object
88 *
89 * @param[in] event - reference to sd_event unique_ptr
90 * @param[in] file - File used by driver to communicate FFDC data
91 * @param[in] instance - OCC instance number
92 */
93 FFDC(EventPtr& event, const fs::path& file, unsigned int instance) :
94 Error(event, file, nullptr), instance(instance)
95 {
96 // Nothing to do here.
97 }
98
99 ~FFDC()
100 {
101 for (auto&& it : temporaryFiles)
102 {
103 close(it.second);
104 fs::remove(it.first);
105 }
106 }
107
108 /** @brief Helper function to create a PEL with the OpenPower DBus
109 * interface
110 *
111 * @param[in] path - the DBus error path
112 * @param[in] src6 - the SBE error SRC6 word
113 * @param[in] msg - the error message
114 * @param[in] fd - the file descriptor for any FFDC
115 */
116 static uint32_t createPEL(const char* path, uint32_t src6, const char* msg,
117 int fd = -1);
118
Eddie James9789e712022-05-25 15:43:40 -0500119 /** @brief Helper function to create a PEL for the OCC reset with the
120 * OpenPower DBus interface
121 *
122 * @param[in] instance - the OCC instance id
123 * @param[in] path - the DBus error path
124 * @param[in] err - the error return code
125 * @param[in] callout - the PEL callout path
Chris Cain3ece5b92025-01-10 16:06:31 -0600126 * @param[in] isInventoryCallout - true if the callout is an inventory path
127 * or false if it is a device path
Eddie James9789e712022-05-25 15:43:40 -0500128 */
129 static void createOCCResetPEL(unsigned int instance, const char* path,
Chris Cain3ece5b92025-01-10 16:06:31 -0600130 int err, const char* deviceCallout,
131 const bool isInventoryCallout);
Eddie James9789e712022-05-25 15:43:40 -0500132
Chris Cain2ccc3f62022-10-05 14:40:07 -0500133 /**
134 * @brief Create a file containing the latest journal traces for the
135 * specified executable and add it to the file list.
136 *
137 * @param[in] fileList - where to add the new file
138 * @param[in] executable - name of app to collect
139 * @param[in] lines - number of journal lines to save
140 *
141 * @return std::unique_ptr<FFDCFile> - The file object
142 */
Patrick Williamsd7542c82024-08-16 15:20:28 -0400143 static std::unique_ptr<FFDCFile> addJournalEntries(
144 FFDCFiles& fileList, const std::string& executable, unsigned int lines);
Chris Cain2ccc3f62022-10-05 14:40:07 -0500145
Eddie James2f9f9bb2021-09-20 14:26:31 -0500146 private:
147 /** @brief OCC instance number. Ex, 0,1, etc */
148 unsigned int instance;
149
150 /** @brief Stores the temporary files and file descriptors
151 * in usage. They will be cleaned up when the class
152 * is destroyed (when the application exits).
153 */
154 std::vector<std::pair<fs::path, int>> temporaryFiles;
155
156 /** @brief When the error event is received, analyzes it
157 * and makes a callback to error handler if the
158 * content denotes an error condition
159 */
160 void analyzeEvent() override;
Chris Cain2ccc3f62022-10-05 14:40:07 -0500161
162 /**
163 * @brief Returns an FFDCFile containing the JSON data
164 *
165 * @param[in] ffdcData - The JSON data to write to a file
166 *
167 * @return std::unique_ptr<FFDCFile> - The file object
168 */
Patrick Williams2d6ec902025-02-01 08:22:13 -0500169 static std::unique_ptr<FFDCFile> makeJsonFFDCFile(
170 const nlohmann::json& ffdcData);
Chris Cain2ccc3f62022-10-05 14:40:07 -0500171
172 /**
173 * @brief Returns a JSON structure containing the previous N journal
174 * entries.
175 *
176 * @param[in] numLines - Number of lines of journal to retrieve
177 * @param[in] executable - name of app to collect for
178 *
179 * @return JSON object that was created
180 */
181 static nlohmann::json getJournalEntries(int numLines,
182 std::string executable);
183
184 /**
185 * @brief Gets the realtime (wallclock) timestamp for the current journal
186 * entry.
187 *
188 * @param journal current journal entry
189 * @return timestamp as a date/time string
190 */
191 static std::string getTimeStamp(sd_journal* journal);
192
193 /**
194 * @brief Gets the value of the specified field for the current journal
195 * entry.
196 *
197 * Returns an empty string if the current journal entry does not have the
198 * specified field.
199 *
200 * @param journal current journal entry
201 * @param field journal field name
202 * @return field value
203 */
204 static std::string getFieldValue(sd_journal* journal,
205 const std::string& field);
206};
207
208/**
209 * @class JournalCloser
210 * @brief Automatically closes the journal when the object goes out of scope.
211 */
212class JournalCloser
213{
214 public:
215 // Specify which compiler-generated methods we want
216 JournalCloser() = delete;
217 JournalCloser(const JournalCloser&) = delete;
218 JournalCloser(JournalCloser&&) = delete;
219 JournalCloser& operator=(const JournalCloser&) = delete;
220 JournalCloser& operator=(JournalCloser&&) = delete;
221
Patrick Williamsa49c9872023-05-10 07:50:35 -0500222 JournalCloser(sd_journal* journal) : journal{journal} {}
Chris Cain2ccc3f62022-10-05 14:40:07 -0500223
224 ~JournalCloser()
225 {
226 sd_journal_close(journal);
227 }
228
229 private:
230 sd_journal* journal{nullptr};
Eddie James2f9f9bb2021-09-20 14:26:31 -0500231};
232
233} // namespace occ
234} // namespace open_power