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 namespace attn
9 {
10 
11 /**
12  *  Callback for dump request properties change signal monitor
13  *
14  * @param[in] i_msg         Dbus message from the dbus match infrastructure
15  * @param[in] i_path        The object path we are monitoring
16  * @param[out] o_inProgress Used to break out of our dbus wait loop
17  * @reutn Always non-zero indicating no error, no cascading callbacks
18  */
19 uint dumpStatusChanged(sdbusplus::message::message& i_msg, std::string i_path,
20                        bool& o_inProgress)
21 {
22     // reply (msg) will be a property change message
23     std::string interface;
24     std::map<std::string, std::variant<std::string, uint8_t>> property;
25     i_msg.read(interface, property);
26 
27     // looking for property Status changes
28     std::string propertyType = "Status";
29     auto dumpStatus          = property.find(propertyType);
30 
31     if (dumpStatus != property.end())
32     {
33         const std::string* status =
34             std::get_if<std::string>(&(dumpStatus->second));
35 
36         if ((nullptr != status) && ("xyz.openbmc_project.Common.Progress."
37                                     "OperationStatus.InProgress" != *status))
38         {
39             // dump is done, trace some info and change in progress flag
40             trace::inf(i_path.c_str());
41             trace::inf(status->c_str());
42             o_inProgress = false;
43         }
44     }
45 
46     return 1; // non-negative return code for successful callback
47 }
48 
49 /**
50  * Register a callback for dump progress status changes
51  *
52  * @param[in] i_path The object path of the dump to monitor
53  */
54 void monitorDump(const std::string& i_path)
55 {
56     bool inProgress = true; // callback will update this
57 
58     // setup the signal match rules and callback
59     std::string matchInterface = "xyz.openbmc_project.Common.Progress";
60     auto bus                   = sdbusplus::bus::new_system();
61 
62     std::unique_ptr<sdbusplus::bus::match_t> match =
63         std::make_unique<sdbusplus::bus::match_t>(
64             bus,
65             sdbusplus::bus::match::rules::propertiesChanged(
66                 i_path.c_str(), matchInterface.c_str()),
67             [&](auto& msg) {
68                 return dumpStatusChanged(msg, i_path, inProgress);
69             });
70 
71     // wait for dump status to be completed (complete == true)
72     trace::inf("dump requested (waiting)");
73     while (true == inProgress)
74     {
75         bus.wait(0);
76         bus.process_discard();
77     }
78     trace::inf("dump completed");
79 }
80 
81 /** Request a dump from the dump manager */
82 void requestDump(uint32_t i_logId, const DumpParameters& i_dumpParameters)
83 {
84     constexpr auto path      = "/org/openpower/dump";
85     constexpr auto interface = "xyz.openbmc_project.Dump.Create";
86     constexpr auto function  = "CreateDump";
87 
88     sdbusplus::message::message method;
89 
90     if (0 == dbusMethod(path, interface, function, method))
91     {
92         try
93         {
94             // dbus call arguments
95             std::map<std::string, std::variant<std::string, uint64_t>>
96                 createParams;
97             createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] =
98                 uint64_t(i_logId);
99             if (DumpType::Hostboot == i_dumpParameters.dumpType)
100             {
101                 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
102                     "com.ibm.Dump.Create.DumpType.Hostboot";
103             }
104             else if (DumpType::Hardware == i_dumpParameters.dumpType)
105             {
106                 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
107                     "com.ibm.Dump.Create.DumpType.Hardware";
108                 createParams
109                     ["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] =
110                         i_dumpParameters.unitId;
111             }
112             else if (DumpType::SBE == i_dumpParameters.dumpType)
113             {
114                 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
115                     "com.ibm.Dump.Create.DumpType.SBE";
116                 createParams
117                     ["com.ibm.Dump.Create.CreateParameters.FailingUnitId"] =
118                         i_dumpParameters.unitId;
119             }
120             method.append(createParams);
121 
122             // using system dbus
123             auto bus      = sdbusplus::bus::new_system();
124             auto response = bus.call(method);
125 
126             // reply will be type dbus::ObjectPath
127             sdbusplus::message::object_path reply;
128             response.read(reply);
129 
130             // monitor dump progress
131             monitorDump(reply);
132         }
133         catch (const sdbusplus::exception::SdBusError& e)
134         {
135             trace::err("requestDump exception");
136             trace::err(e.what());
137         }
138     }
139 }
140 
141 } // namespace attn
142