1 #include "occ_ffdc.hpp" 2 3 #include "elog-errors.hpp" 4 #include "utils.hpp" 5 6 #include <errno.h> 7 #include <fcntl.h> 8 #include <stdio.h> 9 #include <sys/ioctl.h> 10 #include <unistd.h> 11 12 #include <org/open_power/OCC/Device/error.hpp> 13 #include <phosphor-logging/elog.hpp> 14 #include <phosphor-logging/log.hpp> 15 #include <xyz/openbmc_project/Common/error.hpp> 16 #include <xyz/openbmc_project/Logging/Create/server.hpp> 17 18 namespace open_power 19 { 20 namespace occ 21 { 22 23 static constexpr size_t max_ffdc_size = 8192; 24 static constexpr size_t sbe_status_header_size = 8; 25 26 static constexpr auto loggingObjectPath = "/xyz/openbmc_project/logging"; 27 static constexpr auto loggingInterface = "org.open_power.Logging.PEL"; 28 29 using namespace phosphor::logging; 30 using namespace sdbusplus::org::open_power::OCC::Device::Error; 31 using InternalFailure = 32 sdbusplus::xyz::openbmc_project::Common::Error::InternalFailure; 33 34 uint32_t FFDC::createPEL(const char* path, uint32_t src6, const char* msg, 35 int fd) 36 { 37 uint32_t plid = 0; 38 std::vector<std::tuple< 39 sdbusplus::xyz::openbmc_project::Logging::server::Create::FFDCFormat, 40 uint8_t, uint8_t, sdbusplus::message::unix_fd>> 41 pelFFDCInfo; 42 43 log<level::INFO>("Creating PEL with SBE FFDC", entry("SRC6=%08x", src6)); 44 45 if (fd > 0) 46 { 47 pelFFDCInfo.push_back(std::make_tuple( 48 sdbusplus::xyz::openbmc_project::Logging::server::Create:: 49 FFDCFormat::Custom, 50 static_cast<uint8_t>(0xCB), static_cast<uint8_t>(0x01), fd)); 51 } 52 53 std::map<std::string, std::string> additionalData; 54 additionalData.emplace("SRC6", std::to_string(src6)); 55 additionalData.emplace("_PID", std::to_string(getpid())); 56 additionalData.emplace("SBE_ERR_MSG", msg); 57 58 std::string service = 59 utils::getService(loggingObjectPath, loggingInterface); 60 auto& bus = utils::getBus(); 61 62 try 63 { 64 auto method = 65 bus.new_method_call(service.c_str(), loggingObjectPath, 66 loggingInterface, "CreatePELWithFFDCFiles"); 67 auto level = 68 sdbusplus::xyz::openbmc_project::Logging::server::convertForMessage( 69 sdbusplus::xyz::openbmc_project::Logging::server::Entry::Level:: 70 Error); 71 method.append(path, level, additionalData, pelFFDCInfo); 72 auto response = bus.call(method); 73 std::tuple<uint32_t, uint32_t> reply = {0, 0}; 74 75 response.read(reply); 76 plid = std::get<1>(reply); 77 } 78 catch (const sdbusplus::exception::exception& e) 79 { 80 log<level::ERR>("Failed to create PEL"); 81 } 82 83 return plid; 84 } 85 86 // Reads the FFDC file and create an error log 87 void FFDC::analyzeEvent() 88 { 89 int tfd = -1; 90 size_t total = 0; 91 auto data = std::make_unique<unsigned char[]>(max_ffdc_size); 92 while (total < max_ffdc_size) 93 { 94 auto r = read(fd, data.get() + total, max_ffdc_size - total); 95 if (r < 0) 96 { 97 elog<ReadFailure>( 98 phosphor::logging::org::open_power::OCC::Device::ReadFailure:: 99 CALLOUT_ERRNO(errno), 100 phosphor::logging::org::open_power::OCC::Device::ReadFailure:: 101 CALLOUT_DEVICE_PATH(file.c_str())); 102 return; 103 } 104 if (!r) 105 { 106 break; 107 } 108 total += r; 109 } 110 111 lseek(fd, 0, SEEK_SET); 112 113 uint32_t src6 = instance << 16; 114 src6 |= *(data.get() + 2) << 8; 115 src6 |= *(data.get() + 3); 116 117 if (total > sbe_status_header_size) 118 { 119 std::string templateString = 120 fs::temp_directory_path() / "OCC_FFDC_XXXXXX"; 121 tfd = mkostemp(templateString.data(), O_RDWR); 122 if (tfd < 0) 123 { 124 log<level::ERR>("Couldn't create temporary FFDC file"); 125 } 126 else 127 { 128 temporaryFiles.emplace_back(templateString, tfd); 129 size_t written = sbe_status_header_size; 130 while (written < total) 131 { 132 auto r = write(tfd, data.get() + written, total - written); 133 if (r < 0) 134 { 135 close(temporaryFiles.back().second); 136 fs::remove(temporaryFiles.back().first); 137 temporaryFiles.pop_back(); 138 tfd = -1; 139 log<level::ERR>("Couldn't write temporary FFDC file"); 140 break; 141 } 142 if (!r) 143 { 144 break; 145 } 146 written += r; 147 } 148 } 149 } 150 151 createPEL("org.open_power.Processor.Error.SbeChipOpFailure", src6, 152 "SBE command reported error", tfd); 153 } 154 155 } // namespace occ 156 } // namespace open_power 157