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_t( 22 bus, 23 sdbusplus::bus::match::rules::propertiesChanged( 24 path, "xyz.openbmc_project.Common.Progress"), 25 [&](sdbusplus::message_t& 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( 64 "Requesting Dump PEL({EID}) chip({CHIPTYPE}) position({FAILINGUNIT})", 65 "EID", eid, "CHIPTYPE", sbeTypeAttributes.at(sbeType).chipName, 66 "FAILINGUNIT", failingUnit); 67 68 constexpr auto path = "/xyz/openbmc_project/dump/system"; 69 auto dumpRequestType = sbeTypeAttributes.at(sbeType).dumpType; 70 constexpr auto interface = "xyz.openbmc_project.Dump.Create"; 71 constexpr auto function = "CreateDump"; 72 73 try 74 { 75 auto bus = sdbusplus::bus::new_default(); 76 auto service = getService(bus, interface, path); 77 auto method = 78 bus.new_method_call(service.c_str(), path, interface, function); 79 80 std::unordered_map<std::string, std::variant<std::string, uint64_t>> 81 createParams = { 82 {"com.ibm.Dump.Create.CreateParameters.DumpType", 83 dumpRequestType}, 84 {"com.ibm.Dump.Create.CreateParameters.ErrorLogId", 85 uint64_t(eid)}, 86 {"com.ibm.Dump.Create.CreateParameters.FailingUnitId", 87 uint64_t(failingUnit)}}; 88 89 method.append(createParams); 90 sdbusplus::message::object_path reply; 91 bus.call(method).read(reply); 92 93 monitorDumpCreation(reply.str, SBE_DUMP_TIMEOUT); 94 } 95 catch (const sdbusplus::exception_t& e) 96 { 97 lg2::error("D-Bus call createDump exception OBJPATH={OBJPATH}, " 98 "INTERFACE={INTERFACE}, EXCEPTION={ERROR}", 99 "OBJPATH", path, "INTERFACE", interface, "ERROR", e); 100 constexpr auto ERROR_DUMP_DISABLED = 101 "xyz.openbmc_project.Dump.Create.Error.Disabled"; 102 if (e.name() == ERROR_DUMP_DISABLED) 103 { 104 // Dump is disabled, Skip the dump collection. 105 lg2::info("Dump is disabled unit({FAILINGUNIT}), " 106 "skipping dump collection", 107 "FAILINGUNIT", failingUnit); 108 } 109 else 110 { 111 throw; 112 } 113 } 114 catch (const std::exception& e) 115 { 116 throw e; 117 } 118 } 119 120 std::string getService(sdbusplus::bus_t& bus, const std::string& intf, 121 const std::string& path) 122 { 123 constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; 124 constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; 125 constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; 126 try 127 { 128 auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, 129 MAPPER_INTERFACE, "GetObject"); 130 131 mapper.append(path, std::vector<std::string>({intf})); 132 133 auto mapperResponseMsg = bus.call(mapper); 134 std::map<std::string, std::vector<std::string>> mapperResponse; 135 mapperResponseMsg.read(mapperResponse); 136 137 if (mapperResponse.empty()) 138 { 139 lg2::error( 140 "Empty mapper response for GetObject interface({INTERFACE}), " 141 "path({PATH})", 142 "INTERFACE", intf, "PATH", path); 143 144 throw std::runtime_error("Empty mapper response for GetObject"); 145 } 146 return mapperResponse.begin()->first; 147 } 148 catch (const sdbusplus::exception_t& ex) 149 { 150 lg2::error( 151 "Mapper call failed for GetObject errorMsg({ERROR}), path({PATH})," 152 "interface({INTERFACE})", 153 "ERROR", ex, "PATH", path, "INTERFACE", intf); 154 155 throw; 156 } 157 } 158 159 } // namespace openpower::dump::util 160