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 17d872a4a4SAyushi Smriti #include <linux/input.h> 18d872a4a4SAyushi Smriti 19*06584cd0SArun P. Mohanan #include <boost/algorithm/string.hpp> 20147daec5SRichard Marian Thomaiyar #include <boost/container/flat_map.hpp> 21a3702c1fSVernon Mauery #include <ipmid/api.hpp> 22a3702c1fSVernon Mauery #include <manufacturingcommands.hpp> 23a3702c1fSVernon Mauery #include <oemcommands.hpp> 24a3702c1fSVernon Mauery 25fcd2d3a9SJames Feist #include <filesystem> 26fcd2d3a9SJames Feist #include <fstream> 27fcd2d3a9SJames Feist 28a3702c1fSVernon Mauery namespace ipmi 29a3702c1fSVernon Mauery { 30a3702c1fSVernon Mauery 31a3702c1fSVernon Mauery Manufacturing mtm; 32a3702c1fSVernon Mauery 33a3702c1fSVernon Mauery static auto revertTimeOut = 34a3702c1fSVernon Mauery std::chrono::duration_cast<std::chrono::microseconds>( 35a3702c1fSVernon Mauery std::chrono::seconds(60)); // 1 minute timeout 36a3702c1fSVernon Mauery 37f267a67dSYong Li static constexpr uint8_t slotAddressTypeBus = 0; 38f267a67dSYong Li static constexpr uint8_t slotAddressTypeUniqueid = 1; 39f267a67dSYong Li static constexpr uint8_t slotI2CMaxReadSize = 35; 40f267a67dSYong Li 41a3702c1fSVernon Mauery static constexpr const char* callbackMgrService = 42a3702c1fSVernon Mauery "xyz.openbmc_project.CallbackManager"; 43a3702c1fSVernon Mauery static constexpr const char* callbackMgrIntf = 44a3702c1fSVernon Mauery "xyz.openbmc_project.CallbackManager"; 45a3702c1fSVernon Mauery static constexpr const char* callbackMgrObjPath = 46a3702c1fSVernon Mauery "/xyz/openbmc_project/CallbackManager"; 47a3702c1fSVernon Mauery static constexpr const char* retriggerLedUpdate = "RetriggerLEDUpdate"; 48a3702c1fSVernon Mauery 49a3702c1fSVernon Mauery const static constexpr char* systemDService = "org.freedesktop.systemd1"; 50a3702c1fSVernon Mauery const static constexpr char* systemDObjPath = "/org/freedesktop/systemd1"; 51a3702c1fSVernon Mauery const static constexpr char* systemDMgrIntf = 52a3702c1fSVernon Mauery "org.freedesktop.systemd1.Manager"; 53a3702c1fSVernon Mauery const static constexpr char* pidControlService = "phosphor-pid-control.service"; 54a3702c1fSVernon Mauery 55357ddc74SRichard Marian Thomaiyar static inline Cc resetMtmTimer(ipmi::Context::ptr ctx) 56666dd01cSRichard Marian Thomaiyar { 57666dd01cSRichard Marian Thomaiyar boost::system::error_code ec; 58357ddc74SRichard Marian Thomaiyar ctx->bus->yield_method_call<>(ctx->yield, ec, specialModeService, 59666dd01cSRichard Marian Thomaiyar specialModeObjPath, specialModeIntf, 60666dd01cSRichard Marian Thomaiyar "ResetTimer"); 61666dd01cSRichard Marian Thomaiyar if (ec) 62666dd01cSRichard Marian Thomaiyar { 63666dd01cSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 64666dd01cSRichard Marian Thomaiyar "Failed to reset the manufacturing mode timer"); 65666dd01cSRichard Marian Thomaiyar return ccUnspecifiedError; 66666dd01cSRichard Marian Thomaiyar } 67666dd01cSRichard Marian Thomaiyar return ccSuccess; 68666dd01cSRichard Marian Thomaiyar } 69666dd01cSRichard Marian Thomaiyar 7038d2b5a6SJason M. Bills int getGpioPathForSmSignal(const SmSignalGet signal, std::string& path) 71a3702c1fSVernon Mauery { 7238d2b5a6SJason M. Bills switch (signal) 7338d2b5a6SJason M. Bills { 7438d2b5a6SJason M. Bills case SmSignalGet::smPowerButton: 7538d2b5a6SJason M. Bills path = "/xyz/openbmc_project/chassis/buttons/power"; 7638d2b5a6SJason M. Bills break; 7738d2b5a6SJason M. Bills case SmSignalGet::smResetButton: 7838d2b5a6SJason M. Bills path = "/xyz/openbmc_project/chassis/buttons/reset"; 7938d2b5a6SJason M. Bills break; 8038d2b5a6SJason M. Bills case SmSignalGet::smNMIButton: 8138d2b5a6SJason M. Bills path = "/xyz/openbmc_project/chassis/buttons/nmi"; 8238d2b5a6SJason M. Bills break; 838e5e2b04SRichard Marian Thomaiyar case SmSignalGet::smIdentifyButton: 848e5e2b04SRichard Marian Thomaiyar path = "/xyz/openbmc_project/chassis/buttons/id"; 858e5e2b04SRichard Marian Thomaiyar break; 8638d2b5a6SJason M. Bills default: 8738d2b5a6SJason M. Bills return -1; 8838d2b5a6SJason M. Bills break; 8938d2b5a6SJason M. Bills } 9038d2b5a6SJason M. Bills return 0; 91a3702c1fSVernon Mauery } 92a3702c1fSVernon Mauery 9337890392SPatrick Venture ipmi_ret_t ledStoreAndSet(SmSignalSet signal, const std::string& setState) 94a3702c1fSVernon Mauery { 95a3702c1fSVernon Mauery LedProperty* ledProp = mtm.findLedProperty(signal); 96a3702c1fSVernon Mauery if (ledProp == nullptr) 97a3702c1fSVernon Mauery { 98a3702c1fSVernon Mauery return IPMI_CC_INVALID_FIELD_REQUEST; 99a3702c1fSVernon Mauery } 100a3702c1fSVernon Mauery 101a3702c1fSVernon Mauery std::string ledName = ledProp->getName(); 102a3702c1fSVernon Mauery std::string ledService = ledServicePrefix + ledName; 103a3702c1fSVernon Mauery std::string ledPath = ledPathPrefix + ledName; 104a3702c1fSVernon Mauery ipmi::Value presentState; 105a3702c1fSVernon Mauery 106a3702c1fSVernon Mauery if (false == ledProp->getLock()) 107a3702c1fSVernon Mauery { 108a3702c1fSVernon Mauery if (mtm.getProperty(ledService.c_str(), ledPath.c_str(), ledIntf, 109a3702c1fSVernon Mauery "State", &presentState) != 0) 110a3702c1fSVernon Mauery { 111a3702c1fSVernon Mauery return IPMI_CC_UNSPECIFIED_ERROR; 112a3702c1fSVernon Mauery } 113a3702c1fSVernon Mauery ledProp->setPrevState(std::get<std::string>(presentState)); 114a3702c1fSVernon Mauery ledProp->setLock(true); 115a3702c1fSVernon Mauery if (signal == SmSignalSet::smPowerFaultLed || 116a3702c1fSVernon Mauery signal == SmSignalSet::smSystemReadyLed) 117a3702c1fSVernon Mauery { 118a3702c1fSVernon Mauery mtm.revertLedCallback = true; 119a3702c1fSVernon Mauery } 120a3702c1fSVernon Mauery } 12138d2b5a6SJason M. Bills if (mtm.setProperty(ledService, ledPath, ledIntf, "State", 122a3702c1fSVernon Mauery ledStateStr + setState) != 0) 123a3702c1fSVernon Mauery { 124a3702c1fSVernon Mauery return IPMI_CC_UNSPECIFIED_ERROR; 125a3702c1fSVernon Mauery } 126a3702c1fSVernon Mauery return IPMI_CC_OK; 127a3702c1fSVernon Mauery } 128a3702c1fSVernon Mauery 129a3702c1fSVernon Mauery ipmi_ret_t ledRevert(SmSignalSet signal) 130a3702c1fSVernon Mauery { 131a3702c1fSVernon Mauery LedProperty* ledProp = mtm.findLedProperty(signal); 132a3702c1fSVernon Mauery if (ledProp == nullptr) 133a3702c1fSVernon Mauery { 134a3702c1fSVernon Mauery return IPMI_CC_INVALID_FIELD_REQUEST; 135a3702c1fSVernon Mauery } 136a3702c1fSVernon Mauery if (true == ledProp->getLock()) 137a3702c1fSVernon Mauery { 138a3702c1fSVernon Mauery ledProp->setLock(false); 139a3702c1fSVernon Mauery if (signal == SmSignalSet::smPowerFaultLed || 140a3702c1fSVernon Mauery signal == SmSignalSet::smSystemReadyLed) 141a3702c1fSVernon Mauery { 142a3702c1fSVernon Mauery try 143a3702c1fSVernon Mauery { 144a3702c1fSVernon Mauery ipmi::method_no_args::callDbusMethod( 145a3702c1fSVernon Mauery *getSdBus(), callbackMgrService, callbackMgrObjPath, 146a3702c1fSVernon Mauery callbackMgrIntf, retriggerLedUpdate); 147a3702c1fSVernon Mauery } 148a3702c1fSVernon Mauery catch (sdbusplus::exception_t& e) 149a3702c1fSVernon Mauery { 150a3702c1fSVernon Mauery return IPMI_CC_UNSPECIFIED_ERROR; 151a3702c1fSVernon Mauery } 152a3702c1fSVernon Mauery mtm.revertLedCallback = false; 153a3702c1fSVernon Mauery } 154a3702c1fSVernon Mauery else 155a3702c1fSVernon Mauery { 156a3702c1fSVernon Mauery std::string ledName = ledProp->getName(); 157a3702c1fSVernon Mauery std::string ledService = ledServicePrefix + ledName; 158a3702c1fSVernon Mauery std::string ledPath = ledPathPrefix + ledName; 15938d2b5a6SJason M. Bills if (mtm.setProperty(ledService, ledPath, ledIntf, "State", 16038d2b5a6SJason M. Bills ledProp->getPrevState()) != 0) 161a3702c1fSVernon Mauery { 162a3702c1fSVernon Mauery return IPMI_CC_UNSPECIFIED_ERROR; 163a3702c1fSVernon Mauery } 164a3702c1fSVernon Mauery } 165a3702c1fSVernon Mauery } 166a3702c1fSVernon Mauery return IPMI_CC_OK; 167a3702c1fSVernon Mauery } 168a3702c1fSVernon Mauery 169a3702c1fSVernon Mauery void Manufacturing::initData() 170a3702c1fSVernon Mauery { 171a3702c1fSVernon Mauery ledPropertyList.push_back( 172a3702c1fSVernon Mauery LedProperty(SmSignalSet::smPowerFaultLed, "status_amber")); 173a3702c1fSVernon Mauery ledPropertyList.push_back( 174a3702c1fSVernon Mauery LedProperty(SmSignalSet::smSystemReadyLed, "status_green")); 175a3702c1fSVernon Mauery ledPropertyList.push_back( 176a3702c1fSVernon Mauery LedProperty(SmSignalSet::smIdentifyLed, "identify")); 177a3702c1fSVernon Mauery } 178a3702c1fSVernon Mauery 179a3702c1fSVernon Mauery void Manufacturing::revertTimerHandler() 180a3702c1fSVernon Mauery { 181ae13ac62SRichard Marian Thomaiyar 182ae13ac62SRichard Marian Thomaiyar #ifdef BMC_VALIDATION_UNSECURE_FEATURE 183ae13ac62SRichard Marian Thomaiyar if (mtm.getMfgMode() == SpecialMode::valUnsecure) 184ae13ac62SRichard Marian Thomaiyar { 185ae13ac62SRichard Marian Thomaiyar // Don't revert the behaviour for validation unsecure mode. 186ae13ac62SRichard Marian Thomaiyar return; 187ae13ac62SRichard Marian Thomaiyar } 188ae13ac62SRichard Marian Thomaiyar #endif 189a3702c1fSVernon Mauery if (revertFanPWM) 190a3702c1fSVernon Mauery { 191a3702c1fSVernon Mauery revertFanPWM = false; 192a3702c1fSVernon Mauery disablePidControlService(false); 193a3702c1fSVernon Mauery } 194a3702c1fSVernon Mauery 195d872a4a4SAyushi Smriti if (mtmTestBeepFd != -1) 196d872a4a4SAyushi Smriti { 197d872a4a4SAyushi Smriti ::close(mtmTestBeepFd); 198d872a4a4SAyushi Smriti mtmTestBeepFd = -1; 199d872a4a4SAyushi Smriti } 200d872a4a4SAyushi Smriti 201a3702c1fSVernon Mauery for (const auto& ledProperty : ledPropertyList) 202a3702c1fSVernon Mauery { 203a3702c1fSVernon Mauery const std::string& ledName = ledProperty.getName(); 204f365614cSJayaprakash Mutyala if (ledName == "identify" && mtm.getMfgMode() == SpecialMode::mfg) 205f365614cSJayaprakash Mutyala { 206f365614cSJayaprakash Mutyala // Don't revert the behaviour for manufacturing mode 207f365614cSJayaprakash Mutyala continue; 208f365614cSJayaprakash Mutyala } 209a3702c1fSVernon Mauery ledRevert(ledProperty.getSignal()); 210a3702c1fSVernon Mauery } 211a3702c1fSVernon Mauery } 212a3702c1fSVernon Mauery 213a3702c1fSVernon Mauery Manufacturing::Manufacturing() : 214a3702c1fSVernon Mauery revertTimer([&](void) { revertTimerHandler(); }) 215a3702c1fSVernon Mauery { 216a3702c1fSVernon Mauery initData(); 217a3702c1fSVernon Mauery } 218a3702c1fSVernon Mauery 21938d2b5a6SJason M. Bills int8_t Manufacturing::getProperty(const std::string& service, 22038d2b5a6SJason M. Bills const std::string& path, 22138d2b5a6SJason M. Bills const std::string& interface, 22238d2b5a6SJason M. Bills const std::string& propertyName, 22338d2b5a6SJason M. Bills ipmi::Value* reply) 224a3702c1fSVernon Mauery { 225a3702c1fSVernon Mauery try 226a3702c1fSVernon Mauery { 22738d2b5a6SJason M. Bills *reply = ipmi::getDbusProperty(*getSdBus(), service, path, interface, 22838d2b5a6SJason M. Bills propertyName); 229a3702c1fSVernon Mauery } 230a3702c1fSVernon Mauery catch (const sdbusplus::exception::SdBusError& e) 231a3702c1fSVernon Mauery { 232a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 233a3702c1fSVernon Mauery "ERROR: getProperty"); 234a3702c1fSVernon Mauery return -1; 235a3702c1fSVernon Mauery } 236a3702c1fSVernon Mauery 237a3702c1fSVernon Mauery return 0; 238a3702c1fSVernon Mauery } 239a3702c1fSVernon Mauery 24038d2b5a6SJason M. Bills int8_t Manufacturing::setProperty(const std::string& service, 24138d2b5a6SJason M. Bills const std::string& path, 24238d2b5a6SJason M. Bills const std::string& interface, 24338d2b5a6SJason M. Bills const std::string& propertyName, 24438d2b5a6SJason M. Bills ipmi::Value value) 245a3702c1fSVernon Mauery { 246a3702c1fSVernon Mauery try 247a3702c1fSVernon Mauery { 24838d2b5a6SJason M. Bills ipmi::setDbusProperty(*getSdBus(), service, path, interface, 249a3702c1fSVernon Mauery propertyName, value); 250a3702c1fSVernon Mauery } 251a3702c1fSVernon Mauery catch (const sdbusplus::exception::SdBusError& e) 252a3702c1fSVernon Mauery { 253a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 254a3702c1fSVernon Mauery "ERROR: setProperty"); 255a3702c1fSVernon Mauery return -1; 256a3702c1fSVernon Mauery } 257a3702c1fSVernon Mauery 258a3702c1fSVernon Mauery return 0; 259a3702c1fSVernon Mauery } 260a3702c1fSVernon Mauery 261a3702c1fSVernon Mauery int8_t Manufacturing::disablePidControlService(const bool disable) 262a3702c1fSVernon Mauery { 263a3702c1fSVernon Mauery try 264a3702c1fSVernon Mauery { 265a3702c1fSVernon Mauery auto dbus = getSdBus(); 266a3702c1fSVernon Mauery auto method = dbus->new_method_call(systemDService, systemDObjPath, 267a3702c1fSVernon Mauery systemDMgrIntf, 268a3702c1fSVernon Mauery disable ? "StopUnit" : "StartUnit"); 269a3702c1fSVernon Mauery method.append(pidControlService, "replace"); 270a3702c1fSVernon Mauery auto reply = dbus->call(method); 271a3702c1fSVernon Mauery } 272a3702c1fSVernon Mauery catch (const sdbusplus::exception::SdBusError& e) 273a3702c1fSVernon Mauery { 274a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 275a3702c1fSVernon Mauery "ERROR: phosphor-pid-control service start or stop failed"); 276a3702c1fSVernon Mauery return -1; 277a3702c1fSVernon Mauery } 278a3702c1fSVernon Mauery return 0; 279a3702c1fSVernon Mauery } 280a3702c1fSVernon Mauery 28138d2b5a6SJason M. Bills ipmi::RspType<uint8_t, // Signal value 28238d2b5a6SJason M. Bills std::optional<uint16_t> // Fan tach value 28338d2b5a6SJason M. Bills > 284357ddc74SRichard Marian Thomaiyar appMTMGetSignal(ipmi::Context::ptr ctx, uint8_t signalTypeByte, 285147daec5SRichard Marian Thomaiyar uint8_t instance, uint8_t actionByte) 286a3702c1fSVernon Mauery { 287e0511e5fSAyushi Smriti // mfg filter logic is used to allow MTM get signal command only in 288e0511e5fSAyushi Smriti // manfacturing mode. 28938d2b5a6SJason M. Bills 29038d2b5a6SJason M. Bills SmSignalGet signalType = static_cast<SmSignalGet>(signalTypeByte); 29138d2b5a6SJason M. Bills SmActionGet action = static_cast<SmActionGet>(actionByte); 29238d2b5a6SJason M. Bills 29338d2b5a6SJason M. Bills switch (signalType) 29438d2b5a6SJason M. Bills { 29598705b39Sanil kumar appana case SmSignalGet::smChassisIntrusion: 29698705b39Sanil kumar appana { 29798705b39Sanil kumar appana ipmi::Value reply; 29898705b39Sanil kumar appana if (mtm.getProperty(intrusionService, intrusionPath, intrusionIntf, 29998705b39Sanil kumar appana "Status", &reply) < 0) 30098705b39Sanil kumar appana { 30198705b39Sanil kumar appana return ipmi::responseInvalidFieldRequest(); 30298705b39Sanil kumar appana } 30398705b39Sanil kumar appana std::string* intrusionStatus = std::get_if<std::string>(&reply); 30498705b39Sanil kumar appana if (!intrusionStatus) 30598705b39Sanil kumar appana { 30698705b39Sanil kumar appana return ipmi::responseUnspecifiedError(); 30798705b39Sanil kumar appana } 30898705b39Sanil kumar appana 30998705b39Sanil kumar appana uint8_t status = 0; 31098705b39Sanil kumar appana if (!intrusionStatus->compare("Normal")) 31198705b39Sanil kumar appana { 31298705b39Sanil kumar appana status = static_cast<uint8_t>(IntrusionStatus::normal); 31398705b39Sanil kumar appana } 31498705b39Sanil kumar appana else if (!intrusionStatus->compare("HardwareIntrusion")) 31598705b39Sanil kumar appana { 31698705b39Sanil kumar appana status = 31798705b39Sanil kumar appana static_cast<uint8_t>(IntrusionStatus::hardwareIntrusion); 31898705b39Sanil kumar appana } 31998705b39Sanil kumar appana else if (!intrusionStatus->compare("TamperingDetected")) 32098705b39Sanil kumar appana { 32198705b39Sanil kumar appana status = 32298705b39Sanil kumar appana static_cast<uint8_t>(IntrusionStatus::tamperingDetected); 32398705b39Sanil kumar appana } 32498705b39Sanil kumar appana else 32598705b39Sanil kumar appana { 32698705b39Sanil kumar appana return ipmi::responseUnspecifiedError(); 32798705b39Sanil kumar appana } 32898705b39Sanil kumar appana return ipmi::responseSuccess(status, std::nullopt); 32998705b39Sanil kumar appana } 33038d2b5a6SJason M. Bills case SmSignalGet::smFanPwmGet: 33138d2b5a6SJason M. Bills { 332a3702c1fSVernon Mauery ipmi::Value reply; 333147daec5SRichard Marian Thomaiyar std::string fullPath = fanPwmPath + std::to_string(instance + 1); 33438d2b5a6SJason M. Bills if (mtm.getProperty(fanService, fullPath, fanIntf, "Value", 33538d2b5a6SJason M. Bills &reply) < 0) 33638d2b5a6SJason M. Bills { 33738d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 33838d2b5a6SJason M. Bills } 33938d2b5a6SJason M. Bills double* doubleVal = std::get_if<double>(&reply); 34038d2b5a6SJason M. Bills if (doubleVal == nullptr) 34138d2b5a6SJason M. Bills { 34238d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 34338d2b5a6SJason M. Bills } 34438d2b5a6SJason M. Bills uint8_t sensorVal = std::round(*doubleVal); 345357ddc74SRichard Marian Thomaiyar resetMtmTimer(ctx); 34638d2b5a6SJason M. Bills return ipmi::responseSuccess(sensorVal, std::nullopt); 34738d2b5a6SJason M. Bills } 34838d2b5a6SJason M. Bills break; 34938d2b5a6SJason M. Bills case SmSignalGet::smFanTachometerGet: 35038d2b5a6SJason M. Bills { 351147daec5SRichard Marian Thomaiyar boost::system::error_code ec; 352147daec5SRichard Marian Thomaiyar using objFlatMap = boost::container::flat_map< 353147daec5SRichard Marian Thomaiyar std::string, boost::container::flat_map< 354147daec5SRichard Marian Thomaiyar std::string, std::vector<std::string>>>; 355147daec5SRichard Marian Thomaiyar 356357ddc74SRichard Marian Thomaiyar auto flatMap = ctx->bus->yield_method_call<objFlatMap>( 357357ddc74SRichard Marian Thomaiyar ctx->yield, ec, "xyz.openbmc_project.ObjectMapper", 358147daec5SRichard Marian Thomaiyar "/xyz/openbmc_project/object_mapper", 359147daec5SRichard Marian Thomaiyar "xyz.openbmc_project.ObjectMapper", "GetSubTree", 360147daec5SRichard Marian Thomaiyar fanTachBasePath, 0, std::array<const char*, 1>{fanIntf}); 361147daec5SRichard Marian Thomaiyar if (ec) 362147daec5SRichard Marian Thomaiyar { 363147daec5SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 364147daec5SRichard Marian Thomaiyar "Failed to query fan tach sub tree objects"); 365147daec5SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 366147daec5SRichard Marian Thomaiyar } 367147daec5SRichard Marian Thomaiyar if (instance >= flatMap.size()) 36838d2b5a6SJason M. Bills { 36938d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 37038d2b5a6SJason M. Bills } 371147daec5SRichard Marian Thomaiyar auto itr = flatMap.nth(instance); 37238d2b5a6SJason M. Bills ipmi::Value reply; 373147daec5SRichard Marian Thomaiyar if (mtm.getProperty(fanService, itr->first, fanIntf, "Value", 37438d2b5a6SJason M. Bills &reply) < 0) 37538d2b5a6SJason M. Bills { 37638d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 37738d2b5a6SJason M. Bills } 37838d2b5a6SJason M. Bills 37938d2b5a6SJason M. Bills double* doubleVal = std::get_if<double>(&reply); 38038d2b5a6SJason M. Bills if (doubleVal == nullptr) 38138d2b5a6SJason M. Bills { 38238d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 38338d2b5a6SJason M. Bills } 38438d2b5a6SJason M. Bills uint8_t sensorVal = FAN_PRESENT | FAN_SENSOR_PRESENT; 38538d2b5a6SJason M. Bills std::optional<uint16_t> fanTach = std::round(*doubleVal); 38638d2b5a6SJason M. Bills 387357ddc74SRichard Marian Thomaiyar resetMtmTimer(ctx); 38838d2b5a6SJason M. Bills return ipmi::responseSuccess(sensorVal, fanTach); 38938d2b5a6SJason M. Bills } 39038d2b5a6SJason M. Bills break; 3918e5e2b04SRichard Marian Thomaiyar case SmSignalGet::smIdentifyButton: 3928e5e2b04SRichard Marian Thomaiyar { 3938e5e2b04SRichard Marian Thomaiyar if (action == SmActionGet::revert || action == SmActionGet::ignore) 3948e5e2b04SRichard Marian Thomaiyar { 3958e5e2b04SRichard Marian Thomaiyar // ButtonMasked property is not supported for ID button as it is 3968e5e2b04SRichard Marian Thomaiyar // unnecessary. Hence if requested for revert / ignore, override 3978e5e2b04SRichard Marian Thomaiyar // it to sample action to make tools happy. 3988e5e2b04SRichard Marian Thomaiyar action = SmActionGet::sample; 3998e5e2b04SRichard Marian Thomaiyar } 4008e5e2b04SRichard Marian Thomaiyar // fall-through 4018e5e2b04SRichard Marian Thomaiyar } 40238d2b5a6SJason M. Bills case SmSignalGet::smResetButton: 40338d2b5a6SJason M. Bills case SmSignalGet::smPowerButton: 40438d2b5a6SJason M. Bills case SmSignalGet::smNMIButton: 40538d2b5a6SJason M. Bills { 40638d2b5a6SJason M. Bills std::string path; 40738d2b5a6SJason M. Bills if (getGpioPathForSmSignal(signalType, path) < 0) 40838d2b5a6SJason M. Bills { 40938d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 41038d2b5a6SJason M. Bills } 411a3702c1fSVernon Mauery 412a3702c1fSVernon Mauery switch (action) 413a3702c1fSVernon Mauery { 414a3702c1fSVernon Mauery case SmActionGet::sample: 415a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 416a3702c1fSVernon Mauery "case SmActionGet::sample"); 417a3702c1fSVernon Mauery break; 418a3702c1fSVernon Mauery case SmActionGet::ignore: 419a3702c1fSVernon Mauery { 420a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 421a3702c1fSVernon Mauery "case SmActionGet::ignore"); 42238d2b5a6SJason M. Bills if (mtm.setProperty(buttonService, path, buttonIntf, 42338d2b5a6SJason M. Bills "ButtonMasked", true) < 0) 424a3702c1fSVernon Mauery { 42538d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 426a3702c1fSVernon Mauery } 427a3702c1fSVernon Mauery } 428a3702c1fSVernon Mauery break; 429a3702c1fSVernon Mauery case SmActionGet::revert: 430a3702c1fSVernon Mauery { 431a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 432a3702c1fSVernon Mauery "case SmActionGet::revert"); 43338d2b5a6SJason M. Bills if (mtm.setProperty(buttonService, path, buttonIntf, 43438d2b5a6SJason M. Bills "ButtonMasked", false) < 0) 435a3702c1fSVernon Mauery { 43638d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 437a3702c1fSVernon Mauery } 438a3702c1fSVernon Mauery } 439a3702c1fSVernon Mauery break; 440a3702c1fSVernon Mauery 441a3702c1fSVernon Mauery default: 44238d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 443a3702c1fSVernon Mauery break; 444a3702c1fSVernon Mauery } 445a3702c1fSVernon Mauery 446a3702c1fSVernon Mauery ipmi::Value reply; 44738d2b5a6SJason M. Bills if (mtm.getProperty(buttonService, path, buttonIntf, 44838d2b5a6SJason M. Bills "ButtonPressed", &reply) < 0) 449a3702c1fSVernon Mauery { 45038d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 451a3702c1fSVernon Mauery } 45238d2b5a6SJason M. Bills bool* valPtr = std::get_if<bool>(&reply); 45338d2b5a6SJason M. Bills if (valPtr == nullptr) 454a3702c1fSVernon Mauery { 45538d2b5a6SJason M. Bills return ipmi::responseUnspecifiedError(); 456a3702c1fSVernon Mauery } 457357ddc74SRichard Marian Thomaiyar resetMtmTimer(ctx); 45838d2b5a6SJason M. Bills uint8_t sensorVal = *valPtr; 45938d2b5a6SJason M. Bills return ipmi::responseSuccess(sensorVal, std::nullopt); 460a3702c1fSVernon Mauery } 461a3702c1fSVernon Mauery break; 4621b74a210SRichard Marian Thomaiyar case SmSignalGet::smNcsiDiag: 4631b74a210SRichard Marian Thomaiyar { 4641b74a210SRichard Marian Thomaiyar constexpr const char* netBasePath = "/sys/class/net/eth"; 4651b74a210SRichard Marian Thomaiyar constexpr const char* carrierSuffix = "/carrier"; 4661b74a210SRichard Marian Thomaiyar std::ifstream netIfs(netBasePath + std::to_string(instance) + 4671b74a210SRichard Marian Thomaiyar carrierSuffix); 4681b74a210SRichard Marian Thomaiyar if (!netIfs.good()) 4691b74a210SRichard Marian Thomaiyar { 4701b74a210SRichard Marian Thomaiyar return ipmi::responseInvalidFieldRequest(); 4711b74a210SRichard Marian Thomaiyar } 4721b74a210SRichard Marian Thomaiyar std::string carrier; 4731b74a210SRichard Marian Thomaiyar netIfs >> carrier; 474357ddc74SRichard Marian Thomaiyar resetMtmTimer(ctx); 4751b74a210SRichard Marian Thomaiyar return ipmi::responseSuccess( 4761b74a210SRichard Marian Thomaiyar static_cast<uint8_t>(std::stoi(carrier)), std::nullopt); 4771b74a210SRichard Marian Thomaiyar } 4781b74a210SRichard Marian Thomaiyar break; 479a3702c1fSVernon Mauery default: 48038d2b5a6SJason M. Bills return ipmi::responseInvalidFieldRequest(); 481a3702c1fSVernon Mauery break; 482a3702c1fSVernon Mauery } 483a3702c1fSVernon Mauery } 484a3702c1fSVernon Mauery 485357ddc74SRichard Marian Thomaiyar ipmi::RspType<> appMTMSetSignal(ipmi::Context::ptr ctx, uint8_t signalTypeByte, 486357ddc74SRichard Marian Thomaiyar uint8_t instance, uint8_t actionByte, 4875e3bf557SAyushi Smriti std::optional<uint8_t> pwmSpeed) 488a3702c1fSVernon Mauery { 489e0511e5fSAyushi Smriti // mfg filter logic is used to allow MTM set signal command only in 490e0511e5fSAyushi Smriti // manfacturing mode. 4915e3bf557SAyushi Smriti 4925e3bf557SAyushi Smriti SmSignalSet signalType = static_cast<SmSignalSet>(signalTypeByte); 4935e3bf557SAyushi Smriti SmActionSet action = static_cast<SmActionSet>(actionByte); 4945e3bf557SAyushi Smriti Cc retCode = ccSuccess; 49513b0039dSJames Feist int8_t ret = 0; 4965e3bf557SAyushi Smriti 4975e3bf557SAyushi Smriti switch (signalType) 498a3702c1fSVernon Mauery { 499a3702c1fSVernon Mauery case SmSignalSet::smPowerFaultLed: 500a3702c1fSVernon Mauery case SmSignalSet::smSystemReadyLed: 501a3702c1fSVernon Mauery case SmSignalSet::smIdentifyLed: 5025e3bf557SAyushi Smriti switch (action) 503a3702c1fSVernon Mauery { 504a3702c1fSVernon Mauery case SmActionSet::forceDeasserted: 505a3702c1fSVernon Mauery { 506a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 507a3702c1fSVernon Mauery "case SmActionSet::forceDeasserted"); 508a3702c1fSVernon Mauery 5095e3bf557SAyushi Smriti retCode = ledStoreAndSet(signalType, std::string("Off")); 5105e3bf557SAyushi Smriti if (retCode != ccSuccess) 511a3702c1fSVernon Mauery { 5125e3bf557SAyushi Smriti return ipmi::response(retCode); 513a3702c1fSVernon Mauery } 514a3702c1fSVernon Mauery mtm.revertTimer.start(revertTimeOut); 515a3702c1fSVernon Mauery } 516a3702c1fSVernon Mauery break; 517a3702c1fSVernon Mauery case SmActionSet::forceAsserted: 518a3702c1fSVernon Mauery { 519a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 520a3702c1fSVernon Mauery "case SmActionSet::forceAsserted"); 521a3702c1fSVernon Mauery 5225e3bf557SAyushi Smriti retCode = ledStoreAndSet(signalType, std::string("On")); 5235e3bf557SAyushi Smriti if (retCode != ccSuccess) 524a3702c1fSVernon Mauery { 5255e3bf557SAyushi Smriti return ipmi::response(retCode); 526a3702c1fSVernon Mauery } 527a3702c1fSVernon Mauery mtm.revertTimer.start(revertTimeOut); 5285e3bf557SAyushi Smriti if (SmSignalSet::smPowerFaultLed == signalType) 529a3702c1fSVernon Mauery { 530a3702c1fSVernon Mauery // Deassert "system ready" 5315e3bf557SAyushi Smriti retCode = ledStoreAndSet(SmSignalSet::smSystemReadyLed, 532a3702c1fSVernon Mauery std::string("Off")); 533a3702c1fSVernon Mauery } 5345e3bf557SAyushi Smriti else if (SmSignalSet::smSystemReadyLed == signalType) 535a3702c1fSVernon Mauery { 536a3702c1fSVernon Mauery // Deassert "fault led" 5375e3bf557SAyushi Smriti retCode = ledStoreAndSet(SmSignalSet::smPowerFaultLed, 538a3702c1fSVernon Mauery std::string("Off")); 539a3702c1fSVernon Mauery } 540a3702c1fSVernon Mauery } 541a3702c1fSVernon Mauery break; 542a3702c1fSVernon Mauery case SmActionSet::revert: 543a3702c1fSVernon Mauery { 544a3702c1fSVernon Mauery phosphor::logging::log<phosphor::logging::level::INFO>( 545a3702c1fSVernon Mauery "case SmActionSet::revert"); 5465e3bf557SAyushi Smriti retCode = ledRevert(signalType); 547a3702c1fSVernon Mauery } 548a3702c1fSVernon Mauery break; 549a3702c1fSVernon Mauery default: 550a3702c1fSVernon Mauery { 5515e3bf557SAyushi Smriti return ipmi::responseInvalidFieldRequest(); 552a3702c1fSVernon Mauery } 553a3702c1fSVernon Mauery } 554a3702c1fSVernon Mauery break; 555a3702c1fSVernon Mauery case SmSignalSet::smFanPowerSpeed: 556a3702c1fSVernon Mauery { 5575e3bf557SAyushi Smriti if ((action == SmActionSet::forceAsserted) && (!pwmSpeed)) 558a3702c1fSVernon Mauery { 5595e3bf557SAyushi Smriti return ipmi::responseReqDataLenInvalid(); 560a3702c1fSVernon Mauery } 5615e3bf557SAyushi Smriti 5625e3bf557SAyushi Smriti if ((action == SmActionSet::forceAsserted) && (*pwmSpeed > 100)) 5635e3bf557SAyushi Smriti { 5645e3bf557SAyushi Smriti return ipmi::responseInvalidFieldRequest(); 5655e3bf557SAyushi Smriti } 5665e3bf557SAyushi Smriti 567a3702c1fSVernon Mauery uint8_t pwmValue = 0; 5685e3bf557SAyushi Smriti switch (action) 569a3702c1fSVernon Mauery { 570a3702c1fSVernon Mauery case SmActionSet::revert: 571a3702c1fSVernon Mauery { 572a3702c1fSVernon Mauery if (mtm.revertFanPWM) 573a3702c1fSVernon Mauery { 574a3702c1fSVernon Mauery ret = mtm.disablePidControlService(false); 575a3702c1fSVernon Mauery if (ret < 0) 576a3702c1fSVernon Mauery { 5775e3bf557SAyushi Smriti return ipmi::responseUnspecifiedError(); 578a3702c1fSVernon Mauery } 579a3702c1fSVernon Mauery mtm.revertFanPWM = false; 580a3702c1fSVernon Mauery } 581a3702c1fSVernon Mauery } 582a3702c1fSVernon Mauery break; 583a3702c1fSVernon Mauery case SmActionSet::forceAsserted: 584a3702c1fSVernon Mauery { 5855e3bf557SAyushi Smriti pwmValue = *pwmSpeed; 586a3702c1fSVernon Mauery } // fall-through 587a3702c1fSVernon Mauery case SmActionSet::forceDeasserted: 588a3702c1fSVernon Mauery { 589a3702c1fSVernon Mauery if (!mtm.revertFanPWM) 590a3702c1fSVernon Mauery { 591a3702c1fSVernon Mauery ret = mtm.disablePidControlService(true); 592a3702c1fSVernon Mauery if (ret < 0) 593a3702c1fSVernon Mauery { 5945e3bf557SAyushi Smriti return ipmi::responseUnspecifiedError(); 595a3702c1fSVernon Mauery } 596a3702c1fSVernon Mauery mtm.revertFanPWM = true; 597a3702c1fSVernon Mauery } 598a3702c1fSVernon Mauery mtm.revertTimer.start(revertTimeOut); 599a3702c1fSVernon Mauery std::string fanPwmInstancePath = 6005e3bf557SAyushi Smriti fanPwmPath + std::to_string(instance + 1); 601a3702c1fSVernon Mauery 6025e3bf557SAyushi Smriti ret = 6035e3bf557SAyushi Smriti mtm.setProperty(fanService, fanPwmInstancePath, fanIntf, 6045e3bf557SAyushi Smriti "Value", static_cast<double>(pwmValue)); 605a3702c1fSVernon Mauery if (ret < 0) 606a3702c1fSVernon Mauery { 6075e3bf557SAyushi Smriti return ipmi::responseUnspecifiedError(); 608a3702c1fSVernon Mauery } 609a3702c1fSVernon Mauery } 610a3702c1fSVernon Mauery break; 611a3702c1fSVernon Mauery default: 612a3702c1fSVernon Mauery { 6135e3bf557SAyushi Smriti return ipmi::responseInvalidFieldRequest(); 614a3702c1fSVernon Mauery } 615a3702c1fSVernon Mauery } 616a3702c1fSVernon Mauery } 617a3702c1fSVernon Mauery break; 618d872a4a4SAyushi Smriti case SmSignalSet::smSpeaker: 619d872a4a4SAyushi Smriti { 620d872a4a4SAyushi Smriti phosphor::logging::log<phosphor::logging::level::INFO>( 621d872a4a4SAyushi Smriti "Performing Speaker SmActionSet", 622d872a4a4SAyushi Smriti phosphor::logging::entry("ACTION=%d", 623d872a4a4SAyushi Smriti static_cast<uint8_t>(action))); 624d872a4a4SAyushi Smriti switch (action) 625d872a4a4SAyushi Smriti { 626d872a4a4SAyushi Smriti case SmActionSet::forceAsserted: 627d872a4a4SAyushi Smriti { 628d872a4a4SAyushi Smriti char beepDevName[] = "/dev/input/event0"; 629d872a4a4SAyushi Smriti if (mtm.mtmTestBeepFd != -1) 630d872a4a4SAyushi Smriti { 631d872a4a4SAyushi Smriti phosphor::logging::log<phosphor::logging::level::INFO>( 632d872a4a4SAyushi Smriti "mtm beep device is opened already!"); 633d872a4a4SAyushi Smriti // returning success as already beep is in progress 634d872a4a4SAyushi Smriti return ipmi::response(retCode); 635d872a4a4SAyushi Smriti } 636d872a4a4SAyushi Smriti 637d872a4a4SAyushi Smriti if ((mtm.mtmTestBeepFd = 638d872a4a4SAyushi Smriti ::open(beepDevName, O_RDWR | O_CLOEXEC)) < 0) 639d872a4a4SAyushi Smriti { 640d872a4a4SAyushi Smriti phosphor::logging::log<phosphor::logging::level::ERR>( 641d872a4a4SAyushi Smriti "Failed to open input device"); 642d872a4a4SAyushi Smriti return ipmi::responseUnspecifiedError(); 643d872a4a4SAyushi Smriti } 644d872a4a4SAyushi Smriti 645d872a4a4SAyushi Smriti struct input_event event; 646d872a4a4SAyushi Smriti event.type = EV_SND; 647d872a4a4SAyushi Smriti event.code = SND_TONE; 648d872a4a4SAyushi Smriti event.value = 2000; 649d872a4a4SAyushi Smriti 650d872a4a4SAyushi Smriti if (::write(mtm.mtmTestBeepFd, &event, 651d872a4a4SAyushi Smriti sizeof(struct input_event)) != 652d872a4a4SAyushi Smriti sizeof(struct input_event)) 653d872a4a4SAyushi Smriti { 654d872a4a4SAyushi Smriti phosphor::logging::log<phosphor::logging::level::ERR>( 655d872a4a4SAyushi Smriti "Failed to write a tone sound event"); 656d872a4a4SAyushi Smriti ::close(mtm.mtmTestBeepFd); 657d872a4a4SAyushi Smriti mtm.mtmTestBeepFd = -1; 658d872a4a4SAyushi Smriti return ipmi::responseUnspecifiedError(); 659d872a4a4SAyushi Smriti } 660d872a4a4SAyushi Smriti mtm.revertTimer.start(revertTimeOut); 661d872a4a4SAyushi Smriti } 662d872a4a4SAyushi Smriti break; 663d872a4a4SAyushi Smriti case SmActionSet::revert: 664d872a4a4SAyushi Smriti case SmActionSet::forceDeasserted: 665d872a4a4SAyushi Smriti { 666d872a4a4SAyushi Smriti if (mtm.mtmTestBeepFd != -1) 667d872a4a4SAyushi Smriti { 668d872a4a4SAyushi Smriti ::close(mtm.mtmTestBeepFd); 669d872a4a4SAyushi Smriti mtm.mtmTestBeepFd = -1; 670d872a4a4SAyushi Smriti } 671d872a4a4SAyushi Smriti } 672d872a4a4SAyushi Smriti break; 673d872a4a4SAyushi Smriti default: 674d872a4a4SAyushi Smriti { 675d872a4a4SAyushi Smriti return ipmi::responseInvalidFieldRequest(); 676d872a4a4SAyushi Smriti } 677d872a4a4SAyushi Smriti } 678d872a4a4SAyushi Smriti } 679d872a4a4SAyushi Smriti break; 6803594c6d6SRichard Marian Thomaiyar case SmSignalSet::smDiskFaultLed: 6813594c6d6SRichard Marian Thomaiyar { 6823594c6d6SRichard Marian Thomaiyar boost::system::error_code ec; 6833594c6d6SRichard Marian Thomaiyar using objPaths = std::vector<std::string>; 6843594c6d6SRichard Marian Thomaiyar std::string driveBasePath = 6853594c6d6SRichard Marian Thomaiyar "/xyz/openbmc_project/inventory/item/drive/"; 6863594c6d6SRichard Marian Thomaiyar static constexpr const char* driveLedIntf = 6873594c6d6SRichard Marian Thomaiyar "xyz.openbmc_project.Led.Group"; 6883594c6d6SRichard Marian Thomaiyar static constexpr const char* hsbpService = 6893594c6d6SRichard Marian Thomaiyar "xyz.openbmc_project.HsbpManager"; 6903594c6d6SRichard Marian Thomaiyar 6913594c6d6SRichard Marian Thomaiyar auto driveList = ctx->bus->yield_method_call<objPaths>( 6923594c6d6SRichard Marian Thomaiyar ctx->yield, ec, "xyz.openbmc_project.ObjectMapper", 6933594c6d6SRichard Marian Thomaiyar "/xyz/openbmc_project/object_mapper", 6943594c6d6SRichard Marian Thomaiyar "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 6953594c6d6SRichard Marian Thomaiyar driveBasePath, 0, std::array<const char*, 1>{driveLedIntf}); 6963594c6d6SRichard Marian Thomaiyar if (ec) 6973594c6d6SRichard Marian Thomaiyar { 6983594c6d6SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 6993594c6d6SRichard Marian Thomaiyar "Failed to query HSBP drive sub tree objects"); 7003594c6d6SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 7013594c6d6SRichard Marian Thomaiyar } 7023594c6d6SRichard Marian Thomaiyar std::string driveObjPath = 7033594c6d6SRichard Marian Thomaiyar driveBasePath + "Drive_" + std::to_string(instance + 1); 7043594c6d6SRichard Marian Thomaiyar if (std::find(driveList.begin(), driveList.end(), driveObjPath) == 7053594c6d6SRichard Marian Thomaiyar driveList.end()) 7063594c6d6SRichard Marian Thomaiyar { 7073594c6d6SRichard Marian Thomaiyar return ipmi::responseInvalidFieldRequest(); 7083594c6d6SRichard Marian Thomaiyar } 7093594c6d6SRichard Marian Thomaiyar bool driveLedState = false; 7103594c6d6SRichard Marian Thomaiyar switch (action) 7113594c6d6SRichard Marian Thomaiyar { 7123594c6d6SRichard Marian Thomaiyar case SmActionSet::forceAsserted: 7133594c6d6SRichard Marian Thomaiyar { 7143594c6d6SRichard Marian Thomaiyar driveLedState = true; 7153594c6d6SRichard Marian Thomaiyar } 7163594c6d6SRichard Marian Thomaiyar break; 7173594c6d6SRichard Marian Thomaiyar case SmActionSet::revert: 7183594c6d6SRichard Marian Thomaiyar { 7193594c6d6SRichard Marian Thomaiyar driveLedState = false; 7203594c6d6SRichard Marian Thomaiyar } 7213594c6d6SRichard Marian Thomaiyar break; 7223594c6d6SRichard Marian Thomaiyar case SmActionSet::forceDeasserted: 7233594c6d6SRichard Marian Thomaiyar { 7243594c6d6SRichard Marian Thomaiyar driveLedState = false; 7253594c6d6SRichard Marian Thomaiyar } 7263594c6d6SRichard Marian Thomaiyar break; 7273594c6d6SRichard Marian Thomaiyar default: 7283594c6d6SRichard Marian Thomaiyar { 7293594c6d6SRichard Marian Thomaiyar return ipmi::responseInvalidFieldRequest(); 7303594c6d6SRichard Marian Thomaiyar } 7313594c6d6SRichard Marian Thomaiyar } 7323594c6d6SRichard Marian Thomaiyar ret = mtm.setProperty(hsbpService, driveObjPath, driveLedIntf, 7333594c6d6SRichard Marian Thomaiyar "Asserted", driveLedState); 7343594c6d6SRichard Marian Thomaiyar if (ret < 0) 7353594c6d6SRichard Marian Thomaiyar { 7363594c6d6SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 7373594c6d6SRichard Marian Thomaiyar } 7383594c6d6SRichard Marian Thomaiyar } 7393594c6d6SRichard Marian Thomaiyar break; 740a3702c1fSVernon Mauery default: 741a3702c1fSVernon Mauery { 7425e3bf557SAyushi Smriti return ipmi::responseInvalidFieldRequest(); 743a3702c1fSVernon Mauery } 744a3702c1fSVernon Mauery } 7454cc10159SRichard Marian Thomaiyar if (retCode == ccSuccess) 7464cc10159SRichard Marian Thomaiyar { 747357ddc74SRichard Marian Thomaiyar resetMtmTimer(ctx); 7484cc10159SRichard Marian Thomaiyar } 7495e3bf557SAyushi Smriti return ipmi::response(retCode); 750a3702c1fSVernon Mauery } 751a3702c1fSVernon Mauery 752357ddc74SRichard Marian Thomaiyar ipmi::RspType<> mtmKeepAlive(ipmi::Context::ptr ctx, uint8_t reserved, 753666dd01cSRichard Marian Thomaiyar const std::array<char, 5>& intentionalSignature) 754666dd01cSRichard Marian Thomaiyar { 755e0511e5fSAyushi Smriti // mfg filter logic is used to allow MTM keep alive command only in 756e0511e5fSAyushi Smriti // manfacturing mode 757e0511e5fSAyushi Smriti 758666dd01cSRichard Marian Thomaiyar constexpr std::array<char, 5> signatureOk = {'I', 'N', 'T', 'E', 'L'}; 759666dd01cSRichard Marian Thomaiyar if (intentionalSignature != signatureOk || reserved != 0) 760666dd01cSRichard Marian Thomaiyar { 761666dd01cSRichard Marian Thomaiyar return ipmi::responseInvalidFieldRequest(); 762666dd01cSRichard Marian Thomaiyar } 763357ddc74SRichard Marian Thomaiyar return ipmi::response(resetMtmTimer(ctx)); 764666dd01cSRichard Marian Thomaiyar } 765666dd01cSRichard Marian Thomaiyar 766e0511e5fSAyushi Smriti static constexpr unsigned int makeCmdKey(unsigned int netFn, unsigned int cmd) 767e0511e5fSAyushi Smriti { 768e0511e5fSAyushi Smriti return (netFn << 8) | cmd; 769e0511e5fSAyushi Smriti } 770e0511e5fSAyushi Smriti 77185feb130SYong Li ipmi::Cc mfgFilterMessage(ipmi::message::Request::ptr request) 77285feb130SYong Li { 773e0511e5fSAyushi Smriti // Restricted commands, must be executed only in Manufacturing mode 774e0511e5fSAyushi Smriti switch (makeCmdKey(request->ctx->netFn, request->ctx->cmd)) 77585feb130SYong Li { 776e0511e5fSAyushi Smriti // i2c master write read command needs additional checking 777e0511e5fSAyushi Smriti case makeCmdKey(ipmi::netFnApp, ipmi::app::cmdMasterWriteRead): 77885feb130SYong Li if (request->payload.size() > 4) 77985feb130SYong Li { 780ae13ac62SRichard Marian Thomaiyar // Allow write data count > 1 only in Special mode 781ae13ac62SRichard Marian Thomaiyar if (mtm.getMfgMode() == SpecialMode::none) 78285feb130SYong Li { 78385feb130SYong Li return ipmi::ccInsufficientPrivilege; 78485feb130SYong Li } 78585feb130SYong Li } 7862d4a0198Sjayaprakash Mutyala return ipmi::ccSuccess; 787e0511e5fSAyushi Smriti case makeCmdKey(ipmi::netFnOemOne, 788e0511e5fSAyushi Smriti ipmi::intel::general::cmdGetSmSignal): 789e0511e5fSAyushi Smriti case makeCmdKey(ipmi::netFnOemOne, 790e0511e5fSAyushi Smriti ipmi::intel::general::cmdSetSmSignal): 791e0511e5fSAyushi Smriti case makeCmdKey(ipmi::netFnOemOne, 792e0511e5fSAyushi Smriti ipmi::intel::general::cmdMtmKeepAlive): 793e0511e5fSAyushi Smriti case makeCmdKey(ipmi::netFnOemOne, 794e0511e5fSAyushi Smriti ipmi::intel::general::cmdSetManufacturingData): 795e0511e5fSAyushi Smriti case makeCmdKey(ipmi::netFnOemOne, 796e0511e5fSAyushi Smriti ipmi::intel::general::cmdGetManufacturingData): 79727d2356eSVernon Mauery case makeCmdKey(ipmi::intel::netFnGeneral, 79827d2356eSVernon Mauery ipmi::intel::general::cmdSetFITcLayout): 799*06584cd0SArun P. Mohanan case makeCmdKey(ipmi::netFnOemOne, 800*06584cd0SArun P. Mohanan ipmi::intel::general::cmdMTMBMCFeatureControl): 801e0511e5fSAyushi Smriti case makeCmdKey(ipmi::netFnStorage, ipmi::storage::cmdWriteFruData): 8029a13daaeSAppaRao Puli case makeCmdKey(ipmi::netFnOemTwo, ipmi::intel::platform::cmdClearCMOS): 80385feb130SYong Li 804ae13ac62SRichard Marian Thomaiyar // Check for Special mode 805ae13ac62SRichard Marian Thomaiyar if (mtm.getMfgMode() == SpecialMode::none) 806e0511e5fSAyushi Smriti { 807e0511e5fSAyushi Smriti return ipmi::ccInvalidCommand; 808e0511e5fSAyushi Smriti } 8092d4a0198Sjayaprakash Mutyala return ipmi::ccSuccess; 8102d4a0198Sjayaprakash Mutyala case makeCmdKey(ipmi::netFnStorage, ipmi::storage::cmdDeleteSelEntry): 8112d4a0198Sjayaprakash Mutyala { 8122d4a0198Sjayaprakash Mutyala return ipmi::ccInvalidCommand; 8132d4a0198Sjayaprakash Mutyala } 814e0511e5fSAyushi Smriti } 81585feb130SYong Li return ipmi::ccSuccess; 81685feb130SYong Li } 81785feb130SYong Li 8181f0839c2SRichard Marian Thomaiyar static constexpr uint8_t maxEthSize = 6; 8191f0839c2SRichard Marian Thomaiyar static constexpr uint8_t maxSupportedEth = 3; 8201f0839c2SRichard Marian Thomaiyar static constexpr const char* factoryEthAddrBaseFileName = 8211f0839c2SRichard Marian Thomaiyar "/var/sofs/factory-settings/network/mac/eth"; 8221f0839c2SRichard Marian Thomaiyar 823357ddc74SRichard Marian Thomaiyar ipmi::RspType<> setManufacturingData(ipmi::Context::ptr ctx, uint8_t dataType, 8241f0839c2SRichard Marian Thomaiyar std::array<uint8_t, maxEthSize> ethData) 8251f0839c2SRichard Marian Thomaiyar { 8261f0839c2SRichard Marian Thomaiyar // mfg filter logic will restrict this command executing only in mfg mode. 8271f0839c2SRichard Marian Thomaiyar if (dataType >= maxSupportedEth) 8281f0839c2SRichard Marian Thomaiyar { 8291f0839c2SRichard Marian Thomaiyar return ipmi::responseParmOutOfRange(); 8301f0839c2SRichard Marian Thomaiyar } 8311f0839c2SRichard Marian Thomaiyar 8321f0839c2SRichard Marian Thomaiyar constexpr uint8_t invalidData = 0; 8331f0839c2SRichard Marian Thomaiyar constexpr uint8_t validData = 1; 8341f0839c2SRichard Marian Thomaiyar constexpr uint8_t ethAddrStrSize = 8351f0839c2SRichard Marian Thomaiyar 19; // XX:XX:XX:XX:XX:XX + \n + null termination; 8361f0839c2SRichard Marian Thomaiyar std::vector<uint8_t> buff(ethAddrStrSize); 8371f0839c2SRichard Marian Thomaiyar std::snprintf(reinterpret_cast<char*>(buff.data()), ethAddrStrSize, 8381f0839c2SRichard Marian Thomaiyar "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx\n", ethData.at(0), 8391f0839c2SRichard Marian Thomaiyar ethData.at(1), ethData.at(2), ethData.at(3), ethData.at(4), 8401f0839c2SRichard Marian Thomaiyar ethData.at(5)); 8411f0839c2SRichard Marian Thomaiyar std::ofstream oEthFile(factoryEthAddrBaseFileName + 8421f0839c2SRichard Marian Thomaiyar std::to_string(dataType), 8431f0839c2SRichard Marian Thomaiyar std::ofstream::out); 8441f0839c2SRichard Marian Thomaiyar if (!oEthFile.good()) 8451f0839c2SRichard Marian Thomaiyar { 8461f0839c2SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 8471f0839c2SRichard Marian Thomaiyar } 8481f0839c2SRichard Marian Thomaiyar 8491f0839c2SRichard Marian Thomaiyar oEthFile << reinterpret_cast<char*>(buff.data()); 8506d83e4eeSJohnathan Mantey oEthFile.flush(); 8511f0839c2SRichard Marian Thomaiyar oEthFile.close(); 8521f0839c2SRichard Marian Thomaiyar 853357ddc74SRichard Marian Thomaiyar resetMtmTimer(ctx); 8541f0839c2SRichard Marian Thomaiyar return ipmi::responseSuccess(); 8551f0839c2SRichard Marian Thomaiyar } 8561f0839c2SRichard Marian Thomaiyar 8571f0839c2SRichard Marian Thomaiyar ipmi::RspType<uint8_t, std::array<uint8_t, maxEthSize>> 858357ddc74SRichard Marian Thomaiyar getManufacturingData(ipmi::Context::ptr ctx, uint8_t dataType) 8591f0839c2SRichard Marian Thomaiyar { 8601f0839c2SRichard Marian Thomaiyar // mfg filter logic will restrict this command executing only in mfg mode. 8611f0839c2SRichard Marian Thomaiyar if (dataType >= maxSupportedEth) 8621f0839c2SRichard Marian Thomaiyar { 8631f0839c2SRichard Marian Thomaiyar return ipmi::responseParmOutOfRange(); 8641f0839c2SRichard Marian Thomaiyar } 8651f0839c2SRichard Marian Thomaiyar std::array<uint8_t, maxEthSize> ethData{0}; 8661f0839c2SRichard Marian Thomaiyar constexpr uint8_t invalidData = 0; 8671f0839c2SRichard Marian Thomaiyar constexpr uint8_t validData = 1; 8681f0839c2SRichard Marian Thomaiyar 8691f0839c2SRichard Marian Thomaiyar std::ifstream iEthFile(factoryEthAddrBaseFileName + 8701f0839c2SRichard Marian Thomaiyar std::to_string(dataType), 8711f0839c2SRichard Marian Thomaiyar std::ifstream::in); 8721f0839c2SRichard Marian Thomaiyar if (!iEthFile.good()) 8731f0839c2SRichard Marian Thomaiyar { 8741f0839c2SRichard Marian Thomaiyar return ipmi::responseSuccess(invalidData, ethData); 8751f0839c2SRichard Marian Thomaiyar } 8761f0839c2SRichard Marian Thomaiyar std::string ethStr; 8771f0839c2SRichard Marian Thomaiyar iEthFile >> ethStr; 8781f0839c2SRichard Marian Thomaiyar uint8_t* data = ethData.data(); 8791f0839c2SRichard Marian Thomaiyar std::sscanf(ethStr.c_str(), "%02hhx:%02hhx:%02hhx:%02hhx:%02hhx:%02hhx", 8801f0839c2SRichard Marian Thomaiyar data, (data + 1), (data + 2), (data + 3), (data + 4), 8811f0839c2SRichard Marian Thomaiyar (data + 5)); 8821f0839c2SRichard Marian Thomaiyar 883357ddc74SRichard Marian Thomaiyar resetMtmTimer(ctx); 8841f0839c2SRichard Marian Thomaiyar return ipmi::responseSuccess(validData, ethData); 8851f0839c2SRichard Marian Thomaiyar } 8861f0839c2SRichard Marian Thomaiyar 887f267a67dSYong Li /** @brief implements slot master write read IPMI command which can be used for 888f267a67dSYong Li * low-level I2C/SMBus write, read or write-read access for PCIE slots 889f267a67dSYong Li * @param reserved - skip 6 bit 890f267a67dSYong Li * @param addressType - address type 891f267a67dSYong Li * @param bbSlotNum - baseboard slot number 892f267a67dSYong Li * @param riserSlotNum - riser slot number 893f267a67dSYong Li * @param reserved2 - skip 2 bit 894f267a67dSYong Li * @param slaveAddr - slave address 895f267a67dSYong Li * @param readCount - number of bytes to be read 896f267a67dSYong Li * @param writeData - data to be written 897f267a67dSYong Li * 898f267a67dSYong Li * @returns IPMI completion code plus response data 899f267a67dSYong Li */ 900f267a67dSYong Li ipmi::RspType<std::vector<uint8_t>> 901f267a67dSYong Li appSlotI2CMasterWriteRead(uint6_t reserved, uint2_t addressType, 902f267a67dSYong Li uint3_t bbSlotNum, uint3_t riserSlotNum, 903f267a67dSYong Li uint2_t resvered2, uint8_t slaveAddr, 904f267a67dSYong Li uint8_t readCount, std::vector<uint8_t> writeData) 905f267a67dSYong Li { 906f267a67dSYong Li const size_t writeCount = writeData.size(); 907f267a67dSYong Li std::string i2cBus; 908f267a67dSYong Li if (addressType == slotAddressTypeBus) 909f267a67dSYong Li { 910f267a67dSYong Li std::string path = "/dev/i2c-mux/Riser_" + 911f267a67dSYong Li std::to_string(static_cast<uint8_t>(bbSlotNum)) + 912f267a67dSYong Li "_Mux/Pcie_Slot_" + 913f267a67dSYong Li std::to_string(static_cast<uint8_t>(riserSlotNum)); 914f267a67dSYong Li 915f267a67dSYong Li if (std::filesystem::exists(path) && std::filesystem::is_symlink(path)) 916f267a67dSYong Li { 917f267a67dSYong Li i2cBus = std::filesystem::read_symlink(path); 918f267a67dSYong Li } 919f267a67dSYong Li else 920f267a67dSYong Li { 921f267a67dSYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 922f267a67dSYong Li "Master write read command: Cannot get BusID"); 923f267a67dSYong Li return ipmi::responseInvalidFieldRequest(); 924f267a67dSYong Li } 925f267a67dSYong Li } 926f267a67dSYong Li else if (addressType == slotAddressTypeUniqueid) 927f267a67dSYong Li { 928f267a67dSYong Li i2cBus = "/dev/i2c-" + 929f267a67dSYong Li std::to_string(static_cast<uint8_t>(bbSlotNum) | 930f267a67dSYong Li (static_cast<uint8_t>(riserSlotNum) << 3)); 931f267a67dSYong Li } 932f267a67dSYong Li else 933f267a67dSYong Li { 934f267a67dSYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 935f267a67dSYong Li "Master write read command: invalid request"); 936f267a67dSYong Li return ipmi::responseInvalidFieldRequest(); 937f267a67dSYong Li } 938f267a67dSYong Li 939f267a67dSYong Li // Allow single byte write as it is offset byte to read the data, rest allow 940ae13ac62SRichard Marian Thomaiyar // only in Special mode. 941f267a67dSYong Li if (writeCount > 1) 942f267a67dSYong Li { 943ae13ac62SRichard Marian Thomaiyar if (mtm.getMfgMode() == SpecialMode::none) 944f267a67dSYong Li { 945f267a67dSYong Li return ipmi::responseInsufficientPrivilege(); 946f267a67dSYong Li } 947f267a67dSYong Li } 948f267a67dSYong Li 949f267a67dSYong Li if (readCount > slotI2CMaxReadSize) 950f267a67dSYong Li { 951f267a67dSYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 952f267a67dSYong Li "Master write read command: Read count exceeds limit"); 953f267a67dSYong Li return ipmi::responseParmOutOfRange(); 954f267a67dSYong Li } 955f267a67dSYong Li 956f267a67dSYong Li if (!readCount && !writeCount) 957f267a67dSYong Li { 958f267a67dSYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 959f267a67dSYong Li "Master write read command: Read & write count are 0"); 960f267a67dSYong Li return ipmi::responseInvalidFieldRequest(); 961f267a67dSYong Li } 962f267a67dSYong Li 963f267a67dSYong Li std::vector<uint8_t> readBuf(readCount); 964f267a67dSYong Li 965f267a67dSYong Li ipmi::Cc retI2C = ipmi::i2cWriteRead(i2cBus, slaveAddr, writeData, readBuf); 966f267a67dSYong Li if (retI2C != ipmi::ccSuccess) 967f267a67dSYong Li { 968f267a67dSYong Li return ipmi::response(retI2C); 969f267a67dSYong Li } 970f267a67dSYong Li 971f267a67dSYong Li return ipmi::responseSuccess(readBuf); 972f267a67dSYong Li } 973068b4f2cSYong Li 974068b4f2cSYong Li ipmi::RspType<> clearCMOS() 975068b4f2cSYong Li { 976d0d010b7SYong Li // There is an i2c device on bus 4, the slave address is 0x38. Based on the 977eaeb6cb0SYong Li // spec, writing 0x1 to address 0x61 on this device, will trigger the clear 978068b4f2cSYong Li // CMOS action. 979d0d010b7SYong Li constexpr uint8_t slaveAddr = 0x38; 980068b4f2cSYong Li std::string i2cBus = "/dev/i2c-4"; 981eaeb6cb0SYong Li std::vector<uint8_t> writeData = {0x61, 0x1}; 982068b4f2cSYong Li std::vector<uint8_t> readBuf(0); 983068b4f2cSYong Li 984068b4f2cSYong Li ipmi::Cc retI2C = ipmi::i2cWriteRead(i2cBus, slaveAddr, writeData, readBuf); 985068b4f2cSYong Li return ipmi::response(retI2C); 986068b4f2cSYong Li } 98727d2356eSVernon Mauery 98827d2356eSVernon Mauery ipmi::RspType<> setFITcLayout(uint32_t layout) 98927d2356eSVernon Mauery { 99027d2356eSVernon Mauery static constexpr const char* factoryFITcLayout = 99127d2356eSVernon Mauery "/var/sofs/factory-settings/layout/fitc"; 99227d2356eSVernon Mauery std::filesystem::path fitcDir = 99327d2356eSVernon Mauery std::filesystem::path(factoryFITcLayout).parent_path(); 99427d2356eSVernon Mauery std::error_code ec; 99527d2356eSVernon Mauery std::filesystem::create_directories(fitcDir, ec); 99627d2356eSVernon Mauery if (ec) 99727d2356eSVernon Mauery { 99827d2356eSVernon Mauery return ipmi::responseUnspecifiedError(); 99927d2356eSVernon Mauery } 100027d2356eSVernon Mauery try 100127d2356eSVernon Mauery { 100227d2356eSVernon Mauery std::ofstream file(factoryFITcLayout); 100327d2356eSVernon Mauery file << layout; 100427d2356eSVernon Mauery file.flush(); 100527d2356eSVernon Mauery file.close(); 100627d2356eSVernon Mauery } 100727d2356eSVernon Mauery catch (const std::exception& e) 100827d2356eSVernon Mauery { 100927d2356eSVernon Mauery return ipmi::responseUnspecifiedError(); 101027d2356eSVernon Mauery } 101127d2356eSVernon Mauery 101227d2356eSVernon Mauery return ipmi::responseSuccess(); 101327d2356eSVernon Mauery } 101427d2356eSVernon Mauery 1015*06584cd0SArun P. Mohanan static std::vector<std::string> 1016*06584cd0SArun P. Mohanan getMCTPServiceConfigPaths(ipmi::Context::ptr& ctx) 1017*06584cd0SArun P. Mohanan { 1018*06584cd0SArun P. Mohanan boost::system::error_code ec; 1019*06584cd0SArun P. Mohanan auto configPaths = ctx->bus->yield_method_call<std::vector<std::string>>( 1020*06584cd0SArun P. Mohanan ctx->yield, ec, "xyz.openbmc_project.ObjectMapper", 1021*06584cd0SArun P. Mohanan "/xyz/openbmc_project/object_mapper", 1022*06584cd0SArun P. Mohanan "xyz.openbmc_project.ObjectMapper", "GetSubTreePaths", 1023*06584cd0SArun P. Mohanan "/xyz/openbmc_project/inventory/system/board", 2, 1024*06584cd0SArun P. Mohanan std::array<const char*, 1>{ 1025*06584cd0SArun P. Mohanan "xyz.openbmc_project.Configuration.MctpConfiguration"}); 1026*06584cd0SArun P. Mohanan if (ec) 1027*06584cd0SArun P. Mohanan { 1028*06584cd0SArun P. Mohanan throw std::runtime_error( 1029*06584cd0SArun P. Mohanan "Failed to query configuration sub tree objects"); 1030*06584cd0SArun P. Mohanan } 1031*06584cd0SArun P. Mohanan return configPaths; 1032*06584cd0SArun P. Mohanan } 1033*06584cd0SArun P. Mohanan 1034*06584cd0SArun P. Mohanan static ipmi::RspType<> startOrStopService(ipmi::Context::ptr& ctx, 1035*06584cd0SArun P. Mohanan const uint8_t enable, 1036*06584cd0SArun P. Mohanan const std::string& serviceName) 1037*06584cd0SArun P. Mohanan { 1038*06584cd0SArun P. Mohanan constexpr bool runtimeOnly = false; 1039*06584cd0SArun P. Mohanan constexpr bool force = false; 1040*06584cd0SArun P. Mohanan 1041*06584cd0SArun P. Mohanan boost::system::error_code ec; 1042*06584cd0SArun P. Mohanan switch (enable) 1043*06584cd0SArun P. Mohanan { 1044*06584cd0SArun P. Mohanan case ipmi::SupportedFeatureActions::stop: 1045*06584cd0SArun P. Mohanan ctx->bus->yield_method_call(ctx->yield, ec, systemDService, 1046*06584cd0SArun P. Mohanan systemDObjPath, systemDMgrIntf, 1047*06584cd0SArun P. Mohanan "StopUnit", serviceName, "replace"); 1048*06584cd0SArun P. Mohanan break; 1049*06584cd0SArun P. Mohanan case ipmi::SupportedFeatureActions::start: 1050*06584cd0SArun P. Mohanan ctx->bus->yield_method_call(ctx->yield, ec, systemDService, 1051*06584cd0SArun P. Mohanan systemDObjPath, systemDMgrIntf, 1052*06584cd0SArun P. Mohanan "StartUnit", serviceName, "replace"); 1053*06584cd0SArun P. Mohanan break; 1054*06584cd0SArun P. Mohanan case ipmi::SupportedFeatureActions::disable: 1055*06584cd0SArun P. Mohanan ctx->bus->yield_method_call( 1056*06584cd0SArun P. Mohanan ctx->yield, ec, systemDService, systemDObjPath, systemDMgrIntf, 1057*06584cd0SArun P. Mohanan "MaskUnitFiles", 1058*06584cd0SArun P. Mohanan std::array<const char*, 1>{serviceName.c_str()}, runtimeOnly, 1059*06584cd0SArun P. Mohanan force); 1060*06584cd0SArun P. Mohanan ctx->bus->yield_method_call( 1061*06584cd0SArun P. Mohanan ctx->yield, ec, systemDService, systemDObjPath, systemDMgrIntf, 1062*06584cd0SArun P. Mohanan "DisableUnitFiles", 1063*06584cd0SArun P. Mohanan std::array<const char*, 1>{serviceName.c_str()}, runtimeOnly); 1064*06584cd0SArun P. Mohanan break; 1065*06584cd0SArun P. Mohanan case ipmi::SupportedFeatureActions::enable: 1066*06584cd0SArun P. Mohanan ctx->bus->yield_method_call( 1067*06584cd0SArun P. Mohanan ctx->yield, ec, systemDService, systemDObjPath, systemDMgrIntf, 1068*06584cd0SArun P. Mohanan "UnmaskUnitFiles", 1069*06584cd0SArun P. Mohanan std::array<const char*, 1>{serviceName.c_str()}, runtimeOnly); 1070*06584cd0SArun P. Mohanan ctx->bus->yield_method_call( 1071*06584cd0SArun P. Mohanan ctx->yield, ec, systemDService, systemDObjPath, systemDMgrIntf, 1072*06584cd0SArun P. Mohanan "EnableUnitFiles", 1073*06584cd0SArun P. Mohanan std::array<const char*, 1>{serviceName.c_str()}, runtimeOnly, 1074*06584cd0SArun P. Mohanan force); 1075*06584cd0SArun P. Mohanan break; 1076*06584cd0SArun P. Mohanan default: 1077*06584cd0SArun P. Mohanan phosphor::logging::log<phosphor::logging::level::WARNING>( 1078*06584cd0SArun P. Mohanan "ERROR: Invalid feature action selected", 1079*06584cd0SArun P. Mohanan phosphor::logging::entry("ACTION=%d", enable)); 1080*06584cd0SArun P. Mohanan return ipmi::responseInvalidFieldRequest(); 1081*06584cd0SArun P. Mohanan } 1082*06584cd0SArun P. Mohanan if (ec) 1083*06584cd0SArun P. Mohanan { 1084*06584cd0SArun P. Mohanan phosphor::logging::log<phosphor::logging::level::WARNING>( 1085*06584cd0SArun P. Mohanan "ERROR: Service start or stop failed", 1086*06584cd0SArun P. Mohanan phosphor::logging::entry("SERVICE=%s", serviceName.c_str())); 1087*06584cd0SArun P. Mohanan return ipmi::responseUnspecifiedError(); 1088*06584cd0SArun P. Mohanan } 1089*06584cd0SArun P. Mohanan return ipmi::responseSuccess(); 1090*06584cd0SArun P. Mohanan } 1091*06584cd0SArun P. Mohanan 1092*06584cd0SArun P. Mohanan static std::string getMCTPServiceName(const std::string& objectPath) 1093*06584cd0SArun P. Mohanan { 1094*06584cd0SArun P. Mohanan const auto serviceArgument = boost::algorithm::replace_all_copy( 1095*06584cd0SArun P. Mohanan boost::algorithm::replace_first_copy( 1096*06584cd0SArun P. Mohanan objectPath, "/xyz/openbmc_project/inventory/system/board/", ""), 1097*06584cd0SArun P. Mohanan "/", "_2f"); 1098*06584cd0SArun P. Mohanan std::string unitName = 1099*06584cd0SArun P. Mohanan "xyz.openbmc_project.mctpd@" + serviceArgument + ".service"; 1100*06584cd0SArun P. Mohanan return unitName; 1101*06584cd0SArun P. Mohanan } 1102*06584cd0SArun P. Mohanan 1103*06584cd0SArun P. Mohanan static ipmi::RspType<> handleMCTPFeature(ipmi::Context::ptr& ctx, 1104*06584cd0SArun P. Mohanan const uint8_t enable, 1105*06584cd0SArun P. Mohanan const std::string& binding) 1106*06584cd0SArun P. Mohanan { 1107*06584cd0SArun P. Mohanan std::vector<std::string> configPaths; 1108*06584cd0SArun P. Mohanan try 1109*06584cd0SArun P. Mohanan { 1110*06584cd0SArun P. Mohanan configPaths = getMCTPServiceConfigPaths(ctx); 1111*06584cd0SArun P. Mohanan } 1112*06584cd0SArun P. Mohanan catch (const std::exception& e) 1113*06584cd0SArun P. Mohanan { 1114*06584cd0SArun P. Mohanan phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 1115*06584cd0SArun P. Mohanan return ipmi::responseUnspecifiedError(); 1116*06584cd0SArun P. Mohanan } 1117*06584cd0SArun P. Mohanan 1118*06584cd0SArun P. Mohanan for (const auto& objectPath : configPaths) 1119*06584cd0SArun P. Mohanan { 1120*06584cd0SArun P. Mohanan auto const pos = objectPath.find_last_of('/'); 1121*06584cd0SArun P. Mohanan if (binding == objectPath.substr(pos + 1)) 1122*06584cd0SArun P. Mohanan { 1123*06584cd0SArun P. Mohanan return startOrStopService(ctx, enable, 1124*06584cd0SArun P. Mohanan getMCTPServiceName(objectPath)); 1125*06584cd0SArun P. Mohanan } 1126*06584cd0SArun P. Mohanan } 1127*06584cd0SArun P. Mohanan return ipmi::responseSuccess(); 1128*06584cd0SArun P. Mohanan } 1129*06584cd0SArun P. Mohanan 1130*06584cd0SArun P. Mohanan /** @brief implements MTM BMC Feature Control IPMI command which can be 1131*06584cd0SArun P. Mohanan * used to enable or disable the supported BMC features. 1132*06584cd0SArun P. Mohanan * @param yield - context object that represents the currently executing 1133*06584cd0SArun P. Mohanan * coroutine 1134*06584cd0SArun P. Mohanan * @param feature - feature enum to enable or disable 1135*06584cd0SArun P. Mohanan * @param enable - enable or disable the feature 1136*06584cd0SArun P. Mohanan * @param featureArg - custom arguments for that feature 1137*06584cd0SArun P. Mohanan * @param reserved - reserved for future use 1138*06584cd0SArun P. Mohanan * 1139*06584cd0SArun P. Mohanan * @returns IPMI completion code 1140*06584cd0SArun P. Mohanan */ 1141*06584cd0SArun P. Mohanan ipmi::RspType<> mtmBMCFeatureControl(ipmi::Context::ptr ctx, 1142*06584cd0SArun P. Mohanan const uint8_t feature, 1143*06584cd0SArun P. Mohanan const uint8_t enable, 1144*06584cd0SArun P. Mohanan const uint8_t featureArg, 1145*06584cd0SArun P. Mohanan const uint16_t reserved) 1146*06584cd0SArun P. Mohanan { 1147*06584cd0SArun P. Mohanan if (reserved != 0) 1148*06584cd0SArun P. Mohanan { 1149*06584cd0SArun P. Mohanan return ipmi::responseInvalidFieldRequest(); 1150*06584cd0SArun P. Mohanan } 1151*06584cd0SArun P. Mohanan 1152*06584cd0SArun P. Mohanan switch (feature) 1153*06584cd0SArun P. Mohanan { 1154*06584cd0SArun P. Mohanan case ipmi::SupportedFeatureControls::mctp: 1155*06584cd0SArun P. Mohanan switch (featureArg) 1156*06584cd0SArun P. Mohanan { 1157*06584cd0SArun P. Mohanan case ipmi::SupportedMCTPBindings::mctpPCIe: 1158*06584cd0SArun P. Mohanan return handleMCTPFeature(ctx, enable, "MCTP_PCIe"); 1159*06584cd0SArun P. Mohanan case ipmi::SupportedMCTPBindings::mctpSMBusHSBP: 1160*06584cd0SArun P. Mohanan return handleMCTPFeature(ctx, enable, "MCTP_SMBus_HSBP"); 1161*06584cd0SArun P. Mohanan case ipmi::SupportedMCTPBindings::mctpSMBusPCIeSlot: 1162*06584cd0SArun P. Mohanan return handleMCTPFeature(ctx, enable, 1163*06584cd0SArun P. Mohanan "MCTP_SMBus_PCIe_slot"); 1164*06584cd0SArun P. Mohanan default: 1165*06584cd0SArun P. Mohanan return ipmi::responseInvalidFieldRequest(); 1166*06584cd0SArun P. Mohanan } 1167*06584cd0SArun P. Mohanan break; 1168*06584cd0SArun P. Mohanan default: 1169*06584cd0SArun P. Mohanan return ipmi::responseInvalidFieldRequest(); 1170*06584cd0SArun P. Mohanan } 1171*06584cd0SArun P. Mohanan return ipmi::responseSuccess(); 1172*06584cd0SArun P. Mohanan } 1173a3702c1fSVernon Mauery } // namespace ipmi 1174a3702c1fSVernon Mauery 1175a3702c1fSVernon Mauery void register_mtm_commands() __attribute__((constructor)); 1176a3702c1fSVernon Mauery void register_mtm_commands() 1177a3702c1fSVernon Mauery { 117838d2b5a6SJason M. Bills // <Get SM Signal> 117998bbf69aSVernon Mauery ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 118098bbf69aSVernon Mauery ipmi::intel::general::cmdGetSmSignal, 11815e3bf557SAyushi Smriti ipmi::Privilege::Admin, ipmi::appMTMGetSignal); 1182a3702c1fSVernon Mauery 118398bbf69aSVernon Mauery ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 118498bbf69aSVernon Mauery ipmi::intel::general::cmdSetSmSignal, 11855e3bf557SAyushi Smriti ipmi::Privilege::Admin, ipmi::appMTMSetSignal); 1186a3702c1fSVernon Mauery 118798bbf69aSVernon Mauery ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 118898bbf69aSVernon Mauery ipmi::intel::general::cmdMtmKeepAlive, 1189666dd01cSRichard Marian Thomaiyar ipmi::Privilege::Admin, ipmi::mtmKeepAlive); 1190666dd01cSRichard Marian Thomaiyar 119198bbf69aSVernon Mauery ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 119298bbf69aSVernon Mauery ipmi::intel::general::cmdSetManufacturingData, 11931f0839c2SRichard Marian Thomaiyar ipmi::Privilege::Admin, ipmi::setManufacturingData); 11941f0839c2SRichard Marian Thomaiyar 119598bbf69aSVernon Mauery ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 119698bbf69aSVernon Mauery ipmi::intel::general::cmdGetManufacturingData, 11971f0839c2SRichard Marian Thomaiyar ipmi::Privilege::Admin, ipmi::getManufacturingData); 11981f0839c2SRichard Marian Thomaiyar 119927d2356eSVernon Mauery ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 120027d2356eSVernon Mauery ipmi::intel::general::cmdSetFITcLayout, 120127d2356eSVernon Mauery ipmi::Privilege::Admin, ipmi::setFITcLayout); 120227d2356eSVernon Mauery 1203*06584cd0SArun P. Mohanan ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnGeneral, 1204*06584cd0SArun P. Mohanan ipmi::intel::general::cmdMTMBMCFeatureControl, 1205*06584cd0SArun P. Mohanan ipmi::Privilege::Admin, ipmi::mtmBMCFeatureControl); 1206*06584cd0SArun P. Mohanan 120798bbf69aSVernon Mauery ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 120898bbf69aSVernon Mauery ipmi::intel::general::cmdSlotI2CMasterWriteRead, 120998bbf69aSVernon Mauery ipmi::Privilege::Admin, 121098bbf69aSVernon Mauery ipmi::appSlotI2CMasterWriteRead); 1211f267a67dSYong Li 1212068b4f2cSYong Li ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnPlatform, 1213068b4f2cSYong Li ipmi::intel::platform::cmdClearCMOS, 1214068b4f2cSYong Li ipmi::Privilege::Admin, ipmi::clearCMOS); 1215068b4f2cSYong Li 121698bbf69aSVernon Mauery ipmi::registerFilter(ipmi::prioOemBase, 121785feb130SYong Li [](ipmi::message::Request::ptr request) { 121885feb130SYong Li return ipmi::mfgFilterMessage(request); 121985feb130SYong Li }); 1220a3702c1fSVernon Mauery } 1221