| #include "phal_error.hpp" | |
| #include "create_pel.hpp" | |
| #include <libekb.H> | |
| #include <libipl.H> | |
| #include <iomanip> | |
| #include <phosphor-logging/elog.hpp> | |
| #include <sstream> | |
| namespace openpower | |
| { | |
| namespace pel | |
| { | |
| using namespace phosphor::logging; | |
| namespace detail | |
| { | |
| // keys need to be unique so using counter value to generate unique key | |
| static int counter = 0; | |
| // list of debug traces | |
| static std::vector<std::pair<std::string, std::string>> traceLog; | |
| void processLogTraceCallback(void* private_data, const char* fmt, va_list ap) | |
| { | |
| va_list vap; | |
| va_copy(vap, ap); | |
| std::vector<char> log(1 + std::vsnprintf(nullptr, 0, fmt, ap)); | |
| std::vsnprintf(log.data(), log.size(), fmt, vap); | |
| va_end(vap); | |
| std::string logstr(log.begin(), log.end()); | |
| // ignore stray characters in log traces coming from ekb | |
| // example: "\n", which are good for print to screen | |
| if (logstr.length() < 5) | |
| { | |
| return; | |
| } | |
| char timeBuf[80]; | |
| time_t t = time(0); | |
| tm myTm{}; | |
| gmtime_r(&t, &myTm); | |
| strftime(timeBuf, 80, "%Y-%m-%d %H:%M:%S", &myTm); | |
| // key values need to be unique for PEL | |
| // TODO #openbmc/dev/issues/1563 | |
| // If written to Json no need to worry about unique KEY | |
| std::stringstream str; | |
| str << std::setfill('0'); | |
| str << "LOG" << std::setw(3) << counter; | |
| str << " " << timeBuf; | |
| traceLog.emplace_back(std::make_pair(str.str(), std::move(logstr))); | |
| counter++; | |
| } | |
| void processBootErrorCallback(bool status) | |
| { | |
| log<level::INFO>("processBootCallback ", entry("STATUS=%d", status)); | |
| try | |
| { | |
| // If failure in hwp execution | |
| if (!status) | |
| { | |
| FFDCData ffdc = libekb_get_ffdc(); | |
| ffdc.insert(ffdc.end(), traceLog.begin(), traceLog.end()); | |
| openpower::pel::createBootErrorPEL(ffdc); | |
| } | |
| } | |
| catch (std::exception& ex) | |
| { | |
| reset(); | |
| throw ex; | |
| } | |
| reset(); | |
| } | |
| void reset() | |
| { | |
| // reset the trace log and counter | |
| traceLog.clear(); | |
| counter = 0; | |
| } | |
| } // namespace detail | |
| void addBootErrorCallbacks() | |
| { | |
| // set log level to info | |
| ipl_set_loglevel(IPL_INFO); | |
| // add callback for debug traces | |
| ipl_set_logfunc(detail::processLogTraceCallback, NULL); | |
| // add callback for ipl failures | |
| ipl_set_app_callback_func(detail::processBootErrorCallback); | |
| } | |
| } // namespace pel | |
| } // namespace openpower |