blob: e1dce7c8b3470ef69b9a2dfadde6b0aa1d039839 [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 {
72 // If autoreboot is enabled we will start diagnostic mode target
73 // which will ultimately mpipl the host.
Ben Tynerbcf65a82020-12-01 08:46:36 -060074 transitionHost(HostState::Diagnostic);
Ben Tyner792f32f2020-06-02 08:50:47 -050075 }
Ben Tyner40717722020-09-23 09:43:20 -050076 else
77 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050078 // If autoreboot is disabled we will quiesce the host
Ben Tynerbcf65a82020-12-01 08:46:36 -060079 transitionHost(HostState::Quiesce);
Ben Tyner40717722020-09-23 09:43:20 -050080 }
Ben Tyner792f32f2020-06-02 08:50:47 -050081
Ben Tyner8c5e4f42020-10-28 11:11:55 -050082 // gather additional data for PEL
83 std::map<std::string, std::string> tiAdditionalData;
Ben Tynere4f5dbe2020-10-19 07:19:33 -050084
Ben Tyner8c5e4f42020-10-28 11:11:55 -050085 if (nullptr != i_tiDataArea)
86 {
87 parsePhypOpalTiInfo(tiAdditionalData, i_tiDataArea);
Ben Tyner8c5e4f42020-10-28 11:11:55 -050088 }
89
Ben Tynerf5210bb2021-01-05 12:58:10 -060090 tiAdditionalData["Subsystem"] =
91 std::to_string(static_cast<uint8_t>(pel::SubsystemID::hypervisor));
92
93 char srcChar[8];
94 memcpy(srcChar, &(i_tiDataArea->asciiData0), 4);
95 memcpy(&srcChar[4], &(i_tiDataArea->asciiData1), 4);
96 tiAdditionalData["SrcAscii"] = std::string{srcChar};
97
98 eventTerminate(tiAdditionalData, (char*)i_tiDataArea);
Ben Tyner8c5e4f42020-10-28 11:11:55 -050099}
100
101/**
102 * @brief Handle a hostboot terminate immediate special attention
103 *
104 * The TI info data area will contain information pertaining to the TI
105 * condition. The course of action to take regarding the host state will
106 * depend on the contents of the TI info data area. We will also create a
107 * PEL containing the TI info data and FFDC data captured in the system
108 * journal.
109 *
110 * @param i_tiDataArea pointer to TI information filled in by hostboot
111 */
112void handleHbTi(TiDataArea* i_tiDataArea)
113{
114 trace<level::INFO>("HB TI");
115
116 bool hbDumpRequested = true; // HB dump is common case
117 bool generatePel = true; // assume PEL will be created
118 bool terminateHost = true; // transition host state
119
120 // handle specific hostboot reason codes
121 if (nullptr != i_tiDataArea)
122 {
123 std::stringstream ss;
124 ss << std::hex << std::showbase;
125
126 switch (i_tiDataArea->hbTerminateType)
127 {
128 case TI_WITH_PLID:
129 case TI_WITH_EID:
130 ss << "TI with PLID/EID: " << be32toh(i_tiDataArea->asciiData1);
131 trace<level::INFO>(ss.str().c_str());
132 if (0 == i_tiDataArea->hbDumpFlag)
133 {
134 hbDumpRequested = false; // no HB dump requested
135 }
136 break;
137 case TI_WITH_SRC:
138 // SRC is byte 2 and 3 of 4 byte srcWord12HbWord0
139 uint16_t hbSrc = be32toh(i_tiDataArea->srcWord12HbWord0);
140
141 // trace some info
142 ss << "TI with SRC: " << (int)hbSrc;
143 trace<level::INFO>(ss.str().c_str());
144 ss.str(std::string()); // clear stream
145
146 switch (hbSrc)
147 {
148 case HB_SRC_SHUTDOWN_REQUEST:
149 trace<level::INFO>("shutdown request");
150 generatePel = false;
151 break;
152 case HB_SRC_KEY_TRANSITION:
153 trace<level::INFO>("key transition");
154 terminateHost = false;
155 break;
156 case HB_SRC_INSUFFICIENT_HW:
157 trace<level::INFO>("insufficient hardware");
158 break;
159 case HB_SRC_TPM_FAIL:
160 trace<level::INFO>("TPM fail");
161 break;
162 case HB_SRC_ROM_VERIFY:
163 trace<level::INFO>("ROM verify");
164 break;
165 case HB_SRC_EXT_MISMATCH:
166 trace<level::INFO>("EXT mismatch");
167 break;
168 case HB_SRC_ECC_UE:
169 trace<level::INFO>("ECC UE");
170 break;
171 case HB_SRC_UNSUPPORTED_MODE:
172 trace<level::INFO>("unsupported mode");
173 break;
174 case HB_SRC_UNSUPPORTED_SFCRANGE:
175 trace<level::INFO>("unsupported SFC range");
176 break;
177 case HB_SRC_PARTITION_TABLE:
178 trace<level::INFO>("partition table invalid");
179 break;
180 case HB_SRC_UNSUPPORTED_HARDWARE:
181 trace<level::INFO>("unsupported hardware");
182 break;
183 case HB_SRC_PNOR_CORRUPTION:
184 trace<level::INFO>("PNOR corruption");
185 break;
186 default:
187 trace<level::INFO>("reason: other");
188 }
189
190 break;
191 }
192 }
193
194 if (true == terminateHost)
195 {
196 // if hostboot dump is requested initiate dump
197 if (hbDumpRequested)
198 {
199 // Until HB dump support available just quiesce the host - once
200 // dump support is available the dump component will transition
201 // (ipl/halt) the host.
Ben Tynerbcf65a82020-12-01 08:46:36 -0600202 transitionHost(HostState::Quiesce);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500203 }
204 else
205 {
206 // Quiese the host - when the host is quiesced it will either
207 // "halt" or IPL depending on autoreboot setting.
Ben Tynerbcf65a82020-12-01 08:46:36 -0600208 transitionHost(HostState::Quiesce);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500209 }
210 }
211
212 // gather additional data for PEL
213 std::map<std::string, std::string> tiAdditionalData;
214
215 if (nullptr != i_tiDataArea)
216 {
217 parseHbTiInfo(tiAdditionalData, i_tiDataArea);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500218 }
219
220 if (true == generatePel)
221 {
Ben Tynerf5210bb2021-01-05 12:58:10 -0600222 tiAdditionalData["Subsystem"] =
223 std::to_string(static_cast<uint8_t>(pel::SubsystemID::hostboot));
Ben Tyner9ae5ca42020-02-28 13:13:50 -0600224
Ben Tynerf5210bb2021-01-05 12:58:10 -0600225 char srcChar[8];
226 memcpy(srcChar, &(i_tiDataArea->srcWord12HbWord0), 4);
227 memcpy(&srcChar[4], &(i_tiDataArea->asciiData1), 4);
228 tiAdditionalData["SrcAscii"] = std::string{srcChar};
Ben Tyner40717722020-09-23 09:43:20 -0500229
Ben Tynerf5210bb2021-01-05 12:58:10 -0600230 eventTerminate(tiAdditionalData, (char*)i_tiDataArea);
Ben Tyner40717722020-09-23 09:43:20 -0500231 }
232}
233
234/** @brief Parse the TI info data area into map as PHYP/OPAL data */
235void parsePhypOpalTiInfo(std::map<std::string, std::string>& i_map,
236 TiDataArea* i_tiDataArea)
237{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600238 if (nullptr == i_tiDataArea)
239 {
240 return;
241 }
242
Ben Tyner40717722020-09-23 09:43:20 -0500243 std::stringstream ss;
244
245 ss << std::hex << std::showbase;
246 ss << "0x00 TI Area Valid:" << (int)i_tiDataArea->tiAreaValid << ":";
247 ss << "0x01 Command:" << (int)i_tiDataArea->command << ":";
248 ss << "0x02 Num. Data Bytes:" << be16toh(i_tiDataArea->numDataBytes) << ":";
249 ss << "0x04 Reserved:" << (int)i_tiDataArea->reserved1 << ":";
250 ss << "0x06 HWDump Type:" << be16toh(i_tiDataArea->hardwareDumpType) << ":";
251 ss << "0x08 SRC Format:" << (int)i_tiDataArea->srcFormat << ":";
252 ss << "0x09 SRC Flags:" << (int)i_tiDataArea->srcFlags << ":";
253 ss << "0x0a Num. ASCII Words:" << (int)i_tiDataArea->numAsciiWords << ":";
254 ss << "0x0b Num. Hex Words:" << (int)i_tiDataArea->numHexWords << ":";
255 ss << "0x0e Length of SRC:" << be16toh(i_tiDataArea->lenSrc) << ":";
256 ss << "0x10 SRC Word 12:" << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
257 ss << "0x14 SRC Word 13:" << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
258 ss << "0x18 SRC Word 14:" << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
259 ss << "0x1c SRC Word 15:" << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
260 ss << "0x20 SRC Word 16:" << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
261 ss << "0x24 SRC Word 17:" << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
262 ss << "0x28 SRC Word 18:" << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
263 ss << "0x2c SRC Word 19:" << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
264 ss << "0x30 ASCII Data:" << be32toh(i_tiDataArea->asciiData0) << ":";
265 ss << "0x34 ASCII Data:" << be32toh(i_tiDataArea->asciiData1) << ":";
266 ss << "0x38 ASCII Data:" << be32toh(i_tiDataArea->asciiData2) << ":";
267 ss << "0x3c ASCII Data:" << be32toh(i_tiDataArea->asciiData3) << ":";
268 ss << "0x40 ASCII Data:" << be32toh(i_tiDataArea->asciiData4) << ":";
269 ss << "0x44 ASCII Data:" << be32toh(i_tiDataArea->asciiData5) << ":";
270 ss << "0x48 ASCII Data:" << be32toh(i_tiDataArea->asciiData6) << ":";
271 ss << "0x4c ASCII Data:" << be32toh(i_tiDataArea->asciiData7) << ":";
272 ss << "0x50 Location:" << (int)i_tiDataArea->location << ":";
273 ss << "0x51 Code Sections:" << (int)i_tiDataArea->codeSection << ":";
274 ss << "0x52 Additional Size:" << (int)i_tiDataArea->additionalSize << ":";
275 ss << "0x53 Additional Data:" << (int)i_tiDataArea->andData;
276
277 std::string key, value;
278 char delim = ':';
279
280 while (std::getline(ss, key, delim))
281 {
282 std::getline(ss, value, delim);
283 i_map[key] = value;
284 }
285}
286
287/** @brief Parse the TI info data area into map as hostboot data */
288void parseHbTiInfo(std::map<std::string, std::string>& i_map,
289 TiDataArea* i_tiDataArea)
290{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600291 if (nullptr == i_tiDataArea)
292 {
293 return;
294 }
295
Ben Tyner40717722020-09-23 09:43:20 -0500296 std::stringstream ss;
297
298 ss << std::hex << std::showbase;
299 ss << "0x00 TI Area Valid:" << (int)i_tiDataArea->tiAreaValid << ":";
300 ss << "0x04 Reserved:" << (int)i_tiDataArea->reserved1 << ":";
301 ss << "0x05 HB_Term. Type:" << (int)i_tiDataArea->hbTerminateType << ":";
302 ss << "0x0c HB Dump Flag:" << (int)i_tiDataArea->hbDumpFlag << ":";
303 ss << "0x0d Source:" << (int)i_tiDataArea->source << ":";
304 ss << "0x10 HB Word 0:" << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
305 ss << "0x14 HB Word 2:" << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
306 ss << "0x18 HB Word 3:" << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
307 ss << "0x1c HB Word 4:" << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
308 ss << "0x20 HB Word 5:" << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
309 ss << "0x24 HB Word 6:" << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
310 ss << "0x28 HB Word 7:" << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
311 ss << "0x2c HB Word 8:" << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
312 ss << "0x30 error_data:" << be32toh(i_tiDataArea->asciiData0) << ":";
313 ss << "0x34 EID:" << be32toh(i_tiDataArea->asciiData1);
314
315 std::string key, value;
316 char delim = ':';
317
318 while (std::getline(ss, key, delim))
319 {
320 std::getline(ss, value, delim);
321 i_map[key] = value;
322 }
323}
324
325/** @brief Read state of autoreboot propertyi via dbus */
Ben Tynerff17f962020-09-23 08:21:19 -0500326bool autoRebootEnabled()
327{
328 // Use dbus get-property interface to read the autoreboot property
329 auto bus = sdbusplus::bus::new_system();
330 auto method =
331 bus.new_method_call("xyz.openbmc_project.Settings",
332 "/xyz/openbmc_project/control/host0/auto_reboot",
333 "org.freedesktop.DBus.Properties", "Get");
Ben Tyner40717722020-09-23 09:43:20 -0500334
Ben Tynerff17f962020-09-23 08:21:19 -0500335 method.append("xyz.openbmc_project.Control.Boot.RebootPolicy",
336 "AutoReboot");
Ben Tyner40717722020-09-23 09:43:20 -0500337
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500338 bool autoReboot = false; // assume autoreboot attribute not available
339
Ben Tynerff17f962020-09-23 08:21:19 -0500340 try
341 {
342 auto reply = bus.call(method);
Ben Tyner40717722020-09-23 09:43:20 -0500343
Ben Tynerff17f962020-09-23 08:21:19 -0500344 std::variant<bool> result;
345 reply.read(result);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500346 autoReboot = std::get<bool>(result);
Ben Tynerff17f962020-09-23 08:21:19 -0500347 }
348 catch (const sdbusplus::exception::SdBusError& ec)
349 {
Ben Tynerff17f962020-09-23 08:21:19 -0500350 std::string traceMessage =
351 "Error in AutoReboot Get: " + std::string(ec.what());
352 trace<level::INFO>(traceMessage.c_str());
Ben Tynerff17f962020-09-23 08:21:19 -0500353 }
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500354
355 return autoReboot;
Ben Tynerff17f962020-09-23 08:21:19 -0500356}
Ben Tyner40717722020-09-23 09:43:20 -0500357
Ben Tyner9ae5ca42020-02-28 13:13:50 -0600358} // namespace attn