blob: 45d06304755d54bea93e80aa2c27df3a31dee4c0 [file] [log] [blame]
Vernon Mauerya3702c12019-05-22 13:20:59 -07001/*
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
Richard Marian Thomaiyar147daec2019-06-15 07:43:48 +053017#include <boost/container/flat_map.hpp>
Vernon Mauerya3702c12019-05-22 13:20:59 -070018#include <ipmid/api.hpp>
19#include <manufacturingcommands.hpp>
20#include <oemcommands.hpp>
21
22namespace ipmi
23{
24
25Manufacturing mtm;
26
27static auto revertTimeOut =
28 std::chrono::duration_cast<std::chrono::microseconds>(
29 std::chrono::seconds(60)); // 1 minute timeout
30
Vernon Mauerya3702c12019-05-22 13:20:59 -070031static constexpr const char* callbackMgrService =
32 "xyz.openbmc_project.CallbackManager";
33static constexpr const char* callbackMgrIntf =
34 "xyz.openbmc_project.CallbackManager";
35static constexpr const char* callbackMgrObjPath =
36 "/xyz/openbmc_project/CallbackManager";
37static constexpr const char* retriggerLedUpdate = "RetriggerLEDUpdate";
38
39const static constexpr char* systemDService = "org.freedesktop.systemd1";
40const static constexpr char* systemDObjPath = "/org/freedesktop/systemd1";
41const static constexpr char* systemDMgrIntf =
42 "org.freedesktop.systemd1.Manager";
43const static constexpr char* pidControlService = "phosphor-pid-control.service";
44
Richard Marian Thomaiyar666dd012019-08-02 20:55:37 +053045static inline Cc resetMtmTimer(boost::asio::yield_context yield)
46{
47 auto sdbusp = getSdBus();
48 boost::system::error_code ec;
49 sdbusp->yield_method_call<>(yield, ec, specialModeService,
50 specialModeObjPath, specialModeIntf,
51 "ResetTimer");
52 if (ec)
53 {
54 phosphor::logging::log<phosphor::logging::level::ERR>(
55 "Failed to reset the manufacturing mode timer");
56 return ccUnspecifiedError;
57 }
58 return ccSuccess;
59}
60
Jason M. Bills38d2b5a2019-06-03 16:26:11 -070061int getGpioPathForSmSignal(const SmSignalGet signal, std::string& path)
Vernon Mauerya3702c12019-05-22 13:20:59 -070062{
Jason M. Bills38d2b5a2019-06-03 16:26:11 -070063 switch (signal)
64 {
65 case SmSignalGet::smPowerButton:
66 path = "/xyz/openbmc_project/chassis/buttons/power";
67 break;
68 case SmSignalGet::smResetButton:
69 path = "/xyz/openbmc_project/chassis/buttons/reset";
70 break;
71 case SmSignalGet::smNMIButton:
72 path = "/xyz/openbmc_project/chassis/buttons/nmi";
73 break;
Richard Marian Thomaiyar8e5e2b02019-08-01 07:50:55 +053074 case SmSignalGet::smIdentifyButton:
75 path = "/xyz/openbmc_project/chassis/buttons/id";
76 break;
Jason M. Bills38d2b5a2019-06-03 16:26:11 -070077 default:
78 return -1;
79 break;
80 }
81 return 0;
Vernon Mauerya3702c12019-05-22 13:20:59 -070082}
83
84ipmi_ret_t ledStoreAndSet(SmSignalSet signal, std::string setState)
85{
86 LedProperty* ledProp = mtm.findLedProperty(signal);
87 if (ledProp == nullptr)
88 {
89 return IPMI_CC_INVALID_FIELD_REQUEST;
90 }
91
92 std::string ledName = ledProp->getName();
93 std::string ledService = ledServicePrefix + ledName;
94 std::string ledPath = ledPathPrefix + ledName;
95 ipmi::Value presentState;
96
97 if (false == ledProp->getLock())
98 {
99 if (mtm.getProperty(ledService.c_str(), ledPath.c_str(), ledIntf,
100 "State", &presentState) != 0)
101 {
102 return IPMI_CC_UNSPECIFIED_ERROR;
103 }
104 ledProp->setPrevState(std::get<std::string>(presentState));
105 ledProp->setLock(true);
106 if (signal == SmSignalSet::smPowerFaultLed ||
107 signal == SmSignalSet::smSystemReadyLed)
108 {
109 mtm.revertLedCallback = true;
110 }
111 }
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700112 if (mtm.setProperty(ledService, ledPath, ledIntf, "State",
Vernon Mauerya3702c12019-05-22 13:20:59 -0700113 ledStateStr + setState) != 0)
114 {
115 return IPMI_CC_UNSPECIFIED_ERROR;
116 }
117 return IPMI_CC_OK;
118}
119
120ipmi_ret_t ledRevert(SmSignalSet signal)
121{
122 LedProperty* ledProp = mtm.findLedProperty(signal);
123 if (ledProp == nullptr)
124 {
125 return IPMI_CC_INVALID_FIELD_REQUEST;
126 }
127 if (true == ledProp->getLock())
128 {
129 ledProp->setLock(false);
130 if (signal == SmSignalSet::smPowerFaultLed ||
131 signal == SmSignalSet::smSystemReadyLed)
132 {
133 try
134 {
135 ipmi::method_no_args::callDbusMethod(
136 *getSdBus(), callbackMgrService, callbackMgrObjPath,
137 callbackMgrIntf, retriggerLedUpdate);
138 }
139 catch (sdbusplus::exception_t& e)
140 {
141 return IPMI_CC_UNSPECIFIED_ERROR;
142 }
143 mtm.revertLedCallback = false;
144 }
145 else
146 {
147 std::string ledName = ledProp->getName();
148 std::string ledService = ledServicePrefix + ledName;
149 std::string ledPath = ledPathPrefix + ledName;
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700150 if (mtm.setProperty(ledService, ledPath, ledIntf, "State",
151 ledProp->getPrevState()) != 0)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700152 {
153 return IPMI_CC_UNSPECIFIED_ERROR;
154 }
155 }
156 }
157 return IPMI_CC_OK;
158}
159
160void Manufacturing::initData()
161{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700162 ledPropertyList.push_back(
163 LedProperty(SmSignalSet::smPowerFaultLed, "status_amber"));
164 ledPropertyList.push_back(
165 LedProperty(SmSignalSet::smSystemReadyLed, "status_green"));
166 ledPropertyList.push_back(
167 LedProperty(SmSignalSet::smIdentifyLed, "identify"));
168}
169
170void Manufacturing::revertTimerHandler()
171{
Vernon Mauerya3702c12019-05-22 13:20:59 -0700172 if (revertFanPWM)
173 {
174 revertFanPWM = false;
175 disablePidControlService(false);
176 }
177
178 for (const auto& ledProperty : ledPropertyList)
179 {
180 const std::string& ledName = ledProperty.getName();
181 ledRevert(ledProperty.getSignal());
182 }
183}
184
185Manufacturing::Manufacturing() :
186 revertTimer([&](void) { revertTimerHandler(); })
187{
188 initData();
189}
190
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700191int8_t Manufacturing::getProperty(const std::string& service,
192 const std::string& path,
193 const std::string& interface,
194 const std::string& propertyName,
195 ipmi::Value* reply)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700196{
197 try
198 {
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700199 *reply = ipmi::getDbusProperty(*getSdBus(), service, path, interface,
200 propertyName);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700201 }
202 catch (const sdbusplus::exception::SdBusError& e)
203 {
204 phosphor::logging::log<phosphor::logging::level::INFO>(
205 "ERROR: getProperty");
206 return -1;
207 }
208
209 return 0;
210}
211
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700212int8_t Manufacturing::setProperty(const std::string& service,
213 const std::string& path,
214 const std::string& interface,
215 const std::string& propertyName,
216 ipmi::Value value)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700217{
218 try
219 {
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700220 ipmi::setDbusProperty(*getSdBus(), service, path, interface,
Vernon Mauerya3702c12019-05-22 13:20:59 -0700221 propertyName, value);
222 }
223 catch (const sdbusplus::exception::SdBusError& e)
224 {
225 phosphor::logging::log<phosphor::logging::level::INFO>(
226 "ERROR: setProperty");
227 return -1;
228 }
229
230 return 0;
231}
232
233int8_t Manufacturing::disablePidControlService(const bool disable)
234{
235 try
236 {
237 auto dbus = getSdBus();
238 auto method = dbus->new_method_call(systemDService, systemDObjPath,
239 systemDMgrIntf,
240 disable ? "StopUnit" : "StartUnit");
241 method.append(pidControlService, "replace");
242 auto reply = dbus->call(method);
243 }
244 catch (const sdbusplus::exception::SdBusError& e)
245 {
246 phosphor::logging::log<phosphor::logging::level::INFO>(
247 "ERROR: phosphor-pid-control service start or stop failed");
248 return -1;
249 }
250 return 0;
251}
252
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700253ipmi::RspType<uint8_t, // Signal value
254 std::optional<uint16_t> // Fan tach value
255 >
Richard Marian Thomaiyar147daec2019-06-15 07:43:48 +0530256 appMTMGetSignal(boost::asio::yield_context yield, uint8_t signalTypeByte,
257 uint8_t instance, uint8_t actionByte)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700258{
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700259 if (mtm.getAccessLvl() < MtmLvl::mtmAvailable)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700260 {
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700261 return ipmi::responseInvalidCommand();
262 }
Vernon Mauerya3702c12019-05-22 13:20:59 -0700263
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700264 SmSignalGet signalType = static_cast<SmSignalGet>(signalTypeByte);
265 SmActionGet action = static_cast<SmActionGet>(actionByte);
266
267 switch (signalType)
268 {
269 case SmSignalGet::smFanPwmGet:
270 {
271 ipmi::Value reply;
Richard Marian Thomaiyar147daec2019-06-15 07:43:48 +0530272 std::string fullPath = fanPwmPath + std::to_string(instance + 1);
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700273 if (mtm.getProperty(fanService, fullPath, fanIntf, "Value",
274 &reply) < 0)
275 {
276 return ipmi::responseInvalidFieldRequest();
277 }
278 double* doubleVal = std::get_if<double>(&reply);
279 if (doubleVal == nullptr)
280 {
281 return ipmi::responseUnspecifiedError();
282 }
283 uint8_t sensorVal = std::round(*doubleVal);
Richard Marian Thomaiyar4cc10152019-08-02 23:21:45 +0530284 resetMtmTimer(yield);
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700285 return ipmi::responseSuccess(sensorVal, std::nullopt);
286 }
287 break;
288 case SmSignalGet::smFanTachometerGet:
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700289 {
Richard Marian Thomaiyar147daec2019-06-15 07:43:48 +0530290 auto sdbusp = getSdBus();
291 boost::system::error_code ec;
292 using objFlatMap = boost::container::flat_map<
293 std::string, boost::container::flat_map<
294 std::string, std::vector<std::string>>>;
295
296 auto flatMap = sdbusp->yield_method_call<objFlatMap>(
297 yield, ec, "xyz.openbmc_project.ObjectMapper",
298 "/xyz/openbmc_project/object_mapper",
299 "xyz.openbmc_project.ObjectMapper", "GetSubTree",
300 fanTachBasePath, 0, std::array<const char*, 1>{fanIntf});
301 if (ec)
302 {
303 phosphor::logging::log<phosphor::logging::level::ERR>(
304 "Failed to query fan tach sub tree objects");
305 return ipmi::responseUnspecifiedError();
306 }
307 if (instance >= flatMap.size())
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700308 {
309 return ipmi::responseInvalidFieldRequest();
310 }
Richard Marian Thomaiyar147daec2019-06-15 07:43:48 +0530311 auto itr = flatMap.nth(instance);
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700312 ipmi::Value reply;
Richard Marian Thomaiyar147daec2019-06-15 07:43:48 +0530313 if (mtm.getProperty(fanService, itr->first, fanIntf, "Value",
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700314 &reply) < 0)
315 {
316 return ipmi::responseInvalidFieldRequest();
317 }
318
319 double* doubleVal = std::get_if<double>(&reply);
320 if (doubleVal == nullptr)
321 {
322 return ipmi::responseUnspecifiedError();
323 }
324 uint8_t sensorVal = FAN_PRESENT | FAN_SENSOR_PRESENT;
325 std::optional<uint16_t> fanTach = std::round(*doubleVal);
326
Richard Marian Thomaiyar4cc10152019-08-02 23:21:45 +0530327 resetMtmTimer(yield);
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700328 return ipmi::responseSuccess(sensorVal, fanTach);
329 }
330 break;
Richard Marian Thomaiyar8e5e2b02019-08-01 07:50:55 +0530331 case SmSignalGet::smIdentifyButton:
332 {
333 if (action == SmActionGet::revert || action == SmActionGet::ignore)
334 {
335 // ButtonMasked property is not supported for ID button as it is
336 // unnecessary. Hence if requested for revert / ignore, override
337 // it to sample action to make tools happy.
338 action = SmActionGet::sample;
339 }
340 // fall-through
341 }
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700342 case SmSignalGet::smResetButton:
343 case SmSignalGet::smPowerButton:
344 case SmSignalGet::smNMIButton:
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700345 {
346 std::string path;
347 if (getGpioPathForSmSignal(signalType, path) < 0)
348 {
349 return ipmi::responseInvalidFieldRequest();
350 }
351
352 switch (action)
353 {
354 case SmActionGet::sample:
355 phosphor::logging::log<phosphor::logging::level::INFO>(
356 "case SmActionGet::sample");
357 break;
358 case SmActionGet::ignore:
359 {
360 phosphor::logging::log<phosphor::logging::level::INFO>(
361 "case SmActionGet::ignore");
362 if (mtm.setProperty(buttonService, path, buttonIntf,
363 "ButtonMasked", true) < 0)
364 {
365 return ipmi::responseUnspecifiedError();
366 }
367 }
368 break;
369 case SmActionGet::revert:
370 {
371 phosphor::logging::log<phosphor::logging::level::INFO>(
372 "case SmActionGet::revert");
373 if (mtm.setProperty(buttonService, path, buttonIntf,
374 "ButtonMasked", false) < 0)
375 {
376 return ipmi::responseUnspecifiedError();
377 }
378 }
379 break;
380
381 default:
382 return ipmi::responseInvalidFieldRequest();
383 break;
384 }
385
386 ipmi::Value reply;
387 if (mtm.getProperty(buttonService, path, buttonIntf,
388 "ButtonPressed", &reply) < 0)
389 {
390 return ipmi::responseUnspecifiedError();
391 }
392 bool* valPtr = std::get_if<bool>(&reply);
393 if (valPtr == nullptr)
394 {
395 return ipmi::responseUnspecifiedError();
396 }
Richard Marian Thomaiyar4cc10152019-08-02 23:21:45 +0530397 resetMtmTimer(yield);
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700398 uint8_t sensorVal = *valPtr;
399 return ipmi::responseSuccess(sensorVal, std::nullopt);
400 }
401 break;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700402 default:
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700403 return ipmi::responseInvalidFieldRequest();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700404 break;
405 }
Vernon Mauerya3702c12019-05-22 13:20:59 -0700406}
407
Richard Marian Thomaiyar4cc10152019-08-02 23:21:45 +0530408ipmi::RspType<> appMTMSetSignal(boost::asio::yield_context yield,
409 uint8_t signalTypeByte, uint8_t instance,
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000410 uint8_t actionByte,
411 std::optional<uint8_t> pwmSpeed)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700412{
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000413 if (mtm.getAccessLvl() < MtmLvl::mtmAvailable)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700414 {
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000415 return ipmi::responseInvalidCommand();
416 }
417
418 SmSignalSet signalType = static_cast<SmSignalSet>(signalTypeByte);
419 SmActionSet action = static_cast<SmActionSet>(actionByte);
420 Cc retCode = ccSuccess;
421 int8_t ret = 0;
422
423 switch (signalType)
424 {
425 case SmSignalSet::smPowerFaultLed:
426 case SmSignalSet::smSystemReadyLed:
427 case SmSignalSet::smIdentifyLed:
428 switch (action)
429 {
430 case SmActionSet::forceDeasserted:
Vernon Mauerya3702c12019-05-22 13:20:59 -0700431 {
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000432 phosphor::logging::log<phosphor::logging::level::INFO>(
433 "case SmActionSet::forceDeasserted");
Vernon Mauerya3702c12019-05-22 13:20:59 -0700434
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000435 retCode = ledStoreAndSet(signalType, std::string("Off"));
436 if (retCode != ccSuccess)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700437 {
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000438 return ipmi::response(retCode);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700439 }
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000440 mtm.revertTimer.start(revertTimeOut);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700441 }
442 break;
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000443 case SmActionSet::forceAsserted:
Vernon Mauerya3702c12019-05-22 13:20:59 -0700444 {
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000445 phosphor::logging::log<phosphor::logging::level::INFO>(
446 "case SmActionSet::forceAsserted");
Vernon Mauerya3702c12019-05-22 13:20:59 -0700447
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000448 retCode = ledStoreAndSet(signalType, std::string("On"));
449 if (retCode != ccSuccess)
450 {
451 return ipmi::response(retCode);
452 }
453 mtm.revertTimer.start(revertTimeOut);
454 if (SmSignalSet::smPowerFaultLed == signalType)
455 {
456 // Deassert "system ready"
457 retCode = ledStoreAndSet(SmSignalSet::smSystemReadyLed,
458 std::string("Off"));
459 }
460 else if (SmSignalSet::smSystemReadyLed == signalType)
461 {
462 // Deassert "fault led"
463 retCode = ledStoreAndSet(SmSignalSet::smPowerFaultLed,
464 std::string("Off"));
465 }
466 }
467 break;
468 case SmActionSet::revert:
469 {
470 phosphor::logging::log<phosphor::logging::level::INFO>(
471 "case SmActionSet::revert");
472 retCode = ledRevert(signalType);
473 }
474 break;
475 default:
476 {
477 return ipmi::responseInvalidFieldRequest();
478 }
479 }
480 break;
481 case SmSignalSet::smFanPowerSpeed:
482 {
483 if ((action == SmActionSet::forceAsserted) && (!pwmSpeed))
484 {
485 return ipmi::responseReqDataLenInvalid();
486 }
487
488 if ((action == SmActionSet::forceAsserted) && (*pwmSpeed > 100))
489 {
490 return ipmi::responseInvalidFieldRequest();
491 }
492
493 uint8_t pwmValue = 0;
494 switch (action)
495 {
496 case SmActionSet::revert:
497 {
498 if (mtm.revertFanPWM)
499 {
500 ret = mtm.disablePidControlService(false);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700501 if (ret < 0)
502 {
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000503 return ipmi::responseUnspecifiedError();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700504 }
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000505 mtm.revertFanPWM = false;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700506 }
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000507 }
508 break;
509 case SmActionSet::forceAsserted:
510 {
511 pwmValue = *pwmSpeed;
512 } // fall-through
513 case SmActionSet::forceDeasserted:
514 {
515 if (!mtm.revertFanPWM)
Vernon Mauerya3702c12019-05-22 13:20:59 -0700516 {
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000517 ret = mtm.disablePidControlService(true);
518 if (ret < 0)
519 {
520 return ipmi::responseUnspecifiedError();
521 }
522 mtm.revertFanPWM = true;
Vernon Mauerya3702c12019-05-22 13:20:59 -0700523 }
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000524 mtm.revertTimer.start(revertTimeOut);
525 std::string fanPwmInstancePath =
526 fanPwmPath + std::to_string(instance + 1);
527
528 ret =
529 mtm.setProperty(fanService, fanPwmInstancePath, fanIntf,
530 "Value", static_cast<double>(pwmValue));
531 if (ret < 0)
532 {
533 return ipmi::responseUnspecifiedError();
534 }
535 }
536 break;
537 default:
538 {
539 return ipmi::responseInvalidFieldRequest();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700540 }
541 }
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000542 }
543 break;
544 default:
545 {
546 return ipmi::responseInvalidFieldRequest();
Vernon Mauerya3702c12019-05-22 13:20:59 -0700547 }
548 }
Richard Marian Thomaiyar4cc10152019-08-02 23:21:45 +0530549 if (retCode == ccSuccess)
550 {
551 resetMtmTimer(yield);
552 }
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000553 return ipmi::response(retCode);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700554}
555
Richard Marian Thomaiyar666dd012019-08-02 20:55:37 +0530556ipmi::RspType<> mtmKeepAlive(boost::asio::yield_context yield, uint8_t reserved,
557 const std::array<char, 5>& intentionalSignature)
558{
559 // Allow MTM keep alive command only in manfacturing mode.
560 if (mtm.getAccessLvl() != MtmLvl::mtmAvailable)
561 {
562 return ipmi::responseInvalidCommand();
563 }
564 constexpr std::array<char, 5> signatureOk = {'I', 'N', 'T', 'E', 'L'};
565 if (intentionalSignature != signatureOk || reserved != 0)
566 {
567 return ipmi::responseInvalidFieldRequest();
568 }
569 return ipmi::response(resetMtmTimer(yield));
570}
571
Vernon Mauerya3702c12019-05-22 13:20:59 -0700572} // namespace ipmi
573
574void register_mtm_commands() __attribute__((constructor));
575void register_mtm_commands()
576{
Jason M. Bills38d2b5a2019-06-03 16:26:11 -0700577 // <Get SM Signal>
578 ipmi::registerHandler(
579 ipmi::prioOemBase, ipmi::netFnOemOne,
580 static_cast<ipmi::Cmd>(IPMINetFnIntelOemGeneralCmds::GetSmSignal),
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000581 ipmi::Privilege::Admin, ipmi::appMTMGetSignal);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700582
Ayushi Smriti5e3bf552019-07-30 15:32:06 +0000583 ipmi::registerHandler(
584 ipmi::prioOemBase, ipmi::netFnOemOne,
585 static_cast<ipmi::Cmd>(IPMINetFnIntelOemGeneralCmds::SetSmSignal),
586 ipmi::Privilege::Admin, ipmi::appMTMSetSignal);
Vernon Mauerya3702c12019-05-22 13:20:59 -0700587
Richard Marian Thomaiyar666dd012019-08-02 20:55:37 +0530588 ipmi::registerHandler(
589 ipmi::prioOemBase, ipmi::netFnOemOne,
590 static_cast<ipmi::Cmd>(IPMINetfnIntelOEMGeneralCmd::cmdMtmKeepAlive),
591 ipmi::Privilege::Admin, ipmi::mtmKeepAlive);
592
Vernon Mauerya3702c12019-05-22 13:20:59 -0700593 return;
594}