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