1a3702c1fSVernon Mauery /* 2a3702c1fSVernon Mauery // Copyright (c) 2018 Intel Corporation 3a3702c1fSVernon Mauery // 4a3702c1fSVernon Mauery // Licensed under the Apache License, Version 2.0 (the "License"); 5a3702c1fSVernon Mauery // you may not use this file except in compliance with the License. 6a3702c1fSVernon Mauery // You may obtain a copy of the License at 7a3702c1fSVernon Mauery // 8a3702c1fSVernon Mauery // http://www.apache.org/licenses/LICENSE-2.0 9a3702c1fSVernon Mauery // 10a3702c1fSVernon Mauery // Unless required by applicable law or agreed to in writing, software 11a3702c1fSVernon Mauery // distributed under the License is distributed on an "AS IS" BASIS, 12a3702c1fSVernon Mauery // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a3702c1fSVernon Mauery // See the License for the specific language governing permissions and 14a3702c1fSVernon Mauery // limitations under the License. 15a3702c1fSVernon Mauery */ 16a3702c1fSVernon Mauery 17a3702c1fSVernon Mauery #include <ipmid/api.hpp> 18a3702c1fSVernon Mauery #include <manufacturingcommands.hpp> 19a3702c1fSVernon Mauery #include <oemcommands.hpp> 20a3702c1fSVernon Mauery 21a3702c1fSVernon Mauery namespace ipmi 22a3702c1fSVernon Mauery { 23a3702c1fSVernon Mauery 24a3702c1fSVernon Mauery Manufacturing mtm; 25a3702c1fSVernon Mauery 26a3702c1fSVernon Mauery static auto revertTimeOut = 27a3702c1fSVernon Mauery std::chrono::duration_cast<std::chrono::microseconds>( 28a3702c1fSVernon Mauery std::chrono::seconds(60)); // 1 minute timeout 29a3702c1fSVernon Mauery 30a3702c1fSVernon Mauery static constexpr const char* callbackMgrService = 31a3702c1fSVernon Mauery "xyz.openbmc_project.CallbackManager"; 32a3702c1fSVernon Mauery static constexpr const char* callbackMgrIntf = 33a3702c1fSVernon Mauery "xyz.openbmc_project.CallbackManager"; 34a3702c1fSVernon Mauery static constexpr const char* callbackMgrObjPath = 35a3702c1fSVernon Mauery "/xyz/openbmc_project/CallbackManager"; 36a3702c1fSVernon Mauery static constexpr const char* retriggerLedUpdate = "RetriggerLEDUpdate"; 37a3702c1fSVernon Mauery 38a3702c1fSVernon Mauery const static constexpr char* systemDService = "org.freedesktop.systemd1"; 39a3702c1fSVernon Mauery const static constexpr char* systemDObjPath = "/org/freedesktop/systemd1"; 40a3702c1fSVernon Mauery const static constexpr char* systemDMgrIntf = 41a3702c1fSVernon Mauery "org.freedesktop.systemd1.Manager"; 42a3702c1fSVernon Mauery const static constexpr char* pidControlService = "phosphor-pid-control.service"; 43a3702c1fSVernon Mauery 4438d2b5a6SJason M. Bills int getGpioPathForSmSignal(const SmSignalGet signal, std::string& path) 45a3702c1fSVernon Mauery { 4638d2b5a6SJason M. Bills switch (signal) 4738d2b5a6SJason M. Bills { 4838d2b5a6SJason M. Bills case SmSignalGet::smPowerButton: 4938d2b5a6SJason M. Bills path = "/xyz/openbmc_project/chassis/buttons/power"; 5038d2b5a6SJason M. Bills break; 5138d2b5a6SJason M. Bills case SmSignalGet::smResetButton: 5238d2b5a6SJason M. Bills path = "/xyz/openbmc_project/chassis/buttons/reset"; 5338d2b5a6SJason M. Bills break; 5438d2b5a6SJason M. Bills case SmSignalGet::smNMIButton: 5538d2b5a6SJason M. Bills path = "/xyz/openbmc_project/chassis/buttons/nmi"; 5638d2b5a6SJason M. Bills break; 5738d2b5a6SJason M. Bills default: 5838d2b5a6SJason M. Bills return -1; 5938d2b5a6SJason M. Bills break; 6038d2b5a6SJason M. Bills } 6138d2b5a6SJason M. Bills return 0; 62a3702c1fSVernon Mauery } 63a3702c1fSVernon Mauery 64a3702c1fSVernon Mauery ipmi_ret_t ledStoreAndSet(SmSignalSet signal, std::string setState) 65a3702c1fSVernon Mauery { 66a3702c1fSVernon Mauery LedProperty* ledProp = mtm.findLedProperty(signal); 67a3702c1fSVernon Mauery if (ledProp == nullptr) 68a3702c1fSVernon Mauery { 69a3702c1fSVernon Mauery return IPMI_CC_INVALID_FIELD_REQUEST; 70a3702c1fSVernon Mauery } 71a3702c1fSVernon Mauery 72a3702c1fSVernon Mauery std::string ledName = ledProp->getName(); 73a3702c1fSVernon Mauery std::string ledService = ledServicePrefix + ledName; 74a3702c1fSVernon Mauery std::string ledPath = ledPathPrefix + ledName; 75a3702c1fSVernon Mauery ipmi::Value presentState; 76a3702c1fSVernon Mauery 77a3702c1fSVernon Mauery if (false == ledProp->getLock()) 78a3702c1fSVernon Mauery { 79a3702c1fSVernon Mauery if (mtm.getProperty(ledService.c_str(), ledPath.c_str(), ledIntf, 80a3702c1fSVernon Mauery "State", &presentState) != 0) 81a3702c1fSVernon Mauery { 82a3702c1fSVernon Mauery return IPMI_CC_UNSPECIFIED_ERROR; 83a3702c1fSVernon Mauery } 84a3702c1fSVernon Mauery ledProp->setPrevState(std::get<std::string>(presentState)); 85a3702c1fSVernon Mauery ledProp->setLock(true); 86a3702c1fSVernon Mauery if (signal == SmSignalSet::smPowerFaultLed || 87a3702c1fSVernon Mauery signal == SmSignalSet::smSystemReadyLed) 88a3702c1fSVernon Mauery { 89a3702c1fSVernon Mauery mtm.revertLedCallback = true; 90a3702c1fSVernon Mauery } 91a3702c1fSVernon Mauery } 9238d2b5a6SJason M. Bills if (mtm.setProperty(ledService, ledPath, ledIntf, "State", 93a3702c1fSVernon Mauery ledStateStr + setState) != 0) 94a3702c1fSVernon Mauery { 95a3702c1fSVernon Mauery return IPMI_CC_UNSPECIFIED_ERROR; 96a3702c1fSVernon Mauery } 97a3702c1fSVernon Mauery return IPMI_CC_OK; 98a3702c1fSVernon Mauery } 99a3702c1fSVernon Mauery 100a3702c1fSVernon Mauery ipmi_ret_t ledRevert(SmSignalSet signal) 101a3702c1fSVernon Mauery { 102a3702c1fSVernon Mauery LedProperty* ledProp = mtm.findLedProperty(signal); 103a3702c1fSVernon Mauery if (ledProp == nullptr) 104a3702c1fSVernon Mauery { 105a3702c1fSVernon Mauery return IPMI_CC_INVALID_FIELD_REQUEST; 106a3702c1fSVernon Mauery } 107a3702c1fSVernon Mauery if (true == ledProp->getLock()) 108a3702c1fSVernon Mauery { 109a3702c1fSVernon Mauery ledProp->setLock(false); 110a3702c1fSVernon Mauery if (signal == SmSignalSet::smPowerFaultLed || 111a3702c1fSVernon Mauery signal == SmSignalSet::smSystemReadyLed) 112a3702c1fSVernon Mauery { 113a3702c1fSVernon Mauery try 114a3702c1fSVernon Mauery { 115a3702c1fSVernon Mauery ipmi::method_no_args::callDbusMethod( 116a3702c1fSVernon Mauery *getSdBus(), callbackMgrService, callbackMgrObjPath, 117a3702c1fSVernon Mauery callbackMgrIntf, retriggerLedUpdate); 118a3702c1fSVernon Mauery } 119a3702c1fSVernon Mauery catch (sdbusplus::exception_t& e) 120a3702c1fSVernon Mauery { 121a3702c1fSVernon Mauery return IPMI_CC_UNSPECIFIED_ERROR; 122a3702c1fSVernon Mauery } 123a3702c1fSVernon Mauery mtm.revertLedCallback = false; 124a3702c1fSVernon Mauery } 125a3702c1fSVernon Mauery else 126a3702c1fSVernon Mauery { 127a3702c1fSVernon Mauery std::string ledName = ledProp->getName(); 128a3702c1fSVernon Mauery std::string ledService = ledServicePrefix + ledName; 129a3702c1fSVernon Mauery std::string ledPath = ledPathPrefix + ledName; 13038d2b5a6SJason M. Bills if (mtm.setProperty(ledService, ledPath, ledIntf, "State", 13138d2b5a6SJason M. Bills ledProp->getPrevState()) != 0) 132a3702c1fSVernon Mauery { 133a3702c1fSVernon Mauery return IPMI_CC_UNSPECIFIED_ERROR; 134a3702c1fSVernon Mauery } 135a3702c1fSVernon Mauery } 136a3702c1fSVernon Mauery } 137a3702c1fSVernon Mauery return IPMI_CC_OK; 138a3702c1fSVernon Mauery } 139a3702c1fSVernon Mauery 140a3702c1fSVernon Mauery void Manufacturing::initData() 141a3702c1fSVernon Mauery { 142a3702c1fSVernon Mauery ledPropertyList.push_back( 143a3702c1fSVernon Mauery LedProperty(SmSignalSet::smPowerFaultLed, "status_amber")); 144a3702c1fSVernon Mauery ledPropertyList.push_back( 145a3702c1fSVernon Mauery LedProperty(SmSignalSet::smSystemReadyLed, "status_green")); 146a3702c1fSVernon Mauery ledPropertyList.push_back( 147a3702c1fSVernon Mauery LedProperty(SmSignalSet::smIdentifyLed, "identify")); 148a3702c1fSVernon Mauery } 149a3702c1fSVernon Mauery 150a3702c1fSVernon Mauery void Manufacturing::revertTimerHandler() 151a3702c1fSVernon Mauery { 152a3702c1fSVernon Mauery if (revertFanPWM) 153a3702c1fSVernon Mauery { 154a3702c1fSVernon Mauery revertFanPWM = false; 155a3702c1fSVernon Mauery disablePidControlService(false); 156a3702c1fSVernon Mauery } 157a3702c1fSVernon Mauery 158a3702c1fSVernon Mauery for (const auto& ledProperty : ledPropertyList) 159a3702c1fSVernon Mauery { 160a3702c1fSVernon Mauery const std::string& ledName = ledProperty.getName(); 161a3702c1fSVernon Mauery ledRevert(ledProperty.getSignal()); 162a3702c1fSVernon Mauery } 163a3702c1fSVernon Mauery } 164a3702c1fSVernon Mauery 165a3702c1fSVernon Mauery Manufacturing::Manufacturing() : 166a3702c1fSVernon Mauery revertTimer([&](void) { revertTimerHandler(); }) 167a3702c1fSVernon Mauery { 168a3702c1fSVernon Mauery initData(); 169a3702c1fSVernon Mauery } 170a3702c1fSVernon Mauery 17138d2b5a6SJason M. Bills int8_t Manufacturing::getProperty(const std::string& service, 17238d2b5a6SJason M. Bills const std::string& path, 17338d2b5a6SJason M. Bills const std::string& interface, 17438d2b5a6SJason M. Bills const std::string& propertyName, 17538d2b5a6SJason M. Bills ipmi::Value* reply) 176a3702c1fSVernon Mauery { 177a3702c1fSVernon Mauery try 178a3702c1fSVernon Mauery { 17938d2b5a6SJason M. Bills *reply = ipmi::getDbusProperty(*getSdBus(), service, path, interface, 18038d2b5a6SJason M. Bills propertyName); 181a3702c1fSVernon Mauery } 182a3702c1fSVernon Mauery catch (const sdbusplus::exception::SdBusError& e) 183a3702c1fSVernon Mauery { 184a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 185a3702c1fSVernon Mauery "ERROR: getProperty"); 186a3702c1fSVernon Mauery return -1; 187a3702c1fSVernon Mauery } 188a3702c1fSVernon Mauery 189a3702c1fSVernon Mauery return 0; 190a3702c1fSVernon Mauery } 191a3702c1fSVernon Mauery 19238d2b5a6SJason M. Bills int8_t Manufacturing::setProperty(const std::string& service, 19338d2b5a6SJason M. Bills const std::string& path, 19438d2b5a6SJason M. Bills const std::string& interface, 19538d2b5a6SJason M. Bills const std::string& propertyName, 19638d2b5a6SJason M. Bills ipmi::Value value) 197a3702c1fSVernon Mauery { 198a3702c1fSVernon Mauery try 199a3702c1fSVernon Mauery { 20038d2b5a6SJason M. Bills ipmi::setDbusProperty(*getSdBus(), service, path, interface, 201a3702c1fSVernon Mauery propertyName, value); 202a3702c1fSVernon Mauery } 203a3702c1fSVernon Mauery catch (const sdbusplus::exception::SdBusError& e) 204a3702c1fSVernon Mauery { 205a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 206a3702c1fSVernon Mauery "ERROR: setProperty"); 207a3702c1fSVernon Mauery return -1; 208a3702c1fSVernon Mauery } 209a3702c1fSVernon Mauery 210a3702c1fSVernon Mauery return 0; 211a3702c1fSVernon Mauery } 212a3702c1fSVernon Mauery 213a3702c1fSVernon Mauery int8_t Manufacturing::disablePidControlService(const bool disable) 214a3702c1fSVernon Mauery { 215a3702c1fSVernon Mauery try 216a3702c1fSVernon Mauery { 217a3702c1fSVernon Mauery auto dbus = getSdBus(); 218a3702c1fSVernon Mauery auto method = dbus->new_method_call(systemDService, systemDObjPath, 219a3702c1fSVernon Mauery systemDMgrIntf, 220a3702c1fSVernon Mauery disable ? "StopUnit" : "StartUnit"); 221a3702c1fSVernon Mauery method.append(pidControlService, "replace"); 222a3702c1fSVernon Mauery auto reply = dbus->call(method); 223a3702c1fSVernon Mauery } 224a3702c1fSVernon Mauery catch (const sdbusplus::exception::SdBusError& e) 225a3702c1fSVernon Mauery { 226a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 227a3702c1fSVernon Mauery "ERROR: phosphor-pid-control service start or stop failed"); 228a3702c1fSVernon Mauery return -1; 229a3702c1fSVernon Mauery } 230a3702c1fSVernon Mauery return 0; 231a3702c1fSVernon Mauery } 232a3702c1fSVernon Mauery 23338d2b5a6SJason M. Bills ipmi::RspType<uint8_t, // Signal value 23438d2b5a6SJason M. Bills std::optional<uint16_t> // Fan tach value 23538d2b5a6SJason M. Bills > 23638d2b5a6SJason M. Bills appMTMGetSignal(uint8_t signalTypeByte, uint8_t instance, 23738d2b5a6SJason M. Bills uint8_t actionByte) 238a3702c1fSVernon Mauery { 23938d2b5a6SJason M. Bills if (mtm.getAccessLvl() < MtmLvl::mtmAvailable) 24038d2b5a6SJason M. Bills { 24138d2b5a6SJason M. Bills return ipmi::responseInvalidCommand(); 24238d2b5a6SJason M. Bills } 24338d2b5a6SJason M. Bills 24438d2b5a6SJason M. Bills SmSignalGet signalType = static_cast<SmSignalGet>(signalTypeByte); 24538d2b5a6SJason M. Bills SmActionGet action = static_cast<SmActionGet>(actionByte); 24638d2b5a6SJason M. Bills 24738d2b5a6SJason M. Bills switch (signalType) 24838d2b5a6SJason M. Bills { 24938d2b5a6SJason M. Bills case SmSignalGet::smFanPwmGet: 25038d2b5a6SJason M. Bills { 251a3702c1fSVernon Mauery ipmi::Value reply; 25238d2b5a6SJason M. Bills std::string fullPath = fanPwmPath + std::to_string(instance); 25338d2b5a6SJason M. Bills if (mtm.getProperty(fanService, fullPath, fanIntf, "Value", 25438d2b5a6SJason M. Bills &reply) < 0) 25538d2b5a6SJason M. Bills { 25638d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 25738d2b5a6SJason M. Bills } 25838d2b5a6SJason M. Bills double* doubleVal = std::get_if<double>(&reply); 25938d2b5a6SJason M. Bills if (doubleVal == nullptr) 26038d2b5a6SJason M. Bills { 26138d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 26238d2b5a6SJason M. Bills } 26338d2b5a6SJason M. Bills uint8_t sensorVal = std::round(*doubleVal); 26438d2b5a6SJason M. Bills return ipmi::responseSuccess(sensorVal, std::nullopt); 26538d2b5a6SJason M. Bills } 26638d2b5a6SJason M. Bills break; 26738d2b5a6SJason M. Bills case SmSignalGet::smFanTachometerGet: 26838d2b5a6SJason M. Bills 26938d2b5a6SJason M. Bills { 27038d2b5a6SJason M. Bills // Full path calculation pattern: 27138d2b5a6SJason M. Bills // Instance 1 path is 27238d2b5a6SJason M. Bills // /xyz/openbmc_project/sensors/fan_tach/Fan_1a Instance 2 path 27338d2b5a6SJason M. Bills // is /xyz/openbmc_project/sensors/fan_tach/Fan_1b Instance 3 27438d2b5a6SJason M. Bills // path is /xyz/openbmc_project/sensors/fan_tach/Fan_2a 27538d2b5a6SJason M. Bills // and so on... 27638d2b5a6SJason M. Bills std::string fullPath = fanTachPathPrefix; 27738d2b5a6SJason M. Bills std::string fanAb = (instance % 2) == 0 ? "b" : "a"; 27838d2b5a6SJason M. Bills if (0 == instance) 27938d2b5a6SJason M. Bills { 28038d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 28138d2b5a6SJason M. Bills } 28238d2b5a6SJason M. Bills else if (0 == instance / 2) 28338d2b5a6SJason M. Bills { 28438d2b5a6SJason M. Bills fullPath += std::string("1") + fanAb; 28538d2b5a6SJason M. Bills } 28638d2b5a6SJason M. Bills else 28738d2b5a6SJason M. Bills { 28838d2b5a6SJason M. Bills fullPath += std::to_string(instance / 2) + fanAb; 28938d2b5a6SJason M. Bills } 29038d2b5a6SJason M. Bills 29138d2b5a6SJason M. Bills ipmi::Value reply; 29238d2b5a6SJason M. Bills if (mtm.getProperty(fanService, fullPath, fanIntf, "Value", 29338d2b5a6SJason M. Bills &reply) < 0) 29438d2b5a6SJason M. Bills { 29538d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 29638d2b5a6SJason M. Bills } 29738d2b5a6SJason M. Bills 29838d2b5a6SJason M. Bills double* doubleVal = std::get_if<double>(&reply); 29938d2b5a6SJason M. Bills if (doubleVal == nullptr) 30038d2b5a6SJason M. Bills { 30138d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 30238d2b5a6SJason M. Bills } 30338d2b5a6SJason M. Bills uint8_t sensorVal = FAN_PRESENT | FAN_SENSOR_PRESENT; 30438d2b5a6SJason M. Bills std::optional<uint16_t> fanTach = std::round(*doubleVal); 30538d2b5a6SJason M. Bills 30638d2b5a6SJason M. Bills return ipmi::responseSuccess(sensorVal, fanTach); 30738d2b5a6SJason M. Bills } 30838d2b5a6SJason M. Bills break; 30938d2b5a6SJason M. Bills case SmSignalGet::smResetButton: 31038d2b5a6SJason M. Bills case SmSignalGet::smPowerButton: 31138d2b5a6SJason M. Bills case SmSignalGet::smNMIButton: 31238d2b5a6SJason M. Bills case SmSignalGet::smIdentifyButton: 31338d2b5a6SJason M. Bills { 31438d2b5a6SJason M. Bills std::string path; 31538d2b5a6SJason M. Bills if (getGpioPathForSmSignal(signalType, path) < 0) 31638d2b5a6SJason M. Bills { 31738d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 31838d2b5a6SJason M. Bills } 319a3702c1fSVernon Mauery 320a3702c1fSVernon Mauery switch (action) 321a3702c1fSVernon Mauery { 322a3702c1fSVernon Mauery case SmActionGet::sample: 323a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 324a3702c1fSVernon Mauery "case SmActionGet::sample"); 325a3702c1fSVernon Mauery break; 326a3702c1fSVernon Mauery case SmActionGet::ignore: 327a3702c1fSVernon Mauery { 328a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 329a3702c1fSVernon Mauery "case SmActionGet::ignore"); 33038d2b5a6SJason M. Bills if (mtm.setProperty(buttonService, path, buttonIntf, 33138d2b5a6SJason M. Bills "ButtonMasked", true) < 0) 332a3702c1fSVernon Mauery { 33338d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 334a3702c1fSVernon Mauery } 335a3702c1fSVernon Mauery } 336a3702c1fSVernon Mauery break; 337a3702c1fSVernon Mauery case SmActionGet::revert: 338a3702c1fSVernon Mauery { 339a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 340a3702c1fSVernon Mauery "case SmActionGet::revert"); 34138d2b5a6SJason M. Bills if (mtm.setProperty(buttonService, path, buttonIntf, 34238d2b5a6SJason M. Bills "ButtonMasked", false) < 0) 343a3702c1fSVernon Mauery { 34438d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 345a3702c1fSVernon Mauery } 346a3702c1fSVernon Mauery } 347a3702c1fSVernon Mauery break; 348a3702c1fSVernon Mauery 349a3702c1fSVernon Mauery default: 35038d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 351a3702c1fSVernon Mauery break; 352a3702c1fSVernon Mauery } 353a3702c1fSVernon Mauery 354a3702c1fSVernon Mauery ipmi::Value reply; 35538d2b5a6SJason M. Bills if (mtm.getProperty(buttonService, path, buttonIntf, 35638d2b5a6SJason M. Bills "ButtonPressed", &reply) < 0) 357a3702c1fSVernon Mauery { 35838d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 359a3702c1fSVernon Mauery } 36038d2b5a6SJason M. Bills bool* valPtr = std::get_if<bool>(&reply); 36138d2b5a6SJason M. Bills if (valPtr == nullptr) 362a3702c1fSVernon Mauery { 36338d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 364a3702c1fSVernon Mauery } 36538d2b5a6SJason M. Bills uint8_t sensorVal = *valPtr; 36638d2b5a6SJason M. Bills return ipmi::responseSuccess(sensorVal, std::nullopt); 367a3702c1fSVernon Mauery } 368a3702c1fSVernon Mauery break; 369a3702c1fSVernon Mauery default: 37038d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 371a3702c1fSVernon Mauery break; 372a3702c1fSVernon Mauery } 373a3702c1fSVernon Mauery } 374a3702c1fSVernon Mauery 375a3702c1fSVernon Mauery ipmi_ret_t ipmi_app_mtm_set_signal(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 376a3702c1fSVernon Mauery ipmi_request_t request, 377a3702c1fSVernon Mauery ipmi_response_t response, 378a3702c1fSVernon Mauery ipmi_data_len_t data_len, 379a3702c1fSVernon Mauery ipmi_context_t context) 380a3702c1fSVernon Mauery { 381a3702c1fSVernon Mauery uint8_t ret = 0; 382a3702c1fSVernon Mauery ipmi_ret_t retCode = IPMI_CC_OK; 383a3702c1fSVernon Mauery SetSmSignalReq* pReq = static_cast<SetSmSignalReq*>(request); 384a3702c1fSVernon Mauery std::string ledName; 385a3702c1fSVernon Mauery /////////////////// Signal to led configuration //////////////// 386a3702c1fSVernon Mauery // {SM_SYSTEM_READY_LED, STAT_GRN_LED}, GPIOS4 gpio148 387a3702c1fSVernon Mauery // {SM_POWER_FAULT_LED, STAT_AMB_LED}, GPIOS5 gpio149 388a3702c1fSVernon Mauery // {SM_IDENTIFY_LED, IDENTIFY_LED}, GPIOS6 gpio150 389a3702c1fSVernon Mauery // {SM_SPEAKER, SPEAKER}, GPIOAB0 gpio216 390a3702c1fSVernon Mauery ///////////////////////////////////////////////////////////////// 391a3702c1fSVernon Mauery if ((*data_len == sizeof(*pReq)) && 392a3702c1fSVernon Mauery (mtm.getAccessLvl() >= MtmLvl::mtmAvailable)) 393a3702c1fSVernon Mauery { 394a3702c1fSVernon Mauery switch (pReq->Signal) 395a3702c1fSVernon Mauery { 396a3702c1fSVernon Mauery case SmSignalSet::smPowerFaultLed: 397a3702c1fSVernon Mauery case SmSignalSet::smSystemReadyLed: 398a3702c1fSVernon Mauery case SmSignalSet::smIdentifyLed: 399a3702c1fSVernon Mauery switch (pReq->Action) 400a3702c1fSVernon Mauery { 401a3702c1fSVernon Mauery case SmActionSet::forceDeasserted: 402a3702c1fSVernon Mauery { 403a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 404a3702c1fSVernon Mauery "case SmActionSet::forceDeasserted"); 405a3702c1fSVernon Mauery 406a3702c1fSVernon Mauery retCode = 407a3702c1fSVernon Mauery ledStoreAndSet(pReq->Signal, std::string("Off")); 408a3702c1fSVernon Mauery if (retCode != IPMI_CC_OK) 409a3702c1fSVernon Mauery { 410a3702c1fSVernon Mauery break; 411a3702c1fSVernon Mauery } 412a3702c1fSVernon Mauery mtm.revertTimer.start(revertTimeOut); 413a3702c1fSVernon Mauery } 414a3702c1fSVernon Mauery break; 415a3702c1fSVernon Mauery case SmActionSet::forceAsserted: 416a3702c1fSVernon Mauery { 417a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 418a3702c1fSVernon Mauery "case SmActionSet::forceAsserted"); 419a3702c1fSVernon Mauery 420a3702c1fSVernon Mauery retCode = 421a3702c1fSVernon Mauery ledStoreAndSet(pReq->Signal, std::string("On")); 422a3702c1fSVernon Mauery if (retCode != IPMI_CC_OK) 423a3702c1fSVernon Mauery { 424a3702c1fSVernon Mauery break; 425a3702c1fSVernon Mauery } 426a3702c1fSVernon Mauery mtm.revertTimer.start(revertTimeOut); 427a3702c1fSVernon Mauery if (SmSignalSet::smPowerFaultLed == pReq->Signal) 428a3702c1fSVernon Mauery { 429a3702c1fSVernon Mauery // Deassert "system ready" 430a3702c1fSVernon Mauery retCode = 431a3702c1fSVernon Mauery ledStoreAndSet(SmSignalSet::smSystemReadyLed, 432a3702c1fSVernon Mauery std::string("Off")); 433a3702c1fSVernon Mauery if (retCode != IPMI_CC_OK) 434a3702c1fSVernon Mauery { 435a3702c1fSVernon Mauery break; 436a3702c1fSVernon Mauery } 437a3702c1fSVernon Mauery } 438a3702c1fSVernon Mauery else if (SmSignalSet::smSystemReadyLed == pReq->Signal) 439a3702c1fSVernon Mauery { 440a3702c1fSVernon Mauery // Deassert "fault led" 441a3702c1fSVernon Mauery retCode = 442a3702c1fSVernon Mauery ledStoreAndSet(SmSignalSet::smPowerFaultLed, 443a3702c1fSVernon Mauery std::string("Off")); 444a3702c1fSVernon Mauery if (retCode != IPMI_CC_OK) 445a3702c1fSVernon Mauery { 446a3702c1fSVernon Mauery break; 447a3702c1fSVernon Mauery } 448a3702c1fSVernon Mauery } 449a3702c1fSVernon Mauery } 450a3702c1fSVernon Mauery break; 451a3702c1fSVernon Mauery case SmActionSet::revert: 452a3702c1fSVernon Mauery { 453a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 454a3702c1fSVernon Mauery "case SmActionSet::revert"); 455a3702c1fSVernon Mauery retCode = ledRevert(pReq->Signal); 456a3702c1fSVernon Mauery if (retCode != IPMI_CC_OK) 457a3702c1fSVernon Mauery { 458a3702c1fSVernon Mauery break; 459a3702c1fSVernon Mauery } 460a3702c1fSVernon Mauery } 461a3702c1fSVernon Mauery break; 462a3702c1fSVernon Mauery default: 463a3702c1fSVernon Mauery { 464a3702c1fSVernon Mauery retCode = IPMI_CC_INVALID_FIELD_REQUEST; 465a3702c1fSVernon Mauery } 466a3702c1fSVernon Mauery break; 467a3702c1fSVernon Mauery } 468a3702c1fSVernon Mauery break; 469a3702c1fSVernon Mauery case SmSignalSet::smFanPowerSpeed: 470a3702c1fSVernon Mauery { 471a3702c1fSVernon Mauery if (((pReq->Action == SmActionSet::forceAsserted) && 472a3702c1fSVernon Mauery (*data_len != sizeof(*pReq)) && (pReq->Value > 100)) || 473a3702c1fSVernon Mauery pReq->Instance == 0) 474a3702c1fSVernon Mauery { 475a3702c1fSVernon Mauery retCode = IPMI_CC_INVALID_FIELD_REQUEST; 476a3702c1fSVernon Mauery break; 477a3702c1fSVernon Mauery } 478a3702c1fSVernon Mauery uint8_t pwmValue = 0; 479a3702c1fSVernon Mauery switch (pReq->Action) 480a3702c1fSVernon Mauery { 481a3702c1fSVernon Mauery case SmActionSet::revert: 482a3702c1fSVernon Mauery { 483a3702c1fSVernon Mauery if (mtm.revertFanPWM) 484a3702c1fSVernon Mauery { 485a3702c1fSVernon Mauery ret = mtm.disablePidControlService(false); 486a3702c1fSVernon Mauery if (ret < 0) 487a3702c1fSVernon Mauery { 488a3702c1fSVernon Mauery retCode = IPMI_CC_UNSPECIFIED_ERROR; 489a3702c1fSVernon Mauery break; 490a3702c1fSVernon Mauery } 491a3702c1fSVernon Mauery mtm.revertFanPWM = false; 492a3702c1fSVernon Mauery } 493a3702c1fSVernon Mauery } 494a3702c1fSVernon Mauery break; 495a3702c1fSVernon Mauery case SmActionSet::forceAsserted: 496a3702c1fSVernon Mauery { 497a3702c1fSVernon Mauery pwmValue = pReq->Value; 498a3702c1fSVernon Mauery } // fall-through 499a3702c1fSVernon Mauery case SmActionSet::forceDeasserted: 500a3702c1fSVernon Mauery { 501a3702c1fSVernon Mauery if (!mtm.revertFanPWM) 502a3702c1fSVernon Mauery { 503a3702c1fSVernon Mauery ret = mtm.disablePidControlService(true); 504a3702c1fSVernon Mauery if (ret < 0) 505a3702c1fSVernon Mauery { 506a3702c1fSVernon Mauery retCode = IPMI_CC_UNSPECIFIED_ERROR; 507a3702c1fSVernon Mauery break; 508a3702c1fSVernon Mauery } 509a3702c1fSVernon Mauery mtm.revertFanPWM = true; 510a3702c1fSVernon Mauery } 511a3702c1fSVernon Mauery mtm.revertTimer.start(revertTimeOut); 512a3702c1fSVernon Mauery std::string fanPwmInstancePath = 513a3702c1fSVernon Mauery fanPwmPath + std::to_string(pReq->Instance); 514a3702c1fSVernon Mauery 51538d2b5a6SJason M. Bills ret = mtm.setProperty(fanService, fanPwmInstancePath, 51638d2b5a6SJason M. Bills fanIntf, "Value", 51738d2b5a6SJason M. Bills static_cast<double>(pwmValue)); 518a3702c1fSVernon Mauery if (ret < 0) 519a3702c1fSVernon Mauery { 520a3702c1fSVernon Mauery retCode = IPMI_CC_UNSPECIFIED_ERROR; 521a3702c1fSVernon Mauery } 522a3702c1fSVernon Mauery } 523a3702c1fSVernon Mauery break; 524a3702c1fSVernon Mauery default: 525a3702c1fSVernon Mauery { 526a3702c1fSVernon Mauery retCode = IPMI_CC_INVALID_FIELD_REQUEST; 527a3702c1fSVernon Mauery } 528a3702c1fSVernon Mauery break; 529a3702c1fSVernon Mauery } 530a3702c1fSVernon Mauery } 531a3702c1fSVernon Mauery break; 532a3702c1fSVernon Mauery default: 533a3702c1fSVernon Mauery { 534a3702c1fSVernon Mauery retCode = IPMI_CC_INVALID_FIELD_REQUEST; 535a3702c1fSVernon Mauery } 536a3702c1fSVernon Mauery break; 537a3702c1fSVernon Mauery } 538a3702c1fSVernon Mauery } 539a3702c1fSVernon Mauery else 540a3702c1fSVernon Mauery { 541*39f64b32SAyushi Smriti retCode = IPMI_CC_INVALID; 542a3702c1fSVernon Mauery } 543a3702c1fSVernon Mauery 544a3702c1fSVernon Mauery *data_len = 0; // Only CC is return for SetSmSignal cmd 545a3702c1fSVernon Mauery return retCode; 546a3702c1fSVernon Mauery } 547a3702c1fSVernon Mauery 548a3702c1fSVernon Mauery } // namespace ipmi 549a3702c1fSVernon Mauery 550a3702c1fSVernon Mauery void register_mtm_commands() __attribute__((constructor)); 551a3702c1fSVernon Mauery void register_mtm_commands() 552a3702c1fSVernon Mauery { 55338d2b5a6SJason M. Bills // <Get SM Signal> 55438d2b5a6SJason M. Bills ipmi::registerHandler( 55538d2b5a6SJason M. Bills ipmi::prioOemBase, ipmi::netFnOemOne, 55638d2b5a6SJason M. Bills static_cast<ipmi::Cmd>(IPMINetFnIntelOemGeneralCmds::GetSmSignal), 55738d2b5a6SJason M. Bills ipmi::Privilege::User, ipmi::appMTMGetSignal); 558a3702c1fSVernon Mauery 559a3702c1fSVernon Mauery ipmi_register_callback( 560a3702c1fSVernon Mauery netfnIntcOEMGeneral, 561a3702c1fSVernon Mauery static_cast<ipmi_cmd_t>(IPMINetFnIntelOemGeneralCmds::SetSmSignal), 562a3702c1fSVernon Mauery NULL, ipmi::ipmi_app_mtm_set_signal, PRIVILEGE_USER); 563a3702c1fSVernon Mauery 564a3702c1fSVernon Mauery return; 565a3702c1fSVernon Mauery } 566