#include "dump_utils.hpp" #include #include #include #include #include #include #include #include namespace openpower::dump::util { using namespace phosphor::logging; static void monitorDumpCreation(const std::string& path, const uint32_t timeout) { bool inProgress = true; auto bus = sdbusplus::bus::new_system(); auto match = sdbusplus::bus::match_t( bus, sdbusplus::bus::match::rules::propertiesChanged( path, "xyz.openbmc_project.Common.Progress"), [&](sdbusplus::message_t& msg) { std::string interface; std::map> property; msg.read(interface, property); const auto dumpStatus = property.find("Status"); if (dumpStatus != property.end()) { const std::string* status = std::get_if(&(dumpStatus->second)); if (status && *status != "xyz.openbmc_project.Common.Progress.OperationStatus.InProgress") { lg2::info("Dump status({STATUS}) : path={PATH}", "STATUS", status->c_str(), "PATH", path.c_str()); inProgress = false; } } }); // Timeout management for (uint32_t secondsCount = 0; inProgress && secondsCount < timeout; ++secondsCount) { bus.wait(std::chrono::seconds(1)); bus.process_discard(); } if (inProgress) { lg2::error("Dump progress timeout; dump may not be complete."); } } void requestSBEDump(const uint32_t failingUnit, const uint32_t eid, SBETypes sbeType) { lg2::info( "Requesting Dump PEL({EID}) chip({CHIPTYPE}) position({FAILINGUNIT})", "EID", eid, "CHIPTYPE", sbeTypeAttributes.at(sbeType).chipName, "FAILINGUNIT", failingUnit); constexpr auto path = "/xyz/openbmc_project/dump/system"; auto dumpRequestType = sbeTypeAttributes.at(sbeType).dumpType; constexpr auto interface = "xyz.openbmc_project.Dump.Create"; constexpr auto function = "CreateDump"; try { auto bus = sdbusplus::bus::new_default(); auto service = getService(bus, interface, path); auto method = bus.new_method_call(service.c_str(), path, interface, function); std::unordered_map> createParams = { {"com.ibm.Dump.Create.CreateParameters.DumpType", dumpRequestType}, {"com.ibm.Dump.Create.CreateParameters.ErrorLogId", uint64_t(eid)}, {"com.ibm.Dump.Create.CreateParameters.FailingUnitId", uint64_t(failingUnit)}}; method.append(createParams); sdbusplus::message::object_path reply; bus.call(method).read(reply); monitorDumpCreation(reply.str, SBE_DUMP_TIMEOUT); } catch (const sdbusplus::exception_t& e) { lg2::error("D-Bus call createDump exception OBJPATH={OBJPATH}, " "INTERFACE={INTERFACE}, EXCEPTION={ERROR}", "OBJPATH", path, "INTERFACE", interface, "ERROR", e); constexpr auto ERROR_DUMP_DISABLED = "xyz.openbmc_project.Dump.Create.Error.Disabled"; if (e.name() == ERROR_DUMP_DISABLED) { // Dump is disabled, Skip the dump collection. lg2::info("Dump is disabled unit({FAILINGUNIT}), " "skipping dump collection", "FAILINGUNIT", failingUnit); } else { throw; } } catch (const std::exception& e) { throw e; } } std::string getService(sdbusplus::bus_t& bus, const std::string& intf, const std::string& path) { constexpr auto MAPPER_BUSNAME = "xyz.openbmc_project.ObjectMapper"; constexpr auto MAPPER_PATH = "/xyz/openbmc_project/object_mapper"; constexpr auto MAPPER_INTERFACE = "xyz.openbmc_project.ObjectMapper"; try { auto mapper = bus.new_method_call(MAPPER_BUSNAME, MAPPER_PATH, MAPPER_INTERFACE, "GetObject"); mapper.append(path, std::vector({intf})); auto mapperResponseMsg = bus.call(mapper); std::map> mapperResponse; mapperResponseMsg.read(mapperResponse); if (mapperResponse.empty()) { lg2::error( "Empty mapper response for GetObject interface({INTERFACE}), " "path({PATH})", "INTERFACE", intf, "PATH", path); throw std::runtime_error("Empty mapper response for GetObject"); } return mapperResponse.begin()->first; } catch (const sdbusplus::exception_t& ex) { lg2::error( "Mapper call failed for GetObject errorMsg({ERROR}), path({PATH})," "interface({INTERFACE})", "ERROR", ex, "PATH", path, "INTERFACE", intf); throw; } } } // namespace openpower::dump::util