1a835eaa0SJia, Chunhui /* 2a835eaa0SJia, Chunhui // Copyright (c) 2018 Intel Corporation 3a835eaa0SJia, Chunhui // 4a835eaa0SJia, Chunhui // Licensed under the Apache License, Version 2.0 (the "License"); 5a835eaa0SJia, Chunhui // you may not use this file except in compliance with the License. 6a835eaa0SJia, Chunhui // You may obtain a copy of the License at 7a835eaa0SJia, Chunhui // 8a835eaa0SJia, Chunhui // http://www.apache.org/licenses/LICENSE-2.0 9a835eaa0SJia, Chunhui // 10a835eaa0SJia, Chunhui // Unless required by applicable law or agreed to in writing, software 11a835eaa0SJia, Chunhui // distributed under the License is distributed on an "AS IS" BASIS, 12a835eaa0SJia, Chunhui // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13a835eaa0SJia, Chunhui // See the License for the specific language governing permissions and 14a835eaa0SJia, Chunhui // limitations under the License. 15a835eaa0SJia, Chunhui */ 16a835eaa0SJia, Chunhui 1764796041SJason M. Bills #include "xyz/openbmc_project/Common/error.hpp" 1845f04988SKuiying Wang #include "xyz/openbmc_project/Led/Physical/server.hpp" 1964796041SJason M. Bills 20cc49b54bSJia, Chunhui #include <systemd/sd-journal.h> 21a835eaa0SJia, Chunhui 22a835eaa0SJia, Chunhui #include <array> 2391244a6aSJames Feist #include <boost/container/flat_map.hpp> 2423737fe3SYong Li #include <boost/process/child.hpp> 2523737fe3SYong Li #include <boost/process/io.hpp> 2639736d59SChen Yugang #include <com/intel/Control/NMISource/server.hpp> 270669d193SYong Li #include <com/intel/Control/OCOTShutdownPolicy/server.hpp> 2864796041SJason M. Bills #include <commandutils.hpp> 294ac799d7SVernon Mauery #include <filesystem> 30a835eaa0SJia, Chunhui #include <iostream> 31cc49b54bSJia, Chunhui #include <ipmid/api.hpp> 325480ef62SVernon Mauery #include <ipmid/utils.hpp> 3363efafacSJames Feist #include <nlohmann/json.hpp> 34a835eaa0SJia, Chunhui #include <oemcommands.hpp> 35a835eaa0SJia, Chunhui #include <phosphor-logging/log.hpp> 36a835eaa0SJia, Chunhui #include <sdbusplus/bus.hpp> 37d509eb91SSuryakanth Sekar #include <sdbusplus/message/types.hpp> 38a835eaa0SJia, Chunhui #include <string> 3991244a6aSJames Feist #include <variant> 40a835eaa0SJia, Chunhui #include <vector> 414f7e76bbSChen,Yugang #include <xyz/openbmc_project/Control/Boot/Mode/server.hpp> 424f7e76bbSChen,Yugang #include <xyz/openbmc_project/Control/Boot/Source/server.hpp> 43773703a5SCheng C Yang #include <xyz/openbmc_project/Control/PowerSupplyRedundancy/server.hpp> 44d801e463SRichard Marian Thomaiyar #include <xyz/openbmc_project/Control/Security/RestrictionMode/server.hpp> 45a835eaa0SJia, Chunhui 46a835eaa0SJia, Chunhui namespace ipmi 47a835eaa0SJia, Chunhui { 4864796041SJason M. Bills static void registerOEMFunctions() __attribute__((constructor)); 494ac799d7SVernon Mauery 5064796041SJason M. Bills static constexpr size_t maxFRUStringLength = 0x3F; 51a835eaa0SJia, Chunhui 52d509eb91SSuryakanth Sekar static constexpr auto ethernetIntf = 53d509eb91SSuryakanth Sekar "xyz.openbmc_project.Network.EthernetInterface"; 54d509eb91SSuryakanth Sekar static constexpr auto networkIPIntf = "xyz.openbmc_project.Network.IP"; 55d509eb91SSuryakanth Sekar static constexpr auto networkService = "xyz.openbmc_project.Network"; 56d509eb91SSuryakanth Sekar static constexpr auto networkRoot = "/xyz/openbmc_project/network"; 57d509eb91SSuryakanth Sekar 5839736d59SChen Yugang static constexpr const char* oemNmiSourceIntf = "com.intel.Control.NMISource"; 5939736d59SChen Yugang static constexpr const char* oemNmiSourceObjPath = 6039736d59SChen Yugang "/com/intel/control/NMISource"; 6139736d59SChen Yugang static constexpr const char* oemNmiBmcSourceObjPathProp = "BMCSource"; 6239736d59SChen Yugang static constexpr const char* oemNmiEnabledObjPathProp = "Enabled"; 6339736d59SChen Yugang 6463efafacSJames Feist static constexpr const char* dimmOffsetFile = "/var/lib/ipmi/ipmi_dimms.json"; 6563efafacSJames Feist 6639736d59SChen Yugang enum class NmiSource : uint8_t 6739736d59SChen Yugang { 6839736d59SChen Yugang none = 0, 6939736d59SChen Yugang fpBtn = 1, 7039736d59SChen Yugang wdPreTimeout = 2, 7139736d59SChen Yugang pefMatch = 3, 7239736d59SChen Yugang chassisCmd = 4, 7339736d59SChen Yugang memoryError = 5, 7439736d59SChen Yugang pciSerrPerr = 6, 7539736d59SChen Yugang southbridgeNmi = 7, 7639736d59SChen Yugang chipsetNmi = 8, 7739736d59SChen Yugang }; 7839736d59SChen Yugang 79d801e463SRichard Marian Thomaiyar static constexpr const char* restricionModeService = 80d801e463SRichard Marian Thomaiyar "xyz.openbmc_project.RestrictionMode.Manager"; 81d801e463SRichard Marian Thomaiyar static constexpr const char* restricionModeBasePath = 82d801e463SRichard Marian Thomaiyar "/xyz/openbmc_project/control/security/restriction_mode"; 83d801e463SRichard Marian Thomaiyar static constexpr const char* restricionModeIntf = 84d801e463SRichard Marian Thomaiyar "xyz.openbmc_project.Control.Security.RestrictionMode"; 85d801e463SRichard Marian Thomaiyar static constexpr const char* restricionModeProperty = "RestrictionMode"; 86d801e463SRichard Marian Thomaiyar 87d801e463SRichard Marian Thomaiyar static constexpr const char* specialModeService = 88d801e463SRichard Marian Thomaiyar "xyz.openbmc_project.SpecialMode"; 89d801e463SRichard Marian Thomaiyar static constexpr const char* specialModeBasePath = 90*a7b74288SRichard Marian Thomaiyar "/xyz/openbmc_project/security/special_mode"; 91d801e463SRichard Marian Thomaiyar static constexpr const char* specialModeIntf = 92d801e463SRichard Marian Thomaiyar "xyz.openbmc_project.Security.SpecialMode"; 93d801e463SRichard Marian Thomaiyar static constexpr const char* specialModeProperty = "SpecialMode"; 94d801e463SRichard Marian Thomaiyar 95d801e463SRichard Marian Thomaiyar static constexpr const char* dBusPropertyIntf = 96d801e463SRichard Marian Thomaiyar "org.freedesktop.DBus.Properties"; 97d801e463SRichard Marian Thomaiyar static constexpr const char* dBusPropertyGetMethod = "Get"; 98d801e463SRichard Marian Thomaiyar static constexpr const char* dBusPropertySetMethod = "Set"; 99d801e463SRichard Marian Thomaiyar 100a835eaa0SJia, Chunhui // return code: 0 successful 101a835eaa0SJia, Chunhui int8_t getChassisSerialNumber(sdbusplus::bus::bus& bus, std::string& serial) 102a835eaa0SJia, Chunhui { 103a835eaa0SJia, Chunhui std::string objpath = "/xyz/openbmc_project/FruDevice"; 104a835eaa0SJia, Chunhui std::string intf = "xyz.openbmc_project.FruDeviceManager"; 105a835eaa0SJia, Chunhui std::string service = getService(bus, intf, objpath); 106a835eaa0SJia, Chunhui ObjectValueTree valueTree = getManagedObjects(bus, service, "/"); 107a835eaa0SJia, Chunhui if (valueTree.empty()) 108a835eaa0SJia, Chunhui { 109a835eaa0SJia, Chunhui phosphor::logging::log<phosphor::logging::level::ERR>( 110a835eaa0SJia, Chunhui "No object implements interface", 111a835eaa0SJia, Chunhui phosphor::logging::entry("INTF=%s", intf.c_str())); 112a835eaa0SJia, Chunhui return -1; 113a835eaa0SJia, Chunhui } 114a835eaa0SJia, Chunhui 11564796041SJason M. Bills for (const auto& item : valueTree) 116a835eaa0SJia, Chunhui { 117a835eaa0SJia, Chunhui auto interface = item.second.find("xyz.openbmc_project.FruDevice"); 118a835eaa0SJia, Chunhui if (interface == item.second.end()) 119a835eaa0SJia, Chunhui { 120a835eaa0SJia, Chunhui continue; 121a835eaa0SJia, Chunhui } 122a835eaa0SJia, Chunhui 123a835eaa0SJia, Chunhui auto property = interface->second.find("CHASSIS_SERIAL_NUMBER"); 124a835eaa0SJia, Chunhui if (property == interface->second.end()) 125a835eaa0SJia, Chunhui { 126a835eaa0SJia, Chunhui continue; 127a835eaa0SJia, Chunhui } 128a835eaa0SJia, Chunhui 129a835eaa0SJia, Chunhui try 130a835eaa0SJia, Chunhui { 131a835eaa0SJia, Chunhui Value variant = property->second; 1328166c8d7SVernon Mauery std::string& result = std::get<std::string>(variant); 13364796041SJason M. Bills if (result.size() > maxFRUStringLength) 134a835eaa0SJia, Chunhui { 135a835eaa0SJia, Chunhui phosphor::logging::log<phosphor::logging::level::ERR>( 136a835eaa0SJia, Chunhui "FRU serial number exceed maximum length"); 137a835eaa0SJia, Chunhui return -1; 138a835eaa0SJia, Chunhui } 139a835eaa0SJia, Chunhui serial = result; 140a835eaa0SJia, Chunhui return 0; 141a835eaa0SJia, Chunhui } 1428166c8d7SVernon Mauery catch (std::bad_variant_access& e) 143a835eaa0SJia, Chunhui { 14464796041SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 145a835eaa0SJia, Chunhui return -1; 146a835eaa0SJia, Chunhui } 147a835eaa0SJia, Chunhui } 148a835eaa0SJia, Chunhui return -1; 149a835eaa0SJia, Chunhui } 15064796041SJason M. Bills 151a835eaa0SJia, Chunhui ipmi_ret_t ipmiOEMWildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 152a835eaa0SJia, Chunhui ipmi_request_t request, ipmi_response_t response, 15364796041SJason M. Bills ipmi_data_len_t dataLen, ipmi_context_t context) 154a835eaa0SJia, Chunhui { 15564796041SJason M. Bills printCommand(+netfn, +cmd); 156a835eaa0SJia, Chunhui // Status code. 157a835eaa0SJia, Chunhui ipmi_ret_t rc = IPMI_CC_INVALID; 15864796041SJason M. Bills *dataLen = 0; 159a835eaa0SJia, Chunhui return rc; 160a835eaa0SJia, Chunhui } 161a835eaa0SJia, Chunhui 162a835eaa0SJia, Chunhui // Returns the Chassis Identifier (serial #) 163a835eaa0SJia, Chunhui ipmi_ret_t ipmiOEMGetChassisIdentifier(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 164a835eaa0SJia, Chunhui ipmi_request_t request, 165a835eaa0SJia, Chunhui ipmi_response_t response, 16664796041SJason M. Bills ipmi_data_len_t dataLen, 167a835eaa0SJia, Chunhui ipmi_context_t context) 168a835eaa0SJia, Chunhui { 169a835eaa0SJia, Chunhui std::string serial; 17064796041SJason M. Bills if (*dataLen != 0) // invalid request if there are extra parameters 171a835eaa0SJia, Chunhui { 17264796041SJason M. Bills *dataLen = 0; 173a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID; 174a835eaa0SJia, Chunhui } 17515419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 17615419dd5SVernon Mauery if (getChassisSerialNumber(*dbus, serial) == 0) 177a835eaa0SJia, Chunhui { 17864796041SJason M. Bills *dataLen = serial.size(); // length will never exceed response length 179a835eaa0SJia, Chunhui // as it is checked in getChassisSerialNumber 180a835eaa0SJia, Chunhui char* resp = static_cast<char*>(response); 18164796041SJason M. Bills serial.copy(resp, *dataLen); 182a835eaa0SJia, Chunhui return IPMI_CC_OK; 183a835eaa0SJia, Chunhui } 18464796041SJason M. Bills *dataLen = 0; 185a835eaa0SJia, Chunhui return IPMI_CC_RESPONSE_ERROR; 186a835eaa0SJia, Chunhui } 187a835eaa0SJia, Chunhui 188a835eaa0SJia, Chunhui ipmi_ret_t ipmiOEMSetSystemGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 189a835eaa0SJia, Chunhui ipmi_request_t request, 190a835eaa0SJia, Chunhui ipmi_response_t response, 19164796041SJason M. Bills ipmi_data_len_t dataLen, ipmi_context_t context) 192a835eaa0SJia, Chunhui { 193a835eaa0SJia, Chunhui static constexpr size_t safeBufferLength = 50; 194a835eaa0SJia, Chunhui char buf[safeBufferLength] = {0}; 195a835eaa0SJia, Chunhui GUIDData* Data = reinterpret_cast<GUIDData*>(request); 196a835eaa0SJia, Chunhui 19764796041SJason M. Bills if (*dataLen != sizeof(GUIDData)) // 16bytes 198a835eaa0SJia, Chunhui { 19964796041SJason M. Bills *dataLen = 0; 200a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID; 201a835eaa0SJia, Chunhui } 202a835eaa0SJia, Chunhui 20364796041SJason M. Bills *dataLen = 0; 204a835eaa0SJia, Chunhui 205a835eaa0SJia, Chunhui snprintf( 206a835eaa0SJia, Chunhui buf, safeBufferLength, 207a835eaa0SJia, Chunhui "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", 208a835eaa0SJia, Chunhui Data->timeLow4, Data->timeLow3, Data->timeLow2, Data->timeLow1, 209a835eaa0SJia, Chunhui Data->timeMid2, Data->timeMid1, Data->timeHigh2, Data->timeHigh1, 210a835eaa0SJia, Chunhui Data->clock2, Data->clock1, Data->node6, Data->node5, Data->node4, 211a835eaa0SJia, Chunhui Data->node3, Data->node2, Data->node1); 212a835eaa0SJia, Chunhui // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 213a835eaa0SJia, Chunhui std::string guid = buf; 214a835eaa0SJia, Chunhui 215a835eaa0SJia, Chunhui std::string objpath = "/xyz/openbmc_project/control/host0/systemGUID"; 216a835eaa0SJia, Chunhui std::string intf = "xyz.openbmc_project.Common.UUID"; 21715419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 21815419dd5SVernon Mauery std::string service = getService(*dbus, intf, objpath); 21915419dd5SVernon Mauery setDbusProperty(*dbus, service, objpath, intf, "UUID", guid); 220a835eaa0SJia, Chunhui return IPMI_CC_OK; 221a835eaa0SJia, Chunhui } 222a835eaa0SJia, Chunhui 223b02bf095SJason M. Bills ipmi::RspType<> ipmiOEMDisableBMCSystemReset(bool disableResetOnSMI, 224b02bf095SJason M. Bills uint7_t reserved1) 225b02bf095SJason M. Bills { 226b02bf095SJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); 227b02bf095SJason M. Bills 228b02bf095SJason M. Bills try 229b02bf095SJason M. Bills { 230b02bf095SJason M. Bills auto service = 231b02bf095SJason M. Bills ipmi::getService(*busp, bmcResetDisablesIntf, bmcResetDisablesPath); 232b02bf095SJason M. Bills ipmi::setDbusProperty(*busp, service, bmcResetDisablesPath, 233b02bf095SJason M. Bills bmcResetDisablesIntf, "ResetOnSMI", 234b02bf095SJason M. Bills !disableResetOnSMI); 235b02bf095SJason M. Bills } 236b02bf095SJason M. Bills catch (std::exception& e) 237b02bf095SJason M. Bills { 238b02bf095SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>( 239b02bf095SJason M. Bills "Failed to set BMC reset disables", 240b02bf095SJason M. Bills phosphor::logging::entry("EXCEPTION=%s", e.what())); 241b02bf095SJason M. Bills return ipmi::responseUnspecifiedError(); 242b02bf095SJason M. Bills } 243b02bf095SJason M. Bills 244b02bf095SJason M. Bills return ipmi::responseSuccess(); 245b02bf095SJason M. Bills } 246b02bf095SJason M. Bills 247b02bf095SJason M. Bills ipmi::RspType<bool, // disableResetOnSMI 248b02bf095SJason M. Bills uint7_t // reserved 249b02bf095SJason M. Bills > 250b02bf095SJason M. Bills ipmiOEMGetBMCResetDisables() 251b02bf095SJason M. Bills { 252b02bf095SJason M. Bills bool disableResetOnSMI = true; 253b02bf095SJason M. Bills 254b02bf095SJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); 255b02bf095SJason M. Bills try 256b02bf095SJason M. Bills { 257b02bf095SJason M. Bills auto service = 258b02bf095SJason M. Bills ipmi::getService(*busp, bmcResetDisablesIntf, bmcResetDisablesPath); 259b02bf095SJason M. Bills Value variant = 260b02bf095SJason M. Bills ipmi::getDbusProperty(*busp, service, bmcResetDisablesPath, 261b02bf095SJason M. Bills bmcResetDisablesIntf, "ResetOnSMI"); 262b02bf095SJason M. Bills disableResetOnSMI = !std::get<bool>(variant); 263b02bf095SJason M. Bills } 264b02bf095SJason M. Bills catch (std::exception& e) 265b02bf095SJason M. Bills { 266b02bf095SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>( 267b02bf095SJason M. Bills "Failed to get BMC reset disables", 268b02bf095SJason M. Bills phosphor::logging::entry("EXCEPTION=%s", e.what())); 269b02bf095SJason M. Bills return ipmi::responseUnspecifiedError(); 270b02bf095SJason M. Bills } 271b02bf095SJason M. Bills 272b02bf095SJason M. Bills return ipmi::responseSuccess(disableResetOnSMI, 0); 273b02bf095SJason M. Bills } 274b02bf095SJason M. Bills 275a835eaa0SJia, Chunhui ipmi_ret_t ipmiOEMSetBIOSID(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 276a835eaa0SJia, Chunhui ipmi_request_t request, ipmi_response_t response, 277a835eaa0SJia, Chunhui ipmi_data_len_t dataLen, ipmi_context_t context) 278a835eaa0SJia, Chunhui { 279a835eaa0SJia, Chunhui DeviceInfo* data = reinterpret_cast<DeviceInfo*>(request); 280a835eaa0SJia, Chunhui 28164796041SJason M. Bills if ((*dataLen < 2) || (*dataLen != (1 + data->biosIDLength))) 282a835eaa0SJia, Chunhui { 283a835eaa0SJia, Chunhui *dataLen = 0; 284a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID; 285a835eaa0SJia, Chunhui } 28664796041SJason M. Bills std::string idString((char*)data->biosId, data->biosIDLength); 287a835eaa0SJia, Chunhui 28815419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 28915419dd5SVernon Mauery std::string service = getService(*dbus, biosIntf, biosObjPath); 29015419dd5SVernon Mauery setDbusProperty(*dbus, service, biosObjPath, biosIntf, biosProp, idString); 291a835eaa0SJia, Chunhui uint8_t* bytesWritten = static_cast<uint8_t*>(response); 292a835eaa0SJia, Chunhui *bytesWritten = 29364796041SJason M. Bills data->biosIDLength; // how many bytes are written into storage 294a835eaa0SJia, Chunhui *dataLen = 1; 295a835eaa0SJia, Chunhui return IPMI_CC_OK; 296a835eaa0SJia, Chunhui } 297a835eaa0SJia, Chunhui 298a835eaa0SJia, Chunhui ipmi_ret_t ipmiOEMGetDeviceInfo(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 299a835eaa0SJia, Chunhui ipmi_request_t request, 300a835eaa0SJia, Chunhui ipmi_response_t response, 301a835eaa0SJia, Chunhui ipmi_data_len_t dataLen, ipmi_context_t context) 302a835eaa0SJia, Chunhui { 303a835eaa0SJia, Chunhui GetOemDeviceInfoReq* req = reinterpret_cast<GetOemDeviceInfoReq*>(request); 304a835eaa0SJia, Chunhui GetOemDeviceInfoRes* res = reinterpret_cast<GetOemDeviceInfoRes*>(response); 305a835eaa0SJia, Chunhui 306a835eaa0SJia, Chunhui if (*dataLen == 0) 307a835eaa0SJia, Chunhui { 30864796041SJason M. Bills *dataLen = 0; 309a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID; 310a835eaa0SJia, Chunhui } 311a835eaa0SJia, Chunhui 312a835eaa0SJia, Chunhui size_t reqDataLen = *dataLen; 313a835eaa0SJia, Chunhui *dataLen = 0; 31464796041SJason M. Bills if (req->entityType > static_cast<uint8_t>(OEMDevEntityType::sdrVer)) 315a835eaa0SJia, Chunhui { 316a835eaa0SJia, Chunhui return IPMI_CC_INVALID_FIELD_REQUEST; 317a835eaa0SJia, Chunhui } 318a835eaa0SJia, Chunhui 319a835eaa0SJia, Chunhui // handle OEM command items 32064796041SJason M. Bills switch (OEMDevEntityType(req->entityType)) 321a835eaa0SJia, Chunhui { 322a835eaa0SJia, Chunhui case OEMDevEntityType::biosId: 323a835eaa0SJia, Chunhui { 324a835eaa0SJia, Chunhui if (sizeof(GetOemDeviceInfoReq) != reqDataLen) 325a835eaa0SJia, Chunhui { 326a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID; 327a835eaa0SJia, Chunhui } 328a835eaa0SJia, Chunhui 32915419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 33015419dd5SVernon Mauery std::string service = getService(*dbus, biosIntf, biosObjPath); 331a835eaa0SJia, Chunhui try 332a835eaa0SJia, Chunhui { 33315419dd5SVernon Mauery Value variant = getDbusProperty(*dbus, service, biosObjPath, 334a835eaa0SJia, Chunhui biosIntf, biosProp); 3358166c8d7SVernon Mauery std::string& idString = std::get<std::string>(variant); 336a835eaa0SJia, Chunhui if (req->offset >= idString.size()) 337a835eaa0SJia, Chunhui { 338a835eaa0SJia, Chunhui return IPMI_CC_PARM_OUT_OF_RANGE; 339a835eaa0SJia, Chunhui } 340a835eaa0SJia, Chunhui size_t length = 0; 341a835eaa0SJia, Chunhui if (req->countToRead > (idString.size() - req->offset)) 342a835eaa0SJia, Chunhui { 343a835eaa0SJia, Chunhui length = idString.size() - req->offset; 344a835eaa0SJia, Chunhui } 345a835eaa0SJia, Chunhui else 346a835eaa0SJia, Chunhui { 347a835eaa0SJia, Chunhui length = req->countToRead; 348a835eaa0SJia, Chunhui } 349a835eaa0SJia, Chunhui std::copy(idString.begin() + req->offset, idString.end(), 350a835eaa0SJia, Chunhui res->data); 351a835eaa0SJia, Chunhui res->resDatalen = length; 352a835eaa0SJia, Chunhui *dataLen = res->resDatalen + 1; 353a835eaa0SJia, Chunhui } 3548166c8d7SVernon Mauery catch (std::bad_variant_access& e) 355a835eaa0SJia, Chunhui { 35664796041SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 357a835eaa0SJia, Chunhui return IPMI_CC_UNSPECIFIED_ERROR; 358a835eaa0SJia, Chunhui } 359a835eaa0SJia, Chunhui } 360a835eaa0SJia, Chunhui break; 361a835eaa0SJia, Chunhui 362a835eaa0SJia, Chunhui case OEMDevEntityType::devVer: 363a835eaa0SJia, Chunhui case OEMDevEntityType::sdrVer: 364a835eaa0SJia, Chunhui // TODO: 365a835eaa0SJia, Chunhui return IPMI_CC_ILLEGAL_COMMAND; 366a835eaa0SJia, Chunhui default: 367a835eaa0SJia, Chunhui return IPMI_CC_INVALID_FIELD_REQUEST; 368a835eaa0SJia, Chunhui } 369a835eaa0SJia, Chunhui return IPMI_CC_OK; 370a835eaa0SJia, Chunhui } 371a835eaa0SJia, Chunhui 372a835eaa0SJia, Chunhui ipmi_ret_t ipmiOEMGetAICFRU(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 373a835eaa0SJia, Chunhui ipmi_request_t request, ipmi_response_t response, 374a835eaa0SJia, Chunhui ipmi_data_len_t dataLen, ipmi_context_t context) 375a835eaa0SJia, Chunhui { 376a835eaa0SJia, Chunhui if (*dataLen != 0) 377a835eaa0SJia, Chunhui { 37864796041SJason M. Bills *dataLen = 0; 379a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID; 380a835eaa0SJia, Chunhui } 381a835eaa0SJia, Chunhui 382a835eaa0SJia, Chunhui *dataLen = 1; 383a835eaa0SJia, Chunhui uint8_t* res = reinterpret_cast<uint8_t*>(response); 384a835eaa0SJia, Chunhui // temporary fix. We don't support AIC FRU now. Just tell BIOS that no 385a835eaa0SJia, Chunhui // AIC is available so that BIOS will not timeout repeatly which leads to 386a835eaa0SJia, Chunhui // slow booting. 387a835eaa0SJia, Chunhui *res = 0; // Byte1=Count of SlotPosition/FruID records. 388a835eaa0SJia, Chunhui return IPMI_CC_OK; 389a835eaa0SJia, Chunhui } 390a835eaa0SJia, Chunhui 39164796041SJason M. Bills ipmi_ret_t ipmiOEMGetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 39264796041SJason M. Bills ipmi_request_t request, 39364796041SJason M. Bills ipmi_response_t response, 39464796041SJason M. Bills ipmi_data_len_t dataLen, 39564796041SJason M. Bills ipmi_context_t context) 396a835eaa0SJia, Chunhui { 39764796041SJason M. Bills GetPowerRestoreDelayRes* resp = 39864796041SJason M. Bills reinterpret_cast<GetPowerRestoreDelayRes*>(response); 39964796041SJason M. Bills 40064796041SJason M. Bills if (*dataLen != 0) 40164796041SJason M. Bills { 40264796041SJason M. Bills *dataLen = 0; 40364796041SJason M. Bills return IPMI_CC_REQ_DATA_LEN_INVALID; 404a835eaa0SJia, Chunhui } 405a835eaa0SJia, Chunhui 40615419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 40764796041SJason M. Bills std::string service = 40815419dd5SVernon Mauery getService(*dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath); 40964796041SJason M. Bills Value variant = 41015419dd5SVernon Mauery getDbusProperty(*dbus, service, powerRestoreDelayObjPath, 41164796041SJason M. Bills powerRestoreDelayIntf, powerRestoreDelayProp); 41264796041SJason M. Bills 4138166c8d7SVernon Mauery uint16_t delay = std::get<uint16_t>(variant); 41464796041SJason M. Bills resp->byteLSB = delay; 41564796041SJason M. Bills resp->byteMSB = delay >> 8; 41664796041SJason M. Bills 41764796041SJason M. Bills *dataLen = sizeof(GetPowerRestoreDelayRes); 41864796041SJason M. Bills 41964796041SJason M. Bills return IPMI_CC_OK; 42064796041SJason M. Bills } 42164796041SJason M. Bills 422cc49b54bSJia, Chunhui static uint8_t bcdToDec(uint8_t val) 423cc49b54bSJia, Chunhui { 424cc49b54bSJia, Chunhui return ((val / 16 * 10) + (val % 16)); 425cc49b54bSJia, Chunhui } 426cc49b54bSJia, Chunhui 427cc49b54bSJia, Chunhui // Allows an update utility or system BIOS to send the status of an embedded 428cc49b54bSJia, Chunhui // firmware update attempt to the BMC. After received, BMC will create a logging 429cc49b54bSJia, Chunhui // record. 430cc49b54bSJia, Chunhui ipmi::RspType<> ipmiOEMSendEmbeddedFwUpdStatus(uint8_t status, uint8_t target, 431cc49b54bSJia, Chunhui uint8_t majorRevision, 432cc49b54bSJia, Chunhui uint8_t minorRevision, 433cc49b54bSJia, Chunhui uint32_t auxInfo) 434cc49b54bSJia, Chunhui { 435cc49b54bSJia, Chunhui std::string firmware; 436dc24927fSJason M. Bills int instance = (target & targetInstanceMask) >> targetInstanceShift; 437cc49b54bSJia, Chunhui target = (target & selEvtTargetMask) >> selEvtTargetShift; 438cc49b54bSJia, Chunhui 439cc49b54bSJia, Chunhui /* make sure the status is 0, 1, or 2 as per the spec */ 440cc49b54bSJia, Chunhui if (status > 2) 441cc49b54bSJia, Chunhui { 442cc49b54bSJia, Chunhui return ipmi::response(ipmi::ccInvalidFieldRequest); 443cc49b54bSJia, Chunhui } 444dc24927fSJason M. Bills /* make sure the target is 0, 1, 2, or 4 as per the spec */ 445dc24927fSJason M. Bills if (target > 4 || target == 3) 446dc24927fSJason M. Bills { 447dc24927fSJason M. Bills return ipmi::response(ipmi::ccInvalidFieldRequest); 448dc24927fSJason M. Bills } 449cc49b54bSJia, Chunhui /*orignal OEM command is to record OEM SEL. 450cc49b54bSJia, Chunhui But openbmc does not support OEM SEL, so we redirect it to redfish event 451cc49b54bSJia, Chunhui logging. */ 452cc49b54bSJia, Chunhui std::string buildInfo; 453cc49b54bSJia, Chunhui std::string action; 454cc49b54bSJia, Chunhui switch (FWUpdateTarget(target)) 455cc49b54bSJia, Chunhui { 456cc49b54bSJia, Chunhui case FWUpdateTarget::targetBMC: 457cc49b54bSJia, Chunhui firmware = "BMC"; 458dc24927fSJason M. Bills buildInfo = "major: " + std::to_string(majorRevision) + " minor: " + 459cc49b54bSJia, Chunhui std::to_string(bcdToDec(minorRevision)) + // BCD encoded 460cc49b54bSJia, Chunhui " BuildID: " + std::to_string(auxInfo); 461cc49b54bSJia, Chunhui buildInfo += std::to_string(auxInfo); 462cc49b54bSJia, Chunhui break; 463cc49b54bSJia, Chunhui case FWUpdateTarget::targetBIOS: 464cc49b54bSJia, Chunhui firmware = "BIOS"; 465cc49b54bSJia, Chunhui buildInfo = 466cc49b54bSJia, Chunhui "major: " + 467cc49b54bSJia, Chunhui std::to_string(bcdToDec(majorRevision)) + // BCD encoded 468cc49b54bSJia, Chunhui " minor: " + 469cc49b54bSJia, Chunhui std::to_string(bcdToDec(minorRevision)) + // BCD encoded 470cc49b54bSJia, Chunhui " ReleaseNumber: " + // ASCII encoded 471cc49b54bSJia, Chunhui std::to_string(static_cast<uint8_t>(auxInfo >> 0) - '0') + 472cc49b54bSJia, Chunhui std::to_string(static_cast<uint8_t>(auxInfo >> 8) - '0') + 473cc49b54bSJia, Chunhui std::to_string(static_cast<uint8_t>(auxInfo >> 16) - '0') + 474cc49b54bSJia, Chunhui std::to_string(static_cast<uint8_t>(auxInfo >> 24) - '0'); 475cc49b54bSJia, Chunhui break; 476cc49b54bSJia, Chunhui case FWUpdateTarget::targetME: 477cc49b54bSJia, Chunhui firmware = "ME"; 478cc49b54bSJia, Chunhui buildInfo = 479cc49b54bSJia, Chunhui "major: " + std::to_string(majorRevision) + " minor1: " + 480cc49b54bSJia, Chunhui std::to_string(bcdToDec(minorRevision)) + // BCD encoded 481cc49b54bSJia, Chunhui " minor2: " + 482cc49b54bSJia, Chunhui std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 0))) + 483cc49b54bSJia, Chunhui " build1: " + 484cc49b54bSJia, Chunhui std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 8))) + 485cc49b54bSJia, Chunhui " build2: " + 486cc49b54bSJia, Chunhui std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 16))); 487cc49b54bSJia, Chunhui break; 488cc49b54bSJia, Chunhui case FWUpdateTarget::targetOEMEWS: 489cc49b54bSJia, Chunhui firmware = "EWS"; 490dc24927fSJason M. Bills buildInfo = "major: " + std::to_string(majorRevision) + " minor: " + 491cc49b54bSJia, Chunhui std::to_string(bcdToDec(minorRevision)) + // BCD encoded 492cc49b54bSJia, Chunhui " BuildID: " + std::to_string(auxInfo); 493cc49b54bSJia, Chunhui break; 494cc49b54bSJia, Chunhui } 495cc49b54bSJia, Chunhui 496dc24927fSJason M. Bills static const std::string openBMCMessageRegistryVersion("0.1"); 497dc24927fSJason M. Bills std::string redfishMsgID = "OpenBMC." + openBMCMessageRegistryVersion; 498dc24927fSJason M. Bills 499cc49b54bSJia, Chunhui switch (status) 500cc49b54bSJia, Chunhui { 501cc49b54bSJia, Chunhui case 0x0: 502cc49b54bSJia, Chunhui action = "update started"; 503dc24927fSJason M. Bills redfishMsgID += ".FirmwareUpdateStarted"; 504cc49b54bSJia, Chunhui break; 505cc49b54bSJia, Chunhui case 0x1: 506cc49b54bSJia, Chunhui action = "update completed successfully"; 507dc24927fSJason M. Bills redfishMsgID += ".FirmwareUpdateCompleted"; 508cc49b54bSJia, Chunhui break; 509cc49b54bSJia, Chunhui case 0x2: 510cc49b54bSJia, Chunhui action = "update failure"; 511dc24927fSJason M. Bills redfishMsgID += ".FirmwareUpdateFailed"; 512cc49b54bSJia, Chunhui break; 513cc49b54bSJia, Chunhui default: 514cc49b54bSJia, Chunhui action = "unknown"; 515cc49b54bSJia, Chunhui break; 516cc49b54bSJia, Chunhui } 517cc49b54bSJia, Chunhui 518dc24927fSJason M. Bills std::string firmwareInstanceStr = 519dc24927fSJason M. Bills firmware + " instance: " + std::to_string(instance); 520dc24927fSJason M. Bills std::string message("[firmware update] " + firmwareInstanceStr + 521cc49b54bSJia, Chunhui " status: <" + action + "> " + buildInfo); 522cc49b54bSJia, Chunhui 523cc49b54bSJia, Chunhui sd_journal_send("MESSAGE=%s", message.c_str(), "PRIORITY=%i", LOG_INFO, 524dc24927fSJason M. Bills "REDFISH_MESSAGE_ID=%s", redfishMsgID.c_str(), 525dc24927fSJason M. Bills "REDFISH_MESSAGE_ARGS=%s,%s", firmwareInstanceStr.c_str(), 526dc24927fSJason M. Bills buildInfo.c_str(), NULL); 527cc49b54bSJia, Chunhui return ipmi::responseSuccess(); 528cc49b54bSJia, Chunhui } 529cc49b54bSJia, Chunhui 53064796041SJason M. Bills ipmi_ret_t ipmiOEMSetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 53164796041SJason M. Bills ipmi_request_t request, 53264796041SJason M. Bills ipmi_response_t response, 53364796041SJason M. Bills ipmi_data_len_t dataLen, 53464796041SJason M. Bills ipmi_context_t context) 53564796041SJason M. Bills { 53664796041SJason M. Bills SetPowerRestoreDelayReq* data = 53764796041SJason M. Bills reinterpret_cast<SetPowerRestoreDelayReq*>(request); 53864796041SJason M. Bills uint16_t delay = 0; 53964796041SJason M. Bills 54064796041SJason M. Bills if (*dataLen != sizeof(SetPowerRestoreDelayReq)) 54164796041SJason M. Bills { 54264796041SJason M. Bills *dataLen = 0; 54364796041SJason M. Bills return IPMI_CC_REQ_DATA_LEN_INVALID; 54464796041SJason M. Bills } 54564796041SJason M. Bills delay = data->byteMSB; 54664796041SJason M. Bills delay = (delay << 8) | data->byteLSB; 54715419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 54864796041SJason M. Bills std::string service = 54915419dd5SVernon Mauery getService(*dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath); 55015419dd5SVernon Mauery setDbusProperty(*dbus, service, powerRestoreDelayObjPath, 55164796041SJason M. Bills powerRestoreDelayIntf, powerRestoreDelayProp, delay); 55264796041SJason M. Bills *dataLen = 0; 55364796041SJason M. Bills 55464796041SJason M. Bills return IPMI_CC_OK; 55564796041SJason M. Bills } 55664796041SJason M. Bills 55742bd9c8eSJason M. Bills static bool cpuPresent(const std::string& cpuName) 55864796041SJason M. Bills { 55942bd9c8eSJason M. Bills static constexpr const char* cpuPresencePathPrefix = 56042bd9c8eSJason M. Bills "/xyz/openbmc_project/inventory/system/chassis/motherboard/"; 56142bd9c8eSJason M. Bills static constexpr const char* cpuPresenceIntf = 56242bd9c8eSJason M. Bills "xyz.openbmc_project.Inventory.Item"; 56342bd9c8eSJason M. Bills std::string cpuPresencePath = cpuPresencePathPrefix + cpuName; 56442bd9c8eSJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); 56542bd9c8eSJason M. Bills try 56642bd9c8eSJason M. Bills { 56742bd9c8eSJason M. Bills auto service = 56842bd9c8eSJason M. Bills ipmi::getService(*busp, cpuPresenceIntf, cpuPresencePath); 56964796041SJason M. Bills 57042bd9c8eSJason M. Bills ipmi::Value result = ipmi::getDbusProperty( 57142bd9c8eSJason M. Bills *busp, service, cpuPresencePath, cpuPresenceIntf, "Present"); 57242bd9c8eSJason M. Bills return std::get<bool>(result); 57342bd9c8eSJason M. Bills } 57442bd9c8eSJason M. Bills catch (const std::exception& e) 57564796041SJason M. Bills { 57642bd9c8eSJason M. Bills phosphor::logging::log<phosphor::logging::level::INFO>( 57742bd9c8eSJason M. Bills "Cannot find processor presence", 57842bd9c8eSJason M. Bills phosphor::logging::entry("NAME=%s", cpuName.c_str())); 57942bd9c8eSJason M. Bills return false; 58042bd9c8eSJason M. Bills } 58164796041SJason M. Bills } 58264796041SJason M. Bills 58342bd9c8eSJason M. Bills ipmi::RspType<bool, // CATERR Reset Enabled 58442bd9c8eSJason M. Bills bool, // ERR2 Reset Enabled 58542bd9c8eSJason M. Bills uint6_t, // reserved 58642bd9c8eSJason M. Bills uint8_t, // reserved, returns 0x3F 58742bd9c8eSJason M. Bills uint6_t, // CPU1 CATERR Count 58842bd9c8eSJason M. Bills uint2_t, // CPU1 Status 58942bd9c8eSJason M. Bills uint6_t, // CPU2 CATERR Count 59042bd9c8eSJason M. Bills uint2_t, // CPU2 Status 59142bd9c8eSJason M. Bills uint6_t, // CPU3 CATERR Count 59242bd9c8eSJason M. Bills uint2_t, // CPU3 Status 59342bd9c8eSJason M. Bills uint6_t, // CPU4 CATERR Count 59442bd9c8eSJason M. Bills uint2_t, // CPU4 Status 59542bd9c8eSJason M. Bills uint8_t // Crashdump Count 59642bd9c8eSJason M. Bills > 59742bd9c8eSJason M. Bills ipmiOEMGetProcessorErrConfig() 59842bd9c8eSJason M. Bills { 59942bd9c8eSJason M. Bills bool resetOnCATERR = false; 60042bd9c8eSJason M. Bills bool resetOnERR2 = false; 60142bd9c8eSJason M. Bills uint6_t cpu1CATERRCount = 0; 60242bd9c8eSJason M. Bills uint6_t cpu2CATERRCount = 0; 60342bd9c8eSJason M. Bills uint6_t cpu3CATERRCount = 0; 60442bd9c8eSJason M. Bills uint6_t cpu4CATERRCount = 0; 60542bd9c8eSJason M. Bills uint8_t crashdumpCount = 0; 60642bd9c8eSJason M. Bills uint2_t cpu1Status = 60742bd9c8eSJason M. Bills cpuPresent("CPU_1") ? CPUStatus::enabled : CPUStatus::notPresent; 60842bd9c8eSJason M. Bills uint2_t cpu2Status = 60942bd9c8eSJason M. Bills cpuPresent("CPU_2") ? CPUStatus::enabled : CPUStatus::notPresent; 61042bd9c8eSJason M. Bills uint2_t cpu3Status = 61142bd9c8eSJason M. Bills cpuPresent("CPU_3") ? CPUStatus::enabled : CPUStatus::notPresent; 61242bd9c8eSJason M. Bills uint2_t cpu4Status = 61342bd9c8eSJason M. Bills cpuPresent("CPU_4") ? CPUStatus::enabled : CPUStatus::notPresent; 61464796041SJason M. Bills 61542bd9c8eSJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); 61642bd9c8eSJason M. Bills try 61742bd9c8eSJason M. Bills { 61842bd9c8eSJason M. Bills auto service = ipmi::getService(*busp, processorErrConfigIntf, 61942bd9c8eSJason M. Bills processorErrConfigObjPath); 62064796041SJason M. Bills 62142bd9c8eSJason M. Bills ipmi::PropertyMap result = ipmi::getAllDbusProperties( 62242bd9c8eSJason M. Bills *busp, service, processorErrConfigObjPath, processorErrConfigIntf); 62342bd9c8eSJason M. Bills resetOnCATERR = std::get<bool>(result.at("ResetOnCATERR")); 62442bd9c8eSJason M. Bills resetOnERR2 = std::get<bool>(result.at("ResetOnERR2")); 62542bd9c8eSJason M. Bills cpu1CATERRCount = std::get<uint8_t>(result.at("ErrorCountCPU1")); 62642bd9c8eSJason M. Bills cpu2CATERRCount = std::get<uint8_t>(result.at("ErrorCountCPU2")); 62742bd9c8eSJason M. Bills cpu3CATERRCount = std::get<uint8_t>(result.at("ErrorCountCPU3")); 62842bd9c8eSJason M. Bills cpu4CATERRCount = std::get<uint8_t>(result.at("ErrorCountCPU4")); 62942bd9c8eSJason M. Bills crashdumpCount = std::get<uint8_t>(result.at("CrashdumpCount")); 63042bd9c8eSJason M. Bills } 63142bd9c8eSJason M. Bills catch (const std::exception& e) 63242bd9c8eSJason M. Bills { 63342bd9c8eSJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>( 63442bd9c8eSJason M. Bills "Failed to fetch processor error config", 63542bd9c8eSJason M. Bills phosphor::logging::entry("ERROR=%s", e.what())); 63642bd9c8eSJason M. Bills return ipmi::responseUnspecifiedError(); 63742bd9c8eSJason M. Bills } 63864796041SJason M. Bills 63942bd9c8eSJason M. Bills return ipmi::responseSuccess(resetOnCATERR, resetOnERR2, 0, 0x3F, 64042bd9c8eSJason M. Bills cpu1CATERRCount, cpu1Status, cpu2CATERRCount, 64142bd9c8eSJason M. Bills cpu2Status, cpu3CATERRCount, cpu3Status, 64242bd9c8eSJason M. Bills cpu4CATERRCount, cpu4Status, crashdumpCount); 64342bd9c8eSJason M. Bills } 64442bd9c8eSJason M. Bills 64542bd9c8eSJason M. Bills ipmi::RspType<> ipmiOEMSetProcessorErrConfig( 64642bd9c8eSJason M. Bills bool resetOnCATERR, bool resetOnERR2, uint6_t reserved1, uint8_t reserved2, 64742bd9c8eSJason M. Bills std::optional<bool> clearCPUErrorCount, 64842bd9c8eSJason M. Bills std::optional<bool> clearCrashdumpCount, std::optional<uint6_t> reserved3) 64942bd9c8eSJason M. Bills { 65042bd9c8eSJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); 65164796041SJason M. Bills 65264796041SJason M. Bills try 65364796041SJason M. Bills { 65442bd9c8eSJason M. Bills auto service = ipmi::getService(*busp, processorErrConfigIntf, 65542bd9c8eSJason M. Bills processorErrConfigObjPath); 65642bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, 65742bd9c8eSJason M. Bills processorErrConfigIntf, "ResetOnCATERR", 65842bd9c8eSJason M. Bills resetOnCATERR); 65942bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, 66042bd9c8eSJason M. Bills processorErrConfigIntf, "ResetOnERR2", 66142bd9c8eSJason M. Bills resetOnERR2); 66242bd9c8eSJason M. Bills if (clearCPUErrorCount.value_or(false)) 66342bd9c8eSJason M. Bills { 66442bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, 665d3e19936SJason M. Bills processorErrConfigIntf, "ErrorCountCPU1", 666d3e19936SJason M. Bills static_cast<uint8_t>(0)); 66742bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, 668d3e19936SJason M. Bills processorErrConfigIntf, "ErrorCountCPU2", 669d3e19936SJason M. Bills static_cast<uint8_t>(0)); 670d3e19936SJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, 671d3e19936SJason M. Bills processorErrConfigIntf, "ErrorCountCPU3", 672d3e19936SJason M. Bills static_cast<uint8_t>(0)); 673d3e19936SJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, 674d3e19936SJason M. Bills processorErrConfigIntf, "ErrorCountCPU4", 675d3e19936SJason M. Bills static_cast<uint8_t>(0)); 67664796041SJason M. Bills } 67742bd9c8eSJason M. Bills if (clearCrashdumpCount.value_or(false)) 67842bd9c8eSJason M. Bills { 67942bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, 680d3e19936SJason M. Bills processorErrConfigIntf, "CrashdumpCount", 681d3e19936SJason M. Bills static_cast<uint8_t>(0)); 68242bd9c8eSJason M. Bills } 68342bd9c8eSJason M. Bills } 68442bd9c8eSJason M. Bills catch (std::exception& e) 68564796041SJason M. Bills { 686bc546679SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 68742bd9c8eSJason M. Bills "Failed to set processor error config", 68842bd9c8eSJason M. Bills phosphor::logging::entry("EXCEPTION=%s", e.what())); 68942bd9c8eSJason M. Bills return ipmi::responseUnspecifiedError(); 69064796041SJason M. Bills } 69164796041SJason M. Bills 69242bd9c8eSJason M. Bills return ipmi::responseSuccess(); 69364796041SJason M. Bills } 69464796041SJason M. Bills 695703922d0SYong Li ipmi_ret_t ipmiOEMGetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 696703922d0SYong Li ipmi_request_t request, 697703922d0SYong Li ipmi_response_t response, 698703922d0SYong Li ipmi_data_len_t dataLen, 699703922d0SYong Li ipmi_context_t context) 700703922d0SYong Li { 701703922d0SYong Li GetOEMShutdownPolicyRes* resp = 702703922d0SYong Li reinterpret_cast<GetOEMShutdownPolicyRes*>(response); 703703922d0SYong Li 704703922d0SYong Li if (*dataLen != 0) 705703922d0SYong Li { 706703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 70745f04988SKuiying Wang "oem_get_shutdown_policy: invalid input len!"); 708703922d0SYong Li *dataLen = 0; 709703922d0SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID; 710703922d0SYong Li } 711703922d0SYong Li 712703922d0SYong Li *dataLen = 0; 713703922d0SYong Li 714703922d0SYong Li try 715703922d0SYong Li { 71615419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 717703922d0SYong Li std::string service = 71815419dd5SVernon Mauery getService(*dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath); 71915419dd5SVernon Mauery Value variant = getDbusProperty( 72015419dd5SVernon Mauery *dbus, service, oemShutdownPolicyObjPath, oemShutdownPolicyIntf, 721703922d0SYong Li oemShutdownPolicyObjPathProp); 7220669d193SYong Li 7230669d193SYong Li if (sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: 7240669d193SYong Li convertPolicyFromString(std::get<std::string>(variant)) == 7250669d193SYong Li sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy:: 7260669d193SYong Li NoShutdownOnOCOT) 7270669d193SYong Li { 7280669d193SYong Li resp->policy = 0; 7290669d193SYong Li } 7300669d193SYong Li else if (sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: 7310669d193SYong Li convertPolicyFromString(std::get<std::string>(variant)) == 7320669d193SYong Li sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: 7330669d193SYong Li Policy::ShutdownOnOCOT) 7340669d193SYong Li { 7350669d193SYong Li resp->policy = 1; 7360669d193SYong Li } 7370669d193SYong Li else 7380669d193SYong Li { 7390669d193SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 7400669d193SYong Li "oem_set_shutdown_policy: invalid property!", 7410669d193SYong Li phosphor::logging::entry( 7420669d193SYong Li "PROP=%s", std::get<std::string>(variant).c_str())); 7430669d193SYong Li return IPMI_CC_UNSPECIFIED_ERROR; 7440669d193SYong Li } 745703922d0SYong Li // TODO needs to check if it is multi-node products, 746703922d0SYong Li // policy is only supported on node 3/4 747703922d0SYong Li resp->policySupport = shutdownPolicySupported; 748703922d0SYong Li } 749703922d0SYong Li catch (sdbusplus::exception_t& e) 750703922d0SYong Li { 751703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(e.description()); 752703922d0SYong Li return IPMI_CC_UNSPECIFIED_ERROR; 753703922d0SYong Li } 754703922d0SYong Li 755703922d0SYong Li *dataLen = sizeof(GetOEMShutdownPolicyRes); 756703922d0SYong Li return IPMI_CC_OK; 757703922d0SYong Li } 758703922d0SYong Li 759703922d0SYong Li ipmi_ret_t ipmiOEMSetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 760703922d0SYong Li ipmi_request_t request, 761703922d0SYong Li ipmi_response_t response, 762703922d0SYong Li ipmi_data_len_t dataLen, 763703922d0SYong Li ipmi_context_t context) 764703922d0SYong Li { 765703922d0SYong Li uint8_t* req = reinterpret_cast<uint8_t*>(request); 7660669d193SYong Li sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy policy = 7670669d193SYong Li sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy:: 7680669d193SYong Li NoShutdownOnOCOT; 769703922d0SYong Li 770703922d0SYong Li // TODO needs to check if it is multi-node products, 771703922d0SYong Li // policy is only supported on node 3/4 772703922d0SYong Li if (*dataLen != 1) 773703922d0SYong Li { 774703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 775703922d0SYong Li "oem_set_shutdown_policy: invalid input len!"); 776703922d0SYong Li *dataLen = 0; 777703922d0SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID; 778703922d0SYong Li } 779703922d0SYong Li 780703922d0SYong Li *dataLen = 0; 781703922d0SYong Li if ((*req != noShutdownOnOCOT) && (*req != shutdownOnOCOT)) 782703922d0SYong Li { 783703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 784703922d0SYong Li "oem_set_shutdown_policy: invalid input!"); 785703922d0SYong Li return IPMI_CC_INVALID_FIELD_REQUEST; 786703922d0SYong Li } 787703922d0SYong Li 7880669d193SYong Li if (*req == noShutdownOnOCOT) 7890669d193SYong Li { 7900669d193SYong Li policy = sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: 7910669d193SYong Li Policy::NoShutdownOnOCOT; 7920669d193SYong Li } 7930669d193SYong Li else 7940669d193SYong Li { 7950669d193SYong Li policy = sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: 7960669d193SYong Li Policy::ShutdownOnOCOT; 7970669d193SYong Li } 7980669d193SYong Li 799703922d0SYong Li try 800703922d0SYong Li { 80115419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 802703922d0SYong Li std::string service = 80315419dd5SVernon Mauery getService(*dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath); 8040669d193SYong Li setDbusProperty( 80515419dd5SVernon Mauery *dbus, service, oemShutdownPolicyObjPath, oemShutdownPolicyIntf, 8060669d193SYong Li oemShutdownPolicyObjPathProp, 8070669d193SYong Li sdbusplus::com::intel::Control::server::convertForMessage(policy)); 808703922d0SYong Li } 809703922d0SYong Li catch (sdbusplus::exception_t& e) 810703922d0SYong Li { 811703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(e.description()); 812703922d0SYong Li return IPMI_CC_UNSPECIFIED_ERROR; 813703922d0SYong Li } 814703922d0SYong Li 815703922d0SYong Li return IPMI_CC_OK; 816703922d0SYong Li } 817703922d0SYong Li 818d509eb91SSuryakanth Sekar /** @brief implementation for check the DHCP or not in IPv4 819d509eb91SSuryakanth Sekar * @param[in] Channel - Channel number 820d509eb91SSuryakanth Sekar * @returns true or false. 821d509eb91SSuryakanth Sekar */ 822d509eb91SSuryakanth Sekar static bool isDHCPEnabled(uint8_t Channel) 823d509eb91SSuryakanth Sekar { 824d509eb91SSuryakanth Sekar try 825d509eb91SSuryakanth Sekar { 826d509eb91SSuryakanth Sekar auto ethdevice = getChannelName(Channel); 827d509eb91SSuryakanth Sekar if (ethdevice.empty()) 828d509eb91SSuryakanth Sekar { 829d509eb91SSuryakanth Sekar return false; 830d509eb91SSuryakanth Sekar } 831d509eb91SSuryakanth Sekar auto ethIP = ethdevice + "/ipv4"; 83215419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 833d509eb91SSuryakanth Sekar auto ethernetObj = 83415419dd5SVernon Mauery getDbusObject(*dbus, networkIPIntf, networkRoot, ethIP); 83515419dd5SVernon Mauery auto value = getDbusProperty(*dbus, networkService, ethernetObj.first, 836d509eb91SSuryakanth Sekar networkIPIntf, "Origin"); 8378166c8d7SVernon Mauery if (std::get<std::string>(value) == 838d509eb91SSuryakanth Sekar "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 839d509eb91SSuryakanth Sekar { 840d509eb91SSuryakanth Sekar return true; 841d509eb91SSuryakanth Sekar } 842d509eb91SSuryakanth Sekar else 843d509eb91SSuryakanth Sekar { 844d509eb91SSuryakanth Sekar return false; 845d509eb91SSuryakanth Sekar } 846d509eb91SSuryakanth Sekar } 847d509eb91SSuryakanth Sekar catch (sdbusplus::exception_t& e) 848d509eb91SSuryakanth Sekar { 849d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(e.description()); 850d509eb91SSuryakanth Sekar return true; 851d509eb91SSuryakanth Sekar } 852d509eb91SSuryakanth Sekar } 853d509eb91SSuryakanth Sekar 854d509eb91SSuryakanth Sekar /** @brief implementes for check the DHCP or not in IPv6 855d509eb91SSuryakanth Sekar * @param[in] Channel - Channel number 856d509eb91SSuryakanth Sekar * @returns true or false. 857d509eb91SSuryakanth Sekar */ 858d509eb91SSuryakanth Sekar static bool isDHCPIPv6Enabled(uint8_t Channel) 859d509eb91SSuryakanth Sekar { 860d509eb91SSuryakanth Sekar 861d509eb91SSuryakanth Sekar try 862d509eb91SSuryakanth Sekar { 863d509eb91SSuryakanth Sekar auto ethdevice = getChannelName(Channel); 864d509eb91SSuryakanth Sekar if (ethdevice.empty()) 865d509eb91SSuryakanth Sekar { 866d509eb91SSuryakanth Sekar return false; 867d509eb91SSuryakanth Sekar } 868d509eb91SSuryakanth Sekar auto ethIP = ethdevice + "/ipv6"; 86915419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 870d509eb91SSuryakanth Sekar auto objectInfo = 87115419dd5SVernon Mauery getDbusObject(*dbus, networkIPIntf, networkRoot, ethIP); 87215419dd5SVernon Mauery auto properties = getAllDbusProperties(*dbus, objectInfo.second, 873d509eb91SSuryakanth Sekar objectInfo.first, networkIPIntf); 8748166c8d7SVernon Mauery if (std::get<std::string>(properties["Origin"]) == 875d509eb91SSuryakanth Sekar "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") 876d509eb91SSuryakanth Sekar { 877d509eb91SSuryakanth Sekar return true; 878d509eb91SSuryakanth Sekar } 879d509eb91SSuryakanth Sekar else 880d509eb91SSuryakanth Sekar { 881d509eb91SSuryakanth Sekar return false; 882d509eb91SSuryakanth Sekar } 883d509eb91SSuryakanth Sekar } 884d509eb91SSuryakanth Sekar catch (sdbusplus::exception_t& e) 885d509eb91SSuryakanth Sekar { 886d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(e.description()); 887d509eb91SSuryakanth Sekar return true; 888d509eb91SSuryakanth Sekar } 889d509eb91SSuryakanth Sekar } 890d509eb91SSuryakanth Sekar 891d509eb91SSuryakanth Sekar /** @brief implementes the creating of default new user 892d509eb91SSuryakanth Sekar * @param[in] userName - new username in 16 bytes. 893d509eb91SSuryakanth Sekar * @param[in] userPassword - new password in 20 bytes 894d509eb91SSuryakanth Sekar * @returns ipmi completion code. 895d509eb91SSuryakanth Sekar */ 896d509eb91SSuryakanth Sekar ipmi::RspType<> ipmiOEMSetUser2Activation( 897d509eb91SSuryakanth Sekar std::array<uint8_t, ipmi::ipmiMaxUserName>& userName, 898d509eb91SSuryakanth Sekar std::array<uint8_t, ipmi::maxIpmi20PasswordSize>& userPassword) 899d509eb91SSuryakanth Sekar { 900d509eb91SSuryakanth Sekar bool userState = false; 901d509eb91SSuryakanth Sekar // Check for System Interface not exist and LAN should be static 902d509eb91SSuryakanth Sekar for (uint8_t channel = 0; channel < maxIpmiChannels; channel++) 903d509eb91SSuryakanth Sekar { 904d509eb91SSuryakanth Sekar ChannelInfo chInfo; 905d509eb91SSuryakanth Sekar try 906d509eb91SSuryakanth Sekar { 907d509eb91SSuryakanth Sekar getChannelInfo(channel, chInfo); 908d509eb91SSuryakanth Sekar } 909d509eb91SSuryakanth Sekar catch (sdbusplus::exception_t& e) 910d509eb91SSuryakanth Sekar { 911d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>( 912d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: Failed to get Channel Info", 913d509eb91SSuryakanth Sekar phosphor::logging::entry("MSG: %s", e.description())); 914d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccUnspecifiedError); 915d509eb91SSuryakanth Sekar } 916d509eb91SSuryakanth Sekar if (chInfo.mediumType == 917d509eb91SSuryakanth Sekar static_cast<uint8_t>(EChannelMediumType::systemInterface)) 918d509eb91SSuryakanth Sekar { 919d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>( 920d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: system interface exist ."); 921d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable); 922d509eb91SSuryakanth Sekar } 923d509eb91SSuryakanth Sekar else 924d509eb91SSuryakanth Sekar { 925d509eb91SSuryakanth Sekar 926d509eb91SSuryakanth Sekar if (chInfo.mediumType == 927d509eb91SSuryakanth Sekar static_cast<uint8_t>(EChannelMediumType::lan8032)) 928d509eb91SSuryakanth Sekar { 929d509eb91SSuryakanth Sekar if (isDHCPIPv6Enabled(channel) || isDHCPEnabled(channel)) 930d509eb91SSuryakanth Sekar { 931d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>( 932d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: DHCP enabled ."); 933d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable); 934d509eb91SSuryakanth Sekar } 935d509eb91SSuryakanth Sekar } 936d509eb91SSuryakanth Sekar } 937d509eb91SSuryakanth Sekar } 938d509eb91SSuryakanth Sekar uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0; 939d509eb91SSuryakanth Sekar if (ipmi::ccSuccess == 940d509eb91SSuryakanth Sekar ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers)) 941d509eb91SSuryakanth Sekar { 942d509eb91SSuryakanth Sekar if (enabledUsers > 1) 943d509eb91SSuryakanth Sekar { 944d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>( 945d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: more than one user is enabled."); 946d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable); 947d509eb91SSuryakanth Sekar } 948d509eb91SSuryakanth Sekar // Check the user 2 is enabled or not 949d509eb91SSuryakanth Sekar ipmiUserCheckEnabled(ipmiDefaultUserId, userState); 950d509eb91SSuryakanth Sekar if (userState == true) 951d509eb91SSuryakanth Sekar { 952d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>( 953d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: user 2 already enabled ."); 954d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable); 955d509eb91SSuryakanth Sekar } 956d509eb91SSuryakanth Sekar } 957d509eb91SSuryakanth Sekar else 958d509eb91SSuryakanth Sekar { 959d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccUnspecifiedError); 960d509eb91SSuryakanth Sekar } 961d509eb91SSuryakanth Sekar 962d509eb91SSuryakanth Sekar #if BYTE_ORDER == LITTLE_ENDIAN 963d509eb91SSuryakanth Sekar PrivAccess privAccess = {PRIVILEGE_ADMIN, true, true, true, 0}; 964d509eb91SSuryakanth Sekar #endif 965d509eb91SSuryakanth Sekar #if BYTE_ORDER == BIG_ENDIAN 966d509eb91SSuryakanth Sekar PrivAccess privAccess = {0, true, true, true, PRIVILEGE_ADMIN}; 967d509eb91SSuryakanth Sekar #endif 968d509eb91SSuryakanth Sekar 969d509eb91SSuryakanth Sekar if (ipmi::ccSuccess == 970d509eb91SSuryakanth Sekar ipmiUserSetUserName(ipmiDefaultUserId, 971d509eb91SSuryakanth Sekar reinterpret_cast<const char*>(userName.data()))) 972d509eb91SSuryakanth Sekar { 973d509eb91SSuryakanth Sekar if (ipmi::ccSuccess == 974d509eb91SSuryakanth Sekar ipmiUserSetUserPassword( 975d509eb91SSuryakanth Sekar ipmiDefaultUserId, 976d509eb91SSuryakanth Sekar reinterpret_cast<const char*>(userPassword.data()))) 977d509eb91SSuryakanth Sekar { 978d509eb91SSuryakanth Sekar if (ipmi::ccSuccess == 979d509eb91SSuryakanth Sekar ipmiUserSetPrivilegeAccess( 980d509eb91SSuryakanth Sekar ipmiDefaultUserId, 981d509eb91SSuryakanth Sekar static_cast<uint8_t>(ipmi::EChannelID::chanLan1), 982d509eb91SSuryakanth Sekar privAccess, true)) 983d509eb91SSuryakanth Sekar { 984d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::INFO>( 985d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: user created successfully "); 986d509eb91SSuryakanth Sekar return ipmi::responseSuccess(); 987d509eb91SSuryakanth Sekar } 988d509eb91SSuryakanth Sekar } 989d509eb91SSuryakanth Sekar // we need to delete the default user id which added in this command as 990d509eb91SSuryakanth Sekar // password / priv setting is failed. 991d509eb91SSuryakanth Sekar ipmiUserSetUserName(ipmiDefaultUserId, ""); 992d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>( 993d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: password / priv setting is failed."); 994d509eb91SSuryakanth Sekar } 995d509eb91SSuryakanth Sekar else 996d509eb91SSuryakanth Sekar { 997d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>( 998d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: Setting username failed."); 999d509eb91SSuryakanth Sekar } 1000d509eb91SSuryakanth Sekar 1001d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable); 1002d509eb91SSuryakanth Sekar } 1003d509eb91SSuryakanth Sekar 1004fc5e985bSRichard Marian Thomaiyar /** @brief implementes setting password for special user 1005fc5e985bSRichard Marian Thomaiyar * @param[in] specialUserIndex 1006fc5e985bSRichard Marian Thomaiyar * @param[in] userPassword - new password in 20 bytes 1007fc5e985bSRichard Marian Thomaiyar * @returns ipmi completion code. 1008fc5e985bSRichard Marian Thomaiyar */ 1009fc5e985bSRichard Marian Thomaiyar ipmi::RspType<> ipmiOEMSetSpecialUserPassword(ipmi::Context::ptr ctx, 1010fc5e985bSRichard Marian Thomaiyar uint8_t specialUserIndex, 1011fc5e985bSRichard Marian Thomaiyar std::vector<uint8_t> userPassword) 1012fc5e985bSRichard Marian Thomaiyar { 1013fc5e985bSRichard Marian Thomaiyar ChannelInfo chInfo; 1014fc5e985bSRichard Marian Thomaiyar try 1015fc5e985bSRichard Marian Thomaiyar { 1016fc5e985bSRichard Marian Thomaiyar getChannelInfo(ctx->channel, chInfo); 1017fc5e985bSRichard Marian Thomaiyar } 1018fc5e985bSRichard Marian Thomaiyar catch (sdbusplus::exception_t& e) 1019fc5e985bSRichard Marian Thomaiyar { 1020fc5e985bSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 1021fc5e985bSRichard Marian Thomaiyar "ipmiOEMSetSpecialUserPassword: Failed to get Channel Info", 1022fc5e985bSRichard Marian Thomaiyar phosphor::logging::entry("MSG: %s", e.description())); 1023fc5e985bSRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 1024fc5e985bSRichard Marian Thomaiyar } 1025fc5e985bSRichard Marian Thomaiyar if (chInfo.mediumType != 1026fc5e985bSRichard Marian Thomaiyar static_cast<uint8_t>(EChannelMediumType::systemInterface)) 1027fc5e985bSRichard Marian Thomaiyar { 1028fc5e985bSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 1029fc5e985bSRichard Marian Thomaiyar "ipmiOEMSetSpecialUserPassword: Error - supported only in KCS " 1030fc5e985bSRichard Marian Thomaiyar "interface"); 1031fc5e985bSRichard Marian Thomaiyar return ipmi::responseCommandNotAvailable(); 1032fc5e985bSRichard Marian Thomaiyar } 1033fc5e985bSRichard Marian Thomaiyar if (specialUserIndex != 0) 1034fc5e985bSRichard Marian Thomaiyar { 1035fc5e985bSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 1036fc5e985bSRichard Marian Thomaiyar "ipmiOEMSetSpecialUserPassword: Invalid user account"); 1037fc5e985bSRichard Marian Thomaiyar return ipmi::responseParmOutOfRange(); 1038fc5e985bSRichard Marian Thomaiyar } 1039fc5e985bSRichard Marian Thomaiyar constexpr uint8_t minPasswordSizeRequired = 6; 1040fc5e985bSRichard Marian Thomaiyar if (userPassword.size() < minPasswordSizeRequired || 1041fc5e985bSRichard Marian Thomaiyar userPassword.size() > ipmi::maxIpmi20PasswordSize) 1042fc5e985bSRichard Marian Thomaiyar { 1043fc5e985bSRichard Marian Thomaiyar return ipmi::responseReqDataLenInvalid(); 1044fc5e985bSRichard Marian Thomaiyar } 1045fc5e985bSRichard Marian Thomaiyar std::string passwd; 1046fc5e985bSRichard Marian Thomaiyar passwd.assign(reinterpret_cast<const char*>(userPassword.data()), 1047fc5e985bSRichard Marian Thomaiyar userPassword.size()); 1048fc5e985bSRichard Marian Thomaiyar return ipmi::response(ipmiSetSpecialUserPassword("root", passwd)); 1049fc5e985bSRichard Marian Thomaiyar } 1050fc5e985bSRichard Marian Thomaiyar 105145f04988SKuiying Wang namespace ledAction 105245f04988SKuiying Wang { 105345f04988SKuiying Wang using namespace sdbusplus::xyz::openbmc_project::Led::server; 105445f04988SKuiying Wang std::map<Physical::Action, uint8_t> actionDbusToIpmi = { 105545f04988SKuiying Wang {Physical::Action::Off, 0x00}, 105645f04988SKuiying Wang {Physical::Action::On, 0x10}, 105745f04988SKuiying Wang {Physical::Action::Blink, 0x01}}; 105845f04988SKuiying Wang 105945f04988SKuiying Wang std::map<uint8_t, std::string> offsetObjPath = { 106045f04988SKuiying Wang {2, statusAmberObjPath}, {4, statusGreenObjPath}, {6, identifyLEDObjPath}}; 106145f04988SKuiying Wang 106245f04988SKuiying Wang } // namespace ledAction 106345f04988SKuiying Wang 106445f04988SKuiying Wang int8_t getLEDState(sdbusplus::bus::bus& bus, const std::string& intf, 106545f04988SKuiying Wang const std::string& objPath, uint8_t& state) 106645f04988SKuiying Wang { 106745f04988SKuiying Wang try 106845f04988SKuiying Wang { 106945f04988SKuiying Wang std::string service = getService(bus, intf, objPath); 107045f04988SKuiying Wang Value stateValue = 107145f04988SKuiying Wang getDbusProperty(bus, service, objPath, intf, "State"); 10728166c8d7SVernon Mauery std::string strState = std::get<std::string>(stateValue); 107345f04988SKuiying Wang state = ledAction::actionDbusToIpmi.at( 107445f04988SKuiying Wang sdbusplus::xyz::openbmc_project::Led::server::Physical:: 107545f04988SKuiying Wang convertActionFromString(strState)); 107645f04988SKuiying Wang } 107745f04988SKuiying Wang catch (sdbusplus::exception::SdBusError& e) 107845f04988SKuiying Wang { 107945f04988SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 108045f04988SKuiying Wang return -1; 108145f04988SKuiying Wang } 108245f04988SKuiying Wang return 0; 108345f04988SKuiying Wang } 108445f04988SKuiying Wang 108545f04988SKuiying Wang ipmi_ret_t ipmiOEMGetLEDStatus(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 108645f04988SKuiying Wang ipmi_request_t request, ipmi_response_t response, 108745f04988SKuiying Wang ipmi_data_len_t dataLen, ipmi_context_t context) 108845f04988SKuiying Wang { 108945f04988SKuiying Wang uint8_t* resp = reinterpret_cast<uint8_t*>(response); 109045f04988SKuiying Wang // LED Status 109145f04988SKuiying Wang //[1:0] = Reserved 109245f04988SKuiying Wang //[3:2] = Status(Amber) 109345f04988SKuiying Wang //[5:4] = Status(Green) 109445f04988SKuiying Wang //[7:6] = System Identify 109545f04988SKuiying Wang // Status definitions: 109645f04988SKuiying Wang // 00b = Off 109745f04988SKuiying Wang // 01b = Blink 109845f04988SKuiying Wang // 10b = On 109945f04988SKuiying Wang // 11b = invalid 110045f04988SKuiying Wang if (*dataLen != 0) 110145f04988SKuiying Wang { 110245f04988SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 110345f04988SKuiying Wang "oem_get_led_status: invalid input len!"); 110445f04988SKuiying Wang *dataLen = 0; 110545f04988SKuiying Wang return IPMI_CC_REQ_DATA_LEN_INVALID; 110645f04988SKuiying Wang } 110745f04988SKuiying Wang 110845f04988SKuiying Wang phosphor::logging::log<phosphor::logging::level::DEBUG>("GET led status"); 110945f04988SKuiying Wang *resp = 0; 111045f04988SKuiying Wang *dataLen = 0; 111115419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 111245f04988SKuiying Wang for (auto it = ledAction::offsetObjPath.begin(); 111345f04988SKuiying Wang it != ledAction::offsetObjPath.end(); ++it) 111445f04988SKuiying Wang { 111545f04988SKuiying Wang uint8_t state = 0; 111615419dd5SVernon Mauery if (-1 == getLEDState(*dbus, ledIntf, it->second, state)) 111745f04988SKuiying Wang { 111845f04988SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>( 111945f04988SKuiying Wang "oem_get_led_status: fail to get ID LED status!"); 112045f04988SKuiying Wang return IPMI_CC_UNSPECIFIED_ERROR; 112145f04988SKuiying Wang } 112245f04988SKuiying Wang *resp |= state << it->first; 112345f04988SKuiying Wang } 112445f04988SKuiying Wang 112545f04988SKuiying Wang *dataLen = sizeof(*resp); 112645f04988SKuiying Wang return IPMI_CC_OK; 112745f04988SKuiying Wang } 112845f04988SKuiying Wang 112923737fe3SYong Li ipmi_ret_t ipmiOEMCfgHostSerialPortSpeed(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 113023737fe3SYong Li ipmi_request_t request, 113123737fe3SYong Li ipmi_response_t response, 113223737fe3SYong Li ipmi_data_len_t dataLen, 113323737fe3SYong Li ipmi_context_t context) 113423737fe3SYong Li { 113523737fe3SYong Li CfgHostSerialReq* req = reinterpret_cast<CfgHostSerialReq*>(request); 113623737fe3SYong Li uint8_t* resp = reinterpret_cast<uint8_t*>(response); 113723737fe3SYong Li 113823737fe3SYong Li if (*dataLen == 0) 113923737fe3SYong Li { 114023737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 114123737fe3SYong Li "CfgHostSerial: invalid input len!", 114223737fe3SYong Li phosphor::logging::entry("LEN=%d", *dataLen)); 114323737fe3SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID; 114423737fe3SYong Li } 114523737fe3SYong Li 114623737fe3SYong Li switch (req->command) 114723737fe3SYong Li { 114823737fe3SYong Li case getHostSerialCfgCmd: 114923737fe3SYong Li { 115023737fe3SYong Li if (*dataLen != 1) 115123737fe3SYong Li { 115223737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 115323737fe3SYong Li "CfgHostSerial: invalid input len!"); 115423737fe3SYong Li *dataLen = 0; 115523737fe3SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID; 115623737fe3SYong Li } 115723737fe3SYong Li 115823737fe3SYong Li *dataLen = 0; 115923737fe3SYong Li 116023737fe3SYong Li boost::process::ipstream is; 116123737fe3SYong Li std::vector<std::string> data; 116223737fe3SYong Li std::string line; 116323737fe3SYong Li boost::process::child c1(fwGetEnvCmd, "-n", fwHostSerailCfgEnvName, 116423737fe3SYong Li boost::process::std_out > is); 116523737fe3SYong Li 116623737fe3SYong Li while (c1.running() && std::getline(is, line) && !line.empty()) 116723737fe3SYong Li { 116823737fe3SYong Li data.push_back(line); 116923737fe3SYong Li } 117023737fe3SYong Li 117123737fe3SYong Li c1.wait(); 117223737fe3SYong Li if (c1.exit_code()) 117323737fe3SYong Li { 117423737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 117523737fe3SYong Li "CfgHostSerial:: error on execute", 117623737fe3SYong Li phosphor::logging::entry("EXECUTE=%s", fwSetEnvCmd)); 117723737fe3SYong Li // Using the default value 117823737fe3SYong Li *resp = 0; 117923737fe3SYong Li } 118023737fe3SYong Li else 118123737fe3SYong Li { 118223737fe3SYong Li if (data.size() != 1) 118323737fe3SYong Li { 118423737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 118523737fe3SYong Li "CfgHostSerial:: error on read env"); 118623737fe3SYong Li return IPMI_CC_UNSPECIFIED_ERROR; 118723737fe3SYong Li } 118823737fe3SYong Li try 118923737fe3SYong Li { 119023737fe3SYong Li unsigned long tmp = std::stoul(data[0]); 119123737fe3SYong Li if (tmp > std::numeric_limits<uint8_t>::max()) 119223737fe3SYong Li { 119323737fe3SYong Li throw std::out_of_range("Out of range"); 119423737fe3SYong Li } 119523737fe3SYong Li *resp = static_cast<uint8_t>(tmp); 119623737fe3SYong Li } 119723737fe3SYong Li catch (const std::invalid_argument& e) 119823737fe3SYong Li { 119923737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 120023737fe3SYong Li "invalid config ", 120123737fe3SYong Li phosphor::logging::entry("ERR=%s", e.what())); 120223737fe3SYong Li return IPMI_CC_UNSPECIFIED_ERROR; 120323737fe3SYong Li } 120423737fe3SYong Li catch (const std::out_of_range& e) 120523737fe3SYong Li { 120623737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 120723737fe3SYong Li "out_of_range config ", 120823737fe3SYong Li phosphor::logging::entry("ERR=%s", e.what())); 120923737fe3SYong Li return IPMI_CC_UNSPECIFIED_ERROR; 121023737fe3SYong Li } 121123737fe3SYong Li } 121223737fe3SYong Li 121323737fe3SYong Li *dataLen = 1; 121423737fe3SYong Li break; 121523737fe3SYong Li } 121623737fe3SYong Li case setHostSerialCfgCmd: 121723737fe3SYong Li { 121823737fe3SYong Li if (*dataLen != sizeof(CfgHostSerialReq)) 121923737fe3SYong Li { 122023737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 122123737fe3SYong Li "CfgHostSerial: invalid input len!"); 122223737fe3SYong Li *dataLen = 0; 122323737fe3SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID; 122423737fe3SYong Li } 122523737fe3SYong Li 122623737fe3SYong Li *dataLen = 0; 122723737fe3SYong Li 122823737fe3SYong Li if (req->parameter > HostSerialCfgParamMax) 122923737fe3SYong Li { 123023737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 123123737fe3SYong Li "CfgHostSerial: invalid input!"); 123223737fe3SYong Li return IPMI_CC_INVALID_FIELD_REQUEST; 123323737fe3SYong Li } 123423737fe3SYong Li 123523737fe3SYong Li boost::process::child c1(fwSetEnvCmd, fwHostSerailCfgEnvName, 123623737fe3SYong Li std::to_string(req->parameter)); 123723737fe3SYong Li 123823737fe3SYong Li c1.wait(); 123923737fe3SYong Li if (c1.exit_code()) 124023737fe3SYong Li { 124123737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 124223737fe3SYong Li "CfgHostSerial:: error on execute", 124323737fe3SYong Li phosphor::logging::entry("EXECUTE=%s", fwGetEnvCmd)); 124423737fe3SYong Li return IPMI_CC_UNSPECIFIED_ERROR; 124523737fe3SYong Li } 124623737fe3SYong Li break; 124723737fe3SYong Li } 124823737fe3SYong Li default: 124923737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>( 125023737fe3SYong Li "CfgHostSerial: invalid input!"); 125123737fe3SYong Li *dataLen = 0; 125223737fe3SYong Li return IPMI_CC_INVALID_FIELD_REQUEST; 125323737fe3SYong Li } 125423737fe3SYong Li 125523737fe3SYong Li return IPMI_CC_OK; 125623737fe3SYong Li } 125723737fe3SYong Li 125891244a6aSJames Feist constexpr const char* thermalModeInterface = 125991244a6aSJames Feist "xyz.openbmc_project.Control.ThermalMode"; 126091244a6aSJames Feist constexpr const char* thermalModePath = 126191244a6aSJames Feist "/xyz/openbmc_project/control/thermal_mode"; 126291244a6aSJames Feist 126391244a6aSJames Feist bool getFanProfileInterface( 126491244a6aSJames Feist sdbusplus::bus::bus& bus, 126591244a6aSJames Feist boost::container::flat_map< 126691244a6aSJames Feist std::string, std::variant<std::vector<std::string>, std::string>>& resp) 126791244a6aSJames Feist { 126891244a6aSJames Feist auto call = bus.new_method_call(settingsBusName, thermalModePath, PROP_INTF, 126991244a6aSJames Feist "GetAll"); 127091244a6aSJames Feist call.append(thermalModeInterface); 127191244a6aSJames Feist try 127291244a6aSJames Feist { 127391244a6aSJames Feist auto data = bus.call(call); 127491244a6aSJames Feist data.read(resp); 127591244a6aSJames Feist } 127691244a6aSJames Feist catch (sdbusplus::exception_t& e) 127791244a6aSJames Feist { 127891244a6aSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 127991244a6aSJames Feist "getFanProfileInterface: can't get thermal mode!", 128091244a6aSJames Feist phosphor::logging::entry("ERR=%s", e.what())); 128191244a6aSJames Feist return false; 128291244a6aSJames Feist } 128391244a6aSJames Feist return true; 128491244a6aSJames Feist } 128591244a6aSJames Feist 128691244a6aSJames Feist ipmi_ret_t ipmiOEMSetFanConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd, 128791244a6aSJames Feist ipmi_request_t request, ipmi_response_t response, 128891244a6aSJames Feist ipmi_data_len_t dataLen, ipmi_context_t context) 128991244a6aSJames Feist { 129091244a6aSJames Feist 129191244a6aSJames Feist if (*dataLen < 2 || *dataLen > 7) 129291244a6aSJames Feist { 129391244a6aSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 129491244a6aSJames Feist "ipmiOEMSetFanConfig: invalid input len!"); 129591244a6aSJames Feist *dataLen = 0; 129691244a6aSJames Feist return IPMI_CC_REQ_DATA_LEN_INVALID; 129791244a6aSJames Feist } 129891244a6aSJames Feist 129991244a6aSJames Feist // todo: tell bios to only send first 2 bytes 130091244a6aSJames Feist 130191244a6aSJames Feist SetFanConfigReq* req = reinterpret_cast<SetFanConfigReq*>(request); 130291244a6aSJames Feist boost::container::flat_map< 130391244a6aSJames Feist std::string, std::variant<std::vector<std::string>, std::string>> 130491244a6aSJames Feist profileData; 130515419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 130615419dd5SVernon Mauery if (!getFanProfileInterface(*dbus, profileData)) 130791244a6aSJames Feist { 130891244a6aSJames Feist return IPMI_CC_UNSPECIFIED_ERROR; 130991244a6aSJames Feist } 131091244a6aSJames Feist 131191244a6aSJames Feist std::vector<std::string>* supported = 131291244a6aSJames Feist std::get_if<std::vector<std::string>>(&profileData["Supported"]); 131391244a6aSJames Feist if (supported == nullptr) 131491244a6aSJames Feist { 131591244a6aSJames Feist return IPMI_CC_INVALID_FIELD_REQUEST; 131691244a6aSJames Feist } 131791244a6aSJames Feist std::string mode; 131891244a6aSJames Feist if (req->flags & 131991244a6aSJames Feist (1 << static_cast<uint8_t>(setFanProfileFlags::setPerfAcousMode))) 132091244a6aSJames Feist { 132191244a6aSJames Feist bool performanceMode = 132291244a6aSJames Feist (req->flags & (1 << static_cast<uint8_t>( 132391244a6aSJames Feist setFanProfileFlags::performAcousSelect))) > 0; 132491244a6aSJames Feist 132591244a6aSJames Feist if (performanceMode) 132691244a6aSJames Feist { 132791244a6aSJames Feist 132891244a6aSJames Feist if (std::find(supported->begin(), supported->end(), 132991244a6aSJames Feist "Performance") != supported->end()) 133091244a6aSJames Feist { 133191244a6aSJames Feist mode = "Performance"; 133291244a6aSJames Feist } 133391244a6aSJames Feist } 133491244a6aSJames Feist else 133591244a6aSJames Feist { 133691244a6aSJames Feist 133791244a6aSJames Feist if (std::find(supported->begin(), supported->end(), "Acoustic") != 133891244a6aSJames Feist supported->end()) 133991244a6aSJames Feist { 134091244a6aSJames Feist mode = "Acoustic"; 134191244a6aSJames Feist } 134291244a6aSJames Feist } 134391244a6aSJames Feist if (mode.empty()) 134491244a6aSJames Feist { 134591244a6aSJames Feist return IPMI_CC_INVALID_FIELD_REQUEST; 134691244a6aSJames Feist } 134715419dd5SVernon Mauery setDbusProperty(*dbus, settingsBusName, thermalModePath, 134891244a6aSJames Feist thermalModeInterface, "Current", mode); 134991244a6aSJames Feist } 135091244a6aSJames Feist 135191244a6aSJames Feist return IPMI_CC_OK; 135291244a6aSJames Feist } 135391244a6aSJames Feist 13545b693637SJames Feist ipmi::RspType<uint8_t, // profile support map 13555b693637SJames Feist uint8_t, // fan control profile enable 13565b693637SJames Feist uint8_t, // flags 13575b693637SJames Feist uint32_t // dimm presence bit map 13585b693637SJames Feist > 13595b693637SJames Feist ipmiOEMGetFanConfig(uint8_t dimmGroupId) 136091244a6aSJames Feist { 136191244a6aSJames Feist boost::container::flat_map< 136291244a6aSJames Feist std::string, std::variant<std::vector<std::string>, std::string>> 136391244a6aSJames Feist profileData; 136491244a6aSJames Feist 136515419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 136615419dd5SVernon Mauery if (!getFanProfileInterface(*dbus, profileData)) 136791244a6aSJames Feist { 13685b693637SJames Feist return ipmi::responseResponseError(); 136991244a6aSJames Feist } 137091244a6aSJames Feist 137191244a6aSJames Feist std::string* current = std::get_if<std::string>(&profileData["Current"]); 137291244a6aSJames Feist 137391244a6aSJames Feist if (current == nullptr) 137491244a6aSJames Feist { 137591244a6aSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 137691244a6aSJames Feist "ipmiOEMGetFanConfig: can't get current mode!"); 13775b693637SJames Feist return ipmi::responseResponseError(); 137891244a6aSJames Feist } 137991244a6aSJames Feist bool performance = (*current == "Performance"); 138091244a6aSJames Feist 13815b693637SJames Feist uint8_t flags = 0; 138291244a6aSJames Feist if (performance) 138391244a6aSJames Feist { 13845b693637SJames Feist flags |= 1 << 2; 138591244a6aSJames Feist } 138691244a6aSJames Feist 13875b693637SJames Feist return ipmi::responseSuccess(0, 0, flags, 0); 138891244a6aSJames Feist } 13895f957cafSJames Feist constexpr const char* cfmLimitSettingPath = 13905f957cafSJames Feist "/xyz/openbmc_project/control/cfm_limit"; 13915f957cafSJames Feist constexpr const char* cfmLimitIface = "xyz.openbmc_project.Control.CFMLimit"; 1392faa4f223SJames Feist constexpr const size_t legacyExitAirSensorNumber = 0x2e; 139309f6b604SJames Feist constexpr const size_t legacyPCHSensorNumber = 0x22; 139409f6b604SJames Feist constexpr const char* exitAirPathName = "Exit_Air"; 139509f6b604SJames Feist constexpr const char* pchPathName = "SSB_Temp"; 1396acc8a4ebSJames Feist constexpr const char* pidConfigurationIface = 1397acc8a4ebSJames Feist "xyz.openbmc_project.Configuration.Pid"; 1398faa4f223SJames Feist 139909f6b604SJames Feist static std::string getConfigPath(const std::string& name) 1400faa4f223SJames Feist { 140115419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 1402faa4f223SJames Feist auto method = 140315419dd5SVernon Mauery dbus->new_method_call("xyz.openbmc_project.ObjectMapper", 1404faa4f223SJames Feist "/xyz/openbmc_project/object_mapper", 1405faa4f223SJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree"); 1406faa4f223SJames Feist 1407acc8a4ebSJames Feist method.append("/", 0, std::array<const char*, 1>{pidConfigurationIface}); 1408faa4f223SJames Feist std::string path; 1409faa4f223SJames Feist GetSubTreeType resp; 1410faa4f223SJames Feist try 1411faa4f223SJames Feist { 141215419dd5SVernon Mauery auto reply = dbus->call(method); 1413faa4f223SJames Feist reply.read(resp); 1414faa4f223SJames Feist } 1415faa4f223SJames Feist catch (sdbusplus::exception_t&) 1416faa4f223SJames Feist { 1417faa4f223SJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1418faa4f223SJames Feist "ipmiOEMGetFscParameter: mapper error"); 1419faa4f223SJames Feist }; 142009f6b604SJames Feist auto config = 142109f6b604SJames Feist std::find_if(resp.begin(), resp.end(), [&name](const auto& pair) { 142209f6b604SJames Feist return pair.first.find(name) != std::string::npos; 1423faa4f223SJames Feist }); 1424faa4f223SJames Feist if (config != resp.end()) 1425faa4f223SJames Feist { 1426faa4f223SJames Feist path = std::move(config->first); 1427faa4f223SJames Feist } 1428faa4f223SJames Feist return path; 1429faa4f223SJames Feist } 14305f957cafSJames Feist 1431acc8a4ebSJames Feist // flat map to make alphabetical 1432acc8a4ebSJames Feist static boost::container::flat_map<std::string, PropertyMap> getPidConfigs() 1433acc8a4ebSJames Feist { 1434acc8a4ebSJames Feist boost::container::flat_map<std::string, PropertyMap> ret; 143515419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 1436acc8a4ebSJames Feist auto method = 143715419dd5SVernon Mauery dbus->new_method_call("xyz.openbmc_project.ObjectMapper", 1438acc8a4ebSJames Feist "/xyz/openbmc_project/object_mapper", 1439acc8a4ebSJames Feist "xyz.openbmc_project.ObjectMapper", "GetSubTree"); 1440acc8a4ebSJames Feist 1441acc8a4ebSJames Feist method.append("/", 0, std::array<const char*, 1>{pidConfigurationIface}); 1442acc8a4ebSJames Feist GetSubTreeType resp; 1443acc8a4ebSJames Feist 1444acc8a4ebSJames Feist try 1445acc8a4ebSJames Feist { 144615419dd5SVernon Mauery auto reply = dbus->call(method); 1447acc8a4ebSJames Feist reply.read(resp); 1448acc8a4ebSJames Feist } 1449acc8a4ebSJames Feist catch (sdbusplus::exception_t&) 1450acc8a4ebSJames Feist { 1451acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1452acc8a4ebSJames Feist "getFanConfigPaths: mapper error"); 1453acc8a4ebSJames Feist }; 1454acc8a4ebSJames Feist for (const auto& [path, objects] : resp) 1455acc8a4ebSJames Feist { 1456acc8a4ebSJames Feist if (objects.empty()) 1457acc8a4ebSJames Feist { 1458acc8a4ebSJames Feist continue; // should be impossible 1459acc8a4ebSJames Feist } 1460be560b09SZhu, Yunge 1461be560b09SZhu, Yunge try 1462be560b09SZhu, Yunge { 146315419dd5SVernon Mauery ret.emplace(path, 146415419dd5SVernon Mauery getAllDbusProperties(*dbus, objects[0].first, path, 1465acc8a4ebSJames Feist pidConfigurationIface)); 1466acc8a4ebSJames Feist } 1467be560b09SZhu, Yunge catch (sdbusplus::exception_t& e) 1468be560b09SZhu, Yunge { 1469be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>( 1470be560b09SZhu, Yunge "getPidConfigs: can't get DbusProperties!", 1471be560b09SZhu, Yunge phosphor::logging::entry("ERR=%s", e.what())); 1472be560b09SZhu, Yunge } 1473be560b09SZhu, Yunge } 1474acc8a4ebSJames Feist return ret; 1475acc8a4ebSJames Feist } 1476acc8a4ebSJames Feist 1477acc8a4ebSJames Feist ipmi::RspType<uint8_t> ipmiOEMGetFanSpeedOffset(void) 1478acc8a4ebSJames Feist { 1479acc8a4ebSJames Feist boost::container::flat_map<std::string, PropertyMap> data = getPidConfigs(); 1480acc8a4ebSJames Feist if (data.empty()) 1481acc8a4ebSJames Feist { 1482acc8a4ebSJames Feist return ipmi::responseResponseError(); 1483acc8a4ebSJames Feist } 1484acc8a4ebSJames Feist uint8_t minOffset = std::numeric_limits<uint8_t>::max(); 1485acc8a4ebSJames Feist for (const auto& [_, pid] : data) 1486acc8a4ebSJames Feist { 1487acc8a4ebSJames Feist auto findClass = pid.find("Class"); 1488acc8a4ebSJames Feist if (findClass == pid.end()) 1489acc8a4ebSJames Feist { 1490acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1491acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found illegal pid " 1492acc8a4ebSJames Feist "configurations"); 1493acc8a4ebSJames Feist return ipmi::responseResponseError(); 1494acc8a4ebSJames Feist } 1495acc8a4ebSJames Feist std::string type = std::get<std::string>(findClass->second); 1496acc8a4ebSJames Feist if (type == "fan") 1497acc8a4ebSJames Feist { 1498acc8a4ebSJames Feist auto findOutLimit = pid.find("OutLimitMin"); 1499acc8a4ebSJames Feist if (findOutLimit == pid.end()) 1500acc8a4ebSJames Feist { 1501acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1502acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found illegal pid " 1503acc8a4ebSJames Feist "configurations"); 1504acc8a4ebSJames Feist return ipmi::responseResponseError(); 1505acc8a4ebSJames Feist } 1506acc8a4ebSJames Feist // get the min out of all the offsets 1507acc8a4ebSJames Feist minOffset = std::min( 1508acc8a4ebSJames Feist minOffset, 1509acc8a4ebSJames Feist static_cast<uint8_t>(std::get<double>(findOutLimit->second))); 1510acc8a4ebSJames Feist } 1511acc8a4ebSJames Feist } 1512acc8a4ebSJames Feist if (minOffset == std::numeric_limits<uint8_t>::max()) 1513acc8a4ebSJames Feist { 1514acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1515acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found no fan configurations!"); 1516acc8a4ebSJames Feist return ipmi::responseResponseError(); 1517acc8a4ebSJames Feist } 1518acc8a4ebSJames Feist 1519acc8a4ebSJames Feist return ipmi::responseSuccess(minOffset); 1520acc8a4ebSJames Feist } 1521acc8a4ebSJames Feist 1522acc8a4ebSJames Feist ipmi::RspType<> ipmiOEMSetFanSpeedOffset(uint8_t offset) 1523acc8a4ebSJames Feist { 1524acc8a4ebSJames Feist boost::container::flat_map<std::string, PropertyMap> data = getPidConfigs(); 1525acc8a4ebSJames Feist if (data.empty()) 1526acc8a4ebSJames Feist { 1527acc8a4ebSJames Feist 1528acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1529acc8a4ebSJames Feist "ipmiOEMSetFanSpeedOffset: found no pid configurations!"); 1530acc8a4ebSJames Feist return ipmi::responseResponseError(); 1531acc8a4ebSJames Feist } 1532acc8a4ebSJames Feist 153315419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 1534acc8a4ebSJames Feist bool found = false; 1535acc8a4ebSJames Feist for (const auto& [path, pid] : data) 1536acc8a4ebSJames Feist { 1537acc8a4ebSJames Feist auto findClass = pid.find("Class"); 1538acc8a4ebSJames Feist if (findClass == pid.end()) 1539acc8a4ebSJames Feist { 1540acc8a4ebSJames Feist 1541acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1542acc8a4ebSJames Feist "ipmiOEMSetFanSpeedOffset: found illegal pid " 1543acc8a4ebSJames Feist "configurations"); 1544acc8a4ebSJames Feist return ipmi::responseResponseError(); 1545acc8a4ebSJames Feist } 1546acc8a4ebSJames Feist std::string type = std::get<std::string>(findClass->second); 1547acc8a4ebSJames Feist if (type == "fan") 1548acc8a4ebSJames Feist { 1549acc8a4ebSJames Feist auto findOutLimit = pid.find("OutLimitMin"); 1550acc8a4ebSJames Feist if (findOutLimit == pid.end()) 1551acc8a4ebSJames Feist { 1552acc8a4ebSJames Feist 1553acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1554acc8a4ebSJames Feist "ipmiOEMSetFanSpeedOffset: found illegal pid " 1555acc8a4ebSJames Feist "configurations"); 1556acc8a4ebSJames Feist return ipmi::responseResponseError(); 1557acc8a4ebSJames Feist } 155815419dd5SVernon Mauery ipmi::setDbusProperty(*dbus, "xyz.openbmc_project.EntityManager", 1559acc8a4ebSJames Feist path, pidConfigurationIface, "OutLimitMin", 1560acc8a4ebSJames Feist static_cast<double>(offset)); 1561acc8a4ebSJames Feist found = true; 1562acc8a4ebSJames Feist } 1563acc8a4ebSJames Feist } 1564acc8a4ebSJames Feist if (!found) 1565acc8a4ebSJames Feist { 1566acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1567acc8a4ebSJames Feist "ipmiOEMSetFanSpeedOffset: set no fan offsets"); 1568acc8a4ebSJames Feist return ipmi::responseResponseError(); 1569acc8a4ebSJames Feist } 1570acc8a4ebSJames Feist 1571acc8a4ebSJames Feist return ipmi::responseSuccess(); 1572acc8a4ebSJames Feist } 1573acc8a4ebSJames Feist 1574acc8a4ebSJames Feist ipmi::RspType<> ipmiOEMSetFscParameter(uint8_t command, uint8_t param1, 1575acc8a4ebSJames Feist uint8_t param2) 15765f957cafSJames Feist { 15775f957cafSJames Feist constexpr const size_t disableLimiting = 0x0; 15785f957cafSJames Feist 157915419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 1580acc8a4ebSJames Feist if (command == static_cast<uint8_t>(setFscParamFlags::tcontrol)) 15815f957cafSJames Feist { 158209f6b604SJames Feist std::string pathName; 1583acc8a4ebSJames Feist if (param1 == legacyExitAirSensorNumber) 1584faa4f223SJames Feist { 158509f6b604SJames Feist pathName = exitAirPathName; 158609f6b604SJames Feist } 158709f6b604SJames Feist else if (param1 == legacyPCHSensorNumber) 158809f6b604SJames Feist { 158909f6b604SJames Feist pathName = pchPathName; 1590faa4f223SJames Feist } 1591faa4f223SJames Feist else 1592faa4f223SJames Feist { 1593acc8a4ebSJames Feist return ipmi::responseParmOutOfRange(); 1594faa4f223SJames Feist } 159509f6b604SJames Feist std::string path = getConfigPath(pathName); 159609f6b604SJames Feist ipmi::setDbusProperty(*dbus, "xyz.openbmc_project.EntityManager", path, 159709f6b604SJames Feist pidConfigurationIface, "SetPoint", 159809f6b604SJames Feist static_cast<double>(param2)); 159909f6b604SJames Feist return ipmi::responseSuccess(); 1600faa4f223SJames Feist } 1601acc8a4ebSJames Feist else if (command == static_cast<uint8_t>(setFscParamFlags::cfm)) 16025f957cafSJames Feist { 1603acc8a4ebSJames Feist uint16_t cfm = param1 | (static_cast<uint16_t>(param2) << 8); 16045f957cafSJames Feist 16055f957cafSJames Feist // must be greater than 50 based on eps 16065f957cafSJames Feist if (cfm < 50 && cfm != disableLimiting) 16075f957cafSJames Feist { 1608acc8a4ebSJames Feist return ipmi::responseParmOutOfRange(); 16095f957cafSJames Feist } 16105f957cafSJames Feist 16115f957cafSJames Feist try 16125f957cafSJames Feist { 161315419dd5SVernon Mauery ipmi::setDbusProperty(*dbus, settingsBusName, cfmLimitSettingPath, 16145f957cafSJames Feist cfmLimitIface, "Limit", 16155f957cafSJames Feist static_cast<double>(cfm)); 16165f957cafSJames Feist } 16175f957cafSJames Feist catch (sdbusplus::exception_t& e) 16185f957cafSJames Feist { 16195f957cafSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 16205f957cafSJames Feist "ipmiOEMSetFscParameter: can't set cfm setting!", 16215f957cafSJames Feist phosphor::logging::entry("ERR=%s", e.what())); 1622acc8a4ebSJames Feist return ipmi::responseResponseError(); 16235f957cafSJames Feist } 1624acc8a4ebSJames Feist return ipmi::responseSuccess(); 1625acc8a4ebSJames Feist } 1626acc8a4ebSJames Feist else if (command == static_cast<uint8_t>(setFscParamFlags::maxPwm)) 1627acc8a4ebSJames Feist { 1628acc8a4ebSJames Feist constexpr const size_t maxDomainCount = 8; 1629acc8a4ebSJames Feist uint8_t requestedDomainMask = param1; 1630acc8a4ebSJames Feist boost::container::flat_map data = getPidConfigs(); 1631acc8a4ebSJames Feist if (data.empty()) 1632acc8a4ebSJames Feist { 1633acc8a4ebSJames Feist 1634acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1635acc8a4ebSJames Feist "ipmiOEMSetFscParameter: found no pid configurations!"); 1636acc8a4ebSJames Feist return ipmi::responseResponseError(); 1637acc8a4ebSJames Feist } 1638acc8a4ebSJames Feist size_t count = 0; 1639acc8a4ebSJames Feist for (const auto& [path, pid] : data) 1640acc8a4ebSJames Feist { 1641acc8a4ebSJames Feist auto findClass = pid.find("Class"); 1642acc8a4ebSJames Feist if (findClass == pid.end()) 1643acc8a4ebSJames Feist { 1644acc8a4ebSJames Feist 1645acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1646acc8a4ebSJames Feist "ipmiOEMSetFscParameter: found illegal pid " 1647acc8a4ebSJames Feist "configurations"); 1648acc8a4ebSJames Feist return ipmi::responseResponseError(); 1649acc8a4ebSJames Feist } 1650acc8a4ebSJames Feist std::string type = std::get<std::string>(findClass->second); 1651acc8a4ebSJames Feist if (type == "fan") 1652acc8a4ebSJames Feist { 1653acc8a4ebSJames Feist if (requestedDomainMask & (1 << count)) 1654acc8a4ebSJames Feist { 1655acc8a4ebSJames Feist ipmi::setDbusProperty( 165615419dd5SVernon Mauery *dbus, "xyz.openbmc_project.EntityManager", path, 1657acc8a4ebSJames Feist pidConfigurationIface, "OutLimitMax", 1658acc8a4ebSJames Feist static_cast<double>(param2)); 1659acc8a4ebSJames Feist } 1660acc8a4ebSJames Feist count++; 1661acc8a4ebSJames Feist } 1662acc8a4ebSJames Feist } 1663acc8a4ebSJames Feist return ipmi::responseSuccess(); 16645f957cafSJames Feist } 16655f957cafSJames Feist else 16665f957cafSJames Feist { 16675f957cafSJames Feist // todo other command parts possibly 16685f957cafSJames Feist // tcontrol is handled in peci now 16695f957cafSJames Feist // fan speed offset not implemented yet 16705f957cafSJames Feist // domain pwm limit not implemented 1671acc8a4ebSJames Feist return ipmi::responseParmOutOfRange(); 16725f957cafSJames Feist } 16735f957cafSJames Feist } 16745f957cafSJames Feist 1675acc8a4ebSJames Feist ipmi::RspType< 1676acc8a4ebSJames Feist std::variant<uint8_t, std::array<uint8_t, 2>, std::array<uint16_t, 2>>> 1677acc8a4ebSJames Feist ipmiOEMGetFscParameter(uint8_t command, std::optional<uint8_t> param) 16785f957cafSJames Feist { 167909f6b604SJames Feist constexpr uint8_t legacyDefaultSetpoint = -128; 16805f957cafSJames Feist 168115419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 1682acc8a4ebSJames Feist if (command == static_cast<uint8_t>(setFscParamFlags::tcontrol)) 16835f957cafSJames Feist { 1684acc8a4ebSJames Feist if (!param) 1685acc8a4ebSJames Feist { 1686acc8a4ebSJames Feist return ipmi::responseReqDataLenInvalid(); 16875f957cafSJames Feist } 16885f957cafSJames Feist 168909f6b604SJames Feist std::string pathName; 169009f6b604SJames Feist 169109f6b604SJames Feist if (*param == legacyExitAirSensorNumber) 169209f6b604SJames Feist { 169309f6b604SJames Feist pathName = exitAirPathName; 169409f6b604SJames Feist } 169509f6b604SJames Feist else if (*param == legacyPCHSensorNumber) 169609f6b604SJames Feist { 169709f6b604SJames Feist pathName = pchPathName; 169809f6b604SJames Feist } 169909f6b604SJames Feist else 1700faa4f223SJames Feist { 1701acc8a4ebSJames Feist return ipmi::responseParmOutOfRange(); 1702faa4f223SJames Feist } 170309f6b604SJames Feist 170409f6b604SJames Feist uint8_t setpoint = legacyDefaultSetpoint; 170509f6b604SJames Feist std::string path = getConfigPath(pathName); 1706faa4f223SJames Feist if (path.size()) 1707faa4f223SJames Feist { 170815419dd5SVernon Mauery Value val = ipmi::getDbusProperty( 170915419dd5SVernon Mauery *dbus, "xyz.openbmc_project.EntityManager", path, 171015419dd5SVernon Mauery pidConfigurationIface, "SetPoint"); 1711faa4f223SJames Feist setpoint = std::floor(std::get<double>(val) + 0.5); 1712faa4f223SJames Feist } 1713faa4f223SJames Feist 1714faa4f223SJames Feist // old implementation used to return the "default" and current, we 1715faa4f223SJames Feist // don't make the default readily available so just make both the 1716faa4f223SJames Feist // same 1717faa4f223SJames Feist 1718acc8a4ebSJames Feist return ipmi::responseSuccess( 1719acc8a4ebSJames Feist std::array<uint8_t, 2>{setpoint, setpoint}); 1720faa4f223SJames Feist } 1721acc8a4ebSJames Feist else if (command == static_cast<uint8_t>(setFscParamFlags::maxPwm)) 1722acc8a4ebSJames Feist { 1723acc8a4ebSJames Feist constexpr const size_t maxDomainCount = 8; 1724acc8a4ebSJames Feist 1725acc8a4ebSJames Feist if (!param) 1726acc8a4ebSJames Feist { 1727acc8a4ebSJames Feist return ipmi::responseReqDataLenInvalid(); 1728acc8a4ebSJames Feist } 1729acc8a4ebSJames Feist uint8_t requestedDomain = *param; 1730acc8a4ebSJames Feist if (requestedDomain >= maxDomainCount) 1731acc8a4ebSJames Feist { 1732acc8a4ebSJames Feist return ipmi::responseInvalidFieldRequest(); 1733acc8a4ebSJames Feist } 1734acc8a4ebSJames Feist 1735acc8a4ebSJames Feist boost::container::flat_map data = getPidConfigs(); 1736acc8a4ebSJames Feist if (data.empty()) 1737acc8a4ebSJames Feist { 1738acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1739acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found no pid configurations!"); 1740acc8a4ebSJames Feist return ipmi::responseResponseError(); 1741acc8a4ebSJames Feist } 1742acc8a4ebSJames Feist size_t count = 0; 1743acc8a4ebSJames Feist for (const auto& [_, pid] : data) 1744acc8a4ebSJames Feist { 1745acc8a4ebSJames Feist auto findClass = pid.find("Class"); 1746acc8a4ebSJames Feist if (findClass == pid.end()) 1747acc8a4ebSJames Feist { 1748acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1749acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found illegal pid " 1750acc8a4ebSJames Feist "configurations"); 1751acc8a4ebSJames Feist return ipmi::responseResponseError(); 1752acc8a4ebSJames Feist } 1753acc8a4ebSJames Feist std::string type = std::get<std::string>(findClass->second); 1754acc8a4ebSJames Feist if (type == "fan") 1755acc8a4ebSJames Feist { 1756acc8a4ebSJames Feist if (requestedDomain == count) 1757acc8a4ebSJames Feist { 1758acc8a4ebSJames Feist auto findOutLimit = pid.find("OutLimitMax"); 1759acc8a4ebSJames Feist if (findOutLimit == pid.end()) 1760acc8a4ebSJames Feist { 1761acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1762acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found illegal pid " 1763acc8a4ebSJames Feist "configurations"); 1764acc8a4ebSJames Feist return ipmi::responseResponseError(); 1765acc8a4ebSJames Feist } 1766acc8a4ebSJames Feist 1767acc8a4ebSJames Feist return ipmi::responseSuccess( 1768acc8a4ebSJames Feist static_cast<uint8_t>(std::floor( 1769acc8a4ebSJames Feist std::get<double>(findOutLimit->second) + 0.5))); 1770acc8a4ebSJames Feist } 1771acc8a4ebSJames Feist else 1772acc8a4ebSJames Feist { 1773acc8a4ebSJames Feist count++; 1774acc8a4ebSJames Feist } 1775acc8a4ebSJames Feist } 1776acc8a4ebSJames Feist } 1777acc8a4ebSJames Feist 1778acc8a4ebSJames Feist return ipmi::responseInvalidFieldRequest(); 1779acc8a4ebSJames Feist } 1780acc8a4ebSJames Feist else if (command == static_cast<uint8_t>(setFscParamFlags::cfm)) 17815f957cafSJames Feist { 17825f957cafSJames Feist 17835f957cafSJames Feist /* 17845f957cafSJames Feist DataLen should be 1, but host is sending us an extra bit. As the 1785acc8a4ebSJames Feist previous behavior didn't seem to prevent this, ignore the check for 1786acc8a4ebSJames Feist now. 17875f957cafSJames Feist 1788acc8a4ebSJames Feist if (param) 17895f957cafSJames Feist { 17905f957cafSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 17915f957cafSJames Feist "ipmiOEMGetFscParameter: invalid input len!"); 17925f957cafSJames Feist return IPMI_CC_REQ_DATA_LEN_INVALID; 17935f957cafSJames Feist } 17945f957cafSJames Feist */ 17955f957cafSJames Feist Value cfmLimit; 17965f957cafSJames Feist Value cfmMaximum; 17975f957cafSJames Feist try 17985f957cafSJames Feist { 179915419dd5SVernon Mauery cfmLimit = ipmi::getDbusProperty(*dbus, settingsBusName, 18005f957cafSJames Feist cfmLimitSettingPath, cfmLimitIface, 18015f957cafSJames Feist "Limit"); 18025f957cafSJames Feist cfmMaximum = ipmi::getDbusProperty( 180315419dd5SVernon Mauery *dbus, "xyz.openbmc_project.ExitAirTempSensor", 18045f957cafSJames Feist "/xyz/openbmc_project/control/MaxCFM", cfmLimitIface, "Limit"); 18055f957cafSJames Feist } 18065f957cafSJames Feist catch (sdbusplus::exception_t& e) 18075f957cafSJames Feist { 18085f957cafSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 1809acc8a4ebSJames Feist "ipmiOEMGetFscParameter: can't get cfm setting!", 18105f957cafSJames Feist phosphor::logging::entry("ERR=%s", e.what())); 1811acc8a4ebSJames Feist return ipmi::responseResponseError(); 18125f957cafSJames Feist } 18135f957cafSJames Feist 1814acc8a4ebSJames Feist double cfmMax = std::get<double>(cfmMaximum); 1815acc8a4ebSJames Feist double cfmLim = std::get<double>(cfmLimit); 1816acc8a4ebSJames Feist 1817acc8a4ebSJames Feist cfmLim = std::floor(cfmLim + 0.5); 1818acc8a4ebSJames Feist cfmMax = std::floor(cfmMax + 0.5); 1819acc8a4ebSJames Feist uint16_t cfmLimResp = static_cast<uint16_t>(cfmLim); 1820acc8a4ebSJames Feist uint16_t cfmMaxResp = static_cast<uint16_t>(cfmMax); 1821acc8a4ebSJames Feist 1822acc8a4ebSJames Feist return ipmi::responseSuccess( 1823acc8a4ebSJames Feist std::array<uint16_t, 2>{cfmLimResp, cfmMaxResp}); 18245f957cafSJames Feist } 18255f957cafSJames Feist 18265f957cafSJames Feist else 18275f957cafSJames Feist { 18285f957cafSJames Feist // todo other command parts possibly 18295f957cafSJames Feist // domain pwm limit not implemented 1830acc8a4ebSJames Feist return ipmi::responseParmOutOfRange(); 18315f957cafSJames Feist } 18325f957cafSJames Feist } 18335f957cafSJames Feist 1834773703a5SCheng C Yang using crConfigVariant = 1835773703a5SCheng C Yang std::variant<bool, uint8_t, uint32_t, std::vector<uint8_t>, std::string>; 1836773703a5SCheng C Yang 1837773703a5SCheng C Yang int setCRConfig(ipmi::Context::ptr ctx, const std::string& property, 1838773703a5SCheng C Yang const crConfigVariant& value, 1839773703a5SCheng C Yang std::chrono::microseconds timeout = ipmi::IPMI_DBUS_TIMEOUT) 1840773703a5SCheng C Yang { 1841773703a5SCheng C Yang boost::system::error_code ec; 1842773703a5SCheng C Yang ctx->bus->yield_method_call<void>( 184328c7290cSJames Feist ctx->yield, ec, "xyz.openbmc_project.Settings", 1844773703a5SCheng C Yang "/xyz/openbmc_project/control/power_supply_redundancy", 1845773703a5SCheng C Yang "org.freedesktop.DBus.Properties", "Set", 1846773703a5SCheng C Yang "xyz.openbmc_project.Control.PowerSupplyRedundancy", property, value); 1847773703a5SCheng C Yang if (ec) 1848773703a5SCheng C Yang { 1849773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 1850773703a5SCheng C Yang "Failed to set dbus property to cold redundancy"); 1851773703a5SCheng C Yang return -1; 1852773703a5SCheng C Yang } 1853773703a5SCheng C Yang 1854773703a5SCheng C Yang return 0; 1855773703a5SCheng C Yang } 1856773703a5SCheng C Yang 1857773703a5SCheng C Yang int getCRConfig(ipmi::Context::ptr ctx, const std::string& property, 1858773703a5SCheng C Yang crConfigVariant& value, 1859773703a5SCheng C Yang std::chrono::microseconds timeout = ipmi::IPMI_DBUS_TIMEOUT) 1860773703a5SCheng C Yang { 1861773703a5SCheng C Yang boost::system::error_code ec; 1862773703a5SCheng C Yang value = ctx->bus->yield_method_call<crConfigVariant>( 186328c7290cSJames Feist ctx->yield, ec, "xyz.openbmc_project.Settings", 1864773703a5SCheng C Yang "/xyz/openbmc_project/control/power_supply_redundancy", 1865773703a5SCheng C Yang "org.freedesktop.DBus.Properties", "Get", 1866773703a5SCheng C Yang "xyz.openbmc_project.Control.PowerSupplyRedundancy", property); 1867773703a5SCheng C Yang if (ec) 1868773703a5SCheng C Yang { 1869773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 1870773703a5SCheng C Yang "Failed to get dbus property to cold redundancy"); 1871773703a5SCheng C Yang return -1; 1872773703a5SCheng C Yang } 1873773703a5SCheng C Yang return 0; 1874773703a5SCheng C Yang } 1875773703a5SCheng C Yang 1876773703a5SCheng C Yang uint8_t getPSUCount(void) 1877773703a5SCheng C Yang { 1878773703a5SCheng C Yang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 1879773703a5SCheng C Yang ipmi::Value num; 1880773703a5SCheng C Yang try 1881773703a5SCheng C Yang { 1882773703a5SCheng C Yang num = ipmi::getDbusProperty( 1883773703a5SCheng C Yang *dbus, "xyz.openbmc_project.PSURedundancy", 1884773703a5SCheng C Yang "/xyz/openbmc_project/control/power_supply_redundancy", 1885773703a5SCheng C Yang "xyz.openbmc_project.Control.PowerSupplyRedundancy", "PSUNumber"); 1886773703a5SCheng C Yang } 1887773703a5SCheng C Yang catch (sdbusplus::exception_t& e) 1888773703a5SCheng C Yang { 1889773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 1890773703a5SCheng C Yang "Failed to get PSUNumber property from dbus interface"); 1891773703a5SCheng C Yang return 0; 1892773703a5SCheng C Yang } 1893773703a5SCheng C Yang uint8_t* pNum = std::get_if<uint8_t>(&num); 1894773703a5SCheng C Yang if (!pNum) 1895773703a5SCheng C Yang { 1896773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 1897773703a5SCheng C Yang "Error to get PSU Number"); 1898773703a5SCheng C Yang return 0; 1899773703a5SCheng C Yang } 1900773703a5SCheng C Yang return *pNum; 1901773703a5SCheng C Yang } 1902773703a5SCheng C Yang 1903773703a5SCheng C Yang bool validateCRAlgo(std::vector<uint8_t>& conf, uint8_t num) 1904773703a5SCheng C Yang { 1905773703a5SCheng C Yang if (conf.size() < num) 1906773703a5SCheng C Yang { 1907773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 1908773703a5SCheng C Yang "Invalid PSU Ranking"); 1909773703a5SCheng C Yang return false; 1910773703a5SCheng C Yang } 1911773703a5SCheng C Yang std::set<uint8_t> confSet; 1912773703a5SCheng C Yang for (uint8_t i = 0; i < num; i++) 1913773703a5SCheng C Yang { 1914773703a5SCheng C Yang if (conf[i] > num) 1915773703a5SCheng C Yang { 1916773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 1917773703a5SCheng C Yang "PSU Ranking is larger than current PSU number"); 1918773703a5SCheng C Yang return false; 1919773703a5SCheng C Yang } 1920773703a5SCheng C Yang confSet.emplace(conf[i]); 1921773703a5SCheng C Yang } 1922773703a5SCheng C Yang 1923773703a5SCheng C Yang if (confSet.size() != num) 1924773703a5SCheng C Yang { 1925773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 1926773703a5SCheng C Yang "duplicate PSU Ranking"); 1927773703a5SCheng C Yang return false; 1928773703a5SCheng C Yang } 1929773703a5SCheng C Yang return true; 1930773703a5SCheng C Yang } 1931773703a5SCheng C Yang 1932773703a5SCheng C Yang enum class crParameter 1933773703a5SCheng C Yang { 1934773703a5SCheng C Yang crStatus = 0, 1935773703a5SCheng C Yang crFeature = 1, 1936773703a5SCheng C Yang rotationFeature = 2, 1937773703a5SCheng C Yang rotationAlgo = 3, 1938773703a5SCheng C Yang rotationPeriod = 4, 1939773703a5SCheng C Yang numOfPSU = 5 1940773703a5SCheng C Yang }; 1941773703a5SCheng C Yang 1942773703a5SCheng C Yang constexpr ipmi::Cc ccParameterNotSupported = 0x80; 1943773703a5SCheng C Yang static const constexpr uint32_t oneDay = 0x15180; 1944773703a5SCheng C Yang static const constexpr uint32_t oneMonth = 0xf53700; 1945773703a5SCheng C Yang static const constexpr uint8_t userSpecific = 0x01; 1946773703a5SCheng C Yang static const constexpr uint8_t crSetCompleted = 0; 1947773703a5SCheng C Yang ipmi::RspType<uint8_t> ipmiOEMSetCRConfig(ipmi::Context::ptr ctx, 1948773703a5SCheng C Yang uint8_t parameter, 1949773703a5SCheng C Yang ipmi::message::Payload& payload) 1950773703a5SCheng C Yang { 1951773703a5SCheng C Yang switch (static_cast<crParameter>(parameter)) 1952773703a5SCheng C Yang { 1953773703a5SCheng C Yang case crParameter::crFeature: 1954773703a5SCheng C Yang { 1955773703a5SCheng C Yang uint8_t param1; 1956773703a5SCheng C Yang if (payload.unpack(param1) || !payload.fullyUnpacked()) 1957773703a5SCheng C Yang { 1958773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid(); 1959773703a5SCheng C Yang } 1960773703a5SCheng C Yang // ColdRedundancy Enable can only be true or flase 1961773703a5SCheng C Yang if (param1 > 1) 1962773703a5SCheng C Yang { 1963773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest(); 1964773703a5SCheng C Yang } 1965773703a5SCheng C Yang if (setCRConfig(ctx, "ColdRedundancyEnabled", 1966773703a5SCheng C Yang static_cast<bool>(param1))) 1967773703a5SCheng C Yang { 1968773703a5SCheng C Yang return ipmi::responseResponseError(); 1969773703a5SCheng C Yang } 1970773703a5SCheng C Yang break; 1971773703a5SCheng C Yang } 1972773703a5SCheng C Yang case crParameter::rotationFeature: 1973773703a5SCheng C Yang { 1974773703a5SCheng C Yang uint8_t param1; 1975773703a5SCheng C Yang if (payload.unpack(param1) || !payload.fullyUnpacked()) 1976773703a5SCheng C Yang { 1977773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid(); 1978773703a5SCheng C Yang } 1979773703a5SCheng C Yang // Rotation Enable can only be true or false 1980773703a5SCheng C Yang if (param1 > 1) 1981773703a5SCheng C Yang { 1982773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest(); 1983773703a5SCheng C Yang } 1984773703a5SCheng C Yang if (setCRConfig(ctx, "RotationEnabled", static_cast<bool>(param1))) 1985773703a5SCheng C Yang { 1986773703a5SCheng C Yang return ipmi::responseResponseError(); 1987773703a5SCheng C Yang } 1988773703a5SCheng C Yang break; 1989773703a5SCheng C Yang } 1990773703a5SCheng C Yang case crParameter::rotationAlgo: 1991773703a5SCheng C Yang { 1992773703a5SCheng C Yang // Rotation Algorithm can only be 0-BMC Specific or 1-User Specific 1993773703a5SCheng C Yang std::string algoName; 1994773703a5SCheng C Yang uint8_t param1; 1995773703a5SCheng C Yang if (payload.unpack(param1)) 1996773703a5SCheng C Yang { 1997773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid(); 1998773703a5SCheng C Yang } 1999773703a5SCheng C Yang switch (param1) 2000773703a5SCheng C Yang { 2001773703a5SCheng C Yang case 0: 2002773703a5SCheng C Yang algoName = "xyz.openbmc_project.Control." 2003773703a5SCheng C Yang "PowerSupplyRedundancy.Algo.bmcSpecific"; 2004773703a5SCheng C Yang break; 2005773703a5SCheng C Yang case 1: 2006773703a5SCheng C Yang algoName = "xyz.openbmc_project.Control." 2007773703a5SCheng C Yang "PowerSupplyRedundancy.Algo.userSpecific"; 2008773703a5SCheng C Yang break; 2009773703a5SCheng C Yang default: 2010773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest(); 2011773703a5SCheng C Yang } 2012773703a5SCheng C Yang if (setCRConfig(ctx, "RotationAlgorithm", algoName)) 2013773703a5SCheng C Yang { 2014773703a5SCheng C Yang return ipmi::responseResponseError(); 2015773703a5SCheng C Yang } 2016773703a5SCheng C Yang 2017773703a5SCheng C Yang uint8_t numberOfPSU = getPSUCount(); 2018773703a5SCheng C Yang if (!numberOfPSU) 2019773703a5SCheng C Yang { 2020773703a5SCheng C Yang return ipmi::responseResponseError(); 2021773703a5SCheng C Yang } 2022773703a5SCheng C Yang std::vector<uint8_t> rankOrder; 2023773703a5SCheng C Yang 2024773703a5SCheng C Yang if (param1 == userSpecific) 2025773703a5SCheng C Yang { 2026773703a5SCheng C Yang if (payload.unpack(rankOrder) || !payload.fullyUnpacked()) 2027773703a5SCheng C Yang { 2028773703a5SCheng C Yang ipmi::responseReqDataLenInvalid(); 2029773703a5SCheng C Yang } 2030773703a5SCheng C Yang if (rankOrder.size() < numberOfPSU) 2031773703a5SCheng C Yang { 2032773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid(); 2033773703a5SCheng C Yang } 2034773703a5SCheng C Yang 2035773703a5SCheng C Yang if (!validateCRAlgo(rankOrder, numberOfPSU)) 2036773703a5SCheng C Yang { 2037773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest(); 2038773703a5SCheng C Yang } 2039773703a5SCheng C Yang } 2040773703a5SCheng C Yang else 2041773703a5SCheng C Yang { 2042773703a5SCheng C Yang if (rankOrder.size() > 0) 2043773703a5SCheng C Yang { 2044773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid(); 2045773703a5SCheng C Yang } 2046773703a5SCheng C Yang for (uint8_t i = 1; i <= numberOfPSU; i++) 2047773703a5SCheng C Yang { 2048773703a5SCheng C Yang rankOrder.emplace_back(i); 2049773703a5SCheng C Yang } 2050773703a5SCheng C Yang } 2051773703a5SCheng C Yang if (setCRConfig(ctx, "RotationRankOrder", rankOrder)) 2052773703a5SCheng C Yang { 2053773703a5SCheng C Yang return ipmi::responseResponseError(); 2054773703a5SCheng C Yang } 2055773703a5SCheng C Yang break; 2056773703a5SCheng C Yang } 2057773703a5SCheng C Yang case crParameter::rotationPeriod: 2058773703a5SCheng C Yang { 2059773703a5SCheng C Yang // Minimum Rotation period is One day (86400 seconds) and Max 2060773703a5SCheng C Yang // Rotation Period is 6 month (0xf53700 seconds) 2061773703a5SCheng C Yang uint32_t period; 2062773703a5SCheng C Yang if (payload.unpack(period) || !payload.fullyUnpacked()) 2063773703a5SCheng C Yang { 2064773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid(); 2065773703a5SCheng C Yang } 2066773703a5SCheng C Yang if ((period < oneDay) || (period > oneMonth)) 2067773703a5SCheng C Yang { 2068773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest(); 2069773703a5SCheng C Yang } 2070773703a5SCheng C Yang if (setCRConfig(ctx, "PeriodOfRotation", period)) 2071773703a5SCheng C Yang { 2072773703a5SCheng C Yang return ipmi::responseResponseError(); 2073773703a5SCheng C Yang } 2074773703a5SCheng C Yang break; 2075773703a5SCheng C Yang } 2076773703a5SCheng C Yang default: 2077773703a5SCheng C Yang { 2078773703a5SCheng C Yang return ipmi::response(ccParameterNotSupported); 2079773703a5SCheng C Yang } 2080773703a5SCheng C Yang } 2081773703a5SCheng C Yang 2082773703a5SCheng C Yang // TODO Halfwidth needs to set SetInProgress 2083773703a5SCheng C Yang if (setCRConfig(ctx, "ColdRedundancyStatus", 2084e8cecdffSCheng C Yang std::string("xyz.openbmc_project.Control." 2085e8cecdffSCheng C Yang "PowerSupplyRedundancy.Status.completed"))) 2086773703a5SCheng C Yang { 2087773703a5SCheng C Yang return ipmi::responseResponseError(); 2088773703a5SCheng C Yang } 2089773703a5SCheng C Yang return ipmi::responseSuccess(crSetCompleted); 2090773703a5SCheng C Yang } 2091773703a5SCheng C Yang 2092f41e334dSCheng C Yang ipmi::RspType<uint8_t, std::variant<uint8_t, uint32_t, std::array<uint8_t, 5>>> 2093773703a5SCheng C Yang ipmiOEMGetCRConfig(ipmi::Context::ptr ctx, uint8_t parameter) 2094773703a5SCheng C Yang { 2095773703a5SCheng C Yang crConfigVariant value; 2096773703a5SCheng C Yang switch (static_cast<crParameter>(parameter)) 2097773703a5SCheng C Yang { 2098773703a5SCheng C Yang case crParameter::crStatus: 2099773703a5SCheng C Yang { 2100773703a5SCheng C Yang if (getCRConfig(ctx, "ColdRedundancyStatus", value)) 2101773703a5SCheng C Yang { 2102773703a5SCheng C Yang return ipmi::responseResponseError(); 2103773703a5SCheng C Yang } 2104773703a5SCheng C Yang std::string* pStatus = std::get_if<std::string>(&value); 2105773703a5SCheng C Yang if (!pStatus) 2106773703a5SCheng C Yang { 2107773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2108773703a5SCheng C Yang "Error to get ColdRedundancyStatus property"); 2109773703a5SCheng C Yang return ipmi::responseResponseError(); 2110773703a5SCheng C Yang } 2111773703a5SCheng C Yang namespace server = sdbusplus::xyz::openbmc_project::Control::server; 2112773703a5SCheng C Yang auto status = 2113773703a5SCheng C Yang server::PowerSupplyRedundancy::convertStatusFromString( 2114773703a5SCheng C Yang *pStatus); 2115773703a5SCheng C Yang switch (status) 2116773703a5SCheng C Yang { 2117773703a5SCheng C Yang case server::PowerSupplyRedundancy::Status::inProgress: 2118f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, 2119f41e334dSCheng C Yang static_cast<uint8_t>(0)); 2120773703a5SCheng C Yang 2121773703a5SCheng C Yang case server::PowerSupplyRedundancy::Status::completed: 2122f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, 2123f41e334dSCheng C Yang static_cast<uint8_t>(1)); 2124773703a5SCheng C Yang default: 2125773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2126773703a5SCheng C Yang "Error to get valid status"); 2127773703a5SCheng C Yang return ipmi::responseResponseError(); 2128773703a5SCheng C Yang } 2129773703a5SCheng C Yang } 2130773703a5SCheng C Yang case crParameter::crFeature: 2131773703a5SCheng C Yang { 2132773703a5SCheng C Yang if (getCRConfig(ctx, "ColdRedundancyEnabled", value)) 2133773703a5SCheng C Yang { 2134773703a5SCheng C Yang return ipmi::responseResponseError(); 2135773703a5SCheng C Yang } 2136773703a5SCheng C Yang bool* pResponse = std::get_if<bool>(&value); 2137773703a5SCheng C Yang if (!pResponse) 2138773703a5SCheng C Yang { 2139773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2140773703a5SCheng C Yang "Error to get ColdRedundancyEnable property"); 2141773703a5SCheng C Yang return ipmi::responseResponseError(); 2142773703a5SCheng C Yang } 2143773703a5SCheng C Yang 2144f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, 2145f41e334dSCheng C Yang static_cast<uint8_t>(*pResponse)); 2146773703a5SCheng C Yang } 2147773703a5SCheng C Yang case crParameter::rotationFeature: 2148773703a5SCheng C Yang { 2149773703a5SCheng C Yang if (getCRConfig(ctx, "RotationEnabled", value)) 2150773703a5SCheng C Yang { 2151773703a5SCheng C Yang return ipmi::responseResponseError(); 2152773703a5SCheng C Yang } 2153773703a5SCheng C Yang bool* pResponse = std::get_if<bool>(&value); 2154773703a5SCheng C Yang if (!pResponse) 2155773703a5SCheng C Yang { 2156773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2157773703a5SCheng C Yang "Error to get RotationEnabled property"); 2158773703a5SCheng C Yang return ipmi::responseResponseError(); 2159773703a5SCheng C Yang } 2160f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, 2161f41e334dSCheng C Yang static_cast<uint8_t>(*pResponse)); 2162773703a5SCheng C Yang } 2163773703a5SCheng C Yang case crParameter::rotationAlgo: 2164773703a5SCheng C Yang { 2165773703a5SCheng C Yang if (getCRConfig(ctx, "RotationAlgorithm", value)) 2166773703a5SCheng C Yang { 2167773703a5SCheng C Yang return ipmi::responseResponseError(); 2168773703a5SCheng C Yang } 2169773703a5SCheng C Yang 2170773703a5SCheng C Yang std::string* pAlgo = std::get_if<std::string>(&value); 2171773703a5SCheng C Yang if (!pAlgo) 2172773703a5SCheng C Yang { 2173773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2174773703a5SCheng C Yang "Error to get RotationAlgorithm property"); 2175773703a5SCheng C Yang return ipmi::responseResponseError(); 2176773703a5SCheng C Yang } 2177773703a5SCheng C Yang std::array<uint8_t, 5> response = {0, 0, 0, 0, 0}; 2178773703a5SCheng C Yang namespace server = sdbusplus::xyz::openbmc_project::Control::server; 2179773703a5SCheng C Yang auto algo = 2180773703a5SCheng C Yang server::PowerSupplyRedundancy::convertAlgoFromString(*pAlgo); 2181773703a5SCheng C Yang switch (algo) 2182773703a5SCheng C Yang { 2183773703a5SCheng C Yang case server::PowerSupplyRedundancy::Algo::bmcSpecific: 2184773703a5SCheng C Yang response[0] = 0; 2185773703a5SCheng C Yang break; 2186773703a5SCheng C Yang case server::PowerSupplyRedundancy::Algo::userSpecific: 2187773703a5SCheng C Yang response[0] = 1; 2188773703a5SCheng C Yang break; 2189773703a5SCheng C Yang default: 2190773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2191773703a5SCheng C Yang "Error to get valid algo"); 2192773703a5SCheng C Yang return ipmi::responseResponseError(); 2193773703a5SCheng C Yang } 2194773703a5SCheng C Yang 2195773703a5SCheng C Yang if (getCRConfig(ctx, "RotationRankOrder", value)) 2196773703a5SCheng C Yang { 2197773703a5SCheng C Yang return ipmi::responseResponseError(); 2198773703a5SCheng C Yang } 2199773703a5SCheng C Yang std::vector<uint8_t>* pResponse = 2200773703a5SCheng C Yang std::get_if<std::vector<uint8_t>>(&value); 2201773703a5SCheng C Yang if (!pResponse) 2202773703a5SCheng C Yang { 2203773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2204773703a5SCheng C Yang "Error to get RotationRankOrder property"); 2205773703a5SCheng C Yang return ipmi::responseResponseError(); 2206773703a5SCheng C Yang } 2207773703a5SCheng C Yang if (pResponse->size() + 1 > response.size()) 2208773703a5SCheng C Yang { 2209773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2210773703a5SCheng C Yang "Incorrect size of RotationAlgorithm property"); 2211773703a5SCheng C Yang return ipmi::responseResponseError(); 2212773703a5SCheng C Yang } 2213773703a5SCheng C Yang std::copy(pResponse->begin(), pResponse->end(), 2214773703a5SCheng C Yang response.begin() + 1); 2215f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, response); 2216773703a5SCheng C Yang } 2217773703a5SCheng C Yang case crParameter::rotationPeriod: 2218773703a5SCheng C Yang { 2219773703a5SCheng C Yang if (getCRConfig(ctx, "PeriodOfRotation", value)) 2220773703a5SCheng C Yang { 2221773703a5SCheng C Yang return ipmi::responseResponseError(); 2222773703a5SCheng C Yang } 2223773703a5SCheng C Yang uint32_t* pResponse = std::get_if<uint32_t>(&value); 2224773703a5SCheng C Yang if (!pResponse) 2225773703a5SCheng C Yang { 2226773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>( 2227773703a5SCheng C Yang "Error to get RotationAlgorithm property"); 2228773703a5SCheng C Yang return ipmi::responseResponseError(); 2229773703a5SCheng C Yang } 2230f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, *pResponse); 2231773703a5SCheng C Yang } 2232773703a5SCheng C Yang case crParameter::numOfPSU: 2233773703a5SCheng C Yang { 2234773703a5SCheng C Yang uint8_t numberOfPSU = getPSUCount(); 2235773703a5SCheng C Yang if (!numberOfPSU) 2236773703a5SCheng C Yang { 2237773703a5SCheng C Yang return ipmi::responseResponseError(); 2238773703a5SCheng C Yang } 2239f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, numberOfPSU); 2240773703a5SCheng C Yang } 2241773703a5SCheng C Yang default: 2242773703a5SCheng C Yang { 2243773703a5SCheng C Yang return ipmi::response(ccParameterNotSupported); 2244773703a5SCheng C Yang } 2245773703a5SCheng C Yang } 2246773703a5SCheng C Yang } 2247773703a5SCheng C Yang 2248be560b09SZhu, Yunge ipmi::RspType<> ipmiOEMSetFaultIndication(uint8_t sourceId, uint8_t faultType, 2249be560b09SZhu, Yunge uint8_t faultState, 2250be560b09SZhu, Yunge uint8_t faultGroup, 2251be560b09SZhu, Yunge std::array<uint8_t, 8>& ledStateData) 2252be560b09SZhu, Yunge { 2253be560b09SZhu, Yunge static constexpr const char* objpath = "/xyz/openbmc_project/EntityManager"; 2254be560b09SZhu, Yunge static constexpr const char* intf = "xyz.openbmc_project.EntityManager"; 2255be560b09SZhu, Yunge constexpr auto maxFaultType = static_cast<size_t>(RemoteFaultType::max); 2256be560b09SZhu, Yunge static const std::array<std::string, maxFaultType> faultNames = { 2257be560b09SZhu, Yunge "faultFan", "faultTemp", "faultPower", 2258be560b09SZhu, Yunge "faultDriveSlot", "faultSoftware", "faultMemory"}; 2259be560b09SZhu, Yunge static constexpr const char* sysGpioPath = "/sys/class/gpio/gpio"; 2260be560b09SZhu, Yunge static constexpr const char* postfixValue = "/value"; 2261be560b09SZhu, Yunge 2262be560b09SZhu, Yunge constexpr uint8_t maxFaultSource = 0x4; 2263be560b09SZhu, Yunge constexpr uint8_t skipLEDs = 0xFF; 2264be560b09SZhu, Yunge constexpr uint8_t pinSize = 64; 2265be560b09SZhu, Yunge constexpr uint8_t groupSize = 16; 2266be560b09SZhu, Yunge 2267be560b09SZhu, Yunge std::vector<uint16_t> ledFaultPins(pinSize, 0xFFFF); 2268be560b09SZhu, Yunge uint64_t resFIndex = 0; 2269be560b09SZhu, Yunge std::string resFType; 2270be560b09SZhu, Yunge std::string service; 2271be560b09SZhu, Yunge ObjectValueTree valueTree; 2272be560b09SZhu, Yunge 2273be560b09SZhu, Yunge // Validate the source, fault type 2274be560b09SZhu, Yunge if ((sourceId >= maxFaultSource) || 2275be560b09SZhu, Yunge (faultType >= static_cast<int8_t>(RemoteFaultType::max)) || 2276be560b09SZhu, Yunge (faultState >= static_cast<int8_t>(RemoteFaultState::maxFaultState)) || 2277be560b09SZhu, Yunge (faultGroup >= static_cast<int8_t>(DimmFaultType::maxFaultGroup))) 2278be560b09SZhu, Yunge { 2279be560b09SZhu, Yunge return ipmi::responseParmOutOfRange(); 2280be560b09SZhu, Yunge } 2281be560b09SZhu, Yunge 228215419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 2283be560b09SZhu, Yunge try 2284be560b09SZhu, Yunge { 228515419dd5SVernon Mauery service = getService(*dbus, intf, objpath); 228615419dd5SVernon Mauery valueTree = getManagedObjects(*dbus, service, "/"); 2287be560b09SZhu, Yunge } 2288be560b09SZhu, Yunge catch (const std::exception& e) 2289be560b09SZhu, Yunge { 2290be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>( 2291be560b09SZhu, Yunge "No object implements interface", 2292be560b09SZhu, Yunge phosphor::logging::entry("SERVICE=%s", service.c_str()), 2293be560b09SZhu, Yunge phosphor::logging::entry("INTF=%s", intf)); 2294be560b09SZhu, Yunge return ipmi::responseResponseError(); 2295be560b09SZhu, Yunge } 2296be560b09SZhu, Yunge 2297be560b09SZhu, Yunge if (valueTree.empty()) 2298be560b09SZhu, Yunge { 2299be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>( 2300be560b09SZhu, Yunge "No object implements interface", 2301be560b09SZhu, Yunge phosphor::logging::entry("INTF=%s", intf)); 2302be560b09SZhu, Yunge return ipmi::responseResponseError(); 2303be560b09SZhu, Yunge } 2304be560b09SZhu, Yunge 2305be560b09SZhu, Yunge for (const auto& item : valueTree) 2306be560b09SZhu, Yunge { 2307be560b09SZhu, Yunge // find LedFault configuration 2308be560b09SZhu, Yunge auto interface = 2309be560b09SZhu, Yunge item.second.find("xyz.openbmc_project.Configuration.LedFault"); 2310be560b09SZhu, Yunge if (interface == item.second.end()) 2311be560b09SZhu, Yunge { 2312be560b09SZhu, Yunge continue; 2313be560b09SZhu, Yunge } 2314be560b09SZhu, Yunge 2315be560b09SZhu, Yunge // find matched fault type: faultMemmory / faultFan 2316be560b09SZhu, Yunge // find LedGpioPins/FaultIndex configuration 2317be560b09SZhu, Yunge auto propertyFaultType = interface->second.find("FaultType"); 2318be560b09SZhu, Yunge auto propertyFIndex = interface->second.find("FaultIndex"); 2319be560b09SZhu, Yunge auto ledIndex = interface->second.find("LedGpioPins"); 2320be560b09SZhu, Yunge 2321be560b09SZhu, Yunge if (propertyFaultType == interface->second.end() || 2322be560b09SZhu, Yunge propertyFIndex == interface->second.end() || 2323be560b09SZhu, Yunge ledIndex == interface->second.end()) 2324be560b09SZhu, Yunge { 2325be560b09SZhu, Yunge continue; 2326be560b09SZhu, Yunge } 2327be560b09SZhu, Yunge 2328be560b09SZhu, Yunge try 2329be560b09SZhu, Yunge { 2330be560b09SZhu, Yunge Value valIndex = propertyFIndex->second; 2331be560b09SZhu, Yunge resFIndex = std::get<uint64_t>(valIndex); 2332be560b09SZhu, Yunge 2333be560b09SZhu, Yunge Value valFType = propertyFaultType->second; 2334be560b09SZhu, Yunge resFType = std::get<std::string>(valFType); 2335be560b09SZhu, Yunge } 2336be560b09SZhu, Yunge catch (const std::bad_variant_access& e) 2337be560b09SZhu, Yunge { 2338be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 2339be560b09SZhu, Yunge return ipmi::responseResponseError(); 2340be560b09SZhu, Yunge } 2341be560b09SZhu, Yunge // find the matched requested fault type: faultMemmory or faultFan 2342be560b09SZhu, Yunge if (resFType != faultNames[faultType]) 2343be560b09SZhu, Yunge { 2344be560b09SZhu, Yunge continue; 2345be560b09SZhu, Yunge } 2346be560b09SZhu, Yunge 2347be560b09SZhu, Yunge // read LedGpioPins data 2348be560b09SZhu, Yunge std::vector<uint64_t> ledgpios; 2349be560b09SZhu, Yunge std::variant<std::vector<uint64_t>> message; 2350be560b09SZhu, Yunge 235115419dd5SVernon Mauery auto method = dbus->new_method_call( 2352be560b09SZhu, Yunge service.c_str(), (std::string(item.first)).c_str(), 2353be560b09SZhu, Yunge "org.freedesktop.DBus.Properties", "Get"); 2354be560b09SZhu, Yunge 2355be560b09SZhu, Yunge method.append("xyz.openbmc_project.Configuration.LedFault", 2356be560b09SZhu, Yunge "LedGpioPins"); 2357be560b09SZhu, Yunge 2358be560b09SZhu, Yunge try 2359be560b09SZhu, Yunge { 236015419dd5SVernon Mauery auto reply = dbus->call(method); 2361be560b09SZhu, Yunge reply.read(message); 2362be560b09SZhu, Yunge ledgpios = std::get<std::vector<uint64_t>>(message); 2363be560b09SZhu, Yunge } 2364be560b09SZhu, Yunge catch (std::exception& e) 2365be560b09SZhu, Yunge { 2366be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 2367be560b09SZhu, Yunge return ipmi::responseResponseError(); 2368be560b09SZhu, Yunge } 2369be560b09SZhu, Yunge 2370be560b09SZhu, Yunge // Check the size to be sure it will never overflow on groupSize 2371be560b09SZhu, Yunge if (ledgpios.size() > groupSize) 2372be560b09SZhu, Yunge { 2373be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>( 2374be560b09SZhu, Yunge "Fault gpio Pins out of range!"); 2375be560b09SZhu, Yunge return ipmi::responseParmOutOfRange(); 2376be560b09SZhu, Yunge } 2377be560b09SZhu, Yunge // Store data, according to command data bit index order 2378be560b09SZhu, Yunge for (int i = 0; i < ledgpios.size(); i++) 2379be560b09SZhu, Yunge { 2380be560b09SZhu, Yunge ledFaultPins[i + groupSize * resFIndex] = ledgpios[i]; 2381be560b09SZhu, Yunge } 2382be560b09SZhu, Yunge } 2383be560b09SZhu, Yunge 2384be560b09SZhu, Yunge switch (RemoteFaultType(faultType)) 2385be560b09SZhu, Yunge { 2386be560b09SZhu, Yunge case (RemoteFaultType::fan): 2387be560b09SZhu, Yunge case (RemoteFaultType::memory): 2388be560b09SZhu, Yunge { 2389be560b09SZhu, Yunge if (faultGroup == skipLEDs) 2390be560b09SZhu, Yunge { 2391be560b09SZhu, Yunge return ipmi::responseSuccess(); 2392be560b09SZhu, Yunge } 2393be560b09SZhu, Yunge 2394be560b09SZhu, Yunge uint64_t ledState = 0; 2395be560b09SZhu, Yunge // calculate led state bit filed count, each byte has 8bits 2396be560b09SZhu, Yunge // the maximum bits will be 8 * 8 bits 2397be560b09SZhu, Yunge constexpr uint8_t size = sizeof(ledStateData) * 8; 2398be560b09SZhu, Yunge for (int i = 0; i < sizeof(ledStateData); i++) 2399be560b09SZhu, Yunge { 2400be560b09SZhu, Yunge ledState = (uint64_t)(ledState << 8); 2401be560b09SZhu, Yunge ledState = (uint64_t)(ledState | (uint64_t)ledStateData[i]); 2402be560b09SZhu, Yunge } 2403be560b09SZhu, Yunge 2404be560b09SZhu, Yunge std::bitset<size> ledStateBits(ledState); 2405be560b09SZhu, Yunge std::string gpioValue; 2406be560b09SZhu, Yunge for (int i = 0; i < size; i++) 2407be560b09SZhu, Yunge { // skip invalid value 2408be560b09SZhu, Yunge if (ledFaultPins[i] == 0xFFFF) 2409be560b09SZhu, Yunge { 2410be560b09SZhu, Yunge continue; 2411be560b09SZhu, Yunge } 2412be560b09SZhu, Yunge 2413be560b09SZhu, Yunge std::string device = sysGpioPath + 2414be560b09SZhu, Yunge std::to_string(ledFaultPins[i]) + 2415be560b09SZhu, Yunge postfixValue; 2416be560b09SZhu, Yunge std::fstream gpioFile; 2417be560b09SZhu, Yunge 2418be560b09SZhu, Yunge gpioFile.open(device, std::ios::out); 2419be560b09SZhu, Yunge 2420be560b09SZhu, Yunge if (!gpioFile.good()) 2421be560b09SZhu, Yunge { 2422be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>( 2423be560b09SZhu, Yunge "Not Find Led Gpio Device!", 2424be560b09SZhu, Yunge phosphor::logging::entry("DEVICE=%s", device.c_str())); 2425be560b09SZhu, Yunge return ipmi::responseResponseError(); 2426be560b09SZhu, Yunge } 2427be560b09SZhu, Yunge gpioFile << std::to_string( 2428be560b09SZhu, Yunge static_cast<uint8_t>(ledStateBits[i])); 2429be560b09SZhu, Yunge gpioFile.close(); 2430be560b09SZhu, Yunge } 2431be560b09SZhu, Yunge break; 2432be560b09SZhu, Yunge } 2433be560b09SZhu, Yunge default: 2434be560b09SZhu, Yunge { 2435be560b09SZhu, Yunge // now only support two fault types 2436be560b09SZhu, Yunge return ipmi::responseParmOutOfRange(); 2437be560b09SZhu, Yunge } 2438be560b09SZhu, Yunge } 2439be560b09SZhu, Yunge 2440be560b09SZhu, Yunge return ipmi::responseSuccess(); 2441be560b09SZhu, Yunge } 2442be560b09SZhu, Yunge 2443ea537d53SRichard Marian Thomaiyar ipmi::RspType<uint8_t> ipmiOEMReadBoardProductId() 2444ea537d53SRichard Marian Thomaiyar { 2445ea537d53SRichard Marian Thomaiyar uint8_t prodId = 0; 2446ea537d53SRichard Marian Thomaiyar try 2447ea537d53SRichard Marian Thomaiyar { 244815419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 2449ea537d53SRichard Marian Thomaiyar const DbusObjectInfo& object = getDbusObject( 245015419dd5SVernon Mauery *dbus, "xyz.openbmc_project.Inventory.Item.Board", 2451ea537d53SRichard Marian Thomaiyar "/xyz/openbmc_project/inventory/system/board/", "Baseboard"); 2452ea537d53SRichard Marian Thomaiyar const Value& propValue = getDbusProperty( 245315419dd5SVernon Mauery *dbus, object.second, object.first, 2454ea537d53SRichard Marian Thomaiyar "xyz.openbmc_project.Inventory.Item.Board", "ProductId"); 2455ea537d53SRichard Marian Thomaiyar prodId = static_cast<uint8_t>(std::get<uint64_t>(propValue)); 2456ea537d53SRichard Marian Thomaiyar } 2457ea537d53SRichard Marian Thomaiyar catch (std::exception& e) 2458ea537d53SRichard Marian Thomaiyar { 2459ea537d53SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 2460ea537d53SRichard Marian Thomaiyar "ipmiOEMReadBoardProductId: Product ID read failed!", 2461ea537d53SRichard Marian Thomaiyar phosphor::logging::entry("ERR=%s", e.what())); 2462ea537d53SRichard Marian Thomaiyar } 2463ea537d53SRichard Marian Thomaiyar return ipmi::responseSuccess(prodId); 2464ea537d53SRichard Marian Thomaiyar } 2465ea537d53SRichard Marian Thomaiyar 2466d801e463SRichard Marian Thomaiyar /** @brief implements the get security mode command 2467d801e463SRichard Marian Thomaiyar * @param ctx - ctx pointer 2468d801e463SRichard Marian Thomaiyar * 2469d801e463SRichard Marian Thomaiyar * @returns IPMI completion code with following data 2470d801e463SRichard Marian Thomaiyar * - restriction mode value - As specified in 2471d801e463SRichard Marian Thomaiyar * xyz.openbmc_project.Control.Security.RestrictionMode.interface.yaml 2472d801e463SRichard Marian Thomaiyar * - special mode value - As specified in 2473d801e463SRichard Marian Thomaiyar * xyz.openbmc_project.Control.Security.SpecialMode.interface.yaml 2474d801e463SRichard Marian Thomaiyar */ 2475d801e463SRichard Marian Thomaiyar ipmi::RspType<uint8_t, uint8_t> ipmiGetSecurityMode(ipmi::Context::ptr ctx) 2476d801e463SRichard Marian Thomaiyar { 2477d801e463SRichard Marian Thomaiyar namespace securityNameSpace = 2478d801e463SRichard Marian Thomaiyar sdbusplus::xyz::openbmc_project::Control::Security::server; 2479d801e463SRichard Marian Thomaiyar uint8_t restrictionModeValue = 0; 2480d801e463SRichard Marian Thomaiyar uint8_t specialModeValue = 0; 2481d801e463SRichard Marian Thomaiyar 2482d801e463SRichard Marian Thomaiyar boost::system::error_code ec; 2483d801e463SRichard Marian Thomaiyar auto varRestrMode = ctx->bus->yield_method_call<std::variant<std::string>>( 248428c7290cSJames Feist ctx->yield, ec, restricionModeService, restricionModeBasePath, 2485d801e463SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertyGetMethod, restricionModeIntf, 2486d801e463SRichard Marian Thomaiyar restricionModeProperty); 2487d801e463SRichard Marian Thomaiyar if (ec) 2488d801e463SRichard Marian Thomaiyar { 2489d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 2490d801e463SRichard Marian Thomaiyar "ipmiGetSecurityMode: failed to get RestrictionMode property", 2491d801e463SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str())); 2492d801e463SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 2493d801e463SRichard Marian Thomaiyar } 2494d801e463SRichard Marian Thomaiyar restrictionModeValue = static_cast<uint8_t>( 2495d801e463SRichard Marian Thomaiyar securityNameSpace::RestrictionMode::convertModesFromString( 2496d801e463SRichard Marian Thomaiyar std::get<std::string>(varRestrMode))); 2497d801e463SRichard Marian Thomaiyar auto varSpecialMode = ctx->bus->yield_method_call<std::variant<uint8_t>>( 249828c7290cSJames Feist ctx->yield, ec, specialModeService, specialModeBasePath, 2499d801e463SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertyGetMethod, specialModeIntf, 2500d801e463SRichard Marian Thomaiyar specialModeProperty); 2501d801e463SRichard Marian Thomaiyar if (ec) 2502d801e463SRichard Marian Thomaiyar { 2503d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 2504d801e463SRichard Marian Thomaiyar "ipmiGetSecurityMode: failed to get SpecialMode property", 2505d801e463SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str())); 2506d801e463SRichard Marian Thomaiyar // fall through, let us not worry about SpecialMode property, which is 2507d801e463SRichard Marian Thomaiyar // not required in user scenario 2508d801e463SRichard Marian Thomaiyar } 2509d801e463SRichard Marian Thomaiyar else 2510d801e463SRichard Marian Thomaiyar { 2511d801e463SRichard Marian Thomaiyar specialModeValue = std::get<uint8_t>(varSpecialMode); 2512d801e463SRichard Marian Thomaiyar } 2513d801e463SRichard Marian Thomaiyar return ipmi::responseSuccess(restrictionModeValue, specialModeValue); 2514d801e463SRichard Marian Thomaiyar } 2515d801e463SRichard Marian Thomaiyar 2516d801e463SRichard Marian Thomaiyar /** @brief implements the set security mode command 2517d801e463SRichard Marian Thomaiyar * Command allows to upgrade the restriction mode and won't allow 2518d801e463SRichard Marian Thomaiyar * to downgrade from system interface 2519d801e463SRichard Marian Thomaiyar * @param ctx - ctx pointer 2520d801e463SRichard Marian Thomaiyar * @param restrictionMode - restriction mode value to be set. 2521d801e463SRichard Marian Thomaiyar * 2522d801e463SRichard Marian Thomaiyar * @returns IPMI completion code 2523d801e463SRichard Marian Thomaiyar */ 2524d801e463SRichard Marian Thomaiyar ipmi::RspType<> ipmiSetSecurityMode(ipmi::Context::ptr ctx, 2525d801e463SRichard Marian Thomaiyar uint8_t restrictionMode) 2526d801e463SRichard Marian Thomaiyar { 2527d801e463SRichard Marian Thomaiyar namespace securityNameSpace = 2528d801e463SRichard Marian Thomaiyar sdbusplus::xyz::openbmc_project::Control::Security::server; 2529d801e463SRichard Marian Thomaiyar 2530d801e463SRichard Marian Thomaiyar ChannelInfo chInfo; 2531d801e463SRichard Marian Thomaiyar if (getChannelInfo(ctx->channel, chInfo) != ccSuccess) 2532d801e463SRichard Marian Thomaiyar { 2533d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 2534d801e463SRichard Marian Thomaiyar "ipmiSetSecurityMode: Failed to get Channel Info", 2535d801e463SRichard Marian Thomaiyar phosphor::logging::entry("CHANNEL=%d", ctx->channel)); 2536d801e463SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 2537d801e463SRichard Marian Thomaiyar } 2538d801e463SRichard Marian Thomaiyar auto reqMode = 2539d801e463SRichard Marian Thomaiyar static_cast<securityNameSpace::RestrictionMode::Modes>(restrictionMode); 2540d801e463SRichard Marian Thomaiyar 2541d801e463SRichard Marian Thomaiyar if ((reqMode < securityNameSpace::RestrictionMode::Modes::Provisioning) || 2542d801e463SRichard Marian Thomaiyar (reqMode > 2543d801e463SRichard Marian Thomaiyar securityNameSpace::RestrictionMode::Modes::ProvisionedHostDisabled)) 2544d801e463SRichard Marian Thomaiyar { 2545d801e463SRichard Marian Thomaiyar return ipmi::responseInvalidFieldRequest(); 2546d801e463SRichard Marian Thomaiyar } 2547d801e463SRichard Marian Thomaiyar 2548d801e463SRichard Marian Thomaiyar boost::system::error_code ec; 2549d801e463SRichard Marian Thomaiyar auto varRestrMode = ctx->bus->yield_method_call<std::variant<std::string>>( 255028c7290cSJames Feist ctx->yield, ec, restricionModeService, restricionModeBasePath, 2551d801e463SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertyGetMethod, restricionModeIntf, 2552d801e463SRichard Marian Thomaiyar restricionModeProperty); 2553d801e463SRichard Marian Thomaiyar if (ec) 2554d801e463SRichard Marian Thomaiyar { 2555d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 2556d801e463SRichard Marian Thomaiyar "ipmiSetSecurityMode: failed to get RestrictionMode property", 2557d801e463SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str())); 2558d801e463SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 2559d801e463SRichard Marian Thomaiyar } 2560d801e463SRichard Marian Thomaiyar auto currentRestrictionMode = 2561d801e463SRichard Marian Thomaiyar securityNameSpace::RestrictionMode::convertModesFromString( 2562d801e463SRichard Marian Thomaiyar std::get<std::string>(varRestrMode)); 2563d801e463SRichard Marian Thomaiyar 2564d801e463SRichard Marian Thomaiyar if (chInfo.mediumType != 2565d801e463SRichard Marian Thomaiyar static_cast<uint8_t>(EChannelMediumType::lan8032) && 2566d801e463SRichard Marian Thomaiyar currentRestrictionMode > reqMode) 2567d801e463SRichard Marian Thomaiyar { 2568d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 2569d801e463SRichard Marian Thomaiyar "ipmiSetSecurityMode - Downgrading security mode not supported " 2570d801e463SRichard Marian Thomaiyar "through system interface", 2571d801e463SRichard Marian Thomaiyar phosphor::logging::entry( 2572d801e463SRichard Marian Thomaiyar "CUR_MODE=%d", static_cast<uint8_t>(currentRestrictionMode)), 2573d801e463SRichard Marian Thomaiyar phosphor::logging::entry("REQ_MODE=%d", restrictionMode)); 2574d801e463SRichard Marian Thomaiyar return ipmi::responseCommandNotAvailable(); 2575d801e463SRichard Marian Thomaiyar } 2576d801e463SRichard Marian Thomaiyar 2577d801e463SRichard Marian Thomaiyar ec.clear(); 2578d801e463SRichard Marian Thomaiyar ctx->bus->yield_method_call<>( 257928c7290cSJames Feist ctx->yield, ec, restricionModeService, restricionModeBasePath, 2580d801e463SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertySetMethod, restricionModeIntf, 2581d801e463SRichard Marian Thomaiyar restricionModeProperty, 2582d801e463SRichard Marian Thomaiyar static_cast<std::variant<std::string>>( 2583d801e463SRichard Marian Thomaiyar securityNameSpace::convertForMessage(reqMode))); 2584d801e463SRichard Marian Thomaiyar 2585d801e463SRichard Marian Thomaiyar if (ec) 2586d801e463SRichard Marian Thomaiyar { 2587d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>( 2588d801e463SRichard Marian Thomaiyar "ipmiSetSecurityMode: failed to set RestrictionMode property", 2589d801e463SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str())); 2590d801e463SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError(); 2591d801e463SRichard Marian Thomaiyar } 2592d801e463SRichard Marian Thomaiyar return ipmi::responseSuccess(); 2593d801e463SRichard Marian Thomaiyar } 2594d801e463SRichard Marian Thomaiyar 25954ac799d7SVernon Mauery ipmi::RspType<uint8_t /* restore status */> 25964ac799d7SVernon Mauery ipmiRestoreConfiguration(const std::array<uint8_t, 3>& clr, uint8_t cmd) 25974ac799d7SVernon Mauery { 25984ac799d7SVernon Mauery static constexpr std::array<uint8_t, 3> expClr = {'C', 'L', 'R'}; 25994ac799d7SVernon Mauery 26004ac799d7SVernon Mauery if (clr != expClr) 26014ac799d7SVernon Mauery { 26024ac799d7SVernon Mauery return ipmi::responseInvalidFieldRequest(); 26034ac799d7SVernon Mauery } 26044ac799d7SVernon Mauery constexpr uint8_t cmdStatus = 0; 26054ac799d7SVernon Mauery constexpr uint8_t cmdDefaultRestore = 0xaa; 26064ac799d7SVernon Mauery constexpr uint8_t cmdFullRestore = 0xbb; 26074ac799d7SVernon Mauery constexpr uint8_t cmdFormat = 0xcc; 26084ac799d7SVernon Mauery 26094ac799d7SVernon Mauery constexpr const char* restoreOpFname = "/tmp/.rwfs/.restore_op"; 26104ac799d7SVernon Mauery 26114ac799d7SVernon Mauery switch (cmd) 26124ac799d7SVernon Mauery { 26134ac799d7SVernon Mauery case cmdStatus: 26144ac799d7SVernon Mauery break; 26154ac799d7SVernon Mauery case cmdDefaultRestore: 26164ac799d7SVernon Mauery case cmdFullRestore: 26174ac799d7SVernon Mauery case cmdFormat: 26184ac799d7SVernon Mauery { 26194ac799d7SVernon Mauery // write file to rwfs root 26204ac799d7SVernon Mauery int value = (cmd - 1) & 0x03; // map aa, bb, cc => 1, 2, 3 26214ac799d7SVernon Mauery std::ofstream restoreFile(restoreOpFname); 26224ac799d7SVernon Mauery if (!restoreFile) 26234ac799d7SVernon Mauery { 26244ac799d7SVernon Mauery return ipmi::responseUnspecifiedError(); 26254ac799d7SVernon Mauery } 26264ac799d7SVernon Mauery restoreFile << value << "\n"; 26274ac799d7SVernon Mauery break; 26284ac799d7SVernon Mauery } 26294ac799d7SVernon Mauery default: 26304ac799d7SVernon Mauery return ipmi::responseInvalidFieldRequest(); 26314ac799d7SVernon Mauery } 26324ac799d7SVernon Mauery 26334ac799d7SVernon Mauery constexpr uint8_t restorePending = 0; 26344ac799d7SVernon Mauery constexpr uint8_t restoreComplete = 1; 26354ac799d7SVernon Mauery 26364ac799d7SVernon Mauery uint8_t restoreStatus = std::filesystem::exists(restoreOpFname) 26374ac799d7SVernon Mauery ? restorePending 26384ac799d7SVernon Mauery : restoreComplete; 26394ac799d7SVernon Mauery return ipmi::responseSuccess(restoreStatus); 26404ac799d7SVernon Mauery } 26414ac799d7SVernon Mauery 264239736d59SChen Yugang ipmi::RspType<uint8_t> ipmiOEMGetNmiSource(void) 264339736d59SChen Yugang { 264439736d59SChen Yugang uint8_t bmcSource; 264539736d59SChen Yugang namespace nmi = sdbusplus::com::intel::Control::server; 264639736d59SChen Yugang 264739736d59SChen Yugang try 264839736d59SChen Yugang { 264939736d59SChen Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 265039736d59SChen Yugang std::string service = 265139736d59SChen Yugang getService(*dbus, oemNmiSourceIntf, oemNmiSourceObjPath); 265239736d59SChen Yugang Value variant = 265339736d59SChen Yugang getDbusProperty(*dbus, service, oemNmiSourceObjPath, 265439736d59SChen Yugang oemNmiSourceIntf, oemNmiBmcSourceObjPathProp); 265539736d59SChen Yugang 265639736d59SChen Yugang switch (nmi::NMISource::convertBMCSourceSignalFromString( 265739736d59SChen Yugang std::get<std::string>(variant))) 265839736d59SChen Yugang { 265939736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::None: 266039736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::none); 266139736d59SChen Yugang break; 266239736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::FpBtn: 266339736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::fpBtn); 266439736d59SChen Yugang break; 266539736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::WdPreTimeout: 266639736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::wdPreTimeout); 266739736d59SChen Yugang break; 266839736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::PefMatch: 266939736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::pefMatch); 267039736d59SChen Yugang break; 267139736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::ChassisCmd: 267239736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::chassisCmd); 267339736d59SChen Yugang break; 267439736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::MemoryError: 267539736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::memoryError); 267639736d59SChen Yugang break; 267739736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::PciSerrPerr: 267839736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::pciSerrPerr); 267939736d59SChen Yugang break; 268039736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::SouthbridgeNmi: 268139736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::southbridgeNmi); 268239736d59SChen Yugang break; 268339736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::ChipsetNmi: 268439736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::chipsetNmi); 268539736d59SChen Yugang break; 268639736d59SChen Yugang default: 268739736d59SChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>( 268839736d59SChen Yugang "NMI source: invalid property!", 268939736d59SChen Yugang phosphor::logging::entry( 269039736d59SChen Yugang "PROP=%s", std::get<std::string>(variant).c_str())); 269139736d59SChen Yugang return ipmi::responseResponseError(); 269239736d59SChen Yugang } 269339736d59SChen Yugang } 269439736d59SChen Yugang catch (sdbusplus::exception::SdBusError& e) 269539736d59SChen Yugang { 269639736d59SChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 269739736d59SChen Yugang return ipmi::responseResponseError(); 269839736d59SChen Yugang } 269939736d59SChen Yugang 270039736d59SChen Yugang return ipmi::responseSuccess(bmcSource); 270139736d59SChen Yugang } 270239736d59SChen Yugang 270339736d59SChen Yugang ipmi::RspType<> ipmiOEMSetNmiSource(uint8_t sourceId) 270439736d59SChen Yugang { 270539736d59SChen Yugang namespace nmi = sdbusplus::com::intel::Control::server; 270639736d59SChen Yugang 270739736d59SChen Yugang nmi::NMISource::BMCSourceSignal bmcSourceSignal = 270839736d59SChen Yugang nmi::NMISource::BMCSourceSignal::None; 270939736d59SChen Yugang 271039736d59SChen Yugang switch (NmiSource(sourceId)) 271139736d59SChen Yugang { 271239736d59SChen Yugang case NmiSource::none: 271339736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::None; 271439736d59SChen Yugang break; 271539736d59SChen Yugang case NmiSource::fpBtn: 271639736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::FpBtn; 271739736d59SChen Yugang break; 271839736d59SChen Yugang case NmiSource::wdPreTimeout: 271939736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::WdPreTimeout; 272039736d59SChen Yugang break; 272139736d59SChen Yugang case NmiSource::pefMatch: 272239736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::PefMatch; 272339736d59SChen Yugang break; 272439736d59SChen Yugang case NmiSource::chassisCmd: 272539736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::ChassisCmd; 272639736d59SChen Yugang break; 272739736d59SChen Yugang case NmiSource::memoryError: 272839736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::MemoryError; 272939736d59SChen Yugang break; 273039736d59SChen Yugang case NmiSource::pciSerrPerr: 273139736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::PciSerrPerr; 273239736d59SChen Yugang break; 273339736d59SChen Yugang case NmiSource::southbridgeNmi: 273439736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::SouthbridgeNmi; 273539736d59SChen Yugang break; 273639736d59SChen Yugang case NmiSource::chipsetNmi: 273739736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::ChipsetNmi; 273839736d59SChen Yugang break; 273939736d59SChen Yugang default: 274039736d59SChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>( 274139736d59SChen Yugang "NMI source: invalid property!"); 274239736d59SChen Yugang return ipmi::responseResponseError(); 274339736d59SChen Yugang } 274439736d59SChen Yugang 274539736d59SChen Yugang try 274639736d59SChen Yugang { 274739736d59SChen Yugang // keep NMI signal source 274839736d59SChen Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 274939736d59SChen Yugang std::string service = 275039736d59SChen Yugang getService(*dbus, oemNmiSourceIntf, oemNmiSourceObjPath); 275139736d59SChen Yugang setDbusProperty( 275239736d59SChen Yugang *dbus, service, oemNmiSourceObjPath, oemNmiSourceIntf, 275339736d59SChen Yugang oemNmiBmcSourceObjPathProp, 275439736d59SChen Yugang sdbusplus::com::intel::Control::server::convertForMessage( 275539736d59SChen Yugang bmcSourceSignal)); 275699be6330SChen Yugang // set Enabled property to inform NMI source handling 275799be6330SChen Yugang // to trigger a NMI_OUT BSOD. 275899be6330SChen Yugang // if it's triggered by NMI source property changed, 275999be6330SChen Yugang // NMI_OUT BSOD could be missed if the same source occurs twice in a row 276099be6330SChen Yugang if (bmcSourceSignal != nmi::NMISource::BMCSourceSignal::None) 276199be6330SChen Yugang { 276299be6330SChen Yugang setDbusProperty(*dbus, service, oemNmiSourceObjPath, 276399be6330SChen Yugang oemNmiSourceIntf, oemNmiEnabledObjPathProp, 276499be6330SChen Yugang static_cast<bool>(true)); 276599be6330SChen Yugang } 276639736d59SChen Yugang } 276739736d59SChen Yugang catch (sdbusplus::exception_t& e) 276839736d59SChen Yugang { 276939736d59SChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 277039736d59SChen Yugang return ipmi::responseResponseError(); 277139736d59SChen Yugang } 277239736d59SChen Yugang 277339736d59SChen Yugang return ipmi::responseSuccess(); 277439736d59SChen Yugang } 277539736d59SChen Yugang 277663efafacSJames Feist namespace dimmOffset 277763efafacSJames Feist { 277863efafacSJames Feist constexpr const char* dimmPower = "DimmPower"; 277963efafacSJames Feist constexpr const char* staticCltt = "StaticCltt"; 278063efafacSJames Feist constexpr const char* offsetPath = "/xyz/openbmc_project/Inventory/Item/Dimm"; 278163efafacSJames Feist constexpr const char* offsetInterface = 278263efafacSJames Feist "xyz.openbmc_project.Inventory.Item.Dimm.Offset"; 278363efafacSJames Feist constexpr const char* property = "DimmOffset"; 278463efafacSJames Feist 278563efafacSJames Feist }; // namespace dimmOffset 278663efafacSJames Feist 278763efafacSJames Feist ipmi::RspType<> 278863efafacSJames Feist ipmiOEMSetDimmOffset(uint8_t type, 278963efafacSJames Feist const std::vector<std::tuple<uint8_t, uint8_t>>& data) 279063efafacSJames Feist { 279163efafacSJames Feist if (type != static_cast<uint8_t>(dimmOffsetTypes::dimmPower) && 279263efafacSJames Feist type != static_cast<uint8_t>(dimmOffsetTypes::staticCltt)) 279363efafacSJames Feist { 279463efafacSJames Feist return ipmi::responseInvalidFieldRequest(); 279563efafacSJames Feist } 279663efafacSJames Feist 279763efafacSJames Feist if (data.empty()) 279863efafacSJames Feist { 279963efafacSJames Feist return ipmi::responseInvalidFieldRequest(); 280063efafacSJames Feist } 280163efafacSJames Feist nlohmann::json json; 280263efafacSJames Feist 280363efafacSJames Feist std::ifstream jsonStream(dimmOffsetFile); 280463efafacSJames Feist if (jsonStream.good()) 280563efafacSJames Feist { 280663efafacSJames Feist json = nlohmann::json::parse(jsonStream, nullptr, false); 280763efafacSJames Feist if (json.is_discarded()) 280863efafacSJames Feist { 280963efafacSJames Feist json = nlohmann::json(); 281063efafacSJames Feist } 281163efafacSJames Feist jsonStream.close(); 281263efafacSJames Feist } 281363efafacSJames Feist 281463efafacSJames Feist std::string typeName; 281563efafacSJames Feist if (type == static_cast<uint8_t>(dimmOffsetTypes::dimmPower)) 281663efafacSJames Feist { 281763efafacSJames Feist typeName = dimmOffset::dimmPower; 281863efafacSJames Feist } 281963efafacSJames Feist else 282063efafacSJames Feist { 282163efafacSJames Feist typeName = dimmOffset::staticCltt; 282263efafacSJames Feist } 282363efafacSJames Feist 282463efafacSJames Feist nlohmann::json& field = json[typeName]; 282563efafacSJames Feist 282663efafacSJames Feist for (const auto& [index, value] : data) 282763efafacSJames Feist { 282863efafacSJames Feist field[index] = value; 282963efafacSJames Feist } 283063efafacSJames Feist 283163efafacSJames Feist for (nlohmann::json& val : field) 283263efafacSJames Feist { 283363efafacSJames Feist if (val == nullptr) 283463efafacSJames Feist { 283563efafacSJames Feist val = static_cast<uint8_t>(0); 283663efafacSJames Feist } 283763efafacSJames Feist } 283863efafacSJames Feist 283963efafacSJames Feist std::ofstream output(dimmOffsetFile); 284063efafacSJames Feist if (!output.good()) 284163efafacSJames Feist { 284263efafacSJames Feist std::cerr << "Error writing json file\n"; 284363efafacSJames Feist return ipmi::responseResponseError(); 284463efafacSJames Feist } 284563efafacSJames Feist 284663efafacSJames Feist output << json.dump(4); 284763efafacSJames Feist 284863efafacSJames Feist if (type == static_cast<uint8_t>(dimmOffsetTypes::staticCltt)) 284963efafacSJames Feist { 285063efafacSJames Feist std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 285163efafacSJames Feist 285263efafacSJames Feist std::variant<std::vector<uint8_t>> offsets = 285363efafacSJames Feist field.get<std::vector<uint8_t>>(); 285463efafacSJames Feist auto call = bus->new_method_call( 285563efafacSJames Feist settingsBusName, dimmOffset::offsetPath, PROP_INTF, "Set"); 285663efafacSJames Feist call.append(dimmOffset::offsetInterface, dimmOffset::property, offsets); 285763efafacSJames Feist try 285863efafacSJames Feist { 285963efafacSJames Feist bus->call(call); 286063efafacSJames Feist } 286163efafacSJames Feist catch (sdbusplus::exception_t& e) 286263efafacSJames Feist { 286363efafacSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>( 286463efafacSJames Feist "ipmiOEMSetDimmOffset: can't set dimm offsets!", 286563efafacSJames Feist phosphor::logging::entry("ERR=%s", e.what())); 286663efafacSJames Feist return ipmi::responseResponseError(); 286763efafacSJames Feist } 286863efafacSJames Feist } 286963efafacSJames Feist 287063efafacSJames Feist return ipmi::responseSuccess(); 287163efafacSJames Feist } 287263efafacSJames Feist 287363efafacSJames Feist ipmi::RspType<uint8_t> ipmiOEMGetDimmOffset(uint8_t type, uint8_t index) 287463efafacSJames Feist { 287563efafacSJames Feist 287663efafacSJames Feist if (type != static_cast<uint8_t>(dimmOffsetTypes::dimmPower) && 287763efafacSJames Feist type != static_cast<uint8_t>(dimmOffsetTypes::staticCltt)) 287863efafacSJames Feist { 287963efafacSJames Feist return ipmi::responseInvalidFieldRequest(); 288063efafacSJames Feist } 288163efafacSJames Feist 288263efafacSJames Feist std::ifstream jsonStream(dimmOffsetFile); 288363efafacSJames Feist 288463efafacSJames Feist auto json = nlohmann::json::parse(jsonStream, nullptr, false); 288563efafacSJames Feist if (json.is_discarded()) 288663efafacSJames Feist { 288763efafacSJames Feist std::cerr << "File error in " << dimmOffsetFile << "\n"; 288863efafacSJames Feist return ipmi::responseResponseError(); 288963efafacSJames Feist } 289063efafacSJames Feist 289163efafacSJames Feist std::string typeName; 289263efafacSJames Feist if (type == static_cast<uint8_t>(dimmOffsetTypes::dimmPower)) 289363efafacSJames Feist { 289463efafacSJames Feist typeName = dimmOffset::dimmPower; 289563efafacSJames Feist } 289663efafacSJames Feist else 289763efafacSJames Feist { 289863efafacSJames Feist typeName = dimmOffset::staticCltt; 289963efafacSJames Feist } 290063efafacSJames Feist 290163efafacSJames Feist auto it = json.find(typeName); 290263efafacSJames Feist if (it == json.end()) 290363efafacSJames Feist { 290463efafacSJames Feist return ipmi::responseInvalidFieldRequest(); 290563efafacSJames Feist } 290663efafacSJames Feist 290763efafacSJames Feist if (it->size() <= index) 290863efafacSJames Feist { 290963efafacSJames Feist return ipmi::responseInvalidFieldRequest(); 291063efafacSJames Feist } 291163efafacSJames Feist 291263efafacSJames Feist uint8_t resp = it->at(index).get<uint8_t>(); 291363efafacSJames Feist return ipmi::responseSuccess(resp); 291463efafacSJames Feist } 291563efafacSJames Feist 29164f7e76bbSChen,Yugang namespace boot_options 29174f7e76bbSChen,Yugang { 29184f7e76bbSChen,Yugang 29194f7e76bbSChen,Yugang using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server; 29204f7e76bbSChen,Yugang using IpmiValue = uint8_t; 29214f7e76bbSChen,Yugang constexpr auto ipmiDefault = 0; 29224f7e76bbSChen,Yugang 29234f7e76bbSChen,Yugang std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = { 29244f7e76bbSChen,Yugang {0x01, Source::Sources::Network}, 29254f7e76bbSChen,Yugang {0x02, Source::Sources::Disk}, 29264f7e76bbSChen,Yugang {0x05, Source::Sources::ExternalMedia}, 29274f7e76bbSChen,Yugang {0x0f, Source::Sources::RemovableMedia}, 29284f7e76bbSChen,Yugang {ipmiDefault, Source::Sources::Default}}; 29294f7e76bbSChen,Yugang 29304f7e76bbSChen,Yugang std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = { 2931ca12a7beSChen Yugang {0x06, Mode::Modes::Setup}, {ipmiDefault, Mode::Modes::Regular}}; 29324f7e76bbSChen,Yugang 29334f7e76bbSChen,Yugang std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = { 29344f7e76bbSChen,Yugang {Source::Sources::Network, 0x01}, 29354f7e76bbSChen,Yugang {Source::Sources::Disk, 0x02}, 29364f7e76bbSChen,Yugang {Source::Sources::ExternalMedia, 0x05}, 29374f7e76bbSChen,Yugang {Source::Sources::RemovableMedia, 0x0f}, 29384f7e76bbSChen,Yugang {Source::Sources::Default, ipmiDefault}}; 29394f7e76bbSChen,Yugang 29404f7e76bbSChen,Yugang std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = { 2941ca12a7beSChen Yugang {Mode::Modes::Setup, 0x06}, {Mode::Modes::Regular, ipmiDefault}}; 29424f7e76bbSChen,Yugang 29434f7e76bbSChen,Yugang static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode"; 29444f7e76bbSChen,Yugang static constexpr auto bootSourceIntf = 29454f7e76bbSChen,Yugang "xyz.openbmc_project.Control.Boot.Source"; 29464f7e76bbSChen,Yugang static constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable"; 29474f7e76bbSChen,Yugang static constexpr auto persistentObjPath = 29484f7e76bbSChen,Yugang "/xyz/openbmc_project/control/host0/boot"; 29494f7e76bbSChen,Yugang static constexpr auto oneTimePath = 29504f7e76bbSChen,Yugang "/xyz/openbmc_project/control/host0/boot/one_time"; 29514f7e76bbSChen,Yugang static constexpr auto bootSourceProp = "BootSource"; 29524f7e76bbSChen,Yugang static constexpr auto bootModeProp = "BootMode"; 29534f7e76bbSChen,Yugang static constexpr auto oneTimeBootEnableProp = "Enabled"; 29544f7e76bbSChen,Yugang static constexpr auto httpBootMode = 29554f7e76bbSChen,Yugang "xyz.openbmc_project.Control.Boot.Source.Sources.Http"; 29564f7e76bbSChen,Yugang 29574f7e76bbSChen,Yugang enum class BootOptionParameter : size_t 29584f7e76bbSChen,Yugang { 29594f7e76bbSChen,Yugang setInProgress = 0x0, 29604f7e76bbSChen,Yugang bootFlags = 0x5, 29614f7e76bbSChen,Yugang }; 29624f7e76bbSChen,Yugang static constexpr uint8_t setComplete = 0x0; 29634f7e76bbSChen,Yugang static constexpr uint8_t setInProgress = 0x1; 29644f7e76bbSChen,Yugang static uint8_t transferStatus = setComplete; 29654f7e76bbSChen,Yugang static constexpr uint8_t setParmVersion = 0x01; 29664f7e76bbSChen,Yugang static constexpr uint8_t setParmBootFlagsPermanent = 0x40; 29674f7e76bbSChen,Yugang static constexpr uint8_t setParmBootFlagsValidOneTime = 0x80; 29684f7e76bbSChen,Yugang static constexpr uint8_t setParmBootFlagsValidPermanent = 0xC0; 29694f7e76bbSChen,Yugang static constexpr uint8_t httpBoot = 0xd; 29704f7e76bbSChen,Yugang static constexpr uint8_t bootSourceMask = 0x3c; 29714f7e76bbSChen,Yugang 29724f7e76bbSChen,Yugang } // namespace boot_options 29734f7e76bbSChen,Yugang 29744f7e76bbSChen,Yugang ipmi::RspType<uint8_t, // version 29754f7e76bbSChen,Yugang uint8_t, // param 29764f7e76bbSChen,Yugang uint8_t, // data0, dependent on parameter 29774f7e76bbSChen,Yugang std::optional<uint8_t> // data1, dependent on parameter 29784f7e76bbSChen,Yugang > 29794f7e76bbSChen,Yugang ipmiOemGetEfiBootOptions(uint8_t parameter, uint8_t set, uint8_t block) 29804f7e76bbSChen,Yugang { 29814f7e76bbSChen,Yugang using namespace boot_options; 29824f7e76bbSChen,Yugang uint8_t bootOption = 0; 29834f7e76bbSChen,Yugang 29844f7e76bbSChen,Yugang if (parameter == static_cast<uint8_t>(BootOptionParameter::setInProgress)) 29854f7e76bbSChen,Yugang { 29864f7e76bbSChen,Yugang return ipmi::responseSuccess(setParmVersion, parameter, transferStatus, 29874f7e76bbSChen,Yugang std::nullopt); 29884f7e76bbSChen,Yugang } 29894f7e76bbSChen,Yugang 29904f7e76bbSChen,Yugang if (parameter != static_cast<uint8_t>(BootOptionParameter::bootFlags)) 29914f7e76bbSChen,Yugang { 29924f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>( 29934f7e76bbSChen,Yugang "Unsupported parameter"); 29944f7e76bbSChen,Yugang return ipmi::responseResponseError(); 29954f7e76bbSChen,Yugang } 29964f7e76bbSChen,Yugang 29974f7e76bbSChen,Yugang try 29984f7e76bbSChen,Yugang { 29994f7e76bbSChen,Yugang auto oneTimeEnabled = false; 30004f7e76bbSChen,Yugang // read one time Enabled property 30014f7e76bbSChen,Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 30024f7e76bbSChen,Yugang std::string service = getService(*dbus, enabledIntf, oneTimePath); 30034f7e76bbSChen,Yugang Value variant = getDbusProperty(*dbus, service, oneTimePath, 30044f7e76bbSChen,Yugang enabledIntf, oneTimeBootEnableProp); 30054f7e76bbSChen,Yugang oneTimeEnabled = std::get<bool>(variant); 30064f7e76bbSChen,Yugang 30074f7e76bbSChen,Yugang // get BootSource and BootMode properties 30084f7e76bbSChen,Yugang // according to oneTimeEnable 30094f7e76bbSChen,Yugang auto bootObjPath = oneTimePath; 30104f7e76bbSChen,Yugang if (oneTimeEnabled == false) 30114f7e76bbSChen,Yugang { 30124f7e76bbSChen,Yugang bootObjPath = persistentObjPath; 30134f7e76bbSChen,Yugang } 30144f7e76bbSChen,Yugang 30154f7e76bbSChen,Yugang service = getService(*dbus, bootModeIntf, bootObjPath); 30164f7e76bbSChen,Yugang variant = getDbusProperty(*dbus, service, bootObjPath, bootModeIntf, 30174f7e76bbSChen,Yugang bootModeProp); 30184f7e76bbSChen,Yugang 30194f7e76bbSChen,Yugang auto bootMode = 30204f7e76bbSChen,Yugang Mode::convertModesFromString(std::get<std::string>(variant)); 30214f7e76bbSChen,Yugang 30224f7e76bbSChen,Yugang service = getService(*dbus, bootSourceIntf, bootObjPath); 30234f7e76bbSChen,Yugang variant = getDbusProperty(*dbus, service, bootObjPath, bootSourceIntf, 30244f7e76bbSChen,Yugang bootSourceProp); 30254f7e76bbSChen,Yugang 30264f7e76bbSChen,Yugang if (std::get<std::string>(variant) == httpBootMode) 30274f7e76bbSChen,Yugang { 30284f7e76bbSChen,Yugang bootOption = httpBoot; 30294f7e76bbSChen,Yugang } 30304f7e76bbSChen,Yugang else 30314f7e76bbSChen,Yugang { 30324f7e76bbSChen,Yugang auto bootSource = Source::convertSourcesFromString( 30334f7e76bbSChen,Yugang std::get<std::string>(variant)); 30344f7e76bbSChen,Yugang bootOption = sourceDbusToIpmi.at(bootSource); 30354f7e76bbSChen,Yugang if (Source::Sources::Default == bootSource) 30364f7e76bbSChen,Yugang { 30374f7e76bbSChen,Yugang bootOption = modeDbusToIpmi.at(bootMode); 30384f7e76bbSChen,Yugang } 30394f7e76bbSChen,Yugang } 30404f7e76bbSChen,Yugang 30414f7e76bbSChen,Yugang uint8_t oneTime = oneTimeEnabled ? setParmBootFlagsValidOneTime 30424f7e76bbSChen,Yugang : setParmBootFlagsValidPermanent; 30434f7e76bbSChen,Yugang bootOption <<= 2; // shift for responseconstexpr 30444f7e76bbSChen,Yugang return ipmi::responseSuccess(setParmVersion, parameter, oneTime, 30454f7e76bbSChen,Yugang bootOption); 30464f7e76bbSChen,Yugang } 30474f7e76bbSChen,Yugang catch (sdbusplus::exception_t& e) 30484f7e76bbSChen,Yugang { 30494f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 30504f7e76bbSChen,Yugang return ipmi::responseResponseError(); 30514f7e76bbSChen,Yugang } 30524f7e76bbSChen,Yugang } 30534f7e76bbSChen,Yugang 30544f7e76bbSChen,Yugang ipmi::RspType<> ipmiOemSetEfiBootOptions(uint8_t bootFlag, uint8_t bootParam, 30554f7e76bbSChen,Yugang std::optional<uint8_t> bootOption) 30564f7e76bbSChen,Yugang { 30574f7e76bbSChen,Yugang using namespace boot_options; 30584f7e76bbSChen,Yugang auto oneTimeEnabled = false; 30594f7e76bbSChen,Yugang 30604f7e76bbSChen,Yugang if (bootFlag == static_cast<uint8_t>(BootOptionParameter::setInProgress)) 30614f7e76bbSChen,Yugang { 30624f7e76bbSChen,Yugang if (bootOption) 30634f7e76bbSChen,Yugang { 30644f7e76bbSChen,Yugang return ipmi::responseReqDataLenInvalid(); 30654f7e76bbSChen,Yugang } 30664f7e76bbSChen,Yugang 30674f7e76bbSChen,Yugang if (transferStatus == setInProgress) 30684f7e76bbSChen,Yugang { 30694f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>( 30704f7e76bbSChen,Yugang "boot option set in progress!"); 30714f7e76bbSChen,Yugang return ipmi::responseResponseError(); 30724f7e76bbSChen,Yugang } 30734f7e76bbSChen,Yugang 30744f7e76bbSChen,Yugang transferStatus = bootParam; 30754f7e76bbSChen,Yugang return ipmi::responseSuccess(); 30764f7e76bbSChen,Yugang } 30774f7e76bbSChen,Yugang 30784f7e76bbSChen,Yugang if (bootFlag != (uint8_t)BootOptionParameter::bootFlags) 30794f7e76bbSChen,Yugang { 30804f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>( 30814f7e76bbSChen,Yugang "Unsupported parameter"); 30824f7e76bbSChen,Yugang return ipmi::responseResponseError(); 30834f7e76bbSChen,Yugang } 30844f7e76bbSChen,Yugang 30854f7e76bbSChen,Yugang if (!bootOption) 30864f7e76bbSChen,Yugang { 30874f7e76bbSChen,Yugang return ipmi::responseReqDataLenInvalid(); 30884f7e76bbSChen,Yugang } 30894f7e76bbSChen,Yugang 30904f7e76bbSChen,Yugang if (((bootOption.value() & bootSourceMask) >> 2) != 30914f7e76bbSChen,Yugang httpBoot) // not http boot, exit 30924f7e76bbSChen,Yugang { 30934f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>( 30944f7e76bbSChen,Yugang "wrong boot option parameter!"); 30954f7e76bbSChen,Yugang return ipmi::responseParmOutOfRange(); 30964f7e76bbSChen,Yugang } 30974f7e76bbSChen,Yugang 30984f7e76bbSChen,Yugang try 30994f7e76bbSChen,Yugang { 31004f7e76bbSChen,Yugang bool permanent = (bootParam & setParmBootFlagsPermanent) == 31014f7e76bbSChen,Yugang setParmBootFlagsPermanent; 31024f7e76bbSChen,Yugang 31034f7e76bbSChen,Yugang // read one time Enabled property 31044f7e76bbSChen,Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 31054f7e76bbSChen,Yugang std::string service = getService(*dbus, enabledIntf, oneTimePath); 31064f7e76bbSChen,Yugang Value variant = getDbusProperty(*dbus, service, oneTimePath, 31074f7e76bbSChen,Yugang enabledIntf, oneTimeBootEnableProp); 31084f7e76bbSChen,Yugang oneTimeEnabled = std::get<bool>(variant); 31094f7e76bbSChen,Yugang 31104f7e76bbSChen,Yugang /* 31114f7e76bbSChen,Yugang * Check if the current boot setting is onetime or permanent, if the 31124f7e76bbSChen,Yugang * request in the command is otherwise, then set the "Enabled" 31134f7e76bbSChen,Yugang * property in one_time object path to 'True' to indicate onetime 31144f7e76bbSChen,Yugang * and 'False' to indicate permanent. 31154f7e76bbSChen,Yugang * 31164f7e76bbSChen,Yugang * Once the onetime/permanent setting is applied, then the bootMode 31174f7e76bbSChen,Yugang * and bootSource is updated for the corresponding object. 31184f7e76bbSChen,Yugang */ 31194f7e76bbSChen,Yugang if (permanent == oneTimeEnabled) 31204f7e76bbSChen,Yugang { 31214f7e76bbSChen,Yugang setDbusProperty(*dbus, service, oneTimePath, enabledIntf, 31224f7e76bbSChen,Yugang oneTimeBootEnableProp, !permanent); 31234f7e76bbSChen,Yugang } 31244f7e76bbSChen,Yugang 31254f7e76bbSChen,Yugang // set BootSource and BootMode properties 31264f7e76bbSChen,Yugang // according to oneTimeEnable or persistent 31274f7e76bbSChen,Yugang auto bootObjPath = oneTimePath; 31284f7e76bbSChen,Yugang if (oneTimeEnabled == false) 31294f7e76bbSChen,Yugang { 31304f7e76bbSChen,Yugang bootObjPath = persistentObjPath; 31314f7e76bbSChen,Yugang } 31324f7e76bbSChen,Yugang std::string bootMode = 31334f7e76bbSChen,Yugang "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"; 31344f7e76bbSChen,Yugang std::string bootSource = httpBootMode; 31354f7e76bbSChen,Yugang 31364f7e76bbSChen,Yugang service = getService(*dbus, bootModeIntf, bootObjPath); 31374f7e76bbSChen,Yugang setDbusProperty(*dbus, service, bootObjPath, bootModeIntf, bootModeProp, 31384f7e76bbSChen,Yugang bootMode); 31394f7e76bbSChen,Yugang 31404f7e76bbSChen,Yugang service = getService(*dbus, bootSourceIntf, bootObjPath); 31414f7e76bbSChen,Yugang setDbusProperty(*dbus, service, bootObjPath, bootSourceIntf, 31424f7e76bbSChen,Yugang bootSourceProp, bootSource); 31434f7e76bbSChen,Yugang } 31444f7e76bbSChen,Yugang catch (sdbusplus::exception_t& e) 31454f7e76bbSChen,Yugang { 31464f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 31474f7e76bbSChen,Yugang return ipmi::responseResponseError(); 31484f7e76bbSChen,Yugang } 31494f7e76bbSChen,Yugang 31504f7e76bbSChen,Yugang return ipmi::responseSuccess(); 31514f7e76bbSChen,Yugang } 31524f7e76bbSChen,Yugang 3153ca12a7beSChen Yugang ipmi::RspType<> ipmiOemSetBootOptions(uint8_t bootFlag, uint8_t bootParam, 3154ca12a7beSChen Yugang std::optional<uint8_t> bootOption) 3155ca12a7beSChen Yugang { 3156ca12a7beSChen Yugang bool oneTimeEnabled = false; 3157ca12a7beSChen Yugang uint8_t bootOptionValue = 0; 3158ca12a7beSChen Yugang static constexpr const uint8_t shiftBits = 2; 3159ca12a7beSChen Yugang 3160ca12a7beSChen Yugang if (bootFlag == 3161ca12a7beSChen Yugang static_cast<uint8_t>(boot_options::BootOptionParameter::setInProgress)) 3162ca12a7beSChen Yugang { 3163ca12a7beSChen Yugang if (bootOption) 3164ca12a7beSChen Yugang { 3165ca12a7beSChen Yugang return ipmi::responseReqDataLenInvalid(); 3166ca12a7beSChen Yugang } 3167ca12a7beSChen Yugang 3168ca12a7beSChen Yugang if (boot_options::transferStatus == boot_options::setInProgress) 3169ca12a7beSChen Yugang { 3170ca12a7beSChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>( 3171ca12a7beSChen Yugang "boot option set in progress!"); 3172ca12a7beSChen Yugang return ipmi::responseResponseError(); 3173ca12a7beSChen Yugang } 3174ca12a7beSChen Yugang 3175ca12a7beSChen Yugang boot_options::transferStatus = bootParam; 3176ca12a7beSChen Yugang return ipmi::responseSuccess(); 3177ca12a7beSChen Yugang } 3178ca12a7beSChen Yugang 3179ca12a7beSChen Yugang if (bootFlag != 3180ca12a7beSChen Yugang static_cast<uint8_t>(boot_options::BootOptionParameter::bootFlags)) 3181ca12a7beSChen Yugang { 3182ca12a7beSChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>( 3183ca12a7beSChen Yugang "Unsupported parameter"); 3184ca12a7beSChen Yugang return ipmi::responseResponseError(); 3185ca12a7beSChen Yugang } 3186ca12a7beSChen Yugang 3187ca12a7beSChen Yugang if (!bootOption) 3188ca12a7beSChen Yugang { 3189ca12a7beSChen Yugang return ipmi::responseReqDataLenInvalid(); 3190ca12a7beSChen Yugang } 3191ca12a7beSChen Yugang bootOptionValue = 3192ca12a7beSChen Yugang (bootOption.value() & boot_options::bootSourceMask) >> shiftBits; 3193ca12a7beSChen Yugang 3194ca12a7beSChen Yugang try 3195ca12a7beSChen Yugang { 3196ca12a7beSChen Yugang bool permanent = 3197ca12a7beSChen Yugang (bootParam & boot_options::setParmBootFlagsPermanent) == 3198ca12a7beSChen Yugang boot_options::setParmBootFlagsPermanent; 3199ca12a7beSChen Yugang auto bootMode = boot_options::Mode::Modes::Regular; 3200ca12a7beSChen Yugang auto bootSource = boot_options::Source::Sources::Default; 3201ca12a7beSChen Yugang 3202ca12a7beSChen Yugang // read one time Enabled property 3203ca12a7beSChen Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); 3204ca12a7beSChen Yugang std::string service = getService(*dbus, boot_options::enabledIntf, 3205ca12a7beSChen Yugang boot_options::oneTimePath); 3206ca12a7beSChen Yugang Value variant = getDbusProperty( 3207ca12a7beSChen Yugang *dbus, service, boot_options::oneTimePath, 3208ca12a7beSChen Yugang boot_options::enabledIntf, boot_options::oneTimeBootEnableProp); 3209ca12a7beSChen Yugang oneTimeEnabled = std::get_if<bool>(&variant); 3210ca12a7beSChen Yugang 3211ca12a7beSChen Yugang /* 3212ca12a7beSChen Yugang * Check if the current boot setting is onetime or permanent, if the 3213ca12a7beSChen Yugang * request in the command is otherwise, then set the "Enabled" 3214ca12a7beSChen Yugang * property in one_time object path to 'True' to indicate onetime 3215ca12a7beSChen Yugang * and 'False' to indicate permanent. 3216ca12a7beSChen Yugang * 3217ca12a7beSChen Yugang * Once the onetime/permanent setting is applied, then the bootMode 3218ca12a7beSChen Yugang * and bootSource is updated for the corresponding object. 3219ca12a7beSChen Yugang */ 3220ca12a7beSChen Yugang if (permanent == oneTimeEnabled) 3221ca12a7beSChen Yugang { 3222ca12a7beSChen Yugang setDbusProperty(*dbus, service, boot_options::oneTimePath, 3223ca12a7beSChen Yugang boot_options::enabledIntf, 3224ca12a7beSChen Yugang boot_options::oneTimeBootEnableProp, !permanent); 3225ca12a7beSChen Yugang } 3226ca12a7beSChen Yugang 3227ca12a7beSChen Yugang // set BootSource and BootMode properties 3228ca12a7beSChen Yugang // according to oneTimeEnable or persistent 3229ca12a7beSChen Yugang auto bootObjPath = boot_options::oneTimePath; 3230ca12a7beSChen Yugang if (oneTimeEnabled == false) 3231ca12a7beSChen Yugang { 3232ca12a7beSChen Yugang bootObjPath = boot_options::persistentObjPath; 3233ca12a7beSChen Yugang } 3234ca12a7beSChen Yugang 3235ca12a7beSChen Yugang auto modeItr = boot_options::modeIpmiToDbus.find(bootOptionValue); 3236ca12a7beSChen Yugang auto sourceItr = boot_options::sourceIpmiToDbus.find(bootOptionValue); 3237ca12a7beSChen Yugang 3238ca12a7beSChen Yugang if (boot_options::sourceIpmiToDbus.end() != sourceItr) 3239ca12a7beSChen Yugang { 3240ca12a7beSChen Yugang bootSource = sourceItr->second; 3241ca12a7beSChen Yugang } 3242ca12a7beSChen Yugang 3243ca12a7beSChen Yugang if (boot_options::modeIpmiToDbus.end() != modeItr) 3244ca12a7beSChen Yugang { 3245ca12a7beSChen Yugang bootMode = modeItr->second; 3246ca12a7beSChen Yugang } 3247ca12a7beSChen Yugang 3248ca12a7beSChen Yugang if ((boot_options::modeIpmiToDbus.end() == modeItr) && 3249ca12a7beSChen Yugang (boot_options::sourceIpmiToDbus.end() == sourceItr)) 3250ca12a7beSChen Yugang { 3251ca12a7beSChen Yugang // return error if boot option is not supported 3252ca12a7beSChen Yugang return ipmi::responseInvalidFieldRequest(); 3253ca12a7beSChen Yugang } 3254ca12a7beSChen Yugang service = getService(*dbus, boot_options::bootModeIntf, bootObjPath); 3255ca12a7beSChen Yugang setDbusProperty(*dbus, service, bootObjPath, boot_options::bootModeIntf, 3256ca12a7beSChen Yugang boot_options::bootModeProp, 3257ca12a7beSChen Yugang convertForMessage(bootMode)); 3258ca12a7beSChen Yugang 3259ca12a7beSChen Yugang service = getService(*dbus, boot_options::bootSourceIntf, bootObjPath); 3260ca12a7beSChen Yugang setDbusProperty( 3261ca12a7beSChen Yugang *dbus, service, bootObjPath, boot_options::bootSourceIntf, 3262ca12a7beSChen Yugang boot_options::bootSourceProp, convertForMessage(bootSource)); 3263ca12a7beSChen Yugang } 3264ca12a7beSChen Yugang catch (sdbusplus::exception_t& e) 3265ca12a7beSChen Yugang { 3266ca12a7beSChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); 3267ca12a7beSChen Yugang return ipmi::responseResponseError(); 3268ca12a7beSChen Yugang } 3269ca12a7beSChen Yugang 3270ca12a7beSChen Yugang return ipmi::responseSuccess(); 3271ca12a7beSChen Yugang } 3272ca12a7beSChen Yugang 327364796041SJason M. Bills static void registerOEMFunctions(void) 3274a835eaa0SJia, Chunhui { 3275a835eaa0SJia, Chunhui phosphor::logging::log<phosphor::logging::level::INFO>( 3276a835eaa0SJia, Chunhui "Registering OEM commands"); 327798bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, IPMI_CMD_WILDCARD, NULL, 3278a835eaa0SJia, Chunhui ipmiOEMWildcard, 3279a835eaa0SJia, Chunhui PRIVILEGE_USER); // wildcard default handler 328098bbf69aSVernon Mauery 328198bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnApp, IPMI_CMD_WILDCARD, NULL, 328264796041SJason M. Bills ipmiOEMWildcard, 328364796041SJason M. Bills PRIVILEGE_USER); // wildcard default handler 328498bbf69aSVernon Mauery 328598bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, 328698bbf69aSVernon Mauery intel::general::cmdGetChassisIdentifier, NULL, 328798bbf69aSVernon Mauery ipmiOEMGetChassisIdentifier, 3288a835eaa0SJia, Chunhui PRIVILEGE_USER); // get chassis identifier 328998bbf69aSVernon Mauery 329098bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, intel::general::cmdSetSystemGUID, 329164796041SJason M. Bills NULL, ipmiOEMSetSystemGUID, 3292a835eaa0SJia, Chunhui PRIVILEGE_ADMIN); // set system guid 3293b02bf095SJason M. Bills 3294b02bf095SJason M. Bills // <Disable BMC System Reset Action> 329598bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 329698bbf69aSVernon Mauery intel::general::cmdDisableBMCSystemReset, Privilege::Admin, 329798bbf69aSVernon Mauery ipmiOEMDisableBMCSystemReset); 329898bbf69aSVernon Mauery 3299b02bf095SJason M. Bills // <Get BMC Reset Disables> 330098bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 330198bbf69aSVernon Mauery intel::general::cmdGetBMCResetDisables, Privilege::Admin, 330298bbf69aSVernon Mauery ipmiOEMGetBMCResetDisables); 3303b02bf095SJason M. Bills 330498bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, intel::general::cmdSetBIOSID, 330564796041SJason M. Bills NULL, ipmiOEMSetBIOSID, PRIVILEGE_ADMIN); 3306cc49b54bSJia, Chunhui 330798bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, 330898bbf69aSVernon Mauery intel::general::cmdGetOEMDeviceInfo, NULL, 330998bbf69aSVernon Mauery ipmiOEMGetDeviceInfo, PRIVILEGE_USER); 3310cc49b54bSJia, Chunhui 331198bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, 331298bbf69aSVernon Mauery intel::general::cmdGetAICSlotFRUIDSlotPosRecords, NULL, 331398bbf69aSVernon Mauery ipmiOEMGetAICFRU, PRIVILEGE_USER); 3314d509eb91SSuryakanth Sekar 331598bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral, 331698bbf69aSVernon Mauery intel::general::cmdSendEmbeddedFWUpdStatus, 331798bbf69aSVernon Mauery Privilege::Operator, ipmiOEMSendEmbeddedFwUpdStatus); 3318d509eb91SSuryakanth Sekar 331998bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, 332098bbf69aSVernon Mauery intel::general::cmdSetPowerRestoreDelay, NULL, 332198bbf69aSVernon Mauery ipmiOEMSetPowerRestoreDelay, PRIVILEGE_OPERATOR); 332298bbf69aSVernon Mauery 332398bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, 332498bbf69aSVernon Mauery intel::general::cmdGetPowerRestoreDelay, NULL, 332598bbf69aSVernon Mauery ipmiOEMGetPowerRestoreDelay, PRIVILEGE_USER); 332698bbf69aSVernon Mauery 332798bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral, 332898bbf69aSVernon Mauery intel::general::cmdSetOEMUser2Activation, 332998bbf69aSVernon Mauery Privilege::Callback, ipmiOEMSetUser2Activation); 333098bbf69aSVernon Mauery 333198bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral, 333298bbf69aSVernon Mauery intel::general::cmdSetSpecialUserPassword, 333398bbf69aSVernon Mauery Privilege::Callback, ipmiOEMSetSpecialUserPassword); 3334fc5e985bSRichard Marian Thomaiyar 333542bd9c8eSJason M. Bills // <Get Processor Error Config> 333698bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 333798bbf69aSVernon Mauery intel::general::cmdGetProcessorErrConfig, Privilege::User, 333898bbf69aSVernon Mauery ipmiOEMGetProcessorErrConfig); 333998bbf69aSVernon Mauery 334042bd9c8eSJason M. Bills // <Set Processor Error Config> 334198bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 334298bbf69aSVernon Mauery intel::general::cmdSetProcessorErrConfig, Privilege::Admin, 334398bbf69aSVernon Mauery ipmiOEMSetProcessorErrConfig); 334442bd9c8eSJason M. Bills 334598bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, 334698bbf69aSVernon Mauery intel::general::cmdSetShutdownPolicy, NULL, 334798bbf69aSVernon Mauery ipmiOEMSetShutdownPolicy, PRIVILEGE_ADMIN); 334891244a6aSJames Feist 334998bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, 335098bbf69aSVernon Mauery intel::general::cmdGetShutdownPolicy, NULL, 335198bbf69aSVernon Mauery ipmiOEMGetShutdownPolicy, PRIVILEGE_ADMIN); 335298bbf69aSVernon Mauery 335398bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, intel::general::cmdSetFanConfig, 335491244a6aSJames Feist NULL, ipmiOEMSetFanConfig, PRIVILEGE_USER); 335591244a6aSJames Feist 335698bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 335798bbf69aSVernon Mauery intel::general::cmdGetFanConfig, Privilege::User, 335898bbf69aSVernon Mauery ipmiOEMGetFanConfig); 335991244a6aSJames Feist 336098bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 336198bbf69aSVernon Mauery intel::general::cmdGetFanSpeedOffset, Privilege::User, 336298bbf69aSVernon Mauery ipmiOEMGetFanSpeedOffset); 33635f957cafSJames Feist 336498bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 336598bbf69aSVernon Mauery intel::general::cmdSetFanSpeedOffset, Privilege::User, 336698bbf69aSVernon Mauery ipmiOEMSetFanSpeedOffset); 3367acc8a4ebSJames Feist 336898bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 336998bbf69aSVernon Mauery intel::general::cmdSetFscParameter, Privilege::User, 337098bbf69aSVernon Mauery ipmiOEMSetFscParameter); 3371acc8a4ebSJames Feist 337298bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 337398bbf69aSVernon Mauery intel::general::cmdGetFscParameter, Privilege::User, 337498bbf69aSVernon Mauery ipmiOEMGetFscParameter); 33755f957cafSJames Feist 337698bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral, 337798bbf69aSVernon Mauery intel::general::cmdReadBaseBoardProductId, Privilege::Admin, 337898bbf69aSVernon Mauery ipmiOEMReadBoardProductId); 3379ea537d53SRichard Marian Thomaiyar 338098bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 338198bbf69aSVernon Mauery intel::general::cmdGetNmiStatus, Privilege::User, 338298bbf69aSVernon Mauery ipmiOEMGetNmiSource); 338339736d59SChen Yugang 338498bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 338598bbf69aSVernon Mauery intel::general::cmdSetNmiStatus, Privilege::Operator, 338698bbf69aSVernon Mauery ipmiOEMSetNmiSource); 338739736d59SChen Yugang 338898bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 338998bbf69aSVernon Mauery intel::general::cmdGetEfiBootOptions, Privilege::User, 339098bbf69aSVernon Mauery ipmiOemGetEfiBootOptions); 33914f7e76bbSChen,Yugang 339298bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 339398bbf69aSVernon Mauery intel::general::cmdSetEfiBootOptions, Privilege::Operator, 339498bbf69aSVernon Mauery ipmiOemSetEfiBootOptions); 33954f7e76bbSChen,Yugang 339698bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 339798bbf69aSVernon Mauery intel::general::cmdGetSecurityMode, Privilege::User, 339898bbf69aSVernon Mauery ipmiGetSecurityMode); 3399d801e463SRichard Marian Thomaiyar 340098bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 340198bbf69aSVernon Mauery intel::general::cmdSetSecurityMode, Privilege::Admin, 340298bbf69aSVernon Mauery ipmiSetSecurityMode); 3403d801e463SRichard Marian Thomaiyar 340498bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, intel::general::cmdGetLEDStatus, 340545f04988SKuiying Wang NULL, ipmiOEMGetLEDStatus, PRIVILEGE_ADMIN); 34064ac799d7SVernon Mauery 340798bbf69aSVernon Mauery ipmiPrintAndRegister(ipmi::intel::netFnPlatform, 340898bbf69aSVernon Mauery ipmi::intel::platform::cmdCfgHostSerialPortSpeed, NULL, 340998bbf69aSVernon Mauery ipmiOEMCfgHostSerialPortSpeed, PRIVILEGE_ADMIN); 3410773703a5SCheng C Yang 341198bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 341298bbf69aSVernon Mauery intel::general::cmdSetFaultIndication, Privilege::Operator, 341398bbf69aSVernon Mauery ipmiOEMSetFaultIndication); 341498bbf69aSVernon Mauery 341598bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 341698bbf69aSVernon Mauery intel::general::cmdSetColdRedundancyConfig, Privilege::User, 341798bbf69aSVernon Mauery ipmiOEMSetCRConfig); 341898bbf69aSVernon Mauery 341998bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 342098bbf69aSVernon Mauery intel::general::cmdGetColdRedundancyConfig, Privilege::User, 342198bbf69aSVernon Mauery ipmiOEMGetCRConfig); 342298bbf69aSVernon Mauery 342398bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 342498bbf69aSVernon Mauery intel::general::cmdRestoreConfiguration, Privilege::Admin, 34254ac799d7SVernon Mauery ipmiRestoreConfiguration); 342663efafacSJames Feist 342798bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 342898bbf69aSVernon Mauery intel::general::cmdSetDimmOffset, Privilege::Operator, 342998bbf69aSVernon Mauery ipmiOEMSetDimmOffset); 343063efafacSJames Feist 343198bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral, 343298bbf69aSVernon Mauery intel::general::cmdGetDimmOffset, Privilege::Operator, 343398bbf69aSVernon Mauery ipmiOEMGetDimmOffset); 3434ca12a7beSChen Yugang 343598bbf69aSVernon Mauery registerHandler(prioOemBase, netFnChassis, chassis::cmdSetSystemBootOptions, 343698bbf69aSVernon Mauery Privilege::Operator, ipmiOemSetBootOptions); 3437a835eaa0SJia, Chunhui } 3438a835eaa0SJia, Chunhui 3439a835eaa0SJia, Chunhui } // namespace ipmi 3440