blob: 677cf148a239ca6ad83b7f639710eecec436f0e5 [file] [log] [blame]
Ben Tynerbcf65a82020-12-01 08:46:36 -06001#include <attn/attn_common.hpp>
Ben Tynerb797b3e2020-06-29 10:12:05 -05002#include <attn/attn_handler.hpp>
3#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 Tyner8c5e4f42020-10-28 11:11:55 -050027 // check TI data area if it is available
Ben Tynere4f5dbe2020-10-19 07:19:33 -050028 if (nullptr != i_tiDataArea)
Ben Tyner792f32f2020-06-02 08:50:47 -050029 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050030 // HB v. PHYP TI logic: Only hosboot will fill in hbTerminateType
31 // and it will be non-zero. Only hostboot will fill out source and it
32 // it will be non-zero. Only PHYP will fill in srcFormat and it will
33 // be non-zero.
34 // source and only PHYP will fill in srcFormat.
35 if ((0 == i_tiDataArea->hbTerminateType) &&
36 (0 == i_tiDataArea->source) && (0 != i_tiDataArea->srcFormat))
Ben Tynere4f5dbe2020-10-19 07:19:33 -050037 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050038 handlePhypTi(i_tiDataArea);
Ben Tynere4f5dbe2020-10-19 07:19:33 -050039 }
40 else
41 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050042 handleHbTi(i_tiDataArea);
Ben Tynere4f5dbe2020-10-19 07:19:33 -050043 }
Ben Tyner8c5e4f42020-10-28 11:11:55 -050044 }
45 else
46 {
47 // TI data was not available, assume PHYP TI for now. When a host state
48 // management interface becomes availabe we may be able to make a more
49 // informed decision here.
50 handlePhypTi(i_tiDataArea);
Ben Tynere4f5dbe2020-10-19 07:19:33 -050051 }
Ben Tyner40717722020-09-23 09:43:20 -050052
Ben Tyner8c5e4f42020-10-28 11:11:55 -050053 return rc;
54}
Ben Tynere4f5dbe2020-10-19 07:19:33 -050055
Ben Tyner8c5e4f42020-10-28 11:11:55 -050056/**
Ben Tyner8c5e4f42020-10-28 11:11:55 -050057 * @brief Handle a PHYP terminate immediate special attention
58 *
59 * The TI info data area will contain information pertaining to the TI
60 * condition. We will wither quiesce the host or initiate a MPIPL depending
61 * depending on the auto reboot configuration. We will also create a PEL which
62 * will contain the TI info data and FFDC data captured in the system journal.
63 *
64 * @param i_tiDataArea pointer to TI information filled in by hostboot
65 */
66void handlePhypTi(TiDataArea* i_tiDataArea)
67{
68 trace<level::INFO>("PHYP TI");
69
70 if (autoRebootEnabled())
71 {
Ben Tynerfe2757b2021-01-14 13:17:50 -060072 // If autoreboot is enabled we will start crash (mpipl) mode target
73 transitionHost(HostState::Crash);
Ben Tyner792f32f2020-06-02 08:50:47 -050074 }
Ben Tyner40717722020-09-23 09:43:20 -050075 else
76 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050077 // If autoreboot is disabled we will quiesce the host
Ben Tynerbcf65a82020-12-01 08:46:36 -060078 transitionHost(HostState::Quiesce);
Ben Tyner40717722020-09-23 09:43:20 -050079 }
Ben Tyner792f32f2020-06-02 08:50:47 -050080
Ben Tyner8c5e4f42020-10-28 11:11:55 -050081 // gather additional data for PEL
82 std::map<std::string, std::string> tiAdditionalData;
Ben Tynere4f5dbe2020-10-19 07:19:33 -050083
Ben Tyner8c5e4f42020-10-28 11:11:55 -050084 if (nullptr != i_tiDataArea)
85 {
86 parsePhypOpalTiInfo(tiAdditionalData, i_tiDataArea);
Ben Tyner8c5e4f42020-10-28 11:11:55 -050087 }
88
Ben Tynerf5210bb2021-01-05 12:58:10 -060089 tiAdditionalData["Subsystem"] =
90 std::to_string(static_cast<uint8_t>(pel::SubsystemID::hypervisor));
91
92 char srcChar[8];
93 memcpy(srcChar, &(i_tiDataArea->asciiData0), 4);
94 memcpy(&srcChar[4], &(i_tiDataArea->asciiData1), 4);
95 tiAdditionalData["SrcAscii"] = std::string{srcChar};
96
97 eventTerminate(tiAdditionalData, (char*)i_tiDataArea);
Ben Tyner8c5e4f42020-10-28 11:11:55 -050098}
99
100/**
101 * @brief Handle a hostboot terminate immediate special attention
102 *
103 * The TI info data area will contain information pertaining to the TI
104 * condition. The course of action to take regarding the host state will
105 * depend on the contents of the TI info data area. We will also create a
106 * PEL containing the TI info data and FFDC data captured in the system
107 * journal.
108 *
109 * @param i_tiDataArea pointer to TI information filled in by hostboot
110 */
111void handleHbTi(TiDataArea* i_tiDataArea)
112{
113 trace<level::INFO>("HB TI");
114
115 bool hbDumpRequested = true; // HB dump is common case
116 bool generatePel = true; // assume PEL will be created
117 bool terminateHost = true; // transition host state
118
119 // handle specific hostboot reason codes
120 if (nullptr != i_tiDataArea)
121 {
122 std::stringstream ss;
123 ss << std::hex << std::showbase;
124
125 switch (i_tiDataArea->hbTerminateType)
126 {
127 case TI_WITH_PLID:
128 case TI_WITH_EID:
129 ss << "TI with PLID/EID: " << be32toh(i_tiDataArea->asciiData1);
130 trace<level::INFO>(ss.str().c_str());
131 if (0 == i_tiDataArea->hbDumpFlag)
132 {
133 hbDumpRequested = false; // no HB dump requested
134 }
135 break;
136 case TI_WITH_SRC:
137 // SRC is byte 2 and 3 of 4 byte srcWord12HbWord0
138 uint16_t hbSrc = be32toh(i_tiDataArea->srcWord12HbWord0);
139
140 // trace some info
141 ss << "TI with SRC: " << (int)hbSrc;
142 trace<level::INFO>(ss.str().c_str());
143 ss.str(std::string()); // clear stream
144
145 switch (hbSrc)
146 {
147 case HB_SRC_SHUTDOWN_REQUEST:
148 trace<level::INFO>("shutdown request");
149 generatePel = false;
150 break;
151 case HB_SRC_KEY_TRANSITION:
152 trace<level::INFO>("key transition");
153 terminateHost = false;
154 break;
155 case HB_SRC_INSUFFICIENT_HW:
156 trace<level::INFO>("insufficient hardware");
157 break;
158 case HB_SRC_TPM_FAIL:
159 trace<level::INFO>("TPM fail");
160 break;
161 case HB_SRC_ROM_VERIFY:
162 trace<level::INFO>("ROM verify");
163 break;
164 case HB_SRC_EXT_MISMATCH:
165 trace<level::INFO>("EXT mismatch");
166 break;
167 case HB_SRC_ECC_UE:
168 trace<level::INFO>("ECC UE");
169 break;
170 case HB_SRC_UNSUPPORTED_MODE:
171 trace<level::INFO>("unsupported mode");
172 break;
173 case HB_SRC_UNSUPPORTED_SFCRANGE:
174 trace<level::INFO>("unsupported SFC range");
175 break;
176 case HB_SRC_PARTITION_TABLE:
177 trace<level::INFO>("partition table invalid");
178 break;
179 case HB_SRC_UNSUPPORTED_HARDWARE:
180 trace<level::INFO>("unsupported hardware");
181 break;
182 case HB_SRC_PNOR_CORRUPTION:
183 trace<level::INFO>("PNOR corruption");
184 break;
185 default:
186 trace<level::INFO>("reason: other");
187 }
188
189 break;
190 }
191 }
192
193 if (true == terminateHost)
194 {
195 // if hostboot dump is requested initiate dump
196 if (hbDumpRequested)
197 {
198 // Until HB dump support available just quiesce the host - once
199 // dump support is available the dump component will transition
200 // (ipl/halt) the host.
Ben Tynerbcf65a82020-12-01 08:46:36 -0600201 transitionHost(HostState::Quiesce);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500202 }
203 else
204 {
205 // Quiese the host - when the host is quiesced it will either
206 // "halt" or IPL depending on autoreboot setting.
Ben Tynerbcf65a82020-12-01 08:46:36 -0600207 transitionHost(HostState::Quiesce);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500208 }
209 }
210
211 // gather additional data for PEL
212 std::map<std::string, std::string> tiAdditionalData;
213
214 if (nullptr != i_tiDataArea)
215 {
216 parseHbTiInfo(tiAdditionalData, i_tiDataArea);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500217 }
218
219 if (true == generatePel)
220 {
Ben Tynerf5210bb2021-01-05 12:58:10 -0600221 tiAdditionalData["Subsystem"] =
222 std::to_string(static_cast<uint8_t>(pel::SubsystemID::hostboot));
Ben Tyner9ae5ca42020-02-28 13:13:50 -0600223
Ben Tynerf5210bb2021-01-05 12:58:10 -0600224 char srcChar[8];
225 memcpy(srcChar, &(i_tiDataArea->srcWord12HbWord0), 4);
226 memcpy(&srcChar[4], &(i_tiDataArea->asciiData1), 4);
227 tiAdditionalData["SrcAscii"] = std::string{srcChar};
Ben Tyner40717722020-09-23 09:43:20 -0500228
Ben Tynerf5210bb2021-01-05 12:58:10 -0600229 eventTerminate(tiAdditionalData, (char*)i_tiDataArea);
Ben Tyner40717722020-09-23 09:43:20 -0500230 }
231}
232
233/** @brief Parse the TI info data area into map as PHYP/OPAL data */
234void parsePhypOpalTiInfo(std::map<std::string, std::string>& i_map,
235 TiDataArea* i_tiDataArea)
236{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600237 if (nullptr == i_tiDataArea)
238 {
239 return;
240 }
241
Ben Tyner40717722020-09-23 09:43:20 -0500242 std::stringstream ss;
243
244 ss << std::hex << std::showbase;
245 ss << "0x00 TI Area Valid:" << (int)i_tiDataArea->tiAreaValid << ":";
246 ss << "0x01 Command:" << (int)i_tiDataArea->command << ":";
247 ss << "0x02 Num. Data Bytes:" << be16toh(i_tiDataArea->numDataBytes) << ":";
248 ss << "0x04 Reserved:" << (int)i_tiDataArea->reserved1 << ":";
249 ss << "0x06 HWDump Type:" << be16toh(i_tiDataArea->hardwareDumpType) << ":";
250 ss << "0x08 SRC Format:" << (int)i_tiDataArea->srcFormat << ":";
251 ss << "0x09 SRC Flags:" << (int)i_tiDataArea->srcFlags << ":";
252 ss << "0x0a Num. ASCII Words:" << (int)i_tiDataArea->numAsciiWords << ":";
253 ss << "0x0b Num. Hex Words:" << (int)i_tiDataArea->numHexWords << ":";
254 ss << "0x0e Length of SRC:" << be16toh(i_tiDataArea->lenSrc) << ":";
255 ss << "0x10 SRC Word 12:" << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
256 ss << "0x14 SRC Word 13:" << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
257 ss << "0x18 SRC Word 14:" << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
258 ss << "0x1c SRC Word 15:" << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
259 ss << "0x20 SRC Word 16:" << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
260 ss << "0x24 SRC Word 17:" << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
261 ss << "0x28 SRC Word 18:" << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
262 ss << "0x2c SRC Word 19:" << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
263 ss << "0x30 ASCII Data:" << be32toh(i_tiDataArea->asciiData0) << ":";
264 ss << "0x34 ASCII Data:" << be32toh(i_tiDataArea->asciiData1) << ":";
265 ss << "0x38 ASCII Data:" << be32toh(i_tiDataArea->asciiData2) << ":";
266 ss << "0x3c ASCII Data:" << be32toh(i_tiDataArea->asciiData3) << ":";
267 ss << "0x40 ASCII Data:" << be32toh(i_tiDataArea->asciiData4) << ":";
268 ss << "0x44 ASCII Data:" << be32toh(i_tiDataArea->asciiData5) << ":";
269 ss << "0x48 ASCII Data:" << be32toh(i_tiDataArea->asciiData6) << ":";
270 ss << "0x4c ASCII Data:" << be32toh(i_tiDataArea->asciiData7) << ":";
271 ss << "0x50 Location:" << (int)i_tiDataArea->location << ":";
272 ss << "0x51 Code Sections:" << (int)i_tiDataArea->codeSection << ":";
273 ss << "0x52 Additional Size:" << (int)i_tiDataArea->additionalSize << ":";
274 ss << "0x53 Additional Data:" << (int)i_tiDataArea->andData;
275
276 std::string key, value;
277 char delim = ':';
278
279 while (std::getline(ss, key, delim))
280 {
281 std::getline(ss, value, delim);
282 i_map[key] = value;
283 }
284}
285
286/** @brief Parse the TI info data area into map as hostboot data */
287void parseHbTiInfo(std::map<std::string, std::string>& i_map,
288 TiDataArea* i_tiDataArea)
289{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600290 if (nullptr == i_tiDataArea)
291 {
292 return;
293 }
294
Ben Tyner40717722020-09-23 09:43:20 -0500295 std::stringstream ss;
296
297 ss << std::hex << std::showbase;
298 ss << "0x00 TI Area Valid:" << (int)i_tiDataArea->tiAreaValid << ":";
299 ss << "0x04 Reserved:" << (int)i_tiDataArea->reserved1 << ":";
300 ss << "0x05 HB_Term. Type:" << (int)i_tiDataArea->hbTerminateType << ":";
301 ss << "0x0c HB Dump Flag:" << (int)i_tiDataArea->hbDumpFlag << ":";
302 ss << "0x0d Source:" << (int)i_tiDataArea->source << ":";
303 ss << "0x10 HB Word 0:" << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
304 ss << "0x14 HB Word 2:" << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
305 ss << "0x18 HB Word 3:" << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
306 ss << "0x1c HB Word 4:" << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
307 ss << "0x20 HB Word 5:" << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
308 ss << "0x24 HB Word 6:" << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
309 ss << "0x28 HB Word 7:" << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
310 ss << "0x2c HB Word 8:" << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
311 ss << "0x30 error_data:" << be32toh(i_tiDataArea->asciiData0) << ":";
312 ss << "0x34 EID:" << be32toh(i_tiDataArea->asciiData1);
313
314 std::string key, value;
315 char delim = ':';
316
317 while (std::getline(ss, key, delim))
318 {
319 std::getline(ss, value, delim);
320 i_map[key] = value;
321 }
322}
323
324/** @brief Read state of autoreboot propertyi via dbus */
Ben Tynerff17f962020-09-23 08:21:19 -0500325bool autoRebootEnabled()
326{
327 // Use dbus get-property interface to read the autoreboot property
328 auto bus = sdbusplus::bus::new_system();
329 auto method =
330 bus.new_method_call("xyz.openbmc_project.Settings",
331 "/xyz/openbmc_project/control/host0/auto_reboot",
332 "org.freedesktop.DBus.Properties", "Get");
Ben Tyner40717722020-09-23 09:43:20 -0500333
Ben Tynerff17f962020-09-23 08:21:19 -0500334 method.append("xyz.openbmc_project.Control.Boot.RebootPolicy",
335 "AutoReboot");
Ben Tyner40717722020-09-23 09:43:20 -0500336
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500337 bool autoReboot = false; // assume autoreboot attribute not available
338
Ben Tynerff17f962020-09-23 08:21:19 -0500339 try
340 {
341 auto reply = bus.call(method);
Ben Tyner40717722020-09-23 09:43:20 -0500342
Ben Tynerff17f962020-09-23 08:21:19 -0500343 std::variant<bool> result;
344 reply.read(result);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500345 autoReboot = std::get<bool>(result);
Ben Tynerff17f962020-09-23 08:21:19 -0500346 }
347 catch (const sdbusplus::exception::SdBusError& ec)
348 {
Ben Tynerff17f962020-09-23 08:21:19 -0500349 std::string traceMessage =
350 "Error in AutoReboot Get: " + std::string(ec.what());
351 trace<level::INFO>(traceMessage.c_str());
Ben Tynerff17f962020-09-23 08:21:19 -0500352 }
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500353
354 return autoReboot;
Ben Tynerff17f962020-09-23 08:21:19 -0500355}
Ben Tyner40717722020-09-23 09:43:20 -0500356
Ben Tyner9ae5ca42020-02-28 13:13:50 -0600357} // namespace attn