1 #include <attn/attn_common.hpp>
2 #include <attn/attn_dbus.hpp>
3 #include <attn/attn_logging.hpp>
4 #include <util/dbus.hpp>
5 #include <util/trace.hpp>
6 
7 #include <string>
8 #include <vector>
9 
10 namespace attn
11 {
12 
13 /** @brief Create a dbus method */
dbusMethod(const std::string & i_path,const std::string & i_interface,const std::string & i_function,sdbusplus::message_t & o_method)14 int dbusMethod(const std::string& i_path, const std::string& i_interface,
15                const std::string& i_function, sdbusplus::message_t& o_method)
16 {
17     int rc = RC_DBUS_ERROR; // assume error
18 
19     try
20     {
21         auto bus = sdbusplus::bus::new_system(); // using system dbus
22 
23         // we need to find the service implementing the interface
24         util::dbus::DBusService service;
25 
26         if (0 == util::dbus::findService(i_interface, i_path, service))
27         {
28             // return the method
29             o_method =
30                 bus.new_method_call(service.c_str(), i_path.c_str(),
31                                     i_interface.c_str(), i_function.c_str());
32 
33             rc = RC_SUCCESS;
34         }
35         else
36         {
37             // This trace will be picked up in event log
38             trace::inf("dbusMethod service not found");
39             trace::inf(i_path.c_str());
40             trace::inf(i_interface.c_str());
41         }
42     }
43     catch (const sdbusplus::exception::SdBusError& e)
44     {
45         trace::err("dbusMethod exception");
46         trace::err(e.what());
47     }
48 
49     return rc;
50 }
51 
52 /** @brief Create a PEL from raw PEL data */
createPelRaw(const std::vector<uint8_t> & i_buffer)53 void createPelRaw(const std::vector<uint8_t>& i_buffer)
54 {
55     // Create FFDC file from buffer data
56     util::FFDCFile pelFile{util::FFDCFormat::Text};
57     auto fd = pelFile.getFileDescriptor();
58 
59     auto filePath = pelFile.getPath(); // path to ffdc file
60 
61     size_t numBytes = write(fd, i_buffer.data(), i_buffer.size());
62     if (i_buffer.size() != numBytes)
63     {
64         trace::err("%s only %u of %u bytes written", filePath.c_str(), numBytes,
65                    i_buffer.size());
66     }
67 
68     lseek(fd, 0, SEEK_SET);
69 
70     // Additional data for log
71     std::map<std::string, std::string> additional;
72     additional.emplace("RAWPEL", filePath.string());
73     additional.emplace("_PID", std::to_string(getpid()));
74 
75     // dbus specifics
76     constexpr auto interface = "xyz.openbmc_project.Logging.Create";
77     constexpr auto function = "Create";
78 
79     sdbusplus::message_t method;
80 
81     if (0 == dbusMethod(pathLogging, interface, function, method))
82     {
83         try
84         {
85             // append additional dbus call parameters
86             method.append(eventPelTerminate, levelPelError, additional);
87 
88             // using system dbus, no reply
89             auto bus = sdbusplus::bus::new_system();
90             bus.call_noreply(method);
91         }
92         catch (const sdbusplus::exception::SdBusError& e)
93         {
94             trace::err("createPelRaw exception");
95             trace::err(e.what());
96         }
97     }
98 }
99 
100 /** @brief Get file descriptor of exisitng PEL */
getPel(const uint32_t i_pelId)101 int getPel(const uint32_t i_pelId)
102 {
103     // GetPEL returns file descriptor (int)
104     int fd = -1;
105 
106     // dbus specifics
107     constexpr auto interface = "org.open_power.Logging.PEL";
108     constexpr auto function = "GetPEL";
109 
110     sdbusplus::message_t method;
111 
112     if (0 == dbusMethod(pathLogging, interface, function, method))
113     {
114         try
115         {
116             // additional dbus call parameters
117             method.append(i_pelId);
118 
119             // using system dbus
120             auto bus = sdbusplus::bus::new_system();
121             auto response = bus.call(method);
122 
123             // reply will be a unix file descriptor
124             sdbusplus::message::unix_fd reply;
125 
126             // parse dbus response into reply
127             response.read(reply);
128 
129             fd = dup(reply); // need to copy (dup) the file descriptor
130         }
131         catch (const sdbusplus::exception::SdBusError& e)
132         {
133             trace::err("getPel exception");
134             trace::err(e.what());
135         }
136     }
137 
138     return fd; // file descriptor or -1
139 }
140 
141 } // namespace attn
142