blob: 97843b8b73212ce0e6edaa7454b31dd3fd419630 [file] [log] [blame]
Ben Tyner4bbcb382021-02-22 09:29:00 -06001#include <attn_dbus.hpp>
2#include <attn_handler.hpp>
Ben Tyner188f1092021-02-01 09:33:06 -06003#include <attn_logging.hpp>
Ben Tyner4bbcb382021-02-22 09:29:00 -06004#include <xyz/openbmc_project/State/Boot/Progress/server.hpp>
Ben Tyner188f1092021-02-01 09:33:06 -06005
6#include <string>
7#include <vector>
8
9namespace attn
10{
11
12/**
13 * Create a dbus method
14 *
15 * Find the dbus service associated with the dbus object path and create
16 * a dbus method for calling the specified dbus interface and function.
17 *
18 * @param i_path - dbus object path
19 * @param i_interface - dbus method interface
20 * @param i_function - dbus interface function
21 * @param o_method - method that is created
Ben Tyner4bbcb382021-02-22 09:29:00 -060022 * @param i_extended - optional for extended methods
Ben Tyner188f1092021-02-01 09:33:06 -060023 * @return non-zero if error
24 *
25 **/
26int dbusMethod(const std::string& i_path, const std::string& i_interface,
27 const std::string& i_function,
Ben Tyner4bbcb382021-02-22 09:29:00 -060028 sdbusplus::message::message& o_method,
29 const std::string& i_extended = "")
Ben Tyner188f1092021-02-01 09:33:06 -060030{
Ben Tyner4bbcb382021-02-22 09:29:00 -060031 int rc = RC_DBUS_ERROR; // assume error
Ben Tyner188f1092021-02-01 09:33:06 -060032
33 try
34 {
35 constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper";
36 constexpr auto pathFind = "/xyz/openbmc_project/object_mapper";
37 constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper";
38 constexpr auto functionFind = "GetObject";
39
40 auto bus = sdbusplus::bus::new_system(); // using system dbus
41
42 // method to find service from object path and object interface
43 auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind,
44 functionFind);
45
46 // find the service for specified object path and interface
47 method.append(i_path.c_str());
48 method.append(std::vector<std::string>({i_interface}));
49 auto reply = bus.call(method);
50
51 // dbus call results
52 std::map<std::string, std::vector<std::string>> responseFindService;
53 reply.read(responseFindService);
54
55 // If we successfully found the service associated with the dbus object
56 // path and interface then create a method for the specified interface
57 // and function.
58 if (!responseFindService.empty())
59 {
60 auto service = responseFindService.begin()->first;
61
Ben Tyner4bbcb382021-02-22 09:29:00 -060062 // Some methods (e.g. get attribute) take an extended parameter
63 if (i_extended == "")
64 {
65 // return the method
66 o_method = bus.new_method_call(service.c_str(), i_path.c_str(),
67 i_interface.c_str(),
68 i_function.c_str());
69 }
70 else
71 {
72 // return extended method
73 o_method =
74 bus.new_method_call(service.c_str(), i_path.c_str(),
75 i_extended.c_str(), i_function.c_str());
76 }
Ben Tyner188f1092021-02-01 09:33:06 -060077
Ben Tyner4bbcb382021-02-22 09:29:00 -060078 rc = RC_SUCCESS;
Ben Tyner188f1092021-02-01 09:33:06 -060079 }
80 else
81 {
Ben Tyner6764d702021-02-12 09:17:23 -060082 // This trace will be picked up in event log
83 trace<level::INFO>("dbusMethod service not found");
84 std::string traceMsgPath = std::string(i_path, maxTraceLen);
85 trace<level::INFO>(traceMsgPath.c_str());
86 std::string traceMsgIface = std::string(i_interface, maxTraceLen);
87 trace<level::INFO>(traceMsgIface.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -060088 }
89 }
90 catch (const sdbusplus::exception::SdBusError& e)
91 {
Ben Tyner6764d702021-02-12 09:17:23 -060092 trace<level::INFO>("dbusMethod exception");
93 std::string traceMsg = std::string(e.what(), maxTraceLen);
94 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -060095 }
96
97 return rc;
98}
99
100/** @brief Create a PEL for the specified event type */
101uint32_t createPel(const std::string& i_event,
102 std::map<std::string, std::string>& i_additional,
103 const std::vector<util::FFDCTuple>& i_ffdc)
104{
105 // CreatePELWithFFDCFiles returns plid
106 int plid = 0;
107
108 // Need to provide pid when using create or create-with-ffdc methods
109 i_additional.emplace("_PID", std::to_string(getpid()));
110
111 // Sdbus call specifics
112 constexpr auto interface = "org.open_power.Logging.PEL";
113 constexpr auto function = "CreatePELWithFFDCFiles";
114
115 sdbusplus::message::message method;
116
117 if (0 == dbusMethod(pathLogging, interface, function, method))
118 {
119 try
120 {
121 // append additional dbus call paramaters
122 method.append(i_event, levelPelError, i_additional, i_ffdc);
123
124 // using system dbus
125 auto bus = sdbusplus::bus::new_system();
126 auto response = bus.call(method);
127
128 // reply will be tuple containing bmc log id, platform log id
129 std::tuple<uint32_t, uint32_t> reply = {0, 0};
130
Ben Tyner4bbcb382021-02-22 09:29:00 -0600131 // parse dbus response into reply
Ben Tyner188f1092021-02-01 09:33:06 -0600132 response.read(reply);
133 plid = std::get<1>(reply); // platform log id is tuple "second"
134 }
135 catch (const sdbusplus::exception::SdBusError& e)
136 {
Ben Tyner6764d702021-02-12 09:17:23 -0600137 trace<level::INFO>("createPel exception");
138 std::string traceMsg = std::string(e.what(), maxTraceLen);
139 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600140 }
141 }
142
143 return plid; // platform log id or 0
144}
145
146/** @brief Create a PEL from raw PEL data */
147void createPelRaw(const std::vector<uint8_t>& i_buffer)
148{
149 // Create FFDC file from buffer data
150 util::FFDCFile pelFile{util::FFDCFormat::Text};
151 auto fd = pelFile.getFileDescriptor();
Ben Tyner188f1092021-02-01 09:33:06 -0600152
153 auto filePath = pelFile.getPath(); // path to ffdc file
154
Ben Tynerd7006092021-02-05 14:55:52 -0600155 size_t numBytes = write(fd, i_buffer.data(), i_buffer.size());
156 if (i_buffer.size() != numBytes)
157 {
158 std::stringstream traceMsg;
159 traceMsg << filePath.c_str() << " only " << (int)numBytes << " of "
160 << (int)i_buffer.size() << " bytes written";
161 auto strobj = traceMsg.str();
162 trace<level::ERROR>(strobj.c_str());
163 }
164
165 lseek(fd, 0, SEEK_SET);
166
Ben Tyner188f1092021-02-01 09:33:06 -0600167 // Additional data for log
168 std::map<std::string, std::string> additional;
169 additional.emplace("RAWPEL", filePath.string());
170 additional.emplace("_PID", std::to_string(getpid()));
171
172 // dbus specifics
173 constexpr auto interface = "xyz.openbmc_project.Logging.Create";
174 constexpr auto function = "Create";
175
176 sdbusplus::message::message method;
177
178 if (0 == dbusMethod(pathLogging, interface, function, method))
179 {
180 try
181 {
182 // append additional dbus call parameters
183 method.append(eventPelTerminate, levelPelError, additional);
184
185 // using system dbus, no reply
186 auto bus = sdbusplus::bus::new_system();
187 bus.call_noreply(method);
188 }
189 catch (const sdbusplus::exception::SdBusError& e)
190 {
Ben Tyner6764d702021-02-12 09:17:23 -0600191 trace<level::INFO>("createPelRaw exception");
192 std::string traceMsg = std::string(e.what(), maxTraceLen);
193 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600194 }
195 }
196}
197
198/** @brief Get file descriptor of exisitng PEL */
199int getPel(const uint32_t i_pelId)
200{
201 // GetPEL returns file descriptor (int)
202 int fd = -1;
203
204 // dbus specifics
205 constexpr auto interface = "org.open_power.Logging.PEL";
206 constexpr auto function = "GetPEL";
207
208 sdbusplus::message::message method;
209
210 if (0 == dbusMethod(pathLogging, interface, function, method))
211 {
212 try
213 {
214 // additional dbus call parameters
215 method.append(i_pelId);
216
217 // using system dbus
218 auto bus = sdbusplus::bus::new_system();
219 auto response = bus.call(method);
220
221 // reply will be a unix file descriptor
222 sdbusplus::message::unix_fd reply;
223
Ben Tyner4bbcb382021-02-22 09:29:00 -0600224 // parse dbus response into reply
Ben Tyner188f1092021-02-01 09:33:06 -0600225 response.read(reply);
226
227 fd = dup(reply); // need to copy (dup) the file descriptor
228 }
229 catch (const sdbusplus::exception::SdBusError& e)
230 {
Ben Tyner6764d702021-02-12 09:17:23 -0600231 trace<level::INFO>("getPel exception");
232 std::string traceMsg = std::string(e.what(), maxTraceLen);
233 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600234 }
235 }
236
237 return fd; // file descriptor or -1
238}
239
Ben Tyner4bbcb382021-02-22 09:29:00 -0600240/** @brief Get the running state of the host */
241HostRunningState hostRunningState()
242{
243 HostRunningState host = HostRunningState::Unknown;
244
245 // dbus specifics
246 constexpr auto path = "/xyz/openbmc_project/state/host0";
247 constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";
248 constexpr auto extended = "org.freedesktop.DBus.Properties";
249 constexpr auto function = "Get";
250
251 sdbusplus::message::message method;
252
253 if (0 == dbusMethod(path, interface, function, method, extended))
254 {
255 try
256 {
257 // additional dbus call parameters
258 method.append(interface, "BootProgress");
259
260 // using system dbus
261 auto bus = sdbusplus::bus::new_system();
262 auto response = bus.call(method);
263
264 // reply will be a variant
265 std::variant<std::string, bool, std::vector<uint8_t>,
266 std::vector<std::string>>
267 reply;
268
269 // parse dbus response into reply
270 response.read(reply);
271
272 // get boot progress (string) and convert to boot stage
273 std::string bootProgress(std::get<std::string>(reply));
274
275 using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
276 server::Progress::ProgressStages;
277
278 BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
279 server::Progress::convertProgressStagesFromString(bootProgress);
280
281 if ((stage == BootProgress::SystemInitComplete) ||
282 (stage == BootProgress::OSStart) ||
283 (stage == BootProgress::OSRunning))
284 {
285 host = HostRunningState::Started;
286 }
287 else
288 {
289 host = HostRunningState::NotStarted;
290 }
291 }
292 catch (const sdbusplus::exception::SdBusError& e)
293 {
294 trace<level::INFO>("hostRunningState exception");
295 std::string traceMsg = std::string(e.what(), maxTraceLen);
296 trace<level::ERROR>(traceMsg.c_str());
297 }
298 }
299
300 return host;
301}
Ben Tyner188f1092021-02-01 09:33:06 -0600302} // namespace attn