xref: /openbmc/openpower-occ-control/occ_ffdc.hpp (revision 2ccc3f699bd147ce68c672b32f44a7afd51ad82c)
12f9f9bbaSEddie James #pragma once
22f9f9bbaSEddie James 
32f9f9bbaSEddie James #include "config.h"
42f9f9bbaSEddie James 
5*2ccc3f69SChris Cain #include "file.hpp"
62f9f9bbaSEddie James #include "occ_errors.hpp"
72f9f9bbaSEddie James 
8*2ccc3f69SChris Cain #include <systemd/sd-journal.h>
9*2ccc3f69SChris Cain 
10*2ccc3f69SChris Cain #include <nlohmann/json.hpp>
11*2ccc3f69SChris Cain #include <xyz/openbmc_project/Logging/Create/server.hpp>
12*2ccc3f69SChris Cain 
13*2ccc3f69SChris Cain using FFDCFormat =
14*2ccc3f69SChris Cain     sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat;
15*2ccc3f69SChris Cain using FFDCFiles = std::vector<
16*2ccc3f69SChris Cain     std::tuple<FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>>;
17*2ccc3f69SChris Cain 
182f9f9bbaSEddie James namespace open_power
192f9f9bbaSEddie James {
202f9f9bbaSEddie James namespace occ
212f9f9bbaSEddie James {
222f9f9bbaSEddie James 
23*2ccc3f69SChris Cain /** @class FFDCFile
24*2ccc3f69SChris Cain  *  @brief Represents a single file that will get opened when created and
25*2ccc3f69SChris Cain  *         deleted when the object is destructed
26*2ccc3f69SChris Cain  */
27*2ccc3f69SChris Cain class FFDCFile
28*2ccc3f69SChris Cain {
29*2ccc3f69SChris Cain   public:
30*2ccc3f69SChris Cain     FFDCFile() = delete;
31*2ccc3f69SChris Cain     FFDCFile(const FFDCFile&) = delete;
32*2ccc3f69SChris Cain     FFDCFile& operator=(const FFDCFile&) = delete;
33*2ccc3f69SChris Cain     FFDCFile(FFDCFile&&) = delete;
34*2ccc3f69SChris Cain     FFDCFile& operator=(FFDCFile&&) = delete;
35*2ccc3f69SChris Cain 
36*2ccc3f69SChris Cain     /**
37*2ccc3f69SChris Cain      * @brief Constructor
38*2ccc3f69SChris Cain      *
39*2ccc3f69SChris Cain      * Opens the file and saves the descriptor
40*2ccc3f69SChris Cain      *
41*2ccc3f69SChris Cain      * @param[in] name - The filename
42*2ccc3f69SChris Cain      */
43*2ccc3f69SChris Cain     explicit FFDCFile(const std::filesystem::path& name);
44*2ccc3f69SChris Cain 
45*2ccc3f69SChris Cain     /**
46*2ccc3f69SChris Cain      * @brief Destructor - Deletes the file
47*2ccc3f69SChris Cain      */
48*2ccc3f69SChris Cain     ~FFDCFile()
49*2ccc3f69SChris Cain     {
50*2ccc3f69SChris Cain         std::filesystem::remove(_name);
51*2ccc3f69SChris Cain     }
52*2ccc3f69SChris Cain 
53*2ccc3f69SChris Cain     /**
54*2ccc3f69SChris Cain      * @brief Returns the file descriptor
55*2ccc3f69SChris Cain      *
56*2ccc3f69SChris Cain      * @return int - The descriptor
57*2ccc3f69SChris Cain      */
58*2ccc3f69SChris Cain     int fd()
59*2ccc3f69SChris Cain     {
60*2ccc3f69SChris Cain         return _fd();
61*2ccc3f69SChris Cain     }
62*2ccc3f69SChris Cain 
63*2ccc3f69SChris Cain   private:
64*2ccc3f69SChris Cain     /**
65*2ccc3f69SChris Cain      * @brief The file descriptor holder
66*2ccc3f69SChris Cain      */
67*2ccc3f69SChris Cain     FileDescriptor _fd;
68*2ccc3f69SChris Cain 
69*2ccc3f69SChris Cain     /**
70*2ccc3f69SChris Cain      * @brief The filename
71*2ccc3f69SChris Cain      */
72*2ccc3f69SChris Cain     const std::filesystem::path _name;
73*2ccc3f69SChris Cain };
74*2ccc3f69SChris Cain 
752f9f9bbaSEddie James /** @class FFDC
762f9f9bbaSEddie James  *  @brief Monitors for SBE FFDC availability
772f9f9bbaSEddie James  */
782f9f9bbaSEddie James class FFDC : public Error
792f9f9bbaSEddie James {
802f9f9bbaSEddie James   public:
812f9f9bbaSEddie James     FFDC() = delete;
822f9f9bbaSEddie James     FFDC(const FFDC&) = delete;
832f9f9bbaSEddie James     FFDC& operator=(const FFDC&) = delete;
842f9f9bbaSEddie James     FFDC(FFDC&&) = default;
852f9f9bbaSEddie James     FFDC& operator=(FFDC&&) = default;
862f9f9bbaSEddie James 
872f9f9bbaSEddie James     /** @brief Constructs the FFDC object
882f9f9bbaSEddie James      *
892f9f9bbaSEddie James      *  @param[in] event    - reference to sd_event unique_ptr
902f9f9bbaSEddie James      *  @param[in] file     - File used by driver to communicate FFDC data
912f9f9bbaSEddie James      *  @param[in] instance - OCC instance number
922f9f9bbaSEddie James      */
932f9f9bbaSEddie James     FFDC(EventPtr& event, const fs::path& file, unsigned int instance) :
942f9f9bbaSEddie James         Error(event, file, nullptr), instance(instance)
952f9f9bbaSEddie James     {
962f9f9bbaSEddie James         // Nothing to do here.
972f9f9bbaSEddie James     }
982f9f9bbaSEddie James 
992f9f9bbaSEddie James     ~FFDC()
1002f9f9bbaSEddie James     {
1012f9f9bbaSEddie James         for (auto&& it : temporaryFiles)
1022f9f9bbaSEddie James         {
1032f9f9bbaSEddie James             close(it.second);
1042f9f9bbaSEddie James             fs::remove(it.first);
1052f9f9bbaSEddie James         }
1062f9f9bbaSEddie James     }
1072f9f9bbaSEddie James 
1082f9f9bbaSEddie James     /** @brief Helper function to create a PEL with the OpenPower DBus
1092f9f9bbaSEddie James      *         interface
1102f9f9bbaSEddie James      *
1112f9f9bbaSEddie James      * @param[in] path - the DBus error path
1122f9f9bbaSEddie James      * @param[in] src6 - the SBE error SRC6 word
1132f9f9bbaSEddie James      * @param[in] msg - the error message
1142f9f9bbaSEddie James      * @param[in] fd - the file descriptor for any FFDC
1152f9f9bbaSEddie James      */
1162f9f9bbaSEddie James     static uint32_t createPEL(const char* path, uint32_t src6, const char* msg,
1172f9f9bbaSEddie James                               int fd = -1);
1182f9f9bbaSEddie James 
1199789e71fSEddie James     /** @brief Helper function to create a PEL for the OCC reset with the
1209789e71fSEddie James      * OpenPower DBus interface
1219789e71fSEddie James      *
1229789e71fSEddie James      * @param[in] instance - the OCC instance id
1239789e71fSEddie James      * @param[in] path - the DBus error path
1249789e71fSEddie James      * @param[in] err - the error return code
1259789e71fSEddie James      * @param[in] callout - the PEL callout path
1269789e71fSEddie James      */
1279789e71fSEddie James     static void createOCCResetPEL(unsigned int instance, const char* path,
1289789e71fSEddie James                                   int err, const char* callout);
1299789e71fSEddie James 
130*2ccc3f69SChris Cain     /**
131*2ccc3f69SChris Cain      * @brief Create a file containing the latest journal traces for the
132*2ccc3f69SChris Cain      *        specified executable and add it to the file list.
133*2ccc3f69SChris Cain      *
134*2ccc3f69SChris Cain      * @param[in] fileList     - where to add the new file
135*2ccc3f69SChris Cain      * @param[in] executable   - name of app to collect
136*2ccc3f69SChris Cain      * @param[in] lines        - number of journal lines to save
137*2ccc3f69SChris Cain      *
138*2ccc3f69SChris Cain      * @return std::unique_ptr<FFDCFile> - The file object
139*2ccc3f69SChris Cain      */
140*2ccc3f69SChris Cain     static std::unique_ptr<FFDCFile>
141*2ccc3f69SChris Cain         addJournalEntries(FFDCFiles& fileList, const std::string& executable,
142*2ccc3f69SChris Cain                           unsigned int lines);
143*2ccc3f69SChris Cain 
1442f9f9bbaSEddie James   private:
1452f9f9bbaSEddie James     /** @brief OCC instance number. Ex, 0,1, etc */
1462f9f9bbaSEddie James     unsigned int instance;
1472f9f9bbaSEddie James 
1482f9f9bbaSEddie James     /** @brief Stores the temporary files and file descriptors
1492f9f9bbaSEddie James      *         in usage. They will be cleaned up when the class
1502f9f9bbaSEddie James      *         is destroyed (when the application exits).
1512f9f9bbaSEddie James      */
1522f9f9bbaSEddie James     std::vector<std::pair<fs::path, int>> temporaryFiles;
1532f9f9bbaSEddie James 
1542f9f9bbaSEddie James     /** @brief When the error event is received, analyzes it
1552f9f9bbaSEddie James      *         and makes a callback to error handler if the
1562f9f9bbaSEddie James      *         content denotes an error condition
1572f9f9bbaSEddie James      */
1582f9f9bbaSEddie James     void analyzeEvent() override;
159*2ccc3f69SChris Cain 
160*2ccc3f69SChris Cain     /**
161*2ccc3f69SChris Cain      * @brief Returns an FFDCFile containing the JSON data
162*2ccc3f69SChris Cain      *
163*2ccc3f69SChris Cain      * @param[in] ffdcData - The JSON data to write to a file
164*2ccc3f69SChris Cain      *
165*2ccc3f69SChris Cain      * @return std::unique_ptr<FFDCFile> - The file object
166*2ccc3f69SChris Cain      */
167*2ccc3f69SChris Cain     static std::unique_ptr<FFDCFile>
168*2ccc3f69SChris Cain         makeJsonFFDCFile(const nlohmann::json& ffdcData);
169*2ccc3f69SChris Cain 
170*2ccc3f69SChris Cain     /**
171*2ccc3f69SChris Cain      * @brief Returns a JSON structure containing the previous N journal
172*2ccc3f69SChris Cain      * entries.
173*2ccc3f69SChris Cain      *
174*2ccc3f69SChris Cain      * @param[in] numLines   - Number of lines of journal to retrieve
175*2ccc3f69SChris Cain      * @param[in] executable - name of app to collect for
176*2ccc3f69SChris Cain      *
177*2ccc3f69SChris Cain      * @return JSON object that was created
178*2ccc3f69SChris Cain      */
179*2ccc3f69SChris Cain     static nlohmann::json getJournalEntries(int numLines,
180*2ccc3f69SChris Cain                                             std::string executable);
181*2ccc3f69SChris Cain 
182*2ccc3f69SChris Cain     /**
183*2ccc3f69SChris Cain      * @brief Gets the realtime (wallclock) timestamp for the current journal
184*2ccc3f69SChris Cain      * entry.
185*2ccc3f69SChris Cain      *
186*2ccc3f69SChris Cain      * @param journal current journal entry
187*2ccc3f69SChris Cain      * @return timestamp as a date/time string
188*2ccc3f69SChris Cain      */
189*2ccc3f69SChris Cain     static std::string getTimeStamp(sd_journal* journal);
190*2ccc3f69SChris Cain 
191*2ccc3f69SChris Cain     /**
192*2ccc3f69SChris Cain      * @brief Gets the value of the specified field for the current journal
193*2ccc3f69SChris Cain      * entry.
194*2ccc3f69SChris Cain      *
195*2ccc3f69SChris Cain      * Returns an empty string if the current journal entry does not have the
196*2ccc3f69SChris Cain      * specified field.
197*2ccc3f69SChris Cain      *
198*2ccc3f69SChris Cain      * @param journal current journal entry
199*2ccc3f69SChris Cain      * @param field journal field name
200*2ccc3f69SChris Cain      * @return field value
201*2ccc3f69SChris Cain      */
202*2ccc3f69SChris Cain     static std::string getFieldValue(sd_journal* journal,
203*2ccc3f69SChris Cain                                      const std::string& field);
204*2ccc3f69SChris Cain };
205*2ccc3f69SChris Cain 
206*2ccc3f69SChris Cain /**
207*2ccc3f69SChris Cain  * @class JournalCloser
208*2ccc3f69SChris Cain  *  @brief Automatically closes the journal when the object goes out of scope.
209*2ccc3f69SChris Cain  */
210*2ccc3f69SChris Cain class JournalCloser
211*2ccc3f69SChris Cain {
212*2ccc3f69SChris Cain   public:
213*2ccc3f69SChris Cain     // Specify which compiler-generated methods we want
214*2ccc3f69SChris Cain     JournalCloser() = delete;
215*2ccc3f69SChris Cain     JournalCloser(const JournalCloser&) = delete;
216*2ccc3f69SChris Cain     JournalCloser(JournalCloser&&) = delete;
217*2ccc3f69SChris Cain     JournalCloser& operator=(const JournalCloser&) = delete;
218*2ccc3f69SChris Cain     JournalCloser& operator=(JournalCloser&&) = delete;
219*2ccc3f69SChris Cain 
220*2ccc3f69SChris Cain     JournalCloser(sd_journal* journal) : journal{journal}
221*2ccc3f69SChris Cain     {}
222*2ccc3f69SChris Cain 
223*2ccc3f69SChris Cain     ~JournalCloser()
224*2ccc3f69SChris Cain     {
225*2ccc3f69SChris Cain         sd_journal_close(journal);
226*2ccc3f69SChris Cain     }
227*2ccc3f69SChris Cain 
228*2ccc3f69SChris Cain   private:
229*2ccc3f69SChris Cain     sd_journal* journal{nullptr};
2302f9f9bbaSEddie James };
2312f9f9bbaSEddie James 
2322f9f9bbaSEddie James } // namespace occ
2332f9f9bbaSEddie James } // namespace open_power
234