1 #include "config.h" 2 3 #include "dump_utils.hpp" 4 5 #include "util.hpp" 6 7 #include <phosphor-logging/log.hpp> 8 #include <sdbusplus/bus.hpp> 9 #include <sdbusplus/exception.hpp> 10 #include <sdbusplus/server.hpp> 11 12 #include <format> 13 14 namespace openpower::phal::dump 15 { 16 17 using namespace phosphor::logging; 18 19 /** 20 * Callback for dump request properties change signal monitor 21 * 22 * @param[in] msg Dbus message from the dbus match infrastructure 23 * @param[in] path The object path we are monitoring 24 * @param[out] inProgress Used to break out of our dbus wait loop 25 * @reutn Always non-zero indicating no error, no cascading callbacks 26 */ 27 uint32_t dumpStatusChanged(sdbusplus::message_t& msg, const std::string& path, 28 bool& inProgress) 29 { 30 // reply (msg) will be a property change message 31 std::string interface; 32 std::map<std::string, std::variant<std::string, uint8_t>> property; 33 msg.read(interface, property); 34 35 // looking for property Status changes 36 std::string propertyType = "Status"; 37 auto dumpStatus = property.find(propertyType); 38 39 if (dumpStatus != property.end()) 40 { 41 const std::string* status = 42 std::get_if<std::string>(&(dumpStatus->second)); 43 44 if ((nullptr != status) && ("xyz.openbmc_project.Common.Progress." 45 "OperationStatus.InProgress" != *status)) 46 { 47 // dump is done, trace some info and change in progress flag 48 log<level::INFO>(std::format("Dump status({}) : path={}", 49 status->c_str(), path.c_str()) 50 .c_str()); 51 inProgress = false; 52 } 53 } 54 55 return 1; // non-negative return code for successful callback 56 } 57 58 /** 59 * Register a callback for dump progress status changes 60 * 61 * @param[in] path The object path of the dump to monitor 62 * @param timeout - timeout - timeout interval in seconds 63 */ 64 void monitorDump(const std::string& path, const uint32_t timeout) 65 { 66 bool inProgress = true; // callback will update this 67 68 // setup the signal match rules and callback 69 std::string matchInterface = "xyz.openbmc_project.Common.Progress"; 70 auto bus = sdbusplus::bus::new_system(); 71 72 std::unique_ptr<sdbusplus::bus::match_t> match = 73 std::make_unique<sdbusplus::bus::match_t>( 74 bus, 75 sdbusplus::bus::match::rules::propertiesChanged( 76 path.c_str(), matchInterface.c_str()), 77 [&](auto& msg) { 78 return dumpStatusChanged(msg, path, inProgress); 79 }); 80 81 // wait for dump status to be completed (complete == true) 82 // or until timeout interval 83 log<level::INFO>("dump requested (waiting)"); 84 bool timedOut = false; 85 uint32_t secondsCount = 0; 86 while ((true == inProgress) && !timedOut) 87 { 88 bus.wait(std::chrono::seconds(1)); 89 bus.process_discard(); 90 91 if (++secondsCount == timeout) 92 { 93 timedOut = true; 94 } 95 } 96 if (timedOut) 97 { 98 log<level::ERR>("Dump progress status did not change to " 99 "complete within the timeout interval, exiting..."); 100 } 101 } 102 103 void requestDump(const DumpParameters& dumpParameters) 104 { 105 log<level::INFO>(std::format("Requesting Dump PEL({}) Index({})", 106 dumpParameters.logId, dumpParameters.unitId) 107 .c_str()); 108 109 constexpr auto path = OP_DUMP_OBJ_PATH; 110 constexpr auto interface = "xyz.openbmc_project.Dump.Create"; 111 constexpr auto function = "CreateDump"; 112 113 sdbusplus::message_t method; 114 115 auto bus = sdbusplus::bus::new_default(); 116 117 try 118 { 119 std::string service = util::getService(bus, path, interface); 120 auto method = bus.new_method_call(service.c_str(), path, interface, 121 function); 122 123 // dbus call arguments 124 std::map<std::string, std::variant<std::string, uint64_t>> createParams; 125 createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] = 126 uint64_t(dumpParameters.logId); 127 if (DumpType::SBE == dumpParameters.dumpType) 128 { 129 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] = 130 "com.ibm.Dump.Create.DumpType.SBE"; 131 createParams["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] = 132 dumpParameters.unitId; 133 } 134 method.append(createParams); 135 136 auto response = bus.call(method); 137 138 // reply will be type dbus::ObjectPath 139 sdbusplus::message::object_path reply; 140 response.read(reply); 141 142 // monitor dump progress 143 monitorDump(reply, dumpParameters.timeout); 144 } 145 catch (const sdbusplus::exception_t& e) 146 { 147 log<level::ERR>(std::format("D-Bus call createDump exception", 148 "OBJPATH={}, INTERFACE={}, EXCEPTION={}", 149 path, interface, e.what()) 150 .c_str()); 151 constexpr auto ERROR_DUMP_DISABLED = 152 "xyz.openbmc_project.Dump.Create.Error.Disabled"; 153 if (e.name() == ERROR_DUMP_DISABLED) 154 { 155 // Dump is disabled, Skip the dump collection. 156 log<level::INFO>( 157 std::format("Dump is disabled on({}), skipping dump collection", 158 dumpParameters.unitId) 159 .c_str()); 160 } 161 else 162 { 163 throw std::runtime_error( 164 "Error in invoking D-Bus createDump interface"); 165 } 166 } 167 catch (const std::exception& e) 168 { 169 throw e; 170 } 171 } 172 173 } // namespace openpower::phal::dump 174