1 #include "dump_utils.hpp" 2 3 #include <phosphor-logging/elog-errors.hpp> 4 #include <phosphor-logging/elog.hpp> 5 #include <phosphor-logging/lg2.hpp> 6 #include <phosphor-logging/log.hpp> 7 #include <xyz/openbmc_project/Common/File/error.hpp> 8 9 #include <format> 10 #include <fstream> 11 #include <string> 12 13 namespace openpower::dump::util 14 { 15 using namespace phosphor::logging; 16 17 static void monitorDumpCreation(const std::string& path, const uint32_t timeout) 18 { 19 bool inProgress = true; 20 auto bus = sdbusplus::bus::new_system(); 21 auto match = sdbusplus::bus::match::match( 22 bus, 23 sdbusplus::bus::match::rules::propertiesChanged( 24 path, "xyz.openbmc_project.Common.Progress"), 25 [&](sdbusplus::message::message& msg) { 26 std::string interface; 27 std::map<std::string, std::variant<std::string, uint8_t>> property; 28 msg.read(interface, property); 29 30 const auto dumpStatus = property.find("Status"); 31 if (dumpStatus != property.end()) 32 { 33 const std::string* status = 34 std::get_if<std::string>(&(dumpStatus->second)); 35 if (status && 36 *status != 37 "xyz.openbmc_project.Common.Progress.OperationStatus.InProgress") 38 { 39 lg2::info("Dump status({STATUS}) : path={PATH}", "STATUS", 40 status->c_str(), "PATH", path.c_str()); 41 inProgress = false; 42 } 43 } 44 }); 45 46 // Timeout management 47 for (uint32_t secondsCount = 0; inProgress && secondsCount < timeout; 48 ++secondsCount) 49 { 50 bus.wait(std::chrono::seconds(1)); 51 bus.process_discard(); 52 } 53 54 if (inProgress) 55 { 56 lg2::error("Dump progress timeout; dump may not be complete."); 57 } 58 } 59 60 void requestSBEDump(const uint32_t failingUnit, const uint32_t eid, 61 SBETypes sbeType) 62 { 63 lg2::info("Requesting Dump PEL({EID}) chip position({FAILINGUNIT})", "EID", 64 eid, "FAILINGUNIT", failingUnit); 65 66 auto path = sbeTypeAttributes.at(sbeType).dumpPath.c_str(); 67 constexpr auto interface = "xyz.openbmc_project.Dump.Create"; 68 constexpr auto function = "CreateDump"; 69 70 try 71 { 72 auto bus = sdbusplus::bus::new_default(); 73 auto service = getService(bus, interface, path); 74 auto method = bus.new_method_call(service.c_str(), path, interface, 75 function); 76 77 std::unordered_map<std::string, std::variant<std::string, uint64_t>> 78 createParams = { 79 {"com.ibm.Dump.Create.CreateParameters.ErrorLogId", 80 uint64_t(eid)}, 81 {"com.ibm.Dump.Create.CreateParameters.FailingUnitId", 82 uint64_t(failingUnit)}}; 83 84 method.append(createParams); 85 sdbusplus::message::object_path reply; 86 bus.call(method).read(reply); 87 88 monitorDumpCreation(reply.str, SBE_DUMP_TIMEOUT); 89 } 90 catch (const sdbusplus::exception::exception& e) 91 { 92 lg2::error("D-Bus call createDump exception OBJPATH={OBJPATH}, " 93 "INTERFACE={INTERFACE}, EXCEPTION={ERROR}", 94 "OBJPATH", path, "INTERFACE", interface, "ERROR", e); 95 constexpr auto ERROR_DUMP_DISABLED = 96 "xyz.openbmc_project.Dump.Create.Error.Disabled"; 97 if (e.name() == ERROR_DUMP_DISABLED) 98 { 99 // Dump is disabled, Skip the dump collection. 100 lg2::info("Dump is disabled unit({FAILINGUNIT}), " 101 "skipping dump collection", 102 "FAILINGUNIT", failingUnit); 103 } 104 else 105 { 106 throw; 107 } 108 } 109 catch (const std::exception& e) 110 { 111 throw e; 112 } 113 } 114 115 std::string getService(sdbusplus::bus::bus& bus, const std::string& intf, 116 const std::string& path) 117 { 118 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; 119 constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; 120 constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; 121 try 122 { 123 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, 124 MAPPER_INTERFACE, "GetObject"); 125 126 mapper.append(path, std::vector<std::string>({intf})); 127 128 auto mapperResponseMsg = bus.call(mapper); 129 std::map<std::string, std::vector<std::string>> mapperResponse; 130 mapperResponseMsg.read(mapperResponse); 131 132 if (mapperResponse.empty()) 133 { 134 lg2::error( 135 "Empty mapper response for GetObject interface({INTERFACE}), " 136 "path({PATH})", 137 "INTERFACE", intf, "PATH", path); 138 139 throw std::runtime_error("Empty mapper response for GetObject"); 140 } 141 return mapperResponse.begin()->first; 142 } 143 catch (const sdbusplus::exception::exception& ex) 144 { 145 lg2::error( 146 "Mapper call failed for GetObject errorMsg({ERROR}), path({PATH})," 147 "interface({INTERFACE})", 148 "ERROR", ex, "PATH", path, "INTERFACE", intf); 149 150 throw; 151 } 152 } 153 154 } // namespace openpower::dump::util 155