blob: 35fb346162727ff9b36977bfae5f7c84cf7d1ef5 [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>
4#include <attn/ti_handler.hpp>
Ben Tyner9ae5ca42020-02-28 13:13:50 -06005#include <sdbusplus/bus.hpp>
Ben Tynerff17f962020-09-23 08:21:19 -05006#include <sdbusplus/exception.hpp>
Ben Tyner9ae5ca42020-02-28 13:13:50 -06007
Ben Tyner40717722020-09-23 09:43:20 -05008#include <iomanip>
9#include <iostream>
10
Ben Tyner9ae5ca42020-02-28 13:13:50 -060011namespace attn
12{
13
Ben Tyner8c5e4f42020-10-28 11:11:55 -050014/**
15 * @brief Determine if this is a HB or PHYP TI event
16 *
17 * Use the TI info data area to determine if this is either a HB or a PHYP
18 * TI event then handle the event.
19 *
20 * @param i_tiDataArea pointer to the TI infor data
21 */
Ben Tyner792f32f2020-06-02 08:50:47 -050022int tiHandler(TiDataArea* i_tiDataArea)
Ben Tyner9ae5ca42020-02-28 13:13:50 -060023{
Ben Tynere4f5dbe2020-10-19 07:19:33 -050024 int rc = RC_SUCCESS;
Ben Tyner9ae5ca42020-02-28 13:13:50 -060025
Ben Tyner8c5e4f42020-10-28 11:11:55 -050026 // check TI data area if it is available
Ben Tynere4f5dbe2020-10-19 07:19:33 -050027 if (nullptr != i_tiDataArea)
Ben Tyner792f32f2020-06-02 08:50:47 -050028 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050029 // HB v. PHYP TI logic: Only hosboot will fill in hbTerminateType
30 // and it will be non-zero. Only hostboot will fill out source and it
31 // it will be non-zero. Only PHYP will fill in srcFormat and it will
32 // be non-zero.
33 // source and only PHYP will fill in srcFormat.
34 if ((0 == i_tiDataArea->hbTerminateType) &&
35 (0 == i_tiDataArea->source) && (0 != i_tiDataArea->srcFormat))
Ben Tynere4f5dbe2020-10-19 07:19:33 -050036 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050037 handlePhypTi(i_tiDataArea);
Ben Tynere4f5dbe2020-10-19 07:19:33 -050038 }
39 else
40 {
Ben Tyner8c5e4f42020-10-28 11:11:55 -050041 handleHbTi(i_tiDataArea);
Ben Tynere4f5dbe2020-10-19 07:19:33 -050042 }
Ben Tyner8c5e4f42020-10-28 11:11:55 -050043 }
44 else
45 {
46 // TI data was not available, assume PHYP TI for now. When a host state
47 // management interface becomes availabe we may be able to make a more
48 // informed decision here.
49 handlePhypTi(i_tiDataArea);
Ben Tynere4f5dbe2020-10-19 07:19:33 -050050 }
Ben Tyner40717722020-09-23 09:43:20 -050051
Ben Tyner8c5e4f42020-10-28 11:11:55 -050052 return rc;
53}
Ben Tynere4f5dbe2020-10-19 07:19:33 -050054
Ben Tyner8c5e4f42020-10-28 11:11:55 -050055/**
Ben Tyner8c5e4f42020-10-28 11:11:55 -050056 * @brief Handle a PHYP terminate immediate special attention
57 *
58 * The TI info data area will contain information pertaining to the TI
59 * condition. We will wither quiesce the host or initiate a MPIPL depending
60 * depending on the auto reboot configuration. We will also create a PEL which
61 * will contain the TI info data and FFDC data captured in the system journal.
62 *
63 * @param i_tiDataArea pointer to TI information filled in by hostboot
64 */
65void handlePhypTi(TiDataArea* i_tiDataArea)
66{
67 trace<level::INFO>("PHYP TI");
68
69 if (autoRebootEnabled())
70 {
71 // If autoreboot is enabled we will start diagnostic mode target
72 // which will ultimately mpipl the host.
Ben Tynerbcf65a82020-12-01 08:46:36 -060073 transitionHost(HostState::Diagnostic);
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);
87 parseRawTiInfo(tiAdditionalData, i_tiDataArea);
88 }
89
90 eventTerminate(tiAdditionalData); // generate PEL
91}
92
93/**
94 * @brief Handle a hostboot terminate immediate special attention
95 *
96 * The TI info data area will contain information pertaining to the TI
97 * condition. The course of action to take regarding the host state will
98 * depend on the contents of the TI info data area. We will also create a
99 * PEL containing the TI info data and FFDC data captured in the system
100 * journal.
101 *
102 * @param i_tiDataArea pointer to TI information filled in by hostboot
103 */
104void handleHbTi(TiDataArea* i_tiDataArea)
105{
106 trace<level::INFO>("HB TI");
107
108 bool hbDumpRequested = true; // HB dump is common case
109 bool generatePel = true; // assume PEL will be created
110 bool terminateHost = true; // transition host state
111
112 // handle specific hostboot reason codes
113 if (nullptr != i_tiDataArea)
114 {
115 std::stringstream ss;
116 ss << std::hex << std::showbase;
117
118 switch (i_tiDataArea->hbTerminateType)
119 {
120 case TI_WITH_PLID:
121 case TI_WITH_EID:
122 ss << "TI with PLID/EID: " << be32toh(i_tiDataArea->asciiData1);
123 trace<level::INFO>(ss.str().c_str());
124 if (0 == i_tiDataArea->hbDumpFlag)
125 {
126 hbDumpRequested = false; // no HB dump requested
127 }
128 break;
129 case TI_WITH_SRC:
130 // SRC is byte 2 and 3 of 4 byte srcWord12HbWord0
131 uint16_t hbSrc = be32toh(i_tiDataArea->srcWord12HbWord0);
132
133 // trace some info
134 ss << "TI with SRC: " << (int)hbSrc;
135 trace<level::INFO>(ss.str().c_str());
136 ss.str(std::string()); // clear stream
137
138 switch (hbSrc)
139 {
140 case HB_SRC_SHUTDOWN_REQUEST:
141 trace<level::INFO>("shutdown request");
142 generatePel = false;
143 break;
144 case HB_SRC_KEY_TRANSITION:
145 trace<level::INFO>("key transition");
146 terminateHost = false;
147 break;
148 case HB_SRC_INSUFFICIENT_HW:
149 trace<level::INFO>("insufficient hardware");
150 break;
151 case HB_SRC_TPM_FAIL:
152 trace<level::INFO>("TPM fail");
153 break;
154 case HB_SRC_ROM_VERIFY:
155 trace<level::INFO>("ROM verify");
156 break;
157 case HB_SRC_EXT_MISMATCH:
158 trace<level::INFO>("EXT mismatch");
159 break;
160 case HB_SRC_ECC_UE:
161 trace<level::INFO>("ECC UE");
162 break;
163 case HB_SRC_UNSUPPORTED_MODE:
164 trace<level::INFO>("unsupported mode");
165 break;
166 case HB_SRC_UNSUPPORTED_SFCRANGE:
167 trace<level::INFO>("unsupported SFC range");
168 break;
169 case HB_SRC_PARTITION_TABLE:
170 trace<level::INFO>("partition table invalid");
171 break;
172 case HB_SRC_UNSUPPORTED_HARDWARE:
173 trace<level::INFO>("unsupported hardware");
174 break;
175 case HB_SRC_PNOR_CORRUPTION:
176 trace<level::INFO>("PNOR corruption");
177 break;
178 default:
179 trace<level::INFO>("reason: other");
180 }
181
182 break;
183 }
184 }
185
186 if (true == terminateHost)
187 {
188 // if hostboot dump is requested initiate dump
189 if (hbDumpRequested)
190 {
191 // Until HB dump support available just quiesce the host - once
192 // dump support is available the dump component will transition
193 // (ipl/halt) the host.
Ben Tynerbcf65a82020-12-01 08:46:36 -0600194 transitionHost(HostState::Quiesce);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500195 }
196 else
197 {
198 // Quiese the host - when the host is quiesced it will either
199 // "halt" or IPL depending on autoreboot setting.
Ben Tynerbcf65a82020-12-01 08:46:36 -0600200 transitionHost(HostState::Quiesce);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500201 }
202 }
203
204 // gather additional data for PEL
205 std::map<std::string, std::string> tiAdditionalData;
206
207 if (nullptr != i_tiDataArea)
208 {
209 parseHbTiInfo(tiAdditionalData, i_tiDataArea);
210 parseRawTiInfo(tiAdditionalData, i_tiDataArea);
211 }
212
213 if (true == generatePel)
214 {
215 eventTerminate(tiAdditionalData); // generate PEL
216 }
Ben Tyner9ae5ca42020-02-28 13:13:50 -0600217}
218
Ben Tyner40717722020-09-23 09:43:20 -0500219/** @brief Parse the TI info data area into map as raw 32-bit fields */
220void parseRawTiInfo(std::map<std::string, std::string>& i_map,
221 TiDataArea* i_buffer)
222{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600223 if (nullptr == i_buffer)
224 {
225 return;
226 }
Ben Tyner40717722020-09-23 09:43:20 -0500227
228 uint32_t* tiDataArea = (uint32_t*)i_buffer;
229 std::stringstream ss;
230
231 ss << std::hex << std::setfill('0');
232 ss << "raw:";
233 while (tiDataArea <= (uint32_t*)((char*)i_buffer + sizeof(TiDataArea)))
234 {
235 ss << std::setw(8) << std::endl << be32toh(*tiDataArea);
236 tiDataArea++;
237 }
238
239 std::string key, value;
240 char delim = ':';
241
242 while (std::getline(ss, key, delim))
243 {
244 std::getline(ss, value, delim);
245 i_map[key] = value;
246 }
247}
248
249/** @brief Parse the TI info data area into map as PHYP/OPAL data */
250void parsePhypOpalTiInfo(std::map<std::string, std::string>& i_map,
251 TiDataArea* i_tiDataArea)
252{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600253 if (nullptr == i_tiDataArea)
254 {
255 return;
256 }
257
Ben Tyner40717722020-09-23 09:43:20 -0500258 std::stringstream ss;
259
260 ss << std::hex << std::showbase;
261 ss << "0x00 TI Area Valid:" << (int)i_tiDataArea->tiAreaValid << ":";
262 ss << "0x01 Command:" << (int)i_tiDataArea->command << ":";
263 ss << "0x02 Num. Data Bytes:" << be16toh(i_tiDataArea->numDataBytes) << ":";
264 ss << "0x04 Reserved:" << (int)i_tiDataArea->reserved1 << ":";
265 ss << "0x06 HWDump Type:" << be16toh(i_tiDataArea->hardwareDumpType) << ":";
266 ss << "0x08 SRC Format:" << (int)i_tiDataArea->srcFormat << ":";
267 ss << "0x09 SRC Flags:" << (int)i_tiDataArea->srcFlags << ":";
268 ss << "0x0a Num. ASCII Words:" << (int)i_tiDataArea->numAsciiWords << ":";
269 ss << "0x0b Num. Hex Words:" << (int)i_tiDataArea->numHexWords << ":";
270 ss << "0x0e Length of SRC:" << be16toh(i_tiDataArea->lenSrc) << ":";
271 ss << "0x10 SRC Word 12:" << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
272 ss << "0x14 SRC Word 13:" << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
273 ss << "0x18 SRC Word 14:" << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
274 ss << "0x1c SRC Word 15:" << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
275 ss << "0x20 SRC Word 16:" << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
276 ss << "0x24 SRC Word 17:" << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
277 ss << "0x28 SRC Word 18:" << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
278 ss << "0x2c SRC Word 19:" << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
279 ss << "0x30 ASCII Data:" << be32toh(i_tiDataArea->asciiData0) << ":";
280 ss << "0x34 ASCII Data:" << be32toh(i_tiDataArea->asciiData1) << ":";
281 ss << "0x38 ASCII Data:" << be32toh(i_tiDataArea->asciiData2) << ":";
282 ss << "0x3c ASCII Data:" << be32toh(i_tiDataArea->asciiData3) << ":";
283 ss << "0x40 ASCII Data:" << be32toh(i_tiDataArea->asciiData4) << ":";
284 ss << "0x44 ASCII Data:" << be32toh(i_tiDataArea->asciiData5) << ":";
285 ss << "0x48 ASCII Data:" << be32toh(i_tiDataArea->asciiData6) << ":";
286 ss << "0x4c ASCII Data:" << be32toh(i_tiDataArea->asciiData7) << ":";
287 ss << "0x50 Location:" << (int)i_tiDataArea->location << ":";
288 ss << "0x51 Code Sections:" << (int)i_tiDataArea->codeSection << ":";
289 ss << "0x52 Additional Size:" << (int)i_tiDataArea->additionalSize << ":";
290 ss << "0x53 Additional Data:" << (int)i_tiDataArea->andData;
291
292 std::string key, value;
293 char delim = ':';
294
295 while (std::getline(ss, key, delim))
296 {
297 std::getline(ss, value, delim);
298 i_map[key] = value;
299 }
300}
301
302/** @brief Parse the TI info data area into map as hostboot data */
303void parseHbTiInfo(std::map<std::string, std::string>& i_map,
304 TiDataArea* i_tiDataArea)
305{
Ben Tyner1c4b02e2020-11-09 14:00:29 -0600306 if (nullptr == i_tiDataArea)
307 {
308 return;
309 }
310
Ben Tyner40717722020-09-23 09:43:20 -0500311 std::stringstream ss;
312
313 ss << std::hex << std::showbase;
314 ss << "0x00 TI Area Valid:" << (int)i_tiDataArea->tiAreaValid << ":";
315 ss << "0x04 Reserved:" << (int)i_tiDataArea->reserved1 << ":";
316 ss << "0x05 HB_Term. Type:" << (int)i_tiDataArea->hbTerminateType << ":";
317 ss << "0x0c HB Dump Flag:" << (int)i_tiDataArea->hbDumpFlag << ":";
318 ss << "0x0d Source:" << (int)i_tiDataArea->source << ":";
319 ss << "0x10 HB Word 0:" << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
320 ss << "0x14 HB Word 2:" << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
321 ss << "0x18 HB Word 3:" << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
322 ss << "0x1c HB Word 4:" << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
323 ss << "0x20 HB Word 5:" << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
324 ss << "0x24 HB Word 6:" << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
325 ss << "0x28 HB Word 7:" << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
326 ss << "0x2c HB Word 8:" << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
327 ss << "0x30 error_data:" << be32toh(i_tiDataArea->asciiData0) << ":";
328 ss << "0x34 EID:" << be32toh(i_tiDataArea->asciiData1);
329
330 std::string key, value;
331 char delim = ':';
332
333 while (std::getline(ss, key, delim))
334 {
335 std::getline(ss, value, delim);
336 i_map[key] = value;
337 }
338}
339
340/** @brief Read state of autoreboot propertyi via dbus */
Ben Tynerff17f962020-09-23 08:21:19 -0500341bool autoRebootEnabled()
342{
343 // Use dbus get-property interface to read the autoreboot property
344 auto bus = sdbusplus::bus::new_system();
345 auto method =
346 bus.new_method_call("xyz.openbmc_project.Settings",
347 "/xyz/openbmc_project/control/host0/auto_reboot",
348 "org.freedesktop.DBus.Properties", "Get");
Ben Tyner40717722020-09-23 09:43:20 -0500349
Ben Tynerff17f962020-09-23 08:21:19 -0500350 method.append("xyz.openbmc_project.Control.Boot.RebootPolicy",
351 "AutoReboot");
Ben Tyner40717722020-09-23 09:43:20 -0500352
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500353 bool autoReboot = false; // assume autoreboot attribute not available
354
Ben Tynerff17f962020-09-23 08:21:19 -0500355 try
356 {
357 auto reply = bus.call(method);
Ben Tyner40717722020-09-23 09:43:20 -0500358
Ben Tynerff17f962020-09-23 08:21:19 -0500359 std::variant<bool> result;
360 reply.read(result);
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500361 autoReboot = std::get<bool>(result);
Ben Tynerff17f962020-09-23 08:21:19 -0500362 }
363 catch (const sdbusplus::exception::SdBusError& ec)
364 {
Ben Tynerff17f962020-09-23 08:21:19 -0500365 std::string traceMessage =
366 "Error in AutoReboot Get: " + std::string(ec.what());
367 trace<level::INFO>(traceMessage.c_str());
Ben Tynerff17f962020-09-23 08:21:19 -0500368 }
Ben Tyner8c5e4f42020-10-28 11:11:55 -0500369
370 return autoReboot;
Ben Tynerff17f962020-09-23 08:21:19 -0500371}
Ben Tyner40717722020-09-23 09:43:20 -0500372
Ben Tyner9ae5ca42020-02-28 13:13:50 -0600373} // namespace attn