blob: 3d24f32e72b6bc7f35070b294bcad3f511737f1f [file] [log] [blame]
Ben Tynerb797b3e2020-06-29 10:12:05 -05001#include <attn/attn_handler.hpp>
2#include <attn/attn_logging.hpp>
3#include <attn/ti_handler.hpp>
Ben Tyner9ae5ca42020-02-28 13:13:50 -06004#include <sdbusplus/bus.hpp>
Ben Tynerff17f962020-09-23 08:21:19 -05005#include <sdbusplus/exception.hpp>
Ben Tyner9ae5ca42020-02-28 13:13:50 -06006
Ben Tyner40717722020-09-23 09:43:20 -05007#include <iomanip>
8#include <iostream>
9
Ben Tyner9ae5ca42020-02-28 13:13:50 -060010namespace attn
11{
12
Ben Tynerff17f962020-09-23 08:21:19 -050013/** @brief Start host diagnostic mode or quiesce host on TI */
Ben Tyner792f32f2020-06-02 08:50:47 -050014int tiHandler(TiDataArea* i_tiDataArea)
Ben Tyner9ae5ca42020-02-28 13:13:50 -060015{
Ben Tynere4f5dbe2020-10-19 07:19:33 -050016 int rc = RC_SUCCESS;
Ben Tyner9ae5ca42020-02-28 13:13:50 -060017
Ben Tynere4f5dbe2020-10-19 07:19:33 -050018 std::map<std::string, std::string> tiAdditionalData;
19
20 // If TI Info is available we can add it to the PEL
21 if (nullptr != i_tiDataArea)
Ben Tyner792f32f2020-06-02 08:50:47 -050022 {
Ben Tynere4f5dbe2020-10-19 07:19:33 -050023 if (0xa1 == i_tiDataArea->command)
24 {
25 parsePhypOpalTiInfo(tiAdditionalData, i_tiDataArea);
26 }
27 else
28 {
29 parseHbTiInfo(tiAdditionalData, i_tiDataArea);
30 }
31 parseRawTiInfo(tiAdditionalData, i_tiDataArea);
32 }
Ben Tyner40717722020-09-23 09:43:20 -050033
Ben Tynere4f5dbe2020-10-19 07:19:33 -050034 eventTerminate(tiAdditionalData); // generate PEL
35
36 // Transition host by starting appropriate dbus target
37 auto bus = sdbusplus::bus::new_system();
38 auto method = bus.new_method_call(
39 "org.freedesktop.systemd1", "/org/freedesktop/systemd1",
40 "org.freedesktop.systemd1.Manager", "StartUnit");
41
42 // If TI info is not available we are going to assume PHYP TI for now
43 // (as opposed to HB TI - we have already decided it is not a breakpoint).
44 if ((nullptr == i_tiDataArea) || (0xa1 == i_tiDataArea->command))
45 {
46 trace<level::INFO>("PHYP TI");
Ben Tyner9ae5ca42020-02-28 13:13:50 -060047
Ben Tynerff17f962020-09-23 08:21:19 -050048 if (autoRebootEnabled())
49 {
50 // If autoreboot is enabled we will start diagnostic mode target
51 // which will ultimately mpipl the host.
52 trace<level::INFO>("start obmc-host-diagnostic-mode target");
53 method.append("obmc-host-diagnostic-mode@0.target");
54 }
55 else
56 {
Ben Tynere4f5dbe2020-10-19 07:19:33 -050057 // If autoreboot is disabled we will quiesce the host
Ben Tynerff17f962020-09-23 08:21:19 -050058 trace<level::INFO>("start obmc-host-quiesce target");
59 method.append("obmc-host-quiesce@0.target");
60 }
Ben Tyner792f32f2020-06-02 08:50:47 -050061 }
Ben Tyner40717722020-09-23 09:43:20 -050062 else
63 {
Ben Tynere4f5dbe2020-10-19 07:19:33 -050064 // For now we are just going to just quiesce host on HB TI
65 trace<level::INFO>("HB TI");
66 trace<level::INFO>("start obmc-host-quiesce target");
67 method.append("obmc-host-quiesce@0.target");
Ben Tyner40717722020-09-23 09:43:20 -050068 }
Ben Tyner792f32f2020-06-02 08:50:47 -050069
Ben Tynere4f5dbe2020-10-19 07:19:33 -050070 method.append("replace"); // mode = replace conflicting queued jobs
71 bus.call_noreply(method); // start the service
72
Ben Tyner792f32f2020-06-02 08:50:47 -050073 return rc;
Ben Tyner9ae5ca42020-02-28 13:13:50 -060074}
75
Ben Tyner40717722020-09-23 09:43:20 -050076/** @brief Parse the TI info data area into map as raw 32-bit fields */
77void parseRawTiInfo(std::map<std::string, std::string>& i_map,
78 TiDataArea* i_buffer)
79{
80
81 uint32_t* tiDataArea = (uint32_t*)i_buffer;
82 std::stringstream ss;
83
84 ss << std::hex << std::setfill('0');
85 ss << "raw:";
86 while (tiDataArea <= (uint32_t*)((char*)i_buffer + sizeof(TiDataArea)))
87 {
88 ss << std::setw(8) << std::endl << be32toh(*tiDataArea);
89 tiDataArea++;
90 }
91
92 std::string key, value;
93 char delim = ':';
94
95 while (std::getline(ss, key, delim))
96 {
97 std::getline(ss, value, delim);
98 i_map[key] = value;
99 }
100}
101
102/** @brief Parse the TI info data area into map as PHYP/OPAL data */
103void parsePhypOpalTiInfo(std::map<std::string, std::string>& i_map,
104 TiDataArea* i_tiDataArea)
105{
106 std::stringstream ss;
107
108 ss << std::hex << std::showbase;
109 ss << "0x00 TI Area Valid:" << (int)i_tiDataArea->tiAreaValid << ":";
110 ss << "0x01 Command:" << (int)i_tiDataArea->command << ":";
111 ss << "0x02 Num. Data Bytes:" << be16toh(i_tiDataArea->numDataBytes) << ":";
112 ss << "0x04 Reserved:" << (int)i_tiDataArea->reserved1 << ":";
113 ss << "0x06 HWDump Type:" << be16toh(i_tiDataArea->hardwareDumpType) << ":";
114 ss << "0x08 SRC Format:" << (int)i_tiDataArea->srcFormat << ":";
115 ss << "0x09 SRC Flags:" << (int)i_tiDataArea->srcFlags << ":";
116 ss << "0x0a Num. ASCII Words:" << (int)i_tiDataArea->numAsciiWords << ":";
117 ss << "0x0b Num. Hex Words:" << (int)i_tiDataArea->numHexWords << ":";
118 ss << "0x0e Length of SRC:" << be16toh(i_tiDataArea->lenSrc) << ":";
119 ss << "0x10 SRC Word 12:" << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
120 ss << "0x14 SRC Word 13:" << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
121 ss << "0x18 SRC Word 14:" << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
122 ss << "0x1c SRC Word 15:" << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
123 ss << "0x20 SRC Word 16:" << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
124 ss << "0x24 SRC Word 17:" << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
125 ss << "0x28 SRC Word 18:" << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
126 ss << "0x2c SRC Word 19:" << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
127 ss << "0x30 ASCII Data:" << be32toh(i_tiDataArea->asciiData0) << ":";
128 ss << "0x34 ASCII Data:" << be32toh(i_tiDataArea->asciiData1) << ":";
129 ss << "0x38 ASCII Data:" << be32toh(i_tiDataArea->asciiData2) << ":";
130 ss << "0x3c ASCII Data:" << be32toh(i_tiDataArea->asciiData3) << ":";
131 ss << "0x40 ASCII Data:" << be32toh(i_tiDataArea->asciiData4) << ":";
132 ss << "0x44 ASCII Data:" << be32toh(i_tiDataArea->asciiData5) << ":";
133 ss << "0x48 ASCII Data:" << be32toh(i_tiDataArea->asciiData6) << ":";
134 ss << "0x4c ASCII Data:" << be32toh(i_tiDataArea->asciiData7) << ":";
135 ss << "0x50 Location:" << (int)i_tiDataArea->location << ":";
136 ss << "0x51 Code Sections:" << (int)i_tiDataArea->codeSection << ":";
137 ss << "0x52 Additional Size:" << (int)i_tiDataArea->additionalSize << ":";
138 ss << "0x53 Additional Data:" << (int)i_tiDataArea->andData;
139
140 std::string key, value;
141 char delim = ':';
142
143 while (std::getline(ss, key, delim))
144 {
145 std::getline(ss, value, delim);
146 i_map[key] = value;
147 }
148}
149
150/** @brief Parse the TI info data area into map as hostboot data */
151void parseHbTiInfo(std::map<std::string, std::string>& i_map,
152 TiDataArea* i_tiDataArea)
153{
154 std::stringstream ss;
155
156 ss << std::hex << std::showbase;
157 ss << "0x00 TI Area Valid:" << (int)i_tiDataArea->tiAreaValid << ":";
158 ss << "0x04 Reserved:" << (int)i_tiDataArea->reserved1 << ":";
159 ss << "0x05 HB_Term. Type:" << (int)i_tiDataArea->hbTerminateType << ":";
160 ss << "0x0c HB Dump Flag:" << (int)i_tiDataArea->hbDumpFlag << ":";
161 ss << "0x0d Source:" << (int)i_tiDataArea->source << ":";
162 ss << "0x10 HB Word 0:" << be32toh(i_tiDataArea->srcWord12HbWord0) << ":";
163 ss << "0x14 HB Word 2:" << be32toh(i_tiDataArea->srcWord13HbWord2) << ":";
164 ss << "0x18 HB Word 3:" << be32toh(i_tiDataArea->srcWord14HbWord3) << ":";
165 ss << "0x1c HB Word 4:" << be32toh(i_tiDataArea->srcWord15HbWord4) << ":";
166 ss << "0x20 HB Word 5:" << be32toh(i_tiDataArea->srcWord16HbWord5) << ":";
167 ss << "0x24 HB Word 6:" << be32toh(i_tiDataArea->srcWord17HbWord6) << ":";
168 ss << "0x28 HB Word 7:" << be32toh(i_tiDataArea->srcWord18HbWord7) << ":";
169 ss << "0x2c HB Word 8:" << be32toh(i_tiDataArea->srcWord19HbWord8) << ":";
170 ss << "0x30 error_data:" << be32toh(i_tiDataArea->asciiData0) << ":";
171 ss << "0x34 EID:" << be32toh(i_tiDataArea->asciiData1);
172
173 std::string key, value;
174 char delim = ':';
175
176 while (std::getline(ss, key, delim))
177 {
178 std::getline(ss, value, delim);
179 i_map[key] = value;
180 }
181}
182
183/** @brief Read state of autoreboot propertyi via dbus */
Ben Tynerff17f962020-09-23 08:21:19 -0500184bool autoRebootEnabled()
185{
186 // Use dbus get-property interface to read the autoreboot property
187 auto bus = sdbusplus::bus::new_system();
188 auto method =
189 bus.new_method_call("xyz.openbmc_project.Settings",
190 "/xyz/openbmc_project/control/host0/auto_reboot",
191 "org.freedesktop.DBus.Properties", "Get");
Ben Tyner40717722020-09-23 09:43:20 -0500192
Ben Tynerff17f962020-09-23 08:21:19 -0500193 method.append("xyz.openbmc_project.Control.Boot.RebootPolicy",
194 "AutoReboot");
Ben Tyner40717722020-09-23 09:43:20 -0500195
Ben Tynerff17f962020-09-23 08:21:19 -0500196 try
197 {
198 auto reply = bus.call(method);
Ben Tyner40717722020-09-23 09:43:20 -0500199
Ben Tynerff17f962020-09-23 08:21:19 -0500200 std::variant<bool> result;
201 reply.read(result);
202 auto autoReboot = std::get<bool>(result);
Ben Tyner40717722020-09-23 09:43:20 -0500203
Ben Tynerff17f962020-09-23 08:21:19 -0500204 if (autoReboot)
205 {
206 trace<level::INFO>("Auto reboot enabled");
207 return true;
208 }
209 else
210 {
211 trace<level::INFO>("Auto reboot disabled.");
212 return false;
213 }
214 }
215 catch (const sdbusplus::exception::SdBusError& ec)
216 {
Ben Tynerff17f962020-09-23 08:21:19 -0500217 std::string traceMessage =
218 "Error in AutoReboot Get: " + std::string(ec.what());
219 trace<level::INFO>(traceMessage.c_str());
220 return false; // assume autoreboot disabled
221 }
222}
Ben Tyner40717722020-09-23 09:43:20 -0500223
Ben Tyner9ae5ca42020-02-28 13:13:50 -0600224} // namespace attn