blob: 777ac16bbcec21c443100655928f770b795d720c [file] [log] [blame]
Charles Hsudbd77b92020-10-29 11:20:34 +08001/*
2// Copyright (c) 2018 Intel Corporation
3//
4// Licensed under the Apache License, Version 2.0 (the "License");
5// you may not use this file except in compliance with the License.
6// You may obtain a copy of the License at
7//
8// http://www.apache.org/licenses/LICENSE-2.0
9//
10// Unless required by applicable law or agreed to in writing, software
11// distributed under the License is distributed on an "AS IS" BASIS,
12// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13// See the License for the specific language governing permissions and
14// limitations under the License.
15*/
16
17#pragma once
18#include <sel_logger.hpp>
19#include <sensorutils.hpp>
20
Willy Tuf0243dc2021-08-03 22:49:14 -070021#include <string>
Charles Hsudbd77b92020-10-29 11:20:34 +080022#include <string_view>
23#include <variant>
24
25enum class watchdogEventOffsets : uint8_t
26{
27 noAction = 0x00,
28 hardReset = 0x01,
29 powerDown = 0x02,
30 powerCycle = 0x03,
31};
32
33enum class watchdogTimerUseOffsets : uint8_t
34{
35 reserved = 0x00,
36 BIOSFRB2 = 0x01,
37 BIOSPOST = 0x02,
38 OSLoad = 0x03,
39 SMSOS = 0x04,
40 OEM = 0x05,
41 unspecified = 0x0f,
42};
43
44enum class watchdogInterruptTypeOffsets : uint8_t
45{
46 none = 0x00,
47 SMI = 0x01,
48 NMI = 0x02,
49 messageInterrupt = 0x03,
50 unspecified = 0x0f,
51};
52
53static constexpr const uint8_t wdtNologBit = (1 << 7);
54static constexpr int interruptTypeBits = 4;
55
Willy Tuf0243dc2021-08-03 22:49:14 -070056inline static void sendWatchdogEventLog(
57 std::shared_ptr<sdbusplus::asio::connection> conn,
Patrick Williamsccef2272022-07-22 19:26:54 -050058 sdbusplus::message_t& msg, bool assert,
Willy Tuf0243dc2021-08-03 22:49:14 -070059 std::optional<std::string_view> expireAction = std::nullopt)
Charles Hsudbd77b92020-10-29 11:20:34 +080060{
Willy Tuf0243dc2021-08-03 22:49:14 -070061 // SEL event data is three bytes where 0xFF means unspecified
62 std::vector<uint8_t> eventData(selEvtDataMaxSize, 0xFF);
Charles Hsudbd77b92020-10-29 11:20:34 +080063
Patrick Williamsccef2272022-07-22 19:26:54 -050064 sdbusplus::message_t getWatchdogStatus =
Willy Tuf0243dc2021-08-03 22:49:14 -070065 conn->new_method_call(msg.get_sender(), msg.get_path(),
66 "org.freedesktop.DBus.Properties", "GetAll");
67 getWatchdogStatus.append("xyz.openbmc_project.State.Watchdog");
68 boost::container::flat_map<std::string,
69 std::variant<std::string, uint64_t, bool>>
70 watchdogStatus;
Charles Hsudbd77b92020-10-29 11:20:34 +080071
Willy Tuf0243dc2021-08-03 22:49:14 -070072 try
73 {
Patrick Williamsccef2272022-07-22 19:26:54 -050074 sdbusplus::message_t getWatchdogStatusResp =
Willy Tuf0243dc2021-08-03 22:49:14 -070075 conn->call(getWatchdogStatus);
76 getWatchdogStatusResp.read(watchdogStatus);
77 }
Patrick Williams3f4cd972021-10-06 12:42:50 -050078 catch (const sdbusplus::exception_t&)
Willy Tuf0243dc2021-08-03 22:49:14 -070079 {
80 std::cerr << "error getting watchdog status from " << msg.get_path()
81 << "\n";
82 return;
83 }
Charles Hsudbd77b92020-10-29 11:20:34 +080084
Willy Tuf0243dc2021-08-03 22:49:14 -070085 if (!expireAction)
86 {
Charles Hsudbd77b92020-10-29 11:20:34 +080087 auto getExpireAction = watchdogStatus.find("ExpireAction");
Charles Hsudbd77b92020-10-29 11:20:34 +080088 if (getExpireAction != watchdogStatus.end())
89 {
90 expireAction = std::get<std::string>(getExpireAction->second);
Willy Tuf0243dc2021-08-03 22:49:14 -070091 expireAction->remove_prefix(std::min(
92 expireAction->find_last_of(".") + 1, expireAction->size()));
Charles Hsudbd77b92020-10-29 11:20:34 +080093 }
Willy Tuf0243dc2021-08-03 22:49:14 -070094 }
Charles Hsudbd77b92020-10-29 11:20:34 +080095
Willy Tuf0243dc2021-08-03 22:49:14 -070096 if (*expireAction == "HardReset")
97 {
98 eventData[0] = static_cast<uint8_t>(watchdogEventOffsets::hardReset);
99 }
100 else if (*expireAction == "PowerOff")
101 {
102 eventData[0] = static_cast<uint8_t>(watchdogEventOffsets::powerDown);
103 }
104 else if (*expireAction == "PowerCycle")
105 {
106 eventData[0] = static_cast<uint8_t>(watchdogEventOffsets::powerCycle);
107 }
108 else if (*expireAction == "None")
109 {
110 eventData[0] = static_cast<uint8_t>(watchdogEventOffsets::noAction);
111 }
Charles Hsudbd77b92020-10-29 11:20:34 +0800112
Willy Tuf0243dc2021-08-03 22:49:14 -0700113 auto getPreTimeoutInterrupt = watchdogStatus.find("PreTimeoutInterrupt");
114 std::string_view preTimeoutInterrupt;
115 if (getPreTimeoutInterrupt != watchdogStatus.end())
116 {
117 preTimeoutInterrupt =
118 std::get<std::string>(getPreTimeoutInterrupt->second);
119 preTimeoutInterrupt.remove_prefix(
120 std::min(preTimeoutInterrupt.find_last_of(".") + 1,
121 preTimeoutInterrupt.size()));
122 }
123 if (preTimeoutInterrupt == "None")
124 {
125 eventData[1] &=
126 (static_cast<uint8_t>(watchdogInterruptTypeOffsets::none)
127 << interruptTypeBits);
128 }
129 else if (preTimeoutInterrupt == "SMI")
130 {
131 eventData[1] &= (static_cast<uint8_t>(watchdogInterruptTypeOffsets::SMI)
132 << interruptTypeBits);
133 }
134 else if (preTimeoutInterrupt == "NMI")
135 {
136 eventData[1] &= (static_cast<uint8_t>(watchdogInterruptTypeOffsets::NMI)
137 << interruptTypeBits);
138 }
139 else if (preTimeoutInterrupt == "MI")
140 {
141 eventData[1] &= (static_cast<uint8_t>(
142 watchdogInterruptTypeOffsets::messageInterrupt)
143 << interruptTypeBits);
144 }
Charles Hsudbd77b92020-10-29 11:20:34 +0800145
Willy Tuf0243dc2021-08-03 22:49:14 -0700146 auto getCurrentTimerUse = watchdogStatus.find("CurrentTimerUse");
147 std::string_view currentTimerUse;
148 if (getCurrentTimerUse != watchdogStatus.end())
149 {
150 currentTimerUse = std::get<std::string>(getCurrentTimerUse->second);
151 currentTimerUse.remove_prefix(std::min(
152 currentTimerUse.find_last_of(".") + 1, currentTimerUse.size()));
153 }
154 if (currentTimerUse == "BIOSFRB2")
155 {
156 eventData[1] |= static_cast<uint8_t>(watchdogTimerUseOffsets::BIOSFRB2);
157 }
158 else if (currentTimerUse == "BIOSPOST")
159 {
160 eventData[1] |= static_cast<uint8_t>(watchdogTimerUseOffsets::BIOSPOST);
161 }
162 else if (currentTimerUse == "OSLoad")
163 {
164 eventData[1] |= static_cast<uint8_t>(watchdogTimerUseOffsets::OSLoad);
165 }
166 else if (currentTimerUse == "SMSOS")
167 {
168 eventData[1] |= static_cast<uint8_t>(watchdogTimerUseOffsets::SMSOS);
169 }
170 else if (currentTimerUse == "OEM")
171 {
172 eventData[1] |= static_cast<uint8_t>(watchdogTimerUseOffsets::OEM);
173 }
174 else
175 {
176 eventData[1] |=
177 static_cast<uint8_t>(watchdogTimerUseOffsets::unspecified);
178 }
Charles Hsudbd77b92020-10-29 11:20:34 +0800179
Willy Tuf0243dc2021-08-03 22:49:14 -0700180 auto getWatchdogInterval = watchdogStatus.find("Interval");
181 uint64_t watchdogInterval = 0;
182 if (getWatchdogInterval != watchdogStatus.end())
183 {
184 watchdogInterval = std::get<uint64_t>(getWatchdogInterval->second);
185 }
Charles Hsudbd77b92020-10-29 11:20:34 +0800186
Willy Tuf0243dc2021-08-03 22:49:14 -0700187 // get watchdog status properties
188 static bool wdt_nolog;
Patrick Williamsccef2272022-07-22 19:26:54 -0500189 sdbusplus::bus_t bus = sdbusplus::bus::new_default();
Willy Tuf0243dc2021-08-03 22:49:14 -0700190 uint8_t netFn = 0x06;
191 uint8_t lun = 0x00;
192 uint8_t cmd = 0x25;
193 std::vector<uint8_t> commandData;
194 std::map<std::string, std::variant<int>> options;
Charles Hsudbd77b92020-10-29 11:20:34 +0800195
Willy Tuf0243dc2021-08-03 22:49:14 -0700196 auto ipmiCall = bus.new_method_call(
197 "xyz.openbmc_project.Ipmi.Host", "/xyz/openbmc_project/Ipmi",
198 "xyz.openbmc_project.Ipmi.Server", "execute");
199 ipmiCall.append(netFn, lun, cmd, commandData, options);
200 std::tuple<uint8_t, uint8_t, uint8_t, uint8_t, std::vector<uint8_t>> rsp;
201 auto ipmiReply = bus.call(ipmiCall);
202 ipmiReply.read(rsp);
203 auto& [rnetFn, rlun, rcmd, cc, responseData] = rsp;
Charles Hsudbd77b92020-10-29 11:20:34 +0800204
Willy Tuf0243dc2021-08-03 22:49:14 -0700205 std::string direction;
206 std::string eventMessageArgs;
207 if (assert)
208 {
209 direction = " enable ";
210 eventMessageArgs = "Enabled";
211 wdt_nolog = responseData[0] & wdtNologBit;
212 }
213 else
214 {
215 direction = " disable ";
216 eventMessageArgs = "Disabled";
217 }
Charles Hsudbd77b92020-10-29 11:20:34 +0800218
Willy Tuf0243dc2021-08-03 22:49:14 -0700219 // Set Watchdog Timer byte1[7]-1b=don't log
220 if (!wdt_nolog)
221 {
222 // Construct a human-readable message of this event for the log
223 std::string journalMsg(
224 std::string(currentTimerUse) + std::string(direction) +
225 "watchdog countdown " + std::to_string(watchdogInterval / 1000) +
226 " seconds " + std::string(*expireAction) + " action");
Charles Hsudbd77b92020-10-29 11:20:34 +0800227
Willy Tuf0243dc2021-08-03 22:49:14 -0700228 std::string redfishMessageID = "OpenBMC.0.1.IPMIWatchdog";
229
Konstantin Aladyshev6f5342d2023-04-19 09:23:11 +0000230 selAddSystemRecord(
231 conn, journalMsg, std::string(msg.get_path()), eventData, assert,
232 selBMCGenID, "REDFISH_MESSAGE_ID=%s", redfishMessageID.c_str(),
233 "REDFISH_MESSAGE_ARGS=%s", eventMessageArgs.c_str(), NULL);
Willy Tuf0243dc2021-08-03 22:49:14 -0700234 }
235}
236
Patrick Williamsccef2272022-07-22 19:26:54 -0500237inline static sdbusplus::bus::match_t
Willy Tuf0243dc2021-08-03 22:49:14 -0700238 startWatchdogEventMonitor(std::shared_ptr<sdbusplus::asio::connection> conn)
239{
Patrick Williamsccef2272022-07-22 19:26:54 -0500240 auto watchdogEventMatcherCallback = [conn](sdbusplus::message_t& msg) {
241 std::string expiredAction;
242 msg.read(expiredAction);
Willy Tuf0243dc2021-08-03 22:49:14 -0700243
Patrick Williamsccef2272022-07-22 19:26:54 -0500244 std::string_view action = expiredAction;
245 action.remove_prefix(
246 std::min(action.find_last_of(".") + 1, action.size()));
Willy Tuf0243dc2021-08-03 22:49:14 -0700247
Patrick Williamsccef2272022-07-22 19:26:54 -0500248 sendWatchdogEventLog(conn, msg, true, action);
249 };
Willy Tuf0243dc2021-08-03 22:49:14 -0700250
Patrick Williamsccef2272022-07-22 19:26:54 -0500251 sdbusplus::bus::match_t watchdogEventMatcher(
252 static_cast<sdbusplus::bus_t&>(*conn),
Willy Tuf0243dc2021-08-03 22:49:14 -0700253 "type='signal',interface='xyz.openbmc_project.Watchdog',"
254 "member='Timeout'",
Charles Hsudbd77b92020-10-29 11:20:34 +0800255 std::move(watchdogEventMatcherCallback));
Willy Tuf0243dc2021-08-03 22:49:14 -0700256
Charles Hsudbd77b92020-10-29 11:20:34 +0800257 return watchdogEventMatcher;
258}