| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 1 | /* | 
|  | 2 | // Copyright (c) 2018 Intel Corporation | 
|  | 3 | // | 
|  | 4 | // Licensed under the Apache License, Version 2.0 (the "License"); | 
|  | 5 | // you may not use this file except in compliance with the License. | 
|  | 6 | // You may obtain a copy of the License at | 
|  | 7 | // | 
|  | 8 | //      http://www.apache.org/licenses/LICENSE-2.0 | 
|  | 9 | // | 
|  | 10 | // Unless required by applicable law or agreed to in writing, software | 
|  | 11 | // distributed under the License is distributed on an "AS IS" BASIS, | 
|  | 12 | // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | 
|  | 13 | // See the License for the specific language governing permissions and | 
|  | 14 | // limitations under the License. | 
|  | 15 | */ | 
|  | 16 |  | 
| Patrick Venture | c2a07d4 | 2020-05-30 16:35:03 -0700 | [diff] [blame] | 17 | #include "types.hpp" | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 18 | #include "xyz/openbmc_project/Common/error.hpp" | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 19 | #include "xyz/openbmc_project/Led/Physical/server.hpp" | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 20 |  | 
| Jayaprakash Mutyala | 9420416 | 2020-10-23 06:17:56 +0000 | [diff] [blame] | 21 | #include <openssl/crypto.h> | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 22 | #include <systemd/sd-journal.h> | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 23 |  | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 24 | #include <appcommands.hpp> | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 25 | #include <boost/container/flat_map.hpp> | 
| Yong Li | 23737fe | 2019-02-19 08:49:55 +0800 | [diff] [blame] | 26 | #include <boost/process/child.hpp> | 
|  | 27 | #include <boost/process/io.hpp> | 
| Yong Li | 0669d19 | 2019-05-06 14:01:46 +0800 | [diff] [blame] | 28 | #include <com/intel/Control/OCOTShutdownPolicy/server.hpp> | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 29 | #include <commandutils.hpp> | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 30 | #include <gpiod.hpp> | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 31 | #include <ipmid/api.hpp> | 
| Vernon Mauery | 5480ef6 | 2019-03-20 13:43:11 -0700 | [diff] [blame] | 32 | #include <ipmid/utils.hpp> | 
| James Feist | 63efafa | 2019-07-24 12:39:21 -0700 | [diff] [blame] | 33 | #include <nlohmann/json.hpp> | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 34 | #include <oemcommands.hpp> | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 35 | #include <phosphor-logging/log.hpp> | 
|  | 36 | #include <sdbusplus/bus.hpp> | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 37 | #include <sdbusplus/message/types.hpp> | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 38 | #include <xyz/openbmc_project/Chassis/Control/NMISource/server.hpp> | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 39 | #include <xyz/openbmc_project/Control/Boot/Mode/server.hpp> | 
|  | 40 | #include <xyz/openbmc_project/Control/Boot/Source/server.hpp> | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 41 | #include <xyz/openbmc_project/Control/PowerSupplyRedundancy/server.hpp> | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 42 | #include <xyz/openbmc_project/Control/Security/RestrictionMode/server.hpp> | 
| Richard Marian Thomaiyar | 8d4f8d7 | 2019-11-11 12:06:40 +0530 | [diff] [blame] | 43 | #include <xyz/openbmc_project/Control/Security/SpecialMode/server.hpp> | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 44 |  | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 45 | #include <array> | 
|  | 46 | #include <filesystem> | 
|  | 47 | #include <iostream> | 
|  | 48 | #include <regex> | 
| Ankita Vilas Gawade | a165038 | 2022-01-08 10:30:40 +0000 | [diff] [blame^] | 49 | #include <set> | 
| James Feist | fcd2d3a | 2020-05-28 10:38:15 -0700 | [diff] [blame] | 50 | #include <string> | 
|  | 51 | #include <variant> | 
|  | 52 | #include <vector> | 
|  | 53 |  | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 54 | namespace ipmi | 
|  | 55 | { | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 56 | static void registerOEMFunctions() __attribute__((constructor)); | 
| Vernon Mauery | 4ac799d | 2019-05-20 15:50:37 -0700 | [diff] [blame] | 57 |  | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 58 | static constexpr size_t maxFRUStringLength = 0x3F; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 59 |  | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 60 | static constexpr auto ethernetIntf = | 
|  | 61 | "xyz.openbmc_project.Network.EthernetInterface"; | 
|  | 62 | static constexpr auto networkIPIntf = "xyz.openbmc_project.Network.IP"; | 
|  | 63 | static constexpr auto networkService = "xyz.openbmc_project.Network"; | 
|  | 64 | static constexpr auto networkRoot = "/xyz/openbmc_project/network"; | 
|  | 65 |  | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 66 | static constexpr const char* oemNmiSourceIntf = | 
|  | 67 | "xyz.openbmc_project.Chassis.Control.NMISource"; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 68 | static constexpr const char* oemNmiSourceObjPath = | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 69 | "/xyz/openbmc_project/Chassis/Control/NMISource"; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 70 | static constexpr const char* oemNmiBmcSourceObjPathProp = "BMCSource"; | 
|  | 71 | static constexpr const char* oemNmiEnabledObjPathProp = "Enabled"; | 
|  | 72 |  | 
| James Feist | 63efafa | 2019-07-24 12:39:21 -0700 | [diff] [blame] | 73 | static constexpr const char* dimmOffsetFile = "/var/lib/ipmi/ipmi_dimms.json"; | 
| srikanta mondal | 2030d7c | 2020-05-03 17:25:25 +0000 | [diff] [blame] | 74 | static constexpr const char* multiNodeObjPath = | 
|  | 75 | "/xyz/openbmc_project/MultiNode/Status"; | 
|  | 76 | static constexpr const char* multiNodeIntf = | 
|  | 77 | "xyz.openbmc_project.Chassis.MultiNode"; | 
| James Feist | 63efafa | 2019-07-24 12:39:21 -0700 | [diff] [blame] | 78 |  | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 79 | enum class NmiSource : uint8_t | 
|  | 80 | { | 
|  | 81 | none = 0, | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 82 | frontPanelButton = 1, | 
|  | 83 | watchdog = 2, | 
|  | 84 | chassisCmd = 3, | 
|  | 85 | memoryError = 4, | 
|  | 86 | pciBusError = 5, | 
|  | 87 | pch = 6, | 
|  | 88 | chipset = 7, | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 89 | }; | 
|  | 90 |  | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 91 | enum class SpecialUserIndex : uint8_t | 
|  | 92 | { | 
|  | 93 | rootUser = 0, | 
|  | 94 | atScaleDebugUser = 1 | 
|  | 95 | }; | 
|  | 96 |  | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 97 | static constexpr const char* restricionModeService = | 
|  | 98 | "xyz.openbmc_project.RestrictionMode.Manager"; | 
|  | 99 | static constexpr const char* restricionModeBasePath = | 
|  | 100 | "/xyz/openbmc_project/control/security/restriction_mode"; | 
|  | 101 | static constexpr const char* restricionModeIntf = | 
|  | 102 | "xyz.openbmc_project.Control.Security.RestrictionMode"; | 
|  | 103 | static constexpr const char* restricionModeProperty = "RestrictionMode"; | 
|  | 104 |  | 
|  | 105 | static constexpr const char* specialModeService = | 
|  | 106 | "xyz.openbmc_project.SpecialMode"; | 
|  | 107 | static constexpr const char* specialModeBasePath = | 
| Richard Marian Thomaiyar | a7b7428 | 2019-09-22 21:53:14 +0530 | [diff] [blame] | 108 | "/xyz/openbmc_project/security/special_mode"; | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 109 | static constexpr const char* specialModeIntf = | 
|  | 110 | "xyz.openbmc_project.Security.SpecialMode"; | 
|  | 111 | static constexpr const char* specialModeProperty = "SpecialMode"; | 
|  | 112 |  | 
|  | 113 | static constexpr const char* dBusPropertyIntf = | 
|  | 114 | "org.freedesktop.DBus.Properties"; | 
|  | 115 | static constexpr const char* dBusPropertyGetMethod = "Get"; | 
|  | 116 | static constexpr const char* dBusPropertySetMethod = "Set"; | 
|  | 117 |  | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 118 | // return code: 0 successful | 
|  | 119 | int8_t getChassisSerialNumber(sdbusplus::bus::bus& bus, std::string& serial) | 
|  | 120 | { | 
|  | 121 | std::string objpath = "/xyz/openbmc_project/FruDevice"; | 
|  | 122 | std::string intf = "xyz.openbmc_project.FruDeviceManager"; | 
|  | 123 | std::string service = getService(bus, intf, objpath); | 
|  | 124 | ObjectValueTree valueTree = getManagedObjects(bus, service, "/"); | 
|  | 125 | if (valueTree.empty()) | 
|  | 126 | { | 
|  | 127 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 128 | "No object implements interface", | 
|  | 129 | phosphor::logging::entry("INTF=%s", intf.c_str())); | 
|  | 130 | return -1; | 
|  | 131 | } | 
|  | 132 |  | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 133 | for (const auto& item : valueTree) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 134 | { | 
|  | 135 | auto interface = item.second.find("xyz.openbmc_project.FruDevice"); | 
|  | 136 | if (interface == item.second.end()) | 
|  | 137 | { | 
|  | 138 | continue; | 
|  | 139 | } | 
|  | 140 |  | 
|  | 141 | auto property = interface->second.find("CHASSIS_SERIAL_NUMBER"); | 
|  | 142 | if (property == interface->second.end()) | 
|  | 143 | { | 
|  | 144 | continue; | 
|  | 145 | } | 
|  | 146 |  | 
|  | 147 | try | 
|  | 148 | { | 
|  | 149 | Value variant = property->second; | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 150 | std::string& result = std::get<std::string>(variant); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 151 | if (result.size() > maxFRUStringLength) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 152 | { | 
|  | 153 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 154 | "FRU serial number exceed maximum length"); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 155 | return -1; | 
|  | 156 | } | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 157 | serial = result; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 158 | return 0; | 
|  | 159 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 160 | catch (const std::bad_variant_access& e) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 161 | { | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 162 | phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 163 | return -1; | 
|  | 164 | } | 
|  | 165 | } | 
|  | 166 | return -1; | 
|  | 167 | } | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 168 |  | 
| Ankita Vilas Gawade | a165038 | 2022-01-08 10:30:40 +0000 | [diff] [blame^] | 169 | namespace mailbox | 
|  | 170 | { | 
|  | 171 | static uint8_t bus = 4; | 
|  | 172 | static std::string i2cBus = "/dev/i2c-" + std::to_string(bus); | 
|  | 173 | static uint8_t slaveAddr = 56; | 
|  | 174 | static constexpr auto systemRoot = "/xyz/openbmc_project/inventory/system"; | 
|  | 175 | static constexpr auto sessionIntf = "xyz.openbmc_project.Configuration.PFR"; | 
|  | 176 | const std::string match = "Baseboard/PFR"; | 
|  | 177 | static bool i2cConfigLoaded = false; | 
|  | 178 | // Command register for UFM provisioning/access commands; read/write allowed | 
|  | 179 | // from CPU/BMC. | 
|  | 180 | static const constexpr uint8_t provisioningCommand = 0x0b; | 
|  | 181 | // Trigger register for the command set in the previous offset. | 
|  | 182 | static const constexpr uint8_t triggerCommand = 0x0c; | 
|  | 183 | // Set 0x0c to 0x05 to execute command specified at “UFM/Provisioning Command” | 
|  | 184 | // register | 
|  | 185 | static const constexpr uint8_t flushRead = 0x05; | 
|  | 186 | // FIFO read registers | 
|  | 187 | std::set<uint8_t> readFifoReg = {0x08, 0x0C, 0x0D, 0x13}; | 
|  | 188 |  | 
|  | 189 | // UFM Read FIFO | 
|  | 190 | static const constexpr uint8_t readFifo = 0x0e; | 
|  | 191 |  | 
|  | 192 | enum registerType : uint8_t | 
|  | 193 | { | 
|  | 194 | singleByteRegister = 0, | 
|  | 195 | fifoReadRegister, | 
|  | 196 |  | 
|  | 197 | }; | 
|  | 198 |  | 
|  | 199 | void loadPfrConfig(ipmi::Context::ptr& ctx, bool& i2cConfigLoaded) | 
|  | 200 | { | 
|  | 201 | ipmi::ObjectTree objectTree; | 
|  | 202 |  | 
|  | 203 | boost::system::error_code ec = ipmi::getAllDbusObjects( | 
|  | 204 | ctx, systemRoot, sessionIntf, match, objectTree); | 
|  | 205 |  | 
|  | 206 | if (ec) | 
|  | 207 | { | 
|  | 208 |  | 
|  | 209 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 210 | "Failed to fetch PFR object from dbus", | 
|  | 211 | phosphor::logging::entry("INTERFACE=%s", sessionIntf), | 
|  | 212 | phosphor::logging::entry("ERROR=%s", ec.message().c_str())); | 
|  | 213 |  | 
|  | 214 | return; | 
|  | 215 | } | 
|  | 216 |  | 
|  | 217 | for (auto& softObject : objectTree) | 
|  | 218 | { | 
|  | 219 | const std::string& objPath = softObject.first; | 
|  | 220 | const std::string& serviceName = softObject.second.begin()->first; | 
|  | 221 | // PFR object found.. check for PFR support | 
|  | 222 | ipmi::PropertyMap result; | 
|  | 223 |  | 
|  | 224 | ec = ipmi::getAllDbusProperties(ctx, serviceName, objPath, sessionIntf, | 
|  | 225 | result); | 
|  | 226 |  | 
|  | 227 | if (ec) | 
|  | 228 | { | 
|  | 229 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 230 | "Failed to fetch pfr properties", | 
|  | 231 | phosphor::logging::entry("ERROR=%s", ec.message().c_str())); | 
|  | 232 | return; | 
|  | 233 | } | 
|  | 234 |  | 
|  | 235 | const uint64_t* i2cBusNum = nullptr; | 
|  | 236 | const uint64_t* address = nullptr; | 
|  | 237 |  | 
|  | 238 | for (const auto& [propName, propVariant] : result) | 
|  | 239 | { | 
|  | 240 |  | 
|  | 241 | if (propName == "Address") | 
|  | 242 | { | 
|  | 243 | address = std::get_if<uint64_t>(&propVariant); | 
|  | 244 | } | 
|  | 245 | else if (propName == "Bus") | 
|  | 246 | { | 
|  | 247 | i2cBusNum = std::get_if<uint64_t>(&propVariant); | 
|  | 248 | } | 
|  | 249 | } | 
|  | 250 |  | 
|  | 251 | if ((address == nullptr) || (i2cBusNum == nullptr)) | 
|  | 252 | { | 
|  | 253 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 254 | "Unable to read the pfr properties"); | 
|  | 255 | return; | 
|  | 256 | } | 
|  | 257 |  | 
|  | 258 | bus = static_cast<int>(*i2cBusNum); | 
|  | 259 | i2cBus = "/dev/i2c-" + std::to_string(bus); | 
|  | 260 | slaveAddr = static_cast<int>(*address); | 
|  | 261 |  | 
|  | 262 | i2cConfigLoaded = true; | 
|  | 263 | } | 
|  | 264 | } | 
|  | 265 |  | 
|  | 266 | void writefifo(const uint8_t cmdReg, const uint8_t val) | 
|  | 267 | { | 
|  | 268 | // Based on the spec, writing cmdReg to address val on this device, will | 
|  | 269 | // trigger the write FIFO operation. | 
|  | 270 | std::vector<uint8_t> writeData = {cmdReg, val}; | 
|  | 271 | std::vector<uint8_t> readBuf(0); | 
|  | 272 | ipmi::Cc retI2C = ipmi::i2cWriteRead(i2cBus, slaveAddr, writeData, readBuf); | 
|  | 273 | } | 
|  | 274 |  | 
|  | 275 | } // namespace mailbox | 
|  | 276 |  | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 277 | // Returns the Chassis Identifier (serial #) | 
|  | 278 | ipmi_ret_t ipmiOEMGetChassisIdentifier(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 279 | ipmi_request_t request, | 
|  | 280 | ipmi_response_t response, | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 281 | ipmi_data_len_t dataLen, | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 282 | ipmi_context_t context) | 
|  | 283 | { | 
|  | 284 | std::string serial; | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 285 | if (*dataLen != 0) // invalid request if there are extra parameters | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 286 | { | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 287 | *dataLen = 0; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 288 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 289 | } | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 290 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 291 | if (getChassisSerialNumber(*dbus, serial) == 0) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 292 | { | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 293 | *dataLen = serial.size(); // length will never exceed response length | 
|  | 294 | // as it is checked in getChassisSerialNumber | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 295 | char* resp = static_cast<char*>(response); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 296 | serial.copy(resp, *dataLen); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 297 | return IPMI_CC_OK; | 
|  | 298 | } | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 299 | *dataLen = 0; | 
|  | 300 | return IPMI_CC_RESPONSE_ERROR; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 301 | } | 
|  | 302 |  | 
|  | 303 | ipmi_ret_t ipmiOEMSetSystemGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 304 | ipmi_request_t request, | 
|  | 305 | ipmi_response_t response, | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 306 | ipmi_data_len_t dataLen, ipmi_context_t context) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 307 | { | 
|  | 308 | static constexpr size_t safeBufferLength = 50; | 
|  | 309 | char buf[safeBufferLength] = {0}; | 
|  | 310 | GUIDData* Data = reinterpret_cast<GUIDData*>(request); | 
|  | 311 |  | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 312 | if (*dataLen != sizeof(GUIDData)) // 16bytes | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 313 | { | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 314 | *dataLen = 0; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 315 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 316 | } | 
|  | 317 |  | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 318 | *dataLen = 0; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 319 |  | 
|  | 320 | snprintf( | 
|  | 321 | buf, safeBufferLength, | 
|  | 322 | "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x", | 
|  | 323 | Data->timeLow4, Data->timeLow3, Data->timeLow2, Data->timeLow1, | 
|  | 324 | Data->timeMid2, Data->timeMid1, Data->timeHigh2, Data->timeHigh1, | 
|  | 325 | Data->clock2, Data->clock1, Data->node6, Data->node5, Data->node4, | 
|  | 326 | Data->node3, Data->node2, Data->node1); | 
|  | 327 | // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223 | 
|  | 328 | std::string guid = buf; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 329 |  | 
|  | 330 | std::string objpath = "/xyz/openbmc_project/control/host0/systemGUID"; | 
|  | 331 | std::string intf = "xyz.openbmc_project.Common.UUID"; | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 332 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 333 | std::string service = getService(*dbus, intf, objpath); | 
|  | 334 | setDbusProperty(*dbus, service, objpath, intf, "UUID", guid); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 335 | return IPMI_CC_OK; | 
|  | 336 | } | 
|  | 337 |  | 
| Jason M. Bills | b02bf09 | 2019-08-15 13:01:56 -0700 | [diff] [blame] | 338 | ipmi::RspType<> ipmiOEMDisableBMCSystemReset(bool disableResetOnSMI, | 
|  | 339 | uint7_t reserved1) | 
|  | 340 | { | 
| Jayaprakash Mutyala | 0a652fa | 2021-07-01 17:09:39 +0000 | [diff] [blame] | 341 | if (reserved1) | 
|  | 342 | { | 
|  | 343 | return ipmi::responseInvalidFieldRequest(); | 
|  | 344 | } | 
|  | 345 |  | 
| Jason M. Bills | b02bf09 | 2019-08-15 13:01:56 -0700 | [diff] [blame] | 346 | std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); | 
|  | 347 |  | 
|  | 348 | try | 
|  | 349 | { | 
|  | 350 | auto service = | 
|  | 351 | ipmi::getService(*busp, bmcResetDisablesIntf, bmcResetDisablesPath); | 
|  | 352 | ipmi::setDbusProperty(*busp, service, bmcResetDisablesPath, | 
|  | 353 | bmcResetDisablesIntf, "ResetOnSMI", | 
|  | 354 | !disableResetOnSMI); | 
|  | 355 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 356 | catch (const std::exception& e) | 
| Jason M. Bills | b02bf09 | 2019-08-15 13:01:56 -0700 | [diff] [blame] | 357 | { | 
|  | 358 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 359 | "Failed to set BMC reset disables", | 
|  | 360 | phosphor::logging::entry("EXCEPTION=%s", e.what())); | 
|  | 361 | return ipmi::responseUnspecifiedError(); | 
|  | 362 | } | 
|  | 363 |  | 
|  | 364 | return ipmi::responseSuccess(); | 
|  | 365 | } | 
|  | 366 |  | 
|  | 367 | ipmi::RspType<bool,   // disableResetOnSMI | 
|  | 368 | uint7_t // reserved | 
|  | 369 | > | 
|  | 370 | ipmiOEMGetBMCResetDisables() | 
|  | 371 | { | 
|  | 372 | bool disableResetOnSMI = true; | 
|  | 373 |  | 
|  | 374 | std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); | 
|  | 375 | try | 
|  | 376 | { | 
|  | 377 | auto service = | 
|  | 378 | ipmi::getService(*busp, bmcResetDisablesIntf, bmcResetDisablesPath); | 
|  | 379 | Value variant = | 
|  | 380 | ipmi::getDbusProperty(*busp, service, bmcResetDisablesPath, | 
|  | 381 | bmcResetDisablesIntf, "ResetOnSMI"); | 
|  | 382 | disableResetOnSMI = !std::get<bool>(variant); | 
|  | 383 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 384 | catch (const std::exception& e) | 
| Jason M. Bills | b02bf09 | 2019-08-15 13:01:56 -0700 | [diff] [blame] | 385 | { | 
|  | 386 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 387 | "Failed to get BMC reset disables", | 
|  | 388 | phosphor::logging::entry("EXCEPTION=%s", e.what())); | 
|  | 389 | return ipmi::responseUnspecifiedError(); | 
|  | 390 | } | 
|  | 391 |  | 
|  | 392 | return ipmi::responseSuccess(disableResetOnSMI, 0); | 
|  | 393 | } | 
|  | 394 |  | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 395 | ipmi_ret_t ipmiOEMSetBIOSID(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 396 | ipmi_request_t request, ipmi_response_t response, | 
|  | 397 | ipmi_data_len_t dataLen, ipmi_context_t context) | 
|  | 398 | { | 
|  | 399 | DeviceInfo* data = reinterpret_cast<DeviceInfo*>(request); | 
|  | 400 |  | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 401 | if ((*dataLen < 2) || (*dataLen != (1 + data->biosIDLength))) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 402 | { | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 403 | *dataLen = 0; | 
|  | 404 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 405 | } | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 406 | std::string idString((char*)data->biosId, data->biosIDLength); | 
| Chalapathi Venkataramashetty | fb9f1aa | 2021-05-07 08:37:07 +0000 | [diff] [blame] | 407 | for (auto idChar : idString) | 
|  | 408 | { | 
|  | 409 | if (!std::isprint(static_cast<unsigned char>(idChar))) | 
|  | 410 | { | 
|  | 411 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 412 | "BIOS ID contains non printable character"); | 
|  | 413 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 414 | } | 
|  | 415 | } | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 416 |  | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 417 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Chalapathi | 899bfd1 | 2020-04-15 15:07:02 +0000 | [diff] [blame] | 418 | std::string service = getService(*dbus, biosVersionIntf, biosActiveObjPath); | 
|  | 419 | setDbusProperty(*dbus, service, biosActiveObjPath, biosVersionIntf, | 
| Yong Li | 2742b85 | 2019-12-16 14:55:11 +0800 | [diff] [blame] | 420 | biosVersionProp, idString); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 421 | uint8_t* bytesWritten = static_cast<uint8_t*>(response); | 
|  | 422 | *bytesWritten = | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 423 | data->biosIDLength; // how many bytes are written into storage | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 424 | *dataLen = 1; | 
|  | 425 | return IPMI_CC_OK; | 
|  | 426 | } | 
|  | 427 |  | 
| Jayaprakash Mutyala | 90da3d9 | 2021-11-18 22:01:22 +0000 | [diff] [blame] | 428 | bool getActiveHSCSoftwareVersionInfo(std::string& hscVersion, size_t hscNumber) | 
|  | 429 | { | 
|  | 430 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 431 | try | 
|  | 432 | { | 
|  | 433 | std::string hsbpObjPath = | 
|  | 434 | "/xyz/openbmc_project/software/HSBP_" + std::to_string(hscNumber); | 
|  | 435 | auto service = getService(*dbus, biosVersionIntf, hsbpObjPath); | 
|  | 436 | Value hscVersionValue = | 
|  | 437 | getDbusProperty(*dbus, "xyz.openbmc_project.HsbpManager", | 
|  | 438 | hsbpObjPath, biosVersionIntf, "Version"); | 
|  | 439 | hscVersion = std::get<std::string>(hscVersionValue); | 
|  | 440 | } | 
|  | 441 | catch (const sdbusplus::exception::exception& e) | 
|  | 442 | { | 
|  | 443 | phosphor::logging::log<phosphor::logging::level::INFO>( | 
|  | 444 | "Failed to retrieve HSBP version information", | 
|  | 445 | phosphor::logging::entry("HSBP Number=%d", hscNumber)); | 
|  | 446 | return false; | 
|  | 447 | } | 
|  | 448 | return true; | 
|  | 449 | } | 
|  | 450 |  | 
|  | 451 | bool getHscVerInfo(ipmi::Context::ptr ctx, uint8_t& hsc0Major, | 
|  | 452 | uint8_t& hsc0Minor, uint8_t& hsc1Major, uint8_t& hsc1Minor, | 
|  | 453 | uint8_t& hsc2Major, uint8_t& hsc2Minor) | 
|  | 454 | { | 
|  | 455 | std::string hscVersion; | 
|  | 456 | std::array<uint8_t, 6> hscVersions{0}; | 
|  | 457 |  | 
|  | 458 | for (size_t hscNumber = 1; hscNumber <= 3; hscNumber++) | 
|  | 459 | { | 
|  | 460 | if (!getActiveHSCSoftwareVersionInfo(hscVersion, hscNumber)) | 
|  | 461 | { | 
|  | 462 | continue; | 
|  | 463 | } | 
|  | 464 | std::regex pattern1("(\\d+?).(\\d+?).(\\d+?)"); | 
|  | 465 | constexpr size_t matchedPhosphor = 4; | 
|  | 466 | std::smatch results; | 
|  | 467 | // hscVersion = BOOT_VER.FPGA_VER.SECURITY_REVISION (Example: 00.02.01) | 
|  | 468 | if (std::regex_match(hscVersion, results, pattern1)) | 
|  | 469 | { | 
|  | 470 | // Major version is FPGA_VER and Minor version is SECURITY_REV | 
|  | 471 | if (results.size() == matchedPhosphor) | 
|  | 472 | { | 
|  | 473 | int index = (hscNumber - 1) * 2; | 
|  | 474 | hscVersions[index] = | 
|  | 475 | static_cast<uint8_t>(std::stoi(results[2])); | 
|  | 476 | hscVersions[index + 1] = | 
|  | 477 | static_cast<uint8_t>(std::stoi(results[3])); | 
|  | 478 | } | 
|  | 479 | } | 
|  | 480 | } | 
|  | 481 | hsc0Major = hscVersions[0]; | 
|  | 482 | hsc0Minor = hscVersions[1]; | 
|  | 483 | hsc1Major = hscVersions[2]; | 
|  | 484 | hsc1Minor = hscVersions[3]; | 
|  | 485 | hsc2Major = hscVersions[4]; | 
|  | 486 | hsc2Minor = hscVersions[5]; | 
|  | 487 | return true; | 
|  | 488 | } | 
|  | 489 |  | 
| AppaRao Puli | e99e7ed | 2020-01-17 12:27:10 +0530 | [diff] [blame] | 490 | bool getSwVerInfo(ipmi::Context::ptr ctx, uint8_t& bmcMajor, uint8_t& bmcMinor, | 
|  | 491 | uint8_t& meMajor, uint8_t& meMinor) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 492 | { | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 493 | // step 1 : get BMC Major and Minor numbers from its DBUS property | 
| AppaRao Puli | e99e7ed | 2020-01-17 12:27:10 +0530 | [diff] [blame] | 494 | std::string bmcVersion; | 
|  | 495 | if (getActiveSoftwareVersionInfo(ctx, versionPurposeBMC, bmcVersion)) | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 496 | { | 
|  | 497 | return false; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 498 | } | 
|  | 499 |  | 
| AppaRao Puli | e99e7ed | 2020-01-17 12:27:10 +0530 | [diff] [blame] | 500 | std::optional<MetaRevision> rev = convertIntelVersion(bmcVersion); | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 501 | if (rev.has_value()) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 502 | { | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 503 | MetaRevision revision = rev.value(); | 
|  | 504 | bmcMajor = revision.major; | 
|  | 505 |  | 
|  | 506 | revision.minor = (revision.minor > 99 ? 99 : revision.minor); | 
|  | 507 | bmcMinor = revision.minor % 10 + (revision.minor / 10) * 16; | 
|  | 508 | } | 
|  | 509 |  | 
|  | 510 | // step 2 : get ME Major and Minor numbers from its DBUS property | 
| AppaRao Puli | 32825a2 | 2020-01-17 15:52:41 +0530 | [diff] [blame] | 511 | std::string meVersion; | 
|  | 512 | if (getActiveSoftwareVersionInfo(ctx, versionPurposeME, meVersion)) | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 513 | { | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 514 | return false; | 
|  | 515 | } | 
| AppaRao Puli | 32825a2 | 2020-01-17 15:52:41 +0530 | [diff] [blame] | 516 | std::regex pattern1("(\\d+?).(\\d+?).(\\d+?).(\\d+?).(\\d+?)"); | 
|  | 517 | constexpr size_t matchedPhosphor = 6; | 
|  | 518 | std::smatch results; | 
|  | 519 | if (std::regex_match(meVersion, results, pattern1)) | 
|  | 520 | { | 
|  | 521 | if (results.size() == matchedPhosphor) | 
|  | 522 | { | 
|  | 523 | meMajor = static_cast<uint8_t>(std::stoi(results[1])); | 
| Jayaprakash Mutyala | d065702 | 2021-08-26 21:18:08 +0000 | [diff] [blame] | 524 | meMinor = static_cast<uint8_t>(std::stoi(results[2]) << 4 | | 
|  | 525 | std::stoi(results[3])); | 
| AppaRao Puli | 32825a2 | 2020-01-17 15:52:41 +0530 | [diff] [blame] | 526 | } | 
|  | 527 | } | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 528 | return true; | 
|  | 529 | } | 
|  | 530 |  | 
|  | 531 | ipmi::RspType< | 
|  | 532 | std::variant<std::string, | 
|  | 533 | std::tuple<uint8_t, std::array<uint8_t, 2>, | 
|  | 534 | std::array<uint8_t, 2>, std::array<uint8_t, 2>, | 
|  | 535 | std::array<uint8_t, 2>, std::array<uint8_t, 2>>, | 
|  | 536 | std::tuple<uint8_t, std::array<uint8_t, 2>>>> | 
| AppaRao Puli | e99e7ed | 2020-01-17 12:27:10 +0530 | [diff] [blame] | 537 | ipmiOEMGetDeviceInfo(ipmi::Context::ptr ctx, uint8_t entityType, | 
|  | 538 | std::optional<uint8_t> countToRead, | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 539 | std::optional<uint8_t> offset) | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 540 | { | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 541 | if (entityType > static_cast<uint8_t>(OEMDevEntityType::sdrVer)) | 
|  | 542 | { | 
|  | 543 | return ipmi::responseInvalidFieldRequest(); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 544 | } | 
|  | 545 |  | 
|  | 546 | // handle OEM command items | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 547 | switch (OEMDevEntityType(entityType)) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 548 | { | 
|  | 549 | case OEMDevEntityType::biosId: | 
|  | 550 | { | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 551 | // Byte 2&3, Only used with selecting BIOS | 
|  | 552 | if (!countToRead || !offset) | 
|  | 553 | { | 
|  | 554 | return ipmi::responseReqDataLenInvalid(); | 
|  | 555 | } | 
|  | 556 |  | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 557 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Yong Li | 2742b85 | 2019-12-16 14:55:11 +0800 | [diff] [blame] | 558 | std::string service = | 
| Chalapathi | 899bfd1 | 2020-04-15 15:07:02 +0000 | [diff] [blame] | 559 | getService(*dbus, biosVersionIntf, biosActiveObjPath); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 560 | try | 
|  | 561 | { | 
| Yong Li | 2742b85 | 2019-12-16 14:55:11 +0800 | [diff] [blame] | 562 | Value variant = | 
| Chalapathi | 899bfd1 | 2020-04-15 15:07:02 +0000 | [diff] [blame] | 563 | getDbusProperty(*dbus, service, biosActiveObjPath, | 
| Yong Li | 2742b85 | 2019-12-16 14:55:11 +0800 | [diff] [blame] | 564 | biosVersionIntf, biosVersionProp); | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 565 | std::string& idString = std::get<std::string>(variant); | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 566 | if (*offset >= idString.size()) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 567 | { | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 568 | return ipmi::responseParmOutOfRange(); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 569 | } | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 570 | size_t length = 0; | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 571 | if (*countToRead > (idString.size() - *offset)) | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 572 | { | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 573 | length = idString.size() - *offset; | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 574 | } | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 575 | else | 
|  | 576 | { | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 577 | length = *countToRead; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 578 | } | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 579 |  | 
|  | 580 | std::string readBuf = {0}; | 
|  | 581 | readBuf.resize(length); | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 582 | std::copy_n(idString.begin() + *offset, length, | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 583 | (readBuf.begin())); | 
|  | 584 | return ipmi::responseSuccess(readBuf); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 585 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 586 | catch (const std::bad_variant_access& e) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 587 | { | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 588 | return ipmi::responseUnspecifiedError(); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 589 | } | 
|  | 590 | } | 
|  | 591 | break; | 
|  | 592 |  | 
|  | 593 | case OEMDevEntityType::devVer: | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 594 | { | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 595 | // Byte 2&3, Only used with selecting BIOS | 
|  | 596 | if (countToRead || offset) | 
|  | 597 | { | 
|  | 598 | return ipmi::responseReqDataLenInvalid(); | 
|  | 599 | } | 
|  | 600 |  | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 601 | constexpr const size_t verLen = 2; | 
|  | 602 | constexpr const size_t verTotalLen = 10; | 
|  | 603 | std::array<uint8_t, verLen> bmcBuf = {0xff, 0xff}; | 
|  | 604 | std::array<uint8_t, verLen> hsc0Buf = {0xff, 0xff}; | 
|  | 605 | std::array<uint8_t, verLen> hsc1Buf = {0xff, 0xff}; | 
|  | 606 | std::array<uint8_t, verLen> meBuf = {0xff, 0xff}; | 
|  | 607 | std::array<uint8_t, verLen> hsc2Buf = {0xff, 0xff}; | 
|  | 608 | // data0/1: BMC version number; data6/7: ME version number | 
| AppaRao Puli | e99e7ed | 2020-01-17 12:27:10 +0530 | [diff] [blame] | 609 | if (!getSwVerInfo(ctx, bmcBuf[0], bmcBuf[1], meBuf[0], meBuf[1])) | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 610 | { | 
|  | 611 | return ipmi::responseUnspecifiedError(); | 
|  | 612 | } | 
| Jayaprakash Mutyala | 90da3d9 | 2021-11-18 22:01:22 +0000 | [diff] [blame] | 613 | if (!getHscVerInfo(ctx, hsc0Buf[0], hsc0Buf[1], hsc1Buf[0], | 
|  | 614 | hsc1Buf[1], hsc2Buf[0], hsc2Buf[1])) | 
|  | 615 | { | 
|  | 616 | return ipmi::responseUnspecifiedError(); | 
|  | 617 | } | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 618 | return ipmi::responseSuccess( | 
|  | 619 | std::tuple< | 
|  | 620 | uint8_t, std::array<uint8_t, verLen>, | 
|  | 621 | std::array<uint8_t, verLen>, std::array<uint8_t, verLen>, | 
|  | 622 | std::array<uint8_t, verLen>, std::array<uint8_t, verLen>>{ | 
|  | 623 | verTotalLen, bmcBuf, hsc0Buf, hsc1Buf, meBuf, hsc2Buf}); | 
|  | 624 | } | 
|  | 625 | break; | 
|  | 626 |  | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 627 | case OEMDevEntityType::sdrVer: | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 628 | { | 
| AppaRao Puli | d46cb42 | 2020-01-21 18:40:21 +0530 | [diff] [blame] | 629 | // Byte 2&3, Only used with selecting BIOS | 
|  | 630 | if (countToRead || offset) | 
|  | 631 | { | 
|  | 632 | return ipmi::responseReqDataLenInvalid(); | 
|  | 633 | } | 
|  | 634 |  | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 635 | constexpr const size_t sdrLen = 2; | 
|  | 636 | std::array<uint8_t, sdrLen> readBuf = {0x01, 0x0}; | 
|  | 637 | return ipmi::responseSuccess( | 
|  | 638 | std::tuple<uint8_t, std::array<uint8_t, sdrLen>>{sdrLen, | 
|  | 639 | readBuf}); | 
|  | 640 | } | 
|  | 641 | break; | 
|  | 642 |  | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 643 | default: | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 644 | return ipmi::responseInvalidFieldRequest(); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 645 | } | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 646 | } | 
|  | 647 |  | 
|  | 648 | ipmi_ret_t ipmiOEMGetAICFRU(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 649 | ipmi_request_t request, ipmi_response_t response, | 
|  | 650 | ipmi_data_len_t dataLen, ipmi_context_t context) | 
|  | 651 | { | 
|  | 652 | if (*dataLen != 0) | 
|  | 653 | { | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 654 | *dataLen = 0; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 655 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 656 | } | 
|  | 657 |  | 
|  | 658 | *dataLen = 1; | 
|  | 659 | uint8_t* res = reinterpret_cast<uint8_t*>(response); | 
|  | 660 | // temporary fix. We don't support AIC FRU now. Just tell BIOS that no | 
|  | 661 | // AIC is available so that BIOS will not timeout repeatly which leads to | 
|  | 662 | // slow booting. | 
|  | 663 | *res = 0; // Byte1=Count of SlotPosition/FruID records. | 
|  | 664 | return IPMI_CC_OK; | 
|  | 665 | } | 
|  | 666 |  | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 667 | ipmi_ret_t ipmiOEMGetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 668 | ipmi_request_t request, | 
|  | 669 | ipmi_response_t response, | 
|  | 670 | ipmi_data_len_t dataLen, | 
|  | 671 | ipmi_context_t context) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 672 | { | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 673 | GetPowerRestoreDelayRes* resp = | 
|  | 674 | reinterpret_cast<GetPowerRestoreDelayRes*>(response); | 
|  | 675 |  | 
|  | 676 | if (*dataLen != 0) | 
|  | 677 | { | 
|  | 678 | *dataLen = 0; | 
|  | 679 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 680 | } | 
|  | 681 |  | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 682 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 683 | std::string service = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 684 | getService(*dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 685 | Value variant = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 686 | getDbusProperty(*dbus, service, powerRestoreDelayObjPath, | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 687 | powerRestoreDelayIntf, powerRestoreDelayProp); | 
|  | 688 |  | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 689 | uint16_t delay = std::get<uint16_t>(variant); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 690 | resp->byteLSB = delay; | 
|  | 691 | resp->byteMSB = delay >> 8; | 
|  | 692 |  | 
|  | 693 | *dataLen = sizeof(GetPowerRestoreDelayRes); | 
|  | 694 |  | 
|  | 695 | return IPMI_CC_OK; | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 696 | } | 
|  | 697 |  | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 698 | static uint8_t bcdToDec(uint8_t val) | 
|  | 699 | { | 
|  | 700 | return ((val / 16 * 10) + (val % 16)); | 
|  | 701 | } | 
|  | 702 |  | 
|  | 703 | // Allows an update utility or system BIOS to send the status of an embedded | 
|  | 704 | // firmware update attempt to the BMC. After received, BMC will create a logging | 
|  | 705 | // record. | 
|  | 706 | ipmi::RspType<> ipmiOEMSendEmbeddedFwUpdStatus(uint8_t status, uint8_t target, | 
|  | 707 | uint8_t majorRevision, | 
|  | 708 | uint8_t minorRevision, | 
|  | 709 | uint32_t auxInfo) | 
|  | 710 | { | 
|  | 711 | std::string firmware; | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 712 | int instance = (target & targetInstanceMask) >> targetInstanceShift; | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 713 | target = (target & selEvtTargetMask) >> selEvtTargetShift; | 
|  | 714 |  | 
|  | 715 | /* make sure the status is 0, 1, or 2 as per the spec */ | 
|  | 716 | if (status > 2) | 
|  | 717 | { | 
|  | 718 | return ipmi::response(ipmi::ccInvalidFieldRequest); | 
|  | 719 | } | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 720 | /* make sure the target is 0, 1, 2, or 4 as per the spec */ | 
|  | 721 | if (target > 4 || target == 3) | 
|  | 722 | { | 
|  | 723 | return ipmi::response(ipmi::ccInvalidFieldRequest); | 
|  | 724 | } | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 725 | /*orignal OEM command is to record OEM SEL. | 
|  | 726 | But openbmc does not support OEM SEL, so we redirect it to redfish event | 
|  | 727 | logging. */ | 
|  | 728 | std::string buildInfo; | 
|  | 729 | std::string action; | 
|  | 730 | switch (FWUpdateTarget(target)) | 
|  | 731 | { | 
|  | 732 | case FWUpdateTarget::targetBMC: | 
|  | 733 | firmware = "BMC"; | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 734 | buildInfo = "major: " + std::to_string(majorRevision) + " minor: " + | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 735 | std::to_string(bcdToDec(minorRevision)) + // BCD encoded | 
|  | 736 | " BuildID: " + std::to_string(auxInfo); | 
|  | 737 | buildInfo += std::to_string(auxInfo); | 
|  | 738 | break; | 
|  | 739 | case FWUpdateTarget::targetBIOS: | 
|  | 740 | firmware = "BIOS"; | 
|  | 741 | buildInfo = | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 742 | "major: " + | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 743 | std::to_string(bcdToDec(majorRevision)) + // BCD encoded | 
|  | 744 | " minor: " + | 
|  | 745 | std::to_string(bcdToDec(minorRevision)) + // BCD encoded | 
|  | 746 | " ReleaseNumber: " +                      // ASCII encoded | 
|  | 747 | std::to_string(static_cast<uint8_t>(auxInfo >> 0) - '0') + | 
|  | 748 | std::to_string(static_cast<uint8_t>(auxInfo >> 8) - '0') + | 
|  | 749 | std::to_string(static_cast<uint8_t>(auxInfo >> 16) - '0') + | 
|  | 750 | std::to_string(static_cast<uint8_t>(auxInfo >> 24) - '0'); | 
|  | 751 | break; | 
|  | 752 | case FWUpdateTarget::targetME: | 
|  | 753 | firmware = "ME"; | 
|  | 754 | buildInfo = | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 755 | "major: " + std::to_string(majorRevision) + " minor1: " + | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 756 | std::to_string(bcdToDec(minorRevision)) + // BCD encoded | 
|  | 757 | " minor2: " + | 
|  | 758 | std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 0))) + | 
|  | 759 | " build1: " + | 
|  | 760 | std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 8))) + | 
|  | 761 | " build2: " + | 
|  | 762 | std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 16))); | 
|  | 763 | break; | 
|  | 764 | case FWUpdateTarget::targetOEMEWS: | 
|  | 765 | firmware = "EWS"; | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 766 | buildInfo = "major: " + std::to_string(majorRevision) + " minor: " + | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 767 | std::to_string(bcdToDec(minorRevision)) + // BCD encoded | 
|  | 768 | " BuildID: " + std::to_string(auxInfo); | 
|  | 769 | break; | 
|  | 770 | } | 
|  | 771 |  | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 772 | static const std::string openBMCMessageRegistryVersion("0.1"); | 
|  | 773 | std::string redfishMsgID = "OpenBMC." + openBMCMessageRegistryVersion; | 
|  | 774 |  | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 775 | switch (status) | 
|  | 776 | { | 
|  | 777 | case 0x0: | 
|  | 778 | action = "update started"; | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 779 | redfishMsgID += ".FirmwareUpdateStarted"; | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 780 | break; | 
|  | 781 | case 0x1: | 
|  | 782 | action = "update completed successfully"; | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 783 | redfishMsgID += ".FirmwareUpdateCompleted"; | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 784 | break; | 
|  | 785 | case 0x2: | 
|  | 786 | action = "update failure"; | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 787 | redfishMsgID += ".FirmwareUpdateFailed"; | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 788 | break; | 
|  | 789 | default: | 
|  | 790 | action = "unknown"; | 
|  | 791 | break; | 
|  | 792 | } | 
|  | 793 |  | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 794 | std::string firmwareInstanceStr = | 
|  | 795 | firmware + " instance: " + std::to_string(instance); | 
|  | 796 | std::string message("[firmware update] " + firmwareInstanceStr + | 
|  | 797 | " status: <" + action + "> " + buildInfo); | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 798 |  | 
|  | 799 | sd_journal_send("MESSAGE=%s", message.c_str(), "PRIORITY=%i", LOG_INFO, | 
| Jason M. Bills | dc24927 | 2019-04-03 09:58:40 -0700 | [diff] [blame] | 800 | "REDFISH_MESSAGE_ID=%s", redfishMsgID.c_str(), | 
|  | 801 | "REDFISH_MESSAGE_ARGS=%s,%s", firmwareInstanceStr.c_str(), | 
|  | 802 | buildInfo.c_str(), NULL); | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 803 | return ipmi::responseSuccess(); | 
|  | 804 | } | 
|  | 805 |  | 
| Rajashekar Gade Reddy | 2b664d5 | 2020-03-23 22:09:00 +0530 | [diff] [blame] | 806 | ipmi::RspType<uint8_t, std::vector<uint8_t>> | 
|  | 807 | ipmiOEMSlotIpmb(ipmi::Context::ptr ctx, uint6_t reserved1, | 
|  | 808 | uint2_t slotNumber, uint3_t baseBoardSlotNum, | 
|  | 809 | uint3_t riserSlotNum, uint2_t reserved2, uint8_t slaveAddr, | 
|  | 810 | uint8_t netFn, uint8_t cmd, | 
|  | 811 | std::optional<std::vector<uint8_t>> writeData) | 
|  | 812 | { | 
|  | 813 | if (reserved1 || reserved2) | 
|  | 814 | { | 
|  | 815 | return ipmi::responseInvalidFieldRequest(); | 
|  | 816 | } | 
|  | 817 |  | 
|  | 818 | boost::system::error_code ec; | 
|  | 819 | using ipmbResponse = std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t, | 
|  | 820 | std::vector<uint8_t>>; | 
|  | 821 | ipmbResponse res = ctx->bus->yield_method_call<ipmbResponse>( | 
|  | 822 | ctx->yield, ec, "xyz.openbmc_project.Ipmi.Channel.Ipmb", | 
|  | 823 | "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb", | 
|  | 824 | "SlotIpmbRequest", static_cast<uint8_t>(slotNumber), | 
|  | 825 | static_cast<uint8_t>(baseBoardSlotNum), slaveAddr, netFn, cmd, | 
|  | 826 | *writeData); | 
|  | 827 | if (ec) | 
|  | 828 | { | 
|  | 829 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 830 | "Failed to call dbus method SlotIpmbRequest"); | 
|  | 831 | return ipmi::responseUnspecifiedError(); | 
|  | 832 | } | 
|  | 833 |  | 
|  | 834 | std::vector<uint8_t> dataReceived(0); | 
|  | 835 | int status = -1; | 
|  | 836 | uint8_t resNetFn = 0, resLun = 0, resCmd = 0, cc = 0; | 
|  | 837 |  | 
|  | 838 | std::tie(status, resNetFn, resLun, resCmd, cc, dataReceived) = res; | 
|  | 839 |  | 
|  | 840 | if (status) | 
|  | 841 | { | 
|  | 842 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 843 | "Failed to get response from SlotIpmbRequest"); | 
|  | 844 | return ipmi::responseResponseError(); | 
|  | 845 | } | 
|  | 846 | return ipmi::responseSuccess(cc, dataReceived); | 
|  | 847 | } | 
|  | 848 |  | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 849 | ipmi_ret_t ipmiOEMSetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 850 | ipmi_request_t request, | 
|  | 851 | ipmi_response_t response, | 
|  | 852 | ipmi_data_len_t dataLen, | 
|  | 853 | ipmi_context_t context) | 
|  | 854 | { | 
|  | 855 | SetPowerRestoreDelayReq* data = | 
|  | 856 | reinterpret_cast<SetPowerRestoreDelayReq*>(request); | 
|  | 857 | uint16_t delay = 0; | 
|  | 858 |  | 
|  | 859 | if (*dataLen != sizeof(SetPowerRestoreDelayReq)) | 
|  | 860 | { | 
|  | 861 | *dataLen = 0; | 
|  | 862 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 863 | } | 
|  | 864 | delay = data->byteMSB; | 
|  | 865 | delay = (delay << 8) | data->byteLSB; | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 866 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 867 | std::string service = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 868 | getService(*dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath); | 
|  | 869 | setDbusProperty(*dbus, service, powerRestoreDelayObjPath, | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 870 | powerRestoreDelayIntf, powerRestoreDelayProp, delay); | 
|  | 871 | *dataLen = 0; | 
|  | 872 |  | 
|  | 873 | return IPMI_CC_OK; | 
|  | 874 | } | 
|  | 875 |  | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 876 | static bool cpuPresent(const std::string& cpuName) | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 877 | { | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 878 | static constexpr const char* cpuPresencePathPrefix = | 
|  | 879 | "/xyz/openbmc_project/inventory/system/chassis/motherboard/"; | 
|  | 880 | static constexpr const char* cpuPresenceIntf = | 
|  | 881 | "xyz.openbmc_project.Inventory.Item"; | 
|  | 882 | std::string cpuPresencePath = cpuPresencePathPrefix + cpuName; | 
|  | 883 | std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); | 
|  | 884 | try | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 885 | { | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 886 | auto service = | 
|  | 887 | ipmi::getService(*busp, cpuPresenceIntf, cpuPresencePath); | 
|  | 888 |  | 
|  | 889 | ipmi::Value result = ipmi::getDbusProperty( | 
|  | 890 | *busp, service, cpuPresencePath, cpuPresenceIntf, "Present"); | 
|  | 891 | return std::get<bool>(result); | 
|  | 892 | } | 
|  | 893 | catch (const std::exception& e) | 
|  | 894 | { | 
|  | 895 | phosphor::logging::log<phosphor::logging::level::INFO>( | 
|  | 896 | "Cannot find processor presence", | 
|  | 897 | phosphor::logging::entry("NAME=%s", cpuName.c_str())); | 
|  | 898 | return false; | 
|  | 899 | } | 
|  | 900 | } | 
|  | 901 |  | 
|  | 902 | ipmi::RspType<bool,    // CATERR Reset Enabled | 
|  | 903 | bool,    // ERR2 Reset Enabled | 
|  | 904 | uint6_t, // reserved | 
|  | 905 | uint8_t, // reserved, returns 0x3F | 
|  | 906 | uint6_t, // CPU1 CATERR Count | 
|  | 907 | uint2_t, // CPU1 Status | 
|  | 908 | uint6_t, // CPU2 CATERR Count | 
|  | 909 | uint2_t, // CPU2 Status | 
|  | 910 | uint6_t, // CPU3 CATERR Count | 
|  | 911 | uint2_t, // CPU3 Status | 
|  | 912 | uint6_t, // CPU4 CATERR Count | 
|  | 913 | uint2_t, // CPU4 Status | 
|  | 914 | uint8_t  // Crashdump Count | 
|  | 915 | > | 
|  | 916 | ipmiOEMGetProcessorErrConfig() | 
|  | 917 | { | 
|  | 918 | bool resetOnCATERR = false; | 
|  | 919 | bool resetOnERR2 = false; | 
|  | 920 | uint6_t cpu1CATERRCount = 0; | 
|  | 921 | uint6_t cpu2CATERRCount = 0; | 
|  | 922 | uint6_t cpu3CATERRCount = 0; | 
|  | 923 | uint6_t cpu4CATERRCount = 0; | 
|  | 924 | uint8_t crashdumpCount = 0; | 
| Jason M. Bills | 24df90f | 2021-06-15 12:46:13 -0700 | [diff] [blame] | 925 | uint2_t cpu1Status = cpuPresent("CPU_1") | 
|  | 926 | ? types::enum_cast<uint8_t>(CPUStatus::enabled) | 
|  | 927 | : types::enum_cast<uint8_t>(CPUStatus::notPresent); | 
|  | 928 | uint2_t cpu2Status = cpuPresent("CPU_2") | 
|  | 929 | ? types::enum_cast<uint8_t>(CPUStatus::enabled) | 
|  | 930 | : types::enum_cast<uint8_t>(CPUStatus::notPresent); | 
|  | 931 | uint2_t cpu3Status = cpuPresent("CPU_3") | 
|  | 932 | ? types::enum_cast<uint8_t>(CPUStatus::enabled) | 
|  | 933 | : types::enum_cast<uint8_t>(CPUStatus::notPresent); | 
|  | 934 | uint2_t cpu4Status = cpuPresent("CPU_4") | 
|  | 935 | ? types::enum_cast<uint8_t>(CPUStatus::enabled) | 
|  | 936 | : types::enum_cast<uint8_t>(CPUStatus::notPresent); | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 937 |  | 
|  | 938 | std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); | 
|  | 939 | try | 
|  | 940 | { | 
|  | 941 | auto service = ipmi::getService(*busp, processorErrConfigIntf, | 
|  | 942 | processorErrConfigObjPath); | 
|  | 943 |  | 
|  | 944 | ipmi::PropertyMap result = ipmi::getAllDbusProperties( | 
|  | 945 | *busp, service, processorErrConfigObjPath, processorErrConfigIntf); | 
|  | 946 | resetOnCATERR = std::get<bool>(result.at("ResetOnCATERR")); | 
|  | 947 | resetOnERR2 = std::get<bool>(result.at("ResetOnERR2")); | 
|  | 948 | cpu1CATERRCount = std::get<uint8_t>(result.at("ErrorCountCPU1")); | 
|  | 949 | cpu2CATERRCount = std::get<uint8_t>(result.at("ErrorCountCPU2")); | 
|  | 950 | cpu3CATERRCount = std::get<uint8_t>(result.at("ErrorCountCPU3")); | 
|  | 951 | cpu4CATERRCount = std::get<uint8_t>(result.at("ErrorCountCPU4")); | 
|  | 952 | crashdumpCount = std::get<uint8_t>(result.at("CrashdumpCount")); | 
|  | 953 | } | 
|  | 954 | catch (const std::exception& e) | 
|  | 955 | { | 
|  | 956 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 957 | "Failed to fetch processor error config", | 
|  | 958 | phosphor::logging::entry("ERROR=%s", e.what())); | 
|  | 959 | return ipmi::responseUnspecifiedError(); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 960 | } | 
|  | 961 |  | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 962 | return ipmi::responseSuccess(resetOnCATERR, resetOnERR2, 0, 0x3F, | 
|  | 963 | cpu1CATERRCount, cpu1Status, cpu2CATERRCount, | 
|  | 964 | cpu2Status, cpu3CATERRCount, cpu3Status, | 
|  | 965 | cpu4CATERRCount, cpu4Status, crashdumpCount); | 
|  | 966 | } | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 967 |  | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 968 | ipmi::RspType<> ipmiOEMSetProcessorErrConfig( | 
|  | 969 | bool resetOnCATERR, bool resetOnERR2, uint6_t reserved1, uint8_t reserved2, | 
|  | 970 | std::optional<bool> clearCPUErrorCount, | 
|  | 971 | std::optional<bool> clearCrashdumpCount, std::optional<uint6_t> reserved3) | 
|  | 972 | { | 
| Jayaprakash Mutyala | 0a652fa | 2021-07-01 17:09:39 +0000 | [diff] [blame] | 973 | if (reserved1 || reserved2) | 
|  | 974 | { | 
|  | 975 | return ipmi::responseInvalidFieldRequest(); | 
|  | 976 | } | 
|  | 977 |  | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 978 | std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus(); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 979 |  | 
|  | 980 | try | 
|  | 981 | { | 
| Jayaprakash Mutyala | 0a652fa | 2021-07-01 17:09:39 +0000 | [diff] [blame] | 982 | if (reserved3.value_or(0)) | 
|  | 983 | { | 
|  | 984 | return ipmi::responseInvalidFieldRequest(); | 
|  | 985 | } | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 986 | auto service = ipmi::getService(*busp, processorErrConfigIntf, | 
|  | 987 | processorErrConfigObjPath); | 
|  | 988 | ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, | 
|  | 989 | processorErrConfigIntf, "ResetOnCATERR", | 
|  | 990 | resetOnCATERR); | 
|  | 991 | ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, | 
|  | 992 | processorErrConfigIntf, "ResetOnERR2", | 
|  | 993 | resetOnERR2); | 
|  | 994 | if (clearCPUErrorCount.value_or(false)) | 
|  | 995 | { | 
|  | 996 | ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, | 
| Jason M. Bills | d3e1993 | 2019-08-15 12:39:03 -0700 | [diff] [blame] | 997 | processorErrConfigIntf, "ErrorCountCPU1", | 
|  | 998 | static_cast<uint8_t>(0)); | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 999 | ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, | 
| Jason M. Bills | d3e1993 | 2019-08-15 12:39:03 -0700 | [diff] [blame] | 1000 | processorErrConfigIntf, "ErrorCountCPU2", | 
|  | 1001 | static_cast<uint8_t>(0)); | 
|  | 1002 | ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, | 
|  | 1003 | processorErrConfigIntf, "ErrorCountCPU3", | 
|  | 1004 | static_cast<uint8_t>(0)); | 
|  | 1005 | ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, | 
|  | 1006 | processorErrConfigIntf, "ErrorCountCPU4", | 
|  | 1007 | static_cast<uint8_t>(0)); | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 1008 | } | 
|  | 1009 | if (clearCrashdumpCount.value_or(false)) | 
|  | 1010 | { | 
|  | 1011 | ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath, | 
| Jason M. Bills | d3e1993 | 2019-08-15 12:39:03 -0700 | [diff] [blame] | 1012 | processorErrConfigIntf, "CrashdumpCount", | 
|  | 1013 | static_cast<uint8_t>(0)); | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 1014 | } | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 1015 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1016 | catch (const std::exception& e) | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 1017 | { | 
| Kuiying Wang | bc54667 | 2018-11-23 15:41:05 +0800 | [diff] [blame] | 1018 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 1019 | "Failed to set processor error config", | 
|  | 1020 | phosphor::logging::entry("EXCEPTION=%s", e.what())); | 
|  | 1021 | return ipmi::responseUnspecifiedError(); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 1022 | } | 
|  | 1023 |  | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 1024 | return ipmi::responseSuccess(); | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 1025 | } | 
|  | 1026 |  | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1027 | ipmi_ret_t ipmiOEMGetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 1028 | ipmi_request_t request, | 
|  | 1029 | ipmi_response_t response, | 
|  | 1030 | ipmi_data_len_t dataLen, | 
|  | 1031 | ipmi_context_t context) | 
|  | 1032 | { | 
|  | 1033 | GetOEMShutdownPolicyRes* resp = | 
|  | 1034 | reinterpret_cast<GetOEMShutdownPolicyRes*>(response); | 
|  | 1035 |  | 
|  | 1036 | if (*dataLen != 0) | 
|  | 1037 | { | 
|  | 1038 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1039 | "oem_get_shutdown_policy: invalid input len!"); | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1040 | *dataLen = 0; | 
|  | 1041 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 1042 | } | 
|  | 1043 |  | 
|  | 1044 | *dataLen = 0; | 
|  | 1045 |  | 
|  | 1046 | try | 
|  | 1047 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1048 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1049 | std::string service = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1050 | getService(*dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath); | 
|  | 1051 | Value variant = getDbusProperty( | 
|  | 1052 | *dbus, service, oemShutdownPolicyObjPath, oemShutdownPolicyIntf, | 
|  | 1053 | oemShutdownPolicyObjPathProp); | 
| Yong Li | 0669d19 | 2019-05-06 14:01:46 +0800 | [diff] [blame] | 1054 |  | 
|  | 1055 | if (sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: | 
|  | 1056 | convertPolicyFromString(std::get<std::string>(variant)) == | 
|  | 1057 | sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy:: | 
|  | 1058 | NoShutdownOnOCOT) | 
|  | 1059 | { | 
|  | 1060 | resp->policy = 0; | 
|  | 1061 | } | 
|  | 1062 | else if (sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: | 
|  | 1063 | convertPolicyFromString(std::get<std::string>(variant)) == | 
|  | 1064 | sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: | 
|  | 1065 | Policy::ShutdownOnOCOT) | 
|  | 1066 | { | 
|  | 1067 | resp->policy = 1; | 
|  | 1068 | } | 
|  | 1069 | else | 
|  | 1070 | { | 
|  | 1071 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1072 | "oem_set_shutdown_policy: invalid property!", | 
|  | 1073 | phosphor::logging::entry( | 
|  | 1074 | "PROP=%s", std::get<std::string>(variant).c_str())); | 
|  | 1075 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 1076 | } | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1077 | // TODO needs to check if it is multi-node products, | 
|  | 1078 | // policy is only supported on node 3/4 | 
|  | 1079 | resp->policySupport = shutdownPolicySupported; | 
|  | 1080 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1081 | catch (const sdbusplus::exception_t& e) | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1082 | { | 
|  | 1083 | phosphor::logging::log<phosphor::logging::level::ERR>(e.description()); | 
|  | 1084 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 1085 | } | 
|  | 1086 |  | 
|  | 1087 | *dataLen = sizeof(GetOEMShutdownPolicyRes); | 
|  | 1088 | return IPMI_CC_OK; | 
|  | 1089 | } | 
|  | 1090 |  | 
|  | 1091 | ipmi_ret_t ipmiOEMSetShutdownPolicy(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 1092 | ipmi_request_t request, | 
|  | 1093 | ipmi_response_t response, | 
|  | 1094 | ipmi_data_len_t dataLen, | 
|  | 1095 | ipmi_context_t context) | 
|  | 1096 | { | 
|  | 1097 | uint8_t* req = reinterpret_cast<uint8_t*>(request); | 
| Yong Li | 0669d19 | 2019-05-06 14:01:46 +0800 | [diff] [blame] | 1098 | sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy policy = | 
|  | 1099 | sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy:: | 
|  | 1100 | NoShutdownOnOCOT; | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1101 |  | 
|  | 1102 | // TODO needs to check if it is multi-node products, | 
|  | 1103 | // policy is only supported on node 3/4 | 
|  | 1104 | if (*dataLen != 1) | 
|  | 1105 | { | 
|  | 1106 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1107 | "oem_set_shutdown_policy: invalid input len!"); | 
|  | 1108 | *dataLen = 0; | 
|  | 1109 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 1110 | } | 
|  | 1111 |  | 
|  | 1112 | *dataLen = 0; | 
|  | 1113 | if ((*req != noShutdownOnOCOT) && (*req != shutdownOnOCOT)) | 
|  | 1114 | { | 
|  | 1115 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1116 | "oem_set_shutdown_policy: invalid input!"); | 
|  | 1117 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 1118 | } | 
|  | 1119 |  | 
| Yong Li | 0669d19 | 2019-05-06 14:01:46 +0800 | [diff] [blame] | 1120 | if (*req == noShutdownOnOCOT) | 
|  | 1121 | { | 
|  | 1122 | policy = sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: | 
|  | 1123 | Policy::NoShutdownOnOCOT; | 
|  | 1124 | } | 
|  | 1125 | else | 
|  | 1126 | { | 
|  | 1127 | policy = sdbusplus::com::intel::Control::server::OCOTShutdownPolicy:: | 
|  | 1128 | Policy::ShutdownOnOCOT; | 
|  | 1129 | } | 
|  | 1130 |  | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1131 | try | 
|  | 1132 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1133 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1134 | std::string service = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1135 | getService(*dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath); | 
| Yong Li | 0669d19 | 2019-05-06 14:01:46 +0800 | [diff] [blame] | 1136 | setDbusProperty( | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1137 | *dbus, service, oemShutdownPolicyObjPath, oemShutdownPolicyIntf, | 
| Yong Li | 0669d19 | 2019-05-06 14:01:46 +0800 | [diff] [blame] | 1138 | oemShutdownPolicyObjPathProp, | 
|  | 1139 | sdbusplus::com::intel::Control::server::convertForMessage(policy)); | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1140 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1141 | catch (const sdbusplus::exception_t& e) | 
| Yong Li | 703922d | 2018-11-06 13:25:31 +0800 | [diff] [blame] | 1142 | { | 
|  | 1143 | phosphor::logging::log<phosphor::logging::level::ERR>(e.description()); | 
|  | 1144 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 1145 | } | 
|  | 1146 |  | 
|  | 1147 | return IPMI_CC_OK; | 
|  | 1148 | } | 
|  | 1149 |  | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1150 | /** @brief implementation for check the DHCP or not in IPv4 | 
|  | 1151 | *  @param[in] Channel - Channel number | 
|  | 1152 | *  @returns true or false. | 
|  | 1153 | */ | 
|  | 1154 | static bool isDHCPEnabled(uint8_t Channel) | 
|  | 1155 | { | 
|  | 1156 | try | 
|  | 1157 | { | 
|  | 1158 | auto ethdevice = getChannelName(Channel); | 
|  | 1159 | if (ethdevice.empty()) | 
|  | 1160 | { | 
|  | 1161 | return false; | 
|  | 1162 | } | 
|  | 1163 | auto ethIP = ethdevice + "/ipv4"; | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1164 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1165 | auto ethernetObj = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1166 | getDbusObject(*dbus, networkIPIntf, networkRoot, ethIP); | 
|  | 1167 | auto value = getDbusProperty(*dbus, networkService, ethernetObj.first, | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1168 | networkIPIntf, "Origin"); | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 1169 | if (std::get<std::string>(value) == | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1170 | "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") | 
|  | 1171 | { | 
|  | 1172 | return true; | 
|  | 1173 | } | 
|  | 1174 | else | 
|  | 1175 | { | 
|  | 1176 | return false; | 
|  | 1177 | } | 
|  | 1178 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1179 | catch (const sdbusplus::exception_t& e) | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1180 | { | 
|  | 1181 | phosphor::logging::log<phosphor::logging::level::ERR>(e.description()); | 
|  | 1182 | return true; | 
|  | 1183 | } | 
|  | 1184 | } | 
|  | 1185 |  | 
|  | 1186 | /** @brief implementes for check the DHCP or not in IPv6 | 
|  | 1187 | *  @param[in] Channel - Channel number | 
|  | 1188 | *  @returns true or false. | 
|  | 1189 | */ | 
|  | 1190 | static bool isDHCPIPv6Enabled(uint8_t Channel) | 
|  | 1191 | { | 
|  | 1192 |  | 
|  | 1193 | try | 
|  | 1194 | { | 
|  | 1195 | auto ethdevice = getChannelName(Channel); | 
|  | 1196 | if (ethdevice.empty()) | 
|  | 1197 | { | 
|  | 1198 | return false; | 
|  | 1199 | } | 
|  | 1200 | auto ethIP = ethdevice + "/ipv6"; | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1201 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1202 | auto objectInfo = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1203 | getDbusObject(*dbus, networkIPIntf, networkRoot, ethIP); | 
|  | 1204 | auto properties = getAllDbusProperties(*dbus, objectInfo.second, | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1205 | objectInfo.first, networkIPIntf); | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 1206 | if (std::get<std::string>(properties["Origin"]) == | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1207 | "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP") | 
|  | 1208 | { | 
|  | 1209 | return true; | 
|  | 1210 | } | 
|  | 1211 | else | 
|  | 1212 | { | 
|  | 1213 | return false; | 
|  | 1214 | } | 
|  | 1215 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1216 | catch (const sdbusplus::exception_t& e) | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1217 | { | 
|  | 1218 | phosphor::logging::log<phosphor::logging::level::ERR>(e.description()); | 
|  | 1219 | return true; | 
|  | 1220 | } | 
|  | 1221 | } | 
|  | 1222 |  | 
|  | 1223 | /** @brief implementes the creating of default new user | 
|  | 1224 | *  @param[in] userName - new username in 16 bytes. | 
|  | 1225 | *  @param[in] userPassword - new password in 20 bytes | 
|  | 1226 | *  @returns ipmi completion code. | 
|  | 1227 | */ | 
|  | 1228 | ipmi::RspType<> ipmiOEMSetUser2Activation( | 
|  | 1229 | std::array<uint8_t, ipmi::ipmiMaxUserName>& userName, | 
| Vernon Mauery | 3b3d29b | 2021-08-05 15:03:35 -0700 | [diff] [blame] | 1230 | const SecureBuffer& userPassword) | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1231 | { | 
| Vernon Mauery | 3b3d29b | 2021-08-05 15:03:35 -0700 | [diff] [blame] | 1232 | if (userPassword.size() != ipmi::maxIpmi20PasswordSize) | 
|  | 1233 | { | 
|  | 1234 | return ipmi::responseReqDataLenInvalid(); | 
|  | 1235 | } | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1236 | bool userState = false; | 
|  | 1237 | // Check for System Interface not exist and LAN should be static | 
|  | 1238 | for (uint8_t channel = 0; channel < maxIpmiChannels; channel++) | 
|  | 1239 | { | 
| Manish Baing | 440f62b | 2021-07-15 22:00:37 +0000 | [diff] [blame] | 1240 | ChannelInfo chInfo{}; | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1241 | try | 
|  | 1242 | { | 
|  | 1243 | getChannelInfo(channel, chInfo); | 
|  | 1244 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1245 | catch (const sdbusplus::exception_t& e) | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1246 | { | 
|  | 1247 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1248 | "ipmiOEMSetUser2Activation: Failed to get Channel Info", | 
|  | 1249 | phosphor::logging::entry("MSG: %s", e.description())); | 
|  | 1250 | return ipmi::response(ipmi::ccUnspecifiedError); | 
|  | 1251 | } | 
|  | 1252 | if (chInfo.mediumType == | 
|  | 1253 | static_cast<uint8_t>(EChannelMediumType::systemInterface)) | 
|  | 1254 | { | 
|  | 1255 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1256 | "ipmiOEMSetUser2Activation: system interface  exist ."); | 
|  | 1257 | return ipmi::response(ipmi::ccCommandNotAvailable); | 
|  | 1258 | } | 
|  | 1259 | else | 
|  | 1260 | { | 
|  | 1261 |  | 
|  | 1262 | if (chInfo.mediumType == | 
|  | 1263 | static_cast<uint8_t>(EChannelMediumType::lan8032)) | 
|  | 1264 | { | 
|  | 1265 | if (isDHCPIPv6Enabled(channel) || isDHCPEnabled(channel)) | 
|  | 1266 | { | 
|  | 1267 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1268 | "ipmiOEMSetUser2Activation: DHCP enabled ."); | 
|  | 1269 | return ipmi::response(ipmi::ccCommandNotAvailable); | 
|  | 1270 | } | 
|  | 1271 | } | 
|  | 1272 | } | 
|  | 1273 | } | 
|  | 1274 | uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0; | 
|  | 1275 | if (ipmi::ccSuccess == | 
|  | 1276 | ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers)) | 
|  | 1277 | { | 
|  | 1278 | if (enabledUsers > 1) | 
|  | 1279 | { | 
|  | 1280 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1281 | "ipmiOEMSetUser2Activation: more than one user is enabled."); | 
|  | 1282 | return ipmi::response(ipmi::ccCommandNotAvailable); | 
|  | 1283 | } | 
|  | 1284 | // Check the user 2 is enabled or not | 
|  | 1285 | ipmiUserCheckEnabled(ipmiDefaultUserId, userState); | 
|  | 1286 | if (userState == true) | 
|  | 1287 | { | 
|  | 1288 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1289 | "ipmiOEMSetUser2Activation: user 2 already enabled ."); | 
|  | 1290 | return ipmi::response(ipmi::ccCommandNotAvailable); | 
|  | 1291 | } | 
|  | 1292 | } | 
|  | 1293 | else | 
|  | 1294 | { | 
|  | 1295 | return ipmi::response(ipmi::ccUnspecifiedError); | 
|  | 1296 | } | 
|  | 1297 |  | 
|  | 1298 | #if BYTE_ORDER == LITTLE_ENDIAN | 
|  | 1299 | PrivAccess privAccess = {PRIVILEGE_ADMIN, true, true, true, 0}; | 
|  | 1300 | #endif | 
|  | 1301 | #if BYTE_ORDER == BIG_ENDIAN | 
|  | 1302 | PrivAccess privAccess = {0, true, true, true, PRIVILEGE_ADMIN}; | 
|  | 1303 | #endif | 
|  | 1304 |  | 
| Vernon Mauery | 037cabd | 2020-05-14 12:16:01 -0700 | [diff] [blame] | 1305 | // ipmiUserSetUserName correctly handles char*, possibly non-null | 
|  | 1306 | // terminated strings using ipmiMaxUserName size | 
| Jayaprakash Mutyala | 3fbe8d2 | 2020-10-29 14:42:59 +0000 | [diff] [blame] | 1307 | size_t nameLen = strnlen(reinterpret_cast<const char*>(userName.data()), | 
|  | 1308 | sizeof(userName)); | 
|  | 1309 | const std::string userNameRaw( | 
|  | 1310 | reinterpret_cast<const char*>(userName.data()), nameLen); | 
| jayaprakash Mutyala | 1429d4f | 2020-03-04 18:20:16 +0000 | [diff] [blame] | 1311 |  | 
| Vernon Mauery | 037cabd | 2020-05-14 12:16:01 -0700 | [diff] [blame] | 1312 | if (ipmi::ccSuccess == ipmiUserSetUserName(ipmiDefaultUserId, userNameRaw)) | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1313 | { | 
|  | 1314 | if (ipmi::ccSuccess == | 
|  | 1315 | ipmiUserSetUserPassword( | 
|  | 1316 | ipmiDefaultUserId, | 
|  | 1317 | reinterpret_cast<const char*>(userPassword.data()))) | 
|  | 1318 | { | 
|  | 1319 | if (ipmi::ccSuccess == | 
|  | 1320 | ipmiUserSetPrivilegeAccess( | 
|  | 1321 | ipmiDefaultUserId, | 
|  | 1322 | static_cast<uint8_t>(ipmi::EChannelID::chanLan1), | 
|  | 1323 | privAccess, true)) | 
|  | 1324 | { | 
|  | 1325 | phosphor::logging::log<phosphor::logging::level::INFO>( | 
|  | 1326 | "ipmiOEMSetUser2Activation: user created successfully "); | 
| Jayaprakash Mutyala | 9420416 | 2020-10-23 06:17:56 +0000 | [diff] [blame] | 1327 |  | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1328 | return ipmi::responseSuccess(); | 
|  | 1329 | } | 
|  | 1330 | } | 
|  | 1331 | // we need to delete  the default user id which added in this command as | 
|  | 1332 | // password / priv setting is failed. | 
| Jayaprakash Mutyala | 3fbe8d2 | 2020-10-29 14:42:59 +0000 | [diff] [blame] | 1333 | ipmiUserSetUserName(ipmiDefaultUserId, static_cast<std::string>("")); | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 1334 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1335 | "ipmiOEMSetUser2Activation: password / priv setting is failed."); | 
|  | 1336 | } | 
|  | 1337 | else | 
|  | 1338 | { | 
|  | 1339 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1340 | "ipmiOEMSetUser2Activation: Setting username failed."); | 
|  | 1341 | } | 
|  | 1342 |  | 
|  | 1343 | return ipmi::response(ipmi::ccCommandNotAvailable); | 
|  | 1344 | } | 
|  | 1345 |  | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1346 | /** @brief implementes executing the linux command | 
|  | 1347 | *  @param[in] linux command | 
|  | 1348 | *  @returns status | 
|  | 1349 | */ | 
|  | 1350 |  | 
|  | 1351 | static uint8_t executeCmd(const char* path) | 
|  | 1352 | { | 
|  | 1353 | boost::process::child execProg(path); | 
|  | 1354 | execProg.wait(); | 
|  | 1355 |  | 
|  | 1356 | int retCode = execProg.exit_code(); | 
|  | 1357 | if (retCode) | 
|  | 1358 | { | 
|  | 1359 | return ipmi::ccUnspecifiedError; | 
|  | 1360 | } | 
|  | 1361 | return ipmi::ccSuccess; | 
|  | 1362 | } | 
|  | 1363 |  | 
|  | 1364 | /** @brief implementes ASD Security event logging | 
|  | 1365 | *  @param[in] Event message string | 
|  | 1366 | *  @param[in] Event Severity | 
|  | 1367 | *  @returns status | 
|  | 1368 | */ | 
|  | 1369 |  | 
|  | 1370 | static void atScaleDebugEventlog(std::string msg, int severity) | 
|  | 1371 | { | 
|  | 1372 | std::string eventStr = "OpenBMC.0.1." + msg; | 
|  | 1373 | sd_journal_send("MESSAGE=Security Event: %s", eventStr.c_str(), | 
|  | 1374 | "PRIORITY=%i", severity, "REDFISH_MESSAGE_ID=%s", | 
|  | 1375 | eventStr.c_str(), NULL); | 
|  | 1376 | } | 
|  | 1377 |  | 
| Richard Marian Thomaiyar | fc5e985 | 2019-04-14 15:06:27 +0530 | [diff] [blame] | 1378 | /** @brief implementes setting password for special user | 
|  | 1379 | *  @param[in] specialUserIndex | 
|  | 1380 | *  @param[in] userPassword - new password in 20 bytes | 
|  | 1381 | *  @returns ipmi completion code. | 
|  | 1382 | */ | 
|  | 1383 | ipmi::RspType<> ipmiOEMSetSpecialUserPassword(ipmi::Context::ptr ctx, | 
|  | 1384 | uint8_t specialUserIndex, | 
|  | 1385 | std::vector<uint8_t> userPassword) | 
|  | 1386 | { | 
|  | 1387 | ChannelInfo chInfo; | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1388 | ipmi_ret_t status = ipmi::ccSuccess; | 
|  | 1389 |  | 
| Richard Marian Thomaiyar | fc5e985 | 2019-04-14 15:06:27 +0530 | [diff] [blame] | 1390 | try | 
|  | 1391 | { | 
|  | 1392 | getChannelInfo(ctx->channel, chInfo); | 
|  | 1393 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1394 | catch (const sdbusplus::exception_t& e) | 
| Richard Marian Thomaiyar | fc5e985 | 2019-04-14 15:06:27 +0530 | [diff] [blame] | 1395 | { | 
|  | 1396 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1397 | "ipmiOEMSetSpecialUserPassword: Failed to get Channel Info", | 
|  | 1398 | phosphor::logging::entry("MSG: %s", e.description())); | 
|  | 1399 | return ipmi::responseUnspecifiedError(); | 
|  | 1400 | } | 
|  | 1401 | if (chInfo.mediumType != | 
|  | 1402 | static_cast<uint8_t>(EChannelMediumType::systemInterface)) | 
|  | 1403 | { | 
|  | 1404 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1405 | "ipmiOEMSetSpecialUserPassword: Error - supported only in KCS " | 
|  | 1406 | "interface"); | 
|  | 1407 | return ipmi::responseCommandNotAvailable(); | 
|  | 1408 | } | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1409 |  | 
|  | 1410 | // 0 for root user  and 1 for AtScaleDebug is allowed | 
|  | 1411 | if (specialUserIndex > | 
|  | 1412 | static_cast<uint8_t>(SpecialUserIndex::atScaleDebugUser)) | 
| Richard Marian Thomaiyar | fc5e985 | 2019-04-14 15:06:27 +0530 | [diff] [blame] | 1413 | { | 
|  | 1414 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1415 | "ipmiOEMSetSpecialUserPassword: Invalid user account"); | 
|  | 1416 | return ipmi::responseParmOutOfRange(); | 
|  | 1417 | } | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1418 | if (userPassword.size() != 0) | 
| Richard Marian Thomaiyar | fc5e985 | 2019-04-14 15:06:27 +0530 | [diff] [blame] | 1419 | { | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1420 | constexpr uint8_t minPasswordSizeRequired = 6; | 
| Patrick Williams | 2393985 | 2021-09-02 11:18:35 -0500 | [diff] [blame] | 1421 | SecureString passwd; | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1422 | if (userPassword.size() < minPasswordSizeRequired || | 
|  | 1423 | userPassword.size() > ipmi::maxIpmi20PasswordSize) | 
|  | 1424 | { | 
| Jayaprakash Mutyala | 9420416 | 2020-10-23 06:17:56 +0000 | [diff] [blame] | 1425 | OPENSSL_cleanse(userPassword.data(), userPassword.size()); | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1426 | return ipmi::responseReqDataLenInvalid(); | 
|  | 1427 | } | 
|  | 1428 | passwd.assign(reinterpret_cast<const char*>(userPassword.data()), | 
|  | 1429 | userPassword.size()); | 
| Jayaprakash Mutyala | 9420416 | 2020-10-23 06:17:56 +0000 | [diff] [blame] | 1430 | // Clear sensitive data | 
|  | 1431 | OPENSSL_cleanse(userPassword.data(), userPassword.size()); | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1432 | if (specialUserIndex == | 
|  | 1433 | static_cast<uint8_t>(SpecialUserIndex::atScaleDebugUser)) | 
|  | 1434 | { | 
|  | 1435 | status = ipmiSetSpecialUserPassword("asdbg", passwd); | 
|  | 1436 |  | 
|  | 1437 | atScaleDebugEventlog("AtScaleDebugSpecialUserEnabled", LOG_CRIT); | 
|  | 1438 | } | 
|  | 1439 | else | 
|  | 1440 | { | 
|  | 1441 | status = ipmiSetSpecialUserPassword("root", passwd); | 
|  | 1442 | } | 
|  | 1443 | return ipmi::response(status); | 
| Richard Marian Thomaiyar | fc5e985 | 2019-04-14 15:06:27 +0530 | [diff] [blame] | 1444 | } | 
| Suryakanth Sekar | 822b0b4 | 2019-11-15 18:32:53 +0530 | [diff] [blame] | 1445 | else | 
|  | 1446 | { | 
|  | 1447 | if (specialUserIndex == | 
|  | 1448 | static_cast<uint8_t>(SpecialUserIndex::rootUser)) | 
|  | 1449 | { | 
|  | 1450 | status = executeCmd("passwd -d root"); | 
|  | 1451 | } | 
|  | 1452 | else | 
|  | 1453 | { | 
|  | 1454 |  | 
|  | 1455 | status = executeCmd("passwd -d asdbg"); | 
|  | 1456 |  | 
|  | 1457 | if (status == 0) | 
|  | 1458 | { | 
|  | 1459 | atScaleDebugEventlog("AtScaleDebugSpecialUserDisabled", | 
|  | 1460 | LOG_INFO); | 
|  | 1461 | } | 
|  | 1462 | } | 
|  | 1463 | return ipmi::response(status); | 
|  | 1464 | } | 
| Richard Marian Thomaiyar | fc5e985 | 2019-04-14 15:06:27 +0530 | [diff] [blame] | 1465 | } | 
|  | 1466 |  | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1467 | namespace ledAction | 
|  | 1468 | { | 
|  | 1469 | using namespace sdbusplus::xyz::openbmc_project::Led::server; | 
|  | 1470 | std::map<Physical::Action, uint8_t> actionDbusToIpmi = { | 
| jayaprakash Mutyala | 934ee9c | 2019-12-13 17:49:27 +0000 | [diff] [blame] | 1471 | {Physical::Action::Off, 0}, | 
|  | 1472 | {Physical::Action::On, 2}, | 
|  | 1473 | {Physical::Action::Blink, 1}}; | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1474 |  | 
|  | 1475 | std::map<uint8_t, std::string> offsetObjPath = { | 
|  | 1476 | {2, statusAmberObjPath}, {4, statusGreenObjPath}, {6, identifyLEDObjPath}}; | 
|  | 1477 |  | 
|  | 1478 | } // namespace ledAction | 
|  | 1479 |  | 
|  | 1480 | int8_t getLEDState(sdbusplus::bus::bus& bus, const std::string& intf, | 
|  | 1481 | const std::string& objPath, uint8_t& state) | 
|  | 1482 | { | 
|  | 1483 | try | 
|  | 1484 | { | 
|  | 1485 | std::string service = getService(bus, intf, objPath); | 
|  | 1486 | Value stateValue = | 
|  | 1487 | getDbusProperty(bus, service, objPath, intf, "State"); | 
| Vernon Mauery | 8166c8d | 2019-05-23 11:22:30 -0700 | [diff] [blame] | 1488 | std::string strState = std::get<std::string>(stateValue); | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1489 | state = ledAction::actionDbusToIpmi.at( | 
|  | 1490 | sdbusplus::xyz::openbmc_project::Led::server::Physical:: | 
|  | 1491 | convertActionFromString(strState)); | 
|  | 1492 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1493 | catch (const sdbusplus::exception::exception& e) | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1494 | { | 
|  | 1495 | phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); | 
|  | 1496 | return -1; | 
|  | 1497 | } | 
|  | 1498 | return 0; | 
|  | 1499 | } | 
|  | 1500 |  | 
| NITIN SHARMA | abd11ca | 2019-06-12 12:31:42 +0000 | [diff] [blame] | 1501 | ipmi::RspType<uint8_t> ipmiOEMGetLEDStatus() | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1502 | { | 
| NITIN SHARMA | abd11ca | 2019-06-12 12:31:42 +0000 | [diff] [blame] | 1503 | uint8_t ledstate = 0; | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1504 | phosphor::logging::log<phosphor::logging::level::DEBUG>("GET led status"); | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1505 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1506 | for (auto it = ledAction::offsetObjPath.begin(); | 
|  | 1507 | it != ledAction::offsetObjPath.end(); ++it) | 
|  | 1508 | { | 
|  | 1509 | uint8_t state = 0; | 
| NITIN SHARMA | abd11ca | 2019-06-12 12:31:42 +0000 | [diff] [blame] | 1510 | if (getLEDState(*dbus, ledIntf, it->second, state) == -1) | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1511 | { | 
|  | 1512 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1513 | "oem_get_led_status: fail to get ID LED status!"); | 
| NITIN SHARMA | abd11ca | 2019-06-12 12:31:42 +0000 | [diff] [blame] | 1514 | return ipmi::responseUnspecifiedError(); | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1515 | } | 
| NITIN SHARMA | abd11ca | 2019-06-12 12:31:42 +0000 | [diff] [blame] | 1516 | ledstate |= state << it->first; | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1517 | } | 
| NITIN SHARMA | abd11ca | 2019-06-12 12:31:42 +0000 | [diff] [blame] | 1518 | return ipmi::responseSuccess(ledstate); | 
| Kuiying Wang | 45f0498 | 2018-12-26 09:23:08 +0800 | [diff] [blame] | 1519 | } | 
|  | 1520 |  | 
| Yong Li | 23737fe | 2019-02-19 08:49:55 +0800 | [diff] [blame] | 1521 | ipmi_ret_t ipmiOEMCfgHostSerialPortSpeed(ipmi_netfn_t netfn, ipmi_cmd_t cmd, | 
|  | 1522 | ipmi_request_t request, | 
|  | 1523 | ipmi_response_t response, | 
|  | 1524 | ipmi_data_len_t dataLen, | 
|  | 1525 | ipmi_context_t context) | 
|  | 1526 | { | 
|  | 1527 | CfgHostSerialReq* req = reinterpret_cast<CfgHostSerialReq*>(request); | 
|  | 1528 | uint8_t* resp = reinterpret_cast<uint8_t*>(response); | 
|  | 1529 |  | 
|  | 1530 | if (*dataLen == 0) | 
|  | 1531 | { | 
|  | 1532 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1533 | "CfgHostSerial: invalid input len!", | 
|  | 1534 | phosphor::logging::entry("LEN=%d", *dataLen)); | 
|  | 1535 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 1536 | } | 
|  | 1537 |  | 
|  | 1538 | switch (req->command) | 
|  | 1539 | { | 
|  | 1540 | case getHostSerialCfgCmd: | 
|  | 1541 | { | 
|  | 1542 | if (*dataLen != 1) | 
|  | 1543 | { | 
|  | 1544 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1545 | "CfgHostSerial: invalid input len!"); | 
|  | 1546 | *dataLen = 0; | 
|  | 1547 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 1548 | } | 
|  | 1549 |  | 
|  | 1550 | *dataLen = 0; | 
|  | 1551 |  | 
|  | 1552 | boost::process::ipstream is; | 
|  | 1553 | std::vector<std::string> data; | 
|  | 1554 | std::string line; | 
|  | 1555 | boost::process::child c1(fwGetEnvCmd, "-n", fwHostSerailCfgEnvName, | 
|  | 1556 | boost::process::std_out > is); | 
|  | 1557 |  | 
|  | 1558 | while (c1.running() && std::getline(is, line) && !line.empty()) | 
|  | 1559 | { | 
|  | 1560 | data.push_back(line); | 
|  | 1561 | } | 
|  | 1562 |  | 
|  | 1563 | c1.wait(); | 
|  | 1564 | if (c1.exit_code()) | 
|  | 1565 | { | 
|  | 1566 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1567 | "CfgHostSerial:: error on execute", | 
|  | 1568 | phosphor::logging::entry("EXECUTE=%s", fwSetEnvCmd)); | 
|  | 1569 | // Using the default value | 
|  | 1570 | *resp = 0; | 
|  | 1571 | } | 
|  | 1572 | else | 
|  | 1573 | { | 
|  | 1574 | if (data.size() != 1) | 
|  | 1575 | { | 
|  | 1576 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1577 | "CfgHostSerial:: error on read env"); | 
|  | 1578 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 1579 | } | 
|  | 1580 | try | 
|  | 1581 | { | 
|  | 1582 | unsigned long tmp = std::stoul(data[0]); | 
|  | 1583 | if (tmp > std::numeric_limits<uint8_t>::max()) | 
|  | 1584 | { | 
|  | 1585 | throw std::out_of_range("Out of range"); | 
|  | 1586 | } | 
|  | 1587 | *resp = static_cast<uint8_t>(tmp); | 
|  | 1588 | } | 
|  | 1589 | catch (const std::invalid_argument& e) | 
|  | 1590 | { | 
|  | 1591 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1592 | "invalid config ", | 
|  | 1593 | phosphor::logging::entry("ERR=%s", e.what())); | 
|  | 1594 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 1595 | } | 
|  | 1596 | catch (const std::out_of_range& e) | 
|  | 1597 | { | 
|  | 1598 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1599 | "out_of_range config ", | 
|  | 1600 | phosphor::logging::entry("ERR=%s", e.what())); | 
|  | 1601 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 1602 | } | 
|  | 1603 | } | 
|  | 1604 |  | 
|  | 1605 | *dataLen = 1; | 
|  | 1606 | break; | 
|  | 1607 | } | 
|  | 1608 | case setHostSerialCfgCmd: | 
|  | 1609 | { | 
|  | 1610 | if (*dataLen != sizeof(CfgHostSerialReq)) | 
|  | 1611 | { | 
|  | 1612 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1613 | "CfgHostSerial: invalid input len!"); | 
|  | 1614 | *dataLen = 0; | 
|  | 1615 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 1616 | } | 
|  | 1617 |  | 
|  | 1618 | *dataLen = 0; | 
|  | 1619 |  | 
|  | 1620 | if (req->parameter > HostSerialCfgParamMax) | 
|  | 1621 | { | 
|  | 1622 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1623 | "CfgHostSerial: invalid input!"); | 
|  | 1624 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 1625 | } | 
|  | 1626 |  | 
|  | 1627 | boost::process::child c1(fwSetEnvCmd, fwHostSerailCfgEnvName, | 
|  | 1628 | std::to_string(req->parameter)); | 
|  | 1629 |  | 
|  | 1630 | c1.wait(); | 
|  | 1631 | if (c1.exit_code()) | 
|  | 1632 | { | 
|  | 1633 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1634 | "CfgHostSerial:: error on execute", | 
|  | 1635 | phosphor::logging::entry("EXECUTE=%s", fwGetEnvCmd)); | 
|  | 1636 | return IPMI_CC_UNSPECIFIED_ERROR; | 
|  | 1637 | } | 
|  | 1638 | break; | 
|  | 1639 | } | 
|  | 1640 | default: | 
|  | 1641 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1642 | "CfgHostSerial: invalid input!"); | 
|  | 1643 | *dataLen = 0; | 
|  | 1644 | return IPMI_CC_INVALID_FIELD_REQUEST; | 
|  | 1645 | } | 
|  | 1646 |  | 
|  | 1647 | return IPMI_CC_OK; | 
|  | 1648 | } | 
|  | 1649 |  | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1650 | constexpr const char* thermalModeInterface = | 
|  | 1651 | "xyz.openbmc_project.Control.ThermalMode"; | 
|  | 1652 | constexpr const char* thermalModePath = | 
|  | 1653 | "/xyz/openbmc_project/control/thermal_mode"; | 
|  | 1654 |  | 
|  | 1655 | bool getFanProfileInterface( | 
|  | 1656 | sdbusplus::bus::bus& bus, | 
|  | 1657 | boost::container::flat_map< | 
|  | 1658 | std::string, std::variant<std::vector<std::string>, std::string>>& resp) | 
|  | 1659 | { | 
|  | 1660 | auto call = bus.new_method_call(settingsBusName, thermalModePath, PROP_INTF, | 
|  | 1661 | "GetAll"); | 
|  | 1662 | call.append(thermalModeInterface); | 
|  | 1663 | try | 
|  | 1664 | { | 
|  | 1665 | auto data = bus.call(call); | 
|  | 1666 | data.read(resp); | 
|  | 1667 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1668 | catch (const sdbusplus::exception_t& e) | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1669 | { | 
|  | 1670 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1671 | "getFanProfileInterface: can't get thermal mode!", | 
|  | 1672 | phosphor::logging::entry("ERR=%s", e.what())); | 
|  | 1673 | return false; | 
|  | 1674 | } | 
|  | 1675 | return true; | 
|  | 1676 | } | 
|  | 1677 |  | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1678 | /**@brief implements the OEM set fan config. | 
|  | 1679 | * @param selectedFanProfile - fan profile to enable | 
|  | 1680 | * @param reserved1 | 
|  | 1681 | * @param performanceMode - Performance/Acoustic mode | 
|  | 1682 | * @param reserved2 | 
|  | 1683 | * @param setPerformanceMode - set Performance/Acoustic mode | 
|  | 1684 | * @param setFanProfile - set fan profile | 
|  | 1685 | * | 
|  | 1686 | * @return IPMI completion code. | 
|  | 1687 | **/ | 
|  | 1688 | ipmi::RspType<> ipmiOEMSetFanConfig(uint8_t selectedFanProfile, | 
|  | 1689 |  | 
|  | 1690 | uint2_t reserved1, bool performanceMode, | 
|  | 1691 | uint3_t reserved2, bool setPerformanceMode, | 
| Joshi-Mansi | 619186d | 2020-01-27 19:16:03 +0530 | [diff] [blame] | 1692 | bool setFanProfile, | 
|  | 1693 | std::optional<uint8_t> dimmGroupId, | 
|  | 1694 | std::optional<uint32_t> dimmPresenceBitmap) | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1695 | { | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1696 | if (reserved1 || reserved2) | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1697 | { | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1698 | return ipmi::responseInvalidFieldRequest(); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1699 | } | 
| Joshi-Mansi | 619186d | 2020-01-27 19:16:03 +0530 | [diff] [blame] | 1700 |  | 
|  | 1701 | if (dimmGroupId) | 
|  | 1702 | { | 
|  | 1703 | if (*dimmGroupId >= maxCPUNum) | 
|  | 1704 | { | 
|  | 1705 | return ipmi::responseInvalidFieldRequest(); | 
|  | 1706 | } | 
|  | 1707 | if (!cpuPresent("CPU_" + std::to_string(*dimmGroupId + 1))) | 
|  | 1708 | { | 
|  | 1709 | return ipmi::responseInvalidFieldRequest(); | 
|  | 1710 | } | 
|  | 1711 | } | 
|  | 1712 |  | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1713 | // todo: tell bios to only send first 2 bytes | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1714 | boost::container::flat_map< | 
|  | 1715 | std::string, std::variant<std::vector<std::string>, std::string>> | 
|  | 1716 | profileData; | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1717 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 1718 | if (!getFanProfileInterface(*dbus, profileData)) | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1719 | { | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1720 | return ipmi::responseUnspecifiedError(); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1721 | } | 
|  | 1722 |  | 
|  | 1723 | std::vector<std::string>* supported = | 
|  | 1724 | std::get_if<std::vector<std::string>>(&profileData["Supported"]); | 
|  | 1725 | if (supported == nullptr) | 
|  | 1726 | { | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1727 | return ipmi::responseInvalidFieldRequest(); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1728 | } | 
|  | 1729 | std::string mode; | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1730 | if (setPerformanceMode) | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1731 | { | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1732 | if (performanceMode) | 
|  | 1733 | { | 
|  | 1734 |  | 
|  | 1735 | if (std::find(supported->begin(), supported->end(), | 
|  | 1736 | "Performance") != supported->end()) | 
|  | 1737 | { | 
|  | 1738 | mode = "Performance"; | 
|  | 1739 | } | 
|  | 1740 | } | 
|  | 1741 | else | 
|  | 1742 | { | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1743 | if (std::find(supported->begin(), supported->end(), "Acoustic") != | 
|  | 1744 | supported->end()) | 
|  | 1745 | { | 
|  | 1746 | mode = "Acoustic"; | 
|  | 1747 | } | 
|  | 1748 | } | 
|  | 1749 | if (mode.empty()) | 
|  | 1750 | { | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1751 | return ipmi::responseInvalidFieldRequest(); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1752 | } | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1753 |  | 
|  | 1754 | try | 
|  | 1755 | { | 
|  | 1756 | setDbusProperty(*dbus, settingsBusName, thermalModePath, | 
|  | 1757 | thermalModeInterface, "Current", mode); | 
|  | 1758 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1759 | catch (const sdbusplus::exception_t& e) | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1760 | { | 
|  | 1761 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1762 | "ipmiOEMSetFanConfig: can't set thermal mode!", | 
|  | 1763 | phosphor::logging::entry("EXCEPTION=%s", e.what())); | 
|  | 1764 | return ipmi::responseResponseError(); | 
|  | 1765 | } | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1766 | } | 
|  | 1767 |  | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 1768 | return ipmi::responseSuccess(); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1769 | } | 
|  | 1770 |  | 
| James Feist | 5b69363 | 2019-07-09 09:06:09 -0700 | [diff] [blame] | 1771 | ipmi::RspType<uint8_t, // profile support map | 
|  | 1772 | uint8_t, // fan control profile enable | 
|  | 1773 | uint8_t, // flags | 
|  | 1774 | uint32_t // dimm presence bit map | 
|  | 1775 | > | 
|  | 1776 | ipmiOEMGetFanConfig(uint8_t dimmGroupId) | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1777 | { | 
| Joshi-Mansi | 36f05ce | 2020-01-14 14:29:34 +0530 | [diff] [blame] | 1778 | if (dimmGroupId >= maxCPUNum) | 
|  | 1779 | { | 
|  | 1780 | return ipmi::responseInvalidFieldRequest(); | 
|  | 1781 | } | 
|  | 1782 |  | 
|  | 1783 | bool cpuStatus = cpuPresent("CPU_" + std::to_string(dimmGroupId + 1)); | 
|  | 1784 |  | 
|  | 1785 | if (!cpuStatus) | 
|  | 1786 | { | 
|  | 1787 | return ipmi::responseInvalidFieldRequest(); | 
|  | 1788 | } | 
|  | 1789 |  | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1790 | boost::container::flat_map< | 
|  | 1791 | std::string, std::variant<std::vector<std::string>, std::string>> | 
|  | 1792 | profileData; | 
|  | 1793 |  | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1794 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 1795 | if (!getFanProfileInterface(*dbus, profileData)) | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1796 | { | 
| James Feist | 5b69363 | 2019-07-09 09:06:09 -0700 | [diff] [blame] | 1797 | return ipmi::responseResponseError(); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1798 | } | 
|  | 1799 |  | 
|  | 1800 | std::string* current = std::get_if<std::string>(&profileData["Current"]); | 
|  | 1801 |  | 
|  | 1802 | if (current == nullptr) | 
|  | 1803 | { | 
|  | 1804 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1805 | "ipmiOEMGetFanConfig: can't get current mode!"); | 
| James Feist | 5b69363 | 2019-07-09 09:06:09 -0700 | [diff] [blame] | 1806 | return ipmi::responseResponseError(); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1807 | } | 
|  | 1808 | bool performance = (*current == "Performance"); | 
|  | 1809 |  | 
| James Feist | 5b69363 | 2019-07-09 09:06:09 -0700 | [diff] [blame] | 1810 | uint8_t flags = 0; | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1811 | if (performance) | 
|  | 1812 | { | 
| James Feist | 5b69363 | 2019-07-09 09:06:09 -0700 | [diff] [blame] | 1813 | flags |= 1 << 2; | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1814 | } | 
|  | 1815 |  | 
| jayaprakash Mutyala | 4b1552d | 2020-02-11 12:07:29 +0000 | [diff] [blame] | 1816 | constexpr uint8_t fanControlDefaultProfile = 0x80; | 
|  | 1817 | constexpr uint8_t fanControlProfileState = 0x00; | 
|  | 1818 | constexpr uint32_t dimmPresenceBitmap = 0x00; | 
|  | 1819 |  | 
|  | 1820 | return ipmi::responseSuccess(fanControlDefaultProfile, | 
|  | 1821 | fanControlProfileState, flags, | 
|  | 1822 | dimmPresenceBitmap); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 1823 | } | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 1824 | constexpr const char* cfmLimitSettingPath = | 
|  | 1825 | "/xyz/openbmc_project/control/cfm_limit"; | 
|  | 1826 | constexpr const char* cfmLimitIface = "xyz.openbmc_project.Control.CFMLimit"; | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1827 | constexpr const size_t legacyExitAirSensorNumber = 0x2e; | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 1828 | constexpr const size_t legacyPCHSensorNumber = 0x22; | 
|  | 1829 | constexpr const char* exitAirPathName = "Exit_Air"; | 
|  | 1830 | constexpr const char* pchPathName = "SSB_Temp"; | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1831 | constexpr const char* pidConfigurationIface = | 
|  | 1832 | "xyz.openbmc_project.Configuration.Pid"; | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1833 |  | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 1834 | static std::string getConfigPath(const std::string& name) | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1835 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1836 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1837 | auto method = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1838 | dbus->new_method_call("xyz.openbmc_project.ObjectMapper", | 
|  | 1839 | "/xyz/openbmc_project/object_mapper", | 
|  | 1840 | "xyz.openbmc_project.ObjectMapper", "GetSubTree"); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1841 |  | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1842 | method.append("/", 0, std::array<const char*, 1>{pidConfigurationIface}); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1843 | std::string path; | 
|  | 1844 | GetSubTreeType resp; | 
|  | 1845 | try | 
|  | 1846 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1847 | auto reply = dbus->call(method); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1848 | reply.read(resp); | 
|  | 1849 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1850 | catch (const sdbusplus::exception_t&) | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1851 | { | 
|  | 1852 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1853 | "ipmiOEMGetFscParameter: mapper error"); | 
|  | 1854 | }; | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 1855 | auto config = | 
|  | 1856 | std::find_if(resp.begin(), resp.end(), [&name](const auto& pair) { | 
|  | 1857 | return pair.first.find(name) != std::string::npos; | 
|  | 1858 | }); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 1859 | if (config != resp.end()) | 
|  | 1860 | { | 
|  | 1861 | path = std::move(config->first); | 
|  | 1862 | } | 
|  | 1863 | return path; | 
|  | 1864 | } | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 1865 |  | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1866 | // flat map to make alphabetical | 
|  | 1867 | static boost::container::flat_map<std::string, PropertyMap> getPidConfigs() | 
|  | 1868 | { | 
|  | 1869 | boost::container::flat_map<std::string, PropertyMap> ret; | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1870 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1871 | auto method = | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1872 | dbus->new_method_call("xyz.openbmc_project.ObjectMapper", | 
|  | 1873 | "/xyz/openbmc_project/object_mapper", | 
|  | 1874 | "xyz.openbmc_project.ObjectMapper", "GetSubTree"); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1875 |  | 
|  | 1876 | method.append("/", 0, std::array<const char*, 1>{pidConfigurationIface}); | 
|  | 1877 | GetSubTreeType resp; | 
|  | 1878 |  | 
|  | 1879 | try | 
|  | 1880 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1881 | auto reply = dbus->call(method); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1882 | reply.read(resp); | 
|  | 1883 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1884 | catch (const sdbusplus::exception_t&) | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1885 | { | 
|  | 1886 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1887 | "getFanConfigPaths: mapper error"); | 
|  | 1888 | }; | 
|  | 1889 | for (const auto& [path, objects] : resp) | 
|  | 1890 | { | 
|  | 1891 | if (objects.empty()) | 
|  | 1892 | { | 
|  | 1893 | continue; // should be impossible | 
|  | 1894 | } | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 1895 |  | 
|  | 1896 | try | 
|  | 1897 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1898 | ret.emplace(path, | 
|  | 1899 | getAllDbusProperties(*dbus, objects[0].first, path, | 
|  | 1900 | pidConfigurationIface)); | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 1901 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 1902 | catch (const sdbusplus::exception_t& e) | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 1903 | { | 
|  | 1904 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1905 | "getPidConfigs: can't get DbusProperties!", | 
|  | 1906 | phosphor::logging::entry("ERR=%s", e.what())); | 
|  | 1907 | } | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1908 | } | 
|  | 1909 | return ret; | 
|  | 1910 | } | 
|  | 1911 |  | 
|  | 1912 | ipmi::RspType<uint8_t> ipmiOEMGetFanSpeedOffset(void) | 
|  | 1913 | { | 
|  | 1914 | boost::container::flat_map<std::string, PropertyMap> data = getPidConfigs(); | 
|  | 1915 | if (data.empty()) | 
|  | 1916 | { | 
|  | 1917 | return ipmi::responseResponseError(); | 
|  | 1918 | } | 
|  | 1919 | uint8_t minOffset = std::numeric_limits<uint8_t>::max(); | 
|  | 1920 | for (const auto& [_, pid] : data) | 
|  | 1921 | { | 
|  | 1922 | auto findClass = pid.find("Class"); | 
|  | 1923 | if (findClass == pid.end()) | 
|  | 1924 | { | 
|  | 1925 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1926 | "ipmiOEMGetFscParameter: found illegal pid " | 
|  | 1927 | "configurations"); | 
|  | 1928 | return ipmi::responseResponseError(); | 
|  | 1929 | } | 
|  | 1930 | std::string type = std::get<std::string>(findClass->second); | 
|  | 1931 | if (type == "fan") | 
|  | 1932 | { | 
|  | 1933 | auto findOutLimit = pid.find("OutLimitMin"); | 
|  | 1934 | if (findOutLimit == pid.end()) | 
|  | 1935 | { | 
|  | 1936 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1937 | "ipmiOEMGetFscParameter: found illegal pid " | 
|  | 1938 | "configurations"); | 
|  | 1939 | return ipmi::responseResponseError(); | 
|  | 1940 | } | 
|  | 1941 | // get the min out of all the offsets | 
|  | 1942 | minOffset = std::min( | 
|  | 1943 | minOffset, | 
|  | 1944 | static_cast<uint8_t>(std::get<double>(findOutLimit->second))); | 
|  | 1945 | } | 
|  | 1946 | } | 
|  | 1947 | if (minOffset == std::numeric_limits<uint8_t>::max()) | 
|  | 1948 | { | 
|  | 1949 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1950 | "ipmiOEMGetFscParameter: found no fan configurations!"); | 
|  | 1951 | return ipmi::responseResponseError(); | 
|  | 1952 | } | 
|  | 1953 |  | 
|  | 1954 | return ipmi::responseSuccess(minOffset); | 
|  | 1955 | } | 
|  | 1956 |  | 
|  | 1957 | ipmi::RspType<> ipmiOEMSetFanSpeedOffset(uint8_t offset) | 
|  | 1958 | { | 
| Manish Baing | baa579f | 2021-10-08 22:30:32 +0000 | [diff] [blame] | 1959 | constexpr uint8_t maxFanSpeedOffset = 100; | 
|  | 1960 | if (offset > maxFanSpeedOffset) | 
|  | 1961 | { | 
|  | 1962 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1963 | "ipmiOEMSetFanSpeedOffset: fan offset greater than limit"); | 
|  | 1964 | return ipmi::responseInvalidFieldRequest(); | 
|  | 1965 | } | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1966 | boost::container::flat_map<std::string, PropertyMap> data = getPidConfigs(); | 
|  | 1967 | if (data.empty()) | 
|  | 1968 | { | 
|  | 1969 |  | 
|  | 1970 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1971 | "ipmiOEMSetFanSpeedOffset: found no pid configurations!"); | 
|  | 1972 | return ipmi::responseResponseError(); | 
|  | 1973 | } | 
|  | 1974 |  | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 1975 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 1976 | bool found = false; | 
|  | 1977 | for (const auto& [path, pid] : data) | 
|  | 1978 | { | 
|  | 1979 | auto findClass = pid.find("Class"); | 
|  | 1980 | if (findClass == pid.end()) | 
|  | 1981 | { | 
|  | 1982 |  | 
|  | 1983 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1984 | "ipmiOEMSetFanSpeedOffset: found illegal pid " | 
|  | 1985 | "configurations"); | 
|  | 1986 | return ipmi::responseResponseError(); | 
|  | 1987 | } | 
|  | 1988 | std::string type = std::get<std::string>(findClass->second); | 
|  | 1989 | if (type == "fan") | 
|  | 1990 | { | 
|  | 1991 | auto findOutLimit = pid.find("OutLimitMin"); | 
|  | 1992 | if (findOutLimit == pid.end()) | 
|  | 1993 | { | 
|  | 1994 |  | 
|  | 1995 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 1996 | "ipmiOEMSetFanSpeedOffset: found illegal pid " | 
|  | 1997 | "configurations"); | 
|  | 1998 | return ipmi::responseResponseError(); | 
|  | 1999 | } | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2000 | ipmi::setDbusProperty(*dbus, "xyz.openbmc_project.EntityManager", | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2001 | path, pidConfigurationIface, "OutLimitMin", | 
|  | 2002 | static_cast<double>(offset)); | 
|  | 2003 | found = true; | 
|  | 2004 | } | 
|  | 2005 | } | 
|  | 2006 | if (!found) | 
|  | 2007 | { | 
|  | 2008 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2009 | "ipmiOEMSetFanSpeedOffset: set no fan offsets"); | 
|  | 2010 | return ipmi::responseResponseError(); | 
|  | 2011 | } | 
|  | 2012 |  | 
|  | 2013 | return ipmi::responseSuccess(); | 
|  | 2014 | } | 
|  | 2015 |  | 
|  | 2016 | ipmi::RspType<> ipmiOEMSetFscParameter(uint8_t command, uint8_t param1, | 
|  | 2017 | uint8_t param2) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2018 | { | 
|  | 2019 | constexpr const size_t disableLimiting = 0x0; | 
|  | 2020 |  | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2021 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2022 | if (command == static_cast<uint8_t>(setFscParamFlags::tcontrol)) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2023 | { | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 2024 | std::string pathName; | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2025 | if (param1 == legacyExitAirSensorNumber) | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2026 | { | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 2027 | pathName = exitAirPathName; | 
|  | 2028 | } | 
|  | 2029 | else if (param1 == legacyPCHSensorNumber) | 
|  | 2030 | { | 
|  | 2031 | pathName = pchPathName; | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2032 | } | 
|  | 2033 | else | 
|  | 2034 | { | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2035 | return ipmi::responseParmOutOfRange(); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2036 | } | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 2037 | std::string path = getConfigPath(pathName); | 
|  | 2038 | ipmi::setDbusProperty(*dbus, "xyz.openbmc_project.EntityManager", path, | 
|  | 2039 | pidConfigurationIface, "SetPoint", | 
|  | 2040 | static_cast<double>(param2)); | 
|  | 2041 | return ipmi::responseSuccess(); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2042 | } | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2043 | else if (command == static_cast<uint8_t>(setFscParamFlags::cfm)) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2044 | { | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2045 | uint16_t cfm = param1 | (static_cast<uint16_t>(param2) << 8); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2046 |  | 
|  | 2047 | // must be greater than 50 based on eps | 
|  | 2048 | if (cfm < 50 && cfm != disableLimiting) | 
|  | 2049 | { | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2050 | return ipmi::responseParmOutOfRange(); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2051 | } | 
|  | 2052 |  | 
|  | 2053 | try | 
|  | 2054 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2055 | ipmi::setDbusProperty(*dbus, settingsBusName, cfmLimitSettingPath, | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2056 | cfmLimitIface, "Limit", | 
|  | 2057 | static_cast<double>(cfm)); | 
|  | 2058 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 2059 | catch (const sdbusplus::exception_t& e) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2060 | { | 
|  | 2061 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2062 | "ipmiOEMSetFscParameter: can't set cfm setting!", | 
|  | 2063 | phosphor::logging::entry("ERR=%s", e.what())); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2064 | return ipmi::responseResponseError(); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2065 | } | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2066 | return ipmi::responseSuccess(); | 
|  | 2067 | } | 
|  | 2068 | else if (command == static_cast<uint8_t>(setFscParamFlags::maxPwm)) | 
|  | 2069 | { | 
|  | 2070 | constexpr const size_t maxDomainCount = 8; | 
|  | 2071 | uint8_t requestedDomainMask = param1; | 
|  | 2072 | boost::container::flat_map data = getPidConfigs(); | 
|  | 2073 | if (data.empty()) | 
|  | 2074 | { | 
|  | 2075 |  | 
|  | 2076 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2077 | "ipmiOEMSetFscParameter: found no pid configurations!"); | 
|  | 2078 | return ipmi::responseResponseError(); | 
|  | 2079 | } | 
|  | 2080 | size_t count = 0; | 
|  | 2081 | for (const auto& [path, pid] : data) | 
|  | 2082 | { | 
|  | 2083 | auto findClass = pid.find("Class"); | 
|  | 2084 | if (findClass == pid.end()) | 
|  | 2085 | { | 
|  | 2086 |  | 
|  | 2087 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2088 | "ipmiOEMSetFscParameter: found illegal pid " | 
|  | 2089 | "configurations"); | 
|  | 2090 | return ipmi::responseResponseError(); | 
|  | 2091 | } | 
|  | 2092 | std::string type = std::get<std::string>(findClass->second); | 
|  | 2093 | if (type == "fan") | 
|  | 2094 | { | 
|  | 2095 | if (requestedDomainMask & (1 << count)) | 
|  | 2096 | { | 
|  | 2097 | ipmi::setDbusProperty( | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2098 | *dbus, "xyz.openbmc_project.EntityManager", path, | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2099 | pidConfigurationIface, "OutLimitMax", | 
|  | 2100 | static_cast<double>(param2)); | 
|  | 2101 | } | 
|  | 2102 | count++; | 
|  | 2103 | } | 
|  | 2104 | } | 
|  | 2105 | return ipmi::responseSuccess(); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2106 | } | 
|  | 2107 | else | 
|  | 2108 | { | 
|  | 2109 | // todo other command parts possibly | 
|  | 2110 | // tcontrol is handled in peci now | 
|  | 2111 | // fan speed offset not implemented yet | 
|  | 2112 | // domain pwm limit not implemented | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2113 | return ipmi::responseParmOutOfRange(); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2114 | } | 
|  | 2115 | } | 
|  | 2116 |  | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2117 | ipmi::RspType< | 
|  | 2118 | std::variant<uint8_t, std::array<uint8_t, 2>, std::array<uint16_t, 2>>> | 
|  | 2119 | ipmiOEMGetFscParameter(uint8_t command, std::optional<uint8_t> param) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2120 | { | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 2121 | constexpr uint8_t legacyDefaultSetpoint = -128; | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2122 |  | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2123 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2124 | if (command == static_cast<uint8_t>(setFscParamFlags::tcontrol)) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2125 | { | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2126 | if (!param) | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2127 | { | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2128 | return ipmi::responseReqDataLenInvalid(); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2129 | } | 
|  | 2130 |  | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 2131 | std::string pathName; | 
|  | 2132 |  | 
|  | 2133 | if (*param == legacyExitAirSensorNumber) | 
|  | 2134 | { | 
|  | 2135 | pathName = exitAirPathName; | 
|  | 2136 | } | 
|  | 2137 | else if (*param == legacyPCHSensorNumber) | 
|  | 2138 | { | 
|  | 2139 | pathName = pchPathName; | 
|  | 2140 | } | 
|  | 2141 | else | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2142 | { | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2143 | return ipmi::responseParmOutOfRange(); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2144 | } | 
| James Feist | 09f6b60 | 2019-08-08 11:30:03 -0700 | [diff] [blame] | 2145 |  | 
|  | 2146 | uint8_t setpoint = legacyDefaultSetpoint; | 
|  | 2147 | std::string path = getConfigPath(pathName); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2148 | if (path.size()) | 
|  | 2149 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2150 | Value val = ipmi::getDbusProperty( | 
|  | 2151 | *dbus, "xyz.openbmc_project.EntityManager", path, | 
|  | 2152 | pidConfigurationIface, "SetPoint"); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2153 | setpoint = std::floor(std::get<double>(val) + 0.5); | 
|  | 2154 | } | 
|  | 2155 |  | 
|  | 2156 | // old implementation used to return the "default" and current, we | 
|  | 2157 | // don't make the default readily available so just make both the | 
|  | 2158 | // same | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2159 |  | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2160 | return ipmi::responseSuccess( | 
|  | 2161 | std::array<uint8_t, 2>{setpoint, setpoint}); | 
| James Feist | faa4f22 | 2019-03-21 16:21:55 -0700 | [diff] [blame] | 2162 | } | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2163 | else if (command == static_cast<uint8_t>(setFscParamFlags::maxPwm)) | 
|  | 2164 | { | 
|  | 2165 | constexpr const size_t maxDomainCount = 8; | 
|  | 2166 |  | 
|  | 2167 | if (!param) | 
|  | 2168 | { | 
|  | 2169 | return ipmi::responseReqDataLenInvalid(); | 
|  | 2170 | } | 
|  | 2171 | uint8_t requestedDomain = *param; | 
|  | 2172 | if (requestedDomain >= maxDomainCount) | 
|  | 2173 | { | 
|  | 2174 | return ipmi::responseInvalidFieldRequest(); | 
|  | 2175 | } | 
|  | 2176 |  | 
|  | 2177 | boost::container::flat_map data = getPidConfigs(); | 
|  | 2178 | if (data.empty()) | 
|  | 2179 | { | 
|  | 2180 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2181 | "ipmiOEMGetFscParameter: found no pid configurations!"); | 
|  | 2182 | return ipmi::responseResponseError(); | 
|  | 2183 | } | 
|  | 2184 | size_t count = 0; | 
|  | 2185 | for (const auto& [_, pid] : data) | 
|  | 2186 | { | 
|  | 2187 | auto findClass = pid.find("Class"); | 
|  | 2188 | if (findClass == pid.end()) | 
|  | 2189 | { | 
|  | 2190 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2191 | "ipmiOEMGetFscParameter: found illegal pid " | 
|  | 2192 | "configurations"); | 
|  | 2193 | return ipmi::responseResponseError(); | 
|  | 2194 | } | 
|  | 2195 | std::string type = std::get<std::string>(findClass->second); | 
|  | 2196 | if (type == "fan") | 
|  | 2197 | { | 
|  | 2198 | if (requestedDomain == count) | 
|  | 2199 | { | 
|  | 2200 | auto findOutLimit = pid.find("OutLimitMax"); | 
|  | 2201 | if (findOutLimit == pid.end()) | 
|  | 2202 | { | 
|  | 2203 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2204 | "ipmiOEMGetFscParameter: found illegal pid " | 
|  | 2205 | "configurations"); | 
|  | 2206 | return ipmi::responseResponseError(); | 
|  | 2207 | } | 
|  | 2208 |  | 
|  | 2209 | return ipmi::responseSuccess( | 
|  | 2210 | static_cast<uint8_t>(std::floor( | 
|  | 2211 | std::get<double>(findOutLimit->second) + 0.5))); | 
|  | 2212 | } | 
|  | 2213 | else | 
|  | 2214 | { | 
|  | 2215 | count++; | 
|  | 2216 | } | 
|  | 2217 | } | 
|  | 2218 | } | 
|  | 2219 |  | 
|  | 2220 | return ipmi::responseInvalidFieldRequest(); | 
|  | 2221 | } | 
|  | 2222 | else if (command == static_cast<uint8_t>(setFscParamFlags::cfm)) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2223 | { | 
|  | 2224 |  | 
|  | 2225 | /* | 
|  | 2226 | DataLen should be 1, but host is sending us an extra bit. As the | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2227 | previous behavior didn't seem to prevent this, ignore the check for | 
|  | 2228 | now. | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2229 |  | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2230 | if (param) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2231 | { | 
|  | 2232 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2233 | "ipmiOEMGetFscParameter: invalid input len!"); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2234 | return IPMI_CC_REQ_DATA_LEN_INVALID; | 
|  | 2235 | } | 
|  | 2236 | */ | 
|  | 2237 | Value cfmLimit; | 
|  | 2238 | Value cfmMaximum; | 
|  | 2239 | try | 
|  | 2240 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2241 | cfmLimit = ipmi::getDbusProperty(*dbus, settingsBusName, | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2242 | cfmLimitSettingPath, cfmLimitIface, | 
|  | 2243 | "Limit"); | 
|  | 2244 | cfmMaximum = ipmi::getDbusProperty( | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2245 | *dbus, "xyz.openbmc_project.ExitAirTempSensor", | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2246 | "/xyz/openbmc_project/control/MaxCFM", cfmLimitIface, "Limit"); | 
|  | 2247 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 2248 | catch (const sdbusplus::exception_t& e) | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2249 | { | 
|  | 2250 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2251 | "ipmiOEMGetFscParameter: can't get cfm setting!", | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2252 | phosphor::logging::entry("ERR=%s", e.what())); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2253 | return ipmi::responseResponseError(); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2254 | } | 
|  | 2255 |  | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2256 | double cfmMax = std::get<double>(cfmMaximum); | 
|  | 2257 | double cfmLim = std::get<double>(cfmLimit); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2258 |  | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2259 | cfmLim = std::floor(cfmLim + 0.5); | 
|  | 2260 | cfmMax = std::floor(cfmMax + 0.5); | 
|  | 2261 | uint16_t cfmLimResp = static_cast<uint16_t>(cfmLim); | 
|  | 2262 | uint16_t cfmMaxResp = static_cast<uint16_t>(cfmMax); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2263 |  | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2264 | return ipmi::responseSuccess( | 
|  | 2265 | std::array<uint16_t, 2>{cfmLimResp, cfmMaxResp}); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2266 | } | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2267 |  | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2268 | else | 
|  | 2269 | { | 
|  | 2270 | // todo other command parts possibly | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2271 | // domain pwm limit not implemented | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 2272 | return ipmi::responseParmOutOfRange(); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 2273 | } | 
|  | 2274 | } | 
|  | 2275 |  | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2276 | using crConfigVariant = | 
|  | 2277 | std::variant<bool, uint8_t, uint32_t, std::vector<uint8_t>, std::string>; | 
|  | 2278 |  | 
|  | 2279 | int setCRConfig(ipmi::Context::ptr ctx, const std::string& property, | 
|  | 2280 | const crConfigVariant& value, | 
|  | 2281 | std::chrono::microseconds timeout = ipmi::IPMI_DBUS_TIMEOUT) | 
|  | 2282 | { | 
|  | 2283 | boost::system::error_code ec; | 
|  | 2284 | ctx->bus->yield_method_call<void>( | 
| Kuiying Wang | e45333a | 2020-07-22 22:06:37 +0800 | [diff] [blame] | 2285 | ctx->yield, ec, "xyz.openbmc_project.PSURedundancy", | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2286 | "/xyz/openbmc_project/control/power_supply_redundancy", | 
|  | 2287 | "org.freedesktop.DBus.Properties", "Set", | 
|  | 2288 | "xyz.openbmc_project.Control.PowerSupplyRedundancy", property, value); | 
|  | 2289 | if (ec) | 
|  | 2290 | { | 
|  | 2291 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2292 | "Failed to set dbus property to cold redundancy"); | 
|  | 2293 | return -1; | 
|  | 2294 | } | 
|  | 2295 |  | 
|  | 2296 | return 0; | 
|  | 2297 | } | 
|  | 2298 |  | 
| Kuiying Wang | e45333a | 2020-07-22 22:06:37 +0800 | [diff] [blame] | 2299 | int getCRConfig( | 
|  | 2300 | ipmi::Context::ptr ctx, const std::string& property, crConfigVariant& value, | 
|  | 2301 | const std::string& service = "xyz.openbmc_project.PSURedundancy", | 
|  | 2302 | std::chrono::microseconds timeout = ipmi::IPMI_DBUS_TIMEOUT) | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2303 | { | 
|  | 2304 | boost::system::error_code ec; | 
|  | 2305 | value = ctx->bus->yield_method_call<crConfigVariant>( | 
| Yong Li | 19445ab | 2019-12-20 18:25:29 +0800 | [diff] [blame] | 2306 | ctx->yield, ec, service, | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2307 | "/xyz/openbmc_project/control/power_supply_redundancy", | 
|  | 2308 | "org.freedesktop.DBus.Properties", "Get", | 
|  | 2309 | "xyz.openbmc_project.Control.PowerSupplyRedundancy", property); | 
|  | 2310 | if (ec) | 
|  | 2311 | { | 
|  | 2312 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2313 | "Failed to get dbus property to cold redundancy"); | 
|  | 2314 | return -1; | 
|  | 2315 | } | 
|  | 2316 | return 0; | 
|  | 2317 | } | 
|  | 2318 |  | 
|  | 2319 | uint8_t getPSUCount(void) | 
|  | 2320 | { | 
|  | 2321 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 2322 | ipmi::Value num; | 
|  | 2323 | try | 
|  | 2324 | { | 
|  | 2325 | num = ipmi::getDbusProperty( | 
|  | 2326 | *dbus, "xyz.openbmc_project.PSURedundancy", | 
|  | 2327 | "/xyz/openbmc_project/control/power_supply_redundancy", | 
|  | 2328 | "xyz.openbmc_project.Control.PowerSupplyRedundancy", "PSUNumber"); | 
|  | 2329 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 2330 | catch (const sdbusplus::exception_t& e) | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2331 | { | 
|  | 2332 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2333 | "Failed to get PSUNumber property from dbus interface"); | 
|  | 2334 | return 0; | 
|  | 2335 | } | 
|  | 2336 | uint8_t* pNum = std::get_if<uint8_t>(&num); | 
|  | 2337 | if (!pNum) | 
|  | 2338 | { | 
|  | 2339 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2340 | "Error to get PSU Number"); | 
|  | 2341 | return 0; | 
|  | 2342 | } | 
|  | 2343 | return *pNum; | 
|  | 2344 | } | 
|  | 2345 |  | 
|  | 2346 | bool validateCRAlgo(std::vector<uint8_t>& conf, uint8_t num) | 
|  | 2347 | { | 
|  | 2348 | if (conf.size() < num) | 
|  | 2349 | { | 
|  | 2350 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2351 | "Invalid PSU Ranking"); | 
|  | 2352 | return false; | 
|  | 2353 | } | 
|  | 2354 | std::set<uint8_t> confSet; | 
|  | 2355 | for (uint8_t i = 0; i < num; i++) | 
|  | 2356 | { | 
|  | 2357 | if (conf[i] > num) | 
|  | 2358 | { | 
|  | 2359 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2360 | "PSU Ranking is larger than current PSU number"); | 
|  | 2361 | return false; | 
|  | 2362 | } | 
|  | 2363 | confSet.emplace(conf[i]); | 
|  | 2364 | } | 
|  | 2365 |  | 
|  | 2366 | if (confSet.size() != num) | 
|  | 2367 | { | 
|  | 2368 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2369 | "duplicate PSU Ranking"); | 
|  | 2370 | return false; | 
|  | 2371 | } | 
|  | 2372 | return true; | 
|  | 2373 | } | 
|  | 2374 |  | 
|  | 2375 | enum class crParameter | 
|  | 2376 | { | 
|  | 2377 | crStatus = 0, | 
|  | 2378 | crFeature = 1, | 
|  | 2379 | rotationFeature = 2, | 
|  | 2380 | rotationAlgo = 3, | 
|  | 2381 | rotationPeriod = 4, | 
| Yong Li | 19445ab | 2019-12-20 18:25:29 +0800 | [diff] [blame] | 2382 | numOfPSU = 5, | 
|  | 2383 | rotationRankOrderEffective = 6 | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2384 | }; | 
|  | 2385 |  | 
|  | 2386 | constexpr ipmi::Cc ccParameterNotSupported = 0x80; | 
|  | 2387 | static const constexpr uint32_t oneDay = 0x15180; | 
|  | 2388 | static const constexpr uint32_t oneMonth = 0xf53700; | 
|  | 2389 | static const constexpr uint8_t userSpecific = 0x01; | 
|  | 2390 | static const constexpr uint8_t crSetCompleted = 0; | 
|  | 2391 | ipmi::RspType<uint8_t> ipmiOEMSetCRConfig(ipmi::Context::ptr ctx, | 
|  | 2392 | uint8_t parameter, | 
|  | 2393 | ipmi::message::Payload& payload) | 
|  | 2394 | { | 
|  | 2395 | switch (static_cast<crParameter>(parameter)) | 
|  | 2396 | { | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2397 | case crParameter::rotationFeature: | 
|  | 2398 | { | 
|  | 2399 | uint8_t param1; | 
|  | 2400 | if (payload.unpack(param1) || !payload.fullyUnpacked()) | 
|  | 2401 | { | 
|  | 2402 | return ipmi::responseReqDataLenInvalid(); | 
|  | 2403 | } | 
|  | 2404 | // Rotation Enable can only be true or false | 
|  | 2405 | if (param1 > 1) | 
|  | 2406 | { | 
|  | 2407 | return ipmi::responseInvalidFieldRequest(); | 
|  | 2408 | } | 
|  | 2409 | if (setCRConfig(ctx, "RotationEnabled", static_cast<bool>(param1))) | 
|  | 2410 | { | 
|  | 2411 | return ipmi::responseResponseError(); | 
|  | 2412 | } | 
|  | 2413 | break; | 
|  | 2414 | } | 
|  | 2415 | case crParameter::rotationAlgo: | 
|  | 2416 | { | 
|  | 2417 | // Rotation Algorithm can only be 0-BMC Specific or 1-User Specific | 
|  | 2418 | std::string algoName; | 
|  | 2419 | uint8_t param1; | 
|  | 2420 | if (payload.unpack(param1)) | 
|  | 2421 | { | 
|  | 2422 | return ipmi::responseReqDataLenInvalid(); | 
|  | 2423 | } | 
|  | 2424 | switch (param1) | 
|  | 2425 | { | 
|  | 2426 | case 0: | 
|  | 2427 | algoName = "xyz.openbmc_project.Control." | 
|  | 2428 | "PowerSupplyRedundancy.Algo.bmcSpecific"; | 
|  | 2429 | break; | 
|  | 2430 | case 1: | 
|  | 2431 | algoName = "xyz.openbmc_project.Control." | 
|  | 2432 | "PowerSupplyRedundancy.Algo.userSpecific"; | 
|  | 2433 | break; | 
|  | 2434 | default: | 
|  | 2435 | return ipmi::responseInvalidFieldRequest(); | 
|  | 2436 | } | 
|  | 2437 | if (setCRConfig(ctx, "RotationAlgorithm", algoName)) | 
|  | 2438 | { | 
|  | 2439 | return ipmi::responseResponseError(); | 
|  | 2440 | } | 
|  | 2441 |  | 
|  | 2442 | uint8_t numberOfPSU = getPSUCount(); | 
|  | 2443 | if (!numberOfPSU) | 
|  | 2444 | { | 
|  | 2445 | return ipmi::responseResponseError(); | 
|  | 2446 | } | 
|  | 2447 | std::vector<uint8_t> rankOrder; | 
|  | 2448 |  | 
|  | 2449 | if (param1 == userSpecific) | 
|  | 2450 | { | 
|  | 2451 | if (payload.unpack(rankOrder) || !payload.fullyUnpacked()) | 
|  | 2452 | { | 
|  | 2453 | ipmi::responseReqDataLenInvalid(); | 
|  | 2454 | } | 
| Yong Li | 8331513 | 2019-10-23 17:42:24 +0800 | [diff] [blame] | 2455 | if (rankOrder.size() != numberOfPSU) | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2456 | { | 
|  | 2457 | return ipmi::responseReqDataLenInvalid(); | 
|  | 2458 | } | 
|  | 2459 |  | 
|  | 2460 | if (!validateCRAlgo(rankOrder, numberOfPSU)) | 
|  | 2461 | { | 
|  | 2462 | return ipmi::responseInvalidFieldRequest(); | 
|  | 2463 | } | 
|  | 2464 | } | 
|  | 2465 | else | 
|  | 2466 | { | 
|  | 2467 | if (rankOrder.size() > 0) | 
|  | 2468 | { | 
|  | 2469 | return ipmi::responseReqDataLenInvalid(); | 
|  | 2470 | } | 
|  | 2471 | for (uint8_t i = 1; i <= numberOfPSU; i++) | 
|  | 2472 | { | 
|  | 2473 | rankOrder.emplace_back(i); | 
|  | 2474 | } | 
|  | 2475 | } | 
|  | 2476 | if (setCRConfig(ctx, "RotationRankOrder", rankOrder)) | 
|  | 2477 | { | 
|  | 2478 | return ipmi::responseResponseError(); | 
|  | 2479 | } | 
|  | 2480 | break; | 
|  | 2481 | } | 
|  | 2482 | case crParameter::rotationPeriod: | 
|  | 2483 | { | 
|  | 2484 | // Minimum Rotation period is  One day (86400 seconds) and Max | 
|  | 2485 | // Rotation Period is 6 month (0xf53700 seconds) | 
|  | 2486 | uint32_t period; | 
|  | 2487 | if (payload.unpack(period) || !payload.fullyUnpacked()) | 
|  | 2488 | { | 
|  | 2489 | return ipmi::responseReqDataLenInvalid(); | 
|  | 2490 | } | 
|  | 2491 | if ((period < oneDay) || (period > oneMonth)) | 
|  | 2492 | { | 
|  | 2493 | return ipmi::responseInvalidFieldRequest(); | 
|  | 2494 | } | 
|  | 2495 | if (setCRConfig(ctx, "PeriodOfRotation", period)) | 
|  | 2496 | { | 
|  | 2497 | return ipmi::responseResponseError(); | 
|  | 2498 | } | 
|  | 2499 | break; | 
|  | 2500 | } | 
|  | 2501 | default: | 
|  | 2502 | { | 
|  | 2503 | return ipmi::response(ccParameterNotSupported); | 
|  | 2504 | } | 
|  | 2505 | } | 
|  | 2506 |  | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2507 | return ipmi::responseSuccess(crSetCompleted); | 
|  | 2508 | } | 
|  | 2509 |  | 
| Yong Li | 8331513 | 2019-10-23 17:42:24 +0800 | [diff] [blame] | 2510 | ipmi::RspType<uint8_t, std::variant<uint8_t, uint32_t, std::vector<uint8_t>>> | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2511 | ipmiOEMGetCRConfig(ipmi::Context::ptr ctx, uint8_t parameter) | 
|  | 2512 | { | 
|  | 2513 | crConfigVariant value; | 
|  | 2514 | switch (static_cast<crParameter>(parameter)) | 
|  | 2515 | { | 
|  | 2516 | case crParameter::crStatus: | 
|  | 2517 | { | 
|  | 2518 | if (getCRConfig(ctx, "ColdRedundancyStatus", value)) | 
|  | 2519 | { | 
|  | 2520 | return ipmi::responseResponseError(); | 
|  | 2521 | } | 
|  | 2522 | std::string* pStatus = std::get_if<std::string>(&value); | 
|  | 2523 | if (!pStatus) | 
|  | 2524 | { | 
|  | 2525 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2526 | "Error to get ColdRedundancyStatus property"); | 
|  | 2527 | return ipmi::responseResponseError(); | 
|  | 2528 | } | 
|  | 2529 | namespace server = sdbusplus::xyz::openbmc_project::Control::server; | 
|  | 2530 | auto status = | 
|  | 2531 | server::PowerSupplyRedundancy::convertStatusFromString( | 
|  | 2532 | *pStatus); | 
|  | 2533 | switch (status) | 
|  | 2534 | { | 
|  | 2535 | case server::PowerSupplyRedundancy::Status::inProgress: | 
| Cheng C Yang | f41e334 | 2019-09-10 04:47:23 +0800 | [diff] [blame] | 2536 | return ipmi::responseSuccess(parameter, | 
| Kuiying Wang | e45333a | 2020-07-22 22:06:37 +0800 | [diff] [blame] | 2537 | static_cast<uint8_t>(1)); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2538 |  | 
|  | 2539 | case server::PowerSupplyRedundancy::Status::completed: | 
| Cheng C Yang | f41e334 | 2019-09-10 04:47:23 +0800 | [diff] [blame] | 2540 | return ipmi::responseSuccess(parameter, | 
| Kuiying Wang | e45333a | 2020-07-22 22:06:37 +0800 | [diff] [blame] | 2541 | static_cast<uint8_t>(0)); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2542 | default: | 
|  | 2543 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2544 | "Error to get valid status"); | 
|  | 2545 | return ipmi::responseResponseError(); | 
|  | 2546 | } | 
|  | 2547 | } | 
|  | 2548 | case crParameter::crFeature: | 
|  | 2549 | { | 
| Kuiying Wang | e45333a | 2020-07-22 22:06:37 +0800 | [diff] [blame] | 2550 | if (getCRConfig(ctx, "PowerSupplyRedundancyEnabled", value)) | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2551 | { | 
|  | 2552 | return ipmi::responseResponseError(); | 
|  | 2553 | } | 
|  | 2554 | bool* pResponse = std::get_if<bool>(&value); | 
|  | 2555 | if (!pResponse) | 
|  | 2556 | { | 
|  | 2557 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
| Kuiying Wang | e45333a | 2020-07-22 22:06:37 +0800 | [diff] [blame] | 2558 | "Error to get PowerSupplyRedundancyEnabled property"); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2559 | return ipmi::responseResponseError(); | 
|  | 2560 | } | 
|  | 2561 |  | 
| Cheng C Yang | f41e334 | 2019-09-10 04:47:23 +0800 | [diff] [blame] | 2562 | return ipmi::responseSuccess(parameter, | 
|  | 2563 | static_cast<uint8_t>(*pResponse)); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2564 | } | 
|  | 2565 | case crParameter::rotationFeature: | 
|  | 2566 | { | 
|  | 2567 | if (getCRConfig(ctx, "RotationEnabled", value)) | 
|  | 2568 | { | 
|  | 2569 | return ipmi::responseResponseError(); | 
|  | 2570 | } | 
|  | 2571 | bool* pResponse = std::get_if<bool>(&value); | 
|  | 2572 | if (!pResponse) | 
|  | 2573 | { | 
|  | 2574 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2575 | "Error to get RotationEnabled property"); | 
|  | 2576 | return ipmi::responseResponseError(); | 
|  | 2577 | } | 
| Cheng C Yang | f41e334 | 2019-09-10 04:47:23 +0800 | [diff] [blame] | 2578 | return ipmi::responseSuccess(parameter, | 
|  | 2579 | static_cast<uint8_t>(*pResponse)); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2580 | } | 
|  | 2581 | case crParameter::rotationAlgo: | 
|  | 2582 | { | 
|  | 2583 | if (getCRConfig(ctx, "RotationAlgorithm", value)) | 
|  | 2584 | { | 
|  | 2585 | return ipmi::responseResponseError(); | 
|  | 2586 | } | 
|  | 2587 |  | 
|  | 2588 | std::string* pAlgo = std::get_if<std::string>(&value); | 
|  | 2589 | if (!pAlgo) | 
|  | 2590 | { | 
|  | 2591 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2592 | "Error to get RotationAlgorithm property"); | 
|  | 2593 | return ipmi::responseResponseError(); | 
|  | 2594 | } | 
| Yong Li | 8331513 | 2019-10-23 17:42:24 +0800 | [diff] [blame] | 2595 | std::vector<uint8_t> response; | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2596 | namespace server = sdbusplus::xyz::openbmc_project::Control::server; | 
|  | 2597 | auto algo = | 
|  | 2598 | server::PowerSupplyRedundancy::convertAlgoFromString(*pAlgo); | 
| Yong Li | 8331513 | 2019-10-23 17:42:24 +0800 | [diff] [blame] | 2599 |  | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2600 | switch (algo) | 
|  | 2601 | { | 
|  | 2602 | case server::PowerSupplyRedundancy::Algo::bmcSpecific: | 
| Yong Li | 8331513 | 2019-10-23 17:42:24 +0800 | [diff] [blame] | 2603 | response.push_back(0); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2604 | break; | 
|  | 2605 | case server::PowerSupplyRedundancy::Algo::userSpecific: | 
| Yong Li | 8331513 | 2019-10-23 17:42:24 +0800 | [diff] [blame] | 2606 | response.push_back(1); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2607 | break; | 
|  | 2608 | default: | 
|  | 2609 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2610 | "Error to get valid algo"); | 
|  | 2611 | return ipmi::responseResponseError(); | 
|  | 2612 | } | 
|  | 2613 |  | 
|  | 2614 | if (getCRConfig(ctx, "RotationRankOrder", value)) | 
|  | 2615 | { | 
|  | 2616 | return ipmi::responseResponseError(); | 
|  | 2617 | } | 
|  | 2618 | std::vector<uint8_t>* pResponse = | 
|  | 2619 | std::get_if<std::vector<uint8_t>>(&value); | 
|  | 2620 | if (!pResponse) | 
|  | 2621 | { | 
|  | 2622 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2623 | "Error to get RotationRankOrder property"); | 
|  | 2624 | return ipmi::responseResponseError(); | 
|  | 2625 | } | 
| Yong Li | 8331513 | 2019-10-23 17:42:24 +0800 | [diff] [blame] | 2626 |  | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2627 | std::copy(pResponse->begin(), pResponse->end(), | 
| Yong Li | 8331513 | 2019-10-23 17:42:24 +0800 | [diff] [blame] | 2628 | std::back_inserter(response)); | 
|  | 2629 |  | 
| Cheng C Yang | f41e334 | 2019-09-10 04:47:23 +0800 | [diff] [blame] | 2630 | return ipmi::responseSuccess(parameter, response); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2631 | } | 
|  | 2632 | case crParameter::rotationPeriod: | 
|  | 2633 | { | 
|  | 2634 | if (getCRConfig(ctx, "PeriodOfRotation", value)) | 
|  | 2635 | { | 
|  | 2636 | return ipmi::responseResponseError(); | 
|  | 2637 | } | 
|  | 2638 | uint32_t* pResponse = std::get_if<uint32_t>(&value); | 
|  | 2639 | if (!pResponse) | 
|  | 2640 | { | 
|  | 2641 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2642 | "Error to get RotationAlgorithm property"); | 
|  | 2643 | return ipmi::responseResponseError(); | 
|  | 2644 | } | 
| Cheng C Yang | f41e334 | 2019-09-10 04:47:23 +0800 | [diff] [blame] | 2645 | return ipmi::responseSuccess(parameter, *pResponse); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2646 | } | 
|  | 2647 | case crParameter::numOfPSU: | 
|  | 2648 | { | 
|  | 2649 | uint8_t numberOfPSU = getPSUCount(); | 
|  | 2650 | if (!numberOfPSU) | 
|  | 2651 | { | 
|  | 2652 | return ipmi::responseResponseError(); | 
|  | 2653 | } | 
| Cheng C Yang | f41e334 | 2019-09-10 04:47:23 +0800 | [diff] [blame] | 2654 | return ipmi::responseSuccess(parameter, numberOfPSU); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2655 | } | 
| Yong Li | 19445ab | 2019-12-20 18:25:29 +0800 | [diff] [blame] | 2656 | case crParameter::rotationRankOrderEffective: | 
|  | 2657 | { | 
|  | 2658 | if (getCRConfig(ctx, "RotationRankOrder", value, | 
|  | 2659 | "xyz.openbmc_project.PSURedundancy")) | 
|  | 2660 | { | 
|  | 2661 | return ipmi::responseResponseError(); | 
|  | 2662 | } | 
|  | 2663 | std::vector<uint8_t>* pResponse = | 
|  | 2664 | std::get_if<std::vector<uint8_t>>(&value); | 
|  | 2665 | if (!pResponse) | 
|  | 2666 | { | 
|  | 2667 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2668 | "Error to get effective RotationRankOrder property"); | 
|  | 2669 | return ipmi::responseResponseError(); | 
|  | 2670 | } | 
|  | 2671 | return ipmi::responseSuccess(parameter, *pResponse); | 
|  | 2672 | } | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 2673 | default: | 
|  | 2674 | { | 
|  | 2675 | return ipmi::response(ccParameterNotSupported); | 
|  | 2676 | } | 
|  | 2677 | } | 
|  | 2678 | } | 
|  | 2679 |  | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2680 | ipmi::RspType<> ipmiOEMSetFaultIndication(uint8_t sourceId, uint8_t faultType, | 
|  | 2681 | uint8_t faultState, | 
|  | 2682 | uint8_t faultGroup, | 
|  | 2683 | std::array<uint8_t, 8>& ledStateData) | 
|  | 2684 | { | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2685 | constexpr auto maxFaultType = static_cast<size_t>(RemoteFaultType::max); | 
|  | 2686 | static const std::array<std::string, maxFaultType> faultNames = { | 
|  | 2687 | "faultFan",       "faultTemp",     "faultPower", | 
|  | 2688 | "faultDriveSlot", "faultSoftware", "faultMemory"}; | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2689 |  | 
|  | 2690 | constexpr uint8_t maxFaultSource = 0x4; | 
|  | 2691 | constexpr uint8_t skipLEDs = 0xFF; | 
|  | 2692 | constexpr uint8_t pinSize = 64; | 
|  | 2693 | constexpr uint8_t groupSize = 16; | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2694 | constexpr uint8_t groupNum = 5; // 4 for fault memory, 1 for faultFan | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2695 |  | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2696 | // same pin names need to be defined in dts file | 
|  | 2697 | static const std::array<std::array<std::string, groupSize>, groupNum> | 
|  | 2698 | faultLedPinNames = {{ | 
|  | 2699 | "LED_CPU1_CH1_DIMM1_FAULT", | 
|  | 2700 | "LED_CPU1_CH1_DIMM2_FAULT", | 
|  | 2701 | "LED_CPU1_CH2_DIMM1_FAULT", | 
|  | 2702 | "LED_CPU1_CH2_DIMM2_FAULT", | 
|  | 2703 | "LED_CPU1_CH3_DIMM1_FAULT", | 
|  | 2704 | "LED_CPU1_CH3_DIMM2_FAULT", | 
|  | 2705 | "LED_CPU1_CH4_DIMM1_FAULT", | 
|  | 2706 | "LED_CPU1_CH4_DIMM2_FAULT", | 
|  | 2707 | "LED_CPU1_CH5_DIMM1_FAULT", | 
|  | 2708 | "LED_CPU1_CH5_DIMM2_FAULT", | 
|  | 2709 | "LED_CPU1_CH6_DIMM1_FAULT", | 
|  | 2710 | "LED_CPU1_CH6_DIMM2_FAULT", | 
|  | 2711 | "", | 
|  | 2712 | "", | 
|  | 2713 | "", | 
|  | 2714 | "", // end of group1 | 
|  | 2715 | "LED_CPU2_CH1_DIMM1_FAULT", | 
|  | 2716 | "LED_CPU2_CH1_DIMM2_FAULT", | 
|  | 2717 | "LED_CPU2_CH2_DIMM1_FAULT", | 
|  | 2718 | "LED_CPU2_CH2_DIMM2_FAULT", | 
|  | 2719 | "LED_CPU2_CH3_DIMM1_FAULT", | 
|  | 2720 | "LED_CPU2_CH3_DIMM2_FAULT", | 
|  | 2721 | "LED_CPU2_CH4_DIMM1_FAULT", | 
|  | 2722 | "LED_CPU2_CH4_DIMM2_FAULT", | 
|  | 2723 | "LED_CPU2_CH5_DIMM1_FAULT", | 
|  | 2724 | "LED_CPU2_CH5_DIMM2_FAULT", | 
|  | 2725 | "LED_CPU2_CH6_DIMM1_FAULT", | 
|  | 2726 | "LED_CPU2_CH6_DIMM2_FAULT", | 
|  | 2727 | "", | 
|  | 2728 | "", | 
|  | 2729 | "", | 
|  | 2730 | "", // endof group2 | 
|  | 2731 | "LED_CPU3_CH1_DIMM1_FAULT", | 
|  | 2732 | "LED_CPU3_CH1_DIMM2_FAULT", | 
|  | 2733 | "LED_CPU3_CH2_DIMM1_FAULT", | 
|  | 2734 | "LED_CPU3_CH2_DIMM2_FAULT", | 
|  | 2735 | "LED_CPU3_CH3_DIMM1_FAULT", | 
|  | 2736 | "LED_CPU3_CH3_DIMM2_FAULT", | 
|  | 2737 | "LED_CPU3_CH4_DIMM1_FAULT", | 
|  | 2738 | "LED_CPU3_CH4_DIMM2_FAULT", | 
|  | 2739 | "LED_CPU3_CH5_DIMM1_FAULT", | 
|  | 2740 | "LED_CPU3_CH5_DIMM2_FAULT", | 
|  | 2741 | "LED_CPU3_CH6_DIMM1_FAULT", | 
|  | 2742 | "LED_CPU3_CH6_DIMM2_FAULT", | 
|  | 2743 | "", | 
|  | 2744 | "", | 
|  | 2745 | "", | 
|  | 2746 | "", // end of group3 | 
|  | 2747 | "LED_CPU4_CH1_DIMM1_FAULT", | 
|  | 2748 | "LED_CPU4_CH1_DIMM2_FAULT", | 
|  | 2749 | "LED_CPU4_CH2_DIMM1_FAULT", | 
|  | 2750 | "LED_CPU4_CH2_DIMM2_FAULT", | 
|  | 2751 | "LED_CPU4_CH3_DIMM1_FAULT", | 
|  | 2752 | "LED_CPU4_CH3_DIMM2_FAULT", | 
|  | 2753 | "LED_CPU4_CH4_DIMM1_FAULT", | 
|  | 2754 | "LED_CPU4_CH4_DIMM2_FAULT", | 
|  | 2755 | "LED_CPU4_CH5_DIMM1_FAULT", | 
|  | 2756 | "LED_CPU4_CH5_DIMM2_FAULT", | 
|  | 2757 | "LED_CPU4_CH6_DIMM1_FAULT", | 
|  | 2758 | "LED_CPU4_CH6_DIMM2_FAULT", | 
|  | 2759 | "", | 
|  | 2760 | "", | 
|  | 2761 | "", | 
|  | 2762 | "", // end of group4 | 
|  | 2763 | "LED_FAN1_FAULT", | 
|  | 2764 | "LED_FAN2_FAULT", | 
|  | 2765 | "LED_FAN3_FAULT", | 
|  | 2766 | "LED_FAN4_FAULT", | 
|  | 2767 | "LED_FAN5_FAULT", | 
|  | 2768 | "LED_FAN6_FAULT", | 
|  | 2769 | "LED_FAN7_FAULT", | 
|  | 2770 | "LED_FAN8_FAULT", | 
|  | 2771 | "", | 
|  | 2772 | "", | 
|  | 2773 | "", | 
|  | 2774 | "", | 
|  | 2775 | "", | 
|  | 2776 | "", | 
|  | 2777 | "", | 
|  | 2778 | "" // end of group5 | 
|  | 2779 | }}; | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2780 |  | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2781 | // Validate the source, fault type -- | 
|  | 2782 | // (Byte 1) sourceId: Unspecified, Hot-Swap Controller 0, Hot-Swap | 
|  | 2783 | // Controller 1, BIOS (Byte 2) fault type: fan, temperature, power, | 
|  | 2784 | // driveslot, software, memory (Byte 3) FaultState: OK, Degraded, | 
|  | 2785 | // Non-Critical, Critical, Non-Recoverable, (Byte 4) is faultGroup, | 
|  | 2786 | // definition differs based on fault type (Byte 2) | 
|  | 2787 | //          Type Fan=> Group: 0=FanGroupID, FF-not used | 
|  | 2788 | //                  Byte 5-11 00h, not used | 
|  | 2789 | //                  Byte12 FanLedState [7:0]-Fans 7:0 | 
|  | 2790 | //          Type Memory=> Group: 0 = DIMM GroupID, FF-not used | 
|  | 2791 | //                  Byte 5:12 - DIMM LED state (64bit field, LS Byte first) | 
|  | 2792 | //                  [63:48] = CPU4 channels 7:0, 2 bits per channel | 
|  | 2793 | //                  [47:32] = CPU3 channels 7:0, 2 bits per channel | 
|  | 2794 | //                  [31:16] = CPU2 channels 7:0, 2 bits per channel | 
|  | 2795 | //                  [15:0] =  CPU1 channels 7:0, 2 bits per channel | 
|  | 2796 | //          Type Other=> Component Fault LED Group ID, not used set to 0xFF | 
|  | 2797 | //                  Byte[5:12]: reserved 0x00h | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2798 | if ((sourceId >= maxFaultSource) || | 
|  | 2799 | (faultType >= static_cast<int8_t>(RemoteFaultType::max)) || | 
|  | 2800 | (faultState >= static_cast<int8_t>(RemoteFaultState::maxFaultState)) || | 
|  | 2801 | (faultGroup >= static_cast<int8_t>(DimmFaultType::maxFaultGroup))) | 
|  | 2802 | { | 
|  | 2803 | return ipmi::responseParmOutOfRange(); | 
|  | 2804 | } | 
|  | 2805 |  | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2806 | size_t pinGroupOffset = 0; | 
|  | 2807 | size_t pinGroupMax = pinSize / groupSize; | 
|  | 2808 | if (RemoteFaultType::fan == RemoteFaultType(faultType)) | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2809 | { | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2810 | pinGroupOffset = 4; | 
|  | 2811 | pinGroupMax = groupNum - pinSize / groupSize; | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2812 | } | 
|  | 2813 |  | 
|  | 2814 | switch (RemoteFaultType(faultType)) | 
|  | 2815 | { | 
|  | 2816 | case (RemoteFaultType::fan): | 
|  | 2817 | case (RemoteFaultType::memory): | 
|  | 2818 | { | 
|  | 2819 | if (faultGroup == skipLEDs) | 
|  | 2820 | { | 
|  | 2821 | return ipmi::responseSuccess(); | 
|  | 2822 | } | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2823 | // calculate led state bit filed count, each byte has 8bits | 
|  | 2824 | // the maximum bits will be 8 * 8 bits | 
|  | 2825 | constexpr uint8_t size = sizeof(ledStateData) * 8; | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2826 |  | 
|  | 2827 | // assemble ledState | 
|  | 2828 | uint64_t ledState = 0; | 
|  | 2829 | bool hasError = false; | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2830 | for (int i = 0; i < sizeof(ledStateData); i++) | 
|  | 2831 | { | 
|  | 2832 | ledState = (uint64_t)(ledState << 8); | 
|  | 2833 | ledState = (uint64_t)(ledState | (uint64_t)ledStateData[i]); | 
|  | 2834 | } | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2835 | std::bitset<size> ledStateBits(ledState); | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2836 |  | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2837 | for (int group = 0; group < pinGroupMax; group++) | 
|  | 2838 | { | 
|  | 2839 | for (int i = 0; i < groupSize; i++) | 
|  | 2840 | { // skip non-existing pins | 
|  | 2841 | if (0 == faultLedPinNames[group + pinGroupOffset][i].size()) | 
|  | 2842 | { | 
|  | 2843 | continue; | 
|  | 2844 | } | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2845 |  | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2846 | gpiod::line line = gpiod::find_line( | 
|  | 2847 | faultLedPinNames[group + pinGroupOffset][i]); | 
|  | 2848 | if (!line) | 
|  | 2849 | { | 
|  | 2850 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2851 | "Not Find Led Gpio Device!", | 
|  | 2852 | phosphor::logging::entry( | 
|  | 2853 | "DEVICE=%s", | 
|  | 2854 | faultLedPinNames[group + pinGroupOffset][i] | 
|  | 2855 | .c_str())); | 
|  | 2856 | hasError = true; | 
|  | 2857 | continue; | 
|  | 2858 | } | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2859 |  | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2860 | bool activeHigh = | 
|  | 2861 | (line.active_state() == gpiod::line::ACTIVE_HIGH); | 
|  | 2862 | try | 
|  | 2863 | { | 
|  | 2864 | line.request( | 
|  | 2865 | {"faultLed", gpiod::line_request::DIRECTION_OUTPUT, | 
|  | 2866 | activeHigh | 
|  | 2867 | ? 0 | 
|  | 2868 | : gpiod::line_request::FLAG_ACTIVE_LOW}); | 
|  | 2869 | line.set_value(ledStateBits[i + group * groupSize]); | 
|  | 2870 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 2871 | catch (const std::system_error&) | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2872 | { | 
|  | 2873 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2874 | "Error write Led Gpio Device!", | 
|  | 2875 | phosphor::logging::entry( | 
|  | 2876 | "DEVICE=%s", | 
|  | 2877 | faultLedPinNames[group + pinGroupOffset][i] | 
|  | 2878 | .c_str())); | 
|  | 2879 | hasError = true; | 
|  | 2880 | continue; | 
|  | 2881 | } | 
|  | 2882 | } // for int i | 
|  | 2883 | } | 
|  | 2884 | if (hasError) | 
|  | 2885 | { | 
|  | 2886 | return ipmi::responseResponseError(); | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2887 | } | 
|  | 2888 | break; | 
|  | 2889 | } | 
|  | 2890 | default: | 
|  | 2891 | { | 
|  | 2892 | // now only support two fault types | 
|  | 2893 | return ipmi::responseParmOutOfRange(); | 
|  | 2894 | } | 
| Zhikui Ren | ce4e73f | 2019-12-06 13:59:47 -0800 | [diff] [blame] | 2895 | } // switch | 
| Zhu, Yunge | be560b0 | 2019-04-21 21:19:21 -0400 | [diff] [blame] | 2896 | return ipmi::responseSuccess(); | 
|  | 2897 | } | 
|  | 2898 |  | 
| Richard Marian Thomaiyar | ea537d5 | 2019-04-24 21:33:48 +0530 | [diff] [blame] | 2899 | ipmi::RspType<uint8_t> ipmiOEMReadBoardProductId() | 
|  | 2900 | { | 
|  | 2901 | uint8_t prodId = 0; | 
|  | 2902 | try | 
|  | 2903 | { | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2904 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
| Richard Marian Thomaiyar | ea537d5 | 2019-04-24 21:33:48 +0530 | [diff] [blame] | 2905 | const DbusObjectInfo& object = getDbusObject( | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2906 | *dbus, "xyz.openbmc_project.Inventory.Item.Board", | 
| Richard Marian Thomaiyar | ea537d5 | 2019-04-24 21:33:48 +0530 | [diff] [blame] | 2907 | "/xyz/openbmc_project/inventory/system/board/", "Baseboard"); | 
|  | 2908 | const Value& propValue = getDbusProperty( | 
| Vernon Mauery | 15419dd | 2019-05-24 09:40:30 -0700 | [diff] [blame] | 2909 | *dbus, object.second, object.first, | 
| Suryakanth Sekar | 6c57e5c | 2020-01-10 17:11:58 +0530 | [diff] [blame] | 2910 | "xyz.openbmc_project.Inventory.Item.Board.Motherboard", | 
|  | 2911 | "ProductId"); | 
| Richard Marian Thomaiyar | ea537d5 | 2019-04-24 21:33:48 +0530 | [diff] [blame] | 2912 | prodId = static_cast<uint8_t>(std::get<uint64_t>(propValue)); | 
|  | 2913 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 2914 | catch (const std::exception& e) | 
| Richard Marian Thomaiyar | ea537d5 | 2019-04-24 21:33:48 +0530 | [diff] [blame] | 2915 | { | 
|  | 2916 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2917 | "ipmiOEMReadBoardProductId: Product ID read failed!", | 
|  | 2918 | phosphor::logging::entry("ERR=%s", e.what())); | 
|  | 2919 | } | 
|  | 2920 | return ipmi::responseSuccess(prodId); | 
|  | 2921 | } | 
|  | 2922 |  | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 2923 | /** @brief implements the get security mode command | 
|  | 2924 | *  @param ctx - ctx pointer | 
|  | 2925 | * | 
|  | 2926 | *  @returns IPMI completion code with following data | 
|  | 2927 | *   - restriction mode value - As specified in | 
|  | 2928 | * xyz.openbmc_project.Control.Security.RestrictionMode.interface.yaml | 
|  | 2929 | *   - special mode value - As specified in | 
|  | 2930 | * xyz.openbmc_project.Control.Security.SpecialMode.interface.yaml | 
|  | 2931 | */ | 
|  | 2932 | ipmi::RspType<uint8_t, uint8_t> ipmiGetSecurityMode(ipmi::Context::ptr ctx) | 
|  | 2933 | { | 
|  | 2934 | namespace securityNameSpace = | 
|  | 2935 | sdbusplus::xyz::openbmc_project::Control::Security::server; | 
|  | 2936 | uint8_t restrictionModeValue = 0; | 
|  | 2937 | uint8_t specialModeValue = 0; | 
|  | 2938 |  | 
|  | 2939 | boost::system::error_code ec; | 
|  | 2940 | auto varRestrMode = ctx->bus->yield_method_call<std::variant<std::string>>( | 
| James Feist | 28c7290 | 2019-09-16 10:34:07 -0700 | [diff] [blame] | 2941 | ctx->yield, ec, restricionModeService, restricionModeBasePath, | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 2942 | dBusPropertyIntf, dBusPropertyGetMethod, restricionModeIntf, | 
|  | 2943 | restricionModeProperty); | 
|  | 2944 | if (ec) | 
|  | 2945 | { | 
|  | 2946 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2947 | "ipmiGetSecurityMode: failed to get RestrictionMode property", | 
|  | 2948 | phosphor::logging::entry("ERROR=%s", ec.message().c_str())); | 
|  | 2949 | return ipmi::responseUnspecifiedError(); | 
|  | 2950 | } | 
|  | 2951 | restrictionModeValue = static_cast<uint8_t>( | 
|  | 2952 | securityNameSpace::RestrictionMode::convertModesFromString( | 
|  | 2953 | std::get<std::string>(varRestrMode))); | 
| Richard Marian Thomaiyar | 8d4f8d7 | 2019-11-11 12:06:40 +0530 | [diff] [blame] | 2954 | auto varSpecialMode = | 
|  | 2955 | ctx->bus->yield_method_call<std::variant<std::string>>( | 
|  | 2956 | ctx->yield, ec, specialModeService, specialModeBasePath, | 
|  | 2957 | dBusPropertyIntf, dBusPropertyGetMethod, specialModeIntf, | 
|  | 2958 | specialModeProperty); | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 2959 | if (ec) | 
|  | 2960 | { | 
|  | 2961 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 2962 | "ipmiGetSecurityMode: failed to get SpecialMode property", | 
|  | 2963 | phosphor::logging::entry("ERROR=%s", ec.message().c_str())); | 
|  | 2964 | // fall through, let us not worry about SpecialMode property, which is | 
|  | 2965 | // not required in user scenario | 
|  | 2966 | } | 
|  | 2967 | else | 
|  | 2968 | { | 
| Richard Marian Thomaiyar | 8d4f8d7 | 2019-11-11 12:06:40 +0530 | [diff] [blame] | 2969 | specialModeValue = static_cast<uint8_t>( | 
|  | 2970 | securityNameSpace::SpecialMode::convertModesFromString( | 
|  | 2971 | std::get<std::string>(varSpecialMode))); | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 2972 | } | 
|  | 2973 | return ipmi::responseSuccess(restrictionModeValue, specialModeValue); | 
|  | 2974 | } | 
|  | 2975 |  | 
|  | 2976 | /** @brief implements the set security mode command | 
|  | 2977 | *  Command allows to upgrade the restriction mode and won't allow | 
|  | 2978 | *  to downgrade from system interface | 
|  | 2979 | *  @param ctx - ctx pointer | 
|  | 2980 | *  @param restrictionMode - restriction mode value to be set. | 
|  | 2981 | * | 
|  | 2982 | *  @returns IPMI completion code | 
|  | 2983 | */ | 
|  | 2984 | ipmi::RspType<> ipmiSetSecurityMode(ipmi::Context::ptr ctx, | 
| Richard Marian Thomaiyar | 1079106 | 2019-11-11 12:19:53 +0530 | [diff] [blame] | 2985 | uint8_t restrictionMode, | 
|  | 2986 | std::optional<uint8_t> specialMode) | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 2987 | { | 
| Richard Marian Thomaiyar | 1079106 | 2019-11-11 12:19:53 +0530 | [diff] [blame] | 2988 | #ifndef BMC_VALIDATION_UNSECURE_FEATURE | 
|  | 2989 | if (specialMode) | 
|  | 2990 | { | 
|  | 2991 | return ipmi::responseReqDataLenInvalid(); | 
|  | 2992 | } | 
|  | 2993 | #endif | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 2994 | namespace securityNameSpace = | 
|  | 2995 | sdbusplus::xyz::openbmc_project::Control::Security::server; | 
|  | 2996 |  | 
|  | 2997 | ChannelInfo chInfo; | 
|  | 2998 | if (getChannelInfo(ctx->channel, chInfo) != ccSuccess) | 
|  | 2999 | { | 
|  | 3000 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3001 | "ipmiSetSecurityMode: Failed to get Channel Info", | 
|  | 3002 | phosphor::logging::entry("CHANNEL=%d", ctx->channel)); | 
|  | 3003 | return ipmi::responseUnspecifiedError(); | 
|  | 3004 | } | 
|  | 3005 | auto reqMode = | 
|  | 3006 | static_cast<securityNameSpace::RestrictionMode::Modes>(restrictionMode); | 
|  | 3007 |  | 
|  | 3008 | if ((reqMode < securityNameSpace::RestrictionMode::Modes::Provisioning) || | 
|  | 3009 | (reqMode > | 
|  | 3010 | securityNameSpace::RestrictionMode::Modes::ProvisionedHostDisabled)) | 
|  | 3011 | { | 
|  | 3012 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3013 | } | 
|  | 3014 |  | 
|  | 3015 | boost::system::error_code ec; | 
|  | 3016 | auto varRestrMode = ctx->bus->yield_method_call<std::variant<std::string>>( | 
| James Feist | 28c7290 | 2019-09-16 10:34:07 -0700 | [diff] [blame] | 3017 | ctx->yield, ec, restricionModeService, restricionModeBasePath, | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 3018 | dBusPropertyIntf, dBusPropertyGetMethod, restricionModeIntf, | 
|  | 3019 | restricionModeProperty); | 
|  | 3020 | if (ec) | 
|  | 3021 | { | 
|  | 3022 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3023 | "ipmiSetSecurityMode: failed to get RestrictionMode property", | 
|  | 3024 | phosphor::logging::entry("ERROR=%s", ec.message().c_str())); | 
|  | 3025 | return ipmi::responseUnspecifiedError(); | 
|  | 3026 | } | 
|  | 3027 | auto currentRestrictionMode = | 
|  | 3028 | securityNameSpace::RestrictionMode::convertModesFromString( | 
|  | 3029 | std::get<std::string>(varRestrMode)); | 
|  | 3030 |  | 
|  | 3031 | if (chInfo.mediumType != | 
|  | 3032 | static_cast<uint8_t>(EChannelMediumType::lan8032) && | 
|  | 3033 | currentRestrictionMode > reqMode) | 
|  | 3034 | { | 
|  | 3035 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3036 | "ipmiSetSecurityMode - Downgrading security mode not supported " | 
|  | 3037 | "through system interface", | 
|  | 3038 | phosphor::logging::entry( | 
|  | 3039 | "CUR_MODE=%d", static_cast<uint8_t>(currentRestrictionMode)), | 
|  | 3040 | phosphor::logging::entry("REQ_MODE=%d", restrictionMode)); | 
|  | 3041 | return ipmi::responseCommandNotAvailable(); | 
|  | 3042 | } | 
|  | 3043 |  | 
|  | 3044 | ec.clear(); | 
|  | 3045 | ctx->bus->yield_method_call<>( | 
| James Feist | 28c7290 | 2019-09-16 10:34:07 -0700 | [diff] [blame] | 3046 | ctx->yield, ec, restricionModeService, restricionModeBasePath, | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 3047 | dBusPropertyIntf, dBusPropertySetMethod, restricionModeIntf, | 
|  | 3048 | restricionModeProperty, | 
|  | 3049 | static_cast<std::variant<std::string>>( | 
|  | 3050 | securityNameSpace::convertForMessage(reqMode))); | 
|  | 3051 |  | 
|  | 3052 | if (ec) | 
|  | 3053 | { | 
|  | 3054 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3055 | "ipmiSetSecurityMode: failed to set RestrictionMode property", | 
|  | 3056 | phosphor::logging::entry("ERROR=%s", ec.message().c_str())); | 
|  | 3057 | return ipmi::responseUnspecifiedError(); | 
|  | 3058 | } | 
| Richard Marian Thomaiyar | 1079106 | 2019-11-11 12:19:53 +0530 | [diff] [blame] | 3059 |  | 
|  | 3060 | #ifdef BMC_VALIDATION_UNSECURE_FEATURE | 
|  | 3061 | if (specialMode) | 
|  | 3062 | { | 
| Jayaprakash Mutyala | d77489f | 2020-09-05 01:00:04 +0000 | [diff] [blame] | 3063 | constexpr uint8_t mfgMode = 0x01; | 
|  | 3064 | // Manufacturing mode is reserved. So can't enable this mode. | 
|  | 3065 | if (specialMode.value() == mfgMode) | 
|  | 3066 | { | 
|  | 3067 | phosphor::logging::log<phosphor::logging::level::INFO>( | 
|  | 3068 | "ipmiSetSecurityMode: Can't enable Manufacturing mode"); | 
|  | 3069 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3070 | } | 
|  | 3071 |  | 
| Richard Marian Thomaiyar | 1079106 | 2019-11-11 12:19:53 +0530 | [diff] [blame] | 3072 | ec.clear(); | 
|  | 3073 | ctx->bus->yield_method_call<>( | 
|  | 3074 | ctx->yield, ec, specialModeService, specialModeBasePath, | 
|  | 3075 | dBusPropertyIntf, dBusPropertySetMethod, specialModeIntf, | 
|  | 3076 | specialModeProperty, | 
|  | 3077 | static_cast<std::variant<std::string>>( | 
|  | 3078 | securityNameSpace::convertForMessage( | 
|  | 3079 | static_cast<securityNameSpace::SpecialMode::Modes>( | 
|  | 3080 | specialMode.value())))); | 
|  | 3081 |  | 
|  | 3082 | if (ec) | 
|  | 3083 | { | 
|  | 3084 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3085 | "ipmiSetSecurityMode: failed to set SpecialMode property", | 
|  | 3086 | phosphor::logging::entry("ERROR=%s", ec.message().c_str())); | 
|  | 3087 | return ipmi::responseUnspecifiedError(); | 
|  | 3088 | } | 
|  | 3089 | } | 
|  | 3090 | #endif | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 3091 | return ipmi::responseSuccess(); | 
|  | 3092 | } | 
|  | 3093 |  | 
| Vernon Mauery | 4ac799d | 2019-05-20 15:50:37 -0700 | [diff] [blame] | 3094 | ipmi::RspType<uint8_t /* restore status */> | 
|  | 3095 | ipmiRestoreConfiguration(const std::array<uint8_t, 3>& clr, uint8_t cmd) | 
|  | 3096 | { | 
|  | 3097 | static constexpr std::array<uint8_t, 3> expClr = {'C', 'L', 'R'}; | 
|  | 3098 |  | 
|  | 3099 | if (clr != expClr) | 
|  | 3100 | { | 
|  | 3101 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3102 | } | 
|  | 3103 | constexpr uint8_t cmdStatus = 0; | 
|  | 3104 | constexpr uint8_t cmdDefaultRestore = 0xaa; | 
|  | 3105 | constexpr uint8_t cmdFullRestore = 0xbb; | 
|  | 3106 | constexpr uint8_t cmdFormat = 0xcc; | 
|  | 3107 |  | 
|  | 3108 | constexpr const char* restoreOpFname = "/tmp/.rwfs/.restore_op"; | 
|  | 3109 |  | 
|  | 3110 | switch (cmd) | 
|  | 3111 | { | 
|  | 3112 | case cmdStatus: | 
|  | 3113 | break; | 
|  | 3114 | case cmdDefaultRestore: | 
|  | 3115 | case cmdFullRestore: | 
|  | 3116 | case cmdFormat: | 
|  | 3117 | { | 
|  | 3118 | // write file to rwfs root | 
|  | 3119 | int value = (cmd - 1) & 0x03; // map aa, bb, cc => 1, 2, 3 | 
|  | 3120 | std::ofstream restoreFile(restoreOpFname); | 
|  | 3121 | if (!restoreFile) | 
|  | 3122 | { | 
|  | 3123 | return ipmi::responseUnspecifiedError(); | 
|  | 3124 | } | 
|  | 3125 | restoreFile << value << "\n"; | 
| Arun P. Mohanan | ba1fbc8 | 2021-04-26 11:26:53 +0530 | [diff] [blame] | 3126 |  | 
|  | 3127 | phosphor::logging::log<phosphor::logging::level::WARNING>( | 
|  | 3128 | "Restore to default will be performed on next BMC boot", | 
|  | 3129 | phosphor::logging::entry("ACTION=0x%0X", cmd)); | 
|  | 3130 |  | 
| Vernon Mauery | 4ac799d | 2019-05-20 15:50:37 -0700 | [diff] [blame] | 3131 | break; | 
|  | 3132 | } | 
|  | 3133 | default: | 
|  | 3134 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3135 | } | 
|  | 3136 |  | 
|  | 3137 | constexpr uint8_t restorePending = 0; | 
|  | 3138 | constexpr uint8_t restoreComplete = 1; | 
|  | 3139 |  | 
|  | 3140 | uint8_t restoreStatus = std::filesystem::exists(restoreOpFname) | 
|  | 3141 | ? restorePending | 
|  | 3142 | : restoreComplete; | 
|  | 3143 | return ipmi::responseSuccess(restoreStatus); | 
|  | 3144 | } | 
|  | 3145 |  | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3146 | ipmi::RspType<uint8_t> ipmiOEMGetNmiSource(void) | 
|  | 3147 | { | 
|  | 3148 | uint8_t bmcSource; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3149 | namespace nmi = sdbusplus::xyz::openbmc_project::Chassis::Control::server; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3150 |  | 
|  | 3151 | try | 
|  | 3152 | { | 
|  | 3153 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 3154 | std::string service = | 
|  | 3155 | getService(*dbus, oemNmiSourceIntf, oemNmiSourceObjPath); | 
|  | 3156 | Value variant = | 
|  | 3157 | getDbusProperty(*dbus, service, oemNmiSourceObjPath, | 
|  | 3158 | oemNmiSourceIntf, oemNmiBmcSourceObjPathProp); | 
|  | 3159 |  | 
|  | 3160 | switch (nmi::NMISource::convertBMCSourceSignalFromString( | 
|  | 3161 | std::get<std::string>(variant))) | 
|  | 3162 | { | 
|  | 3163 | case nmi::NMISource::BMCSourceSignal::None: | 
|  | 3164 | bmcSource = static_cast<uint8_t>(NmiSource::none); | 
|  | 3165 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3166 | case nmi::NMISource::BMCSourceSignal::FrontPanelButton: | 
|  | 3167 | bmcSource = static_cast<uint8_t>(NmiSource::frontPanelButton); | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3168 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3169 | case nmi::NMISource::BMCSourceSignal::Watchdog: | 
|  | 3170 | bmcSource = static_cast<uint8_t>(NmiSource::watchdog); | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3171 | break; | 
|  | 3172 | case nmi::NMISource::BMCSourceSignal::ChassisCmd: | 
|  | 3173 | bmcSource = static_cast<uint8_t>(NmiSource::chassisCmd); | 
|  | 3174 | break; | 
|  | 3175 | case nmi::NMISource::BMCSourceSignal::MemoryError: | 
|  | 3176 | bmcSource = static_cast<uint8_t>(NmiSource::memoryError); | 
|  | 3177 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3178 | case nmi::NMISource::BMCSourceSignal::PciBusError: | 
|  | 3179 | bmcSource = static_cast<uint8_t>(NmiSource::pciBusError); | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3180 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3181 | case nmi::NMISource::BMCSourceSignal::PCH: | 
|  | 3182 | bmcSource = static_cast<uint8_t>(NmiSource::pch); | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3183 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3184 | case nmi::NMISource::BMCSourceSignal::Chipset: | 
|  | 3185 | bmcSource = static_cast<uint8_t>(NmiSource::chipset); | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3186 | break; | 
|  | 3187 | default: | 
|  | 3188 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3189 | "NMI source: invalid property!", | 
|  | 3190 | phosphor::logging::entry( | 
|  | 3191 | "PROP=%s", std::get<std::string>(variant).c_str())); | 
|  | 3192 | return ipmi::responseResponseError(); | 
|  | 3193 | } | 
|  | 3194 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 3195 | catch (const sdbusplus::exception::exception& e) | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3196 | { | 
|  | 3197 | phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); | 
|  | 3198 | return ipmi::responseResponseError(); | 
|  | 3199 | } | 
|  | 3200 |  | 
|  | 3201 | return ipmi::responseSuccess(bmcSource); | 
|  | 3202 | } | 
|  | 3203 |  | 
|  | 3204 | ipmi::RspType<> ipmiOEMSetNmiSource(uint8_t sourceId) | 
|  | 3205 | { | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3206 | namespace nmi = sdbusplus::xyz::openbmc_project::Chassis::Control::server; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3207 |  | 
|  | 3208 | nmi::NMISource::BMCSourceSignal bmcSourceSignal = | 
|  | 3209 | nmi::NMISource::BMCSourceSignal::None; | 
|  | 3210 |  | 
|  | 3211 | switch (NmiSource(sourceId)) | 
|  | 3212 | { | 
|  | 3213 | case NmiSource::none: | 
|  | 3214 | bmcSourceSignal = nmi::NMISource::BMCSourceSignal::None; | 
|  | 3215 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3216 | case NmiSource::frontPanelButton: | 
|  | 3217 | bmcSourceSignal = nmi::NMISource::BMCSourceSignal::FrontPanelButton; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3218 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3219 | case NmiSource::watchdog: | 
|  | 3220 | bmcSourceSignal = nmi::NMISource::BMCSourceSignal::Watchdog; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3221 | break; | 
|  | 3222 | case NmiSource::chassisCmd: | 
|  | 3223 | bmcSourceSignal = nmi::NMISource::BMCSourceSignal::ChassisCmd; | 
|  | 3224 | break; | 
|  | 3225 | case NmiSource::memoryError: | 
|  | 3226 | bmcSourceSignal = nmi::NMISource::BMCSourceSignal::MemoryError; | 
|  | 3227 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3228 | case NmiSource::pciBusError: | 
|  | 3229 | bmcSourceSignal = nmi::NMISource::BMCSourceSignal::PciBusError; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3230 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3231 | case NmiSource::pch: | 
|  | 3232 | bmcSourceSignal = nmi::NMISource::BMCSourceSignal::PCH; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3233 | break; | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3234 | case NmiSource::chipset: | 
|  | 3235 | bmcSourceSignal = nmi::NMISource::BMCSourceSignal::Chipset; | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3236 | break; | 
|  | 3237 | default: | 
|  | 3238 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3239 | "NMI source: invalid property!"); | 
|  | 3240 | return ipmi::responseResponseError(); | 
|  | 3241 | } | 
|  | 3242 |  | 
|  | 3243 | try | 
|  | 3244 | { | 
|  | 3245 | // keep NMI signal source | 
|  | 3246 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 3247 | std::string service = | 
|  | 3248 | getService(*dbus, oemNmiSourceIntf, oemNmiSourceObjPath); | 
| Chen Yugang | 97cf96e | 2019-11-01 08:55:11 +0800 | [diff] [blame] | 3249 | setDbusProperty(*dbus, service, oemNmiSourceObjPath, oemNmiSourceIntf, | 
|  | 3250 | oemNmiBmcSourceObjPathProp, | 
|  | 3251 | nmi::convertForMessage(bmcSourceSignal)); | 
| Chen Yugang | 99be633 | 2019-08-09 16:20:48 +0800 | [diff] [blame] | 3252 | // set Enabled property to inform NMI source handling | 
|  | 3253 | // to trigger a NMI_OUT BSOD. | 
|  | 3254 | // if it's triggered by NMI source property changed, | 
|  | 3255 | // NMI_OUT BSOD could be missed if the same source occurs twice in a row | 
|  | 3256 | if (bmcSourceSignal != nmi::NMISource::BMCSourceSignal::None) | 
|  | 3257 | { | 
|  | 3258 | setDbusProperty(*dbus, service, oemNmiSourceObjPath, | 
|  | 3259 | oemNmiSourceIntf, oemNmiEnabledObjPathProp, | 
|  | 3260 | static_cast<bool>(true)); | 
|  | 3261 | } | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3262 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 3263 | catch (const sdbusplus::exception_t& e) | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 3264 | { | 
|  | 3265 | phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); | 
|  | 3266 | return ipmi::responseResponseError(); | 
|  | 3267 | } | 
|  | 3268 |  | 
|  | 3269 | return ipmi::responseSuccess(); | 
|  | 3270 | } | 
|  | 3271 |  | 
| James Feist | 63efafa | 2019-07-24 12:39:21 -0700 | [diff] [blame] | 3272 | namespace dimmOffset | 
|  | 3273 | { | 
|  | 3274 | constexpr const char* dimmPower = "DimmPower"; | 
|  | 3275 | constexpr const char* staticCltt = "StaticCltt"; | 
|  | 3276 | constexpr const char* offsetPath = "/xyz/openbmc_project/Inventory/Item/Dimm"; | 
|  | 3277 | constexpr const char* offsetInterface = | 
|  | 3278 | "xyz.openbmc_project.Inventory.Item.Dimm.Offset"; | 
|  | 3279 | constexpr const char* property = "DimmOffset"; | 
|  | 3280 |  | 
|  | 3281 | }; // namespace dimmOffset | 
|  | 3282 |  | 
|  | 3283 | ipmi::RspType<> | 
|  | 3284 | ipmiOEMSetDimmOffset(uint8_t type, | 
|  | 3285 | const std::vector<std::tuple<uint8_t, uint8_t>>& data) | 
|  | 3286 | { | 
|  | 3287 | if (type != static_cast<uint8_t>(dimmOffsetTypes::dimmPower) && | 
|  | 3288 | type != static_cast<uint8_t>(dimmOffsetTypes::staticCltt)) | 
|  | 3289 | { | 
|  | 3290 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3291 | } | 
|  | 3292 |  | 
|  | 3293 | if (data.empty()) | 
|  | 3294 | { | 
|  | 3295 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3296 | } | 
|  | 3297 | nlohmann::json json; | 
|  | 3298 |  | 
|  | 3299 | std::ifstream jsonStream(dimmOffsetFile); | 
|  | 3300 | if (jsonStream.good()) | 
|  | 3301 | { | 
|  | 3302 | json = nlohmann::json::parse(jsonStream, nullptr, false); | 
|  | 3303 | if (json.is_discarded()) | 
|  | 3304 | { | 
|  | 3305 | json = nlohmann::json(); | 
|  | 3306 | } | 
|  | 3307 | jsonStream.close(); | 
|  | 3308 | } | 
|  | 3309 |  | 
|  | 3310 | std::string typeName; | 
|  | 3311 | if (type == static_cast<uint8_t>(dimmOffsetTypes::dimmPower)) | 
|  | 3312 | { | 
|  | 3313 | typeName = dimmOffset::dimmPower; | 
|  | 3314 | } | 
|  | 3315 | else | 
|  | 3316 | { | 
|  | 3317 | typeName = dimmOffset::staticCltt; | 
|  | 3318 | } | 
|  | 3319 |  | 
|  | 3320 | nlohmann::json& field = json[typeName]; | 
|  | 3321 |  | 
|  | 3322 | for (const auto& [index, value] : data) | 
|  | 3323 | { | 
|  | 3324 | field[index] = value; | 
|  | 3325 | } | 
|  | 3326 |  | 
|  | 3327 | for (nlohmann::json& val : field) | 
|  | 3328 | { | 
|  | 3329 | if (val == nullptr) | 
|  | 3330 | { | 
|  | 3331 | val = static_cast<uint8_t>(0); | 
|  | 3332 | } | 
|  | 3333 | } | 
|  | 3334 |  | 
|  | 3335 | std::ofstream output(dimmOffsetFile); | 
|  | 3336 | if (!output.good()) | 
|  | 3337 | { | 
|  | 3338 | std::cerr << "Error writing json file\n"; | 
|  | 3339 | return ipmi::responseResponseError(); | 
|  | 3340 | } | 
|  | 3341 |  | 
|  | 3342 | output << json.dump(4); | 
|  | 3343 |  | 
|  | 3344 | if (type == static_cast<uint8_t>(dimmOffsetTypes::staticCltt)) | 
|  | 3345 | { | 
|  | 3346 | std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); | 
|  | 3347 |  | 
|  | 3348 | std::variant<std::vector<uint8_t>> offsets = | 
|  | 3349 | field.get<std::vector<uint8_t>>(); | 
|  | 3350 | auto call = bus->new_method_call( | 
|  | 3351 | settingsBusName, dimmOffset::offsetPath, PROP_INTF, "Set"); | 
|  | 3352 | call.append(dimmOffset::offsetInterface, dimmOffset::property, offsets); | 
|  | 3353 | try | 
|  | 3354 | { | 
|  | 3355 | bus->call(call); | 
|  | 3356 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 3357 | catch (const sdbusplus::exception_t& e) | 
| James Feist | 63efafa | 2019-07-24 12:39:21 -0700 | [diff] [blame] | 3358 | { | 
|  | 3359 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3360 | "ipmiOEMSetDimmOffset: can't set dimm offsets!", | 
|  | 3361 | phosphor::logging::entry("ERR=%s", e.what())); | 
|  | 3362 | return ipmi::responseResponseError(); | 
|  | 3363 | } | 
|  | 3364 | } | 
|  | 3365 |  | 
|  | 3366 | return ipmi::responseSuccess(); | 
|  | 3367 | } | 
|  | 3368 |  | 
|  | 3369 | ipmi::RspType<uint8_t> ipmiOEMGetDimmOffset(uint8_t type, uint8_t index) | 
|  | 3370 | { | 
|  | 3371 |  | 
|  | 3372 | if (type != static_cast<uint8_t>(dimmOffsetTypes::dimmPower) && | 
|  | 3373 | type != static_cast<uint8_t>(dimmOffsetTypes::staticCltt)) | 
|  | 3374 | { | 
|  | 3375 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3376 | } | 
|  | 3377 |  | 
|  | 3378 | std::ifstream jsonStream(dimmOffsetFile); | 
|  | 3379 |  | 
|  | 3380 | auto json = nlohmann::json::parse(jsonStream, nullptr, false); | 
|  | 3381 | if (json.is_discarded()) | 
|  | 3382 | { | 
|  | 3383 | std::cerr << "File error in " << dimmOffsetFile << "\n"; | 
|  | 3384 | return ipmi::responseResponseError(); | 
|  | 3385 | } | 
|  | 3386 |  | 
|  | 3387 | std::string typeName; | 
|  | 3388 | if (type == static_cast<uint8_t>(dimmOffsetTypes::dimmPower)) | 
|  | 3389 | { | 
|  | 3390 | typeName = dimmOffset::dimmPower; | 
|  | 3391 | } | 
|  | 3392 | else | 
|  | 3393 | { | 
|  | 3394 | typeName = dimmOffset::staticCltt; | 
|  | 3395 | } | 
|  | 3396 |  | 
|  | 3397 | auto it = json.find(typeName); | 
|  | 3398 | if (it == json.end()) | 
|  | 3399 | { | 
|  | 3400 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3401 | } | 
|  | 3402 |  | 
|  | 3403 | if (it->size() <= index) | 
|  | 3404 | { | 
|  | 3405 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3406 | } | 
|  | 3407 |  | 
|  | 3408 | uint8_t resp = it->at(index).get<uint8_t>(); | 
|  | 3409 | return ipmi::responseSuccess(resp); | 
|  | 3410 | } | 
|  | 3411 |  | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 3412 | namespace boot_options | 
|  | 3413 | { | 
|  | 3414 |  | 
|  | 3415 | using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server; | 
|  | 3416 | using IpmiValue = uint8_t; | 
|  | 3417 | constexpr auto ipmiDefault = 0; | 
|  | 3418 |  | 
|  | 3419 | std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = { | 
|  | 3420 | {0x01, Source::Sources::Network}, | 
|  | 3421 | {0x02, Source::Sources::Disk}, | 
|  | 3422 | {0x05, Source::Sources::ExternalMedia}, | 
|  | 3423 | {0x0f, Source::Sources::RemovableMedia}, | 
|  | 3424 | {ipmiDefault, Source::Sources::Default}}; | 
|  | 3425 |  | 
|  | 3426 | std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = { | 
| Chen Yugang | ca12a7b | 2019-09-03 18:11:44 +0800 | [diff] [blame] | 3427 | {0x06, Mode::Modes::Setup}, {ipmiDefault, Mode::Modes::Regular}}; | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 3428 |  | 
|  | 3429 | std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = { | 
|  | 3430 | {Source::Sources::Network, 0x01}, | 
|  | 3431 | {Source::Sources::Disk, 0x02}, | 
|  | 3432 | {Source::Sources::ExternalMedia, 0x05}, | 
|  | 3433 | {Source::Sources::RemovableMedia, 0x0f}, | 
|  | 3434 | {Source::Sources::Default, ipmiDefault}}; | 
|  | 3435 |  | 
|  | 3436 | std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = { | 
| Chen Yugang | ca12a7b | 2019-09-03 18:11:44 +0800 | [diff] [blame] | 3437 | {Mode::Modes::Setup, 0x06}, {Mode::Modes::Regular, ipmiDefault}}; | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 3438 |  | 
|  | 3439 | static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode"; | 
|  | 3440 | static constexpr auto bootSourceIntf = | 
|  | 3441 | "xyz.openbmc_project.Control.Boot.Source"; | 
|  | 3442 | static constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable"; | 
|  | 3443 | static constexpr auto persistentObjPath = | 
|  | 3444 | "/xyz/openbmc_project/control/host0/boot"; | 
|  | 3445 | static constexpr auto oneTimePath = | 
|  | 3446 | "/xyz/openbmc_project/control/host0/boot/one_time"; | 
|  | 3447 | static constexpr auto bootSourceProp = "BootSource"; | 
|  | 3448 | static constexpr auto bootModeProp = "BootMode"; | 
|  | 3449 | static constexpr auto oneTimeBootEnableProp = "Enabled"; | 
|  | 3450 | static constexpr auto httpBootMode = | 
|  | 3451 | "xyz.openbmc_project.Control.Boot.Source.Sources.Http"; | 
|  | 3452 |  | 
|  | 3453 | enum class BootOptionParameter : size_t | 
|  | 3454 | { | 
|  | 3455 | setInProgress = 0x0, | 
|  | 3456 | bootFlags = 0x5, | 
|  | 3457 | }; | 
|  | 3458 | static constexpr uint8_t setComplete = 0x0; | 
|  | 3459 | static constexpr uint8_t setInProgress = 0x1; | 
|  | 3460 | static uint8_t transferStatus = setComplete; | 
|  | 3461 | static constexpr uint8_t setParmVersion = 0x01; | 
|  | 3462 | static constexpr uint8_t setParmBootFlagsPermanent = 0x40; | 
|  | 3463 | static constexpr uint8_t setParmBootFlagsValidOneTime = 0x80; | 
|  | 3464 | static constexpr uint8_t setParmBootFlagsValidPermanent = 0xC0; | 
|  | 3465 | static constexpr uint8_t httpBoot = 0xd; | 
|  | 3466 | static constexpr uint8_t bootSourceMask = 0x3c; | 
|  | 3467 |  | 
|  | 3468 | } // namespace boot_options | 
|  | 3469 |  | 
|  | 3470 | ipmi::RspType<uint8_t,               // version | 
|  | 3471 | uint8_t,               // param | 
|  | 3472 | uint8_t,               // data0, dependent on parameter | 
|  | 3473 | std::optional<uint8_t> // data1, dependent on parameter | 
|  | 3474 | > | 
|  | 3475 | ipmiOemGetEfiBootOptions(uint8_t parameter, uint8_t set, uint8_t block) | 
|  | 3476 | { | 
|  | 3477 | using namespace boot_options; | 
|  | 3478 | uint8_t bootOption = 0; | 
|  | 3479 |  | 
|  | 3480 | if (parameter == static_cast<uint8_t>(BootOptionParameter::setInProgress)) | 
|  | 3481 | { | 
|  | 3482 | return ipmi::responseSuccess(setParmVersion, parameter, transferStatus, | 
|  | 3483 | std::nullopt); | 
|  | 3484 | } | 
|  | 3485 |  | 
|  | 3486 | if (parameter != static_cast<uint8_t>(BootOptionParameter::bootFlags)) | 
|  | 3487 | { | 
|  | 3488 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3489 | "Unsupported parameter"); | 
| Jayaprakash Mutyala | 3694d07 | 2021-07-22 10:34:37 +0000 | [diff] [blame] | 3490 | return ipmi::response(ccParameterNotSupported); | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 3491 | } | 
|  | 3492 |  | 
|  | 3493 | try | 
|  | 3494 | { | 
|  | 3495 | auto oneTimeEnabled = false; | 
|  | 3496 | // read one time Enabled property | 
|  | 3497 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 3498 | std::string service = getService(*dbus, enabledIntf, oneTimePath); | 
|  | 3499 | Value variant = getDbusProperty(*dbus, service, oneTimePath, | 
|  | 3500 | enabledIntf, oneTimeBootEnableProp); | 
|  | 3501 | oneTimeEnabled = std::get<bool>(variant); | 
|  | 3502 |  | 
|  | 3503 | // get BootSource and BootMode properties | 
|  | 3504 | // according to oneTimeEnable | 
|  | 3505 | auto bootObjPath = oneTimePath; | 
|  | 3506 | if (oneTimeEnabled == false) | 
|  | 3507 | { | 
|  | 3508 | bootObjPath = persistentObjPath; | 
|  | 3509 | } | 
|  | 3510 |  | 
|  | 3511 | service = getService(*dbus, bootModeIntf, bootObjPath); | 
|  | 3512 | variant = getDbusProperty(*dbus, service, bootObjPath, bootModeIntf, | 
|  | 3513 | bootModeProp); | 
|  | 3514 |  | 
|  | 3515 | auto bootMode = | 
|  | 3516 | Mode::convertModesFromString(std::get<std::string>(variant)); | 
|  | 3517 |  | 
|  | 3518 | service = getService(*dbus, bootSourceIntf, bootObjPath); | 
|  | 3519 | variant = getDbusProperty(*dbus, service, bootObjPath, bootSourceIntf, | 
|  | 3520 | bootSourceProp); | 
|  | 3521 |  | 
|  | 3522 | if (std::get<std::string>(variant) == httpBootMode) | 
|  | 3523 | { | 
|  | 3524 | bootOption = httpBoot; | 
|  | 3525 | } | 
|  | 3526 | else | 
|  | 3527 | { | 
|  | 3528 | auto bootSource = Source::convertSourcesFromString( | 
|  | 3529 | std::get<std::string>(variant)); | 
|  | 3530 | bootOption = sourceDbusToIpmi.at(bootSource); | 
|  | 3531 | if (Source::Sources::Default == bootSource) | 
|  | 3532 | { | 
|  | 3533 | bootOption = modeDbusToIpmi.at(bootMode); | 
|  | 3534 | } | 
|  | 3535 | } | 
|  | 3536 |  | 
|  | 3537 | uint8_t oneTime = oneTimeEnabled ? setParmBootFlagsValidOneTime | 
|  | 3538 | : setParmBootFlagsValidPermanent; | 
|  | 3539 | bootOption <<= 2; // shift for responseconstexpr | 
|  | 3540 | return ipmi::responseSuccess(setParmVersion, parameter, oneTime, | 
|  | 3541 | bootOption); | 
|  | 3542 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 3543 | catch (const sdbusplus::exception_t& e) | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 3544 | { | 
|  | 3545 | phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); | 
|  | 3546 | return ipmi::responseResponseError(); | 
|  | 3547 | } | 
|  | 3548 | } | 
|  | 3549 |  | 
|  | 3550 | ipmi::RspType<> ipmiOemSetEfiBootOptions(uint8_t bootFlag, uint8_t bootParam, | 
|  | 3551 | std::optional<uint8_t> bootOption) | 
|  | 3552 | { | 
|  | 3553 | using namespace boot_options; | 
|  | 3554 | auto oneTimeEnabled = false; | 
|  | 3555 |  | 
|  | 3556 | if (bootFlag == static_cast<uint8_t>(BootOptionParameter::setInProgress)) | 
|  | 3557 | { | 
|  | 3558 | if (bootOption) | 
|  | 3559 | { | 
|  | 3560 | return ipmi::responseReqDataLenInvalid(); | 
|  | 3561 | } | 
|  | 3562 |  | 
|  | 3563 | if (transferStatus == setInProgress) | 
|  | 3564 | { | 
|  | 3565 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3566 | "boot option set in progress!"); | 
|  | 3567 | return ipmi::responseResponseError(); | 
|  | 3568 | } | 
|  | 3569 |  | 
|  | 3570 | transferStatus = bootParam; | 
|  | 3571 | return ipmi::responseSuccess(); | 
|  | 3572 | } | 
|  | 3573 |  | 
|  | 3574 | if (bootFlag != (uint8_t)BootOptionParameter::bootFlags) | 
|  | 3575 | { | 
|  | 3576 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3577 | "Unsupported parameter"); | 
| Jayaprakash Mutyala | 3694d07 | 2021-07-22 10:34:37 +0000 | [diff] [blame] | 3578 | return ipmi::response(ccParameterNotSupported); | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 3579 | } | 
|  | 3580 |  | 
|  | 3581 | if (!bootOption) | 
|  | 3582 | { | 
|  | 3583 | return ipmi::responseReqDataLenInvalid(); | 
|  | 3584 | } | 
|  | 3585 |  | 
|  | 3586 | if (((bootOption.value() & bootSourceMask) >> 2) != | 
|  | 3587 | httpBoot) // not http boot, exit | 
|  | 3588 | { | 
|  | 3589 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3590 | "wrong boot option parameter!"); | 
|  | 3591 | return ipmi::responseParmOutOfRange(); | 
|  | 3592 | } | 
|  | 3593 |  | 
|  | 3594 | try | 
|  | 3595 | { | 
|  | 3596 | bool permanent = (bootParam & setParmBootFlagsPermanent) == | 
|  | 3597 | setParmBootFlagsPermanent; | 
|  | 3598 |  | 
|  | 3599 | // read one time Enabled property | 
|  | 3600 | std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus(); | 
|  | 3601 | std::string service = getService(*dbus, enabledIntf, oneTimePath); | 
|  | 3602 | Value variant = getDbusProperty(*dbus, service, oneTimePath, | 
|  | 3603 | enabledIntf, oneTimeBootEnableProp); | 
|  | 3604 | oneTimeEnabled = std::get<bool>(variant); | 
|  | 3605 |  | 
|  | 3606 | /* | 
|  | 3607 | * Check if the current boot setting is onetime or permanent, if the | 
|  | 3608 | * request in the command is otherwise, then set the "Enabled" | 
|  | 3609 | * property in one_time object path to 'True' to indicate onetime | 
|  | 3610 | * and 'False' to indicate permanent. | 
|  | 3611 | * | 
|  | 3612 | * Once the onetime/permanent setting is applied, then the bootMode | 
|  | 3613 | * and bootSource is updated for the corresponding object. | 
|  | 3614 | */ | 
|  | 3615 | if (permanent == oneTimeEnabled) | 
|  | 3616 | { | 
|  | 3617 | setDbusProperty(*dbus, service, oneTimePath, enabledIntf, | 
|  | 3618 | oneTimeBootEnableProp, !permanent); | 
|  | 3619 | } | 
|  | 3620 |  | 
|  | 3621 | // set BootSource and BootMode properties | 
|  | 3622 | // according to oneTimeEnable or persistent | 
|  | 3623 | auto bootObjPath = oneTimePath; | 
|  | 3624 | if (oneTimeEnabled == false) | 
|  | 3625 | { | 
|  | 3626 | bootObjPath = persistentObjPath; | 
|  | 3627 | } | 
|  | 3628 | std::string bootMode = | 
|  | 3629 | "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular"; | 
|  | 3630 | std::string bootSource = httpBootMode; | 
|  | 3631 |  | 
|  | 3632 | service = getService(*dbus, bootModeIntf, bootObjPath); | 
|  | 3633 | setDbusProperty(*dbus, service, bootObjPath, bootModeIntf, bootModeProp, | 
|  | 3634 | bootMode); | 
|  | 3635 |  | 
|  | 3636 | service = getService(*dbus, bootSourceIntf, bootObjPath); | 
|  | 3637 | setDbusProperty(*dbus, service, bootObjPath, bootSourceIntf, | 
|  | 3638 | bootSourceProp, bootSource); | 
|  | 3639 | } | 
| Patrick Williams | bd51e6a | 2021-10-06 13:09:44 -0500 | [diff] [blame] | 3640 | catch (const sdbusplus::exception_t& e) | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 3641 | { | 
|  | 3642 | phosphor::logging::log<phosphor::logging::level::ERR>(e.what()); | 
|  | 3643 | return ipmi::responseResponseError(); | 
|  | 3644 | } | 
|  | 3645 |  | 
|  | 3646 | return ipmi::responseSuccess(); | 
|  | 3647 | } | 
|  | 3648 |  | 
| Cheng C Yang | 4e6ee15 | 2019-09-25 10:27:44 +0800 | [diff] [blame] | 3649 | using BasicVariantType = | 
|  | 3650 | std::variant<std::vector<std::string>, std::vector<uint64_t>, std::string, | 
|  | 3651 | int64_t, uint64_t, double, int32_t, uint32_t, int16_t, | 
|  | 3652 | uint16_t, uint8_t, bool>; | 
|  | 3653 | using PropertyMapType = | 
|  | 3654 | boost::container::flat_map<std::string, BasicVariantType>; | 
|  | 3655 | static constexpr const std::array<const char*, 1> psuPresenceTypes = { | 
|  | 3656 | "xyz.openbmc_project.Configuration.PSUPresence"}; | 
|  | 3657 | int getPSUAddress(ipmi::Context::ptr ctx, uint8_t& bus, | 
|  | 3658 | std::vector<uint64_t>& addrTable) | 
|  | 3659 | { | 
|  | 3660 | boost::system::error_code ec; | 
|  | 3661 | GetSubTreeType subtree = ctx->bus->yield_method_call<GetSubTreeType>( | 
|  | 3662 | ctx->yield, ec, "xyz.openbmc_project.ObjectMapper", | 
|  | 3663 | "/xyz/openbmc_project/object_mapper", | 
|  | 3664 | "xyz.openbmc_project.ObjectMapper", "GetSubTree", | 
|  | 3665 | "/xyz/openbmc_project/inventory/system", 3, psuPresenceTypes); | 
|  | 3666 | if (ec) | 
|  | 3667 | { | 
|  | 3668 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3669 | "Failed to set dbus property to cold redundancy"); | 
|  | 3670 | return -1; | 
|  | 3671 | } | 
|  | 3672 | for (const auto& object : subtree) | 
|  | 3673 | { | 
|  | 3674 | std::string pathName = object.first; | 
|  | 3675 | for (const auto& serviceIface : object.second) | 
|  | 3676 | { | 
|  | 3677 | std::string serviceName = serviceIface.first; | 
|  | 3678 |  | 
|  | 3679 | ec.clear(); | 
|  | 3680 | PropertyMapType propMap = | 
|  | 3681 | ctx->bus->yield_method_call<PropertyMapType>( | 
|  | 3682 | ctx->yield, ec, serviceName, pathName, | 
|  | 3683 | "org.freedesktop.DBus.Properties", "GetAll", | 
|  | 3684 | "xyz.openbmc_project.Configuration.PSUPresence"); | 
|  | 3685 | if (ec) | 
|  | 3686 | { | 
|  | 3687 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3688 | "Failed to set dbus property to cold redundancy"); | 
|  | 3689 | return -1; | 
|  | 3690 | } | 
|  | 3691 | auto psuBus = std::get_if<uint64_t>(&propMap["Bus"]); | 
|  | 3692 | auto psuAddress = | 
|  | 3693 | std::get_if<std::vector<uint64_t>>(&propMap["Address"]); | 
|  | 3694 |  | 
|  | 3695 | if (psuBus == nullptr || psuAddress == nullptr) | 
|  | 3696 | { | 
|  | 3697 | std::cerr << "error finding necessary " | 
|  | 3698 | "entry in configuration\n"; | 
|  | 3699 | return -1; | 
|  | 3700 | } | 
|  | 3701 | bus = static_cast<uint8_t>(*psuBus); | 
|  | 3702 | addrTable = *psuAddress; | 
|  | 3703 | return 0; | 
|  | 3704 | } | 
|  | 3705 | } | 
|  | 3706 | return -1; | 
|  | 3707 | } | 
|  | 3708 |  | 
|  | 3709 | static const constexpr uint8_t addrOffset = 8; | 
|  | 3710 | static const constexpr uint8_t psuRevision = 0xd9; | 
|  | 3711 | static const constexpr uint8_t defaultPSUBus = 7; | 
|  | 3712 | // Second Minor, Primary Minor, Major | 
|  | 3713 | static const constexpr size_t verLen = 3; | 
|  | 3714 | ipmi::RspType<std::vector<uint8_t>> ipmiOEMGetPSUVersion(ipmi::Context::ptr ctx) | 
|  | 3715 | { | 
|  | 3716 | uint8_t bus = defaultPSUBus; | 
|  | 3717 | std::vector<uint64_t> addrTable; | 
|  | 3718 | std::vector<uint8_t> result; | 
|  | 3719 | if (getPSUAddress(ctx, bus, addrTable)) | 
|  | 3720 | { | 
|  | 3721 | std::cerr << "Failed to get PSU bus and address\n"; | 
|  | 3722 | return ipmi::responseResponseError(); | 
|  | 3723 | } | 
|  | 3724 |  | 
|  | 3725 | for (const auto& slaveAddr : addrTable) | 
|  | 3726 | { | 
|  | 3727 | std::vector<uint8_t> writeData = {psuRevision}; | 
|  | 3728 | std::vector<uint8_t> readBuf(verLen); | 
|  | 3729 | uint8_t addr = static_cast<uint8_t>(slaveAddr) + addrOffset; | 
|  | 3730 | std::string i2cBus = "/dev/i2c-" + std::to_string(bus); | 
|  | 3731 |  | 
|  | 3732 | auto retI2C = ipmi::i2cWriteRead(i2cBus, addr, writeData, readBuf); | 
|  | 3733 | if (retI2C != ipmi::ccSuccess) | 
|  | 3734 | { | 
|  | 3735 | for (size_t idx = 0; idx < verLen; idx++) | 
|  | 3736 | { | 
|  | 3737 | result.emplace_back(0x00); | 
|  | 3738 | } | 
|  | 3739 | } | 
|  | 3740 | else | 
|  | 3741 | { | 
|  | 3742 | for (const uint8_t& data : readBuf) | 
|  | 3743 | { | 
|  | 3744 | result.emplace_back(data); | 
|  | 3745 | } | 
|  | 3746 | } | 
|  | 3747 | } | 
|  | 3748 |  | 
|  | 3749 | return ipmi::responseSuccess(result); | 
|  | 3750 | } | 
|  | 3751 |  | 
| srikanta mondal | 2030d7c | 2020-05-03 17:25:25 +0000 | [diff] [blame] | 3752 | std::optional<uint8_t> getMultiNodeInfoPresence(ipmi::Context::ptr ctx, | 
|  | 3753 | const std::string& name) | 
|  | 3754 | { | 
|  | 3755 | Value dbusValue = 0; | 
|  | 3756 | std::string serviceName; | 
|  | 3757 |  | 
|  | 3758 | boost::system::error_code ec = | 
|  | 3759 | ipmi::getService(ctx, multiNodeIntf, multiNodeObjPath, serviceName); | 
|  | 3760 |  | 
|  | 3761 | if (ec) | 
|  | 3762 | { | 
|  | 3763 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3764 | "Failed to perform Multinode getService."); | 
|  | 3765 | return std::nullopt; | 
|  | 3766 | } | 
|  | 3767 |  | 
|  | 3768 | ec = ipmi::getDbusProperty(ctx, serviceName, multiNodeObjPath, | 
|  | 3769 | multiNodeIntf, name, dbusValue); | 
|  | 3770 | if (ec) | 
|  | 3771 | { | 
|  | 3772 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3773 | "Failed to perform Multinode get property"); | 
|  | 3774 | return std::nullopt; | 
|  | 3775 | } | 
|  | 3776 |  | 
|  | 3777 | auto multiNodeVal = std::get_if<uint8_t>(&dbusValue); | 
|  | 3778 | if (!multiNodeVal) | 
|  | 3779 | { | 
|  | 3780 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3781 | "getMultiNodeInfoPresence: error to get multinode"); | 
|  | 3782 | return std::nullopt; | 
|  | 3783 | } | 
|  | 3784 | return *multiNodeVal; | 
|  | 3785 | } | 
|  | 3786 |  | 
|  | 3787 | /** @brief implements OEM get reading command | 
|  | 3788 | *  @param domain ID | 
|  | 3789 | *  @param reading Type | 
|  | 3790 | *    - 00h = platform Power Consumption | 
|  | 3791 | *    - 01h = inlet Air Temp | 
|  | 3792 | *    - 02h = icc_TDC from PECI | 
|  | 3793 | *  @param reserved, write as 0000h | 
|  | 3794 | * | 
|  | 3795 | *  @returns IPMI completion code plus response data | 
|  | 3796 | *  - response | 
|  | 3797 | *     - domain ID | 
|  | 3798 | *     - reading Type | 
|  | 3799 | *       - 00h = platform Power Consumption | 
|  | 3800 | *       - 01h = inlet Air Temp | 
|  | 3801 | *       - 02h = icc_TDC from PECI | 
|  | 3802 | *     - reading | 
|  | 3803 | */ | 
|  | 3804 | ipmi::RspType<uint4_t, // domain ID | 
|  | 3805 | uint4_t, // reading Type | 
|  | 3806 | uint16_t // reading Value | 
|  | 3807 | > | 
|  | 3808 | ipmiOEMGetReading(ipmi::Context::ptr ctx, uint4_t domainId, | 
|  | 3809 | uint4_t readingType, uint16_t reserved) | 
|  | 3810 | { | 
|  | 3811 | constexpr uint8_t platformPower = 0; | 
|  | 3812 | constexpr uint8_t inletAirTemp = 1; | 
|  | 3813 | constexpr uint8_t iccTdc = 2; | 
|  | 3814 |  | 
|  | 3815 | if ((static_cast<uint8_t>(readingType) > iccTdc) || domainId || reserved) | 
|  | 3816 | { | 
|  | 3817 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3818 | } | 
|  | 3819 |  | 
|  | 3820 | // This command should run only from multi-node product. | 
|  | 3821 | // For all other platforms this command will return invalid. | 
|  | 3822 |  | 
|  | 3823 | std::optional<uint8_t> nodeInfo = | 
|  | 3824 | getMultiNodeInfoPresence(ctx, "NodePresence"); | 
|  | 3825 | if (!nodeInfo || !*nodeInfo) | 
|  | 3826 | { | 
|  | 3827 | return ipmi::responseInvalidCommand(); | 
|  | 3828 | } | 
|  | 3829 |  | 
|  | 3830 | uint16_t oemReadingValue = 0; | 
|  | 3831 | if (static_cast<uint8_t>(readingType) == inletAirTemp) | 
|  | 3832 | { | 
|  | 3833 | double value = 0; | 
|  | 3834 | boost::system::error_code ec = ipmi::getDbusProperty( | 
|  | 3835 | ctx, "xyz.openbmc_project.HwmonTempSensor", | 
|  | 3836 | "/xyz/openbmc_project/sensors/temperature/Inlet_BRD_Temp", | 
|  | 3837 | "xyz.openbmc_project.Sensor.Value", "Value", value); | 
|  | 3838 | if (ec) | 
|  | 3839 | { | 
|  | 3840 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3841 | "Failed to get BMC Get OEM temperature", | 
|  | 3842 | phosphor::logging::entry("EXCEPTION=%s", ec.message().c_str())); | 
|  | 3843 | return ipmi::responseUnspecifiedError(); | 
|  | 3844 | } | 
|  | 3845 | // Take the Inlet temperature | 
|  | 3846 | oemReadingValue = static_cast<uint16_t>(value); | 
|  | 3847 | } | 
|  | 3848 | else | 
|  | 3849 | { | 
|  | 3850 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3851 | "Currently Get OEM Reading support only for Inlet Air Temp"); | 
|  | 3852 | return ipmi::responseParmOutOfRange(); | 
|  | 3853 | } | 
|  | 3854 | return ipmi::responseSuccess(domainId, readingType, oemReadingValue); | 
|  | 3855 | } | 
|  | 3856 |  | 
| AppaRao Puli | 2897206 | 2019-11-11 02:04:45 +0530 | [diff] [blame] | 3857 | /** @brief implements the maximum size of | 
|  | 3858 | *  bridgeable messages used between KCS and | 
|  | 3859 | *  IPMB interfacesget security mode command. | 
|  | 3860 | * | 
|  | 3861 | *  @returns IPMI completion code with following data | 
|  | 3862 | *   - KCS Buffer Size (In multiples of four bytes) | 
|  | 3863 | *   - IPMB Buffer Size (In multiples of four bytes) | 
|  | 3864 | **/ | 
|  | 3865 | ipmi::RspType<uint8_t, uint8_t> ipmiOEMGetBufferSize() | 
|  | 3866 | { | 
|  | 3867 | // for now this is hard coded; really this number is dependent on | 
|  | 3868 | // the BMC kcs driver as well as the host kcs driver.... | 
|  | 3869 | // we can't know the latter. | 
|  | 3870 | uint8_t kcsMaxBufferSize = 63 / 4; | 
|  | 3871 | uint8_t ipmbMaxBufferSize = 128 / 4; | 
|  | 3872 |  | 
|  | 3873 | return ipmi::responseSuccess(kcsMaxBufferSize, ipmbMaxBufferSize); | 
|  | 3874 | } | 
|  | 3875 |  | 
| Ankita Vilas Gawade | a165038 | 2022-01-08 10:30:40 +0000 | [diff] [blame^] | 3876 | ipmi::RspType<std::vector<uint8_t>> | 
|  | 3877 | ipmiOEMReadPFRMailbox(ipmi::Context::ptr& ctx, const uint8_t readRegister, | 
|  | 3878 | const uint8_t numOfBytes, uint8_t registerIdentifier) | 
|  | 3879 | { | 
|  | 3880 | if (!ipmi::mailbox::i2cConfigLoaded) | 
|  | 3881 | { | 
|  | 3882 |  | 
|  | 3883 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3884 | "Calling PFR Load Configuration Function to Get I2C Bus and Slave " | 
|  | 3885 | "Address "); | 
|  | 3886 |  | 
|  | 3887 | ipmi::mailbox::loadPfrConfig(ctx, ipmi::mailbox::i2cConfigLoaded); | 
|  | 3888 | } | 
|  | 3889 |  | 
|  | 3890 | if (!numOfBytes && !readRegister) | 
|  | 3891 | { | 
|  | 3892 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3893 | "OEM IPMI command: Read & write count are 0 which is invalid "); | 
|  | 3894 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3895 | } | 
|  | 3896 |  | 
|  | 3897 | switch (registerIdentifier) | 
|  | 3898 | { | 
|  | 3899 | case ipmi::mailbox::registerType::fifoReadRegister: | 
|  | 3900 | { | 
|  | 3901 | // Check if readRegister is an FIFO read register | 
|  | 3902 | if (registerIdentifier == 1) | 
|  | 3903 | { | 
|  | 3904 | if (ipmi::mailbox::readFifoReg.find(readRegister) == | 
|  | 3905 | ipmi::mailbox::readFifoReg.end()) | 
|  | 3906 | { | 
|  | 3907 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3908 | "OEM IPMI command: Register is not a Read FIFO  "); | 
|  | 3909 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3910 | } | 
|  | 3911 |  | 
|  | 3912 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3913 | "OEM IPMI command: Register is a Read FIFO  "); | 
|  | 3914 |  | 
|  | 3915 | ipmi::mailbox::writefifo(ipmi::mailbox::provisioningCommand, | 
|  | 3916 | readRegister); | 
|  | 3917 | ipmi::mailbox::writefifo(ipmi::mailbox::triggerCommand, | 
|  | 3918 | ipmi::mailbox::flushRead); | 
|  | 3919 |  | 
|  | 3920 | std::vector<uint8_t> writeData = {ipmi::mailbox::readFifo}; | 
|  | 3921 | std::vector<uint8_t> readBuf(1); | 
|  | 3922 | std::vector<uint8_t> result; | 
|  | 3923 |  | 
|  | 3924 | for (int i = 0; i < numOfBytes; i++) | 
|  | 3925 | { | 
|  | 3926 |  | 
|  | 3927 | ipmi::Cc ret = ipmi::i2cWriteRead(ipmi::mailbox::i2cBus, | 
|  | 3928 | ipmi::mailbox::slaveAddr, | 
|  | 3929 | writeData, readBuf); | 
|  | 3930 | if (ret != ipmi::ccSuccess) | 
|  | 3931 | { | 
|  | 3932 | return ipmi::response(ret); | 
|  | 3933 | } | 
|  | 3934 |  | 
|  | 3935 | else | 
|  | 3936 | { | 
|  | 3937 | for (const uint8_t& data : readBuf) | 
|  | 3938 | { | 
|  | 3939 | result.emplace_back(data); | 
|  | 3940 | } | 
|  | 3941 | } | 
|  | 3942 | } | 
|  | 3943 |  | 
|  | 3944 | return ipmi::responseSuccess(result); | 
|  | 3945 | } | 
|  | 3946 | } | 
|  | 3947 |  | 
|  | 3948 | case ipmi::mailbox::registerType::singleByteRegister: | 
|  | 3949 | { | 
|  | 3950 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3951 | "OEM IPMI command: Register is a Single Byte Register "); | 
|  | 3952 |  | 
|  | 3953 | std::vector<uint8_t> writeData = {readRegister}; | 
|  | 3954 | std::vector<uint8_t> readBuf(numOfBytes); | 
|  | 3955 |  | 
|  | 3956 | ipmi::Cc ret = ipmi::i2cWriteRead(ipmi::mailbox::i2cBus, | 
|  | 3957 | ipmi::mailbox::slaveAddr, | 
|  | 3958 | writeData, readBuf); | 
|  | 3959 | if (ret != ipmi::ccSuccess) | 
|  | 3960 | { | 
|  | 3961 | return ipmi::response(ret); | 
|  | 3962 | } | 
|  | 3963 | return ipmi::responseSuccess(readBuf); | 
|  | 3964 | } | 
|  | 3965 |  | 
|  | 3966 | default: | 
|  | 3967 | { | 
|  | 3968 |  | 
|  | 3969 | phosphor::logging::log<phosphor::logging::level::ERR>( | 
|  | 3970 | "OEM IPMI command: Register identifier is not valid.It should " | 
|  | 3971 | "be 0 " | 
|  | 3972 | "for Single Byte Register and 1 for FIFO Read Register"); | 
|  | 3973 |  | 
|  | 3974 | return ipmi::responseInvalidFieldRequest(); | 
|  | 3975 | } | 
|  | 3976 | } | 
|  | 3977 | } | 
|  | 3978 |  | 
| Jason M. Bills | 6479604 | 2018-10-03 16:51:55 -0700 | [diff] [blame] | 3979 | static void registerOEMFunctions(void) | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 3980 | { | 
|  | 3981 | phosphor::logging::log<phosphor::logging::level::INFO>( | 
|  | 3982 | "Registering OEM commands"); | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 3983 | ipmiPrintAndRegister(intel::netFnGeneral, | 
|  | 3984 | intel::general::cmdGetChassisIdentifier, NULL, | 
|  | 3985 | ipmiOEMGetChassisIdentifier, | 
|  | 3986 | PRIVILEGE_USER); // get chassis identifier | 
|  | 3987 |  | 
|  | 3988 | ipmiPrintAndRegister(intel::netFnGeneral, intel::general::cmdSetSystemGUID, | 
|  | 3989 | NULL, ipmiOEMSetSystemGUID, | 
|  | 3990 | PRIVILEGE_ADMIN); // set system guid | 
| Jason M. Bills | b02bf09 | 2019-08-15 13:01:56 -0700 | [diff] [blame] | 3991 |  | 
|  | 3992 | // <Disable BMC System Reset Action> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 3993 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 3994 | intel::general::cmdDisableBMCSystemReset, Privilege::Admin, | 
|  | 3995 | ipmiOEMDisableBMCSystemReset); | 
|  | 3996 |  | 
| Jason M. Bills | b02bf09 | 2019-08-15 13:01:56 -0700 | [diff] [blame] | 3997 | // <Get BMC Reset Disables> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 3998 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 3999 | intel::general::cmdGetBMCResetDisables, Privilege::Admin, | 
|  | 4000 | ipmiOEMGetBMCResetDisables); | 
| Jason M. Bills | b02bf09 | 2019-08-15 13:01:56 -0700 | [diff] [blame] | 4001 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4002 | ipmiPrintAndRegister(intel::netFnGeneral, intel::general::cmdSetBIOSID, | 
|  | 4003 | NULL, ipmiOEMSetBIOSID, PRIVILEGE_ADMIN); | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 4004 |  | 
| Chen Yugang | 7a04f3a | 2019-10-08 11:12:35 +0800 | [diff] [blame] | 4005 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4006 | intel::general::cmdGetOEMDeviceInfo, Privilege::User, | 
|  | 4007 | ipmiOEMGetDeviceInfo); | 
| Jia, Chunhui | cc49b54 | 2019-03-20 15:41:07 +0800 | [diff] [blame] | 4008 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4009 | ipmiPrintAndRegister(intel::netFnGeneral, | 
|  | 4010 | intel::general::cmdGetAICSlotFRUIDSlotPosRecords, NULL, | 
|  | 4011 | ipmiOEMGetAICFRU, PRIVILEGE_USER); | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 4012 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4013 | registerHandler(prioOpenBmcBase, intel::netFnGeneral, | 
|  | 4014 | intel::general::cmdSendEmbeddedFWUpdStatus, | 
|  | 4015 | Privilege::Operator, ipmiOEMSendEmbeddedFwUpdStatus); | 
| Suryakanth Sekar | d509eb9 | 2018-11-15 17:44:11 +0530 | [diff] [blame] | 4016 |  | 
| Rajashekar Gade Reddy | 2b664d5 | 2020-03-23 22:09:00 +0530 | [diff] [blame] | 4017 | registerHandler(prioOpenBmcBase, intel::netFnApp, intel::app::cmdSlotIpmb, | 
|  | 4018 | Privilege::Admin, ipmiOEMSlotIpmb); | 
|  | 4019 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4020 | ipmiPrintAndRegister(intel::netFnGeneral, | 
|  | 4021 | intel::general::cmdSetPowerRestoreDelay, NULL, | 
|  | 4022 | ipmiOEMSetPowerRestoreDelay, PRIVILEGE_OPERATOR); | 
|  | 4023 |  | 
|  | 4024 | ipmiPrintAndRegister(intel::netFnGeneral, | 
|  | 4025 | intel::general::cmdGetPowerRestoreDelay, NULL, | 
|  | 4026 | ipmiOEMGetPowerRestoreDelay, PRIVILEGE_USER); | 
|  | 4027 |  | 
|  | 4028 | registerHandler(prioOpenBmcBase, intel::netFnGeneral, | 
|  | 4029 | intel::general::cmdSetOEMUser2Activation, | 
|  | 4030 | Privilege::Callback, ipmiOEMSetUser2Activation); | 
|  | 4031 |  | 
|  | 4032 | registerHandler(prioOpenBmcBase, intel::netFnGeneral, | 
|  | 4033 | intel::general::cmdSetSpecialUserPassword, | 
|  | 4034 | Privilege::Callback, ipmiOEMSetSpecialUserPassword); | 
| Richard Marian Thomaiyar | fc5e985 | 2019-04-14 15:06:27 +0530 | [diff] [blame] | 4035 |  | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 4036 | // <Get Processor Error Config> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4037 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4038 | intel::general::cmdGetProcessorErrConfig, Privilege::User, | 
|  | 4039 | ipmiOEMGetProcessorErrConfig); | 
|  | 4040 |  | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 4041 | // <Set Processor Error Config> | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4042 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4043 | intel::general::cmdSetProcessorErrConfig, Privilege::Admin, | 
|  | 4044 | ipmiOEMSetProcessorErrConfig); | 
| Jason M. Bills | 42bd9c8 | 2019-06-28 16:39:34 -0700 | [diff] [blame] | 4045 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4046 | ipmiPrintAndRegister(intel::netFnGeneral, | 
|  | 4047 | intel::general::cmdSetShutdownPolicy, NULL, | 
|  | 4048 | ipmiOEMSetShutdownPolicy, PRIVILEGE_ADMIN); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 4049 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4050 | ipmiPrintAndRegister(intel::netFnGeneral, | 
|  | 4051 | intel::general::cmdGetShutdownPolicy, NULL, | 
|  | 4052 | ipmiOEMGetShutdownPolicy, PRIVILEGE_ADMIN); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 4053 |  | 
| anil kumar appana | f945eee | 2019-09-25 23:29:11 +0000 | [diff] [blame] | 4054 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4055 | intel::general::cmdSetFanConfig, Privilege::User, | 
|  | 4056 | ipmiOEMSetFanConfig); | 
| James Feist | 91244a6 | 2019-02-19 15:04:54 -0800 | [diff] [blame] | 4057 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4058 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4059 | intel::general::cmdGetFanConfig, Privilege::User, | 
|  | 4060 | ipmiOEMGetFanConfig); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 4061 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4062 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4063 | intel::general::cmdGetFanSpeedOffset, Privilege::User, | 
|  | 4064 | ipmiOEMGetFanSpeedOffset); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 4065 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4066 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4067 | intel::general::cmdSetFanSpeedOffset, Privilege::User, | 
|  | 4068 | ipmiOEMSetFanSpeedOffset); | 
| James Feist | acc8a4e | 2019-04-02 14:23:57 -0700 | [diff] [blame] | 4069 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4070 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4071 | intel::general::cmdSetFscParameter, Privilege::User, | 
|  | 4072 | ipmiOEMSetFscParameter); | 
| James Feist | 5f957ca | 2019-03-14 15:33:55 -0700 | [diff] [blame] | 4073 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4074 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4075 | intel::general::cmdGetFscParameter, Privilege::User, | 
|  | 4076 | ipmiOEMGetFscParameter); | 
| Richard Marian Thomaiyar | ea537d5 | 2019-04-24 21:33:48 +0530 | [diff] [blame] | 4077 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4078 | registerHandler(prioOpenBmcBase, intel::netFnGeneral, | 
|  | 4079 | intel::general::cmdReadBaseBoardProductId, Privilege::Admin, | 
|  | 4080 | ipmiOEMReadBoardProductId); | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 4081 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4082 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4083 | intel::general::cmdGetNmiStatus, Privilege::User, | 
|  | 4084 | ipmiOEMGetNmiSource); | 
| Chen Yugang | 39736d5 | 2019-07-12 16:24:33 +0800 | [diff] [blame] | 4085 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4086 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4087 | intel::general::cmdSetNmiStatus, Privilege::Operator, | 
|  | 4088 | ipmiOEMSetNmiSource); | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 4089 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4090 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4091 | intel::general::cmdGetEfiBootOptions, Privilege::User, | 
|  | 4092 | ipmiOemGetEfiBootOptions); | 
| Chen,Yugang | 4f7e76b | 2019-08-20 09:28:06 +0800 | [diff] [blame] | 4093 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4094 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4095 | intel::general::cmdSetEfiBootOptions, Privilege::Operator, | 
|  | 4096 | ipmiOemSetEfiBootOptions); | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 4097 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4098 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4099 | intel::general::cmdGetSecurityMode, Privilege::User, | 
|  | 4100 | ipmiGetSecurityMode); | 
| Richard Marian Thomaiyar | d801e46 | 2019-06-20 01:05:40 +0530 | [diff] [blame] | 4101 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4102 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4103 | intel::general::cmdSetSecurityMode, Privilege::Admin, | 
|  | 4104 | ipmiSetSecurityMode); | 
| Vernon Mauery | 4ac799d | 2019-05-20 15:50:37 -0700 | [diff] [blame] | 4105 |  | 
| NITIN SHARMA | abd11ca | 2019-06-12 12:31:42 +0000 | [diff] [blame] | 4106 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4107 | intel::general::cmdGetLEDStatus, Privilege::Admin, | 
|  | 4108 | ipmiOEMGetLEDStatus); | 
| Cheng C Yang | 773703a | 2019-08-15 09:41:11 +0800 | [diff] [blame] | 4109 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4110 | ipmiPrintAndRegister(ipmi::intel::netFnPlatform, | 
|  | 4111 | ipmi::intel::platform::cmdCfgHostSerialPortSpeed, NULL, | 
|  | 4112 | ipmiOEMCfgHostSerialPortSpeed, PRIVILEGE_ADMIN); | 
|  | 4113 |  | 
|  | 4114 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4115 | intel::general::cmdSetFaultIndication, Privilege::Operator, | 
|  | 4116 | ipmiOEMSetFaultIndication); | 
|  | 4117 |  | 
|  | 4118 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4119 | intel::general::cmdSetColdRedundancyConfig, Privilege::User, | 
|  | 4120 | ipmiOEMSetCRConfig); | 
|  | 4121 |  | 
|  | 4122 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4123 | intel::general::cmdGetColdRedundancyConfig, Privilege::User, | 
|  | 4124 | ipmiOEMGetCRConfig); | 
|  | 4125 |  | 
|  | 4126 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4127 | intel::general::cmdRestoreConfiguration, Privilege::Admin, | 
| Vernon Mauery | 4ac799d | 2019-05-20 15:50:37 -0700 | [diff] [blame] | 4128 | ipmiRestoreConfiguration); | 
| James Feist | 63efafa | 2019-07-24 12:39:21 -0700 | [diff] [blame] | 4129 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4130 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4131 | intel::general::cmdSetDimmOffset, Privilege::Operator, | 
|  | 4132 | ipmiOEMSetDimmOffset); | 
| James Feist | 63efafa | 2019-07-24 12:39:21 -0700 | [diff] [blame] | 4133 |  | 
| Vernon Mauery | 98bbf69 | 2019-09-16 11:14:59 -0700 | [diff] [blame] | 4134 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4135 | intel::general::cmdGetDimmOffset, Privilege::Operator, | 
|  | 4136 | ipmiOEMGetDimmOffset); | 
| Chen Yugang | ca12a7b | 2019-09-03 18:11:44 +0800 | [diff] [blame] | 4137 |  | 
| Cheng C Yang | 4e6ee15 | 2019-09-25 10:27:44 +0800 | [diff] [blame] | 4138 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4139 | intel::general::cmdGetPSUVersion, Privilege::User, | 
|  | 4140 | ipmiOEMGetPSUVersion); | 
| AppaRao Puli | 2897206 | 2019-11-11 02:04:45 +0530 | [diff] [blame] | 4141 |  | 
|  | 4142 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4143 | intel::general::cmdGetBufferSize, Privilege::User, | 
|  | 4144 | ipmiOEMGetBufferSize); | 
| srikanta mondal | 2030d7c | 2020-05-03 17:25:25 +0000 | [diff] [blame] | 4145 |  | 
|  | 4146 | registerHandler(prioOemBase, intel::netFnGeneral, | 
|  | 4147 | intel::general::cmdOEMGetReading, Privilege::User, | 
|  | 4148 | ipmiOEMGetReading); | 
| Ankita Vilas Gawade | a165038 | 2022-01-08 10:30:40 +0000 | [diff] [blame^] | 4149 |  | 
|  | 4150 | registerHandler(prioOemBase, intel::netFnApp, intel::app::cmdPFRMailboxRead, | 
|  | 4151 | Privilege::Admin, ipmiOEMReadPFRMailbox); | 
| Jia, Chunhui | a835eaa | 2018-09-05 09:00:41 +0800 | [diff] [blame] | 4152 | } | 
|  | 4153 |  | 
|  | 4154 | } // namespace ipmi |