blob: a82e5cee024ba5c4d1ee4a91171e0e798b2d2ba6 [file] [log] [blame]
Ben Tynerb8335562021-07-16 12:43:52 -05001#include <attn_common.hpp>
Ben Tyner4bbcb382021-02-22 09:29:00 -06002#include <attn_dbus.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
Ben Tyner5c5db652021-02-22 18:22:35 -060012/** @brief Create a dbus method */
Ben Tyner188f1092021-02-01 09:33:06 -060013int dbusMethod(const std::string& i_path, const std::string& i_interface,
14 const std::string& i_function,
Ben Tyner4bbcb382021-02-22 09:29:00 -060015 sdbusplus::message::message& o_method,
Ben Tyner5c5db652021-02-22 18:22:35 -060016 const std::string& i_extended)
Ben Tyner188f1092021-02-01 09:33:06 -060017{
Ben Tyner4bbcb382021-02-22 09:29:00 -060018 int rc = RC_DBUS_ERROR; // assume error
Ben Tyner188f1092021-02-01 09:33:06 -060019
20 try
21 {
22 constexpr auto serviceFind = "xyz.openbmc_project.ObjectMapper";
23 constexpr auto pathFind = "/xyz/openbmc_project/object_mapper";
24 constexpr auto interfaceFind = "xyz.openbmc_project.ObjectMapper";
25 constexpr auto functionFind = "GetObject";
26
27 auto bus = sdbusplus::bus::new_system(); // using system dbus
28
29 // method to find service from object path and object interface
30 auto method = bus.new_method_call(serviceFind, pathFind, interfaceFind,
31 functionFind);
32
33 // find the service for specified object path and interface
34 method.append(i_path.c_str());
35 method.append(std::vector<std::string>({i_interface}));
36 auto reply = bus.call(method);
37
38 // dbus call results
39 std::map<std::string, std::vector<std::string>> responseFindService;
40 reply.read(responseFindService);
41
42 // If we successfully found the service associated with the dbus object
43 // path and interface then create a method for the specified interface
44 // and function.
45 if (!responseFindService.empty())
46 {
47 auto service = responseFindService.begin()->first;
48
Ben Tyner4bbcb382021-02-22 09:29:00 -060049 // Some methods (e.g. get attribute) take an extended parameter
50 if (i_extended == "")
51 {
52 // return the method
53 o_method = bus.new_method_call(service.c_str(), i_path.c_str(),
54 i_interface.c_str(),
55 i_function.c_str());
56 }
57 else
58 {
59 // return extended method
60 o_method =
61 bus.new_method_call(service.c_str(), i_path.c_str(),
62 i_extended.c_str(), i_function.c_str());
63 }
Ben Tyner188f1092021-02-01 09:33:06 -060064
Ben Tyner4bbcb382021-02-22 09:29:00 -060065 rc = RC_SUCCESS;
Ben Tyner188f1092021-02-01 09:33:06 -060066 }
67 else
68 {
Ben Tyner6764d702021-02-12 09:17:23 -060069 // This trace will be picked up in event log
70 trace<level::INFO>("dbusMethod service not found");
71 std::string traceMsgPath = std::string(i_path, maxTraceLen);
72 trace<level::INFO>(traceMsgPath.c_str());
73 std::string traceMsgIface = std::string(i_interface, maxTraceLen);
74 trace<level::INFO>(traceMsgIface.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -060075 }
76 }
77 catch (const sdbusplus::exception::SdBusError& e)
78 {
Ben Tyner5c5db652021-02-22 18:22:35 -060079 trace<level::ERROR>("dbusMethod exception");
Ben Tyner6764d702021-02-12 09:17:23 -060080 std::string traceMsg = std::string(e.what(), maxTraceLen);
81 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -060082 }
83
84 return rc;
85}
86
87/** @brief Create a PEL for the specified event type */
88uint32_t createPel(const std::string& i_event,
89 std::map<std::string, std::string>& i_additional,
90 const std::vector<util::FFDCTuple>& i_ffdc)
91{
92 // CreatePELWithFFDCFiles returns plid
93 int plid = 0;
94
95 // Need to provide pid when using create or create-with-ffdc methods
96 i_additional.emplace("_PID", std::to_string(getpid()));
97
98 // Sdbus call specifics
99 constexpr auto interface = "org.open_power.Logging.PEL";
100 constexpr auto function = "CreatePELWithFFDCFiles";
101
102 sdbusplus::message::message method;
103
104 if (0 == dbusMethod(pathLogging, interface, function, method))
105 {
106 try
107 {
108 // append additional dbus call paramaters
109 method.append(i_event, levelPelError, i_additional, i_ffdc);
110
111 // using system dbus
112 auto bus = sdbusplus::bus::new_system();
113 auto response = bus.call(method);
114
115 // reply will be tuple containing bmc log id, platform log id
116 std::tuple<uint32_t, uint32_t> reply = {0, 0};
117
Ben Tyner4bbcb382021-02-22 09:29:00 -0600118 // parse dbus response into reply
Ben Tyner188f1092021-02-01 09:33:06 -0600119 response.read(reply);
120 plid = std::get<1>(reply); // platform log id is tuple "second"
121 }
122 catch (const sdbusplus::exception::SdBusError& e)
123 {
Ben Tyner5c5db652021-02-22 18:22:35 -0600124 trace<level::ERROR>("createPel exception");
Ben Tyner6764d702021-02-12 09:17:23 -0600125 std::string traceMsg = std::string(e.what(), maxTraceLen);
126 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600127 }
128 }
129
130 return plid; // platform log id or 0
131}
132
133/** @brief Create a PEL from raw PEL data */
134void createPelRaw(const std::vector<uint8_t>& i_buffer)
135{
136 // Create FFDC file from buffer data
137 util::FFDCFile pelFile{util::FFDCFormat::Text};
138 auto fd = pelFile.getFileDescriptor();
Ben Tyner188f1092021-02-01 09:33:06 -0600139
140 auto filePath = pelFile.getPath(); // path to ffdc file
141
Ben Tynerd7006092021-02-05 14:55:52 -0600142 size_t numBytes = write(fd, i_buffer.data(), i_buffer.size());
143 if (i_buffer.size() != numBytes)
144 {
145 std::stringstream traceMsg;
146 traceMsg << filePath.c_str() << " only " << (int)numBytes << " of "
147 << (int)i_buffer.size() << " bytes written";
148 auto strobj = traceMsg.str();
149 trace<level::ERROR>(strobj.c_str());
150 }
151
152 lseek(fd, 0, SEEK_SET);
153
Ben Tyner188f1092021-02-01 09:33:06 -0600154 // Additional data for log
155 std::map<std::string, std::string> additional;
156 additional.emplace("RAWPEL", filePath.string());
157 additional.emplace("_PID", std::to_string(getpid()));
158
159 // dbus specifics
160 constexpr auto interface = "xyz.openbmc_project.Logging.Create";
161 constexpr auto function = "Create";
162
163 sdbusplus::message::message method;
164
165 if (0 == dbusMethod(pathLogging, interface, function, method))
166 {
167 try
168 {
169 // append additional dbus call parameters
170 method.append(eventPelTerminate, levelPelError, additional);
171
172 // using system dbus, no reply
173 auto bus = sdbusplus::bus::new_system();
174 bus.call_noreply(method);
175 }
176 catch (const sdbusplus::exception::SdBusError& e)
177 {
Ben Tyner5c5db652021-02-22 18:22:35 -0600178 trace<level::ERROR>("createPelRaw exception");
Ben Tyner6764d702021-02-12 09:17:23 -0600179 std::string traceMsg = std::string(e.what(), maxTraceLen);
180 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600181 }
182 }
183}
184
185/** @brief Get file descriptor of exisitng PEL */
186int getPel(const uint32_t i_pelId)
187{
188 // GetPEL returns file descriptor (int)
189 int fd = -1;
190
191 // dbus specifics
192 constexpr auto interface = "org.open_power.Logging.PEL";
193 constexpr auto function = "GetPEL";
194
195 sdbusplus::message::message method;
196
197 if (0 == dbusMethod(pathLogging, interface, function, method))
198 {
199 try
200 {
201 // additional dbus call parameters
202 method.append(i_pelId);
203
204 // using system dbus
205 auto bus = sdbusplus::bus::new_system();
206 auto response = bus.call(method);
207
208 // reply will be a unix file descriptor
209 sdbusplus::message::unix_fd reply;
210
Ben Tyner4bbcb382021-02-22 09:29:00 -0600211 // parse dbus response into reply
Ben Tyner188f1092021-02-01 09:33:06 -0600212 response.read(reply);
213
214 fd = dup(reply); // need to copy (dup) the file descriptor
215 }
216 catch (const sdbusplus::exception::SdBusError& e)
217 {
Ben Tyner5c5db652021-02-22 18:22:35 -0600218 trace<level::ERROR>("getPel exception");
Ben Tyner6764d702021-02-12 09:17:23 -0600219 std::string traceMsg = std::string(e.what(), maxTraceLen);
220 trace<level::ERROR>(traceMsg.c_str());
Ben Tyner188f1092021-02-01 09:33:06 -0600221 }
222 }
223
224 return fd; // file descriptor or -1
225}
226
Ben Tyner4bbcb382021-02-22 09:29:00 -0600227/** @brief Get the running state of the host */
228HostRunningState hostRunningState()
229{
230 HostRunningState host = HostRunningState::Unknown;
231
232 // dbus specifics
233 constexpr auto path = "/xyz/openbmc_project/state/host0";
234 constexpr auto interface = "xyz.openbmc_project.State.Boot.Progress";
235 constexpr auto extended = "org.freedesktop.DBus.Properties";
236 constexpr auto function = "Get";
237
238 sdbusplus::message::message method;
239
240 if (0 == dbusMethod(path, interface, function, method, extended))
241 {
242 try
243 {
244 // additional dbus call parameters
245 method.append(interface, "BootProgress");
246
247 // using system dbus
248 auto bus = sdbusplus::bus::new_system();
249 auto response = bus.call(method);
250
251 // reply will be a variant
252 std::variant<std::string, bool, std::vector<uint8_t>,
253 std::vector<std::string>>
254 reply;
255
256 // parse dbus response into reply
257 response.read(reply);
258
259 // get boot progress (string) and convert to boot stage
260 std::string bootProgress(std::get<std::string>(reply));
261
262 using BootProgress = sdbusplus::xyz::openbmc_project::State::Boot::
263 server::Progress::ProgressStages;
264
265 BootProgress stage = sdbusplus::xyz::openbmc_project::State::Boot::
266 server::Progress::convertProgressStagesFromString(bootProgress);
267
268 if ((stage == BootProgress::SystemInitComplete) ||
269 (stage == BootProgress::OSStart) ||
270 (stage == BootProgress::OSRunning))
271 {
272 host = HostRunningState::Started;
273 }
274 else
275 {
276 host = HostRunningState::NotStarted;
277 }
278 }
279 catch (const sdbusplus::exception::SdBusError& e)
280 {
Ben Tyner5c5db652021-02-22 18:22:35 -0600281 trace<level::ERROR>("hostRunningState exception");
Ben Tyner4bbcb382021-02-22 09:29:00 -0600282 std::string traceMsg = std::string(e.what(), maxTraceLen);
283 trace<level::ERROR>(traceMsg.c_str());
284 }
285 }
286
287 return host;
288}
Ben Tyner188f1092021-02-01 09:33:06 -0600289} // namespace attn