1 #include <attn/attn_dbus.hpp> 2 #include <attn/attn_dump.hpp> 3 #include <attn/attn_logging.hpp> 4 #include <sdbusplus/bus.hpp> 5 #include <sdbusplus/exception.hpp> 6 #include <util/trace.hpp> 7 8 constexpr uint64_t dumpTimeout = 3600000000; // microseconds 9 10 constexpr auto operationStatusInProgress = 11 "xyz.openbmc_project.Common.Progress.OperationStatus.InProgress"; 12 13 namespace attn 14 { 15 16 /** 17 * Callback for dump request properties change signal monitor 18 * 19 * @param[in] i_msg Dbus message from the dbus match infrastructure 20 * @param[out] o_dumpStatus Dump status dbus response string 21 * @return Always non-zero indicating no error, no cascading callbacks 22 */ 23 uint dumpStatusChanged(sdbusplus::message_t& i_msg, std::string& o_dumpStatus) 24 { 25 // reply (msg) will be a property change message 26 std::string interface; 27 std::map<std::string, std::variant<std::string, uint8_t>> property; 28 i_msg.read(interface, property); 29 30 // looking for property Status changes 31 std::string propertyType = "Status"; 32 auto dumpStatus = property.find(propertyType); 33 34 if (dumpStatus != property.end()) 35 { 36 const std::string* status = 37 std::get_if<std::string>(&(dumpStatus->second)); 38 39 if (nullptr != status) 40 { 41 o_dumpStatus = *status; 42 } 43 } 44 45 return 1; // non-negative return code for successful callback 46 } 47 48 /** 49 * Register a callback for dump progress status changes 50 * 51 * @param[in] i_path The object path of the dump to monitor 52 */ 53 void monitorDump(const std::string& i_path) 54 { 55 // setup the signal match rules and callback 56 std::string matchInterface = "xyz.openbmc_project.Common.Progress"; 57 auto bus = sdbusplus::bus::new_system(); 58 59 // monitor dump status change property, will update dumpStatus 60 std::string dumpStatus = "requested"; 61 std::unique_ptr<sdbusplus::bus::match_t> match = 62 std::make_unique<sdbusplus::bus::match_t>( 63 bus, 64 sdbusplus::bus::match::rules::propertiesChanged( 65 i_path.c_str(), matchInterface.c_str()), 66 [&](auto& msg) { return dumpStatusChanged(msg, dumpStatus); }); 67 68 // wait for dump status to be completed (complete == true) 69 trace::inf("dump requested %s", i_path.c_str()); 70 71 // wait for dump status not InProgress or timeout 72 uint64_t timeRemaining = dumpTimeout; 73 74 std::chrono::steady_clock::time_point begin = 75 std::chrono::steady_clock::now(); 76 77 while (("requested" == dumpStatus || 78 operationStatusInProgress == dumpStatus) && 79 0 != timeRemaining) 80 { 81 bus.wait(timeRemaining); 82 uint64_t timeElapsed = 83 std::chrono::duration_cast<std::chrono::microseconds>( 84 std::chrono::steady_clock::now() - begin) 85 .count(); 86 87 timeRemaining = 88 timeElapsed > timeRemaining ? 0 : timeRemaining - timeElapsed; 89 90 bus.process_discard(); 91 } 92 93 if (0 == timeRemaining) 94 { 95 trace::err("dump request timed out after %" PRIu64 " microseconds", 96 dumpTimeout); 97 } 98 99 trace::inf("dump status: %s", dumpStatus.c_str()); 100 } 101 102 /** Request a dump from the dump manager */ 103 void requestDump(uint32_t i_logId, const DumpParameters& i_dumpParameters) 104 { 105 constexpr auto path = "/org/openpower/dump"; 106 constexpr auto interface = "xyz.openbmc_project.Dump.Create"; 107 constexpr auto function = "CreateDump"; 108 109 sdbusplus::message_t method; 110 111 if (0 == dbusMethod(path, interface, function, method)) 112 { 113 try 114 { 115 // dbus call arguments 116 std::map<std::string, std::variant<std::string, uint64_t>> 117 createParams; 118 createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] = 119 uint64_t(i_logId); 120 if (DumpType::Hostboot == i_dumpParameters.dumpType) 121 { 122 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] = 123 "com.ibm.Dump.Create.DumpType.Hostboot"; 124 } 125 else if (DumpType::Hardware == i_dumpParameters.dumpType) 126 { 127 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] = 128 "com.ibm.Dump.Create.DumpType.Hardware"; 129 createParams 130 ["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] = 131 i_dumpParameters.unitId; 132 } 133 else if (DumpType::SBE == i_dumpParameters.dumpType) 134 { 135 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] = 136 "com.ibm.Dump.Create.DumpType.SBE"; 137 createParams 138 ["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] = 139 i_dumpParameters.unitId; 140 } 141 method.append(createParams); 142 143 // using system dbus 144 auto bus = sdbusplus::bus::new_system(); 145 auto response = bus.call(method); 146 147 // reply will be type dbus::ObjectPath 148 sdbusplus::message::object_path reply; 149 response.read(reply); 150 151 // monitor dump progress 152 monitorDump(reply); 153 } 154 catch (const sdbusplus::exception::SdBusError& e) 155 { 156 trace::err("requestDump exception"); 157 trace::err(e.what()); 158 } 159 } 160 } 161 162 } // namespace attn 163