Attn: Add support for raw PEL creation

Attention handler needs to pass raw PEL's to phosphor logging in order
to submit PEL's on behalf of other components (e.g. hypervisor)

Signed-off-by: Ben Tyner <ben.tyner@ibm.com>
Change-Id: Id9a30728e7b463ac876b5dca023ca2627a25bb16
diff --git a/attn/attn_logging.cpp b/attn/attn_logging.cpp
index 014fc96..a55ac55 100644
--- a/attn/attn_logging.cpp
+++ b/attn/attn_logging.cpp
@@ -1,21 +1,421 @@
 #include <unistd.h>
 
 #include <attn/attn_logging.hpp>
+#include <attn/pel/pel_minimal.hpp>
 #include <phosphor-logging/log.hpp>
+
 namespace attn
 {
 
-/** @brief journal entry of type INFO using phosphor logging */
+/** @brief Journal entry of type INFO using phosphor logging */
 template <>
 void trace<INFO>(const char* i_message)
 {
     phosphor::logging::log<phosphor::logging::level::INFO>(i_message);
 }
 
-/** @brief add an event to the log for PEL generation */
-void event(EventType i_event, std::map<std::string, std::string>& i_additional)
+/** @brief Tuple containing information about ffdc files */
+using FFDCTuple =
+    std::tuple<util::FFDCFormat, uint8_t, uint8_t, sdbusplus::message::unix_fd>;
+
+/** @brief Gather messages from the journal */
+std::vector<std::string> sdjGetMessages(const std::string& field,
+                                        const std::string& fieldValue,
+                                        unsigned int max);
+
+/**
+ * Create FFDCTuple objects corresponding to the specified FFDC files.
+ *
+ * The D-Bus method to create an error log requires a vector of tuples to
+ * pass in the FFDC file information.
+ *
+ * @param   files - FFDC files
+ * @return  vector of FFDCTuple objects
+ */
+std::vector<FFDCTuple>
+    createFFDCTuples(const std::vector<util::FFDCFile>& files)
+{
+    std::vector<FFDCTuple> ffdcTuples{};
+    for (const util::FFDCFile& file : files)
+    {
+        ffdcTuples.emplace_back(
+            file.getFormat(), file.getSubType(), file.getVersion(),
+            sdbusplus::message::unix_fd(file.getFileDescriptor()));
+    }
+
+    return ffdcTuples;
+}
+
+/**
+ * @brief Create an FFDCFile object containing raw data
+ *
+ * Throws an exception if an error occurs.
+ *
+ * @param   i_buffer - raw data to add to ffdc faw data file
+ * @param   i_size - size of the raw data
+ * @return  FFDCFile object
+ */
+util::FFDCFile createFFDCRawFile(void* i_buffer, size_t i_size)
+{
+    util::FFDCFile file{util::FFDCFormat::Custom};
+
+    // Write buffer to file and then reset file description file offset
+    int fd = file.getFileDescriptor();
+    write(fd, static_cast<char*>(i_buffer), i_size);
+    lseek(fd, 0, SEEK_SET);
+
+    return file;
+}
+
+/**
+ * @brief Create an FFDCFile object containing the specified lines of text data
+ *
+ * Throws an exception if an error occurs.
+ *
+ * @param   lines - lines of text data to write to file
+ * @return  FFDCFile object
+ */
+util::FFDCFile createFFDCTraceFile(const std::vector<std::string>& lines)
+{
+    // Create FFDC file of type Text
+    util::FFDCFile file{util::FFDCFormat::Text};
+    int fd = file.getFileDescriptor();
+
+    // Write FFDC lines to file
+    std::string buffer;
+    for (const std::string& line : lines)
+    {
+        // Copy line to buffer.  Add newline if necessary.
+        buffer = line;
+        if (line.empty() || (line.back() != '\n'))
+        {
+            buffer += '\n';
+        }
+
+        // write buffer to file
+        write(fd, buffer.c_str(), buffer.size());
+    }
+
+    // Seek to beginning of file so error logging system can read data
+    lseek(fd, 0, SEEK_SET);
+
+    return file;
+}
+
+/**
+ * Create FDDC files from journal messages of relevant executables
+ *
+ * Parse the system journal looking for log entries created by the executables
+ * of interest for logging. For each of these entries create a ffdc trace file
+ * that will be used to create ffdc log entries. These files will be pushed
+ * onto the stack of ffdc files.
+ *
+ * @param   i_files - vector of ffdc files that will become log entries
+ */
+void createFFDCTraceFiles(std::vector<util::FFDCFile>& i_files)
+{
+    // Executables of interest
+    std::vector<std::string> executables{"openpower-hw-diags"};
+
+    for (const std::string& executable : executables)
+    {
+        try
+        {
+            // get journal messages
+            std::vector<std::string> messages =
+                sdjGetMessages("SYSLOG_IDENTIFIER", executable, 30);
+
+            // Create FFDC file containing the journal messages
+            if (!messages.empty())
+            {
+                i_files.emplace_back(createFFDCTraceFile(messages));
+            }
+        }
+        catch (const std::exception& e)
+        {
+            std::stringstream ss;
+            ss << "createFFDCFiles: " << e.what();
+            trace<level::INFO>(ss.str().c_str());
+        }
+    }
+}
+
+/**
+ * Create FFDCFile objects containing debug data to store in the error log.
+ *
+ * If an error occurs, the error is written to the journal but an exception
+ * is not thrown.
+ *
+ * @param   i_buffer - raw data (if creating raw dump ffdc entry in log)
+ * @return  vector of FFDCFile objects
+ */
+std::vector<util::FFDCFile> createFFDCFiles(char* i_buffer = nullptr,
+                                            size_t i_size  = 0)
+{
+    std::vector<util::FFDCFile> files{};
+
+    // Create raw dump file
+    if ((nullptr != i_buffer) && (0 != i_size))
+    {
+        files.emplace_back(createFFDCRawFile(i_buffer, i_size));
+    }
+
+    // Create trace dump file
+    createFFDCTraceFiles(files);
+
+    return files;
+}
+
+/**
+ * Get file descriptor of exisitng PEL
+ *
+ * The backend logging code will search for a PEL having the provided PEL ID
+ * and return a file descriptor to a file containing this PEL's  raw PEL data.
+ *
+ * @param  i_pelid - the PEL ID
+ * @return file descriptor of file containing the raw PEL data
+ */
+int getPelFd(uint32_t i_pelId)
+{
+    // GetPEL returns file descriptor (int)
+    int fd = -1;
+
+    // Sdbus call specifics
+    constexpr auto service   = "xyz.openbmc_project.Logging";
+    constexpr auto path      = "/xyz/openbmc_project/logging";
+    constexpr auto interface = "org.open_power.Logging.PEL";
+    constexpr auto function  = "GetPEL";
+
+    // Get the PEL file descriptor
+    try
+    {
+        auto bus    = sdbusplus::bus::new_default_system();
+        auto method = bus.new_method_call(service, path, interface, function);
+        method.append(i_pelId);
+
+        auto resp = bus.call(method);
+
+        sdbusplus::message::unix_fd msgFd;
+        resp.read(msgFd);
+        fd = dup(msgFd); // -1 if not found
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        std::stringstream ss;
+        ss << "getPelFd: " << e.what();
+        trace<level::INFO>(ss.str().c_str());
+    }
+
+    // File descriptor or -1 if not found or call failed
+    return fd;
+}
+
+/**
+ * Create a PEL for the specified event type
+ *
+ * The additional data provided in the map will be placed in a user data
+ * section of the PEL and may additionally contain key words to trigger
+ * certain behaviors by the backend logging code. Each set of data described
+ * in the vector of ffdc data will be placed in additional user data sections.
+ *
+ * @param  i_event - the event type
+ * @param  i_additional - map of additional data
+ * @param  9_ffdc - vector of ffdc data
+ * @return The created PEL's platform log-id
+ */
+uint32_t createPel(std::string i_event,
+                   std::map<std::string, std::string> i_additional,
+                   std::vector<util::FFDCTuple> i_ffdc)
+{
+    // CreatePELWithFFDCFiles returns log-id and platform log-id
+    std::tuple<uint32_t, uint32_t> pelResp = {0, 0};
+
+    // Sdbus call specifics
+    constexpr auto level     = "xyz.openbmc_project.Logging.Entry.Level.Error";
+    constexpr auto service   = "xyz.openbmc_project.Logging";
+    constexpr auto path      = "/xyz/openbmc_project/logging";
+    constexpr auto interface = "org.open_power.Logging.PEL";
+    constexpr auto function  = "CreatePELWithFFDCFiles";
+
+    // Need to provide pid when using create or create-with-ffdc methods
+    i_additional.emplace("_PID", std::to_string(getpid()));
+
+    // Create the PEL
+    try
+    {
+        auto bus    = sdbusplus::bus::new_default_system();
+        auto method = bus.new_method_call(service, path, interface, function);
+        method.append(i_event, level, i_additional, i_ffdc);
+
+        auto resp = bus.call(method);
+
+        resp.read(pelResp);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        std::stringstream ss;
+        ss << "createPel: " << e.what();
+        trace<level::INFO>(ss.str().c_str());
+    }
+
+    // pelResp<0> == log-id, pelResp<1> = platform log-id
+    return std::get<1>(pelResp);
+}
+
+/*
+ * Create a PEL from raw PEL data
+ *
+ * The backend logging code will create a PEL based on the specified PEL data.
+ *
+ * @param   i_buffer - buffer containing a raw PEL
+ */
+void createPelRaw(std::vector<uint8_t>& i_buffer)
+{
+    // Sdbus call specifics
+    constexpr auto event     = "xyz.open_power.Attn.Error.Terminate";
+    constexpr auto level     = "xyz.openbmc_project.Logging.Entry.Level.Error";
+    constexpr auto service   = "xyz.openbmc_project.Logging";
+    constexpr auto path      = "/xyz/openbmc_project/logging";
+    constexpr auto interface = "xyz.openbmc_project.Logging.Create";
+    constexpr auto function  = "Create";
+
+    // Create FFDC file from buffer data
+    util::FFDCFile pelFile{util::FFDCFormat::Text};
+    auto fd = pelFile.getFileDescriptor();
+
+    write(fd, i_buffer.data(), i_buffer.size());
+    lseek(fd, 0, SEEK_SET);
+
+    auto filePath = pelFile.getPath();
+
+    // Additional data for log
+    std::map<std::string, std::string> additional;
+    additional.emplace("RAWPEL", filePath.string());
+    additional.emplace("_PID", std::to_string(getpid()));
+
+    // Create the PEL
+    try
+    {
+        auto bus    = sdbusplus::bus::new_default_system();
+        auto method = bus.new_method_call(service, path, interface, function);
+        method.append(event, level, additional);
+        bus.call_noreply(method);
+    }
+    catch (const sdbusplus::exception::SdBusError& e)
+    {
+        std::stringstream ss;
+        ss << "createPelRaw: " << e.what();
+        trace<level::INFO>(ss.str().c_str());
+    }
+}
+
+/**
+ * Create a PEL from an existing PEL
+ *
+ * Create a new PEL based on the specified raw PEL and submit the new PEL
+ * to the backend logging code as a raw PEL. Note that  additional data map
+ * here contains data to be committed to the PEL and it can also be used to
+ * create the PEL as it contains needed information.
+ *
+ * @param   i_buffer - buffer containing a raw PEL
+ * @param   i_additional - additional data to be added to the new PEL
+ */
+void createPelCustom(std::vector<uint8_t>& i_rawPel,
+                     std::map<std::string, std::string> i_additional)
+{
+    // create PEL object from buffer
+    auto tiPel = std::make_unique<pel::PelMinimal>(i_rawPel);
+
+    // The additional data contains the TI info as well as the value for the
+    // subystem that provided the TI info. Get the subystem from additional
+    // data and then populate the prmary SRC and SRC words for the custom PEL
+    // based on the sybsystem's TI info.
+    uint8_t subsystem = std::stoi(i_additional["Subsystem"]);
+    tiPel->setSubsystem(subsystem);
+
+    if (static_cast<uint8_t>(pel::SubsystemID::hypervisor) == subsystem)
+    {
+        // populate hypervisor SRC words
+        tiPel->setSrcWords(std::array<uint32_t, pel::numSrcWords>{
+            (uint32_t)std::stoul(i_additional["0x10 SRC Word 12"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x14 SRC Word 13"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x18 SRC Word 14"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x1c SRC Word 15"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x20 SRC Word 16"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x24 SRC Word 17"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x28 SRC Word 18"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x2c SRC Word 19"], 0, 16)});
+
+        // populate hypervisor primary SRC
+        std::array<char, pel::asciiStringSize> srcChars{'0'};
+        std::string srcString = i_additional["SrcAscii"];
+        srcString.copy(srcChars.data(),
+                       std::min(srcString.size(), pel::asciiStringSize), 0);
+        tiPel->setAsciiString(srcChars);
+    }
+    else
+    {
+        // Populate hostboot SRC words - note HB word 0 from the shared info
+        // data (additional data "0x10 HB Word") is reflected in the PEL as
+        // "reason code" so we zero it here. Also note that the first word
+        // in this group of words starts at word 0 and word 1 does not exits.
+        tiPel->setSrcWords(std::array<uint32_t, pel::numSrcWords>{
+            (uint32_t)0x00000000,
+            (uint32_t)std::stoul(i_additional["0x14 HB Word 2"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x18 HB Word 3"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x1c HB Word 4"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x20 HB Word 5"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x24 HB Word 6"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x28 HB Word 7"], 0, 16),
+            (uint32_t)std::stoul(i_additional["0x2c HB Word 8"], 0, 16)});
+
+        // populate hostboot primary SRC
+        std::array<char, pel::asciiStringSize> srcChars{'0'};
+        std::string srcString = i_additional["0x30 error_data"];
+        srcString.copy(srcChars.data(),
+                       std::min(srcString.size(), pel::asciiStringSize), 0);
+        tiPel->setAsciiString(srcChars);
+    }
+
+    // set severity, event type and action flags
+    tiPel->setSeverity(static_cast<uint8_t>(pel::Severity::termination));
+    tiPel->setType(static_cast<uint8_t>(pel::EventType::na));
+    tiPel->setAction(static_cast<uint16_t>(pel::ActionFlags::service |
+                                           pel::ActionFlags::report |
+                                           pel::ActionFlags::call));
+
+    // The raw PEL that we used as the basis for this custom PEL contains the
+    // attention handler trace data and does not needed to be in this PEL so
+    // we remove it here.
+    tiPel->setSectionCount(tiPel->getSectionCount() - 1);
+
+    // Update the raw PEL with the new custom PEL data
+    tiPel->raw(i_rawPel);
+
+    // create PEL from raw data
+    createPelRaw(i_rawPel);
+}
+
+/**
+ * Log an event handled by the attention handler
+ *
+ * Basic (non TI) events will generate a standard message-registry based PEL
+ *
+ * TI events will create two PEL's. One PEL will be informational and will
+ * contain trace information relevent to attention handler. The second PEL
+ * will be specific to the TI type (including the primary SRC) and will be
+ * based off of the TI information provided to the attention handler through
+ * shared TI info data area.
+ *
+ * @param  i_event - The event type
+ * @param  i_additional - Additional PEL data
+ * @param  i_ffdc - FFDC PEL data
+ */
+void event(EventType i_event, std::map<std::string, std::string>& i_additional,
+           const std::vector<util::FFDCFile>& i_ffdc)
 {
     bool eventValid = false; // assume no event created
+    bool tiEvent    = false; // assume not a terminate event
 
     std::string eventName;
 
@@ -28,15 +428,13 @@
         case EventType::Terminate:
             eventName  = "org.open_power.Attn.Error.Terminate";
             eventValid = true;
+            tiEvent    = true;
             break;
         case EventType::Vital:
             eventName  = "org.open_power.Attn.Error.Vital";
             eventValid = true;
             break;
         case EventType::HwDiagsFail:
-            eventName  = "org.open_power.HwDiags.Error.Fail";
-            eventValid = true;
-            break;
         case EventType::AttentionFail:
             eventName  = "org.open_power.Attn.Error.Fail";
             eventValid = true;
@@ -48,93 +446,118 @@
 
     if (true == eventValid)
     {
-        // Get access to logging interface and method for creating log
-        auto bus = sdbusplus::bus::new_default_system();
+        // Create PEL with additional data and FFDC data. The newly created
+        // PEL's platform log-id will be returned.
+        auto pelId =
+            createPel(eventName, i_additional, createFFDCTuples(i_ffdc));
 
-        // using direct create method (for additional data)
-        auto method = bus.new_method_call(
-            "xyz.openbmc_project.Logging", "/xyz/openbmc_project/logging",
-            "xyz.openbmc_project.Logging.Create", "CreateWithFFDCFiles");
+        // If this is a TI event we will create an additional PEL that is
+        // specific to the subsystem that generated the TI.
+        if (true == tiEvent)
+        {
+            // get file descriptor and size of information PEL
+            int pelFd = getPelFd(pelId);
 
-        // Create FFDC files containing debug data to store in error log
-        std::vector<util::FFDCFile> files{createFFDCFiles()};
+            // if PEL found, read into buffer
+            if (-1 != pelFd)
+            {
+                auto pelSize = lseek(pelFd, 0, SEEK_END);
+                lseek(pelFd, 0, SEEK_SET);
 
-        // Create FFDC tuples used to pass FFDC files to D-Bus method
-        std::vector<FFDCTuple> ffdcTuples{createFFDCTuples(files)};
+                // read information PEL into buffer
+                std::vector<uint8_t> buffer(pelSize);
+                read(pelFd, buffer.data(), buffer.size());
+                close(pelFd);
 
-        // attach additional data
-        method.append(eventName,
-                      "xyz.openbmc_project.Logging.Entry.Level.Error",
-                      i_additional, ffdcTuples);
-
-        // log the event
-        bus.call_noreply(method);
+                // create PEL from buffer
+                createPelCustom(buffer, i_additional);
+            }
+        }
     }
 }
 
-/** @brief commit checkstop event to log */
+/** @brief Commit checkstop event to log */
 void eventCheckstop(std::map<std::string, std::string>& i_errors)
 {
+    // Additional data for log
     std::map<std::string, std::string> additionalData;
 
-    // TODO need multi-error/multi-callout stuff here
-
-    // if analyzer isolated errors
-    if (!(i_errors.empty()))
-    {
-        // FIXME TEMP CODE - begin
-
-        std::string signature = i_errors.begin()->first;
-        std::string chip      = i_errors.begin()->second;
-
-        additionalData["_PID"]      = std::to_string(getpid());
-        additionalData["SIGNATURE"] = signature;
-        additionalData["CHIP_ID"]   = chip;
-
-        // FIXME TEMP CODE -end
-
-        event(EventType::Checkstop, additionalData);
-    }
+    // Create log event with additional data and FFDC data
+    event(EventType::Checkstop, additionalData, createFFDCFiles(nullptr, 0));
 }
 
-/** @brief commit special attention TI event to log */
-void eventTerminate(std::map<std::string, std::string> i_additionalData)
+/**
+ * Commit special attention TI event to log
+ *
+ * Create a event log with provided additional information and standard
+ * FFDC data plus TI FFDC data
+ *
+ * @param i_additional - Additional log data
+ * @param i_ti_InfoData - TI FFDC data
+ */
+void eventTerminate(std::map<std::string, std::string> i_additionalData,
+                    char* i_tiInfoData)
 {
-    event(EventType::Terminate, i_additionalData);
+    // Create log event with aodditional data and FFDC data
+    event(EventType::Terminate, i_additionalData,
+          createFFDCFiles(i_tiInfoData, 0x53));
 }
 
-/** @brief commit SBE vital event to log */
+/** @brief Commit SBE vital event to log */
 void eventVital()
 {
+    // Additional data for log
     std::map<std::string, std::string> additionalData;
 
-    additionalData["_PID"] = std::to_string(getpid());
-
-    event(EventType::Vital, additionalData);
+    // Create log event with additional data and FFDC data
+    event(EventType::Vital, additionalData, createFFDCFiles(nullptr, 0));
 }
 
-/** @brief commit analyzer failure event to log */
+/**
+ * Commit analyzer failure event to log
+ *
+ * Create an event log containing the specified error code.
+ *
+ * @param i_error - Error code
+ */
 void eventHwDiagsFail(int i_error)
 {
+    // Additiona data for log
     std::map<std::string, std::string> additionalData;
-
-    additionalData["_PID"] = std::to_string(getpid());
-
-    event(EventType::HwDiagsFail, additionalData);
-}
-
-/** @brief commit attention handler failure event to log */
-void eventAttentionFail(int i_error)
-{
-    std::map<std::string, std::string> additionalData;
-
-    additionalData["_PID"]       = std::to_string(getpid());
     additionalData["ERROR_CODE"] = std::to_string(i_error);
 
-    event(EventType::AttentionFail, additionalData);
+    // Create log event with additional data and FFDC data
+    event(EventType::HwDiagsFail, additionalData, createFFDCFiles(nullptr, 0));
 }
 
-/** @brief parse systemd journal message field */
+/**
+ * Commit attention handler failure event to log
+ *
+ * Create an event log containing the specified error code.
+ *
+ * @param i_error - Error code
+ */
+void eventAttentionFail(int i_error)
+{
+    // Additional data for log
+    std::map<std::string, std::string> additionalData;
+    additionalData["ERROR_CODE"] = std::to_string(i_error);
+
+    // Create log event with additional data and FFDC data
+    event(EventType::AttentionFail, additionalData,
+          createFFDCFiles(nullptr, 0));
+}
+
+/**
+ * Parse systemd journal message field
+ *
+ * Parse the journal looking for the specified field and return the journal
+ * data for that field.
+ *
+ * @param  journal - The journal to parse
+ * @param  field - Field containing the data to retrieve
+ * @return Data for the speciefied field
+ */
 std::string sdjGetFieldValue(sd_journal* journal, const char* field)
 {
     const char* data{nullptr};
@@ -167,7 +590,17 @@
     }
 }
 
-/** @brief get messages from systemd journal */
+/**
+ * Gather messages from the journal
+ *
+ * Fetch journal entry data for all entries with the specified field equal to
+ * the specified value.
+ *
+ * @param   field - Field to search on
+ * @param   fieldValue -  Value to search for
+ * @param   max - Maximum number of messages fetch
+ * @return  Vector of journal entry data
+ */
 std::vector<std::string> sdjGetMessages(const std::string& field,
                                         const std::string& fieldValue,
                                         unsigned int max)
@@ -227,78 +660,4 @@
     return messages;
 }
 
-/** @brief create a file containing FFDC data */
-util::FFDCFile createFFDCFile(const std::vector<std::string>& lines)
-{
-    // Create FFDC file of type Text
-    util::FFDCFile file{util::FFDCFormat::Text};
-    int fd = file.getFileDescriptor();
-
-    // Write FFDC lines to file
-    std::string buffer;
-    for (const std::string& line : lines)
-    {
-        // Copy line to buffer.  Add newline if necessary.
-        buffer = line;
-        if (line.empty() || (line.back() != '\n'))
-        {
-            buffer += '\n';
-        }
-
-        // write buffer to file
-        write(fd, buffer.c_str(), buffer.size());
-    }
-
-    // Seek to beginning of file so error logging system can read data
-    lseek(fd, 0, SEEK_SET);
-
-    return file;
-}
-
-/** @brief Create FDDC files from journal messages of relevant executables */
-std::vector<util::FFDCFile> createFFDCFiles()
-{
-    std::vector<util::FFDCFile> files{};
-
-    // Executables of interest
-    std::vector<std::string> executables{"openpower-hw-diags"};
-
-    for (const std::string& executable : executables)
-    {
-        try
-        {
-            // get journal messages
-            std::vector<std::string> messages =
-                sdjGetMessages("SYSLOG_IDENTIFIER", executable, 30);
-
-            // Create FFDC file containing the journal messages
-            if (!messages.empty())
-            {
-                files.emplace_back(createFFDCFile(messages));
-            }
-        }
-        catch (const std::exception& e)
-        {
-            std::stringstream ss;
-            ss << "createFFDCFiles: " << e.what();
-            trace<level::INFO>(ss.str().c_str());
-        }
-    }
-
-    return files;
-}
-
-/** create tuples of FFDC files */
-std::vector<FFDCTuple> createFFDCTuples(std::vector<util::FFDCFile>& files)
-{
-    std::vector<FFDCTuple> ffdcTuples{};
-    for (util::FFDCFile& file : files)
-    {
-        ffdcTuples.emplace_back(
-            file.getFormat(), file.getSubType(), file.getVersion(),
-            sdbusplus::message::unix_fd(file.getFileDescriptor()));
-    }
-    return ffdcTuples;
-}
-
 } // namespace attn