blob: 69191aba1e74b19f450a5dde1dd5ccb263100ed6 [file] [log] [blame]
Ben Tynerbcf65a82020-12-01 08:46:36 -06001#include <attn/attn_common.hpp>
Ben Tyner5c5db652021-02-22 18:22:35 -06002#include <attn/attn_dbus.hpp>
Ben Tynerb797b3e2020-06-29 10:12:05 -05003#include <attn/attn_logging.hpp>
Ben Tynerf5210bb2021-01-05 12:58:10 -06004#include <attn/pel/pel_common.hpp>
Ben Tynerb797b3e2020-06-29 10:12:05 -05005#include <attn/ti_handler.hpp>
Ben Tyner9ae5ca42020-02-28 13:13:50 -06006#include <sdbusplus/bus.hpp>
Ben Tynerff17f962020-09-23 08:21:19 -05007#include <sdbusplus/exception.hpp>
Ben Tyner9ae5ca42020-02-28 13:13:50 -06008
Ben Tyner40717722020-09-23 09:43:20 -05009#include <iomanip>
10#include <iostream>
11
Ben Tyner9ae5ca42020-02-28 13:13:50 -060012namespace attn
13{
14
Ben Tyner8c5e4f42020-10-28 11:11:55 -050015/**
16 * @brief Determine if this is a HB or PHYP TI event
17 *
18 * Use the TI info data area to determine if this is either a HB or a PHYP
19 * TI event then handle the event.
20 *
Ben Tynerf5210bb2021-01-05 12:58:10 -060021 * @param i_tiDataArea pointer to the TI info data
Ben Tyner8c5e4f42020-10-28 11:11:55 -050022 */
Ben Tyner792f32f2020-06-02 08:50:47 -050023int tiHandler(TiDataArea* i_tiDataArea)
Ben Tyner9ae5ca42020-02-28 13:13:50 -060024{
Ben Tynere4f5dbe2020-10-19 07:19:33 -050025 int rc = RC_SUCCESS;
Ben Tyner9ae5ca42020-02-28 13:13:50 -060026
Ben Tynerb8335562021-07-16 12:43:52 -050027 // capture some additional data for logs/traces
28 addHbStatusRegs();
29
Ben Tyner8c5e4f42020-10-28 11:11:55 -050030 // check TI data area if it is available
Ben Tynere4f5dbe2020-10-19 07:19:33 -050031 if (nullptr != i_tiDataArea)
Ben Tyner792f32f2020-06-02 08:50:47 -050032 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050033 // HB v. PHYP TI logic: Only hosboot will fill in hbTerminateType
Ben Tyner8882c322021-02-05 12:13:21 -060034 // and it will be non-zero. Only hostboot will fill out source and
35 // it it will be non-zero. Only PHYP will fill in srcFormat and it
36 // will be non-zero.
Ben Tyner8c5e4f42020-10-28 11:11:55 -050037 if ((0 == i_tiDataArea->hbTerminateType) &&
38 (0 == i_tiDataArea->source) && (0 != i_tiDataArea->srcFormat))
Ben Tynere4f5dbe2020-10-19 07:19:33 -050039 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050040 handlePhypTi(i_tiDataArea);
Ben Tynere4f5dbe2020-10-19 07:19:33 -050041 }
42 else
43 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050044 handleHbTi(i_tiDataArea);
Ben Tynere4f5dbe2020-10-19 07:19:33 -050045 }
Ben Tyner8c5e4f42020-10-28 11:11:55 -050046 }
47 else
48 {
Ben Tyner29651ef2021-02-08 10:51:03 -060049 // TI data was not available This should not happen since we provide
50 // a default TI info in the case where get TI info was not successful.
Ben Tyner7a0dd542021-02-12 09:33:44 -060051 eventAttentionFail((int)AttnSection::tiHandler | ATTN_INFO_NULL);
Ben Tyner29651ef2021-02-08 10:51:03 -060052 rc = RC_NOT_HANDLED;
Ben Tynere4f5dbe2020-10-19 07:19:33 -050053 }
Ben Tyner40717722020-09-23 09:43:20 -050054
Ben Tyner8c5e4f42020-10-28 11:11:55 -050055 return rc;
56}
Ben Tynere4f5dbe2020-10-19 07:19:33 -050057
Ben Tyner8c5e4f42020-10-28 11:11:55 -050058/**
Ben Tyner8c5e4f42020-10-28 11:11:55 -050059 * @brief Handle a PHYP terminate immediate special attention
60 *
61 * The TI info data area will contain information pertaining to the TI
62 * condition. We will wither quiesce the host or initiate a MPIPL depending
63 * depending on the auto reboot configuration. We will also create a PEL which
64 * will contain the TI info data and FFDC data captured in the system journal.
65 *
66 * @param i_tiDataArea pointer to TI information filled in by hostboot
67 */
68void handlePhypTi(TiDataArea* i_tiDataArea)
69{
70 trace<level::INFO>("PHYP TI");
71
Ben Tyner8c5e4f42020-10-28 11:11:55 -050072 // gather additional data for PEL
73 std::map<std::string, std::string> tiAdditionalData;
Ben Tynere4f5dbe2020-10-19 07:19:33 -050074
Ben Tyner8c5e4f42020-10-28 11:11:55 -050075 if (nullptr != i_tiDataArea)
76 {
77 parsePhypOpalTiInfo(tiAdditionalData, i_tiDataArea);
Ben Tyner29651ef2021-02-08 10:51:03 -060078
79 tiAdditionalData["Subsystem"] =
80 std::to_string(static_cast<uint8_t>(pel::SubsystemID::hypervisor));
81
Ben Tyner9d4f91c2021-02-09 08:27:58 -060082 // Copy all ascii src chars to additional data
83 char srcChar[33]; // 32 ascii chars + null term
84 memcpy(srcChar, &(i_tiDataArea->asciiData0), 32);
85 srcChar[32] = 0;
Ben Tyner29651ef2021-02-08 10:51:03 -060086 tiAdditionalData["SrcAscii"] = std::string{srcChar};
87
88 // TI event
89 eventTerminate(tiAdditionalData, (char*)i_tiDataArea);
Ben Tyner8c5e4f42020-10-28 11:11:55 -050090 }
Ben Tyner29651ef2021-02-08 10:51:03 -060091 else
92 {
93 // TI data was not available This should not happen since we provide
94 // a default TI info in the case where get TI info was not successful.
Ben Tyner7a0dd542021-02-12 09:33:44 -060095 eventAttentionFail((int)AttnSection::handlePhypTi | ATTN_INFO_NULL);
Ben Tyner29651ef2021-02-08 10:51:03 -060096 }
Ben Tyner063f6bd2021-03-26 07:45:56 -050097
98 // We are finished creating the event log entries so transition host to
99 // the required state.
100 if (autoRebootEnabled())
101 {
102 // If autoreboot is enabled we will start crash (mpipl) mode target
103 transitionHost(HostState::Crash);
104 }
105 else
106 {
107 // If autoreboot is disabled we will quiesce the host
108 transitionHost(HostState::Quiesce);
109 }
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500110}
111
112/**
113 * @brief Handle a hostboot terminate immediate special attention
114 *
115 * The TI info data area will contain information pertaining to the TI
116 * condition. The course of action to take regarding the host state will
117 * depend on the contents of the TI info data area. We will also create a
118 * PEL containing the TI info data and FFDC data captured in the system
119 * journal.
120 *
121 * @param i_tiDataArea pointer to TI information filled in by hostboot
122 */
123void handleHbTi(TiDataArea* i_tiDataArea)
124{
125 trace<level::INFO>("HB TI");
126
127 bool hbDumpRequested = true; // HB dump is common case
128 bool generatePel = true; // assume PEL will be created
129 bool terminateHost = true; // transition host state
130
131 // handle specific hostboot reason codes
132 if (nullptr != i_tiDataArea)
133 {
Ben Tyner8882c322021-02-05 12:13:21 -0600134 std::stringstream ss; // stream object for tracing
135 std::string strobj; // string object for tracing
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500136
137 switch (i_tiDataArea->hbTerminateType)
138 {
139 case TI_WITH_PLID:
140 case TI_WITH_EID:
Ben Tyner8882c322021-02-05 12:13:21 -0600141
142 // trace this value
143 ss.str(std::string()); // empty the stream
144 ss.clear(); // clear the stream
145 ss << "TI with PLID/EID: " << std::hex << std::showbase
146 << std::setw(8) << std::setfill('0')
147 << be32toh(i_tiDataArea->asciiData1);
148 strobj = ss.str();
149 trace<level::INFO>(strobj.c_str());
150
151 // see if HB dump is requested
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500152 if (0 == i_tiDataArea->hbDumpFlag)
153 {
154 hbDumpRequested = false; // no HB dump requested
155 }
156 break;
157 case TI_WITH_SRC:
Ben Tyner8882c322021-02-05 12:13:21 -0600158 // Reason code is byte 2 and 3 of 4 byte srcWord12HbWord0
159 uint16_t reasonCode = be32toh(i_tiDataArea->srcWord12HbWord0);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500160
Ben Tyner8882c322021-02-05 12:13:21 -0600161 // trace this value
162 ss.str(std::string()); // empty the stream
163 ss.clear(); // clear the stream
164 ss << "TI with SRC: " << std::hex << std::showbase
165 << std::setw(4) << std::setfill('0') << (int)reasonCode;
166 strobj = ss.str();
167 trace<level::INFO>(strobj.c_str());
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500168
Ben Tyner8882c322021-02-05 12:13:21 -0600169 switch (reasonCode)
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500170 {
171 case HB_SRC_SHUTDOWN_REQUEST:
172 trace<level::INFO>("shutdown request");
Ben Tyner8882c322021-02-05 12:13:21 -0600173 generatePel = false;
174 hbDumpRequested = false;
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500175 break;
176 case HB_SRC_KEY_TRANSITION:
Ben Tyner8882c322021-02-05 12:13:21 -0600177 // Note: Should never see this so lets leave
178 // hbDumpRequested == true so we can figure out why
179 // we are here.
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500180 trace<level::INFO>("key transition");
181 terminateHost = false;
182 break;
183 case HB_SRC_INSUFFICIENT_HW:
184 trace<level::INFO>("insufficient hardware");
185 break;
186 case HB_SRC_TPM_FAIL:
187 trace<level::INFO>("TPM fail");
188 break;
189 case HB_SRC_ROM_VERIFY:
190 trace<level::INFO>("ROM verify");
191 break;
192 case HB_SRC_EXT_MISMATCH:
193 trace<level::INFO>("EXT mismatch");
194 break;
195 case HB_SRC_ECC_UE:
196 trace<level::INFO>("ECC UE");
197 break;
198 case HB_SRC_UNSUPPORTED_MODE:
199 trace<level::INFO>("unsupported mode");
200 break;
201 case HB_SRC_UNSUPPORTED_SFCRANGE:
202 trace<level::INFO>("unsupported SFC range");
203 break;
204 case HB_SRC_PARTITION_TABLE:
205 trace<level::INFO>("partition table invalid");
206 break;
207 case HB_SRC_UNSUPPORTED_HARDWARE:
208 trace<level::INFO>("unsupported hardware");
209 break;
210 case HB_SRC_PNOR_CORRUPTION:
211 trace<level::INFO>("PNOR corruption");
212 break;
213 default:
214 trace<level::INFO>("reason: other");
215 }
216
Ben Tyner5c5db652021-02-22 18:22:35 -0600217 break; // case TI_WITH_SRC
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500218 }
219 }
220
Ben Tyner5c5db652021-02-22 18:22:35 -0600221 if (true == generatePel)
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500222 {
Ben Tyner5c5db652021-02-22 18:22:35 -0600223 if (nullptr != i_tiDataArea)
Ben Tyner29651ef2021-02-08 10:51:03 -0600224 {
Ben Tyner5c5db652021-02-22 18:22:35 -0600225 // gather additional data for PEL
226 std::map<std::string, std::string> tiAdditionalData;
227
228 parseHbTiInfo(tiAdditionalData, i_tiDataArea);
229
Ben Tyner29651ef2021-02-08 10:51:03 -0600230 tiAdditionalData["Subsystem"] = std::to_string(
231 static_cast<uint8_t>(pel::SubsystemID::hostboot));
232
Ben Tyner5c5db652021-02-22 18:22:35 -0600233 // Translate hex src value to ascii. This results in an 8
234 // character SRC (hostboot SRC is 32 bits)
Ben Tyner9d4f91c2021-02-09 08:27:58 -0600235 std::stringstream src;
Ben Tyner4bbcb382021-02-22 09:29:00 -0600236 src << std::setw(8) << std::setfill('0') << std::uppercase
237 << std::hex << be32toh(i_tiDataArea->srcWord12HbWord0);
Ben Tyner9d4f91c2021-02-09 08:27:58 -0600238 tiAdditionalData["SrcAscii"] = src.str();
Ben Tyner29651ef2021-02-08 10:51:03 -0600239
Ben Tyner5c5db652021-02-22 18:22:35 -0600240 // Request dump after generating event log?
241 tiAdditionalData["Dump"] =
242 (true == hbDumpRequested) ? "true" : "false";
243
244 // Generate event log
Ben Tyner29651ef2021-02-08 10:51:03 -0600245 eventTerminate(tiAdditionalData, (char*)i_tiDataArea);
246 }
Ben Tyner5c5db652021-02-22 18:22:35 -0600247 else
248 {
249 // TI data was not available This should not happen.
250 eventAttentionFail((int)AttnSection::handleHbTi | ATTN_INFO_NULL);
251 }
Ben Tyner40717722020-09-23 09:43:20 -0500252 }
Ben Tyner063f6bd2021-03-26 07:45:56 -0500253
254 if (true == terminateHost)
255 {
Ben Tyner5c5db652021-02-22 18:22:35 -0600256 transitionHost(HostState::Quiesce);
Ben Tyner063f6bd2021-03-26 07:45:56 -0500257 }
Ben Tyner40717722020-09-23 09:43:20 -0500258}
259
260/** @brief Parse the TI info data area into map as PHYP/OPAL data */
261void parsePhypOpalTiInfo(std::map<std::string, std::string>& i_map,
262 TiDataArea* i_tiDataArea)
263{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600264 if (nullptr == i_tiDataArea)
265 {
266 return;
267 }
268
Ben Tyner40717722020-09-23 09:43:20 -0500269 std::stringstream ss;
270
Ben Tynerfeeea832021-04-06 10:08:11 -0500271 ss << "0x00 TI Area Valid:" << std::setw(2) << std::setfill('0') << std::hex
272 << (int)i_tiDataArea->tiAreaValid << ":";
273 ss << "0x01 Command:" << std::setw(2) << std::setfill('0') << std::hex
274 << (int)i_tiDataArea->command << ":";
275 ss << "0x02 Num. Data Bytes:" << std::setw(4) << std::setfill('0')
276 << std::hex << be16toh(i_tiDataArea->numDataBytes) << ":";
277 ss << "0x04 Reserved:" << std::setw(2) << std::setfill('0') << std::hex
278 << (int)i_tiDataArea->reserved1 << ":";
279 ss << "0x06 HWDump Type:" << std::setw(4) << std::setfill('0') << std::hex
280 << be16toh(i_tiDataArea->hardwareDumpType) << ":";
281 ss << "0x08 SRC Format:" << std::setw(2) << std::setfill('0') << std::hex
282 << (int)i_tiDataArea->srcFormat << ":";
283 ss << "0x09 SRC Flags:" << std::setw(2) << std::setfill('0') << std::hex
284 << (int)i_tiDataArea->srcFlags << ":";
285 ss << "0x0a Num. ASCII Words:" << std::setw(2) << std::setfill('0')
286 << std::hex << (int)i_tiDataArea->numAsciiWords << ":";
287 ss << "0x0b Num. Hex Words:" << std::setw(2) << std::setfill('0')
288 << std::hex << (int)i_tiDataArea->numHexWords << ":";
289 ss << "0x0e Length of SRC:" << std::setw(4) << std::setfill('0') << std::hex
290 << be16toh(i_tiDataArea->lenSrc) << ":";
291 ss << "0x10 SRC Word 12:" << std::setw(8) << std::setfill('0') << std::hex
292 << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
293 ss << "0x14 SRC Word 13:" << std::setw(8) << std::setfill('0') << std::hex
294 << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
295 ss << "0x18 SRC Word 14:" << std::setw(8) << std::setfill('0') << std::hex
296 << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
297 ss << "0x1c SRC Word 15:" << std::setw(8) << std::setfill('0') << std::hex
298 << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
299 ss << "0x20 SRC Word 16:" << std::setw(8) << std::setfill('0') << std::hex
300 << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
301 ss << "0x24 SRC Word 17:" << std::setw(8) << std::setfill('0') << std::hex
302 << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
303 ss << "0x28 SRC Word 18:" << std::setw(8) << std::setfill('0') << std::hex
304 << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
305 ss << "0x2c SRC Word 19:" << std::setw(8) << std::setfill('0') << std::hex
306 << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
307 ss << "0x30 ASCII Data:" << std::setw(8) << std::setfill('0') << std::hex
308 << be32toh(i_tiDataArea->asciiData0) << ":";
309 ss << "0x34 ASCII Data:" << std::setw(8) << std::setfill('0') << std::hex
310 << be32toh(i_tiDataArea->asciiData1) << ":";
311 ss << "0x38 ASCII Data:" << std::setw(8) << std::setfill('0') << std::hex
312 << be32toh(i_tiDataArea->asciiData2) << ":";
313 ss << "0x3c ASCII Data:" << std::setw(8) << std::setfill('0') << std::hex
314 << be32toh(i_tiDataArea->asciiData3) << ":";
315 ss << "0x40 ASCII Data:" << std::setw(8) << std::setfill('0') << std::hex
316 << be32toh(i_tiDataArea->asciiData4) << ":";
317 ss << "0x44 ASCII Data:" << std::setw(8) << std::setfill('0') << std::hex
318 << be32toh(i_tiDataArea->asciiData5) << ":";
319 ss << "0x48 ASCII Data:" << std::setw(8) << std::setfill('0') << std::hex
320 << be32toh(i_tiDataArea->asciiData6) << ":";
321 ss << "0x4c ASCII Data:" << std::setw(8) << std::setfill('0') << std::hex
322 << be32toh(i_tiDataArea->asciiData7) << ":";
323 ss << "0x50 Location:" << std::setw(2) << std::setfill('0') << std::hex
324 << (int)i_tiDataArea->location << ":";
325 ss << "0x51 Code Sections:" << std::setw(2) << std::setfill('0') << std::hex
326 << (int)i_tiDataArea->codeSection << ":";
327 ss << "0x52 Additional Size:" << std::setw(2) << std::setfill('0')
328 << std::hex << (int)i_tiDataArea->additionalSize << ":";
329 ss << "0x53 Additional Data:" << std::setw(2) << std::setfill('0')
330 << std::hex << (int)i_tiDataArea->andData;
Ben Tyner40717722020-09-23 09:43:20 -0500331
332 std::string key, value;
333 char delim = ':';
334
335 while (std::getline(ss, key, delim))
336 {
337 std::getline(ss, value, delim);
338 i_map[key] = value;
339 }
340}
341
342/** @brief Parse the TI info data area into map as hostboot data */
343void parseHbTiInfo(std::map<std::string, std::string>& i_map,
344 TiDataArea* i_tiDataArea)
345{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600346 if (nullptr == i_tiDataArea)
347 {
348 return;
349 }
350
Ben Tyner40717722020-09-23 09:43:20 -0500351 std::stringstream ss;
352
Ben Tynerfeeea832021-04-06 10:08:11 -0500353 ss << "0x00 TI Area Valid:" << std::setw(2) << std::setfill('0') << std::hex
354 << (int)i_tiDataArea->tiAreaValid << ":";
355 ss << "0x04 Reserved:" << std::setw(2) << std::setfill('0') << std::hex
356 << (int)i_tiDataArea->reserved1 << ":";
357 ss << "0x05 HB_Term. Type:" << std::setw(2) << std::setfill('0') << std::hex
358 << (int)i_tiDataArea->hbTerminateType << ":";
359 ss << "0x0c HB Dump Flag:" << std::setw(2) << std::setfill('0') << std::hex
360 << (int)i_tiDataArea->hbDumpFlag << ":";
361 ss << "0x0d Source:" << std::setw(2) << std::setfill('0') << std::hex
362 << (int)i_tiDataArea->source << ":";
363 ss << "0x10 HB Word 0:" << std::setw(8) << std::setfill('0') << std::hex
364 << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
365 ss << "0x14 HB Word 2:" << std::setw(8) << std::setfill('0') << std::hex
366 << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
367 ss << "0x18 HB Word 3:" << std::setw(8) << std::setfill('0') << std::hex
368 << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
369 ss << "0x1c HB Word 4:" << std::setw(8) << std::setfill('0') << std::hex
370 << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
371 ss << "0x20 HB Word 5:" << std::setw(8) << std::setfill('0') << std::hex
372 << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
373 ss << "0x24 HB Word 6:" << std::setw(8) << std::setfill('0') << std::hex
374 << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
375 ss << "0x28 HB Word 7:" << std::setw(8) << std::setfill('0') << std::hex
376 << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
377 ss << "0x2c HB Word 8:" << std::setw(8) << std::setfill('0') << std::hex
378 << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
379 ss << "0x30 error_data:" << std::setw(8) << std::setfill('0') << std::hex
380 << be32toh(i_tiDataArea->asciiData0) << ":";
381 ss << "0x34 EID:" << std::setw(8) << std::setfill('0') << std::hex
382 << be32toh(i_tiDataArea->asciiData1);
Ben Tyner40717722020-09-23 09:43:20 -0500383
384 std::string key, value;
385 char delim = ':';
386
387 while (std::getline(ss, key, delim))
388 {
389 std::getline(ss, value, delim);
390 i_map[key] = value;
391 }
392}
393
394/** @brief Read state of autoreboot propertyi via dbus */
Ben Tynerff17f962020-09-23 08:21:19 -0500395bool autoRebootEnabled()
396{
397 // Use dbus get-property interface to read the autoreboot property
398 auto bus = sdbusplus::bus::new_system();
399 auto method =
400 bus.new_method_call("xyz.openbmc_project.Settings",
401 "/xyz/openbmc_project/control/host0/auto_reboot",
402 "org.freedesktop.DBus.Properties", "Get");
Ben Tyner40717722020-09-23 09:43:20 -0500403
Ben Tynerff17f962020-09-23 08:21:19 -0500404 method.append("xyz.openbmc_project.Control.Boot.RebootPolicy",
405 "AutoReboot");
Ben Tyner40717722020-09-23 09:43:20 -0500406
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500407 bool autoReboot = false; // assume autoreboot attribute not available
408
Ben Tynerff17f962020-09-23 08:21:19 -0500409 try
410 {
411 auto reply = bus.call(method);
Ben Tyner40717722020-09-23 09:43:20 -0500412
Ben Tynerff17f962020-09-23 08:21:19 -0500413 std::variant<bool> result;
414 reply.read(result);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500415 autoReboot = std::get<bool>(result);
Ben Tynerff17f962020-09-23 08:21:19 -0500416 }
Ben Tyner6764d702021-02-12 09:17:23 -0600417 catch (const sdbusplus::exception::SdBusError& e)
Ben Tynerff17f962020-09-23 08:21:19 -0500418 {
Ben Tyner6764d702021-02-12 09:17:23 -0600419 trace<level::INFO>("autoRebootEnbabled exception");
420 std::string traceMsg = std::string(e.what(), maxTraceLen);
421 trace<level::ERROR>(traceMsg.c_str());
Ben Tynerff17f962020-09-23 08:21:19 -0500422 }
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500423
424 return autoReboot;
Ben Tynerff17f962020-09-23 08:21:19 -0500425}
Ben Tyner40717722020-09-23 09:43:20 -0500426
Ben Tyner5c5db652021-02-22 18:22:35 -0600427/**
428 * Callback for dump request properties change signal monitor
429 *
430 * @param[in] i_msg Dbus message from the dbus match infrastructure
431 * @param[in] i_path The object path we are monitoring
432 * @param[out] o_inProgress Used to break out of our dbus wait loop
433 * @reutn Always non-zero indicating no error, no cascading callbacks
434 */
435uint dumpStatusChanged(sdbusplus::message::message& i_msg, std::string i_path,
436 bool& o_inProgress)
437{
438 // reply (msg) will be a property change message
439 std::string interface;
440 std::map<std::string, std::variant<std::string, uint8_t>> property;
441 i_msg.read(interface, property);
442
443 // looking for property Status changes
444 std::string propertyType = "Status";
445 auto dumpStatus = property.find(propertyType);
446
447 if (dumpStatus != property.end())
448 {
449 const std::string* status =
450 std::get_if<std::string>(&(dumpStatus->second));
451
452 if ((nullptr != status) && ("xyz.openbmc_project.Common.Progress."
453 "OperationStatus.InProgress" != *status))
454 {
455 // dump is done, trace some info and change in progress flag
456 trace<level::INFO>(i_path.c_str());
457 trace<level::INFO>((*status).c_str());
458 o_inProgress = false;
459 }
460 }
461
462 return 1; // non-negative return code for successful callback
463}
464
465/**
466 * Register a callback for dump progress status changes
467 *
468 * @param[in] i_path The object path of the dump to monitor
469 */
470void monitorDump(const std::string& i_path)
471{
472 bool inProgress = true; // callback will update this
473
474 // setup the signal match rules and callback
475 std::string matchInterface = "xyz.openbmc_project.Common.Progress";
476 auto bus = sdbusplus::bus::new_system();
477
478 std::unique_ptr<sdbusplus::bus::match_t> match =
479 std::make_unique<sdbusplus::bus::match_t>(
480 bus,
481 sdbusplus::bus::match::rules::propertiesChanged(
482 i_path.c_str(), matchInterface.c_str()),
483 [&](auto& msg) {
484 return dumpStatusChanged(msg, i_path, inProgress);
485 });
486
487 // wait for dump status to be completed (complete == true)
488 trace<level::INFO>("hbdump requested");
489 while (true == inProgress)
490 {
491 bus.wait(0);
492 bus.process_discard();
493 }
494 trace<level::INFO>("hbdump completed");
495}
496
497/** Request a dump from the dump manager */
498void requestDump(const uint32_t logId)
499{
500 constexpr auto path = "/org/openpower/dump";
501 constexpr auto interface = "xyz.openbmc_project.Dump.Create";
502 constexpr auto function = "CreateDump";
503
504 sdbusplus::message::message method;
505
506 if (0 == dbusMethod(path, interface, function, method))
507 {
508 try
509 {
510 // dbus call arguments
Ben Tyner8539ee62021-07-21 09:45:09 -0500511 std::map<std::string, std::variant<std::string, uint64_t>>
512 createParams;
Ben Tyner5c5db652021-02-22 18:22:35 -0600513 createParams["com.ibm.Dump.Create.CreateParameters.DumpType"] =
514 "com.ibm.Dump.Create.DumpType.Hostboot";
515 createParams["com.ibm.Dump.Create.CreateParameters.ErrorLogId"] =
Ben Tyner8539ee62021-07-21 09:45:09 -0500516 uint64_t(logId);
Ben Tyner5c5db652021-02-22 18:22:35 -0600517 method.append(createParams);
518
519 // using system dbus
520 auto bus = sdbusplus::bus::new_system();
521 auto response = bus.call(method);
522
523 // reply will be type dbus::ObjectPath
524 sdbusplus::message::object_path reply;
525 response.read(reply);
526
527 // monitor dump progress
528 monitorDump(reply);
529 }
530 catch (const sdbusplus::exception::SdBusError& e)
531 {
532 trace<level::ERROR>("requestDump exception");
533 std::string traceMsg = std::string(e.what(), maxTraceLen);
534 trace<level::ERROR>(traceMsg.c_str());
535 }
536 }
537}
538
Ben Tyner9ae5ca42020-02-28 13:13:50 -0600539} // namespace attn