xref: /openbmc/openpower-hw-diags/attn/attn_dbus.cpp (revision 5c5db65a37d953cb9393f257aab90a0a209d4861)
14bbcb38fSBen Tyner #include <attn_dbus.hpp>
24bbcb38fSBen Tyner #include <attn_handler.hpp>
3188f1096SBen Tyner #include <attn_logging.hpp>
44bbcb38fSBen Tyner #include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
5188f1096SBen Tyner 
6188f1096SBen Tyner #include <string>
7188f1096SBen Tyner #include <vector>
8188f1096SBen Tyner 
9188f1096SBen Tyner namespace attn
10188f1096SBen Tyner {
11188f1096SBen Tyner 
12*5c5db65aSBen Tyner /** @brief Create a dbus method */
13188f1096SBen Tyner int dbusMethod(const std::string& i_path, const std::string& i_interface,
14188f1096SBen Tyner                const std::string& i_function,
154bbcb38fSBen Tyner                sdbusplus::message::message& o_method,
16*5c5db65aSBen Tyner                const std::string& i_extended)
17188f1096SBen Tyner {
184bbcb38fSBen Tyner     int rc = RC_DBUS_ERROR; // assume error
19188f1096SBen Tyner 
20188f1096SBen Tyner     try
21188f1096SBen Tyner     {
22188f1096SBen Tyner         constexpr auto serviceFind   = "xyz.openbmc_project.ObjectMapper";
23188f1096SBen Tyner         constexpr auto pathFind      = "/xyz/openbmc_project/object_mapper";
24188f1096SBen Tyner         constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper";
25188f1096SBen Tyner         constexpr auto functionFind  = "GetObject";
26188f1096SBen Tyner 
27188f1096SBen Tyner         auto bus = sdbusplus::bus::new_system(); // using system dbus
28188f1096SBen Tyner 
29188f1096SBen Tyner         // method to find service from object path and object interface
30188f1096SBen Tyner         auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind,
31188f1096SBen Tyner                                           functionFind);
32188f1096SBen Tyner 
33188f1096SBen Tyner         // find the service for specified object path and interface
34188f1096SBen Tyner         method.append(i_path.c_str());
35188f1096SBen Tyner         method.append(std::vector<std::string>({i_interface}));
36188f1096SBen Tyner         auto reply = bus.call(method);
37188f1096SBen Tyner 
38188f1096SBen Tyner         // dbus call results
39188f1096SBen Tyner         std::map<std::string, std::vector<std::string>> responseFindService;
40188f1096SBen Tyner         reply.read(responseFindService);
41188f1096SBen Tyner 
42188f1096SBen Tyner         // If we successfully found the service associated with the dbus object
43188f1096SBen Tyner         // path and interface then create a method for the specified interface
44188f1096SBen Tyner         // and function.
45188f1096SBen Tyner         if (!responseFindService.empty())
46188f1096SBen Tyner         {
47188f1096SBen Tyner             auto service = responseFindService.begin()->first;
48188f1096SBen Tyner 
494bbcb38fSBen Tyner             // Some methods (e.g. get attribute) take an extended parameter
504bbcb38fSBen Tyner             if (i_extended == "")
514bbcb38fSBen Tyner             {
52188f1096SBen Tyner                 // return the method
534bbcb38fSBen Tyner                 o_method = bus.new_method_call(service.c_str(), i_path.c_str(),
544bbcb38fSBen Tyner                                                i_interface.c_str(),
554bbcb38fSBen Tyner                                                i_function.c_str());
564bbcb38fSBen Tyner             }
574bbcb38fSBen Tyner             else
584bbcb38fSBen Tyner             {
594bbcb38fSBen Tyner                 // return extended method
60188f1096SBen Tyner                 o_method =
61188f1096SBen Tyner                     bus.new_method_call(service.c_str(), i_path.c_str(),
624bbcb38fSBen Tyner                                         i_extended.c_str(), i_function.c_str());
634bbcb38fSBen Tyner             }
64188f1096SBen Tyner 
654bbcb38fSBen Tyner             rc = RC_SUCCESS;
66188f1096SBen Tyner         }
67188f1096SBen Tyner         else
68188f1096SBen Tyner         {
696764d70eSBen Tyner             // This trace will be picked up in event log
706764d70eSBen Tyner             trace<level::INFO>("dbusMethod service not found");
716764d70eSBen Tyner             std::string traceMsgPath = std::string(i_path, maxTraceLen);
726764d70eSBen Tyner             trace<level::INFO>(traceMsgPath.c_str());
736764d70eSBen Tyner             std::string traceMsgIface = std::string(i_interface, maxTraceLen);
746764d70eSBen Tyner             trace<level::INFO>(traceMsgIface.c_str());
75188f1096SBen Tyner         }
76188f1096SBen Tyner     }
77188f1096SBen Tyner     catch (const sdbusplus::exception::SdBusError& e)
78188f1096SBen Tyner     {
79*5c5db65aSBen Tyner         trace<level::ERROR>("dbusMethod exception");
806764d70eSBen Tyner         std::string traceMsg = std::string(e.what(), maxTraceLen);
816764d70eSBen Tyner         trace<level::ERROR>(traceMsg.c_str());
82188f1096SBen Tyner     }
83188f1096SBen Tyner 
84188f1096SBen Tyner     return rc;
85188f1096SBen Tyner }
86188f1096SBen Tyner 
87188f1096SBen Tyner /** @brief Create a PEL for the specified event type */
88188f1096SBen Tyner uint32_t createPel(const std::string& i_event,
89188f1096SBen Tyner                    std::map<std::string, std::string>& i_additional,
90188f1096SBen Tyner                    const std::vector<util::FFDCTuple>& i_ffdc)
91188f1096SBen Tyner {
92188f1096SBen Tyner     // CreatePELWithFFDCFiles returns plid
93188f1096SBen Tyner     int plid = 0;
94188f1096SBen Tyner 
95188f1096SBen Tyner     // Need to provide pid when using create or create-with-ffdc methods
96188f1096SBen Tyner     i_additional.emplace("_PID", std::to_string(getpid()));
97188f1096SBen Tyner 
98188f1096SBen Tyner     // Sdbus call specifics
99188f1096SBen Tyner     constexpr auto interface = "org.open_power.Logging.PEL";
100188f1096SBen Tyner     constexpr auto function  = "CreatePELWithFFDCFiles";
101188f1096SBen Tyner 
102188f1096SBen Tyner     sdbusplus::message::message method;
103188f1096SBen Tyner 
104188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
105188f1096SBen Tyner     {
106188f1096SBen Tyner         try
107188f1096SBen Tyner         {
108188f1096SBen Tyner             // append additional dbus call paramaters
109188f1096SBen Tyner             method.append(i_event, levelPelError, i_additional, i_ffdc);
110188f1096SBen Tyner 
111188f1096SBen Tyner             // using system dbus
112188f1096SBen Tyner             auto bus      = sdbusplus::bus::new_system();
113188f1096SBen Tyner             auto response = bus.call(method);
114188f1096SBen Tyner 
115188f1096SBen Tyner             // reply will be tuple containing bmc log id, platform log id
116188f1096SBen Tyner             std::tuple<uint32_t, uint32_t> reply = {0, 0};
117188f1096SBen Tyner 
1184bbcb38fSBen Tyner             // parse dbus response into reply
119188f1096SBen Tyner             response.read(reply);
120188f1096SBen Tyner             plid = std::get<1>(reply); // platform log id is tuple "second"
121188f1096SBen Tyner         }
122188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
123188f1096SBen Tyner         {
124*5c5db65aSBen Tyner             trace<level::ERROR>("createPel exception");
1256764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
1266764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
127188f1096SBen Tyner         }
128188f1096SBen Tyner     }
129188f1096SBen Tyner 
130188f1096SBen Tyner     return plid; // platform log id or 0
131188f1096SBen Tyner }
132188f1096SBen Tyner 
133188f1096SBen Tyner /** @brief Create a PEL from raw PEL data */
134188f1096SBen Tyner void createPelRaw(const std::vector<uint8_t>& i_buffer)
135188f1096SBen Tyner {
136188f1096SBen Tyner     // Create FFDC file from buffer data
137188f1096SBen Tyner     util::FFDCFile pelFile{util::FFDCFormat::Text};
138188f1096SBen Tyner     auto fd = pelFile.getFileDescriptor();
139188f1096SBen Tyner 
140188f1096SBen Tyner     auto filePath = pelFile.getPath(); // path to ffdc file
141188f1096SBen Tyner 
142d700609cSBen Tyner     size_t numBytes = write(fd, i_buffer.data(), i_buffer.size());
143d700609cSBen Tyner     if (i_buffer.size() != numBytes)
144d700609cSBen Tyner     {
145d700609cSBen Tyner         std::stringstream traceMsg;
146d700609cSBen Tyner         traceMsg << filePath.c_str() << " only " << (int)numBytes << " of "
147d700609cSBen Tyner                  << (int)i_buffer.size() << " bytes written";
148d700609cSBen Tyner         auto strobj = traceMsg.str();
149d700609cSBen Tyner         trace<level::ERROR>(strobj.c_str());
150d700609cSBen Tyner     }
151d700609cSBen Tyner 
152d700609cSBen Tyner     lseek(fd, 0, SEEK_SET);
153d700609cSBen Tyner 
154188f1096SBen Tyner     // Additional data for log
155188f1096SBen Tyner     std::map<std::string, std::string> additional;
156188f1096SBen Tyner     additional.emplace("RAWPEL", filePath.string());
157188f1096SBen Tyner     additional.emplace("_PID", std::to_string(getpid()));
158188f1096SBen Tyner 
159188f1096SBen Tyner     // dbus specifics
160188f1096SBen Tyner     constexpr auto interface = "xyz.openbmc_project.Logging.Create";
161188f1096SBen Tyner     constexpr auto function  = "Create";
162188f1096SBen Tyner 
163188f1096SBen Tyner     sdbusplus::message::message method;
164188f1096SBen Tyner 
165188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
166188f1096SBen Tyner     {
167188f1096SBen Tyner         try
168188f1096SBen Tyner         {
169188f1096SBen Tyner             // append additional dbus call parameters
170188f1096SBen Tyner             method.append(eventPelTerminate, levelPelError, additional);
171188f1096SBen Tyner 
172188f1096SBen Tyner             // using system dbus, no reply
173188f1096SBen Tyner             auto bus = sdbusplus::bus::new_system();
174188f1096SBen Tyner             bus.call_noreply(method);
175188f1096SBen Tyner         }
176188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
177188f1096SBen Tyner         {
178*5c5db65aSBen Tyner             trace<level::ERROR>("createPelRaw exception");
1796764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
1806764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
181188f1096SBen Tyner         }
182188f1096SBen Tyner     }
183188f1096SBen Tyner }
184188f1096SBen Tyner 
185188f1096SBen Tyner /** @brief Get file descriptor of exisitng PEL */
186188f1096SBen Tyner int getPel(const uint32_t i_pelId)
187188f1096SBen Tyner {
188188f1096SBen Tyner     // GetPEL returns file descriptor (int)
189188f1096SBen Tyner     int fd = -1;
190188f1096SBen Tyner 
191188f1096SBen Tyner     // dbus specifics
192188f1096SBen Tyner     constexpr auto interface = "org.open_power.Logging.PEL";
193188f1096SBen Tyner     constexpr auto function  = "GetPEL";
194188f1096SBen Tyner 
195188f1096SBen Tyner     sdbusplus::message::message method;
196188f1096SBen Tyner 
197188f1096SBen Tyner     if (0 == dbusMethod(pathLogging, interface, function, method))
198188f1096SBen Tyner     {
199188f1096SBen Tyner         try
200188f1096SBen Tyner         {
201188f1096SBen Tyner             // additional dbus call parameters
202188f1096SBen Tyner             method.append(i_pelId);
203188f1096SBen Tyner 
204188f1096SBen Tyner             // using system dbus
205188f1096SBen Tyner             auto bus      = sdbusplus::bus::new_system();
206188f1096SBen Tyner             auto response = bus.call(method);
207188f1096SBen Tyner 
208188f1096SBen Tyner             // reply will be a unix file descriptor
209188f1096SBen Tyner             sdbusplus::message::unix_fd reply;
210188f1096SBen Tyner 
2114bbcb38fSBen Tyner             // parse dbus response into reply
212188f1096SBen Tyner             response.read(reply);
213188f1096SBen Tyner 
214188f1096SBen Tyner             fd = dup(reply); // need to copy (dup) the file descriptor
215188f1096SBen Tyner         }
216188f1096SBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
217188f1096SBen Tyner         {
218*5c5db65aSBen Tyner             trace<level::ERROR>("getPel exception");
2196764d70eSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
2206764d70eSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
221188f1096SBen Tyner         }
222188f1096SBen Tyner     }
223188f1096SBen Tyner 
224188f1096SBen Tyner     return fd; // file descriptor or -1
225188f1096SBen Tyner }
226188f1096SBen Tyner 
2274bbcb38fSBen Tyner /** @brief Get the running state of the host */
2284bbcb38fSBen Tyner HostRunningState hostRunningState()
2294bbcb38fSBen Tyner {
2304bbcb38fSBen Tyner     HostRunningState host = HostRunningState::Unknown;
2314bbcb38fSBen Tyner 
2324bbcb38fSBen Tyner     // dbus specifics
2334bbcb38fSBen Tyner     constexpr auto path      = "/xyz/openbmc_project/state/host0";
2344bbcb38fSBen Tyner     constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";
2354bbcb38fSBen Tyner     constexpr auto extended  = "org.freedesktop.DBus.Properties";
2364bbcb38fSBen Tyner     constexpr auto function  = "Get";
2374bbcb38fSBen Tyner 
2384bbcb38fSBen Tyner     sdbusplus::message::message method;
2394bbcb38fSBen Tyner 
2404bbcb38fSBen Tyner     if (0 == dbusMethod(path, interface, function, method, extended))
2414bbcb38fSBen Tyner     {
2424bbcb38fSBen Tyner         try
2434bbcb38fSBen Tyner         {
2444bbcb38fSBen Tyner             // additional dbus call parameters
2454bbcb38fSBen Tyner             method.append(interface, "BootProgress");
2464bbcb38fSBen Tyner 
2474bbcb38fSBen Tyner             // using system dbus
2484bbcb38fSBen Tyner             auto bus      = sdbusplus::bus::new_system();
2494bbcb38fSBen Tyner             auto response = bus.call(method);
2504bbcb38fSBen Tyner 
2514bbcb38fSBen Tyner             // reply will be a variant
2524bbcb38fSBen Tyner             std::variant<std::string, bool, std::vector<uint8_t>,
2534bbcb38fSBen Tyner                          std::vector<std::string>>
2544bbcb38fSBen Tyner                 reply;
2554bbcb38fSBen Tyner 
2564bbcb38fSBen Tyner             // parse dbus response into reply
2574bbcb38fSBen Tyner             response.read(reply);
2584bbcb38fSBen Tyner 
2594bbcb38fSBen Tyner             // get boot progress (string) and convert to boot stage
2604bbcb38fSBen Tyner             std::string bootProgress(std::get<std::string>(reply));
2614bbcb38fSBen Tyner 
2624bbcb38fSBen Tyner             using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
2634bbcb38fSBen Tyner                 server::Progress::ProgressStages;
2644bbcb38fSBen Tyner 
2654bbcb38fSBen Tyner             BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
2664bbcb38fSBen Tyner                 server::Progress::convertProgressStagesFromString(bootProgress);
2674bbcb38fSBen Tyner 
2684bbcb38fSBen Tyner             if ((stage == BootProgress::SystemInitComplete) ||
2694bbcb38fSBen Tyner                 (stage == BootProgress::OSStart) ||
2704bbcb38fSBen Tyner                 (stage == BootProgress::OSRunning))
2714bbcb38fSBen Tyner             {
2724bbcb38fSBen Tyner                 host = HostRunningState::Started;
2734bbcb38fSBen Tyner             }
2744bbcb38fSBen Tyner             else
2754bbcb38fSBen Tyner             {
2764bbcb38fSBen Tyner                 host = HostRunningState::NotStarted;
2774bbcb38fSBen Tyner             }
2784bbcb38fSBen Tyner         }
2794bbcb38fSBen Tyner         catch (const sdbusplus::exception::SdBusError& e)
2804bbcb38fSBen Tyner         {
281*5c5db65aSBen Tyner             trace<level::ERROR>("hostRunningState exception");
2824bbcb38fSBen Tyner             std::string traceMsg = std::string(e.what(), maxTraceLen);
2834bbcb38fSBen Tyner             trace<level::ERROR>(traceMsg.c_str());
2844bbcb38fSBen Tyner         }
2854bbcb38fSBen Tyner     }
2864bbcb38fSBen Tyner 
2874bbcb38fSBen Tyner     return host;
2884bbcb38fSBen Tyner }
289188f1096SBen Tyner } // namespace attn
290