1a835eaa0SJia, Chunhui /*
2a835eaa0SJia, Chunhui // Copyright (c) 2018 Intel Corporation
3a835eaa0SJia, Chunhui //
4a835eaa0SJia, Chunhui // Licensed under the Apache License, Version 2.0 (the "License");
5a835eaa0SJia, Chunhui // you may not use this file except in compliance with the License.
6a835eaa0SJia, Chunhui // You may obtain a copy of the License at
7a835eaa0SJia, Chunhui //
8a835eaa0SJia, Chunhui // http://www.apache.org/licenses/LICENSE-2.0
9a835eaa0SJia, Chunhui //
10a835eaa0SJia, Chunhui // Unless required by applicable law or agreed to in writing, software
11a835eaa0SJia, Chunhui // distributed under the License is distributed on an "AS IS" BASIS,
12a835eaa0SJia, Chunhui // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13a835eaa0SJia, Chunhui // See the License for the specific language governing permissions and
14a835eaa0SJia, Chunhui // limitations under the License.
15a835eaa0SJia, Chunhui */
16a835eaa0SJia, Chunhui
17c2a07d4bSPatrick Venture #include "types.hpp"
1864796041SJason M. Bills #include "xyz/openbmc_project/Common/error.hpp"
1945f04988SKuiying Wang #include "xyz/openbmc_project/Led/Physical/server.hpp"
2064796041SJason M. Bills
219420416aSJayaprakash Mutyala #include <openssl/crypto.h>
22cc49b54bSJia, Chunhui #include <systemd/sd-journal.h>
23a835eaa0SJia, Chunhui
247a04f3a4SChen Yugang #include <appcommands.hpp>
2591244a6aSJames Feist #include <boost/container/flat_map.hpp>
2623737fe3SYong Li #include <boost/process/child.hpp>
2723737fe3SYong Li #include <boost/process/io.hpp>
280669d193SYong Li #include <com/intel/Control/OCOTShutdownPolicy/server.hpp>
2964796041SJason M. Bills #include <commandutils.hpp>
30ce4e73fdSZhikui Ren #include <gpiod.hpp>
31cc49b54bSJia, Chunhui #include <ipmid/api.hpp>
325480ef62SVernon Mauery #include <ipmid/utils.hpp>
3363efafacSJames Feist #include <nlohmann/json.hpp>
34a835eaa0SJia, Chunhui #include <oemcommands.hpp>
35a835eaa0SJia, Chunhui #include <phosphor-logging/log.hpp>
36a835eaa0SJia, Chunhui #include <sdbusplus/bus.hpp>
37d509eb91SSuryakanth Sekar #include <sdbusplus/message/types.hpp>
3897cf96e6SChen Yugang #include <xyz/openbmc_project/Chassis/Control/NMISource/server.hpp>
394f7e76bbSChen,Yugang #include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
404f7e76bbSChen,Yugang #include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
41773703a5SCheng C Yang #include <xyz/openbmc_project/Control/PowerSupplyRedundancy/server.hpp>
42d801e463SRichard Marian Thomaiyar #include <xyz/openbmc_project/Control/Security/RestrictionMode/server.hpp>
438d4f8d73SRichard Marian Thomaiyar #include <xyz/openbmc_project/Control/Security/SpecialMode/server.hpp>
44a835eaa0SJia, Chunhui
45fcd2d3a9SJames Feist #include <array>
46fcd2d3a9SJames Feist #include <filesystem>
47493d7761SJason M. Bills #include <fstream>
48fcd2d3a9SJames Feist #include <iostream>
49fcd2d3a9SJames Feist #include <regex>
50a165038fSAnkita Vilas Gawade #include <set>
51fcd2d3a9SJames Feist #include <string>
52fcd2d3a9SJames Feist #include <variant>
53fcd2d3a9SJames Feist #include <vector>
54fcd2d3a9SJames Feist
55a835eaa0SJia, Chunhui namespace ipmi
56a835eaa0SJia, Chunhui {
5764796041SJason M. Bills static void registerOEMFunctions() __attribute__((constructor));
584ac799d7SVernon Mauery
5964796041SJason M. Bills static constexpr size_t maxFRUStringLength = 0x3F;
60a835eaa0SJia, Chunhui
61d509eb91SSuryakanth Sekar static constexpr auto ethernetIntf =
62d509eb91SSuryakanth Sekar "xyz.openbmc_project.Network.EthernetInterface";
63d509eb91SSuryakanth Sekar static constexpr auto networkIPIntf = "xyz.openbmc_project.Network.IP";
64d509eb91SSuryakanth Sekar static constexpr auto networkService = "xyz.openbmc_project.Network";
65d509eb91SSuryakanth Sekar static constexpr auto networkRoot = "/xyz/openbmc_project/network";
66d509eb91SSuryakanth Sekar
6797cf96e6SChen Yugang static constexpr const char* oemNmiSourceIntf =
6897cf96e6SChen Yugang "xyz.openbmc_project.Chassis.Control.NMISource";
6939736d59SChen Yugang static constexpr const char* oemNmiSourceObjPath =
7097cf96e6SChen Yugang "/xyz/openbmc_project/Chassis/Control/NMISource";
7139736d59SChen Yugang static constexpr const char* oemNmiBmcSourceObjPathProp = "BMCSource";
7239736d59SChen Yugang static constexpr const char* oemNmiEnabledObjPathProp = "Enabled";
7339736d59SChen Yugang
7463efafacSJames Feist static constexpr const char* dimmOffsetFile = "/var/lib/ipmi/ipmi_dimms.json";
752030d7c8Ssrikanta mondal static constexpr const char* multiNodeObjPath =
762030d7c8Ssrikanta mondal "/xyz/openbmc_project/MultiNode/Status";
772030d7c8Ssrikanta mondal static constexpr const char* multiNodeIntf =
782030d7c8Ssrikanta mondal "xyz.openbmc_project.Chassis.MultiNode";
7963efafacSJames Feist
8039736d59SChen Yugang enum class NmiSource : uint8_t
8139736d59SChen Yugang {
8239736d59SChen Yugang none = 0,
8397cf96e6SChen Yugang frontPanelButton = 1,
8497cf96e6SChen Yugang watchdog = 2,
8597cf96e6SChen Yugang chassisCmd = 3,
8697cf96e6SChen Yugang memoryError = 4,
8797cf96e6SChen Yugang pciBusError = 5,
8897cf96e6SChen Yugang pch = 6,
8997cf96e6SChen Yugang chipset = 7,
9039736d59SChen Yugang };
9139736d59SChen Yugang
92822b0b40SSuryakanth Sekar enum class SpecialUserIndex : uint8_t
93822b0b40SSuryakanth Sekar {
94822b0b40SSuryakanth Sekar rootUser = 0,
95822b0b40SSuryakanth Sekar atScaleDebugUser = 1
96822b0b40SSuryakanth Sekar };
97822b0b40SSuryakanth Sekar
98d801e463SRichard Marian Thomaiyar static constexpr const char* restricionModeService =
99d801e463SRichard Marian Thomaiyar "xyz.openbmc_project.RestrictionMode.Manager";
100d801e463SRichard Marian Thomaiyar static constexpr const char* restricionModeBasePath =
101d801e463SRichard Marian Thomaiyar "/xyz/openbmc_project/control/security/restriction_mode";
102d801e463SRichard Marian Thomaiyar static constexpr const char* restricionModeIntf =
103d801e463SRichard Marian Thomaiyar "xyz.openbmc_project.Control.Security.RestrictionMode";
104d801e463SRichard Marian Thomaiyar static constexpr const char* restricionModeProperty = "RestrictionMode";
105d801e463SRichard Marian Thomaiyar
106d801e463SRichard Marian Thomaiyar static constexpr const char* specialModeService =
107d801e463SRichard Marian Thomaiyar "xyz.openbmc_project.SpecialMode";
108d801e463SRichard Marian Thomaiyar static constexpr const char* specialModeBasePath =
109a7b74288SRichard Marian Thomaiyar "/xyz/openbmc_project/security/special_mode";
110d801e463SRichard Marian Thomaiyar static constexpr const char* specialModeIntf =
111d801e463SRichard Marian Thomaiyar "xyz.openbmc_project.Security.SpecialMode";
112d801e463SRichard Marian Thomaiyar static constexpr const char* specialModeProperty = "SpecialMode";
113d801e463SRichard Marian Thomaiyar
114d801e463SRichard Marian Thomaiyar static constexpr const char* dBusPropertyIntf =
115d801e463SRichard Marian Thomaiyar "org.freedesktop.DBus.Properties";
116d801e463SRichard Marian Thomaiyar static constexpr const char* dBusPropertyGetMethod = "Get";
117d801e463SRichard Marian Thomaiyar static constexpr const char* dBusPropertySetMethod = "Set";
118d801e463SRichard Marian Thomaiyar
119a835eaa0SJia, Chunhui // return code: 0 successful
getChassisSerialNumber(sdbusplus::bus_t & bus,std::string & serial)120f944d2e5SPatrick Williams int8_t getChassisSerialNumber(sdbusplus::bus_t& bus, std::string& serial)
121a835eaa0SJia, Chunhui {
122a835eaa0SJia, Chunhui std::string objpath = "/xyz/openbmc_project/FruDevice";
123a835eaa0SJia, Chunhui std::string intf = "xyz.openbmc_project.FruDeviceManager";
124a835eaa0SJia, Chunhui std::string service = getService(bus, intf, objpath);
125a835eaa0SJia, Chunhui ObjectValueTree valueTree = getManagedObjects(bus, service, "/");
126a835eaa0SJia, Chunhui if (valueTree.empty())
127a835eaa0SJia, Chunhui {
128a835eaa0SJia, Chunhui phosphor::logging::log<phosphor::logging::level::ERR>(
129a835eaa0SJia, Chunhui "No object implements interface",
130a835eaa0SJia, Chunhui phosphor::logging::entry("INTF=%s", intf.c_str()));
131a835eaa0SJia, Chunhui return -1;
132a835eaa0SJia, Chunhui }
133a835eaa0SJia, Chunhui
13464796041SJason M. Bills for (const auto& item : valueTree)
135a835eaa0SJia, Chunhui {
136a835eaa0SJia, Chunhui auto interface = item.second.find("xyz.openbmc_project.FruDevice");
137a835eaa0SJia, Chunhui if (interface == item.second.end())
138a835eaa0SJia, Chunhui {
139a835eaa0SJia, Chunhui continue;
140a835eaa0SJia, Chunhui }
141a835eaa0SJia, Chunhui
142a835eaa0SJia, Chunhui auto property = interface->second.find("CHASSIS_SERIAL_NUMBER");
143a835eaa0SJia, Chunhui if (property == interface->second.end())
144a835eaa0SJia, Chunhui {
145a835eaa0SJia, Chunhui continue;
146a835eaa0SJia, Chunhui }
147a835eaa0SJia, Chunhui
148a835eaa0SJia, Chunhui try
149a835eaa0SJia, Chunhui {
150a835eaa0SJia, Chunhui Value variant = property->second;
1518166c8d7SVernon Mauery std::string& result = std::get<std::string>(variant);
15264796041SJason M. Bills if (result.size() > maxFRUStringLength)
153a835eaa0SJia, Chunhui {
154a835eaa0SJia, Chunhui phosphor::logging::log<phosphor::logging::level::ERR>(
155a835eaa0SJia, Chunhui "FRU serial number exceed maximum length");
156a835eaa0SJia, Chunhui return -1;
157a835eaa0SJia, Chunhui }
158a835eaa0SJia, Chunhui serial = result;
159a835eaa0SJia, Chunhui return 0;
160a835eaa0SJia, Chunhui }
161bd51e6a9SPatrick Williams catch (const std::bad_variant_access& e)
162a835eaa0SJia, Chunhui {
16364796041SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
164a835eaa0SJia, Chunhui return -1;
165a835eaa0SJia, Chunhui }
166a835eaa0SJia, Chunhui }
167a835eaa0SJia, Chunhui return -1;
168a835eaa0SJia, Chunhui }
16964796041SJason M. Bills
170a165038fSAnkita Vilas Gawade namespace mailbox
171a165038fSAnkita Vilas Gawade {
172a165038fSAnkita Vilas Gawade static uint8_t bus = 4;
173a165038fSAnkita Vilas Gawade static std::string i2cBus = "/dev/i2c-" + std::to_string(bus);
17480d4d5f9SMatt Simmering static uint8_t targetAddr = 56;
175a165038fSAnkita Vilas Gawade static constexpr auto systemRoot = "/xyz/openbmc_project/inventory/system";
176a165038fSAnkita Vilas Gawade static constexpr auto sessionIntf = "xyz.openbmc_project.Configuration.PFR";
177a165038fSAnkita Vilas Gawade const std::string match = "Baseboard/PFR";
178a165038fSAnkita Vilas Gawade static bool i2cConfigLoaded = false;
179a165038fSAnkita Vilas Gawade // Command register for UFM provisioning/access commands; read/write allowed
180a165038fSAnkita Vilas Gawade // from CPU/BMC.
181a165038fSAnkita Vilas Gawade static const constexpr uint8_t provisioningCommand = 0x0b;
182a165038fSAnkita Vilas Gawade // Trigger register for the command set in the previous offset.
183a165038fSAnkita Vilas Gawade static const constexpr uint8_t triggerCommand = 0x0c;
184a165038fSAnkita Vilas Gawade // Set 0x0c to 0x05 to execute command specified at “UFM/Provisioning Command”
185a165038fSAnkita Vilas Gawade // register
186a165038fSAnkita Vilas Gawade static const constexpr uint8_t flushRead = 0x05;
187a165038fSAnkita Vilas Gawade // FIFO read registers
188a165038fSAnkita Vilas Gawade std::set<uint8_t> readFifoReg = {0x08, 0x0C, 0x0D, 0x13};
189a165038fSAnkita Vilas Gawade
190a165038fSAnkita Vilas Gawade // UFM Read FIFO
191a165038fSAnkita Vilas Gawade static const constexpr uint8_t readFifo = 0x0e;
192a165038fSAnkita Vilas Gawade
193a165038fSAnkita Vilas Gawade enum registerType : uint8_t
194a165038fSAnkita Vilas Gawade {
195a165038fSAnkita Vilas Gawade singleByteRegister = 0,
196a165038fSAnkita Vilas Gawade fifoReadRegister,
197a165038fSAnkita Vilas Gawade
198a165038fSAnkita Vilas Gawade };
199a165038fSAnkita Vilas Gawade
loadPfrConfig(ipmi::Context::ptr & ctx,bool & i2cConfigLoaded)200a165038fSAnkita Vilas Gawade void loadPfrConfig(ipmi::Context::ptr& ctx, bool& i2cConfigLoaded)
201a165038fSAnkita Vilas Gawade {
202a165038fSAnkita Vilas Gawade ipmi::ObjectTree objectTree;
203a165038fSAnkita Vilas Gawade
204a165038fSAnkita Vilas Gawade boost::system::error_code ec = ipmi::getAllDbusObjects(
205a165038fSAnkita Vilas Gawade ctx, systemRoot, sessionIntf, match, objectTree);
206a165038fSAnkita Vilas Gawade
207a165038fSAnkita Vilas Gawade if (ec)
208a165038fSAnkita Vilas Gawade {
209a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
210a165038fSAnkita Vilas Gawade "Failed to fetch PFR object from dbus",
211a165038fSAnkita Vilas Gawade phosphor::logging::entry("INTERFACE=%s", sessionIntf),
212a165038fSAnkita Vilas Gawade phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
213a165038fSAnkita Vilas Gawade
214a165038fSAnkita Vilas Gawade return;
215a165038fSAnkita Vilas Gawade }
216a165038fSAnkita Vilas Gawade
217a165038fSAnkita Vilas Gawade for (auto& softObject : objectTree)
218a165038fSAnkita Vilas Gawade {
219a165038fSAnkita Vilas Gawade const std::string& objPath = softObject.first;
220a165038fSAnkita Vilas Gawade const std::string& serviceName = softObject.second.begin()->first;
221a165038fSAnkita Vilas Gawade // PFR object found.. check for PFR support
222a165038fSAnkita Vilas Gawade ipmi::PropertyMap result;
223a165038fSAnkita Vilas Gawade
224a165038fSAnkita Vilas Gawade ec = ipmi::getAllDbusProperties(ctx, serviceName, objPath, sessionIntf,
225a165038fSAnkita Vilas Gawade result);
226a165038fSAnkita Vilas Gawade
227a165038fSAnkita Vilas Gawade if (ec)
228a165038fSAnkita Vilas Gawade {
229a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
230a165038fSAnkita Vilas Gawade "Failed to fetch pfr properties",
231a165038fSAnkita Vilas Gawade phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
232a165038fSAnkita Vilas Gawade return;
233a165038fSAnkita Vilas Gawade }
234a165038fSAnkita Vilas Gawade
235a165038fSAnkita Vilas Gawade const uint64_t* i2cBusNum = nullptr;
236a165038fSAnkita Vilas Gawade const uint64_t* address = nullptr;
237a165038fSAnkita Vilas Gawade
238a165038fSAnkita Vilas Gawade for (const auto& [propName, propVariant] : result)
239a165038fSAnkita Vilas Gawade {
240a165038fSAnkita Vilas Gawade if (propName == "Address")
241a165038fSAnkita Vilas Gawade {
242a165038fSAnkita Vilas Gawade address = std::get_if<uint64_t>(&propVariant);
243a165038fSAnkita Vilas Gawade }
244a165038fSAnkita Vilas Gawade else if (propName == "Bus")
245a165038fSAnkita Vilas Gawade {
246a165038fSAnkita Vilas Gawade i2cBusNum = std::get_if<uint64_t>(&propVariant);
247a165038fSAnkita Vilas Gawade }
248a165038fSAnkita Vilas Gawade }
249a165038fSAnkita Vilas Gawade
250a165038fSAnkita Vilas Gawade if ((address == nullptr) || (i2cBusNum == nullptr))
251a165038fSAnkita Vilas Gawade {
252a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
253a165038fSAnkita Vilas Gawade "Unable to read the pfr properties");
254a165038fSAnkita Vilas Gawade return;
255a165038fSAnkita Vilas Gawade }
256a165038fSAnkita Vilas Gawade
257a165038fSAnkita Vilas Gawade bus = static_cast<int>(*i2cBusNum);
258a165038fSAnkita Vilas Gawade i2cBus = "/dev/i2c-" + std::to_string(bus);
25980d4d5f9SMatt Simmering targetAddr = static_cast<int>(*address);
260a165038fSAnkita Vilas Gawade
261a165038fSAnkita Vilas Gawade i2cConfigLoaded = true;
262a165038fSAnkita Vilas Gawade }
263a165038fSAnkita Vilas Gawade }
264a165038fSAnkita Vilas Gawade
writefifo(const uint8_t cmdReg,const uint8_t val)265a165038fSAnkita Vilas Gawade void writefifo(const uint8_t cmdReg, const uint8_t val)
266a165038fSAnkita Vilas Gawade {
267a165038fSAnkita Vilas Gawade // Based on the spec, writing cmdReg to address val on this device, will
268a165038fSAnkita Vilas Gawade // trigger the write FIFO operation.
269a165038fSAnkita Vilas Gawade std::vector<uint8_t> writeData = {cmdReg, val};
270a165038fSAnkita Vilas Gawade std::vector<uint8_t> readBuf(0);
2711bcced08SPatrick Williams ipmi::Cc retI2C =
2721bcced08SPatrick Williams ipmi::i2cWriteRead(i2cBus, targetAddr, writeData, readBuf);
273dcff1506SVernon Mauery if (retI2C)
274dcff1506SVernon Mauery {
275dcff1506SVernon Mauery phosphor::logging::log<phosphor::logging::level::ERR>(
276dcff1506SVernon Mauery "i2cWriteRead returns non-zero");
277dcff1506SVernon Mauery }
278a165038fSAnkita Vilas Gawade }
279a165038fSAnkita Vilas Gawade
280a165038fSAnkita Vilas Gawade } // namespace mailbox
281a165038fSAnkita Vilas Gawade
ipmiOEMGetBmcVersionString()282af65268eSVernon Mauery ipmi::RspType<std::string> ipmiOEMGetBmcVersionString()
283af65268eSVernon Mauery {
284af65268eSVernon Mauery static std::string version{};
285af65268eSVernon Mauery if (version.empty())
286af65268eSVernon Mauery {
287af65268eSVernon Mauery std::regex expr{"^VERSION_ID=(.*)$"};
288af65268eSVernon Mauery static constexpr auto osReleasePath{"/etc/os-release"};
289af65268eSVernon Mauery std::ifstream ifs(osReleasePath);
290af65268eSVernon Mauery if (!ifs.is_open())
291af65268eSVernon Mauery {
292af65268eSVernon Mauery version = "os-release not present";
293af65268eSVernon Mauery }
294af65268eSVernon Mauery std::string line{};
295af65268eSVernon Mauery while (std::getline(ifs, line))
296af65268eSVernon Mauery {
297af65268eSVernon Mauery std::smatch sm;
298af65268eSVernon Mauery if (regex_match(line, sm, expr))
299af65268eSVernon Mauery {
300af65268eSVernon Mauery if (sm.size() == 2)
301af65268eSVernon Mauery {
302af65268eSVernon Mauery std::string v = sm[1].str();
303af65268eSVernon Mauery // remove the quotes
304af65268eSVernon Mauery v.erase(std::remove(v.begin(), v.end(), '\"'), v.end());
305af65268eSVernon Mauery version = v;
306af65268eSVernon Mauery break;
307af65268eSVernon Mauery }
308af65268eSVernon Mauery }
309af65268eSVernon Mauery }
310af65268eSVernon Mauery ifs.close();
311af65268eSVernon Mauery if (version.empty())
312af65268eSVernon Mauery {
313af65268eSVernon Mauery version = "VERSION_ID not present";
314af65268eSVernon Mauery }
315af65268eSVernon Mauery }
316af65268eSVernon Mauery return ipmi::responseSuccess(version);
317af65268eSVernon Mauery }
318af65268eSVernon Mauery
319a835eaa0SJia, Chunhui // Returns the Chassis Identifier (serial #)
ipmiOEMGetChassisIdentifier(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t,ipmi_response_t response,ipmi_data_len_t dataLen,ipmi_context_t)320dcff1506SVernon Mauery ipmi_ret_t ipmiOEMGetChassisIdentifier(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
321a835eaa0SJia, Chunhui ipmi_response_t response,
322dcff1506SVernon Mauery ipmi_data_len_t dataLen, ipmi_context_t)
323a835eaa0SJia, Chunhui {
324a835eaa0SJia, Chunhui std::string serial;
32564796041SJason M. Bills if (*dataLen != 0) // invalid request if there are extra parameters
326a835eaa0SJia, Chunhui {
32764796041SJason M. Bills *dataLen = 0;
328a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID;
329a835eaa0SJia, Chunhui }
33015419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
33115419dd5SVernon Mauery if (getChassisSerialNumber(*dbus, serial) == 0)
332a835eaa0SJia, Chunhui {
33364796041SJason M. Bills *dataLen = serial.size(); // length will never exceed response length
334a835eaa0SJia, Chunhui // as it is checked in getChassisSerialNumber
335a835eaa0SJia, Chunhui char* resp = static_cast<char*>(response);
33664796041SJason M. Bills serial.copy(resp, *dataLen);
337a835eaa0SJia, Chunhui return IPMI_CC_OK;
338a835eaa0SJia, Chunhui }
33964796041SJason M. Bills *dataLen = 0;
340a835eaa0SJia, Chunhui return IPMI_CC_RESPONSE_ERROR;
341a835eaa0SJia, Chunhui }
342a835eaa0SJia, Chunhui
ipmiOEMSetSystemGUID(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t request,ipmi_response_t,ipmi_data_len_t dataLen,ipmi_context_t)343dcff1506SVernon Mauery ipmi_ret_t ipmiOEMSetSystemGUID(ipmi_netfn_t, ipmi_cmd_t,
344dcff1506SVernon Mauery ipmi_request_t request, ipmi_response_t,
345dcff1506SVernon Mauery ipmi_data_len_t dataLen, ipmi_context_t)
346a835eaa0SJia, Chunhui {
347a835eaa0SJia, Chunhui static constexpr size_t safeBufferLength = 50;
348a835eaa0SJia, Chunhui char buf[safeBufferLength] = {0};
349a835eaa0SJia, Chunhui GUIDData* Data = reinterpret_cast<GUIDData*>(request);
350a835eaa0SJia, Chunhui
35164796041SJason M. Bills if (*dataLen != sizeof(GUIDData)) // 16bytes
352a835eaa0SJia, Chunhui {
35364796041SJason M. Bills *dataLen = 0;
354a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID;
355a835eaa0SJia, Chunhui }
356a835eaa0SJia, Chunhui
35764796041SJason M. Bills *dataLen = 0;
358a835eaa0SJia, Chunhui
359a835eaa0SJia, Chunhui snprintf(
360a835eaa0SJia, Chunhui buf, safeBufferLength,
361a835eaa0SJia, Chunhui "%02x%02x%02x%02x-%02x%02x-%02x%02x-%02x%02x-%02x%02x%02x%02x%02x%02x",
362a835eaa0SJia, Chunhui Data->timeLow4, Data->timeLow3, Data->timeLow2, Data->timeLow1,
363a835eaa0SJia, Chunhui Data->timeMid2, Data->timeMid1, Data->timeHigh2, Data->timeHigh1,
364a835eaa0SJia, Chunhui Data->clock2, Data->clock1, Data->node6, Data->node5, Data->node4,
365a835eaa0SJia, Chunhui Data->node3, Data->node2, Data->node1);
366a835eaa0SJia, Chunhui // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
367a835eaa0SJia, Chunhui std::string guid = buf;
368a835eaa0SJia, Chunhui
369a835eaa0SJia, Chunhui std::string objpath = "/xyz/openbmc_project/control/host0/systemGUID";
370a835eaa0SJia, Chunhui std::string intf = "xyz.openbmc_project.Common.UUID";
37115419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
37215419dd5SVernon Mauery std::string service = getService(*dbus, intf, objpath);
37315419dd5SVernon Mauery setDbusProperty(*dbus, service, objpath, intf, "UUID", guid);
374a835eaa0SJia, Chunhui return IPMI_CC_OK;
375a835eaa0SJia, Chunhui }
376a835eaa0SJia, Chunhui
3771bcced08SPatrick Williams ipmi::RspType<>
ipmiOEMDisableBMCSystemReset(bool disableResetOnSMI,uint7_t reserved1)3781bcced08SPatrick Williams ipmiOEMDisableBMCSystemReset(bool disableResetOnSMI, uint7_t reserved1)
379b02bf095SJason M. Bills {
3800a652fa9SJayaprakash Mutyala if (reserved1)
3810a652fa9SJayaprakash Mutyala {
3820a652fa9SJayaprakash Mutyala return ipmi::responseInvalidFieldRequest();
3830a652fa9SJayaprakash Mutyala }
3840a652fa9SJayaprakash Mutyala
385b02bf095SJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
386b02bf095SJason M. Bills
387b02bf095SJason M. Bills try
388b02bf095SJason M. Bills {
3891bcced08SPatrick Williams auto service =
3901bcced08SPatrick Williams ipmi::getService(*busp, bmcResetDisablesIntf, bmcResetDisablesPath);
391b02bf095SJason M. Bills ipmi::setDbusProperty(*busp, service, bmcResetDisablesPath,
392b02bf095SJason M. Bills bmcResetDisablesIntf, "ResetOnSMI",
393b02bf095SJason M. Bills !disableResetOnSMI);
394b02bf095SJason M. Bills }
395bd51e6a9SPatrick Williams catch (const std::exception& e)
396b02bf095SJason M. Bills {
397b02bf095SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(
398b02bf095SJason M. Bills "Failed to set BMC reset disables",
399b02bf095SJason M. Bills phosphor::logging::entry("EXCEPTION=%s", e.what()));
400b02bf095SJason M. Bills return ipmi::responseUnspecifiedError();
401b02bf095SJason M. Bills }
402b02bf095SJason M. Bills
403b02bf095SJason M. Bills return ipmi::responseSuccess();
404b02bf095SJason M. Bills }
405b02bf095SJason M. Bills
406b02bf095SJason M. Bills ipmi::RspType<bool, // disableResetOnSMI
407b02bf095SJason M. Bills uint7_t // reserved
408b02bf095SJason M. Bills >
ipmiOEMGetBMCResetDisables()409b02bf095SJason M. Bills ipmiOEMGetBMCResetDisables()
410b02bf095SJason M. Bills {
411b02bf095SJason M. Bills bool disableResetOnSMI = true;
412b02bf095SJason M. Bills
413b02bf095SJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
414b02bf095SJason M. Bills try
415b02bf095SJason M. Bills {
4161bcced08SPatrick Williams auto service =
4171bcced08SPatrick Williams ipmi::getService(*busp, bmcResetDisablesIntf, bmcResetDisablesPath);
418b02bf095SJason M. Bills Value variant =
419b02bf095SJason M. Bills ipmi::getDbusProperty(*busp, service, bmcResetDisablesPath,
420b02bf095SJason M. Bills bmcResetDisablesIntf, "ResetOnSMI");
421b02bf095SJason M. Bills disableResetOnSMI = !std::get<bool>(variant);
422b02bf095SJason M. Bills }
423bd51e6a9SPatrick Williams catch (const std::exception& e)
424b02bf095SJason M. Bills {
425b02bf095SJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(
426b02bf095SJason M. Bills "Failed to get BMC reset disables",
427b02bf095SJason M. Bills phosphor::logging::entry("EXCEPTION=%s", e.what()));
428b02bf095SJason M. Bills return ipmi::responseUnspecifiedError();
429b02bf095SJason M. Bills }
430b02bf095SJason M. Bills
431b02bf095SJason M. Bills return ipmi::responseSuccess(disableResetOnSMI, 0);
432b02bf095SJason M. Bills }
433b02bf095SJason M. Bills
ipmiOEMSetBIOSID(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t request,ipmi_response_t response,ipmi_data_len_t dataLen,ipmi_context_t)434dcff1506SVernon Mauery ipmi_ret_t ipmiOEMSetBIOSID(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request,
435dcff1506SVernon Mauery ipmi_response_t response, ipmi_data_len_t dataLen,
436dcff1506SVernon Mauery ipmi_context_t)
437a835eaa0SJia, Chunhui {
438a835eaa0SJia, Chunhui DeviceInfo* data = reinterpret_cast<DeviceInfo*>(request);
439a835eaa0SJia, Chunhui
440dcff1506SVernon Mauery if ((*dataLen < 2ul) || (*dataLen != (1ul + data->biosIDLength)))
441a835eaa0SJia, Chunhui {
442a835eaa0SJia, Chunhui *dataLen = 0;
443a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID;
444a835eaa0SJia, Chunhui }
44564796041SJason M. Bills std::string idString((char*)data->biosId, data->biosIDLength);
446fb9f1aa1SChalapathi Venkataramashetty for (auto idChar : idString)
447fb9f1aa1SChalapathi Venkataramashetty {
448fb9f1aa1SChalapathi Venkataramashetty if (!std::isprint(static_cast<unsigned char>(idChar)))
449fb9f1aa1SChalapathi Venkataramashetty {
450fb9f1aa1SChalapathi Venkataramashetty phosphor::logging::log<phosphor::logging::level::ERR>(
451fb9f1aa1SChalapathi Venkataramashetty "BIOS ID contains non printable character");
452fb9f1aa1SChalapathi Venkataramashetty return IPMI_CC_INVALID_FIELD_REQUEST;
453fb9f1aa1SChalapathi Venkataramashetty }
454fb9f1aa1SChalapathi Venkataramashetty }
455a835eaa0SJia, Chunhui
45615419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
457899bfd15SChalapathi std::string service = getService(*dbus, biosVersionIntf, biosActiveObjPath);
458899bfd15SChalapathi setDbusProperty(*dbus, service, biosActiveObjPath, biosVersionIntf,
4592742b85cSYong Li biosVersionProp, idString);
460a835eaa0SJia, Chunhui uint8_t* bytesWritten = static_cast<uint8_t*>(response);
461a835eaa0SJia, Chunhui *bytesWritten =
46264796041SJason M. Bills data->biosIDLength; // how many bytes are written into storage
463a835eaa0SJia, Chunhui *dataLen = 1;
464a835eaa0SJia, Chunhui return IPMI_CC_OK;
465a835eaa0SJia, Chunhui }
466a835eaa0SJia, Chunhui
getActiveHSCSoftwareVersionInfo(std::string & hscVersion,size_t hscNumber)46790da3d9dSJayaprakash Mutyala bool getActiveHSCSoftwareVersionInfo(std::string& hscVersion, size_t hscNumber)
46890da3d9dSJayaprakash Mutyala {
46990da3d9dSJayaprakash Mutyala std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
47090da3d9dSJayaprakash Mutyala try
47190da3d9dSJayaprakash Mutyala {
4721bcced08SPatrick Williams std::string hsbpObjPath =
4731bcced08SPatrick Williams "/xyz/openbmc_project/software/HSBP_" + std::to_string(hscNumber);
47490da3d9dSJayaprakash Mutyala auto service = getService(*dbus, biosVersionIntf, hsbpObjPath);
47590da3d9dSJayaprakash Mutyala Value hscVersionValue =
47690da3d9dSJayaprakash Mutyala getDbusProperty(*dbus, "xyz.openbmc_project.HsbpManager",
47790da3d9dSJayaprakash Mutyala hsbpObjPath, biosVersionIntf, "Version");
47890da3d9dSJayaprakash Mutyala hscVersion = std::get<std::string>(hscVersionValue);
47990da3d9dSJayaprakash Mutyala }
480f944d2e5SPatrick Williams catch (const sdbusplus::exception_t& e)
48190da3d9dSJayaprakash Mutyala {
48290da3d9dSJayaprakash Mutyala phosphor::logging::log<phosphor::logging::level::INFO>(
48390da3d9dSJayaprakash Mutyala "Failed to retrieve HSBP version information",
48490da3d9dSJayaprakash Mutyala phosphor::logging::entry("HSBP Number=%d", hscNumber));
48590da3d9dSJayaprakash Mutyala return false;
48690da3d9dSJayaprakash Mutyala }
48790da3d9dSJayaprakash Mutyala return true;
48890da3d9dSJayaprakash Mutyala }
48990da3d9dSJayaprakash Mutyala
getHscVerInfo(ipmi::Context::ptr &,uint8_t & hsc0Major,uint8_t & hsc0Minor,uint8_t & hsc1Major,uint8_t & hsc1Minor,uint8_t & hsc2Major,uint8_t & hsc2Minor)490dcff1506SVernon Mauery bool getHscVerInfo(ipmi::Context::ptr&, uint8_t& hsc0Major, uint8_t& hsc0Minor,
491dcff1506SVernon Mauery uint8_t& hsc1Major, uint8_t& hsc1Minor, uint8_t& hsc2Major,
492dcff1506SVernon Mauery uint8_t& hsc2Minor)
49390da3d9dSJayaprakash Mutyala {
49490da3d9dSJayaprakash Mutyala std::string hscVersion;
49590da3d9dSJayaprakash Mutyala std::array<uint8_t, 6> hscVersions{0};
49690da3d9dSJayaprakash Mutyala
49790da3d9dSJayaprakash Mutyala for (size_t hscNumber = 1; hscNumber <= 3; hscNumber++)
49890da3d9dSJayaprakash Mutyala {
49990da3d9dSJayaprakash Mutyala if (!getActiveHSCSoftwareVersionInfo(hscVersion, hscNumber))
50090da3d9dSJayaprakash Mutyala {
50190da3d9dSJayaprakash Mutyala continue;
50290da3d9dSJayaprakash Mutyala }
50390da3d9dSJayaprakash Mutyala std::regex pattern1("(\\d+?).(\\d+?).(\\d+?)");
50490da3d9dSJayaprakash Mutyala constexpr size_t matchedPhosphor = 4;
50590da3d9dSJayaprakash Mutyala std::smatch results;
50690da3d9dSJayaprakash Mutyala // hscVersion = BOOT_VER.FPGA_VER.SECURITY_REVISION (Example: 00.02.01)
50790da3d9dSJayaprakash Mutyala if (std::regex_match(hscVersion, results, pattern1))
50890da3d9dSJayaprakash Mutyala {
50990da3d9dSJayaprakash Mutyala // Major version is FPGA_VER and Minor version is SECURITY_REV
51090da3d9dSJayaprakash Mutyala if (results.size() == matchedPhosphor)
51190da3d9dSJayaprakash Mutyala {
51290da3d9dSJayaprakash Mutyala int index = (hscNumber - 1) * 2;
51390da3d9dSJayaprakash Mutyala hscVersions[index] =
51490da3d9dSJayaprakash Mutyala static_cast<uint8_t>(std::stoi(results[2]));
51590da3d9dSJayaprakash Mutyala hscVersions[index + 1] =
51690da3d9dSJayaprakash Mutyala static_cast<uint8_t>(std::stoi(results[3]));
51790da3d9dSJayaprakash Mutyala }
51890da3d9dSJayaprakash Mutyala }
51990da3d9dSJayaprakash Mutyala }
52090da3d9dSJayaprakash Mutyala hsc0Major = hscVersions[0];
52190da3d9dSJayaprakash Mutyala hsc0Minor = hscVersions[1];
52290da3d9dSJayaprakash Mutyala hsc1Major = hscVersions[2];
52390da3d9dSJayaprakash Mutyala hsc1Minor = hscVersions[3];
52490da3d9dSJayaprakash Mutyala hsc2Major = hscVersions[4];
52590da3d9dSJayaprakash Mutyala hsc2Minor = hscVersions[5];
52690da3d9dSJayaprakash Mutyala return true;
52790da3d9dSJayaprakash Mutyala }
52890da3d9dSJayaprakash Mutyala
getSwVerInfo(ipmi::Context::ptr & ctx,uint8_t & bmcMajor,uint8_t & bmcMinor,uint8_t & meMajor,uint8_t & meMinor)529dcff1506SVernon Mauery bool getSwVerInfo(ipmi::Context::ptr& ctx, uint8_t& bmcMajor, uint8_t& bmcMinor,
530e99e7ed3SAppaRao Puli uint8_t& meMajor, uint8_t& meMinor)
531a835eaa0SJia, Chunhui {
5327a04f3a4SChen Yugang // step 1 : get BMC Major and Minor numbers from its DBUS property
533e99e7ed3SAppaRao Puli std::string bmcVersion;
534e99e7ed3SAppaRao Puli if (getActiveSoftwareVersionInfo(ctx, versionPurposeBMC, bmcVersion))
5357a04f3a4SChen Yugang {
5367a04f3a4SChen Yugang return false;
537a835eaa0SJia, Chunhui }
538a835eaa0SJia, Chunhui
539e99e7ed3SAppaRao Puli std::optional<MetaRevision> rev = convertIntelVersion(bmcVersion);
5407a04f3a4SChen Yugang if (rev.has_value())
541a835eaa0SJia, Chunhui {
5427a04f3a4SChen Yugang MetaRevision revision = rev.value();
5437a04f3a4SChen Yugang bmcMajor = revision.major;
5447a04f3a4SChen Yugang
5457a04f3a4SChen Yugang revision.minor = (revision.minor > 99 ? 99 : revision.minor);
5467a04f3a4SChen Yugang bmcMinor = revision.minor % 10 + (revision.minor / 10) * 16;
5477a04f3a4SChen Yugang }
5487a04f3a4SChen Yugang
5497a04f3a4SChen Yugang // step 2 : get ME Major and Minor numbers from its DBUS property
55032825a23SAppaRao Puli std::string meVersion;
55132825a23SAppaRao Puli if (getActiveSoftwareVersionInfo(ctx, versionPurposeME, meVersion))
5527a04f3a4SChen Yugang {
55332825a23SAppaRao Puli return false;
55432825a23SAppaRao Puli }
5557a04f3a4SChen Yugang std::regex pattern1("(\\d+?).(\\d+?).(\\d+?).(\\d+?).(\\d+?)");
5567a04f3a4SChen Yugang constexpr size_t matchedPhosphor = 6;
5577a04f3a4SChen Yugang std::smatch results;
558d46cb42bSAppaRao Puli if (std::regex_match(meVersion, results, pattern1))
5597a04f3a4SChen Yugang {
5607a04f3a4SChen Yugang if (results.size() == matchedPhosphor)
5617a04f3a4SChen Yugang {
5627a04f3a4SChen Yugang meMajor = static_cast<uint8_t>(std::stoi(results[1]));
5631bcced08SPatrick Williams meMinor = static_cast<uint8_t>(
5641bcced08SPatrick Williams std::stoi(results[2]) << 4 | std::stoi(results[3]));
5657a04f3a4SChen Yugang }
5667a04f3a4SChen Yugang }
5677a04f3a4SChen Yugang return true;
5687a04f3a4SChen Yugang }
5697a04f3a4SChen Yugang
5707a04f3a4SChen Yugang ipmi::RspType<
5717a04f3a4SChen Yugang std::variant<std::string,
5727a04f3a4SChen Yugang std::tuple<uint8_t, std::array<uint8_t, 2>,
5737a04f3a4SChen Yugang std::array<uint8_t, 2>, std::array<uint8_t, 2>,
5747a04f3a4SChen Yugang std::array<uint8_t, 2>, std::array<uint8_t, 2>>,
5757a04f3a4SChen Yugang std::tuple<uint8_t, std::array<uint8_t, 2>>>>
ipmiOEMGetDeviceInfo(ipmi::Context::ptr & ctx,uint8_t entityType,std::optional<uint8_t> countToRead,std::optional<uint8_t> offset)576dcff1506SVernon Mauery ipmiOEMGetDeviceInfo(ipmi::Context::ptr& ctx, uint8_t entityType,
577e99e7ed3SAppaRao Puli std::optional<uint8_t> countToRead,
578d46cb42bSAppaRao Puli std::optional<uint8_t> offset)
5797a04f3a4SChen Yugang {
5807a04f3a4SChen Yugang if (entityType > static_cast<uint8_t>(OEMDevEntityType::sdrVer))
5817a04f3a4SChen Yugang {
5827a04f3a4SChen Yugang return ipmi::responseInvalidFieldRequest();
583a835eaa0SJia, Chunhui }
584a835eaa0SJia, Chunhui
585a835eaa0SJia, Chunhui // handle OEM command items
5867a04f3a4SChen Yugang switch (OEMDevEntityType(entityType))
587a835eaa0SJia, Chunhui {
588a835eaa0SJia, Chunhui case OEMDevEntityType::biosId:
589a835eaa0SJia, Chunhui {
590d46cb42bSAppaRao Puli // Byte 2&3, Only used with selecting BIOS
591d46cb42bSAppaRao Puli if (!countToRead || !offset)
592d46cb42bSAppaRao Puli {
593d46cb42bSAppaRao Puli return ipmi::responseReqDataLenInvalid();
594d46cb42bSAppaRao Puli }
595d46cb42bSAppaRao Puli
59615419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
5971bcced08SPatrick Williams std::string service =
5981bcced08SPatrick Williams getService(*dbus, biosVersionIntf, biosActiveObjPath);
599a835eaa0SJia, Chunhui try
600a835eaa0SJia, Chunhui {
6012742b85cSYong Li Value variant =
602899bfd15SChalapathi getDbusProperty(*dbus, service, biosActiveObjPath,
6032742b85cSYong Li biosVersionIntf, biosVersionProp);
6048166c8d7SVernon Mauery std::string& idString = std::get<std::string>(variant);
605d46cb42bSAppaRao Puli if (*offset >= idString.size())
606a835eaa0SJia, Chunhui {
6077a04f3a4SChen Yugang return ipmi::responseParmOutOfRange();
608a835eaa0SJia, Chunhui }
609a835eaa0SJia, Chunhui size_t length = 0;
610d46cb42bSAppaRao Puli if (*countToRead > (idString.size() - *offset))
611a835eaa0SJia, Chunhui {
612d46cb42bSAppaRao Puli length = idString.size() - *offset;
613a835eaa0SJia, Chunhui }
614a835eaa0SJia, Chunhui else
615a835eaa0SJia, Chunhui {
616d46cb42bSAppaRao Puli length = *countToRead;
617a835eaa0SJia, Chunhui }
6187a04f3a4SChen Yugang
6197a04f3a4SChen Yugang std::string readBuf = {0};
6207a04f3a4SChen Yugang readBuf.resize(length);
621d46cb42bSAppaRao Puli std::copy_n(idString.begin() + *offset, length,
6227a04f3a4SChen Yugang (readBuf.begin()));
6237a04f3a4SChen Yugang return ipmi::responseSuccess(readBuf);
624a835eaa0SJia, Chunhui }
625bd51e6a9SPatrick Williams catch (const std::bad_variant_access& e)
626a835eaa0SJia, Chunhui {
6277a04f3a4SChen Yugang return ipmi::responseUnspecifiedError();
628a835eaa0SJia, Chunhui }
629a835eaa0SJia, Chunhui }
630a835eaa0SJia, Chunhui break;
631a835eaa0SJia, Chunhui
632a835eaa0SJia, Chunhui case OEMDevEntityType::devVer:
6337a04f3a4SChen Yugang {
634d46cb42bSAppaRao Puli // Byte 2&3, Only used with selecting BIOS
635d46cb42bSAppaRao Puli if (countToRead || offset)
636d46cb42bSAppaRao Puli {
637d46cb42bSAppaRao Puli return ipmi::responseReqDataLenInvalid();
638d46cb42bSAppaRao Puli }
639d46cb42bSAppaRao Puli
6407a04f3a4SChen Yugang constexpr const size_t verLen = 2;
6417a04f3a4SChen Yugang constexpr const size_t verTotalLen = 10;
6427a04f3a4SChen Yugang std::array<uint8_t, verLen> bmcBuf = {0xff, 0xff};
6437a04f3a4SChen Yugang std::array<uint8_t, verLen> hsc0Buf = {0xff, 0xff};
6447a04f3a4SChen Yugang std::array<uint8_t, verLen> hsc1Buf = {0xff, 0xff};
6457a04f3a4SChen Yugang std::array<uint8_t, verLen> meBuf = {0xff, 0xff};
6467a04f3a4SChen Yugang std::array<uint8_t, verLen> hsc2Buf = {0xff, 0xff};
6477a04f3a4SChen Yugang // data0/1: BMC version number; data6/7: ME version number
648e99e7ed3SAppaRao Puli if (!getSwVerInfo(ctx, bmcBuf[0], bmcBuf[1], meBuf[0], meBuf[1]))
6497a04f3a4SChen Yugang {
6507a04f3a4SChen Yugang return ipmi::responseUnspecifiedError();
651a835eaa0SJia, Chunhui }
65290da3d9dSJayaprakash Mutyala if (!getHscVerInfo(ctx, hsc0Buf[0], hsc0Buf[1], hsc1Buf[0],
65390da3d9dSJayaprakash Mutyala hsc1Buf[1], hsc2Buf[0], hsc2Buf[1]))
65490da3d9dSJayaprakash Mutyala {
65590da3d9dSJayaprakash Mutyala return ipmi::responseUnspecifiedError();
65690da3d9dSJayaprakash Mutyala }
6577a04f3a4SChen Yugang return ipmi::responseSuccess(
6587a04f3a4SChen Yugang std::tuple<
6597a04f3a4SChen Yugang uint8_t, std::array<uint8_t, verLen>,
6607a04f3a4SChen Yugang std::array<uint8_t, verLen>, std::array<uint8_t, verLen>,
6617a04f3a4SChen Yugang std::array<uint8_t, verLen>, std::array<uint8_t, verLen>>{
6627a04f3a4SChen Yugang verTotalLen, bmcBuf, hsc0Buf, hsc1Buf, meBuf, hsc2Buf});
6637a04f3a4SChen Yugang }
6647a04f3a4SChen Yugang break;
6657a04f3a4SChen Yugang
6667a04f3a4SChen Yugang case OEMDevEntityType::sdrVer:
6677a04f3a4SChen Yugang {
668d46cb42bSAppaRao Puli // Byte 2&3, Only used with selecting BIOS
669d46cb42bSAppaRao Puli if (countToRead || offset)
670d46cb42bSAppaRao Puli {
671d46cb42bSAppaRao Puli return ipmi::responseReqDataLenInvalid();
672d46cb42bSAppaRao Puli }
673d46cb42bSAppaRao Puli
6747a04f3a4SChen Yugang constexpr const size_t sdrLen = 2;
6757a04f3a4SChen Yugang std::array<uint8_t, sdrLen> readBuf = {0x01, 0x0};
6767a04f3a4SChen Yugang return ipmi::responseSuccess(
6777a04f3a4SChen Yugang std::tuple<uint8_t, std::array<uint8_t, sdrLen>>{sdrLen,
6787a04f3a4SChen Yugang readBuf});
6797a04f3a4SChen Yugang }
6807a04f3a4SChen Yugang break;
6817a04f3a4SChen Yugang
6827a04f3a4SChen Yugang default:
6837a04f3a4SChen Yugang return ipmi::responseInvalidFieldRequest();
6847a04f3a4SChen Yugang }
685a835eaa0SJia, Chunhui }
686a835eaa0SJia, Chunhui
ipmiOEMGetAICFRU(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t,ipmi_response_t response,ipmi_data_len_t dataLen,ipmi_context_t)687dcff1506SVernon Mauery ipmi_ret_t ipmiOEMGetAICFRU(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
688dcff1506SVernon Mauery ipmi_response_t response, ipmi_data_len_t dataLen,
689dcff1506SVernon Mauery ipmi_context_t)
690a835eaa0SJia, Chunhui {
691a835eaa0SJia, Chunhui if (*dataLen != 0)
692a835eaa0SJia, Chunhui {
69364796041SJason M. Bills *dataLen = 0;
694a835eaa0SJia, Chunhui return IPMI_CC_REQ_DATA_LEN_INVALID;
695a835eaa0SJia, Chunhui }
696a835eaa0SJia, Chunhui
697a835eaa0SJia, Chunhui *dataLen = 1;
698a835eaa0SJia, Chunhui uint8_t* res = reinterpret_cast<uint8_t*>(response);
699a835eaa0SJia, Chunhui // temporary fix. We don't support AIC FRU now. Just tell BIOS that no
700a835eaa0SJia, Chunhui // AIC is available so that BIOS will not timeout repeatly which leads to
701a835eaa0SJia, Chunhui // slow booting.
702a835eaa0SJia, Chunhui *res = 0; // Byte1=Count of SlotPosition/FruID records.
703a835eaa0SJia, Chunhui return IPMI_CC_OK;
704a835eaa0SJia, Chunhui }
705a835eaa0SJia, Chunhui
ipmiOEMGetPowerRestoreDelay(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t,ipmi_response_t response,ipmi_data_len_t dataLen,ipmi_context_t)706dcff1506SVernon Mauery ipmi_ret_t ipmiOEMGetPowerRestoreDelay(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
70764796041SJason M. Bills ipmi_response_t response,
708dcff1506SVernon Mauery ipmi_data_len_t dataLen, ipmi_context_t)
709a835eaa0SJia, Chunhui {
71064796041SJason M. Bills GetPowerRestoreDelayRes* resp =
71164796041SJason M. Bills reinterpret_cast<GetPowerRestoreDelayRes*>(response);
71264796041SJason M. Bills
71364796041SJason M. Bills if (*dataLen != 0)
71464796041SJason M. Bills {
71564796041SJason M. Bills *dataLen = 0;
71664796041SJason M. Bills return IPMI_CC_REQ_DATA_LEN_INVALID;
717a835eaa0SJia, Chunhui }
718a835eaa0SJia, Chunhui
71915419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
7201bcced08SPatrick Williams std::string service =
7211bcced08SPatrick Williams getService(*dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath);
7221bcced08SPatrick Williams Value variant =
7231bcced08SPatrick Williams getDbusProperty(*dbus, service, powerRestoreDelayObjPath,
7241bcced08SPatrick Williams powerRestoreDelayIntf, powerRestoreDelayProp);
72564796041SJason M. Bills
726c42c7edeSAndrei Kartashev uint64_t val = std::get<uint64_t>(variant);
727c42c7edeSAndrei Kartashev val /= 1000000UL;
728c42c7edeSAndrei Kartashev uint16_t delay = val;
72964796041SJason M. Bills resp->byteLSB = delay;
73064796041SJason M. Bills resp->byteMSB = delay >> 8;
73164796041SJason M. Bills
73264796041SJason M. Bills *dataLen = sizeof(GetPowerRestoreDelayRes);
73364796041SJason M. Bills
73464796041SJason M. Bills return IPMI_CC_OK;
73564796041SJason M. Bills }
73664796041SJason M. Bills
bcdToDec(uint8_t val)737cc49b54bSJia, Chunhui static uint8_t bcdToDec(uint8_t val)
738cc49b54bSJia, Chunhui {
739cc49b54bSJia, Chunhui return ((val / 16 * 10) + (val % 16));
740cc49b54bSJia, Chunhui }
741cc49b54bSJia, Chunhui
742cc49b54bSJia, Chunhui // Allows an update utility or system BIOS to send the status of an embedded
743cc49b54bSJia, Chunhui // firmware update attempt to the BMC. After received, BMC will create a logging
744cc49b54bSJia, Chunhui // record.
ipmiOEMSendEmbeddedFwUpdStatus(uint8_t status,uint8_t target,uint8_t majorRevision,uint8_t minorRevision,uint32_t auxInfo)7451bcced08SPatrick Williams ipmi::RspType<> ipmiOEMSendEmbeddedFwUpdStatus(
7461bcced08SPatrick Williams uint8_t status, uint8_t target, uint8_t majorRevision,
7471bcced08SPatrick Williams uint8_t minorRevision, uint32_t auxInfo)
748cc49b54bSJia, Chunhui {
749cc49b54bSJia, Chunhui std::string firmware;
750dc24927fSJason M. Bills int instance = (target & targetInstanceMask) >> targetInstanceShift;
751cc49b54bSJia, Chunhui target = (target & selEvtTargetMask) >> selEvtTargetShift;
752cc49b54bSJia, Chunhui
753cc49b54bSJia, Chunhui /* make sure the status is 0, 1, or 2 as per the spec */
754cc49b54bSJia, Chunhui if (status > 2)
755cc49b54bSJia, Chunhui {
756cc49b54bSJia, Chunhui return ipmi::response(ipmi::ccInvalidFieldRequest);
757cc49b54bSJia, Chunhui }
758dc24927fSJason M. Bills /* make sure the target is 0, 1, 2, or 4 as per the spec */
759dc24927fSJason M. Bills if (target > 4 || target == 3)
760dc24927fSJason M. Bills {
761dc24927fSJason M. Bills return ipmi::response(ipmi::ccInvalidFieldRequest);
762dc24927fSJason M. Bills }
763cc49b54bSJia, Chunhui /*orignal OEM command is to record OEM SEL.
764cc49b54bSJia, Chunhui But openbmc does not support OEM SEL, so we redirect it to redfish event
765cc49b54bSJia, Chunhui logging. */
766cc49b54bSJia, Chunhui std::string buildInfo;
767cc49b54bSJia, Chunhui std::string action;
768cc49b54bSJia, Chunhui switch (FWUpdateTarget(target))
769cc49b54bSJia, Chunhui {
770cc49b54bSJia, Chunhui case FWUpdateTarget::targetBMC:
771cc49b54bSJia, Chunhui firmware = "BMC";
772dc24927fSJason M. Bills buildInfo = "major: " + std::to_string(majorRevision) + " minor: " +
773cc49b54bSJia, Chunhui std::to_string(bcdToDec(minorRevision)) + // BCD encoded
774cc49b54bSJia, Chunhui " BuildID: " + std::to_string(auxInfo);
775cc49b54bSJia, Chunhui buildInfo += std::to_string(auxInfo);
776cc49b54bSJia, Chunhui break;
777cc49b54bSJia, Chunhui case FWUpdateTarget::targetBIOS:
778cc49b54bSJia, Chunhui firmware = "BIOS";
779cc49b54bSJia, Chunhui buildInfo =
780cc49b54bSJia, Chunhui "major: " +
781cc49b54bSJia, Chunhui std::to_string(bcdToDec(majorRevision)) + // BCD encoded
782cc49b54bSJia, Chunhui " minor: " +
783cc49b54bSJia, Chunhui std::to_string(bcdToDec(minorRevision)) + // BCD encoded
784cc49b54bSJia, Chunhui " ReleaseNumber: " + // ASCII encoded
785cc49b54bSJia, Chunhui std::to_string(static_cast<uint8_t>(auxInfo >> 0) - '0') +
786cc49b54bSJia, Chunhui std::to_string(static_cast<uint8_t>(auxInfo >> 8) - '0') +
787cc49b54bSJia, Chunhui std::to_string(static_cast<uint8_t>(auxInfo >> 16) - '0') +
788cc49b54bSJia, Chunhui std::to_string(static_cast<uint8_t>(auxInfo >> 24) - '0');
789cc49b54bSJia, Chunhui break;
790cc49b54bSJia, Chunhui case FWUpdateTarget::targetME:
791cc49b54bSJia, Chunhui firmware = "ME";
792cc49b54bSJia, Chunhui buildInfo =
793cc49b54bSJia, Chunhui "major: " + std::to_string(majorRevision) + " minor1: " +
794cc49b54bSJia, Chunhui std::to_string(bcdToDec(minorRevision)) + // BCD encoded
795cc49b54bSJia, Chunhui " minor2: " +
796cc49b54bSJia, Chunhui std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 0))) +
797cc49b54bSJia, Chunhui " build1: " +
798cc49b54bSJia, Chunhui std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 8))) +
799cc49b54bSJia, Chunhui " build2: " +
800cc49b54bSJia, Chunhui std::to_string(bcdToDec(static_cast<uint8_t>(auxInfo >> 16)));
801cc49b54bSJia, Chunhui break;
802cc49b54bSJia, Chunhui case FWUpdateTarget::targetOEMEWS:
803cc49b54bSJia, Chunhui firmware = "EWS";
804dc24927fSJason M. Bills buildInfo = "major: " + std::to_string(majorRevision) + " minor: " +
805cc49b54bSJia, Chunhui std::to_string(bcdToDec(minorRevision)) + // BCD encoded
806cc49b54bSJia, Chunhui " BuildID: " + std::to_string(auxInfo);
807cc49b54bSJia, Chunhui break;
808cc49b54bSJia, Chunhui }
809cc49b54bSJia, Chunhui
810dc24927fSJason M. Bills static const std::string openBMCMessageRegistryVersion("0.1");
811dc24927fSJason M. Bills std::string redfishMsgID = "OpenBMC." + openBMCMessageRegistryVersion;
812dc24927fSJason M. Bills
813cc49b54bSJia, Chunhui switch (status)
814cc49b54bSJia, Chunhui {
815cc49b54bSJia, Chunhui case 0x0:
816cc49b54bSJia, Chunhui action = "update started";
817dc24927fSJason M. Bills redfishMsgID += ".FirmwareUpdateStarted";
818cc49b54bSJia, Chunhui break;
819cc49b54bSJia, Chunhui case 0x1:
820cc49b54bSJia, Chunhui action = "update completed successfully";
821dc24927fSJason M. Bills redfishMsgID += ".FirmwareUpdateCompleted";
822cc49b54bSJia, Chunhui break;
823cc49b54bSJia, Chunhui case 0x2:
824cc49b54bSJia, Chunhui action = "update failure";
825dc24927fSJason M. Bills redfishMsgID += ".FirmwareUpdateFailed";
826cc49b54bSJia, Chunhui break;
827cc49b54bSJia, Chunhui default:
828cc49b54bSJia, Chunhui action = "unknown";
829cc49b54bSJia, Chunhui break;
830cc49b54bSJia, Chunhui }
831cc49b54bSJia, Chunhui
8321bcced08SPatrick Williams std::string firmwareInstanceStr =
8331bcced08SPatrick Williams firmware + " instance: " + std::to_string(instance);
834dc24927fSJason M. Bills std::string message("[firmware update] " + firmwareInstanceStr +
835cc49b54bSJia, Chunhui " status: <" + action + "> " + buildInfo);
836cc49b54bSJia, Chunhui
837cc49b54bSJia, Chunhui sd_journal_send("MESSAGE=%s", message.c_str(), "PRIORITY=%i", LOG_INFO,
838dc24927fSJason M. Bills "REDFISH_MESSAGE_ID=%s", redfishMsgID.c_str(),
839dc24927fSJason M. Bills "REDFISH_MESSAGE_ARGS=%s,%s", firmwareInstanceStr.c_str(),
840dc24927fSJason M. Bills buildInfo.c_str(), NULL);
841cc49b54bSJia, Chunhui return ipmi::responseSuccess();
842cc49b54bSJia, Chunhui }
843cc49b54bSJia, Chunhui
ipmiOEMSlotIpmb(ipmi::Context::ptr & ctx,uint6_t reserved1,uint2_t slotNumber,uint3_t baseBoardSlotNum,uint3_t riserSlotNum,uint2_t reserved2,uint8_t targetAddr,uint8_t netFn,uint8_t cmd,std::optional<std::vector<uint8_t>> writeData)8441bcced08SPatrick Williams ipmi::RspType<uint8_t, std::vector<uint8_t>> ipmiOEMSlotIpmb(
8451bcced08SPatrick Williams ipmi::Context::ptr& ctx, uint6_t reserved1, uint2_t slotNumber,
8461bcced08SPatrick Williams uint3_t baseBoardSlotNum, [[maybe_unused]] uint3_t riserSlotNum,
8471bcced08SPatrick Williams uint2_t reserved2, uint8_t targetAddr, uint8_t netFn, uint8_t cmd,
8482b664d5aSRajashekar Gade Reddy std::optional<std::vector<uint8_t>> writeData)
8492b664d5aSRajashekar Gade Reddy {
8502b664d5aSRajashekar Gade Reddy if (reserved1 || reserved2)
8512b664d5aSRajashekar Gade Reddy {
8522b664d5aSRajashekar Gade Reddy return ipmi::responseInvalidFieldRequest();
8532b664d5aSRajashekar Gade Reddy }
8542b664d5aSRajashekar Gade Reddy
8552b664d5aSRajashekar Gade Reddy boost::system::error_code ec;
8562b664d5aSRajashekar Gade Reddy using ipmbResponse = std::tuple<int, uint8_t, uint8_t, uint8_t, uint8_t,
8572b664d5aSRajashekar Gade Reddy std::vector<uint8_t>>;
8582b664d5aSRajashekar Gade Reddy ipmbResponse res = ctx->bus->yield_method_call<ipmbResponse>(
8592b664d5aSRajashekar Gade Reddy ctx->yield, ec, "xyz.openbmc_project.Ipmi.Channel.Ipmb",
8602b664d5aSRajashekar Gade Reddy "/xyz/openbmc_project/Ipmi/Channel/Ipmb", "org.openbmc.Ipmb",
8612b664d5aSRajashekar Gade Reddy "SlotIpmbRequest", static_cast<uint8_t>(slotNumber),
86280d4d5f9SMatt Simmering static_cast<uint8_t>(baseBoardSlotNum), targetAddr, netFn, cmd,
8632b664d5aSRajashekar Gade Reddy *writeData);
8642b664d5aSRajashekar Gade Reddy if (ec)
8652b664d5aSRajashekar Gade Reddy {
8662b664d5aSRajashekar Gade Reddy phosphor::logging::log<phosphor::logging::level::ERR>(
8672b664d5aSRajashekar Gade Reddy "Failed to call dbus method SlotIpmbRequest");
8682b664d5aSRajashekar Gade Reddy return ipmi::responseUnspecifiedError();
8692b664d5aSRajashekar Gade Reddy }
8702b664d5aSRajashekar Gade Reddy
8712b664d5aSRajashekar Gade Reddy std::vector<uint8_t> dataReceived(0);
8722b664d5aSRajashekar Gade Reddy int status = -1;
8732b664d5aSRajashekar Gade Reddy uint8_t resNetFn = 0, resLun = 0, resCmd = 0, cc = 0;
8742b664d5aSRajashekar Gade Reddy
8752b664d5aSRajashekar Gade Reddy std::tie(status, resNetFn, resLun, resCmd, cc, dataReceived) = res;
8762b664d5aSRajashekar Gade Reddy
8772b664d5aSRajashekar Gade Reddy if (status)
8782b664d5aSRajashekar Gade Reddy {
8792b664d5aSRajashekar Gade Reddy phosphor::logging::log<phosphor::logging::level::ERR>(
8802b664d5aSRajashekar Gade Reddy "Failed to get response from SlotIpmbRequest");
8812b664d5aSRajashekar Gade Reddy return ipmi::responseResponseError();
8822b664d5aSRajashekar Gade Reddy }
8832b664d5aSRajashekar Gade Reddy return ipmi::responseSuccess(cc, dataReceived);
8842b664d5aSRajashekar Gade Reddy }
8852b664d5aSRajashekar Gade Reddy
ipmiOEMSetPowerRestoreDelay(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t request,ipmi_response_t,ipmi_data_len_t dataLen,ipmi_context_t)886dcff1506SVernon Mauery ipmi_ret_t ipmiOEMSetPowerRestoreDelay(ipmi_netfn_t, ipmi_cmd_t,
887dcff1506SVernon Mauery ipmi_request_t request, ipmi_response_t,
888dcff1506SVernon Mauery ipmi_data_len_t dataLen, ipmi_context_t)
88964796041SJason M. Bills {
89064796041SJason M. Bills SetPowerRestoreDelayReq* data =
89164796041SJason M. Bills reinterpret_cast<SetPowerRestoreDelayReq*>(request);
89264796041SJason M. Bills uint16_t delay = 0;
89364796041SJason M. Bills
89464796041SJason M. Bills if (*dataLen != sizeof(SetPowerRestoreDelayReq))
89564796041SJason M. Bills {
89664796041SJason M. Bills *dataLen = 0;
89764796041SJason M. Bills return IPMI_CC_REQ_DATA_LEN_INVALID;
89864796041SJason M. Bills }
89964796041SJason M. Bills delay = data->byteMSB;
90064796041SJason M. Bills delay = (delay << 8) | data->byteLSB;
901c42c7edeSAndrei Kartashev uint64_t val = delay * 1000000;
90215419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
9031bcced08SPatrick Williams std::string service =
9041bcced08SPatrick Williams getService(*dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath);
90515419dd5SVernon Mauery setDbusProperty(*dbus, service, powerRestoreDelayObjPath,
906c42c7edeSAndrei Kartashev powerRestoreDelayIntf, powerRestoreDelayProp, val);
90764796041SJason M. Bills *dataLen = 0;
90864796041SJason M. Bills
90964796041SJason M. Bills return IPMI_CC_OK;
91064796041SJason M. Bills }
91164796041SJason M. Bills
cpuPresent(const std::string & cpuName)91242bd9c8eSJason M. Bills static bool cpuPresent(const std::string& cpuName)
91364796041SJason M. Bills {
91442bd9c8eSJason M. Bills static constexpr const char* cpuPresencePathPrefix =
91542bd9c8eSJason M. Bills "/xyz/openbmc_project/inventory/system/chassis/motherboard/";
91642bd9c8eSJason M. Bills static constexpr const char* cpuPresenceIntf =
91742bd9c8eSJason M. Bills "xyz.openbmc_project.Inventory.Item";
91842bd9c8eSJason M. Bills std::string cpuPresencePath = cpuPresencePathPrefix + cpuName;
91942bd9c8eSJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
92042bd9c8eSJason M. Bills try
92142bd9c8eSJason M. Bills {
9221bcced08SPatrick Williams auto service =
9231bcced08SPatrick Williams ipmi::getService(*busp, cpuPresenceIntf, cpuPresencePath);
92464796041SJason M. Bills
92542bd9c8eSJason M. Bills ipmi::Value result = ipmi::getDbusProperty(
92642bd9c8eSJason M. Bills *busp, service, cpuPresencePath, cpuPresenceIntf, "Present");
92742bd9c8eSJason M. Bills return std::get<bool>(result);
92842bd9c8eSJason M. Bills }
92942bd9c8eSJason M. Bills catch (const std::exception& e)
93064796041SJason M. Bills {
93142bd9c8eSJason M. Bills phosphor::logging::log<phosphor::logging::level::INFO>(
93242bd9c8eSJason M. Bills "Cannot find processor presence",
93342bd9c8eSJason M. Bills phosphor::logging::entry("NAME=%s", cpuName.c_str()));
93442bd9c8eSJason M. Bills return false;
93542bd9c8eSJason M. Bills }
93664796041SJason M. Bills }
93764796041SJason M. Bills
938f284f855SJason M. Bills ipmi::RspType<bool, // IERR Reset Enabled
93942bd9c8eSJason M. Bills bool, // ERR2 Reset Enabled
94051cf3110SJason M. Bills bool, // MCERR Reset Enabled
94151cf3110SJason M. Bills uint5_t, // reserved
94242bd9c8eSJason M. Bills uint8_t, // reserved, returns 0x3F
943f284f855SJason M. Bills uint6_t, // CPU1 IERR Count
94442bd9c8eSJason M. Bills uint2_t, // CPU1 Status
945f284f855SJason M. Bills uint6_t, // CPU2 IERR Count
94642bd9c8eSJason M. Bills uint2_t, // CPU2 Status
947f284f855SJason M. Bills uint6_t, // CPU3 IERR Count
94842bd9c8eSJason M. Bills uint2_t, // CPU3 Status
949f284f855SJason M. Bills uint6_t, // CPU4 IERR Count
95042bd9c8eSJason M. Bills uint2_t, // CPU4 Status
95142bd9c8eSJason M. Bills uint8_t // Crashdump Count
95242bd9c8eSJason M. Bills >
ipmiOEMGetProcessorErrConfig()95342bd9c8eSJason M. Bills ipmiOEMGetProcessorErrConfig()
95442bd9c8eSJason M. Bills {
955f284f855SJason M. Bills bool resetOnIERR = false;
95642bd9c8eSJason M. Bills bool resetOnERR2 = false;
957*08eb9e5aSJason M. Bills bool resetOnMCERR = false;
958f284f855SJason M. Bills uint6_t cpu1IERRCount = 0;
959f284f855SJason M. Bills uint6_t cpu2IERRCount = 0;
960f284f855SJason M. Bills uint6_t cpu3IERRCount = 0;
961f284f855SJason M. Bills uint6_t cpu4IERRCount = 0;
96242bd9c8eSJason M. Bills uint8_t crashdumpCount = 0;
96324df90f7SJason M. Bills uint2_t cpu1Status = cpuPresent("CPU_1")
96424df90f7SJason M. Bills ? types::enum_cast<uint8_t>(CPUStatus::enabled)
96524df90f7SJason M. Bills : types::enum_cast<uint8_t>(CPUStatus::notPresent);
96624df90f7SJason M. Bills uint2_t cpu2Status = cpuPresent("CPU_2")
96724df90f7SJason M. Bills ? types::enum_cast<uint8_t>(CPUStatus::enabled)
96824df90f7SJason M. Bills : types::enum_cast<uint8_t>(CPUStatus::notPresent);
96924df90f7SJason M. Bills uint2_t cpu3Status = cpuPresent("CPU_3")
97024df90f7SJason M. Bills ? types::enum_cast<uint8_t>(CPUStatus::enabled)
97124df90f7SJason M. Bills : types::enum_cast<uint8_t>(CPUStatus::notPresent);
97224df90f7SJason M. Bills uint2_t cpu4Status = cpuPresent("CPU_4")
97324df90f7SJason M. Bills ? types::enum_cast<uint8_t>(CPUStatus::enabled)
97424df90f7SJason M. Bills : types::enum_cast<uint8_t>(CPUStatus::notPresent);
97564796041SJason M. Bills
97642bd9c8eSJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
97742bd9c8eSJason M. Bills try
97842bd9c8eSJason M. Bills {
97942bd9c8eSJason M. Bills auto service = ipmi::getService(*busp, processorErrConfigIntf,
98042bd9c8eSJason M. Bills processorErrConfigObjPath);
98164796041SJason M. Bills
98242bd9c8eSJason M. Bills ipmi::PropertyMap result = ipmi::getAllDbusProperties(
98342bd9c8eSJason M. Bills *busp, service, processorErrConfigObjPath, processorErrConfigIntf);
984f284f855SJason M. Bills resetOnIERR = std::get<bool>(result.at("ResetOnIERR"));
98542bd9c8eSJason M. Bills resetOnERR2 = std::get<bool>(result.at("ResetOnERR2"));
986*08eb9e5aSJason M. Bills resetOnMCERR = std::get<bool>(result.at("ResetOnMCERR"));
987f284f855SJason M. Bills cpu1IERRCount = std::get<uint8_t>(result.at("ErrorCountCPU1"));
988f284f855SJason M. Bills cpu2IERRCount = std::get<uint8_t>(result.at("ErrorCountCPU2"));
989f284f855SJason M. Bills cpu3IERRCount = std::get<uint8_t>(result.at("ErrorCountCPU3"));
990f284f855SJason M. Bills cpu4IERRCount = std::get<uint8_t>(result.at("ErrorCountCPU4"));
99142bd9c8eSJason M. Bills crashdumpCount = std::get<uint8_t>(result.at("CrashdumpCount"));
99242bd9c8eSJason M. Bills }
99342bd9c8eSJason M. Bills catch (const std::exception& e)
99442bd9c8eSJason M. Bills {
99542bd9c8eSJason M. Bills phosphor::logging::log<phosphor::logging::level::ERR>(
99642bd9c8eSJason M. Bills "Failed to fetch processor error config",
99742bd9c8eSJason M. Bills phosphor::logging::entry("ERROR=%s", e.what()));
99842bd9c8eSJason M. Bills return ipmi::responseUnspecifiedError();
99942bd9c8eSJason M. Bills }
100064796041SJason M. Bills
10011bcced08SPatrick Williams return ipmi::responseSuccess(
1002*08eb9e5aSJason M. Bills resetOnIERR, resetOnERR2, resetOnMCERR, 0, 0x3F, cpu1IERRCount,
10031bcced08SPatrick Williams cpu1Status, cpu2IERRCount, cpu2Status, cpu3IERRCount, cpu3Status,
1004f284f855SJason M. Bills cpu4IERRCount, cpu4Status, crashdumpCount);
100542bd9c8eSJason M. Bills }
100642bd9c8eSJason M. Bills
ipmiOEMSetProcessorErrConfig(bool resetOnIERR,bool resetOnERR2,bool resetOnMCERR,uint5_t reserved1,uint8_t reserved2,std::optional<bool> clearCPUErrorCount,std::optional<bool> clearCrashdumpCount,std::optional<uint6_t> reserved3)100742bd9c8eSJason M. Bills ipmi::RspType<> ipmiOEMSetProcessorErrConfig(
1008*08eb9e5aSJason M. Bills bool resetOnIERR, bool resetOnERR2, bool resetOnMCERR, uint5_t reserved1,
1009*08eb9e5aSJason M. Bills uint8_t reserved2, std::optional<bool> clearCPUErrorCount,
101042bd9c8eSJason M. Bills std::optional<bool> clearCrashdumpCount, std::optional<uint6_t> reserved3)
101142bd9c8eSJason M. Bills {
10120a652fa9SJayaprakash Mutyala if (reserved1 || reserved2)
10130a652fa9SJayaprakash Mutyala {
10140a652fa9SJayaprakash Mutyala return ipmi::responseInvalidFieldRequest();
10150a652fa9SJayaprakash Mutyala }
10160a652fa9SJayaprakash Mutyala
101742bd9c8eSJason M. Bills std::shared_ptr<sdbusplus::asio::connection> busp = getSdBus();
101864796041SJason M. Bills
101964796041SJason M. Bills try
102064796041SJason M. Bills {
10210a652fa9SJayaprakash Mutyala if (reserved3.value_or(0))
10220a652fa9SJayaprakash Mutyala {
10230a652fa9SJayaprakash Mutyala return ipmi::responseInvalidFieldRequest();
10240a652fa9SJayaprakash Mutyala }
102542bd9c8eSJason M. Bills auto service = ipmi::getService(*busp, processorErrConfigIntf,
102642bd9c8eSJason M. Bills processorErrConfigObjPath);
102742bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath,
1028f284f855SJason M. Bills processorErrConfigIntf, "ResetOnIERR",
1029f284f855SJason M. Bills resetOnIERR);
103042bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath,
103142bd9c8eSJason M. Bills processorErrConfigIntf, "ResetOnERR2",
103242bd9c8eSJason M. Bills resetOnERR2);
103351cf3110SJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath,
1034*08eb9e5aSJason M. Bills processorErrConfigIntf, "ResetOnMCERR",
1035*08eb9e5aSJason M. Bills resetOnMCERR);
103642bd9c8eSJason M. Bills if (clearCPUErrorCount.value_or(false))
103742bd9c8eSJason M. Bills {
103842bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath,
1039d3e19936SJason M. Bills processorErrConfigIntf, "ErrorCountCPU1",
1040d3e19936SJason M. Bills static_cast<uint8_t>(0));
104142bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath,
1042d3e19936SJason M. Bills processorErrConfigIntf, "ErrorCountCPU2",
1043d3e19936SJason M. Bills static_cast<uint8_t>(0));
1044d3e19936SJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath,
1045d3e19936SJason M. Bills processorErrConfigIntf, "ErrorCountCPU3",
1046d3e19936SJason M. Bills static_cast<uint8_t>(0));
1047d3e19936SJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath,
1048d3e19936SJason M. Bills processorErrConfigIntf, "ErrorCountCPU4",
1049d3e19936SJason M. Bills static_cast<uint8_t>(0));
105064796041SJason M. Bills }
105142bd9c8eSJason M. Bills if (clearCrashdumpCount.value_or(false))
105242bd9c8eSJason M. Bills {
105342bd9c8eSJason M. Bills ipmi::setDbusProperty(*busp, service, processorErrConfigObjPath,
1054d3e19936SJason M. Bills processorErrConfigIntf, "CrashdumpCount",
1055d3e19936SJason M. Bills static_cast<uint8_t>(0));
105642bd9c8eSJason M. Bills }
105742bd9c8eSJason M. Bills }
1058bd51e6a9SPatrick Williams catch (const std::exception& e)
105964796041SJason M. Bills {
1060bc546679SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>(
106142bd9c8eSJason M. Bills "Failed to set processor error config",
106242bd9c8eSJason M. Bills phosphor::logging::entry("EXCEPTION=%s", e.what()));
106342bd9c8eSJason M. Bills return ipmi::responseUnspecifiedError();
106464796041SJason M. Bills }
106564796041SJason M. Bills
106642bd9c8eSJason M. Bills return ipmi::responseSuccess();
106764796041SJason M. Bills }
106864796041SJason M. Bills
ipmiOEMGetShutdownPolicy(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t,ipmi_response_t response,ipmi_data_len_t dataLen,ipmi_context_t)1069dcff1506SVernon Mauery ipmi_ret_t ipmiOEMGetShutdownPolicy(ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t,
1070703922d0SYong Li ipmi_response_t response,
1071dcff1506SVernon Mauery ipmi_data_len_t dataLen, ipmi_context_t)
1072703922d0SYong Li {
1073703922d0SYong Li GetOEMShutdownPolicyRes* resp =
1074703922d0SYong Li reinterpret_cast<GetOEMShutdownPolicyRes*>(response);
1075703922d0SYong Li
1076703922d0SYong Li if (*dataLen != 0)
1077703922d0SYong Li {
1078703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
107945f04988SKuiying Wang "oem_get_shutdown_policy: invalid input len!");
1080703922d0SYong Li *dataLen = 0;
1081703922d0SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID;
1082703922d0SYong Li }
1083703922d0SYong Li
1084703922d0SYong Li *dataLen = 0;
1085703922d0SYong Li
1086703922d0SYong Li try
1087703922d0SYong Li {
108815419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
10891bcced08SPatrick Williams std::string service =
10901bcced08SPatrick Williams getService(*dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath);
109115419dd5SVernon Mauery Value variant = getDbusProperty(
109215419dd5SVernon Mauery *dbus, service, oemShutdownPolicyObjPath, oemShutdownPolicyIntf,
1093703922d0SYong Li oemShutdownPolicyObjPathProp);
10940669d193SYong Li
10950669d193SYong Li if (sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::
10960669d193SYong Li convertPolicyFromString(std::get<std::string>(variant)) ==
10970669d193SYong Li sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy::
10980669d193SYong Li NoShutdownOnOCOT)
10990669d193SYong Li {
11000669d193SYong Li resp->policy = 0;
11010669d193SYong Li }
11020669d193SYong Li else if (sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::
11030669d193SYong Li convertPolicyFromString(std::get<std::string>(variant)) ==
11040669d193SYong Li sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::
11050669d193SYong Li Policy::ShutdownOnOCOT)
11060669d193SYong Li {
11070669d193SYong Li resp->policy = 1;
11080669d193SYong Li }
11090669d193SYong Li else
11100669d193SYong Li {
11110669d193SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
11120669d193SYong Li "oem_set_shutdown_policy: invalid property!",
11130669d193SYong Li phosphor::logging::entry(
11140669d193SYong Li "PROP=%s", std::get<std::string>(variant).c_str()));
11150669d193SYong Li return IPMI_CC_UNSPECIFIED_ERROR;
11160669d193SYong Li }
1117703922d0SYong Li // TODO needs to check if it is multi-node products,
1118703922d0SYong Li // policy is only supported on node 3/4
1119703922d0SYong Li resp->policySupport = shutdownPolicySupported;
1120703922d0SYong Li }
1121bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
1122703922d0SYong Li {
1123703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
1124703922d0SYong Li return IPMI_CC_UNSPECIFIED_ERROR;
1125703922d0SYong Li }
1126703922d0SYong Li
1127703922d0SYong Li *dataLen = sizeof(GetOEMShutdownPolicyRes);
1128703922d0SYong Li return IPMI_CC_OK;
1129703922d0SYong Li }
1130703922d0SYong Li
ipmiOEMSetShutdownPolicy(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t request,ipmi_response_t,ipmi_data_len_t dataLen,ipmi_context_t)1131dcff1506SVernon Mauery ipmi_ret_t ipmiOEMSetShutdownPolicy(ipmi_netfn_t, ipmi_cmd_t,
1132dcff1506SVernon Mauery ipmi_request_t request, ipmi_response_t,
1133dcff1506SVernon Mauery ipmi_data_len_t dataLen, ipmi_context_t)
1134703922d0SYong Li {
1135703922d0SYong Li uint8_t* req = reinterpret_cast<uint8_t*>(request);
11360669d193SYong Li sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy policy =
11370669d193SYong Li sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::Policy::
11380669d193SYong Li NoShutdownOnOCOT;
1139703922d0SYong Li
1140703922d0SYong Li // TODO needs to check if it is multi-node products,
1141703922d0SYong Li // policy is only supported on node 3/4
1142703922d0SYong Li if (*dataLen != 1)
1143703922d0SYong Li {
1144703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
1145703922d0SYong Li "oem_set_shutdown_policy: invalid input len!");
1146703922d0SYong Li *dataLen = 0;
1147703922d0SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID;
1148703922d0SYong Li }
1149703922d0SYong Li
1150703922d0SYong Li *dataLen = 0;
1151703922d0SYong Li if ((*req != noShutdownOnOCOT) && (*req != shutdownOnOCOT))
1152703922d0SYong Li {
1153703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
1154703922d0SYong Li "oem_set_shutdown_policy: invalid input!");
1155703922d0SYong Li return IPMI_CC_INVALID_FIELD_REQUEST;
1156703922d0SYong Li }
1157703922d0SYong Li
11580669d193SYong Li if (*req == noShutdownOnOCOT)
11590669d193SYong Li {
11600669d193SYong Li policy = sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::
11610669d193SYong Li Policy::NoShutdownOnOCOT;
11620669d193SYong Li }
11630669d193SYong Li else
11640669d193SYong Li {
11650669d193SYong Li policy = sdbusplus::com::intel::Control::server::OCOTShutdownPolicy::
11660669d193SYong Li Policy::ShutdownOnOCOT;
11670669d193SYong Li }
11680669d193SYong Li
1169703922d0SYong Li try
1170703922d0SYong Li {
117115419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
11721bcced08SPatrick Williams std::string service =
11731bcced08SPatrick Williams getService(*dbus, oemShutdownPolicyIntf, oemShutdownPolicyObjPath);
11740669d193SYong Li setDbusProperty(
117515419dd5SVernon Mauery *dbus, service, oemShutdownPolicyObjPath, oemShutdownPolicyIntf,
11760669d193SYong Li oemShutdownPolicyObjPathProp,
11770669d193SYong Li sdbusplus::com::intel::Control::server::convertForMessage(policy));
1178703922d0SYong Li }
1179bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
1180703922d0SYong Li {
1181703922d0SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
1182703922d0SYong Li return IPMI_CC_UNSPECIFIED_ERROR;
1183703922d0SYong Li }
1184703922d0SYong Li
1185703922d0SYong Li return IPMI_CC_OK;
1186703922d0SYong Li }
1187703922d0SYong Li
1188d509eb91SSuryakanth Sekar /** @brief implementation for check the DHCP or not in IPv4
1189d509eb91SSuryakanth Sekar * @param[in] Channel - Channel number
1190d509eb91SSuryakanth Sekar * @returns true or false.
1191d509eb91SSuryakanth Sekar */
isDHCPEnabled(uint8_t Channel)1192d509eb91SSuryakanth Sekar static bool isDHCPEnabled(uint8_t Channel)
1193d509eb91SSuryakanth Sekar {
1194d509eb91SSuryakanth Sekar try
1195d509eb91SSuryakanth Sekar {
1196d509eb91SSuryakanth Sekar auto ethdevice = getChannelName(Channel);
1197d509eb91SSuryakanth Sekar if (ethdevice.empty())
1198d509eb91SSuryakanth Sekar {
1199d509eb91SSuryakanth Sekar return false;
1200d509eb91SSuryakanth Sekar }
1201d509eb91SSuryakanth Sekar auto ethIP = ethdevice + "/ipv4";
120215419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
12031bcced08SPatrick Williams auto ethernetObj =
12041bcced08SPatrick Williams getDbusObject(*dbus, networkIPIntf, networkRoot, ethIP);
120515419dd5SVernon Mauery auto value = getDbusProperty(*dbus, networkService, ethernetObj.first,
1206d509eb91SSuryakanth Sekar networkIPIntf, "Origin");
12078166c8d7SVernon Mauery if (std::get<std::string>(value) ==
1208d509eb91SSuryakanth Sekar "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1209d509eb91SSuryakanth Sekar {
1210d509eb91SSuryakanth Sekar return true;
1211d509eb91SSuryakanth Sekar }
1212d509eb91SSuryakanth Sekar else
1213d509eb91SSuryakanth Sekar {
1214d509eb91SSuryakanth Sekar return false;
1215d509eb91SSuryakanth Sekar }
1216d509eb91SSuryakanth Sekar }
1217bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
1218d509eb91SSuryakanth Sekar {
1219d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
1220d509eb91SSuryakanth Sekar return true;
1221d509eb91SSuryakanth Sekar }
1222d509eb91SSuryakanth Sekar }
1223d509eb91SSuryakanth Sekar
1224d509eb91SSuryakanth Sekar /** @brief implementes for check the DHCP or not in IPv6
1225d509eb91SSuryakanth Sekar * @param[in] Channel - Channel number
1226d509eb91SSuryakanth Sekar * @returns true or false.
1227d509eb91SSuryakanth Sekar */
isDHCPIPv6Enabled(uint8_t Channel)1228d509eb91SSuryakanth Sekar static bool isDHCPIPv6Enabled(uint8_t Channel)
1229d509eb91SSuryakanth Sekar {
1230d509eb91SSuryakanth Sekar try
1231d509eb91SSuryakanth Sekar {
1232d509eb91SSuryakanth Sekar auto ethdevice = getChannelName(Channel);
1233d509eb91SSuryakanth Sekar if (ethdevice.empty())
1234d509eb91SSuryakanth Sekar {
1235d509eb91SSuryakanth Sekar return false;
1236d509eb91SSuryakanth Sekar }
1237d509eb91SSuryakanth Sekar auto ethIP = ethdevice + "/ipv6";
123815419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
12391bcced08SPatrick Williams auto objectInfo =
12401bcced08SPatrick Williams getDbusObject(*dbus, networkIPIntf, networkRoot, ethIP);
124115419dd5SVernon Mauery auto properties = getAllDbusProperties(*dbus, objectInfo.second,
1242d509eb91SSuryakanth Sekar objectInfo.first, networkIPIntf);
12438166c8d7SVernon Mauery if (std::get<std::string>(properties["Origin"]) ==
1244d509eb91SSuryakanth Sekar "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP")
1245d509eb91SSuryakanth Sekar {
1246d509eb91SSuryakanth Sekar return true;
1247d509eb91SSuryakanth Sekar }
1248d509eb91SSuryakanth Sekar else
1249d509eb91SSuryakanth Sekar {
1250d509eb91SSuryakanth Sekar return false;
1251d509eb91SSuryakanth Sekar }
1252d509eb91SSuryakanth Sekar }
1253bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
1254d509eb91SSuryakanth Sekar {
1255d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(e.description());
1256d509eb91SSuryakanth Sekar return true;
1257d509eb91SSuryakanth Sekar }
1258d509eb91SSuryakanth Sekar }
1259d509eb91SSuryakanth Sekar
1260d509eb91SSuryakanth Sekar /** @brief implementes the creating of default new user
1261d509eb91SSuryakanth Sekar * @param[in] userName - new username in 16 bytes.
1262d509eb91SSuryakanth Sekar * @param[in] userPassword - new password in 20 bytes
1263d509eb91SSuryakanth Sekar * @returns ipmi completion code.
1264d509eb91SSuryakanth Sekar */
ipmiOEMSetUser2Activation(std::array<uint8_t,ipmi::ipmiMaxUserName> & userName,const SecureBuffer & userPassword)1265d509eb91SSuryakanth Sekar ipmi::RspType<> ipmiOEMSetUser2Activation(
1266d509eb91SSuryakanth Sekar std::array<uint8_t, ipmi::ipmiMaxUserName>& userName,
12673b3d29b1SVernon Mauery const SecureBuffer& userPassword)
1268d509eb91SSuryakanth Sekar {
12693b3d29b1SVernon Mauery if (userPassword.size() != ipmi::maxIpmi20PasswordSize)
12703b3d29b1SVernon Mauery {
12713b3d29b1SVernon Mauery return ipmi::responseReqDataLenInvalid();
12723b3d29b1SVernon Mauery }
1273d509eb91SSuryakanth Sekar bool userState = false;
1274d509eb91SSuryakanth Sekar // Check for System Interface not exist and LAN should be static
1275d509eb91SSuryakanth Sekar for (uint8_t channel = 0; channel < maxIpmiChannels; channel++)
1276d509eb91SSuryakanth Sekar {
1277440f62bfSManish Baing ChannelInfo chInfo{};
1278d509eb91SSuryakanth Sekar try
1279d509eb91SSuryakanth Sekar {
1280d509eb91SSuryakanth Sekar getChannelInfo(channel, chInfo);
1281d509eb91SSuryakanth Sekar }
1282bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
1283d509eb91SSuryakanth Sekar {
1284d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(
1285d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: Failed to get Channel Info",
1286d509eb91SSuryakanth Sekar phosphor::logging::entry("MSG: %s", e.description()));
1287d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccUnspecifiedError);
1288d509eb91SSuryakanth Sekar }
1289d509eb91SSuryakanth Sekar if (chInfo.mediumType ==
1290d509eb91SSuryakanth Sekar static_cast<uint8_t>(EChannelMediumType::systemInterface))
1291d509eb91SSuryakanth Sekar {
1292d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(
1293d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: system interface exist .");
1294d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable);
1295d509eb91SSuryakanth Sekar }
1296d509eb91SSuryakanth Sekar else
1297d509eb91SSuryakanth Sekar {
1298d509eb91SSuryakanth Sekar if (chInfo.mediumType ==
1299d509eb91SSuryakanth Sekar static_cast<uint8_t>(EChannelMediumType::lan8032))
1300d509eb91SSuryakanth Sekar {
1301d509eb91SSuryakanth Sekar if (isDHCPIPv6Enabled(channel) || isDHCPEnabled(channel))
1302d509eb91SSuryakanth Sekar {
1303d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(
1304d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: DHCP enabled .");
1305d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable);
1306d509eb91SSuryakanth Sekar }
1307d509eb91SSuryakanth Sekar }
1308d509eb91SSuryakanth Sekar }
1309d509eb91SSuryakanth Sekar }
1310d509eb91SSuryakanth Sekar uint8_t maxChUsers = 0, enabledUsers = 0, fixedUsers = 0;
1311d509eb91SSuryakanth Sekar if (ipmi::ccSuccess ==
1312d509eb91SSuryakanth Sekar ipmiUserGetAllCounts(maxChUsers, enabledUsers, fixedUsers))
1313d509eb91SSuryakanth Sekar {
1314d509eb91SSuryakanth Sekar if (enabledUsers > 1)
1315d509eb91SSuryakanth Sekar {
1316d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(
1317d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: more than one user is enabled.");
1318d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable);
1319d509eb91SSuryakanth Sekar }
1320d509eb91SSuryakanth Sekar // Check the user 2 is enabled or not
1321d509eb91SSuryakanth Sekar ipmiUserCheckEnabled(ipmiDefaultUserId, userState);
1322d509eb91SSuryakanth Sekar if (userState == true)
1323d509eb91SSuryakanth Sekar {
1324d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(
1325d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: user 2 already enabled .");
1326d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable);
1327d509eb91SSuryakanth Sekar }
1328d509eb91SSuryakanth Sekar }
1329d509eb91SSuryakanth Sekar else
1330d509eb91SSuryakanth Sekar {
1331d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccUnspecifiedError);
1332d509eb91SSuryakanth Sekar }
1333d509eb91SSuryakanth Sekar
1334d509eb91SSuryakanth Sekar #if BYTE_ORDER == LITTLE_ENDIAN
1335d509eb91SSuryakanth Sekar PrivAccess privAccess = {PRIVILEGE_ADMIN, true, true, true, 0};
1336d509eb91SSuryakanth Sekar #endif
1337d509eb91SSuryakanth Sekar #if BYTE_ORDER == BIG_ENDIAN
1338d509eb91SSuryakanth Sekar PrivAccess privAccess = {0, true, true, true, PRIVILEGE_ADMIN};
1339d509eb91SSuryakanth Sekar #endif
1340d509eb91SSuryakanth Sekar
1341037cabddSVernon Mauery // ipmiUserSetUserName correctly handles char*, possibly non-null
1342037cabddSVernon Mauery // terminated strings using ipmiMaxUserName size
13433fbe8d2aSJayaprakash Mutyala size_t nameLen = strnlen(reinterpret_cast<const char*>(userName.data()),
13443fbe8d2aSJayaprakash Mutyala sizeof(userName));
13453fbe8d2aSJayaprakash Mutyala const std::string userNameRaw(
13463fbe8d2aSJayaprakash Mutyala reinterpret_cast<const char*>(userName.data()), nameLen);
13471429d4f1Sjayaprakash Mutyala
1348037cabddSVernon Mauery if (ipmi::ccSuccess == ipmiUserSetUserName(ipmiDefaultUserId, userNameRaw))
1349d509eb91SSuryakanth Sekar {
1350d509eb91SSuryakanth Sekar if (ipmi::ccSuccess ==
1351d509eb91SSuryakanth Sekar ipmiUserSetUserPassword(
1352d509eb91SSuryakanth Sekar ipmiDefaultUserId,
1353d509eb91SSuryakanth Sekar reinterpret_cast<const char*>(userPassword.data())))
1354d509eb91SSuryakanth Sekar {
1355d509eb91SSuryakanth Sekar if (ipmi::ccSuccess ==
1356d509eb91SSuryakanth Sekar ipmiUserSetPrivilegeAccess(
1357d509eb91SSuryakanth Sekar ipmiDefaultUserId,
1358d509eb91SSuryakanth Sekar static_cast<uint8_t>(ipmi::EChannelID::chanLan1),
1359d509eb91SSuryakanth Sekar privAccess, true))
1360d509eb91SSuryakanth Sekar {
1361d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::INFO>(
1362d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: user created successfully ");
13639420416aSJayaprakash Mutyala
1364d509eb91SSuryakanth Sekar return ipmi::responseSuccess();
1365d509eb91SSuryakanth Sekar }
1366d509eb91SSuryakanth Sekar }
1367d509eb91SSuryakanth Sekar // we need to delete the default user id which added in this command as
1368d509eb91SSuryakanth Sekar // password / priv setting is failed.
13693fbe8d2aSJayaprakash Mutyala ipmiUserSetUserName(ipmiDefaultUserId, static_cast<std::string>(""));
1370d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(
1371d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: password / priv setting is failed.");
1372d509eb91SSuryakanth Sekar }
1373d509eb91SSuryakanth Sekar else
1374d509eb91SSuryakanth Sekar {
1375d509eb91SSuryakanth Sekar phosphor::logging::log<phosphor::logging::level::ERR>(
1376d509eb91SSuryakanth Sekar "ipmiOEMSetUser2Activation: Setting username failed.");
1377d509eb91SSuryakanth Sekar }
1378d509eb91SSuryakanth Sekar
1379d509eb91SSuryakanth Sekar return ipmi::response(ipmi::ccCommandNotAvailable);
1380d509eb91SSuryakanth Sekar }
1381d509eb91SSuryakanth Sekar
1382822b0b40SSuryakanth Sekar /** @brief implementes executing the linux command
1383822b0b40SSuryakanth Sekar * @param[in] linux command
1384822b0b40SSuryakanth Sekar * @returns status
1385822b0b40SSuryakanth Sekar */
1386822b0b40SSuryakanth Sekar
executeCmd(const char * path)1387822b0b40SSuryakanth Sekar static uint8_t executeCmd(const char* path)
1388822b0b40SSuryakanth Sekar {
1389822b0b40SSuryakanth Sekar boost::process::child execProg(path);
1390822b0b40SSuryakanth Sekar execProg.wait();
1391822b0b40SSuryakanth Sekar
1392822b0b40SSuryakanth Sekar int retCode = execProg.exit_code();
1393822b0b40SSuryakanth Sekar if (retCode)
1394822b0b40SSuryakanth Sekar {
1395822b0b40SSuryakanth Sekar return ipmi::ccUnspecifiedError;
1396822b0b40SSuryakanth Sekar }
1397822b0b40SSuryakanth Sekar return ipmi::ccSuccess;
1398822b0b40SSuryakanth Sekar }
1399822b0b40SSuryakanth Sekar
1400822b0b40SSuryakanth Sekar /** @brief implementes ASD Security event logging
1401822b0b40SSuryakanth Sekar * @param[in] Event message string
1402822b0b40SSuryakanth Sekar * @param[in] Event Severity
1403822b0b40SSuryakanth Sekar * @returns status
1404822b0b40SSuryakanth Sekar */
1405822b0b40SSuryakanth Sekar
atScaleDebugEventlog(std::string msg,int severity)1406822b0b40SSuryakanth Sekar static void atScaleDebugEventlog(std::string msg, int severity)
1407822b0b40SSuryakanth Sekar {
1408822b0b40SSuryakanth Sekar std::string eventStr = "OpenBMC.0.1." + msg;
1409822b0b40SSuryakanth Sekar sd_journal_send("MESSAGE=Security Event: %s", eventStr.c_str(),
1410822b0b40SSuryakanth Sekar "PRIORITY=%i", severity, "REDFISH_MESSAGE_ID=%s",
1411822b0b40SSuryakanth Sekar eventStr.c_str(), NULL);
1412822b0b40SSuryakanth Sekar }
1413822b0b40SSuryakanth Sekar
1414fc5e985bSRichard Marian Thomaiyar /** @brief implementes setting password for special user
1415fc5e985bSRichard Marian Thomaiyar * @param[in] specialUserIndex
1416fc5e985bSRichard Marian Thomaiyar * @param[in] userPassword - new password in 20 bytes
1417fc5e985bSRichard Marian Thomaiyar * @returns ipmi completion code.
1418fc5e985bSRichard Marian Thomaiyar */
ipmiOEMSetSpecialUserPassword(ipmi::Context::ptr & ctx,uint8_t specialUserIndex,std::vector<uint8_t> userPassword)1419dcff1506SVernon Mauery ipmi::RspType<> ipmiOEMSetSpecialUserPassword(ipmi::Context::ptr& ctx,
1420fc5e985bSRichard Marian Thomaiyar uint8_t specialUserIndex,
1421fc5e985bSRichard Marian Thomaiyar std::vector<uint8_t> userPassword)
1422fc5e985bSRichard Marian Thomaiyar {
1423fc5e985bSRichard Marian Thomaiyar ChannelInfo chInfo;
1424822b0b40SSuryakanth Sekar ipmi_ret_t status = ipmi::ccSuccess;
1425822b0b40SSuryakanth Sekar
1426fc5e985bSRichard Marian Thomaiyar try
1427fc5e985bSRichard Marian Thomaiyar {
1428fc5e985bSRichard Marian Thomaiyar getChannelInfo(ctx->channel, chInfo);
1429fc5e985bSRichard Marian Thomaiyar }
1430bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
1431fc5e985bSRichard Marian Thomaiyar {
1432fc5e985bSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
1433fc5e985bSRichard Marian Thomaiyar "ipmiOEMSetSpecialUserPassword: Failed to get Channel Info",
1434fc5e985bSRichard Marian Thomaiyar phosphor::logging::entry("MSG: %s", e.description()));
1435fc5e985bSRichard Marian Thomaiyar return ipmi::responseUnspecifiedError();
1436fc5e985bSRichard Marian Thomaiyar }
1437fc5e985bSRichard Marian Thomaiyar if (chInfo.mediumType !=
1438fc5e985bSRichard Marian Thomaiyar static_cast<uint8_t>(EChannelMediumType::systemInterface))
1439fc5e985bSRichard Marian Thomaiyar {
1440fc5e985bSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
1441fc5e985bSRichard Marian Thomaiyar "ipmiOEMSetSpecialUserPassword: Error - supported only in KCS "
1442fc5e985bSRichard Marian Thomaiyar "interface");
1443fc5e985bSRichard Marian Thomaiyar return ipmi::responseCommandNotAvailable();
1444fc5e985bSRichard Marian Thomaiyar }
1445822b0b40SSuryakanth Sekar
1446822b0b40SSuryakanth Sekar // 0 for root user and 1 for AtScaleDebug is allowed
1447822b0b40SSuryakanth Sekar if (specialUserIndex >
1448822b0b40SSuryakanth Sekar static_cast<uint8_t>(SpecialUserIndex::atScaleDebugUser))
1449fc5e985bSRichard Marian Thomaiyar {
1450fc5e985bSRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
1451fc5e985bSRichard Marian Thomaiyar "ipmiOEMSetSpecialUserPassword: Invalid user account");
1452fc5e985bSRichard Marian Thomaiyar return ipmi::responseParmOutOfRange();
1453fc5e985bSRichard Marian Thomaiyar }
1454822b0b40SSuryakanth Sekar if (userPassword.size() != 0)
1455822b0b40SSuryakanth Sekar {
1456fc5e985bSRichard Marian Thomaiyar constexpr uint8_t minPasswordSizeRequired = 6;
145723939855SPatrick Williams SecureString passwd;
1458fc5e985bSRichard Marian Thomaiyar if (userPassword.size() < minPasswordSizeRequired ||
1459fc5e985bSRichard Marian Thomaiyar userPassword.size() > ipmi::maxIpmi20PasswordSize)
1460fc5e985bSRichard Marian Thomaiyar {
14619420416aSJayaprakash Mutyala OPENSSL_cleanse(userPassword.data(), userPassword.size());
1462fc5e985bSRichard Marian Thomaiyar return ipmi::responseReqDataLenInvalid();
1463fc5e985bSRichard Marian Thomaiyar }
1464fc5e985bSRichard Marian Thomaiyar passwd.assign(reinterpret_cast<const char*>(userPassword.data()),
1465fc5e985bSRichard Marian Thomaiyar userPassword.size());
14669420416aSJayaprakash Mutyala // Clear sensitive data
14679420416aSJayaprakash Mutyala OPENSSL_cleanse(userPassword.data(), userPassword.size());
1468822b0b40SSuryakanth Sekar if (specialUserIndex ==
1469822b0b40SSuryakanth Sekar static_cast<uint8_t>(SpecialUserIndex::atScaleDebugUser))
1470822b0b40SSuryakanth Sekar {
1471822b0b40SSuryakanth Sekar status = ipmiSetSpecialUserPassword("asdbg", passwd);
1472822b0b40SSuryakanth Sekar
1473822b0b40SSuryakanth Sekar atScaleDebugEventlog("AtScaleDebugSpecialUserEnabled", LOG_CRIT);
1474822b0b40SSuryakanth Sekar }
1475822b0b40SSuryakanth Sekar else
1476822b0b40SSuryakanth Sekar {
1477822b0b40SSuryakanth Sekar status = ipmiSetSpecialUserPassword("root", passwd);
1478822b0b40SSuryakanth Sekar }
1479822b0b40SSuryakanth Sekar return ipmi::response(status);
1480822b0b40SSuryakanth Sekar }
1481822b0b40SSuryakanth Sekar else
1482822b0b40SSuryakanth Sekar {
1483822b0b40SSuryakanth Sekar if (specialUserIndex ==
1484822b0b40SSuryakanth Sekar static_cast<uint8_t>(SpecialUserIndex::rootUser))
1485822b0b40SSuryakanth Sekar {
1486822b0b40SSuryakanth Sekar status = executeCmd("passwd -d root");
1487822b0b40SSuryakanth Sekar }
1488822b0b40SSuryakanth Sekar else
1489822b0b40SSuryakanth Sekar {
1490822b0b40SSuryakanth Sekar status = executeCmd("passwd -d asdbg");
1491822b0b40SSuryakanth Sekar
1492822b0b40SSuryakanth Sekar if (status == 0)
1493822b0b40SSuryakanth Sekar {
1494822b0b40SSuryakanth Sekar atScaleDebugEventlog("AtScaleDebugSpecialUserDisabled",
1495822b0b40SSuryakanth Sekar LOG_INFO);
1496822b0b40SSuryakanth Sekar }
1497822b0b40SSuryakanth Sekar }
1498822b0b40SSuryakanth Sekar return ipmi::response(status);
1499822b0b40SSuryakanth Sekar }
1500fc5e985bSRichard Marian Thomaiyar }
1501fc5e985bSRichard Marian Thomaiyar
150245f04988SKuiying Wang namespace ledAction
150345f04988SKuiying Wang {
150445f04988SKuiying Wang using namespace sdbusplus::xyz::openbmc_project::Led::server;
150545f04988SKuiying Wang std::map<Physical::Action, uint8_t> actionDbusToIpmi = {
1506934ee9c9Sjayaprakash Mutyala {Physical::Action::Off, 0},
1507934ee9c9Sjayaprakash Mutyala {Physical::Action::On, 2},
1508934ee9c9Sjayaprakash Mutyala {Physical::Action::Blink, 1}};
150945f04988SKuiying Wang
151045f04988SKuiying Wang std::map<uint8_t, std::string> offsetObjPath = {
151145f04988SKuiying Wang {2, statusAmberObjPath}, {4, statusGreenObjPath}, {6, identifyLEDObjPath}};
151245f04988SKuiying Wang
151345f04988SKuiying Wang } // namespace ledAction
151445f04988SKuiying Wang
getLEDState(sdbusplus::bus_t & bus,const std::string & intf,const std::string & objPath,uint8_t & state)1515f944d2e5SPatrick Williams int8_t getLEDState(sdbusplus::bus_t& bus, const std::string& intf,
151645f04988SKuiying Wang const std::string& objPath, uint8_t& state)
151745f04988SKuiying Wang {
151845f04988SKuiying Wang try
151945f04988SKuiying Wang {
152045f04988SKuiying Wang std::string service = getService(bus, intf, objPath);
15211bcced08SPatrick Williams Value stateValue =
15221bcced08SPatrick Williams getDbusProperty(bus, service, objPath, intf, "State");
15238166c8d7SVernon Mauery std::string strState = std::get<std::string>(stateValue);
152445f04988SKuiying Wang state = ledAction::actionDbusToIpmi.at(
152545f04988SKuiying Wang sdbusplus::xyz::openbmc_project::Led::server::Physical::
152645f04988SKuiying Wang convertActionFromString(strState));
152745f04988SKuiying Wang }
1528f944d2e5SPatrick Williams catch (const sdbusplus::exception_t& e)
152945f04988SKuiying Wang {
153045f04988SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
153145f04988SKuiying Wang return -1;
153245f04988SKuiying Wang }
153345f04988SKuiying Wang return 0;
153445f04988SKuiying Wang }
153545f04988SKuiying Wang
ipmiOEMGetLEDStatus()1536abd11ca3SNITIN SHARMA ipmi::RspType<uint8_t> ipmiOEMGetLEDStatus()
153745f04988SKuiying Wang {
1538abd11ca3SNITIN SHARMA uint8_t ledstate = 0;
153945f04988SKuiying Wang phosphor::logging::log<phosphor::logging::level::DEBUG>("GET led status");
154015419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
154145f04988SKuiying Wang for (auto it = ledAction::offsetObjPath.begin();
154245f04988SKuiying Wang it != ledAction::offsetObjPath.end(); ++it)
154345f04988SKuiying Wang {
154445f04988SKuiying Wang uint8_t state = 0;
1545abd11ca3SNITIN SHARMA if (getLEDState(*dbus, ledIntf, it->second, state) == -1)
154645f04988SKuiying Wang {
154745f04988SKuiying Wang phosphor::logging::log<phosphor::logging::level::ERR>(
154845f04988SKuiying Wang "oem_get_led_status: fail to get ID LED status!");
1549abd11ca3SNITIN SHARMA return ipmi::responseUnspecifiedError();
155045f04988SKuiying Wang }
1551abd11ca3SNITIN SHARMA ledstate |= state << it->first;
155245f04988SKuiying Wang }
1553abd11ca3SNITIN SHARMA return ipmi::responseSuccess(ledstate);
155445f04988SKuiying Wang }
155545f04988SKuiying Wang
ipmiOEMCfgHostSerialPortSpeed(ipmi_netfn_t,ipmi_cmd_t,ipmi_request_t request,ipmi_response_t response,ipmi_data_len_t dataLen,ipmi_context_t)15561bcced08SPatrick Williams ipmi_ret_t ipmiOEMCfgHostSerialPortSpeed(
15571bcced08SPatrick Williams ipmi_netfn_t, ipmi_cmd_t, ipmi_request_t request, ipmi_response_t response,
15581bcced08SPatrick Williams ipmi_data_len_t dataLen, ipmi_context_t)
155923737fe3SYong Li {
156023737fe3SYong Li CfgHostSerialReq* req = reinterpret_cast<CfgHostSerialReq*>(request);
156123737fe3SYong Li uint8_t* resp = reinterpret_cast<uint8_t*>(response);
156223737fe3SYong Li
156323737fe3SYong Li if (*dataLen == 0)
156423737fe3SYong Li {
156523737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
156623737fe3SYong Li "CfgHostSerial: invalid input len!",
156723737fe3SYong Li phosphor::logging::entry("LEN=%d", *dataLen));
156823737fe3SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID;
156923737fe3SYong Li }
157023737fe3SYong Li
157123737fe3SYong Li switch (req->command)
157223737fe3SYong Li {
157323737fe3SYong Li case getHostSerialCfgCmd:
157423737fe3SYong Li {
157523737fe3SYong Li if (*dataLen != 1)
157623737fe3SYong Li {
157723737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
157823737fe3SYong Li "CfgHostSerial: invalid input len!");
157923737fe3SYong Li *dataLen = 0;
158023737fe3SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID;
158123737fe3SYong Li }
158223737fe3SYong Li
158323737fe3SYong Li *dataLen = 0;
158423737fe3SYong Li
158523737fe3SYong Li boost::process::ipstream is;
158623737fe3SYong Li std::vector<std::string> data;
158723737fe3SYong Li std::string line;
158823737fe3SYong Li boost::process::child c1(fwGetEnvCmd, "-n", fwHostSerailCfgEnvName,
158923737fe3SYong Li boost::process::std_out > is);
159023737fe3SYong Li
159123737fe3SYong Li while (c1.running() && std::getline(is, line) && !line.empty())
159223737fe3SYong Li {
159323737fe3SYong Li data.push_back(line);
159423737fe3SYong Li }
159523737fe3SYong Li
159623737fe3SYong Li c1.wait();
159723737fe3SYong Li if (c1.exit_code())
159823737fe3SYong Li {
159923737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
160023737fe3SYong Li "CfgHostSerial:: error on execute",
160123737fe3SYong Li phosphor::logging::entry("EXECUTE=%s", fwSetEnvCmd));
160223737fe3SYong Li // Using the default value
160323737fe3SYong Li *resp = 0;
160423737fe3SYong Li }
160523737fe3SYong Li else
160623737fe3SYong Li {
160723737fe3SYong Li if (data.size() != 1)
160823737fe3SYong Li {
160923737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
161023737fe3SYong Li "CfgHostSerial:: error on read env");
161123737fe3SYong Li return IPMI_CC_UNSPECIFIED_ERROR;
161223737fe3SYong Li }
161323737fe3SYong Li try
161423737fe3SYong Li {
161523737fe3SYong Li unsigned long tmp = std::stoul(data[0]);
161623737fe3SYong Li if (tmp > std::numeric_limits<uint8_t>::max())
161723737fe3SYong Li {
161823737fe3SYong Li throw std::out_of_range("Out of range");
161923737fe3SYong Li }
162023737fe3SYong Li *resp = static_cast<uint8_t>(tmp);
162123737fe3SYong Li }
162223737fe3SYong Li catch (const std::invalid_argument& e)
162323737fe3SYong Li {
162423737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
162523737fe3SYong Li "invalid config ",
162623737fe3SYong Li phosphor::logging::entry("ERR=%s", e.what()));
162723737fe3SYong Li return IPMI_CC_UNSPECIFIED_ERROR;
162823737fe3SYong Li }
162923737fe3SYong Li catch (const std::out_of_range& e)
163023737fe3SYong Li {
163123737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
163223737fe3SYong Li "out_of_range config ",
163323737fe3SYong Li phosphor::logging::entry("ERR=%s", e.what()));
163423737fe3SYong Li return IPMI_CC_UNSPECIFIED_ERROR;
163523737fe3SYong Li }
163623737fe3SYong Li }
163723737fe3SYong Li
163823737fe3SYong Li *dataLen = 1;
163923737fe3SYong Li break;
164023737fe3SYong Li }
164123737fe3SYong Li case setHostSerialCfgCmd:
164223737fe3SYong Li {
164323737fe3SYong Li if (*dataLen != sizeof(CfgHostSerialReq))
164423737fe3SYong Li {
164523737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
164623737fe3SYong Li "CfgHostSerial: invalid input len!");
164723737fe3SYong Li *dataLen = 0;
164823737fe3SYong Li return IPMI_CC_REQ_DATA_LEN_INVALID;
164923737fe3SYong Li }
165023737fe3SYong Li
165123737fe3SYong Li *dataLen = 0;
165223737fe3SYong Li
165323737fe3SYong Li if (req->parameter > HostSerialCfgParamMax)
165423737fe3SYong Li {
165523737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
165623737fe3SYong Li "CfgHostSerial: invalid input!");
165723737fe3SYong Li return IPMI_CC_INVALID_FIELD_REQUEST;
165823737fe3SYong Li }
165923737fe3SYong Li
166023737fe3SYong Li boost::process::child c1(fwSetEnvCmd, fwHostSerailCfgEnvName,
166123737fe3SYong Li std::to_string(req->parameter));
166223737fe3SYong Li
166323737fe3SYong Li c1.wait();
166423737fe3SYong Li if (c1.exit_code())
166523737fe3SYong Li {
166623737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
166723737fe3SYong Li "CfgHostSerial:: error on execute",
166823737fe3SYong Li phosphor::logging::entry("EXECUTE=%s", fwGetEnvCmd));
166923737fe3SYong Li return IPMI_CC_UNSPECIFIED_ERROR;
167023737fe3SYong Li }
167123737fe3SYong Li break;
167223737fe3SYong Li }
167323737fe3SYong Li default:
167423737fe3SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
167523737fe3SYong Li "CfgHostSerial: invalid input!");
167623737fe3SYong Li *dataLen = 0;
167723737fe3SYong Li return IPMI_CC_INVALID_FIELD_REQUEST;
167823737fe3SYong Li }
167923737fe3SYong Li
168023737fe3SYong Li return IPMI_CC_OK;
168123737fe3SYong Li }
168223737fe3SYong Li
168391244a6aSJames Feist constexpr const char* thermalModeInterface =
168491244a6aSJames Feist "xyz.openbmc_project.Control.ThermalMode";
168591244a6aSJames Feist constexpr const char* thermalModePath =
168691244a6aSJames Feist "/xyz/openbmc_project/control/thermal_mode";
168791244a6aSJames Feist
getFanProfileInterface(sdbusplus::bus_t & bus,boost::container::flat_map<std::string,ipmi::DbusVariant> & resp)168891244a6aSJames Feist bool getFanProfileInterface(
1689f944d2e5SPatrick Williams sdbusplus::bus_t& bus,
16900748c69dSJason M. Bills boost::container::flat_map<std::string, ipmi::DbusVariant>& resp)
169191244a6aSJames Feist {
169291244a6aSJames Feist auto call = bus.new_method_call(settingsBusName, thermalModePath, PROP_INTF,
169391244a6aSJames Feist "GetAll");
169491244a6aSJames Feist call.append(thermalModeInterface);
169591244a6aSJames Feist try
169691244a6aSJames Feist {
169791244a6aSJames Feist auto data = bus.call(call);
169891244a6aSJames Feist data.read(resp);
169991244a6aSJames Feist }
1700bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
170191244a6aSJames Feist {
170291244a6aSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
170391244a6aSJames Feist "getFanProfileInterface: can't get thermal mode!",
170491244a6aSJames Feist phosphor::logging::entry("ERR=%s", e.what()));
170591244a6aSJames Feist return false;
170691244a6aSJames Feist }
170791244a6aSJames Feist return true;
170891244a6aSJames Feist }
170991244a6aSJames Feist
1710f945eee0Sanil kumar appana /**@brief implements the OEM set fan config.
1711f945eee0Sanil kumar appana * @param selectedFanProfile - fan profile to enable
1712f945eee0Sanil kumar appana * @param reserved1
1713f945eee0Sanil kumar appana * @param performanceMode - Performance/Acoustic mode
1714f945eee0Sanil kumar appana * @param reserved2
1715f945eee0Sanil kumar appana * @param setPerformanceMode - set Performance/Acoustic mode
1716f945eee0Sanil kumar appana * @param setFanProfile - set fan profile
1717f945eee0Sanil kumar appana *
1718f945eee0Sanil kumar appana * @return IPMI completion code.
1719f945eee0Sanil kumar appana **/
ipmiOEMSetFanConfig(uint8_t selectedFanProfile,uint2_t reserved1,bool performanceMode,uint3_t reserved2,bool setPerformanceMode,bool setFanProfile,std::optional<uint8_t> dimmGroupId,std::optional<uint32_t> dimmPresenceBitmap)1720dcff1506SVernon Mauery ipmi::RspType<> ipmiOEMSetFanConfig(
1721dcff1506SVernon Mauery [[maybe_unused]] uint8_t selectedFanProfile, uint2_t reserved1,
1722dcff1506SVernon Mauery bool performanceMode, uint3_t reserved2, bool setPerformanceMode,
1723dcff1506SVernon Mauery [[maybe_unused]] bool setFanProfile, std::optional<uint8_t> dimmGroupId,
1724dcff1506SVernon Mauery [[maybe_unused]] std::optional<uint32_t> dimmPresenceBitmap)
172591244a6aSJames Feist {
1726f945eee0Sanil kumar appana if (reserved1 || reserved2)
1727f945eee0Sanil kumar appana {
1728f945eee0Sanil kumar appana return ipmi::responseInvalidFieldRequest();
172991244a6aSJames Feist }
1730619186dbSJoshi-Mansi
1731619186dbSJoshi-Mansi if (dimmGroupId)
1732619186dbSJoshi-Mansi {
1733619186dbSJoshi-Mansi if (*dimmGroupId >= maxCPUNum)
1734619186dbSJoshi-Mansi {
1735619186dbSJoshi-Mansi return ipmi::responseInvalidFieldRequest();
1736619186dbSJoshi-Mansi }
17376224dec4SSnehalatha Venkatesh if (!cpuPresent("cpu" + std::to_string(*dimmGroupId)))
1738619186dbSJoshi-Mansi {
1739619186dbSJoshi-Mansi return ipmi::responseInvalidFieldRequest();
1740619186dbSJoshi-Mansi }
1741619186dbSJoshi-Mansi }
1742619186dbSJoshi-Mansi
174391244a6aSJames Feist // todo: tell bios to only send first 2 bytes
17440748c69dSJason M. Bills boost::container::flat_map<std::string, ipmi::DbusVariant> profileData;
174515419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
174615419dd5SVernon Mauery if (!getFanProfileInterface(*dbus, profileData))
174791244a6aSJames Feist {
1748f945eee0Sanil kumar appana return ipmi::responseUnspecifiedError();
174991244a6aSJames Feist }
175091244a6aSJames Feist
175191244a6aSJames Feist std::vector<std::string>* supported =
175291244a6aSJames Feist std::get_if<std::vector<std::string>>(&profileData["Supported"]);
175391244a6aSJames Feist if (supported == nullptr)
175491244a6aSJames Feist {
1755f945eee0Sanil kumar appana return ipmi::responseInvalidFieldRequest();
175691244a6aSJames Feist }
175791244a6aSJames Feist std::string mode;
1758f945eee0Sanil kumar appana if (setPerformanceMode)
175991244a6aSJames Feist {
176091244a6aSJames Feist if (performanceMode)
176191244a6aSJames Feist {
176291244a6aSJames Feist if (std::find(supported->begin(), supported->end(),
176391244a6aSJames Feist "Performance") != supported->end())
176491244a6aSJames Feist {
176591244a6aSJames Feist mode = "Performance";
176691244a6aSJames Feist }
176791244a6aSJames Feist }
176891244a6aSJames Feist else
176991244a6aSJames Feist {
177091244a6aSJames Feist if (std::find(supported->begin(), supported->end(), "Acoustic") !=
177191244a6aSJames Feist supported->end())
177291244a6aSJames Feist {
177391244a6aSJames Feist mode = "Acoustic";
177491244a6aSJames Feist }
177591244a6aSJames Feist }
177691244a6aSJames Feist if (mode.empty())
177791244a6aSJames Feist {
1778f945eee0Sanil kumar appana return ipmi::responseInvalidFieldRequest();
177991244a6aSJames Feist }
1780f945eee0Sanil kumar appana
1781f945eee0Sanil kumar appana try
1782f945eee0Sanil kumar appana {
178315419dd5SVernon Mauery setDbusProperty(*dbus, settingsBusName, thermalModePath,
178491244a6aSJames Feist thermalModeInterface, "Current", mode);
178591244a6aSJames Feist }
1786bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
1787f945eee0Sanil kumar appana {
1788f945eee0Sanil kumar appana phosphor::logging::log<phosphor::logging::level::ERR>(
1789f945eee0Sanil kumar appana "ipmiOEMSetFanConfig: can't set thermal mode!",
1790f945eee0Sanil kumar appana phosphor::logging::entry("EXCEPTION=%s", e.what()));
1791f945eee0Sanil kumar appana return ipmi::responseResponseError();
1792f945eee0Sanil kumar appana }
1793f945eee0Sanil kumar appana }
179491244a6aSJames Feist
1795f945eee0Sanil kumar appana return ipmi::responseSuccess();
179691244a6aSJames Feist }
179791244a6aSJames Feist
17985b693637SJames Feist ipmi::RspType<uint8_t, // profile support map
17995b693637SJames Feist uint8_t, // fan control profile enable
18005b693637SJames Feist uint8_t, // flags
18015b693637SJames Feist uint32_t // dimm presence bit map
18025b693637SJames Feist >
ipmiOEMGetFanConfig(uint8_t dimmGroupId)18035b693637SJames Feist ipmiOEMGetFanConfig(uint8_t dimmGroupId)
180491244a6aSJames Feist {
180536f05ce6SJoshi-Mansi if (dimmGroupId >= maxCPUNum)
180636f05ce6SJoshi-Mansi {
180736f05ce6SJoshi-Mansi return ipmi::responseInvalidFieldRequest();
180836f05ce6SJoshi-Mansi }
180936f05ce6SJoshi-Mansi
18106224dec4SSnehalatha Venkatesh bool cpuStatus = cpuPresent("cpu" + std::to_string(dimmGroupId));
181136f05ce6SJoshi-Mansi
181236f05ce6SJoshi-Mansi if (!cpuStatus)
181336f05ce6SJoshi-Mansi {
181436f05ce6SJoshi-Mansi return ipmi::responseInvalidFieldRequest();
181536f05ce6SJoshi-Mansi }
181636f05ce6SJoshi-Mansi
18170748c69dSJason M. Bills boost::container::flat_map<std::string, ipmi::DbusVariant> profileData;
181891244a6aSJames Feist
181915419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
182015419dd5SVernon Mauery if (!getFanProfileInterface(*dbus, profileData))
182191244a6aSJames Feist {
18225b693637SJames Feist return ipmi::responseResponseError();
182391244a6aSJames Feist }
182491244a6aSJames Feist
182591244a6aSJames Feist std::string* current = std::get_if<std::string>(&profileData["Current"]);
182691244a6aSJames Feist
182791244a6aSJames Feist if (current == nullptr)
182891244a6aSJames Feist {
182991244a6aSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
183091244a6aSJames Feist "ipmiOEMGetFanConfig: can't get current mode!");
18315b693637SJames Feist return ipmi::responseResponseError();
183291244a6aSJames Feist }
183391244a6aSJames Feist bool performance = (*current == "Performance");
183491244a6aSJames Feist
18355b693637SJames Feist uint8_t flags = 0;
183691244a6aSJames Feist if (performance)
183791244a6aSJames Feist {
18385b693637SJames Feist flags |= 1 << 2;
183991244a6aSJames Feist }
184091244a6aSJames Feist
18414b1552d8Sjayaprakash Mutyala constexpr uint8_t fanControlDefaultProfile = 0x80;
18424b1552d8Sjayaprakash Mutyala constexpr uint8_t fanControlProfileState = 0x00;
18434b1552d8Sjayaprakash Mutyala constexpr uint32_t dimmPresenceBitmap = 0x00;
18444b1552d8Sjayaprakash Mutyala
18454b1552d8Sjayaprakash Mutyala return ipmi::responseSuccess(fanControlDefaultProfile,
18464b1552d8Sjayaprakash Mutyala fanControlProfileState, flags,
18474b1552d8Sjayaprakash Mutyala dimmPresenceBitmap);
184891244a6aSJames Feist }
18495f957cafSJames Feist constexpr const char* cfmLimitSettingPath =
18505f957cafSJames Feist "/xyz/openbmc_project/control/cfm_limit";
18515f957cafSJames Feist constexpr const char* cfmLimitIface = "xyz.openbmc_project.Control.CFMLimit";
1852faa4f223SJames Feist constexpr const size_t legacyExitAirSensorNumber = 0x2e;
185309f6b604SJames Feist constexpr const size_t legacyPCHSensorNumber = 0x22;
185409f6b604SJames Feist constexpr const char* exitAirPathName = "Exit_Air";
185509f6b604SJames Feist constexpr const char* pchPathName = "SSB_Temp";
1856acc8a4ebSJames Feist constexpr const char* pidConfigurationIface =
1857acc8a4ebSJames Feist "xyz.openbmc_project.Configuration.Pid";
1858faa4f223SJames Feist
getConfigPath(const std::string & name)185909f6b604SJames Feist static std::string getConfigPath(const std::string& name)
1860faa4f223SJames Feist {
186115419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
18621bcced08SPatrick Williams auto method =
18631bcced08SPatrick Williams dbus->new_method_call("xyz.openbmc_project.ObjectMapper",
1864faa4f223SJames Feist "/xyz/openbmc_project/object_mapper",
18651bcced08SPatrick Williams "xyz.openbmc_project.ObjectMapper", "GetSubTree");
1866faa4f223SJames Feist
1867acc8a4ebSJames Feist method.append("/", 0, std::array<const char*, 1>{pidConfigurationIface});
1868faa4f223SJames Feist std::string path;
1869faa4f223SJames Feist GetSubTreeType resp;
1870faa4f223SJames Feist try
1871faa4f223SJames Feist {
187215419dd5SVernon Mauery auto reply = dbus->call(method);
1873faa4f223SJames Feist reply.read(resp);
1874faa4f223SJames Feist }
1875bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t&)
1876faa4f223SJames Feist {
1877faa4f223SJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
1878faa4f223SJames Feist "ipmiOEMGetFscParameter: mapper error");
1879faa4f223SJames Feist };
18801bcced08SPatrick Williams auto config =
18811bcced08SPatrick Williams std::find_if(resp.begin(), resp.end(), [&name](const auto& pair) {
188209f6b604SJames Feist return pair.first.find(name) != std::string::npos;
1883faa4f223SJames Feist });
1884faa4f223SJames Feist if (config != resp.end())
1885faa4f223SJames Feist {
1886faa4f223SJames Feist path = std::move(config->first);
1887faa4f223SJames Feist }
1888faa4f223SJames Feist return path;
1889faa4f223SJames Feist }
18905f957cafSJames Feist
1891acc8a4ebSJames Feist // flat map to make alphabetical
getPidConfigs()1892acc8a4ebSJames Feist static boost::container::flat_map<std::string, PropertyMap> getPidConfigs()
1893acc8a4ebSJames Feist {
1894acc8a4ebSJames Feist boost::container::flat_map<std::string, PropertyMap> ret;
189515419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
18961bcced08SPatrick Williams auto method =
18971bcced08SPatrick Williams dbus->new_method_call("xyz.openbmc_project.ObjectMapper",
1898acc8a4ebSJames Feist "/xyz/openbmc_project/object_mapper",
18991bcced08SPatrick Williams "xyz.openbmc_project.ObjectMapper", "GetSubTree");
1900acc8a4ebSJames Feist
1901acc8a4ebSJames Feist method.append("/", 0, std::array<const char*, 1>{pidConfigurationIface});
1902acc8a4ebSJames Feist GetSubTreeType resp;
1903acc8a4ebSJames Feist
1904acc8a4ebSJames Feist try
1905acc8a4ebSJames Feist {
190615419dd5SVernon Mauery auto reply = dbus->call(method);
1907acc8a4ebSJames Feist reply.read(resp);
1908acc8a4ebSJames Feist }
1909bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t&)
1910acc8a4ebSJames Feist {
1911acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
1912acc8a4ebSJames Feist "getFanConfigPaths: mapper error");
1913acc8a4ebSJames Feist };
1914acc8a4ebSJames Feist for (const auto& [path, objects] : resp)
1915acc8a4ebSJames Feist {
1916acc8a4ebSJames Feist if (objects.empty())
1917acc8a4ebSJames Feist {
1918acc8a4ebSJames Feist continue; // should be impossible
1919acc8a4ebSJames Feist }
1920be560b09SZhu, Yunge
1921be560b09SZhu, Yunge try
1922be560b09SZhu, Yunge {
192315419dd5SVernon Mauery ret.emplace(path,
192415419dd5SVernon Mauery getAllDbusProperties(*dbus, objects[0].first, path,
1925acc8a4ebSJames Feist pidConfigurationIface));
1926acc8a4ebSJames Feist }
1927bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
1928be560b09SZhu, Yunge {
1929be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>(
1930be560b09SZhu, Yunge "getPidConfigs: can't get DbusProperties!",
1931be560b09SZhu, Yunge phosphor::logging::entry("ERR=%s", e.what()));
1932be560b09SZhu, Yunge }
1933be560b09SZhu, Yunge }
1934acc8a4ebSJames Feist return ret;
1935acc8a4ebSJames Feist }
1936acc8a4ebSJames Feist
ipmiOEMGetFanSpeedOffset(void)1937acc8a4ebSJames Feist ipmi::RspType<uint8_t> ipmiOEMGetFanSpeedOffset(void)
1938acc8a4ebSJames Feist {
1939acc8a4ebSJames Feist boost::container::flat_map<std::string, PropertyMap> data = getPidConfigs();
1940acc8a4ebSJames Feist if (data.empty())
1941acc8a4ebSJames Feist {
1942acc8a4ebSJames Feist return ipmi::responseResponseError();
1943acc8a4ebSJames Feist }
1944acc8a4ebSJames Feist uint8_t minOffset = std::numeric_limits<uint8_t>::max();
1945acc8a4ebSJames Feist for (const auto& [_, pid] : data)
1946acc8a4ebSJames Feist {
1947acc8a4ebSJames Feist auto findClass = pid.find("Class");
1948acc8a4ebSJames Feist if (findClass == pid.end())
1949acc8a4ebSJames Feist {
1950acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
1951acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found illegal pid "
1952acc8a4ebSJames Feist "configurations");
1953acc8a4ebSJames Feist return ipmi::responseResponseError();
1954acc8a4ebSJames Feist }
1955acc8a4ebSJames Feist std::string type = std::get<std::string>(findClass->second);
1956acc8a4ebSJames Feist if (type == "fan")
1957acc8a4ebSJames Feist {
1958acc8a4ebSJames Feist auto findOutLimit = pid.find("OutLimitMin");
1959acc8a4ebSJames Feist if (findOutLimit == pid.end())
1960acc8a4ebSJames Feist {
1961acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
1962acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found illegal pid "
1963acc8a4ebSJames Feist "configurations");
1964acc8a4ebSJames Feist return ipmi::responseResponseError();
1965acc8a4ebSJames Feist }
1966acc8a4ebSJames Feist // get the min out of all the offsets
1967acc8a4ebSJames Feist minOffset = std::min(
1968acc8a4ebSJames Feist minOffset,
1969acc8a4ebSJames Feist static_cast<uint8_t>(std::get<double>(findOutLimit->second)));
1970acc8a4ebSJames Feist }
1971acc8a4ebSJames Feist }
1972acc8a4ebSJames Feist if (minOffset == std::numeric_limits<uint8_t>::max())
1973acc8a4ebSJames Feist {
1974acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
1975acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found no fan configurations!");
1976acc8a4ebSJames Feist return ipmi::responseResponseError();
1977acc8a4ebSJames Feist }
1978acc8a4ebSJames Feist
1979acc8a4ebSJames Feist return ipmi::responseSuccess(minOffset);
1980acc8a4ebSJames Feist }
1981acc8a4ebSJames Feist
ipmiOEMSetFanSpeedOffset(uint8_t offset)1982acc8a4ebSJames Feist ipmi::RspType<> ipmiOEMSetFanSpeedOffset(uint8_t offset)
1983acc8a4ebSJames Feist {
1984baa579f9SManish Baing constexpr uint8_t maxFanSpeedOffset = 100;
1985baa579f9SManish Baing if (offset > maxFanSpeedOffset)
1986baa579f9SManish Baing {
1987baa579f9SManish Baing phosphor::logging::log<phosphor::logging::level::ERR>(
1988baa579f9SManish Baing "ipmiOEMSetFanSpeedOffset: fan offset greater than limit");
1989baa579f9SManish Baing return ipmi::responseInvalidFieldRequest();
1990baa579f9SManish Baing }
1991acc8a4ebSJames Feist boost::container::flat_map<std::string, PropertyMap> data = getPidConfigs();
1992acc8a4ebSJames Feist if (data.empty())
1993acc8a4ebSJames Feist {
1994acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
1995acc8a4ebSJames Feist "ipmiOEMSetFanSpeedOffset: found no pid configurations!");
1996acc8a4ebSJames Feist return ipmi::responseResponseError();
1997acc8a4ebSJames Feist }
1998acc8a4ebSJames Feist
199915419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
2000acc8a4ebSJames Feist bool found = false;
2001acc8a4ebSJames Feist for (const auto& [path, pid] : data)
2002acc8a4ebSJames Feist {
2003acc8a4ebSJames Feist auto findClass = pid.find("Class");
2004acc8a4ebSJames Feist if (findClass == pid.end())
2005acc8a4ebSJames Feist {
2006acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2007acc8a4ebSJames Feist "ipmiOEMSetFanSpeedOffset: found illegal pid "
2008acc8a4ebSJames Feist "configurations");
2009acc8a4ebSJames Feist return ipmi::responseResponseError();
2010acc8a4ebSJames Feist }
2011acc8a4ebSJames Feist std::string type = std::get<std::string>(findClass->second);
2012acc8a4ebSJames Feist if (type == "fan")
2013acc8a4ebSJames Feist {
2014acc8a4ebSJames Feist auto findOutLimit = pid.find("OutLimitMin");
2015acc8a4ebSJames Feist if (findOutLimit == pid.end())
2016acc8a4ebSJames Feist {
2017acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2018acc8a4ebSJames Feist "ipmiOEMSetFanSpeedOffset: found illegal pid "
2019acc8a4ebSJames Feist "configurations");
2020acc8a4ebSJames Feist return ipmi::responseResponseError();
2021acc8a4ebSJames Feist }
202215419dd5SVernon Mauery ipmi::setDbusProperty(*dbus, "xyz.openbmc_project.EntityManager",
2023acc8a4ebSJames Feist path, pidConfigurationIface, "OutLimitMin",
2024acc8a4ebSJames Feist static_cast<double>(offset));
2025acc8a4ebSJames Feist found = true;
2026acc8a4ebSJames Feist }
2027acc8a4ebSJames Feist }
2028acc8a4ebSJames Feist if (!found)
2029acc8a4ebSJames Feist {
2030acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2031acc8a4ebSJames Feist "ipmiOEMSetFanSpeedOffset: set no fan offsets");
2032acc8a4ebSJames Feist return ipmi::responseResponseError();
2033acc8a4ebSJames Feist }
2034acc8a4ebSJames Feist
2035acc8a4ebSJames Feist return ipmi::responseSuccess();
2036acc8a4ebSJames Feist }
2037acc8a4ebSJames Feist
ipmiOEMSetFscParameter(uint8_t command,uint8_t param1,uint8_t param2)2038acc8a4ebSJames Feist ipmi::RspType<> ipmiOEMSetFscParameter(uint8_t command, uint8_t param1,
2039acc8a4ebSJames Feist uint8_t param2)
20405f957cafSJames Feist {
20415f957cafSJames Feist constexpr const size_t disableLimiting = 0x0;
20425f957cafSJames Feist
204315419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
2044acc8a4ebSJames Feist if (command == static_cast<uint8_t>(setFscParamFlags::tcontrol))
20455f957cafSJames Feist {
204609f6b604SJames Feist std::string pathName;
2047acc8a4ebSJames Feist if (param1 == legacyExitAirSensorNumber)
2048faa4f223SJames Feist {
204909f6b604SJames Feist pathName = exitAirPathName;
205009f6b604SJames Feist }
205109f6b604SJames Feist else if (param1 == legacyPCHSensorNumber)
205209f6b604SJames Feist {
205309f6b604SJames Feist pathName = pchPathName;
2054faa4f223SJames Feist }
2055faa4f223SJames Feist else
2056faa4f223SJames Feist {
2057acc8a4ebSJames Feist return ipmi::responseParmOutOfRange();
2058faa4f223SJames Feist }
205909f6b604SJames Feist std::string path = getConfigPath(pathName);
206009f6b604SJames Feist ipmi::setDbusProperty(*dbus, "xyz.openbmc_project.EntityManager", path,
206109f6b604SJames Feist pidConfigurationIface, "SetPoint",
206209f6b604SJames Feist static_cast<double>(param2));
206309f6b604SJames Feist return ipmi::responseSuccess();
2064faa4f223SJames Feist }
2065acc8a4ebSJames Feist else if (command == static_cast<uint8_t>(setFscParamFlags::cfm))
20665f957cafSJames Feist {
2067acc8a4ebSJames Feist uint16_t cfm = param1 | (static_cast<uint16_t>(param2) << 8);
20685f957cafSJames Feist
20695f957cafSJames Feist // must be greater than 50 based on eps
20705f957cafSJames Feist if (cfm < 50 && cfm != disableLimiting)
20715f957cafSJames Feist {
2072acc8a4ebSJames Feist return ipmi::responseParmOutOfRange();
20735f957cafSJames Feist }
20745f957cafSJames Feist
20755f957cafSJames Feist try
20765f957cafSJames Feist {
207715419dd5SVernon Mauery ipmi::setDbusProperty(*dbus, settingsBusName, cfmLimitSettingPath,
20785f957cafSJames Feist cfmLimitIface, "Limit",
20795f957cafSJames Feist static_cast<double>(cfm));
20805f957cafSJames Feist }
2081bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
20825f957cafSJames Feist {
20835f957cafSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
20845f957cafSJames Feist "ipmiOEMSetFscParameter: can't set cfm setting!",
20855f957cafSJames Feist phosphor::logging::entry("ERR=%s", e.what()));
2086acc8a4ebSJames Feist return ipmi::responseResponseError();
20875f957cafSJames Feist }
2088acc8a4ebSJames Feist return ipmi::responseSuccess();
2089acc8a4ebSJames Feist }
2090acc8a4ebSJames Feist else if (command == static_cast<uint8_t>(setFscParamFlags::maxPwm))
2091acc8a4ebSJames Feist {
2092acc8a4ebSJames Feist uint8_t requestedDomainMask = param1;
2093acc8a4ebSJames Feist boost::container::flat_map data = getPidConfigs();
2094acc8a4ebSJames Feist if (data.empty())
2095acc8a4ebSJames Feist {
2096acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2097acc8a4ebSJames Feist "ipmiOEMSetFscParameter: found no pid configurations!");
2098acc8a4ebSJames Feist return ipmi::responseResponseError();
2099acc8a4ebSJames Feist }
2100acc8a4ebSJames Feist size_t count = 0;
2101acc8a4ebSJames Feist for (const auto& [path, pid] : data)
2102acc8a4ebSJames Feist {
2103acc8a4ebSJames Feist auto findClass = pid.find("Class");
2104acc8a4ebSJames Feist if (findClass == pid.end())
2105acc8a4ebSJames Feist {
2106acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2107acc8a4ebSJames Feist "ipmiOEMSetFscParameter: found illegal pid "
2108acc8a4ebSJames Feist "configurations");
2109acc8a4ebSJames Feist return ipmi::responseResponseError();
2110acc8a4ebSJames Feist }
2111acc8a4ebSJames Feist std::string type = std::get<std::string>(findClass->second);
2112acc8a4ebSJames Feist if (type == "fan")
2113acc8a4ebSJames Feist {
2114acc8a4ebSJames Feist if (requestedDomainMask & (1 << count))
2115acc8a4ebSJames Feist {
2116acc8a4ebSJames Feist ipmi::setDbusProperty(
211715419dd5SVernon Mauery *dbus, "xyz.openbmc_project.EntityManager", path,
2118acc8a4ebSJames Feist pidConfigurationIface, "OutLimitMax",
2119acc8a4ebSJames Feist static_cast<double>(param2));
2120acc8a4ebSJames Feist }
2121acc8a4ebSJames Feist count++;
2122acc8a4ebSJames Feist }
2123acc8a4ebSJames Feist }
2124acc8a4ebSJames Feist return ipmi::responseSuccess();
21255f957cafSJames Feist }
21265f957cafSJames Feist else
21275f957cafSJames Feist {
21285f957cafSJames Feist // todo other command parts possibly
21295f957cafSJames Feist // tcontrol is handled in peci now
21305f957cafSJames Feist // fan speed offset not implemented yet
21315f957cafSJames Feist // domain pwm limit not implemented
2132acc8a4ebSJames Feist return ipmi::responseParmOutOfRange();
21335f957cafSJames Feist }
21345f957cafSJames Feist }
21355f957cafSJames Feist
2136acc8a4ebSJames Feist ipmi::RspType<
2137acc8a4ebSJames Feist std::variant<uint8_t, std::array<uint8_t, 2>, std::array<uint16_t, 2>>>
ipmiOEMGetFscParameter(uint8_t command,std::optional<uint8_t> param)2138acc8a4ebSJames Feist ipmiOEMGetFscParameter(uint8_t command, std::optional<uint8_t> param)
21395f957cafSJames Feist {
214009f6b604SJames Feist constexpr uint8_t legacyDefaultSetpoint = -128;
21415f957cafSJames Feist
214215419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
2143acc8a4ebSJames Feist if (command == static_cast<uint8_t>(setFscParamFlags::tcontrol))
21445f957cafSJames Feist {
2145acc8a4ebSJames Feist if (!param)
2146acc8a4ebSJames Feist {
2147acc8a4ebSJames Feist return ipmi::responseReqDataLenInvalid();
21485f957cafSJames Feist }
21495f957cafSJames Feist
215009f6b604SJames Feist std::string pathName;
215109f6b604SJames Feist
215209f6b604SJames Feist if (*param == legacyExitAirSensorNumber)
215309f6b604SJames Feist {
215409f6b604SJames Feist pathName = exitAirPathName;
215509f6b604SJames Feist }
215609f6b604SJames Feist else if (*param == legacyPCHSensorNumber)
215709f6b604SJames Feist {
215809f6b604SJames Feist pathName = pchPathName;
215909f6b604SJames Feist }
216009f6b604SJames Feist else
2161faa4f223SJames Feist {
2162acc8a4ebSJames Feist return ipmi::responseParmOutOfRange();
2163faa4f223SJames Feist }
216409f6b604SJames Feist
216509f6b604SJames Feist uint8_t setpoint = legacyDefaultSetpoint;
216609f6b604SJames Feist std::string path = getConfigPath(pathName);
2167faa4f223SJames Feist if (path.size())
2168faa4f223SJames Feist {
216915419dd5SVernon Mauery Value val = ipmi::getDbusProperty(
217015419dd5SVernon Mauery *dbus, "xyz.openbmc_project.EntityManager", path,
217115419dd5SVernon Mauery pidConfigurationIface, "SetPoint");
2172faa4f223SJames Feist setpoint = std::floor(std::get<double>(val) + 0.5);
2173faa4f223SJames Feist }
2174faa4f223SJames Feist
2175faa4f223SJames Feist // old implementation used to return the "default" and current, we
2176faa4f223SJames Feist // don't make the default readily available so just make both the
2177faa4f223SJames Feist // same
2178faa4f223SJames Feist
2179acc8a4ebSJames Feist return ipmi::responseSuccess(
2180acc8a4ebSJames Feist std::array<uint8_t, 2>{setpoint, setpoint});
2181faa4f223SJames Feist }
2182acc8a4ebSJames Feist else if (command == static_cast<uint8_t>(setFscParamFlags::maxPwm))
2183acc8a4ebSJames Feist {
2184acc8a4ebSJames Feist constexpr const size_t maxDomainCount = 8;
2185acc8a4ebSJames Feist
2186acc8a4ebSJames Feist if (!param)
2187acc8a4ebSJames Feist {
2188acc8a4ebSJames Feist return ipmi::responseReqDataLenInvalid();
2189acc8a4ebSJames Feist }
2190acc8a4ebSJames Feist uint8_t requestedDomain = *param;
2191acc8a4ebSJames Feist if (requestedDomain >= maxDomainCount)
2192acc8a4ebSJames Feist {
2193acc8a4ebSJames Feist return ipmi::responseInvalidFieldRequest();
2194acc8a4ebSJames Feist }
2195acc8a4ebSJames Feist
2196acc8a4ebSJames Feist boost::container::flat_map data = getPidConfigs();
2197acc8a4ebSJames Feist if (data.empty())
2198acc8a4ebSJames Feist {
2199acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2200acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found no pid configurations!");
2201acc8a4ebSJames Feist return ipmi::responseResponseError();
2202acc8a4ebSJames Feist }
2203acc8a4ebSJames Feist size_t count = 0;
2204acc8a4ebSJames Feist for (const auto& [_, pid] : data)
2205acc8a4ebSJames Feist {
2206acc8a4ebSJames Feist auto findClass = pid.find("Class");
2207acc8a4ebSJames Feist if (findClass == pid.end())
2208acc8a4ebSJames Feist {
2209acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2210acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found illegal pid "
2211acc8a4ebSJames Feist "configurations");
2212acc8a4ebSJames Feist return ipmi::responseResponseError();
2213acc8a4ebSJames Feist }
2214acc8a4ebSJames Feist std::string type = std::get<std::string>(findClass->second);
2215acc8a4ebSJames Feist if (type == "fan")
2216acc8a4ebSJames Feist {
2217acc8a4ebSJames Feist if (requestedDomain == count)
2218acc8a4ebSJames Feist {
2219acc8a4ebSJames Feist auto findOutLimit = pid.find("OutLimitMax");
2220acc8a4ebSJames Feist if (findOutLimit == pid.end())
2221acc8a4ebSJames Feist {
2222acc8a4ebSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2223acc8a4ebSJames Feist "ipmiOEMGetFscParameter: found illegal pid "
2224acc8a4ebSJames Feist "configurations");
2225acc8a4ebSJames Feist return ipmi::responseResponseError();
2226acc8a4ebSJames Feist }
2227acc8a4ebSJames Feist
2228acc8a4ebSJames Feist return ipmi::responseSuccess(
2229acc8a4ebSJames Feist static_cast<uint8_t>(std::floor(
2230acc8a4ebSJames Feist std::get<double>(findOutLimit->second) + 0.5)));
2231acc8a4ebSJames Feist }
2232acc8a4ebSJames Feist else
2233acc8a4ebSJames Feist {
2234acc8a4ebSJames Feist count++;
2235acc8a4ebSJames Feist }
2236acc8a4ebSJames Feist }
2237acc8a4ebSJames Feist }
2238acc8a4ebSJames Feist
2239acc8a4ebSJames Feist return ipmi::responseInvalidFieldRequest();
2240acc8a4ebSJames Feist }
2241acc8a4ebSJames Feist else if (command == static_cast<uint8_t>(setFscParamFlags::cfm))
22425f957cafSJames Feist {
22435f957cafSJames Feist /*
22445f957cafSJames Feist DataLen should be 1, but host is sending us an extra bit. As the
2245acc8a4ebSJames Feist previous behavior didn't seem to prevent this, ignore the check for
2246acc8a4ebSJames Feist now.
22475f957cafSJames Feist
2248acc8a4ebSJames Feist if (param)
22495f957cafSJames Feist {
22505f957cafSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
22515f957cafSJames Feist "ipmiOEMGetFscParameter: invalid input len!");
22525f957cafSJames Feist return IPMI_CC_REQ_DATA_LEN_INVALID;
22535f957cafSJames Feist }
22545f957cafSJames Feist */
22555f957cafSJames Feist Value cfmLimit;
22565f957cafSJames Feist Value cfmMaximum;
22575f957cafSJames Feist try
22585f957cafSJames Feist {
225915419dd5SVernon Mauery cfmLimit = ipmi::getDbusProperty(*dbus, settingsBusName,
22605f957cafSJames Feist cfmLimitSettingPath, cfmLimitIface,
22615f957cafSJames Feist "Limit");
22625f957cafSJames Feist cfmMaximum = ipmi::getDbusProperty(
226315419dd5SVernon Mauery *dbus, "xyz.openbmc_project.ExitAirTempSensor",
22645f957cafSJames Feist "/xyz/openbmc_project/control/MaxCFM", cfmLimitIface, "Limit");
22655f957cafSJames Feist }
2266bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
22675f957cafSJames Feist {
22685f957cafSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
2269acc8a4ebSJames Feist "ipmiOEMGetFscParameter: can't get cfm setting!",
22705f957cafSJames Feist phosphor::logging::entry("ERR=%s", e.what()));
2271acc8a4ebSJames Feist return ipmi::responseResponseError();
22725f957cafSJames Feist }
22735f957cafSJames Feist
2274acc8a4ebSJames Feist double cfmMax = std::get<double>(cfmMaximum);
2275acc8a4ebSJames Feist double cfmLim = std::get<double>(cfmLimit);
2276acc8a4ebSJames Feist
2277acc8a4ebSJames Feist cfmLim = std::floor(cfmLim + 0.5);
2278acc8a4ebSJames Feist cfmMax = std::floor(cfmMax + 0.5);
2279acc8a4ebSJames Feist uint16_t cfmLimResp = static_cast<uint16_t>(cfmLim);
2280acc8a4ebSJames Feist uint16_t cfmMaxResp = static_cast<uint16_t>(cfmMax);
2281acc8a4ebSJames Feist
2282acc8a4ebSJames Feist return ipmi::responseSuccess(
2283acc8a4ebSJames Feist std::array<uint16_t, 2>{cfmLimResp, cfmMaxResp});
22845f957cafSJames Feist }
22855f957cafSJames Feist
22865f957cafSJames Feist else
22875f957cafSJames Feist {
22885f957cafSJames Feist // todo other command parts possibly
22895f957cafSJames Feist // domain pwm limit not implemented
2290acc8a4ebSJames Feist return ipmi::responseParmOutOfRange();
22915f957cafSJames Feist }
22925f957cafSJames Feist }
22935f957cafSJames Feist
22940748c69dSJason M. Bills using crConfigVariant = ipmi::DbusVariant;
2295773703a5SCheng C Yang
setCRConfig(ipmi::Context::ptr & ctx,const std::string & property,const crConfigVariant & value,std::chrono::microseconds timeout=ipmi::IPMI_DBUS_TIMEOUT)2296dcff1506SVernon Mauery int setCRConfig(ipmi::Context::ptr& ctx, const std::string& property,
2297773703a5SCheng C Yang const crConfigVariant& value,
2298dcff1506SVernon Mauery [[maybe_unused]] std::chrono::microseconds timeout =
2299dcff1506SVernon Mauery ipmi::IPMI_DBUS_TIMEOUT)
2300773703a5SCheng C Yang {
2301773703a5SCheng C Yang boost::system::error_code ec;
2302773703a5SCheng C Yang ctx->bus->yield_method_call<void>(
2303e45333a8SKuiying Wang ctx->yield, ec, "xyz.openbmc_project.PSURedundancy",
2304773703a5SCheng C Yang "/xyz/openbmc_project/control/power_supply_redundancy",
2305773703a5SCheng C Yang "org.freedesktop.DBus.Properties", "Set",
2306773703a5SCheng C Yang "xyz.openbmc_project.Control.PowerSupplyRedundancy", property, value);
2307773703a5SCheng C Yang if (ec)
2308773703a5SCheng C Yang {
2309773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2310773703a5SCheng C Yang "Failed to set dbus property to cold redundancy");
2311773703a5SCheng C Yang return -1;
2312773703a5SCheng C Yang }
2313773703a5SCheng C Yang
2314773703a5SCheng C Yang return 0;
2315773703a5SCheng C Yang }
2316773703a5SCheng C Yang
getCRConfig(ipmi::Context::ptr & ctx,const std::string & property,crConfigVariant & value,const std::string & service="xyz.openbmc_project.PSURedundancy",std::chrono::microseconds timeout=ipmi::IPMI_DBUS_TIMEOUT)2317e45333a8SKuiying Wang int getCRConfig(
2318dcff1506SVernon Mauery ipmi::Context::ptr& ctx, const std::string& property,
2319dcff1506SVernon Mauery crConfigVariant& value,
2320e45333a8SKuiying Wang const std::string& service = "xyz.openbmc_project.PSURedundancy",
2321dcff1506SVernon Mauery [[maybe_unused]] std::chrono::microseconds timeout =
2322dcff1506SVernon Mauery ipmi::IPMI_DBUS_TIMEOUT)
2323773703a5SCheng C Yang {
2324773703a5SCheng C Yang boost::system::error_code ec;
2325773703a5SCheng C Yang value = ctx->bus->yield_method_call<crConfigVariant>(
232619445ab7SYong Li ctx->yield, ec, service,
2327773703a5SCheng C Yang "/xyz/openbmc_project/control/power_supply_redundancy",
2328773703a5SCheng C Yang "org.freedesktop.DBus.Properties", "Get",
2329773703a5SCheng C Yang "xyz.openbmc_project.Control.PowerSupplyRedundancy", property);
2330773703a5SCheng C Yang if (ec)
2331773703a5SCheng C Yang {
2332773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2333773703a5SCheng C Yang "Failed to get dbus property to cold redundancy");
2334773703a5SCheng C Yang return -1;
2335773703a5SCheng C Yang }
2336773703a5SCheng C Yang return 0;
2337773703a5SCheng C Yang }
2338773703a5SCheng C Yang
getPSUCount(void)2339773703a5SCheng C Yang uint8_t getPSUCount(void)
2340773703a5SCheng C Yang {
2341773703a5SCheng C Yang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
2342773703a5SCheng C Yang ipmi::Value num;
2343773703a5SCheng C Yang try
2344773703a5SCheng C Yang {
2345773703a5SCheng C Yang num = ipmi::getDbusProperty(
2346773703a5SCheng C Yang *dbus, "xyz.openbmc_project.PSURedundancy",
2347773703a5SCheng C Yang "/xyz/openbmc_project/control/power_supply_redundancy",
2348773703a5SCheng C Yang "xyz.openbmc_project.Control.PowerSupplyRedundancy", "PSUNumber");
2349773703a5SCheng C Yang }
2350bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
2351773703a5SCheng C Yang {
2352773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2353773703a5SCheng C Yang "Failed to get PSUNumber property from dbus interface");
2354773703a5SCheng C Yang return 0;
2355773703a5SCheng C Yang }
2356773703a5SCheng C Yang uint8_t* pNum = std::get_if<uint8_t>(&num);
2357773703a5SCheng C Yang if (!pNum)
2358773703a5SCheng C Yang {
2359773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2360773703a5SCheng C Yang "Error to get PSU Number");
2361773703a5SCheng C Yang return 0;
2362773703a5SCheng C Yang }
2363773703a5SCheng C Yang return *pNum;
2364773703a5SCheng C Yang }
2365773703a5SCheng C Yang
validateCRAlgo(std::vector<uint8_t> & conf,uint8_t num)2366773703a5SCheng C Yang bool validateCRAlgo(std::vector<uint8_t>& conf, uint8_t num)
2367773703a5SCheng C Yang {
2368773703a5SCheng C Yang if (conf.size() < num)
2369773703a5SCheng C Yang {
2370773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2371773703a5SCheng C Yang "Invalid PSU Ranking");
2372773703a5SCheng C Yang return false;
2373773703a5SCheng C Yang }
2374773703a5SCheng C Yang std::set<uint8_t> confSet;
2375773703a5SCheng C Yang for (uint8_t i = 0; i < num; i++)
2376773703a5SCheng C Yang {
2377773703a5SCheng C Yang if (conf[i] > num)
2378773703a5SCheng C Yang {
2379773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2380773703a5SCheng C Yang "PSU Ranking is larger than current PSU number");
2381773703a5SCheng C Yang return false;
2382773703a5SCheng C Yang }
2383773703a5SCheng C Yang confSet.emplace(conf[i]);
2384773703a5SCheng C Yang }
2385773703a5SCheng C Yang
2386773703a5SCheng C Yang if (confSet.size() != num)
2387773703a5SCheng C Yang {
2388773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2389773703a5SCheng C Yang "duplicate PSU Ranking");
2390773703a5SCheng C Yang return false;
2391773703a5SCheng C Yang }
2392773703a5SCheng C Yang return true;
2393773703a5SCheng C Yang }
2394773703a5SCheng C Yang
2395773703a5SCheng C Yang enum class crParameter
2396773703a5SCheng C Yang {
2397773703a5SCheng C Yang crStatus = 0,
2398773703a5SCheng C Yang crFeature = 1,
2399773703a5SCheng C Yang rotationFeature = 2,
2400773703a5SCheng C Yang rotationAlgo = 3,
2401773703a5SCheng C Yang rotationPeriod = 4,
240219445ab7SYong Li numOfPSU = 5,
240319445ab7SYong Li rotationRankOrderEffective = 6
2404773703a5SCheng C Yang };
2405773703a5SCheng C Yang
2406773703a5SCheng C Yang constexpr ipmi::Cc ccParameterNotSupported = 0x80;
2407773703a5SCheng C Yang static const constexpr uint32_t oneDay = 0x15180;
2408773703a5SCheng C Yang static const constexpr uint32_t oneMonth = 0xf53700;
2409773703a5SCheng C Yang static const constexpr uint8_t userSpecific = 0x01;
2410773703a5SCheng C Yang static const constexpr uint8_t crSetCompleted = 0;
ipmiOEMSetCRConfig(ipmi::Context::ptr & ctx,uint8_t parameter,ipmi::message::Payload & payload)24111bcced08SPatrick Williams ipmi::RspType<uint8_t> ipmiOEMSetCRConfig(
24121bcced08SPatrick Williams ipmi::Context::ptr& ctx, uint8_t parameter, ipmi::message::Payload& payload)
2413773703a5SCheng C Yang {
2414773703a5SCheng C Yang switch (static_cast<crParameter>(parameter))
2415773703a5SCheng C Yang {
2416773703a5SCheng C Yang case crParameter::rotationFeature:
2417773703a5SCheng C Yang {
2418773703a5SCheng C Yang uint8_t param1;
2419773703a5SCheng C Yang if (payload.unpack(param1) || !payload.fullyUnpacked())
2420773703a5SCheng C Yang {
2421773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid();
2422773703a5SCheng C Yang }
2423773703a5SCheng C Yang // Rotation Enable can only be true or false
2424773703a5SCheng C Yang if (param1 > 1)
2425773703a5SCheng C Yang {
2426773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest();
2427773703a5SCheng C Yang }
2428773703a5SCheng C Yang if (setCRConfig(ctx, "RotationEnabled", static_cast<bool>(param1)))
2429773703a5SCheng C Yang {
2430773703a5SCheng C Yang return ipmi::responseResponseError();
2431773703a5SCheng C Yang }
2432773703a5SCheng C Yang break;
2433773703a5SCheng C Yang }
2434773703a5SCheng C Yang case crParameter::rotationAlgo:
2435773703a5SCheng C Yang {
2436773703a5SCheng C Yang // Rotation Algorithm can only be 0-BMC Specific or 1-User Specific
2437773703a5SCheng C Yang std::string algoName;
2438773703a5SCheng C Yang uint8_t param1;
2439773703a5SCheng C Yang if (payload.unpack(param1))
2440773703a5SCheng C Yang {
2441773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid();
2442773703a5SCheng C Yang }
2443773703a5SCheng C Yang switch (param1)
2444773703a5SCheng C Yang {
2445773703a5SCheng C Yang case 0:
2446773703a5SCheng C Yang algoName = "xyz.openbmc_project.Control."
2447773703a5SCheng C Yang "PowerSupplyRedundancy.Algo.bmcSpecific";
2448773703a5SCheng C Yang break;
2449773703a5SCheng C Yang case 1:
2450773703a5SCheng C Yang algoName = "xyz.openbmc_project.Control."
2451773703a5SCheng C Yang "PowerSupplyRedundancy.Algo.userSpecific";
2452773703a5SCheng C Yang break;
2453773703a5SCheng C Yang default:
2454773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest();
2455773703a5SCheng C Yang }
2456773703a5SCheng C Yang if (setCRConfig(ctx, "RotationAlgorithm", algoName))
2457773703a5SCheng C Yang {
2458773703a5SCheng C Yang return ipmi::responseResponseError();
2459773703a5SCheng C Yang }
2460773703a5SCheng C Yang
2461773703a5SCheng C Yang uint8_t numberOfPSU = getPSUCount();
2462773703a5SCheng C Yang if (!numberOfPSU)
2463773703a5SCheng C Yang {
2464773703a5SCheng C Yang return ipmi::responseResponseError();
2465773703a5SCheng C Yang }
2466773703a5SCheng C Yang std::vector<uint8_t> rankOrder;
2467773703a5SCheng C Yang
2468773703a5SCheng C Yang if (param1 == userSpecific)
2469773703a5SCheng C Yang {
2470773703a5SCheng C Yang if (payload.unpack(rankOrder) || !payload.fullyUnpacked())
2471773703a5SCheng C Yang {
2472773703a5SCheng C Yang ipmi::responseReqDataLenInvalid();
2473773703a5SCheng C Yang }
247483315132SYong Li if (rankOrder.size() != numberOfPSU)
2475773703a5SCheng C Yang {
2476773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid();
2477773703a5SCheng C Yang }
2478773703a5SCheng C Yang
2479773703a5SCheng C Yang if (!validateCRAlgo(rankOrder, numberOfPSU))
2480773703a5SCheng C Yang {
2481773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest();
2482773703a5SCheng C Yang }
2483773703a5SCheng C Yang }
2484773703a5SCheng C Yang else
2485773703a5SCheng C Yang {
2486773703a5SCheng C Yang if (rankOrder.size() > 0)
2487773703a5SCheng C Yang {
2488773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid();
2489773703a5SCheng C Yang }
2490773703a5SCheng C Yang for (uint8_t i = 1; i <= numberOfPSU; i++)
2491773703a5SCheng C Yang {
2492773703a5SCheng C Yang rankOrder.emplace_back(i);
2493773703a5SCheng C Yang }
2494773703a5SCheng C Yang }
2495773703a5SCheng C Yang if (setCRConfig(ctx, "RotationRankOrder", rankOrder))
2496773703a5SCheng C Yang {
2497773703a5SCheng C Yang return ipmi::responseResponseError();
2498773703a5SCheng C Yang }
2499773703a5SCheng C Yang break;
2500773703a5SCheng C Yang }
2501773703a5SCheng C Yang case crParameter::rotationPeriod:
2502773703a5SCheng C Yang {
2503773703a5SCheng C Yang // Minimum Rotation period is One day (86400 seconds) and Max
2504773703a5SCheng C Yang // Rotation Period is 6 month (0xf53700 seconds)
2505773703a5SCheng C Yang uint32_t period;
2506773703a5SCheng C Yang if (payload.unpack(period) || !payload.fullyUnpacked())
2507773703a5SCheng C Yang {
2508773703a5SCheng C Yang return ipmi::responseReqDataLenInvalid();
2509773703a5SCheng C Yang }
2510773703a5SCheng C Yang if ((period < oneDay) || (period > oneMonth))
2511773703a5SCheng C Yang {
2512773703a5SCheng C Yang return ipmi::responseInvalidFieldRequest();
2513773703a5SCheng C Yang }
2514773703a5SCheng C Yang if (setCRConfig(ctx, "PeriodOfRotation", period))
2515773703a5SCheng C Yang {
2516773703a5SCheng C Yang return ipmi::responseResponseError();
2517773703a5SCheng C Yang }
2518773703a5SCheng C Yang break;
2519773703a5SCheng C Yang }
2520773703a5SCheng C Yang default:
2521773703a5SCheng C Yang {
2522773703a5SCheng C Yang return ipmi::response(ccParameterNotSupported);
2523773703a5SCheng C Yang }
2524773703a5SCheng C Yang }
2525773703a5SCheng C Yang
2526773703a5SCheng C Yang return ipmi::responseSuccess(crSetCompleted);
2527773703a5SCheng C Yang }
2528773703a5SCheng C Yang
252983315132SYong Li ipmi::RspType<uint8_t, std::variant<uint8_t, uint32_t, std::vector<uint8_t>>>
ipmiOEMGetCRConfig(ipmi::Context::ptr & ctx,uint8_t parameter)2530dcff1506SVernon Mauery ipmiOEMGetCRConfig(ipmi::Context::ptr& ctx, uint8_t parameter)
2531773703a5SCheng C Yang {
2532773703a5SCheng C Yang crConfigVariant value;
2533773703a5SCheng C Yang switch (static_cast<crParameter>(parameter))
2534773703a5SCheng C Yang {
2535773703a5SCheng C Yang case crParameter::crStatus:
2536773703a5SCheng C Yang {
2537773703a5SCheng C Yang if (getCRConfig(ctx, "ColdRedundancyStatus", value))
2538773703a5SCheng C Yang {
2539773703a5SCheng C Yang return ipmi::responseResponseError();
2540773703a5SCheng C Yang }
2541773703a5SCheng C Yang std::string* pStatus = std::get_if<std::string>(&value);
2542773703a5SCheng C Yang if (!pStatus)
2543773703a5SCheng C Yang {
2544773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2545773703a5SCheng C Yang "Error to get ColdRedundancyStatus property");
2546773703a5SCheng C Yang return ipmi::responseResponseError();
2547773703a5SCheng C Yang }
2548773703a5SCheng C Yang namespace server = sdbusplus::xyz::openbmc_project::Control::server;
2549773703a5SCheng C Yang auto status =
2550773703a5SCheng C Yang server::PowerSupplyRedundancy::convertStatusFromString(
2551773703a5SCheng C Yang *pStatus);
2552773703a5SCheng C Yang switch (status)
2553773703a5SCheng C Yang {
2554773703a5SCheng C Yang case server::PowerSupplyRedundancy::Status::inProgress:
2555f41e334dSCheng C Yang return ipmi::responseSuccess(parameter,
2556e45333a8SKuiying Wang static_cast<uint8_t>(1));
2557773703a5SCheng C Yang
2558773703a5SCheng C Yang case server::PowerSupplyRedundancy::Status::completed:
2559f41e334dSCheng C Yang return ipmi::responseSuccess(parameter,
2560e45333a8SKuiying Wang static_cast<uint8_t>(0));
2561773703a5SCheng C Yang default:
2562773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2563773703a5SCheng C Yang "Error to get valid status");
2564773703a5SCheng C Yang return ipmi::responseResponseError();
2565773703a5SCheng C Yang }
2566773703a5SCheng C Yang }
2567773703a5SCheng C Yang case crParameter::crFeature:
2568773703a5SCheng C Yang {
2569e45333a8SKuiying Wang if (getCRConfig(ctx, "PowerSupplyRedundancyEnabled", value))
2570773703a5SCheng C Yang {
2571773703a5SCheng C Yang return ipmi::responseResponseError();
2572773703a5SCheng C Yang }
2573773703a5SCheng C Yang bool* pResponse = std::get_if<bool>(&value);
2574773703a5SCheng C Yang if (!pResponse)
2575773703a5SCheng C Yang {
2576773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2577e45333a8SKuiying Wang "Error to get PowerSupplyRedundancyEnabled property");
2578773703a5SCheng C Yang return ipmi::responseResponseError();
2579773703a5SCheng C Yang }
2580773703a5SCheng C Yang
2581f41e334dSCheng C Yang return ipmi::responseSuccess(parameter,
2582f41e334dSCheng C Yang static_cast<uint8_t>(*pResponse));
2583773703a5SCheng C Yang }
2584773703a5SCheng C Yang case crParameter::rotationFeature:
2585773703a5SCheng C Yang {
2586773703a5SCheng C Yang if (getCRConfig(ctx, "RotationEnabled", value))
2587773703a5SCheng C Yang {
2588773703a5SCheng C Yang return ipmi::responseResponseError();
2589773703a5SCheng C Yang }
2590773703a5SCheng C Yang bool* pResponse = std::get_if<bool>(&value);
2591773703a5SCheng C Yang if (!pResponse)
2592773703a5SCheng C Yang {
2593773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2594773703a5SCheng C Yang "Error to get RotationEnabled property");
2595773703a5SCheng C Yang return ipmi::responseResponseError();
2596773703a5SCheng C Yang }
2597f41e334dSCheng C Yang return ipmi::responseSuccess(parameter,
2598f41e334dSCheng C Yang static_cast<uint8_t>(*pResponse));
2599773703a5SCheng C Yang }
2600773703a5SCheng C Yang case crParameter::rotationAlgo:
2601773703a5SCheng C Yang {
2602773703a5SCheng C Yang if (getCRConfig(ctx, "RotationAlgorithm", value))
2603773703a5SCheng C Yang {
2604773703a5SCheng C Yang return ipmi::responseResponseError();
2605773703a5SCheng C Yang }
2606773703a5SCheng C Yang
2607773703a5SCheng C Yang std::string* pAlgo = std::get_if<std::string>(&value);
2608773703a5SCheng C Yang if (!pAlgo)
2609773703a5SCheng C Yang {
2610773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2611773703a5SCheng C Yang "Error to get RotationAlgorithm property");
2612773703a5SCheng C Yang return ipmi::responseResponseError();
2613773703a5SCheng C Yang }
261483315132SYong Li std::vector<uint8_t> response;
2615773703a5SCheng C Yang namespace server = sdbusplus::xyz::openbmc_project::Control::server;
2616773703a5SCheng C Yang auto algo =
2617773703a5SCheng C Yang server::PowerSupplyRedundancy::convertAlgoFromString(*pAlgo);
261883315132SYong Li
2619773703a5SCheng C Yang switch (algo)
2620773703a5SCheng C Yang {
2621773703a5SCheng C Yang case server::PowerSupplyRedundancy::Algo::bmcSpecific:
262283315132SYong Li response.push_back(0);
2623773703a5SCheng C Yang break;
2624773703a5SCheng C Yang case server::PowerSupplyRedundancy::Algo::userSpecific:
262583315132SYong Li response.push_back(1);
2626773703a5SCheng C Yang break;
2627773703a5SCheng C Yang default:
2628773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2629773703a5SCheng C Yang "Error to get valid algo");
2630773703a5SCheng C Yang return ipmi::responseResponseError();
2631773703a5SCheng C Yang }
2632773703a5SCheng C Yang
2633773703a5SCheng C Yang if (getCRConfig(ctx, "RotationRankOrder", value))
2634773703a5SCheng C Yang {
2635773703a5SCheng C Yang return ipmi::responseResponseError();
2636773703a5SCheng C Yang }
2637773703a5SCheng C Yang std::vector<uint8_t>* pResponse =
2638773703a5SCheng C Yang std::get_if<std::vector<uint8_t>>(&value);
2639773703a5SCheng C Yang if (!pResponse)
2640773703a5SCheng C Yang {
2641773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2642773703a5SCheng C Yang "Error to get RotationRankOrder property");
2643773703a5SCheng C Yang return ipmi::responseResponseError();
2644773703a5SCheng C Yang }
264583315132SYong Li
2646773703a5SCheng C Yang std::copy(pResponse->begin(), pResponse->end(),
264783315132SYong Li std::back_inserter(response));
264883315132SYong Li
2649f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, response);
2650773703a5SCheng C Yang }
2651773703a5SCheng C Yang case crParameter::rotationPeriod:
2652773703a5SCheng C Yang {
2653773703a5SCheng C Yang if (getCRConfig(ctx, "PeriodOfRotation", value))
2654773703a5SCheng C Yang {
2655773703a5SCheng C Yang return ipmi::responseResponseError();
2656773703a5SCheng C Yang }
2657773703a5SCheng C Yang uint32_t* pResponse = std::get_if<uint32_t>(&value);
2658773703a5SCheng C Yang if (!pResponse)
2659773703a5SCheng C Yang {
2660773703a5SCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
2661773703a5SCheng C Yang "Error to get RotationAlgorithm property");
2662773703a5SCheng C Yang return ipmi::responseResponseError();
2663773703a5SCheng C Yang }
2664f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, *pResponse);
2665773703a5SCheng C Yang }
2666773703a5SCheng C Yang case crParameter::numOfPSU:
2667773703a5SCheng C Yang {
2668773703a5SCheng C Yang uint8_t numberOfPSU = getPSUCount();
2669773703a5SCheng C Yang if (!numberOfPSU)
2670773703a5SCheng C Yang {
2671773703a5SCheng C Yang return ipmi::responseResponseError();
2672773703a5SCheng C Yang }
2673f41e334dSCheng C Yang return ipmi::responseSuccess(parameter, numberOfPSU);
2674773703a5SCheng C Yang }
267519445ab7SYong Li case crParameter::rotationRankOrderEffective:
267619445ab7SYong Li {
267719445ab7SYong Li if (getCRConfig(ctx, "RotationRankOrder", value,
267819445ab7SYong Li "xyz.openbmc_project.PSURedundancy"))
267919445ab7SYong Li {
268019445ab7SYong Li return ipmi::responseResponseError();
268119445ab7SYong Li }
268219445ab7SYong Li std::vector<uint8_t>* pResponse =
268319445ab7SYong Li std::get_if<std::vector<uint8_t>>(&value);
268419445ab7SYong Li if (!pResponse)
268519445ab7SYong Li {
268619445ab7SYong Li phosphor::logging::log<phosphor::logging::level::ERR>(
268719445ab7SYong Li "Error to get effective RotationRankOrder property");
268819445ab7SYong Li return ipmi::responseResponseError();
268919445ab7SYong Li }
269019445ab7SYong Li return ipmi::responseSuccess(parameter, *pResponse);
269119445ab7SYong Li }
2692773703a5SCheng C Yang default:
2693773703a5SCheng C Yang {
2694773703a5SCheng C Yang return ipmi::response(ccParameterNotSupported);
2695773703a5SCheng C Yang }
2696773703a5SCheng C Yang }
2697773703a5SCheng C Yang }
2698773703a5SCheng C Yang
ipmiOEMSetFaultIndication(uint8_t sourceId,uint8_t faultType,uint8_t faultState,uint8_t faultGroup,std::array<uint8_t,8> & ledStateData)26991bcced08SPatrick Williams ipmi::RspType<> ipmiOEMSetFaultIndication(
27001bcced08SPatrick Williams uint8_t sourceId, uint8_t faultType, uint8_t faultState, uint8_t faultGroup,
2701be560b09SZhu, Yunge std::array<uint8_t, 8>& ledStateData)
2702be560b09SZhu, Yunge {
2703be560b09SZhu, Yunge constexpr auto maxFaultType = static_cast<size_t>(RemoteFaultType::max);
2704be560b09SZhu, Yunge static const std::array<std::string, maxFaultType> faultNames = {
2705be560b09SZhu, Yunge "faultFan", "faultTemp", "faultPower",
2706be560b09SZhu, Yunge "faultDriveSlot", "faultSoftware", "faultMemory"};
2707be560b09SZhu, Yunge
2708be560b09SZhu, Yunge constexpr uint8_t maxFaultSource = 0x4;
2709be560b09SZhu, Yunge constexpr uint8_t skipLEDs = 0xFF;
2710be560b09SZhu, Yunge constexpr uint8_t pinSize = 64;
2711be560b09SZhu, Yunge constexpr uint8_t groupSize = 16;
2712ce4e73fdSZhikui Ren constexpr uint8_t groupNum = 5; // 4 for fault memory, 1 for faultFan
2713be560b09SZhu, Yunge
2714ce4e73fdSZhikui Ren // same pin names need to be defined in dts file
2715ce4e73fdSZhikui Ren static const std::array<std::array<std::string, groupSize>, groupNum>
2716ce4e73fdSZhikui Ren faultLedPinNames = {{
2717ce4e73fdSZhikui Ren "LED_CPU1_CH1_DIMM1_FAULT",
2718ce4e73fdSZhikui Ren "LED_CPU1_CH1_DIMM2_FAULT",
2719ce4e73fdSZhikui Ren "LED_CPU1_CH2_DIMM1_FAULT",
2720ce4e73fdSZhikui Ren "LED_CPU1_CH2_DIMM2_FAULT",
2721ce4e73fdSZhikui Ren "LED_CPU1_CH3_DIMM1_FAULT",
2722ce4e73fdSZhikui Ren "LED_CPU1_CH3_DIMM2_FAULT",
2723ce4e73fdSZhikui Ren "LED_CPU1_CH4_DIMM1_FAULT",
2724ce4e73fdSZhikui Ren "LED_CPU1_CH4_DIMM2_FAULT",
2725ce4e73fdSZhikui Ren "LED_CPU1_CH5_DIMM1_FAULT",
2726ce4e73fdSZhikui Ren "LED_CPU1_CH5_DIMM2_FAULT",
2727ce4e73fdSZhikui Ren "LED_CPU1_CH6_DIMM1_FAULT",
2728ce4e73fdSZhikui Ren "LED_CPU1_CH6_DIMM2_FAULT",
2729ce4e73fdSZhikui Ren "",
2730ce4e73fdSZhikui Ren "",
2731ce4e73fdSZhikui Ren "",
2732ce4e73fdSZhikui Ren "", // end of group1
2733ce4e73fdSZhikui Ren "LED_CPU2_CH1_DIMM1_FAULT",
2734ce4e73fdSZhikui Ren "LED_CPU2_CH1_DIMM2_FAULT",
2735ce4e73fdSZhikui Ren "LED_CPU2_CH2_DIMM1_FAULT",
2736ce4e73fdSZhikui Ren "LED_CPU2_CH2_DIMM2_FAULT",
2737ce4e73fdSZhikui Ren "LED_CPU2_CH3_DIMM1_FAULT",
2738ce4e73fdSZhikui Ren "LED_CPU2_CH3_DIMM2_FAULT",
2739ce4e73fdSZhikui Ren "LED_CPU2_CH4_DIMM1_FAULT",
2740ce4e73fdSZhikui Ren "LED_CPU2_CH4_DIMM2_FAULT",
2741ce4e73fdSZhikui Ren "LED_CPU2_CH5_DIMM1_FAULT",
2742ce4e73fdSZhikui Ren "LED_CPU2_CH5_DIMM2_FAULT",
2743ce4e73fdSZhikui Ren "LED_CPU2_CH6_DIMM1_FAULT",
2744ce4e73fdSZhikui Ren "LED_CPU2_CH6_DIMM2_FAULT",
2745ce4e73fdSZhikui Ren "",
2746ce4e73fdSZhikui Ren "",
2747ce4e73fdSZhikui Ren "",
2748ce4e73fdSZhikui Ren "", // endof group2
2749ce4e73fdSZhikui Ren "LED_CPU3_CH1_DIMM1_FAULT",
2750ce4e73fdSZhikui Ren "LED_CPU3_CH1_DIMM2_FAULT",
2751ce4e73fdSZhikui Ren "LED_CPU3_CH2_DIMM1_FAULT",
2752ce4e73fdSZhikui Ren "LED_CPU3_CH2_DIMM2_FAULT",
2753ce4e73fdSZhikui Ren "LED_CPU3_CH3_DIMM1_FAULT",
2754ce4e73fdSZhikui Ren "LED_CPU3_CH3_DIMM2_FAULT",
2755ce4e73fdSZhikui Ren "LED_CPU3_CH4_DIMM1_FAULT",
2756ce4e73fdSZhikui Ren "LED_CPU3_CH4_DIMM2_FAULT",
2757ce4e73fdSZhikui Ren "LED_CPU3_CH5_DIMM1_FAULT",
2758ce4e73fdSZhikui Ren "LED_CPU3_CH5_DIMM2_FAULT",
2759ce4e73fdSZhikui Ren "LED_CPU3_CH6_DIMM1_FAULT",
2760ce4e73fdSZhikui Ren "LED_CPU3_CH6_DIMM2_FAULT",
2761ce4e73fdSZhikui Ren "",
2762ce4e73fdSZhikui Ren "",
2763ce4e73fdSZhikui Ren "",
2764ce4e73fdSZhikui Ren "", // end of group3
2765ce4e73fdSZhikui Ren "LED_CPU4_CH1_DIMM1_FAULT",
2766ce4e73fdSZhikui Ren "LED_CPU4_CH1_DIMM2_FAULT",
2767ce4e73fdSZhikui Ren "LED_CPU4_CH2_DIMM1_FAULT",
2768ce4e73fdSZhikui Ren "LED_CPU4_CH2_DIMM2_FAULT",
2769ce4e73fdSZhikui Ren "LED_CPU4_CH3_DIMM1_FAULT",
2770ce4e73fdSZhikui Ren "LED_CPU4_CH3_DIMM2_FAULT",
2771ce4e73fdSZhikui Ren "LED_CPU4_CH4_DIMM1_FAULT",
2772ce4e73fdSZhikui Ren "LED_CPU4_CH4_DIMM2_FAULT",
2773ce4e73fdSZhikui Ren "LED_CPU4_CH5_DIMM1_FAULT",
2774ce4e73fdSZhikui Ren "LED_CPU4_CH5_DIMM2_FAULT",
2775ce4e73fdSZhikui Ren "LED_CPU4_CH6_DIMM1_FAULT",
2776ce4e73fdSZhikui Ren "LED_CPU4_CH6_DIMM2_FAULT",
2777ce4e73fdSZhikui Ren "",
2778ce4e73fdSZhikui Ren "",
2779ce4e73fdSZhikui Ren "",
2780ce4e73fdSZhikui Ren "", // end of group4
2781ce4e73fdSZhikui Ren "LED_FAN1_FAULT",
2782ce4e73fdSZhikui Ren "LED_FAN2_FAULT",
2783ce4e73fdSZhikui Ren "LED_FAN3_FAULT",
2784ce4e73fdSZhikui Ren "LED_FAN4_FAULT",
2785ce4e73fdSZhikui Ren "LED_FAN5_FAULT",
2786ce4e73fdSZhikui Ren "LED_FAN6_FAULT",
2787ce4e73fdSZhikui Ren "LED_FAN7_FAULT",
2788ce4e73fdSZhikui Ren "LED_FAN8_FAULT",
2789ce4e73fdSZhikui Ren "",
2790ce4e73fdSZhikui Ren "",
2791ce4e73fdSZhikui Ren "",
2792ce4e73fdSZhikui Ren "",
2793ce4e73fdSZhikui Ren "",
2794ce4e73fdSZhikui Ren "",
2795ce4e73fdSZhikui Ren "",
2796ce4e73fdSZhikui Ren "" // end of group5
2797ce4e73fdSZhikui Ren }};
2798be560b09SZhu, Yunge
2799ce4e73fdSZhikui Ren // Validate the source, fault type --
2800ce4e73fdSZhikui Ren // (Byte 1) sourceId: Unspecified, Hot-Swap Controller 0, Hot-Swap
2801ce4e73fdSZhikui Ren // Controller 1, BIOS (Byte 2) fault type: fan, temperature, power,
2802ce4e73fdSZhikui Ren // driveslot, software, memory (Byte 3) FaultState: OK, Degraded,
2803ce4e73fdSZhikui Ren // Non-Critical, Critical, Non-Recoverable, (Byte 4) is faultGroup,
2804ce4e73fdSZhikui Ren // definition differs based on fault type (Byte 2)
2805ce4e73fdSZhikui Ren // Type Fan=> Group: 0=FanGroupID, FF-not used
2806ce4e73fdSZhikui Ren // Byte 5-11 00h, not used
2807ce4e73fdSZhikui Ren // Byte12 FanLedState [7:0]-Fans 7:0
2808ce4e73fdSZhikui Ren // Type Memory=> Group: 0 = DIMM GroupID, FF-not used
2809ce4e73fdSZhikui Ren // Byte 5:12 - DIMM LED state (64bit field, LS Byte first)
2810ce4e73fdSZhikui Ren // [63:48] = CPU4 channels 7:0, 2 bits per channel
2811ce4e73fdSZhikui Ren // [47:32] = CPU3 channels 7:0, 2 bits per channel
2812ce4e73fdSZhikui Ren // [31:16] = CPU2 channels 7:0, 2 bits per channel
2813ce4e73fdSZhikui Ren // [15:0] = CPU1 channels 7:0, 2 bits per channel
2814ce4e73fdSZhikui Ren // Type Other=> Component Fault LED Group ID, not used set to 0xFF
2815ce4e73fdSZhikui Ren // Byte[5:12]: reserved 0x00h
2816be560b09SZhu, Yunge if ((sourceId >= maxFaultSource) ||
2817be560b09SZhu, Yunge (faultType >= static_cast<int8_t>(RemoteFaultType::max)) ||
2818be560b09SZhu, Yunge (faultState >= static_cast<int8_t>(RemoteFaultState::maxFaultState)) ||
2819be560b09SZhu, Yunge (faultGroup >= static_cast<int8_t>(DimmFaultType::maxFaultGroup)))
2820be560b09SZhu, Yunge {
2821be560b09SZhu, Yunge return ipmi::responseParmOutOfRange();
2822be560b09SZhu, Yunge }
2823be560b09SZhu, Yunge
2824ce4e73fdSZhikui Ren size_t pinGroupOffset = 0;
2825ce4e73fdSZhikui Ren size_t pinGroupMax = pinSize / groupSize;
2826ce4e73fdSZhikui Ren if (RemoteFaultType::fan == RemoteFaultType(faultType))
2827be560b09SZhu, Yunge {
2828ce4e73fdSZhikui Ren pinGroupOffset = 4;
2829ce4e73fdSZhikui Ren pinGroupMax = groupNum - pinSize / groupSize;
2830be560b09SZhu, Yunge }
2831be560b09SZhu, Yunge
2832be560b09SZhu, Yunge switch (RemoteFaultType(faultType))
2833be560b09SZhu, Yunge {
2834be560b09SZhu, Yunge case (RemoteFaultType::fan):
2835be560b09SZhu, Yunge case (RemoteFaultType::memory):
2836be560b09SZhu, Yunge {
2837be560b09SZhu, Yunge if (faultGroup == skipLEDs)
2838be560b09SZhu, Yunge {
2839be560b09SZhu, Yunge return ipmi::responseSuccess();
2840be560b09SZhu, Yunge }
2841be560b09SZhu, Yunge // calculate led state bit filed count, each byte has 8bits
2842be560b09SZhu, Yunge // the maximum bits will be 8 * 8 bits
2843be560b09SZhu, Yunge constexpr uint8_t size = sizeof(ledStateData) * 8;
2844ce4e73fdSZhikui Ren
2845ce4e73fdSZhikui Ren // assemble ledState
2846ce4e73fdSZhikui Ren uint64_t ledState = 0;
2847ce4e73fdSZhikui Ren bool hasError = false;
2848dcff1506SVernon Mauery for (size_t i = 0; i < sizeof(ledStateData); i++)
2849be560b09SZhu, Yunge {
2850be560b09SZhu, Yunge ledState = (uint64_t)(ledState << 8);
2851be560b09SZhu, Yunge ledState = (uint64_t)(ledState | (uint64_t)ledStateData[i]);
2852be560b09SZhu, Yunge }
2853be560b09SZhu, Yunge std::bitset<size> ledStateBits(ledState);
2854ce4e73fdSZhikui Ren
2855dcff1506SVernon Mauery for (size_t group = 0; group < pinGroupMax; group++)
2856ce4e73fdSZhikui Ren {
2857ce4e73fdSZhikui Ren for (int i = 0; i < groupSize; i++)
2858ce4e73fdSZhikui Ren { // skip non-existing pins
2859ce4e73fdSZhikui Ren if (0 == faultLedPinNames[group + pinGroupOffset][i].size())
2860be560b09SZhu, Yunge {
2861be560b09SZhu, Yunge continue;
2862be560b09SZhu, Yunge }
2863be560b09SZhu, Yunge
2864ce4e73fdSZhikui Ren gpiod::line line = gpiod::find_line(
2865ce4e73fdSZhikui Ren faultLedPinNames[group + pinGroupOffset][i]);
2866ce4e73fdSZhikui Ren if (!line)
2867be560b09SZhu, Yunge {
2868be560b09SZhu, Yunge phosphor::logging::log<phosphor::logging::level::ERR>(
2869be560b09SZhu, Yunge "Not Find Led Gpio Device!",
2870ce4e73fdSZhikui Ren phosphor::logging::entry(
2871ce4e73fdSZhikui Ren "DEVICE=%s",
2872ce4e73fdSZhikui Ren faultLedPinNames[group + pinGroupOffset][i]
2873ce4e73fdSZhikui Ren .c_str()));
2874ce4e73fdSZhikui Ren hasError = true;
2875ce4e73fdSZhikui Ren continue;
2876be560b09SZhu, Yunge }
2877ce4e73fdSZhikui Ren
2878ce4e73fdSZhikui Ren bool activeHigh =
2879ce4e73fdSZhikui Ren (line.active_state() == gpiod::line::ACTIVE_HIGH);
2880ce4e73fdSZhikui Ren try
2881ce4e73fdSZhikui Ren {
2882ce4e73fdSZhikui Ren line.request(
2883ce4e73fdSZhikui Ren {"faultLed", gpiod::line_request::DIRECTION_OUTPUT,
2884ce4e73fdSZhikui Ren activeHigh
2885ce4e73fdSZhikui Ren ? 0
2886ce4e73fdSZhikui Ren : gpiod::line_request::FLAG_ACTIVE_LOW});
2887ce4e73fdSZhikui Ren line.set_value(ledStateBits[i + group * groupSize]);
2888ce4e73fdSZhikui Ren }
2889bd51e6a9SPatrick Williams catch (const std::system_error&)
2890ce4e73fdSZhikui Ren {
2891ce4e73fdSZhikui Ren phosphor::logging::log<phosphor::logging::level::ERR>(
2892ce4e73fdSZhikui Ren "Error write Led Gpio Device!",
2893ce4e73fdSZhikui Ren phosphor::logging::entry(
2894ce4e73fdSZhikui Ren "DEVICE=%s",
2895ce4e73fdSZhikui Ren faultLedPinNames[group + pinGroupOffset][i]
2896ce4e73fdSZhikui Ren .c_str()));
2897ce4e73fdSZhikui Ren hasError = true;
2898ce4e73fdSZhikui Ren continue;
2899ce4e73fdSZhikui Ren }
2900ce4e73fdSZhikui Ren } // for int i
2901ce4e73fdSZhikui Ren }
2902ce4e73fdSZhikui Ren if (hasError)
2903ce4e73fdSZhikui Ren {
2904ce4e73fdSZhikui Ren return ipmi::responseResponseError();
2905be560b09SZhu, Yunge }
2906be560b09SZhu, Yunge break;
2907be560b09SZhu, Yunge }
2908be560b09SZhu, Yunge default:
2909be560b09SZhu, Yunge {
2910be560b09SZhu, Yunge // now only support two fault types
2911be560b09SZhu, Yunge return ipmi::responseParmOutOfRange();
2912be560b09SZhu, Yunge }
2913ce4e73fdSZhikui Ren } // switch
2914be560b09SZhu, Yunge return ipmi::responseSuccess();
2915be560b09SZhu, Yunge }
2916be560b09SZhu, Yunge
ipmiOEMReadBoardProductId()2917ea537d53SRichard Marian Thomaiyar ipmi::RspType<uint8_t> ipmiOEMReadBoardProductId()
2918ea537d53SRichard Marian Thomaiyar {
2919ea537d53SRichard Marian Thomaiyar uint8_t prodId = 0;
2920ea537d53SRichard Marian Thomaiyar try
2921ea537d53SRichard Marian Thomaiyar {
292215419dd5SVernon Mauery std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
2923ea537d53SRichard Marian Thomaiyar const DbusObjectInfo& object = getDbusObject(
292415419dd5SVernon Mauery *dbus, "xyz.openbmc_project.Inventory.Item.Board",
2925ea537d53SRichard Marian Thomaiyar "/xyz/openbmc_project/inventory/system/board/", "Baseboard");
2926ea537d53SRichard Marian Thomaiyar const Value& propValue = getDbusProperty(
292715419dd5SVernon Mauery *dbus, object.second, object.first,
29286c57e5caSSuryakanth Sekar "xyz.openbmc_project.Inventory.Item.Board.Motherboard",
29296c57e5caSSuryakanth Sekar "ProductId");
2930ea537d53SRichard Marian Thomaiyar prodId = static_cast<uint8_t>(std::get<uint64_t>(propValue));
2931ea537d53SRichard Marian Thomaiyar }
2932bd51e6a9SPatrick Williams catch (const std::exception& e)
2933ea537d53SRichard Marian Thomaiyar {
2934ea537d53SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
2935ea537d53SRichard Marian Thomaiyar "ipmiOEMReadBoardProductId: Product ID read failed!",
2936ea537d53SRichard Marian Thomaiyar phosphor::logging::entry("ERR=%s", e.what()));
2937ea537d53SRichard Marian Thomaiyar }
2938ea537d53SRichard Marian Thomaiyar return ipmi::responseSuccess(prodId);
2939ea537d53SRichard Marian Thomaiyar }
2940ea537d53SRichard Marian Thomaiyar
2941d801e463SRichard Marian Thomaiyar /** @brief implements the get security mode command
2942d801e463SRichard Marian Thomaiyar * @param ctx - ctx pointer
2943d801e463SRichard Marian Thomaiyar *
2944d801e463SRichard Marian Thomaiyar * @returns IPMI completion code with following data
2945d801e463SRichard Marian Thomaiyar * - restriction mode value - As specified in
2946d801e463SRichard Marian Thomaiyar * xyz.openbmc_project.Control.Security.RestrictionMode.interface.yaml
2947d801e463SRichard Marian Thomaiyar * - special mode value - As specified in
2948d801e463SRichard Marian Thomaiyar * xyz.openbmc_project.Control.Security.SpecialMode.interface.yaml
2949d801e463SRichard Marian Thomaiyar */
ipmiGetSecurityMode(ipmi::Context::ptr & ctx)2950dcff1506SVernon Mauery ipmi::RspType<uint8_t, uint8_t> ipmiGetSecurityMode(ipmi::Context::ptr& ctx)
2951d801e463SRichard Marian Thomaiyar {
2952d801e463SRichard Marian Thomaiyar namespace securityNameSpace =
2953d801e463SRichard Marian Thomaiyar sdbusplus::xyz::openbmc_project::Control::Security::server;
2954d801e463SRichard Marian Thomaiyar uint8_t restrictionModeValue = 0;
2955d801e463SRichard Marian Thomaiyar uint8_t specialModeValue = 0;
2956d801e463SRichard Marian Thomaiyar
2957d801e463SRichard Marian Thomaiyar boost::system::error_code ec;
29580748c69dSJason M. Bills auto varRestrMode = ctx->bus->yield_method_call<ipmi::DbusVariant>(
295928c7290cSJames Feist ctx->yield, ec, restricionModeService, restricionModeBasePath,
2960d801e463SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertyGetMethod, restricionModeIntf,
2961d801e463SRichard Marian Thomaiyar restricionModeProperty);
2962d801e463SRichard Marian Thomaiyar if (ec)
2963d801e463SRichard Marian Thomaiyar {
2964d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
2965d801e463SRichard Marian Thomaiyar "ipmiGetSecurityMode: failed to get RestrictionMode property",
2966d801e463SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
2967d801e463SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError();
2968d801e463SRichard Marian Thomaiyar }
2969d801e463SRichard Marian Thomaiyar restrictionModeValue = static_cast<uint8_t>(
2970d801e463SRichard Marian Thomaiyar securityNameSpace::RestrictionMode::convertModesFromString(
2971d801e463SRichard Marian Thomaiyar std::get<std::string>(varRestrMode)));
29720748c69dSJason M. Bills auto varSpecialMode = ctx->bus->yield_method_call<ipmi::DbusVariant>(
297328c7290cSJames Feist ctx->yield, ec, specialModeService, specialModeBasePath,
2974d801e463SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertyGetMethod, specialModeIntf,
2975d801e463SRichard Marian Thomaiyar specialModeProperty);
2976d801e463SRichard Marian Thomaiyar if (ec)
2977d801e463SRichard Marian Thomaiyar {
2978d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
2979d801e463SRichard Marian Thomaiyar "ipmiGetSecurityMode: failed to get SpecialMode property",
2980d801e463SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
2981d801e463SRichard Marian Thomaiyar // fall through, let us not worry about SpecialMode property, which is
2982d801e463SRichard Marian Thomaiyar // not required in user scenario
2983d801e463SRichard Marian Thomaiyar }
2984d801e463SRichard Marian Thomaiyar else
2985d801e463SRichard Marian Thomaiyar {
29868d4f8d73SRichard Marian Thomaiyar specialModeValue = static_cast<uint8_t>(
29878d4f8d73SRichard Marian Thomaiyar securityNameSpace::SpecialMode::convertModesFromString(
29888d4f8d73SRichard Marian Thomaiyar std::get<std::string>(varSpecialMode)));
2989d801e463SRichard Marian Thomaiyar }
2990d801e463SRichard Marian Thomaiyar return ipmi::responseSuccess(restrictionModeValue, specialModeValue);
2991d801e463SRichard Marian Thomaiyar }
2992d801e463SRichard Marian Thomaiyar
2993d801e463SRichard Marian Thomaiyar /** @brief implements the set security mode command
2994d801e463SRichard Marian Thomaiyar * Command allows to upgrade the restriction mode and won't allow
2995d801e463SRichard Marian Thomaiyar * to downgrade from system interface
2996d801e463SRichard Marian Thomaiyar * @param ctx - ctx pointer
2997d801e463SRichard Marian Thomaiyar * @param restrictionMode - restriction mode value to be set.
2998d801e463SRichard Marian Thomaiyar *
2999d801e463SRichard Marian Thomaiyar * @returns IPMI completion code
3000d801e463SRichard Marian Thomaiyar */
ipmiSetSecurityMode(ipmi::Context::ptr & ctx,uint8_t restrictionMode,std::optional<uint8_t> specialMode)3001dcff1506SVernon Mauery ipmi::RspType<> ipmiSetSecurityMode(ipmi::Context::ptr& ctx,
300210791062SRichard Marian Thomaiyar uint8_t restrictionMode,
300310791062SRichard Marian Thomaiyar std::optional<uint8_t> specialMode)
3004d801e463SRichard Marian Thomaiyar {
300510791062SRichard Marian Thomaiyar #ifndef BMC_VALIDATION_UNSECURE_FEATURE
300610791062SRichard Marian Thomaiyar if (specialMode)
300710791062SRichard Marian Thomaiyar {
300810791062SRichard Marian Thomaiyar return ipmi::responseReqDataLenInvalid();
300910791062SRichard Marian Thomaiyar }
301010791062SRichard Marian Thomaiyar #endif
3011d801e463SRichard Marian Thomaiyar namespace securityNameSpace =
3012d801e463SRichard Marian Thomaiyar sdbusplus::xyz::openbmc_project::Control::Security::server;
3013d801e463SRichard Marian Thomaiyar
3014d801e463SRichard Marian Thomaiyar ChannelInfo chInfo;
3015d801e463SRichard Marian Thomaiyar if (getChannelInfo(ctx->channel, chInfo) != ccSuccess)
3016d801e463SRichard Marian Thomaiyar {
3017d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
3018d801e463SRichard Marian Thomaiyar "ipmiSetSecurityMode: Failed to get Channel Info",
3019d801e463SRichard Marian Thomaiyar phosphor::logging::entry("CHANNEL=%d", ctx->channel));
3020d801e463SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError();
3021d801e463SRichard Marian Thomaiyar }
3022d801e463SRichard Marian Thomaiyar auto reqMode =
3023d801e463SRichard Marian Thomaiyar static_cast<securityNameSpace::RestrictionMode::Modes>(restrictionMode);
3024d801e463SRichard Marian Thomaiyar
3025d801e463SRichard Marian Thomaiyar if ((reqMode < securityNameSpace::RestrictionMode::Modes::Provisioning) ||
3026d801e463SRichard Marian Thomaiyar (reqMode >
3027d801e463SRichard Marian Thomaiyar securityNameSpace::RestrictionMode::Modes::ProvisionedHostDisabled))
3028d801e463SRichard Marian Thomaiyar {
3029d801e463SRichard Marian Thomaiyar return ipmi::responseInvalidFieldRequest();
3030d801e463SRichard Marian Thomaiyar }
3031d801e463SRichard Marian Thomaiyar
3032d801e463SRichard Marian Thomaiyar boost::system::error_code ec;
30330748c69dSJason M. Bills auto varRestrMode = ctx->bus->yield_method_call<ipmi::DbusVariant>(
303428c7290cSJames Feist ctx->yield, ec, restricionModeService, restricionModeBasePath,
3035d801e463SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertyGetMethod, restricionModeIntf,
3036d801e463SRichard Marian Thomaiyar restricionModeProperty);
3037d801e463SRichard Marian Thomaiyar if (ec)
3038d801e463SRichard Marian Thomaiyar {
3039d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
3040d801e463SRichard Marian Thomaiyar "ipmiSetSecurityMode: failed to get RestrictionMode property",
3041d801e463SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
3042d801e463SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError();
3043d801e463SRichard Marian Thomaiyar }
3044d801e463SRichard Marian Thomaiyar auto currentRestrictionMode =
3045d801e463SRichard Marian Thomaiyar securityNameSpace::RestrictionMode::convertModesFromString(
3046d801e463SRichard Marian Thomaiyar std::get<std::string>(varRestrMode));
3047d801e463SRichard Marian Thomaiyar
3048d801e463SRichard Marian Thomaiyar if (chInfo.mediumType !=
3049d801e463SRichard Marian Thomaiyar static_cast<uint8_t>(EChannelMediumType::lan8032) &&
3050d801e463SRichard Marian Thomaiyar currentRestrictionMode > reqMode)
3051d801e463SRichard Marian Thomaiyar {
3052d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
3053d801e463SRichard Marian Thomaiyar "ipmiSetSecurityMode - Downgrading security mode not supported "
3054d801e463SRichard Marian Thomaiyar "through system interface",
3055d801e463SRichard Marian Thomaiyar phosphor::logging::entry(
3056d801e463SRichard Marian Thomaiyar "CUR_MODE=%d", static_cast<uint8_t>(currentRestrictionMode)),
3057d801e463SRichard Marian Thomaiyar phosphor::logging::entry("REQ_MODE=%d", restrictionMode));
3058d801e463SRichard Marian Thomaiyar return ipmi::responseCommandNotAvailable();
3059d801e463SRichard Marian Thomaiyar }
3060d801e463SRichard Marian Thomaiyar
3061d801e463SRichard Marian Thomaiyar ec.clear();
3062d801e463SRichard Marian Thomaiyar ctx->bus->yield_method_call<>(
306328c7290cSJames Feist ctx->yield, ec, restricionModeService, restricionModeBasePath,
3064d801e463SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertySetMethod, restricionModeIntf,
3065d801e463SRichard Marian Thomaiyar restricionModeProperty,
30660748c69dSJason M. Bills static_cast<ipmi::DbusVariant>(
3067d801e463SRichard Marian Thomaiyar securityNameSpace::convertForMessage(reqMode)));
3068d801e463SRichard Marian Thomaiyar
3069d801e463SRichard Marian Thomaiyar if (ec)
3070d801e463SRichard Marian Thomaiyar {
3071d801e463SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
3072d801e463SRichard Marian Thomaiyar "ipmiSetSecurityMode: failed to set RestrictionMode property",
3073d801e463SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
3074d801e463SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError();
3075d801e463SRichard Marian Thomaiyar }
307610791062SRichard Marian Thomaiyar
307710791062SRichard Marian Thomaiyar #ifdef BMC_VALIDATION_UNSECURE_FEATURE
307810791062SRichard Marian Thomaiyar if (specialMode)
307910791062SRichard Marian Thomaiyar {
3080d77489f1SJayaprakash Mutyala constexpr uint8_t mfgMode = 0x01;
3081d77489f1SJayaprakash Mutyala // Manufacturing mode is reserved. So can't enable this mode.
3082d77489f1SJayaprakash Mutyala if (specialMode.value() == mfgMode)
3083d77489f1SJayaprakash Mutyala {
3084d77489f1SJayaprakash Mutyala phosphor::logging::log<phosphor::logging::level::INFO>(
3085d77489f1SJayaprakash Mutyala "ipmiSetSecurityMode: Can't enable Manufacturing mode");
3086d77489f1SJayaprakash Mutyala return ipmi::responseInvalidFieldRequest();
3087d77489f1SJayaprakash Mutyala }
3088d77489f1SJayaprakash Mutyala
308910791062SRichard Marian Thomaiyar ec.clear();
309010791062SRichard Marian Thomaiyar ctx->bus->yield_method_call<>(
309110791062SRichard Marian Thomaiyar ctx->yield, ec, specialModeService, specialModeBasePath,
309210791062SRichard Marian Thomaiyar dBusPropertyIntf, dBusPropertySetMethod, specialModeIntf,
309310791062SRichard Marian Thomaiyar specialModeProperty,
30940748c69dSJason M. Bills static_cast<ipmi::DbusVariant>(securityNameSpace::convertForMessage(
309510791062SRichard Marian Thomaiyar static_cast<securityNameSpace::SpecialMode::Modes>(
309610791062SRichard Marian Thomaiyar specialMode.value()))));
309710791062SRichard Marian Thomaiyar
309810791062SRichard Marian Thomaiyar if (ec)
309910791062SRichard Marian Thomaiyar {
310010791062SRichard Marian Thomaiyar phosphor::logging::log<phosphor::logging::level::ERR>(
310110791062SRichard Marian Thomaiyar "ipmiSetSecurityMode: failed to set SpecialMode property",
310210791062SRichard Marian Thomaiyar phosphor::logging::entry("ERROR=%s", ec.message().c_str()));
310310791062SRichard Marian Thomaiyar return ipmi::responseUnspecifiedError();
310410791062SRichard Marian Thomaiyar }
310510791062SRichard Marian Thomaiyar }
310610791062SRichard Marian Thomaiyar #endif
3107d801e463SRichard Marian Thomaiyar return ipmi::responseSuccess();
3108d801e463SRichard Marian Thomaiyar }
3109d801e463SRichard Marian Thomaiyar
31104ac799d7SVernon Mauery ipmi::RspType<uint8_t /* restore status */>
ipmiRestoreConfiguration(const std::array<uint8_t,3> & clr,uint8_t cmd)31114ac799d7SVernon Mauery ipmiRestoreConfiguration(const std::array<uint8_t, 3>& clr, uint8_t cmd)
31124ac799d7SVernon Mauery {
31134ac799d7SVernon Mauery static constexpr std::array<uint8_t, 3> expClr = {'C', 'L', 'R'};
31144ac799d7SVernon Mauery
31154ac799d7SVernon Mauery if (clr != expClr)
31164ac799d7SVernon Mauery {
31174ac799d7SVernon Mauery return ipmi::responseInvalidFieldRequest();
31184ac799d7SVernon Mauery }
31194ac799d7SVernon Mauery constexpr uint8_t cmdStatus = 0;
31204ac799d7SVernon Mauery constexpr uint8_t cmdDefaultRestore = 0xaa;
31214ac799d7SVernon Mauery constexpr uint8_t cmdFullRestore = 0xbb;
31224ac799d7SVernon Mauery constexpr uint8_t cmdFormat = 0xcc;
31234ac799d7SVernon Mauery
31244ac799d7SVernon Mauery constexpr const char* restoreOpFname = "/tmp/.rwfs/.restore_op";
31254ac799d7SVernon Mauery
31264ac799d7SVernon Mauery switch (cmd)
31274ac799d7SVernon Mauery {
31284ac799d7SVernon Mauery case cmdStatus:
31294ac799d7SVernon Mauery break;
31304ac799d7SVernon Mauery case cmdDefaultRestore:
31314ac799d7SVernon Mauery case cmdFullRestore:
31324ac799d7SVernon Mauery case cmdFormat:
31334ac799d7SVernon Mauery {
31344ac799d7SVernon Mauery // write file to rwfs root
31354ac799d7SVernon Mauery int value = (cmd - 1) & 0x03; // map aa, bb, cc => 1, 2, 3
31364ac799d7SVernon Mauery std::ofstream restoreFile(restoreOpFname);
31374ac799d7SVernon Mauery if (!restoreFile)
31384ac799d7SVernon Mauery {
31394ac799d7SVernon Mauery return ipmi::responseUnspecifiedError();
31404ac799d7SVernon Mauery }
31414ac799d7SVernon Mauery restoreFile << value << "\n";
3142ba1fbc89SArun P. Mohanan
3143ba1fbc89SArun P. Mohanan phosphor::logging::log<phosphor::logging::level::WARNING>(
3144ba1fbc89SArun P. Mohanan "Restore to default will be performed on next BMC boot",
3145ba1fbc89SArun P. Mohanan phosphor::logging::entry("ACTION=0x%0X", cmd));
3146ba1fbc89SArun P. Mohanan
31474ac799d7SVernon Mauery break;
31484ac799d7SVernon Mauery }
31494ac799d7SVernon Mauery default:
31504ac799d7SVernon Mauery return ipmi::responseInvalidFieldRequest();
31514ac799d7SVernon Mauery }
31524ac799d7SVernon Mauery
31534ac799d7SVernon Mauery constexpr uint8_t restorePending = 0;
31544ac799d7SVernon Mauery constexpr uint8_t restoreComplete = 1;
31554ac799d7SVernon Mauery
31564ac799d7SVernon Mauery uint8_t restoreStatus = std::filesystem::exists(restoreOpFname)
31574ac799d7SVernon Mauery ? restorePending
31584ac799d7SVernon Mauery : restoreComplete;
31594ac799d7SVernon Mauery return ipmi::responseSuccess(restoreStatus);
31604ac799d7SVernon Mauery }
31614ac799d7SVernon Mauery
ipmiOEMGetNmiSource(void)316239736d59SChen Yugang ipmi::RspType<uint8_t> ipmiOEMGetNmiSource(void)
316339736d59SChen Yugang {
316439736d59SChen Yugang uint8_t bmcSource;
316597cf96e6SChen Yugang namespace nmi = sdbusplus::xyz::openbmc_project::Chassis::Control::server;
316639736d59SChen Yugang
316739736d59SChen Yugang try
316839736d59SChen Yugang {
316939736d59SChen Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
31701bcced08SPatrick Williams std::string service =
31711bcced08SPatrick Williams getService(*dbus, oemNmiSourceIntf, oemNmiSourceObjPath);
31721bcced08SPatrick Williams Value variant =
31731bcced08SPatrick Williams getDbusProperty(*dbus, service, oemNmiSourceObjPath,
31741bcced08SPatrick Williams oemNmiSourceIntf, oemNmiBmcSourceObjPathProp);
317539736d59SChen Yugang
317639736d59SChen Yugang switch (nmi::NMISource::convertBMCSourceSignalFromString(
317739736d59SChen Yugang std::get<std::string>(variant)))
317839736d59SChen Yugang {
317939736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::None:
318039736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::none);
318139736d59SChen Yugang break;
318297cf96e6SChen Yugang case nmi::NMISource::BMCSourceSignal::FrontPanelButton:
318397cf96e6SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::frontPanelButton);
318439736d59SChen Yugang break;
318597cf96e6SChen Yugang case nmi::NMISource::BMCSourceSignal::Watchdog:
318697cf96e6SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::watchdog);
318739736d59SChen Yugang break;
318839736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::ChassisCmd:
318939736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::chassisCmd);
319039736d59SChen Yugang break;
319139736d59SChen Yugang case nmi::NMISource::BMCSourceSignal::MemoryError:
319239736d59SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::memoryError);
319339736d59SChen Yugang break;
319497cf96e6SChen Yugang case nmi::NMISource::BMCSourceSignal::PciBusError:
319597cf96e6SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::pciBusError);
319639736d59SChen Yugang break;
319797cf96e6SChen Yugang case nmi::NMISource::BMCSourceSignal::PCH:
319897cf96e6SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::pch);
319939736d59SChen Yugang break;
320097cf96e6SChen Yugang case nmi::NMISource::BMCSourceSignal::Chipset:
320197cf96e6SChen Yugang bmcSource = static_cast<uint8_t>(NmiSource::chipset);
320239736d59SChen Yugang break;
320339736d59SChen Yugang default:
320439736d59SChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>(
320539736d59SChen Yugang "NMI source: invalid property!",
320639736d59SChen Yugang phosphor::logging::entry(
320739736d59SChen Yugang "PROP=%s", std::get<std::string>(variant).c_str()));
320839736d59SChen Yugang return ipmi::responseResponseError();
320939736d59SChen Yugang }
321039736d59SChen Yugang }
3211f944d2e5SPatrick Williams catch (const sdbusplus::exception_t& e)
321239736d59SChen Yugang {
321339736d59SChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
321439736d59SChen Yugang return ipmi::responseResponseError();
321539736d59SChen Yugang }
321639736d59SChen Yugang
321739736d59SChen Yugang return ipmi::responseSuccess(bmcSource);
321839736d59SChen Yugang }
321939736d59SChen Yugang
ipmiOEMSetNmiSource(uint8_t sourceId)322039736d59SChen Yugang ipmi::RspType<> ipmiOEMSetNmiSource(uint8_t sourceId)
322139736d59SChen Yugang {
322297cf96e6SChen Yugang namespace nmi = sdbusplus::xyz::openbmc_project::Chassis::Control::server;
322339736d59SChen Yugang
322439736d59SChen Yugang nmi::NMISource::BMCSourceSignal bmcSourceSignal =
322539736d59SChen Yugang nmi::NMISource::BMCSourceSignal::None;
322639736d59SChen Yugang
322739736d59SChen Yugang switch (NmiSource(sourceId))
322839736d59SChen Yugang {
322939736d59SChen Yugang case NmiSource::none:
323039736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::None;
323139736d59SChen Yugang break;
323297cf96e6SChen Yugang case NmiSource::frontPanelButton:
323397cf96e6SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::FrontPanelButton;
323439736d59SChen Yugang break;
323597cf96e6SChen Yugang case NmiSource::watchdog:
323697cf96e6SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::Watchdog;
323739736d59SChen Yugang break;
323839736d59SChen Yugang case NmiSource::chassisCmd:
323939736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::ChassisCmd;
324039736d59SChen Yugang break;
324139736d59SChen Yugang case NmiSource::memoryError:
324239736d59SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::MemoryError;
324339736d59SChen Yugang break;
324497cf96e6SChen Yugang case NmiSource::pciBusError:
324597cf96e6SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::PciBusError;
324639736d59SChen Yugang break;
324797cf96e6SChen Yugang case NmiSource::pch:
324897cf96e6SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::PCH;
324939736d59SChen Yugang break;
325097cf96e6SChen Yugang case NmiSource::chipset:
325197cf96e6SChen Yugang bmcSourceSignal = nmi::NMISource::BMCSourceSignal::Chipset;
325239736d59SChen Yugang break;
325339736d59SChen Yugang default:
325439736d59SChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>(
325539736d59SChen Yugang "NMI source: invalid property!");
325639736d59SChen Yugang return ipmi::responseResponseError();
325739736d59SChen Yugang }
325839736d59SChen Yugang
325939736d59SChen Yugang try
326039736d59SChen Yugang {
326139736d59SChen Yugang // keep NMI signal source
326239736d59SChen Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
32631bcced08SPatrick Williams std::string service =
32641bcced08SPatrick Williams getService(*dbus, oemNmiSourceIntf, oemNmiSourceObjPath);
326597cf96e6SChen Yugang setDbusProperty(*dbus, service, oemNmiSourceObjPath, oemNmiSourceIntf,
326639736d59SChen Yugang oemNmiBmcSourceObjPathProp,
326797cf96e6SChen Yugang nmi::convertForMessage(bmcSourceSignal));
326899be6330SChen Yugang // set Enabled property to inform NMI source handling
326999be6330SChen Yugang // to trigger a NMI_OUT BSOD.
327099be6330SChen Yugang // if it's triggered by NMI source property changed,
327199be6330SChen Yugang // NMI_OUT BSOD could be missed if the same source occurs twice in a row
327299be6330SChen Yugang if (bmcSourceSignal != nmi::NMISource::BMCSourceSignal::None)
327399be6330SChen Yugang {
327499be6330SChen Yugang setDbusProperty(*dbus, service, oemNmiSourceObjPath,
327599be6330SChen Yugang oemNmiSourceIntf, oemNmiEnabledObjPathProp,
327699be6330SChen Yugang static_cast<bool>(true));
327799be6330SChen Yugang }
327839736d59SChen Yugang }
3279bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
328039736d59SChen Yugang {
328139736d59SChen Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
328239736d59SChen Yugang return ipmi::responseResponseError();
328339736d59SChen Yugang }
328439736d59SChen Yugang
328539736d59SChen Yugang return ipmi::responseSuccess();
328639736d59SChen Yugang }
328739736d59SChen Yugang
328863efafacSJames Feist namespace dimmOffset
328963efafacSJames Feist {
329063efafacSJames Feist constexpr const char* dimmPower = "DimmPower";
329163efafacSJames Feist constexpr const char* staticCltt = "StaticCltt";
329263efafacSJames Feist constexpr const char* offsetPath = "/xyz/openbmc_project/Inventory/Item/Dimm";
329363efafacSJames Feist constexpr const char* offsetInterface =
329463efafacSJames Feist "xyz.openbmc_project.Inventory.Item.Dimm.Offset";
329563efafacSJames Feist constexpr const char* property = "DimmOffset";
329663efafacSJames Feist
329763efafacSJames Feist }; // namespace dimmOffset
329863efafacSJames Feist
ipmiOEMSetDimmOffset(uint8_t type,const std::vector<std::tuple<uint8_t,uint8_t>> & data)32991bcced08SPatrick Williams ipmi::RspType<> ipmiOEMSetDimmOffset(
33001bcced08SPatrick Williams uint8_t type, const std::vector<std::tuple<uint8_t, uint8_t>>& data)
330163efafacSJames Feist {
330263efafacSJames Feist if (type != static_cast<uint8_t>(dimmOffsetTypes::dimmPower) &&
330363efafacSJames Feist type != static_cast<uint8_t>(dimmOffsetTypes::staticCltt))
330463efafacSJames Feist {
330563efafacSJames Feist return ipmi::responseInvalidFieldRequest();
330663efafacSJames Feist }
330763efafacSJames Feist
330863efafacSJames Feist if (data.empty())
330963efafacSJames Feist {
331063efafacSJames Feist return ipmi::responseInvalidFieldRequest();
331163efafacSJames Feist }
331263efafacSJames Feist nlohmann::json json;
331363efafacSJames Feist
331463efafacSJames Feist std::ifstream jsonStream(dimmOffsetFile);
331563efafacSJames Feist if (jsonStream.good())
331663efafacSJames Feist {
331763efafacSJames Feist json = nlohmann::json::parse(jsonStream, nullptr, false);
331863efafacSJames Feist if (json.is_discarded())
331963efafacSJames Feist {
332063efafacSJames Feist json = nlohmann::json();
332163efafacSJames Feist }
332263efafacSJames Feist jsonStream.close();
332363efafacSJames Feist }
332463efafacSJames Feist
332563efafacSJames Feist std::string typeName;
332663efafacSJames Feist if (type == static_cast<uint8_t>(dimmOffsetTypes::dimmPower))
332763efafacSJames Feist {
332863efafacSJames Feist typeName = dimmOffset::dimmPower;
332963efafacSJames Feist }
333063efafacSJames Feist else
333163efafacSJames Feist {
333263efafacSJames Feist typeName = dimmOffset::staticCltt;
333363efafacSJames Feist }
333463efafacSJames Feist
333563efafacSJames Feist nlohmann::json& field = json[typeName];
333663efafacSJames Feist
333763efafacSJames Feist for (const auto& [index, value] : data)
333863efafacSJames Feist {
333963efafacSJames Feist field[index] = value;
334063efafacSJames Feist }
334163efafacSJames Feist
334263efafacSJames Feist for (nlohmann::json& val : field)
334363efafacSJames Feist {
334463efafacSJames Feist if (val == nullptr)
334563efafacSJames Feist {
334663efafacSJames Feist val = static_cast<uint8_t>(0);
334763efafacSJames Feist }
334863efafacSJames Feist }
334963efafacSJames Feist
335063efafacSJames Feist std::ofstream output(dimmOffsetFile);
335163efafacSJames Feist if (!output.good())
335263efafacSJames Feist {
335363efafacSJames Feist std::cerr << "Error writing json file\n";
335463efafacSJames Feist return ipmi::responseResponseError();
335563efafacSJames Feist }
335663efafacSJames Feist
335763efafacSJames Feist output << json.dump(4);
335863efafacSJames Feist
335963efafacSJames Feist if (type == static_cast<uint8_t>(dimmOffsetTypes::staticCltt))
336063efafacSJames Feist {
336163efafacSJames Feist std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus();
336263efafacSJames Feist
33630748c69dSJason M. Bills ipmi::DbusVariant offsets = field.get<std::vector<uint8_t>>();
336463efafacSJames Feist auto call = bus->new_method_call(
336563efafacSJames Feist settingsBusName, dimmOffset::offsetPath, PROP_INTF, "Set");
336663efafacSJames Feist call.append(dimmOffset::offsetInterface, dimmOffset::property, offsets);
336763efafacSJames Feist try
336863efafacSJames Feist {
336963efafacSJames Feist bus->call(call);
337063efafacSJames Feist }
3371bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
337263efafacSJames Feist {
337363efafacSJames Feist phosphor::logging::log<phosphor::logging::level::ERR>(
337463efafacSJames Feist "ipmiOEMSetDimmOffset: can't set dimm offsets!",
337563efafacSJames Feist phosphor::logging::entry("ERR=%s", e.what()));
337663efafacSJames Feist return ipmi::responseResponseError();
337763efafacSJames Feist }
337863efafacSJames Feist }
337963efafacSJames Feist
338063efafacSJames Feist return ipmi::responseSuccess();
338163efafacSJames Feist }
338263efafacSJames Feist
ipmiOEMGetDimmOffset(uint8_t type,uint8_t index)338363efafacSJames Feist ipmi::RspType<uint8_t> ipmiOEMGetDimmOffset(uint8_t type, uint8_t index)
338463efafacSJames Feist {
338563efafacSJames Feist if (type != static_cast<uint8_t>(dimmOffsetTypes::dimmPower) &&
338663efafacSJames Feist type != static_cast<uint8_t>(dimmOffsetTypes::staticCltt))
338763efafacSJames Feist {
338863efafacSJames Feist return ipmi::responseInvalidFieldRequest();
338963efafacSJames Feist }
339063efafacSJames Feist
339163efafacSJames Feist std::ifstream jsonStream(dimmOffsetFile);
339263efafacSJames Feist
339363efafacSJames Feist auto json = nlohmann::json::parse(jsonStream, nullptr, false);
339463efafacSJames Feist if (json.is_discarded())
339563efafacSJames Feist {
339663efafacSJames Feist std::cerr << "File error in " << dimmOffsetFile << "\n";
339763efafacSJames Feist return ipmi::responseResponseError();
339863efafacSJames Feist }
339963efafacSJames Feist
340063efafacSJames Feist std::string typeName;
340163efafacSJames Feist if (type == static_cast<uint8_t>(dimmOffsetTypes::dimmPower))
340263efafacSJames Feist {
340363efafacSJames Feist typeName = dimmOffset::dimmPower;
340463efafacSJames Feist }
340563efafacSJames Feist else
340663efafacSJames Feist {
340763efafacSJames Feist typeName = dimmOffset::staticCltt;
340863efafacSJames Feist }
340963efafacSJames Feist
341063efafacSJames Feist auto it = json.find(typeName);
341163efafacSJames Feist if (it == json.end())
341263efafacSJames Feist {
341363efafacSJames Feist return ipmi::responseInvalidFieldRequest();
341463efafacSJames Feist }
341563efafacSJames Feist
341663efafacSJames Feist if (it->size() <= index)
341763efafacSJames Feist {
341863efafacSJames Feist return ipmi::responseInvalidFieldRequest();
341963efafacSJames Feist }
342063efafacSJames Feist
342163efafacSJames Feist uint8_t resp = it->at(index).get<uint8_t>();
342263efafacSJames Feist return ipmi::responseSuccess(resp);
342363efafacSJames Feist }
342463efafacSJames Feist
34254f7e76bbSChen,Yugang namespace boot_options
34264f7e76bbSChen,Yugang {
34274f7e76bbSChen,Yugang
34284f7e76bbSChen,Yugang using namespace sdbusplus::xyz::openbmc_project::Control::Boot::server;
34294f7e76bbSChen,Yugang using IpmiValue = uint8_t;
34304f7e76bbSChen,Yugang constexpr auto ipmiDefault = 0;
34314f7e76bbSChen,Yugang
34324f7e76bbSChen,Yugang std::map<IpmiValue, Source::Sources> sourceIpmiToDbus = {
34334f7e76bbSChen,Yugang {0x01, Source::Sources::Network},
34344f7e76bbSChen,Yugang {0x02, Source::Sources::Disk},
34354f7e76bbSChen,Yugang {0x05, Source::Sources::ExternalMedia},
34364f7e76bbSChen,Yugang {0x0f, Source::Sources::RemovableMedia},
34374f7e76bbSChen,Yugang {ipmiDefault, Source::Sources::Default}};
34384f7e76bbSChen,Yugang
34394f7e76bbSChen,Yugang std::map<IpmiValue, Mode::Modes> modeIpmiToDbus = {
3440ca12a7beSChen Yugang {0x06, Mode::Modes::Setup}, {ipmiDefault, Mode::Modes::Regular}};
34414f7e76bbSChen,Yugang
34424f7e76bbSChen,Yugang std::map<Source::Sources, IpmiValue> sourceDbusToIpmi = {
34434f7e76bbSChen,Yugang {Source::Sources::Network, 0x01},
34444f7e76bbSChen,Yugang {Source::Sources::Disk, 0x02},
34454f7e76bbSChen,Yugang {Source::Sources::ExternalMedia, 0x05},
34464f7e76bbSChen,Yugang {Source::Sources::RemovableMedia, 0x0f},
34474f7e76bbSChen,Yugang {Source::Sources::Default, ipmiDefault}};
34484f7e76bbSChen,Yugang
34494f7e76bbSChen,Yugang std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = {
3450ca12a7beSChen Yugang {Mode::Modes::Setup, 0x06}, {Mode::Modes::Regular, ipmiDefault}};
34514f7e76bbSChen,Yugang
34524f7e76bbSChen,Yugang static constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
34534f7e76bbSChen,Yugang static constexpr auto bootSourceIntf =
34544f7e76bbSChen,Yugang "xyz.openbmc_project.Control.Boot.Source";
34554f7e76bbSChen,Yugang static constexpr auto enabledIntf = "xyz.openbmc_project.Object.Enable";
34564f7e76bbSChen,Yugang static constexpr auto persistentObjPath =
34574f7e76bbSChen,Yugang "/xyz/openbmc_project/control/host0/boot";
34584f7e76bbSChen,Yugang static constexpr auto oneTimePath =
34594f7e76bbSChen,Yugang "/xyz/openbmc_project/control/host0/boot/one_time";
34604f7e76bbSChen,Yugang static constexpr auto bootSourceProp = "BootSource";
34614f7e76bbSChen,Yugang static constexpr auto bootModeProp = "BootMode";
34624f7e76bbSChen,Yugang static constexpr auto oneTimeBootEnableProp = "Enabled";
34634f7e76bbSChen,Yugang static constexpr auto httpBootMode =
34644f7e76bbSChen,Yugang "xyz.openbmc_project.Control.Boot.Source.Sources.Http";
34654f7e76bbSChen,Yugang
34664f7e76bbSChen,Yugang enum class BootOptionParameter : size_t
34674f7e76bbSChen,Yugang {
34684f7e76bbSChen,Yugang setInProgress = 0x0,
34694f7e76bbSChen,Yugang bootFlags = 0x5,
34704f7e76bbSChen,Yugang };
34714f7e76bbSChen,Yugang static constexpr uint8_t setComplete = 0x0;
34724f7e76bbSChen,Yugang static constexpr uint8_t setInProgress = 0x1;
34734f7e76bbSChen,Yugang static uint8_t transferStatus = setComplete;
34744f7e76bbSChen,Yugang static constexpr uint8_t setParmVersion = 0x01;
34754f7e76bbSChen,Yugang static constexpr uint8_t setParmBootFlagsPermanent = 0x40;
34764f7e76bbSChen,Yugang static constexpr uint8_t setParmBootFlagsValidOneTime = 0x80;
34774f7e76bbSChen,Yugang static constexpr uint8_t setParmBootFlagsValidPermanent = 0xC0;
34784f7e76bbSChen,Yugang static constexpr uint8_t httpBoot = 0xd;
34794f7e76bbSChen,Yugang static constexpr uint8_t bootSourceMask = 0x3c;
34804f7e76bbSChen,Yugang
34814f7e76bbSChen,Yugang } // namespace boot_options
34824f7e76bbSChen,Yugang
34834f7e76bbSChen,Yugang ipmi::RspType<uint8_t, // version
34844f7e76bbSChen,Yugang uint8_t, // param
34854f7e76bbSChen,Yugang uint8_t, // data0, dependent on parameter
34864f7e76bbSChen,Yugang std::optional<uint8_t> // data1, dependent on parameter
34874f7e76bbSChen,Yugang >
ipmiOemGetEfiBootOptions(uint8_t parameter,uint8_t set,uint8_t block)3488dcff1506SVernon Mauery ipmiOemGetEfiBootOptions(uint8_t parameter, [[maybe_unused]] uint8_t set,
3489dcff1506SVernon Mauery [[maybe_unused]] uint8_t block)
34904f7e76bbSChen,Yugang {
34914f7e76bbSChen,Yugang using namespace boot_options;
34924f7e76bbSChen,Yugang uint8_t bootOption = 0;
34934f7e76bbSChen,Yugang
34944f7e76bbSChen,Yugang if (parameter == static_cast<uint8_t>(BootOptionParameter::setInProgress))
34954f7e76bbSChen,Yugang {
34964f7e76bbSChen,Yugang return ipmi::responseSuccess(setParmVersion, parameter, transferStatus,
34974f7e76bbSChen,Yugang std::nullopt);
34984f7e76bbSChen,Yugang }
34994f7e76bbSChen,Yugang
35004f7e76bbSChen,Yugang if (parameter != static_cast<uint8_t>(BootOptionParameter::bootFlags))
35014f7e76bbSChen,Yugang {
35024f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>(
35034f7e76bbSChen,Yugang "Unsupported parameter");
35043694d07aSJayaprakash Mutyala return ipmi::response(ccParameterNotSupported);
35054f7e76bbSChen,Yugang }
35064f7e76bbSChen,Yugang
35074f7e76bbSChen,Yugang try
35084f7e76bbSChen,Yugang {
35094f7e76bbSChen,Yugang auto oneTimeEnabled = false;
35104f7e76bbSChen,Yugang // read one time Enabled property
35114f7e76bbSChen,Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
35124f7e76bbSChen,Yugang std::string service = getService(*dbus, enabledIntf, oneTimePath);
35134f7e76bbSChen,Yugang Value variant = getDbusProperty(*dbus, service, oneTimePath,
35144f7e76bbSChen,Yugang enabledIntf, oneTimeBootEnableProp);
35154f7e76bbSChen,Yugang oneTimeEnabled = std::get<bool>(variant);
35164f7e76bbSChen,Yugang
35174f7e76bbSChen,Yugang // get BootSource and BootMode properties
35184f7e76bbSChen,Yugang // according to oneTimeEnable
35194f7e76bbSChen,Yugang auto bootObjPath = oneTimePath;
35204f7e76bbSChen,Yugang if (oneTimeEnabled == false)
35214f7e76bbSChen,Yugang {
35224f7e76bbSChen,Yugang bootObjPath = persistentObjPath;
35234f7e76bbSChen,Yugang }
35244f7e76bbSChen,Yugang
35254f7e76bbSChen,Yugang service = getService(*dbus, bootModeIntf, bootObjPath);
35264f7e76bbSChen,Yugang variant = getDbusProperty(*dbus, service, bootObjPath, bootModeIntf,
35274f7e76bbSChen,Yugang bootModeProp);
35284f7e76bbSChen,Yugang
35294f7e76bbSChen,Yugang auto bootMode =
35304f7e76bbSChen,Yugang Mode::convertModesFromString(std::get<std::string>(variant));
35314f7e76bbSChen,Yugang
35324f7e76bbSChen,Yugang service = getService(*dbus, bootSourceIntf, bootObjPath);
35334f7e76bbSChen,Yugang variant = getDbusProperty(*dbus, service, bootObjPath, bootSourceIntf,
35344f7e76bbSChen,Yugang bootSourceProp);
35354f7e76bbSChen,Yugang
35364f7e76bbSChen,Yugang if (std::get<std::string>(variant) == httpBootMode)
35374f7e76bbSChen,Yugang {
35384f7e76bbSChen,Yugang bootOption = httpBoot;
35394f7e76bbSChen,Yugang }
35404f7e76bbSChen,Yugang else
35414f7e76bbSChen,Yugang {
35424f7e76bbSChen,Yugang auto bootSource = Source::convertSourcesFromString(
35434f7e76bbSChen,Yugang std::get<std::string>(variant));
35444f7e76bbSChen,Yugang bootOption = sourceDbusToIpmi.at(bootSource);
35454f7e76bbSChen,Yugang if (Source::Sources::Default == bootSource)
35464f7e76bbSChen,Yugang {
35474f7e76bbSChen,Yugang bootOption = modeDbusToIpmi.at(bootMode);
35484f7e76bbSChen,Yugang }
35494f7e76bbSChen,Yugang }
35504f7e76bbSChen,Yugang
35514f7e76bbSChen,Yugang uint8_t oneTime = oneTimeEnabled ? setParmBootFlagsValidOneTime
35524f7e76bbSChen,Yugang : setParmBootFlagsValidPermanent;
35534f7e76bbSChen,Yugang bootOption <<= 2; // shift for responseconstexpr
35544f7e76bbSChen,Yugang return ipmi::responseSuccess(setParmVersion, parameter, oneTime,
35554f7e76bbSChen,Yugang bootOption);
35564f7e76bbSChen,Yugang }
3557bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
35584f7e76bbSChen,Yugang {
35594f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
35604f7e76bbSChen,Yugang return ipmi::responseResponseError();
35614f7e76bbSChen,Yugang }
35624f7e76bbSChen,Yugang }
35634f7e76bbSChen,Yugang
ipmiOemSetEfiBootOptions(uint8_t bootFlag,uint8_t bootParam,std::optional<uint8_t> bootOption)35644f7e76bbSChen,Yugang ipmi::RspType<> ipmiOemSetEfiBootOptions(uint8_t bootFlag, uint8_t bootParam,
35654f7e76bbSChen,Yugang std::optional<uint8_t> bootOption)
35664f7e76bbSChen,Yugang {
35674f7e76bbSChen,Yugang using namespace boot_options;
35684f7e76bbSChen,Yugang auto oneTimeEnabled = false;
35694f7e76bbSChen,Yugang
3570bc01d213SMike Jones if (bootFlag == 0 && bootParam == 0)
3571bc01d213SMike Jones {
3572bc01d213SMike Jones phosphor::logging::log<phosphor::logging::level::ERR>(
3573bc01d213SMike Jones "Unsupported parameter");
3574bc01d213SMike Jones return ipmi::response(ccParameterNotSupported);
3575bc01d213SMike Jones }
35764f7e76bbSChen,Yugang if (bootFlag == static_cast<uint8_t>(BootOptionParameter::setInProgress))
35774f7e76bbSChen,Yugang {
35784f7e76bbSChen,Yugang if (bootOption)
35794f7e76bbSChen,Yugang {
35804f7e76bbSChen,Yugang return ipmi::responseReqDataLenInvalid();
35814f7e76bbSChen,Yugang }
35824f7e76bbSChen,Yugang
35834f7e76bbSChen,Yugang if (transferStatus == setInProgress)
35844f7e76bbSChen,Yugang {
35854f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>(
35864f7e76bbSChen,Yugang "boot option set in progress!");
35874f7e76bbSChen,Yugang return ipmi::responseResponseError();
35884f7e76bbSChen,Yugang }
35894f7e76bbSChen,Yugang
35904f7e76bbSChen,Yugang transferStatus = bootParam;
35914f7e76bbSChen,Yugang return ipmi::responseSuccess();
35924f7e76bbSChen,Yugang }
35934f7e76bbSChen,Yugang
35944f7e76bbSChen,Yugang if (bootFlag != (uint8_t)BootOptionParameter::bootFlags)
35954f7e76bbSChen,Yugang {
35964f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>(
35974f7e76bbSChen,Yugang "Unsupported parameter");
35983694d07aSJayaprakash Mutyala return ipmi::response(ccParameterNotSupported);
35994f7e76bbSChen,Yugang }
36004f7e76bbSChen,Yugang
36014f7e76bbSChen,Yugang if (!bootOption)
36024f7e76bbSChen,Yugang {
36034f7e76bbSChen,Yugang return ipmi::responseReqDataLenInvalid();
36044f7e76bbSChen,Yugang }
36054f7e76bbSChen,Yugang
36064f7e76bbSChen,Yugang if (((bootOption.value() & bootSourceMask) >> 2) !=
36074f7e76bbSChen,Yugang httpBoot) // not http boot, exit
36084f7e76bbSChen,Yugang {
36094f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>(
36104f7e76bbSChen,Yugang "wrong boot option parameter!");
36114f7e76bbSChen,Yugang return ipmi::responseParmOutOfRange();
36124f7e76bbSChen,Yugang }
36134f7e76bbSChen,Yugang
36144f7e76bbSChen,Yugang try
36154f7e76bbSChen,Yugang {
36164f7e76bbSChen,Yugang bool permanent = (bootParam & setParmBootFlagsPermanent) ==
36174f7e76bbSChen,Yugang setParmBootFlagsPermanent;
36184f7e76bbSChen,Yugang
36194f7e76bbSChen,Yugang // read one time Enabled property
36204f7e76bbSChen,Yugang std::shared_ptr<sdbusplus::asio::connection> dbus = getSdBus();
36214f7e76bbSChen,Yugang std::string service = getService(*dbus, enabledIntf, oneTimePath);
36224f7e76bbSChen,Yugang Value variant = getDbusProperty(*dbus, service, oneTimePath,
36234f7e76bbSChen,Yugang enabledIntf, oneTimeBootEnableProp);
36244f7e76bbSChen,Yugang oneTimeEnabled = std::get<bool>(variant);
36254f7e76bbSChen,Yugang
36264f7e76bbSChen,Yugang /*
36274f7e76bbSChen,Yugang * Check if the current boot setting is onetime or permanent, if the
36284f7e76bbSChen,Yugang * request in the command is otherwise, then set the "Enabled"
36294f7e76bbSChen,Yugang * property in one_time object path to 'True' to indicate onetime
36304f7e76bbSChen,Yugang * and 'False' to indicate permanent.
36314f7e76bbSChen,Yugang *
36324f7e76bbSChen,Yugang * Once the onetime/permanent setting is applied, then the bootMode
36334f7e76bbSChen,Yugang * and bootSource is updated for the corresponding object.
36344f7e76bbSChen,Yugang */
36354f7e76bbSChen,Yugang if (permanent == oneTimeEnabled)
36364f7e76bbSChen,Yugang {
36374f7e76bbSChen,Yugang setDbusProperty(*dbus, service, oneTimePath, enabledIntf,
36384f7e76bbSChen,Yugang oneTimeBootEnableProp, !permanent);
36394f7e76bbSChen,Yugang }
36404f7e76bbSChen,Yugang
36414f7e76bbSChen,Yugang // set BootSource and BootMode properties
36424f7e76bbSChen,Yugang // according to oneTimeEnable or persistent
36434f7e76bbSChen,Yugang auto bootObjPath = oneTimePath;
36444f7e76bbSChen,Yugang if (oneTimeEnabled == false)
36454f7e76bbSChen,Yugang {
36464f7e76bbSChen,Yugang bootObjPath = persistentObjPath;
36474f7e76bbSChen,Yugang }
36484f7e76bbSChen,Yugang std::string bootMode =
36494f7e76bbSChen,Yugang "xyz.openbmc_project.Control.Boot.Mode.Modes.Regular";
36504f7e76bbSChen,Yugang std::string bootSource = httpBootMode;
36514f7e76bbSChen,Yugang
36524f7e76bbSChen,Yugang service = getService(*dbus, bootModeIntf, bootObjPath);
36534f7e76bbSChen,Yugang setDbusProperty(*dbus, service, bootObjPath, bootModeIntf, bootModeProp,
36544f7e76bbSChen,Yugang bootMode);
36554f7e76bbSChen,Yugang
36564f7e76bbSChen,Yugang service = getService(*dbus, bootSourceIntf, bootObjPath);
36574f7e76bbSChen,Yugang setDbusProperty(*dbus, service, bootObjPath, bootSourceIntf,
36584f7e76bbSChen,Yugang bootSourceProp, bootSource);
36594f7e76bbSChen,Yugang }
3660bd51e6a9SPatrick Williams catch (const sdbusplus::exception_t& e)
36614f7e76bbSChen,Yugang {
36624f7e76bbSChen,Yugang phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
36634f7e76bbSChen,Yugang return ipmi::responseResponseError();
36644f7e76bbSChen,Yugang }
36654f7e76bbSChen,Yugang
36664f7e76bbSChen,Yugang return ipmi::responseSuccess();
36674f7e76bbSChen,Yugang }
36684f7e76bbSChen,Yugang
36690748c69dSJason M. Bills using BasicVariantType = ipmi::DbusVariant;
36704e6ee15bSCheng C Yang using PropertyMapType =
36714e6ee15bSCheng C Yang boost::container::flat_map<std::string, BasicVariantType>;
36724e6ee15bSCheng C Yang static constexpr const std::array<const char*, 1> psuPresenceTypes = {
36734e6ee15bSCheng C Yang "xyz.openbmc_project.Configuration.PSUPresence"};
getPSUAddress(ipmi::Context::ptr & ctx,uint8_t & bus,std::vector<uint64_t> & addrTable)3674dcff1506SVernon Mauery int getPSUAddress(ipmi::Context::ptr& ctx, uint8_t& bus,
36754e6ee15bSCheng C Yang std::vector<uint64_t>& addrTable)
36764e6ee15bSCheng C Yang {
36774e6ee15bSCheng C Yang boost::system::error_code ec;
36784e6ee15bSCheng C Yang GetSubTreeType subtree = ctx->bus->yield_method_call<GetSubTreeType>(
36794e6ee15bSCheng C Yang ctx->yield, ec, "xyz.openbmc_project.ObjectMapper",
36804e6ee15bSCheng C Yang "/xyz/openbmc_project/object_mapper",
36814e6ee15bSCheng C Yang "xyz.openbmc_project.ObjectMapper", "GetSubTree",
36824e6ee15bSCheng C Yang "/xyz/openbmc_project/inventory/system", 3, psuPresenceTypes);
36834e6ee15bSCheng C Yang if (ec)
36844e6ee15bSCheng C Yang {
36854e6ee15bSCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
36864e6ee15bSCheng C Yang "Failed to set dbus property to cold redundancy");
36874e6ee15bSCheng C Yang return -1;
36884e6ee15bSCheng C Yang }
36894e6ee15bSCheng C Yang for (const auto& object : subtree)
36904e6ee15bSCheng C Yang {
36914e6ee15bSCheng C Yang std::string pathName = object.first;
36924e6ee15bSCheng C Yang for (const auto& serviceIface : object.second)
36934e6ee15bSCheng C Yang {
36944e6ee15bSCheng C Yang std::string serviceName = serviceIface.first;
36954e6ee15bSCheng C Yang
36964e6ee15bSCheng C Yang ec.clear();
36974e6ee15bSCheng C Yang PropertyMapType propMap =
36984e6ee15bSCheng C Yang ctx->bus->yield_method_call<PropertyMapType>(
36994e6ee15bSCheng C Yang ctx->yield, ec, serviceName, pathName,
37004e6ee15bSCheng C Yang "org.freedesktop.DBus.Properties", "GetAll",
37014e6ee15bSCheng C Yang "xyz.openbmc_project.Configuration.PSUPresence");
37024e6ee15bSCheng C Yang if (ec)
37034e6ee15bSCheng C Yang {
37044e6ee15bSCheng C Yang phosphor::logging::log<phosphor::logging::level::ERR>(
37054e6ee15bSCheng C Yang "Failed to set dbus property to cold redundancy");
37064e6ee15bSCheng C Yang return -1;
37074e6ee15bSCheng C Yang }
37084e6ee15bSCheng C Yang auto psuBus = std::get_if<uint64_t>(&propMap["Bus"]);
37094e6ee15bSCheng C Yang auto psuAddress =
37104e6ee15bSCheng C Yang std::get_if<std::vector<uint64_t>>(&propMap["Address"]);
37114e6ee15bSCheng C Yang
37124e6ee15bSCheng C Yang if (psuBus == nullptr || psuAddress == nullptr)
37134e6ee15bSCheng C Yang {
37144e6ee15bSCheng C Yang std::cerr << "error finding necessary "
37154e6ee15bSCheng C Yang "entry in configuration\n";
37164e6ee15bSCheng C Yang return -1;
37174e6ee15bSCheng C Yang }
37184e6ee15bSCheng C Yang bus = static_cast<uint8_t>(*psuBus);
37194e6ee15bSCheng C Yang addrTable = *psuAddress;
37204e6ee15bSCheng C Yang return 0;
37214e6ee15bSCheng C Yang }
37224e6ee15bSCheng C Yang }
37234e6ee15bSCheng C Yang return -1;
37244e6ee15bSCheng C Yang }
37254e6ee15bSCheng C Yang
37264e6ee15bSCheng C Yang static const constexpr uint8_t addrOffset = 8;
37274e6ee15bSCheng C Yang static const constexpr uint8_t psuRevision = 0xd9;
37284e6ee15bSCheng C Yang static const constexpr uint8_t defaultPSUBus = 7;
37294e6ee15bSCheng C Yang // Second Minor, Primary Minor, Major
37304e6ee15bSCheng C Yang static const constexpr size_t verLen = 3;
3731dcff1506SVernon Mauery ipmi::RspType<std::vector<uint8_t>>
ipmiOEMGetPSUVersion(ipmi::Context::ptr & ctx)3732dcff1506SVernon Mauery ipmiOEMGetPSUVersion(ipmi::Context::ptr& ctx)
37334e6ee15bSCheng C Yang {
37344e6ee15bSCheng C Yang uint8_t bus = defaultPSUBus;
37354e6ee15bSCheng C Yang std::vector<uint64_t> addrTable;
37364e6ee15bSCheng C Yang std::vector<uint8_t> result;
37374e6ee15bSCheng C Yang if (getPSUAddress(ctx, bus, addrTable))
37384e6ee15bSCheng C Yang {
37394e6ee15bSCheng C Yang std::cerr << "Failed to get PSU bus and address\n";
37404e6ee15bSCheng C Yang return ipmi::responseResponseError();
37414e6ee15bSCheng C Yang }
37424e6ee15bSCheng C Yang
374380d4d5f9SMatt Simmering for (const auto& targetAddr : addrTable)
37444e6ee15bSCheng C Yang {
37454e6ee15bSCheng C Yang std::vector<uint8_t> writeData = {psuRevision};
37464e6ee15bSCheng C Yang std::vector<uint8_t> readBuf(verLen);
374780d4d5f9SMatt Simmering uint8_t addr = static_cast<uint8_t>(targetAddr) + addrOffset;
37484e6ee15bSCheng C Yang std::string i2cBus = "/dev/i2c-" + std::to_string(bus);
37494e6ee15bSCheng C Yang
37504e6ee15bSCheng C Yang auto retI2C = ipmi::i2cWriteRead(i2cBus, addr, writeData, readBuf);
37514e6ee15bSCheng C Yang if (retI2C != ipmi::ccSuccess)
37524e6ee15bSCheng C Yang {
37534e6ee15bSCheng C Yang for (size_t idx = 0; idx < verLen; idx++)
37544e6ee15bSCheng C Yang {
37554e6ee15bSCheng C Yang result.emplace_back(0x00);
37564e6ee15bSCheng C Yang }
37574e6ee15bSCheng C Yang }
37584e6ee15bSCheng C Yang else
37594e6ee15bSCheng C Yang {
37604e6ee15bSCheng C Yang for (const uint8_t& data : readBuf)
37614e6ee15bSCheng C Yang {
37624e6ee15bSCheng C Yang result.emplace_back(data);
37634e6ee15bSCheng C Yang }
37644e6ee15bSCheng C Yang }
37654e6ee15bSCheng C Yang }
37664e6ee15bSCheng C Yang
37674e6ee15bSCheng C Yang return ipmi::responseSuccess(result);
37684e6ee15bSCheng C Yang }
37694e6ee15bSCheng C Yang
37701bcced08SPatrick Williams std::optional<uint8_t>
getMultiNodeInfoPresence(ipmi::Context::ptr & ctx,const std::string & name)37711bcced08SPatrick Williams getMultiNodeInfoPresence(ipmi::Context::ptr& ctx, const std::string& name)
37722030d7c8Ssrikanta mondal {
37732030d7c8Ssrikanta mondal Value dbusValue = 0;
37742030d7c8Ssrikanta mondal std::string serviceName;
37752030d7c8Ssrikanta mondal
37762030d7c8Ssrikanta mondal boost::system::error_code ec =
37772030d7c8Ssrikanta mondal ipmi::getService(ctx, multiNodeIntf, multiNodeObjPath, serviceName);
37782030d7c8Ssrikanta mondal
37792030d7c8Ssrikanta mondal if (ec)
37802030d7c8Ssrikanta mondal {
37812030d7c8Ssrikanta mondal phosphor::logging::log<phosphor::logging::level::ERR>(
37822030d7c8Ssrikanta mondal "Failed to perform Multinode getService.");
37832030d7c8Ssrikanta mondal return std::nullopt;
37842030d7c8Ssrikanta mondal }
37852030d7c8Ssrikanta mondal
37862030d7c8Ssrikanta mondal ec = ipmi::getDbusProperty(ctx, serviceName, multiNodeObjPath,
37872030d7c8Ssrikanta mondal multiNodeIntf, name, dbusValue);
37882030d7c8Ssrikanta mondal if (ec)
37892030d7c8Ssrikanta mondal {
37902030d7c8Ssrikanta mondal phosphor::logging::log<phosphor::logging::level::ERR>(
37912030d7c8Ssrikanta mondal "Failed to perform Multinode get property");
37922030d7c8Ssrikanta mondal return std::nullopt;
37932030d7c8Ssrikanta mondal }
37942030d7c8Ssrikanta mondal
37952030d7c8Ssrikanta mondal auto multiNodeVal = std::get_if<uint8_t>(&dbusValue);
37962030d7c8Ssrikanta mondal if (!multiNodeVal)
37972030d7c8Ssrikanta mondal {
37982030d7c8Ssrikanta mondal phosphor::logging::log<phosphor::logging::level::ERR>(
37992030d7c8Ssrikanta mondal "getMultiNodeInfoPresence: error to get multinode");
38002030d7c8Ssrikanta mondal return std::nullopt;
38012030d7c8Ssrikanta mondal }
38022030d7c8Ssrikanta mondal return *multiNodeVal;
38032030d7c8Ssrikanta mondal }
38042030d7c8Ssrikanta mondal
38052030d7c8Ssrikanta mondal /** @brief implements OEM get reading command
38062030d7c8Ssrikanta mondal * @param domain ID
38072030d7c8Ssrikanta mondal * @param reading Type
38082030d7c8Ssrikanta mondal * - 00h = platform Power Consumption
38092030d7c8Ssrikanta mondal * - 01h = inlet Air Temp
38102030d7c8Ssrikanta mondal * - 02h = icc_TDC from PECI
38112030d7c8Ssrikanta mondal * @param reserved, write as 0000h
38122030d7c8Ssrikanta mondal *
38132030d7c8Ssrikanta mondal * @returns IPMI completion code plus response data
38142030d7c8Ssrikanta mondal * - response
38152030d7c8Ssrikanta mondal * - domain ID
38162030d7c8Ssrikanta mondal * - reading Type
38172030d7c8Ssrikanta mondal * - 00h = platform Power Consumption
38182030d7c8Ssrikanta mondal * - 01h = inlet Air Temp
38192030d7c8Ssrikanta mondal * - 02h = icc_TDC from PECI
38202030d7c8Ssrikanta mondal * - reading
38212030d7c8Ssrikanta mondal */
38222030d7c8Ssrikanta mondal ipmi::RspType<uint4_t, // domain ID
38232030d7c8Ssrikanta mondal uint4_t, // reading Type
38242030d7c8Ssrikanta mondal uint16_t // reading Value
38252030d7c8Ssrikanta mondal >
ipmiOEMGetReading(ipmi::Context::ptr & ctx,uint4_t domainId,uint4_t readingType,uint16_t reserved)3826dcff1506SVernon Mauery ipmiOEMGetReading(ipmi::Context::ptr& ctx, uint4_t domainId,
38272030d7c8Ssrikanta mondal uint4_t readingType, uint16_t reserved)
38282030d7c8Ssrikanta mondal {
3829dcff1506SVernon Mauery [[maybe_unused]] constexpr uint8_t platformPower = 0;
38302030d7c8Ssrikanta mondal constexpr uint8_t inletAirTemp = 1;
38312030d7c8Ssrikanta mondal constexpr uint8_t iccTdc = 2;
38322030d7c8Ssrikanta mondal
38332030d7c8Ssrikanta mondal if ((static_cast<uint8_t>(readingType) > iccTdc) || domainId || reserved)
38342030d7c8Ssrikanta mondal {
38352030d7c8Ssrikanta mondal return ipmi::responseInvalidFieldRequest();
38362030d7c8Ssrikanta mondal }
38372030d7c8Ssrikanta mondal
38382030d7c8Ssrikanta mondal // This command should run only from multi-node product.
38392030d7c8Ssrikanta mondal // For all other platforms this command will return invalid.
38402030d7c8Ssrikanta mondal
38411bcced08SPatrick Williams std::optional<uint8_t> nodeInfo =
38421bcced08SPatrick Williams getMultiNodeInfoPresence(ctx, "NodePresence");
38432030d7c8Ssrikanta mondal if (!nodeInfo || !*nodeInfo)
38442030d7c8Ssrikanta mondal {
38452030d7c8Ssrikanta mondal return ipmi::responseInvalidCommand();
38462030d7c8Ssrikanta mondal }
38472030d7c8Ssrikanta mondal
38482030d7c8Ssrikanta mondal uint16_t oemReadingValue = 0;
38492030d7c8Ssrikanta mondal if (static_cast<uint8_t>(readingType) == inletAirTemp)
38502030d7c8Ssrikanta mondal {
38512030d7c8Ssrikanta mondal double value = 0;
38522030d7c8Ssrikanta mondal boost::system::error_code ec = ipmi::getDbusProperty(
38532030d7c8Ssrikanta mondal ctx, "xyz.openbmc_project.HwmonTempSensor",
38542030d7c8Ssrikanta mondal "/xyz/openbmc_project/sensors/temperature/Inlet_BRD_Temp",
38552030d7c8Ssrikanta mondal "xyz.openbmc_project.Sensor.Value", "Value", value);
38562030d7c8Ssrikanta mondal if (ec)
38572030d7c8Ssrikanta mondal {
38582030d7c8Ssrikanta mondal phosphor::logging::log<phosphor::logging::level::ERR>(
38592030d7c8Ssrikanta mondal "Failed to get BMC Get OEM temperature",
38602030d7c8Ssrikanta mondal phosphor::logging::entry("EXCEPTION=%s", ec.message().c_str()));
38612030d7c8Ssrikanta mondal return ipmi::responseUnspecifiedError();
38622030d7c8Ssrikanta mondal }
38632030d7c8Ssrikanta mondal // Take the Inlet temperature
38642030d7c8Ssrikanta mondal oemReadingValue = static_cast<uint16_t>(value);
38652030d7c8Ssrikanta mondal }
38662030d7c8Ssrikanta mondal else
38672030d7c8Ssrikanta mondal {
38682030d7c8Ssrikanta mondal phosphor::logging::log<phosphor::logging::level::ERR>(
38692030d7c8Ssrikanta mondal "Currently Get OEM Reading support only for Inlet Air Temp");
38702030d7c8Ssrikanta mondal return ipmi::responseParmOutOfRange();
38712030d7c8Ssrikanta mondal }
38722030d7c8Ssrikanta mondal return ipmi::responseSuccess(domainId, readingType, oemReadingValue);
38732030d7c8Ssrikanta mondal }
38742030d7c8Ssrikanta mondal
387528972063SAppaRao Puli /** @brief implements the maximum size of
387628972063SAppaRao Puli * bridgeable messages used between KCS and
387728972063SAppaRao Puli * IPMB interfacesget security mode command.
387828972063SAppaRao Puli *
387928972063SAppaRao Puli * @returns IPMI completion code with following data
388028972063SAppaRao Puli * - KCS Buffer Size (In multiples of four bytes)
388128972063SAppaRao Puli * - IPMB Buffer Size (In multiples of four bytes)
388228972063SAppaRao Puli **/
ipmiOEMGetBufferSize()388328972063SAppaRao Puli ipmi::RspType<uint8_t, uint8_t> ipmiOEMGetBufferSize()
388428972063SAppaRao Puli {
388528972063SAppaRao Puli // for now this is hard coded; really this number is dependent on
388628972063SAppaRao Puli // the BMC kcs driver as well as the host kcs driver....
388728972063SAppaRao Puli // we can't know the latter.
388828972063SAppaRao Puli uint8_t kcsMaxBufferSize = 63 / 4;
388928972063SAppaRao Puli uint8_t ipmbMaxBufferSize = 128 / 4;
389028972063SAppaRao Puli
389128972063SAppaRao Puli return ipmi::responseSuccess(kcsMaxBufferSize, ipmbMaxBufferSize);
389228972063SAppaRao Puli }
389328972063SAppaRao Puli
3894a165038fSAnkita Vilas Gawade ipmi::RspType<std::vector<uint8_t>>
ipmiOEMReadPFRMailbox(ipmi::Context::ptr & ctx,const uint8_t readRegister,const uint8_t numOfBytes,uint8_t registerIdentifier)3895a165038fSAnkita Vilas Gawade ipmiOEMReadPFRMailbox(ipmi::Context::ptr& ctx, const uint8_t readRegister,
3896a165038fSAnkita Vilas Gawade const uint8_t numOfBytes, uint8_t registerIdentifier)
3897a165038fSAnkita Vilas Gawade {
3898a165038fSAnkita Vilas Gawade if (!ipmi::mailbox::i2cConfigLoaded)
3899a165038fSAnkita Vilas Gawade {
3900a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
390180d4d5f9SMatt Simmering "Calling PFR Load Configuration Function to Get I2C Bus and Target "
3902a165038fSAnkita Vilas Gawade "Address ");
3903a165038fSAnkita Vilas Gawade
3904a165038fSAnkita Vilas Gawade ipmi::mailbox::loadPfrConfig(ctx, ipmi::mailbox::i2cConfigLoaded);
3905a165038fSAnkita Vilas Gawade }
3906a165038fSAnkita Vilas Gawade
3907a165038fSAnkita Vilas Gawade if (!numOfBytes && !readRegister)
3908a165038fSAnkita Vilas Gawade {
3909a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
3910a165038fSAnkita Vilas Gawade "OEM IPMI command: Read & write count are 0 which is invalid ");
3911a165038fSAnkita Vilas Gawade return ipmi::responseInvalidFieldRequest();
3912a165038fSAnkita Vilas Gawade }
3913a165038fSAnkita Vilas Gawade
3914a165038fSAnkita Vilas Gawade switch (registerIdentifier)
3915a165038fSAnkita Vilas Gawade {
3916a165038fSAnkita Vilas Gawade case ipmi::mailbox::registerType::fifoReadRegister:
3917a165038fSAnkita Vilas Gawade {
3918a165038fSAnkita Vilas Gawade // Check if readRegister is an FIFO read register
3919a165038fSAnkita Vilas Gawade if (ipmi::mailbox::readFifoReg.find(readRegister) ==
3920a165038fSAnkita Vilas Gawade ipmi::mailbox::readFifoReg.end())
3921a165038fSAnkita Vilas Gawade {
3922a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
3923a165038fSAnkita Vilas Gawade "OEM IPMI command: Register is not a Read FIFO ");
3924a165038fSAnkita Vilas Gawade return ipmi::responseInvalidFieldRequest();
3925a165038fSAnkita Vilas Gawade }
3926a165038fSAnkita Vilas Gawade
3927a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
3928a165038fSAnkita Vilas Gawade "OEM IPMI command: Register is a Read FIFO ");
3929a165038fSAnkita Vilas Gawade
3930a165038fSAnkita Vilas Gawade ipmi::mailbox::writefifo(ipmi::mailbox::provisioningCommand,
3931a165038fSAnkita Vilas Gawade readRegister);
3932a165038fSAnkita Vilas Gawade ipmi::mailbox::writefifo(ipmi::mailbox::triggerCommand,
3933a165038fSAnkita Vilas Gawade ipmi::mailbox::flushRead);
3934a165038fSAnkita Vilas Gawade
3935a165038fSAnkita Vilas Gawade std::vector<uint8_t> writeData = {ipmi::mailbox::readFifo};
3936a165038fSAnkita Vilas Gawade std::vector<uint8_t> readBuf(1);
3937a165038fSAnkita Vilas Gawade std::vector<uint8_t> result;
3938a165038fSAnkita Vilas Gawade
3939a165038fSAnkita Vilas Gawade for (int i = 0; i < numOfBytes; i++)
3940a165038fSAnkita Vilas Gawade {
3941a165038fSAnkita Vilas Gawade ipmi::Cc ret = ipmi::i2cWriteRead(ipmi::mailbox::i2cBus,
394280d4d5f9SMatt Simmering ipmi::mailbox::targetAddr,
3943a165038fSAnkita Vilas Gawade writeData, readBuf);
3944a165038fSAnkita Vilas Gawade if (ret != ipmi::ccSuccess)
3945a165038fSAnkita Vilas Gawade {
3946a165038fSAnkita Vilas Gawade return ipmi::response(ret);
3947a165038fSAnkita Vilas Gawade }
3948a165038fSAnkita Vilas Gawade
3949a165038fSAnkita Vilas Gawade else
3950a165038fSAnkita Vilas Gawade {
3951a165038fSAnkita Vilas Gawade for (const uint8_t& data : readBuf)
3952a165038fSAnkita Vilas Gawade {
3953a165038fSAnkita Vilas Gawade result.emplace_back(data);
3954a165038fSAnkita Vilas Gawade }
3955a165038fSAnkita Vilas Gawade }
3956a165038fSAnkita Vilas Gawade }
3957a165038fSAnkita Vilas Gawade
3958a165038fSAnkita Vilas Gawade return ipmi::responseSuccess(result);
3959a165038fSAnkita Vilas Gawade }
3960a165038fSAnkita Vilas Gawade
3961a165038fSAnkita Vilas Gawade case ipmi::mailbox::registerType::singleByteRegister:
3962a165038fSAnkita Vilas Gawade {
3963a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
3964a165038fSAnkita Vilas Gawade "OEM IPMI command: Register is a Single Byte Register ");
3965a165038fSAnkita Vilas Gawade
3966a165038fSAnkita Vilas Gawade std::vector<uint8_t> writeData = {readRegister};
3967a165038fSAnkita Vilas Gawade std::vector<uint8_t> readBuf(numOfBytes);
3968a165038fSAnkita Vilas Gawade
3969a165038fSAnkita Vilas Gawade ipmi::Cc ret = ipmi::i2cWriteRead(ipmi::mailbox::i2cBus,
397080d4d5f9SMatt Simmering ipmi::mailbox::targetAddr,
3971a165038fSAnkita Vilas Gawade writeData, readBuf);
3972a165038fSAnkita Vilas Gawade if (ret != ipmi::ccSuccess)
3973a165038fSAnkita Vilas Gawade {
3974a165038fSAnkita Vilas Gawade return ipmi::response(ret);
3975a165038fSAnkita Vilas Gawade }
3976a165038fSAnkita Vilas Gawade return ipmi::responseSuccess(readBuf);
3977a165038fSAnkita Vilas Gawade }
3978a165038fSAnkita Vilas Gawade
3979a165038fSAnkita Vilas Gawade default:
3980a165038fSAnkita Vilas Gawade {
3981a165038fSAnkita Vilas Gawade phosphor::logging::log<phosphor::logging::level::ERR>(
3982a165038fSAnkita Vilas Gawade "OEM IPMI command: Register identifier is not valid.It should "
3983a165038fSAnkita Vilas Gawade "be 0 "
3984a165038fSAnkita Vilas Gawade "for Single Byte Register and 1 for FIFO Read Register");
3985a165038fSAnkita Vilas Gawade
3986a165038fSAnkita Vilas Gawade return ipmi::responseInvalidFieldRequest();
3987a165038fSAnkita Vilas Gawade }
3988a165038fSAnkita Vilas Gawade }
3989a165038fSAnkita Vilas Gawade }
3990a165038fSAnkita Vilas Gawade
registerOEMFunctions(void)399164796041SJason M. Bills static void registerOEMFunctions(void)
3992a835eaa0SJia, Chunhui {
3993a835eaa0SJia, Chunhui phosphor::logging::log<phosphor::logging::level::INFO>(
3994a835eaa0SJia, Chunhui "Registering OEM commands");
3995af65268eSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
3996af65268eSVernon Mauery intel::general::cmdGetBmcVersionString, Privilege::User,
3997af65268eSVernon Mauery ipmiOEMGetBmcVersionString);
3998af65268eSVernon Mauery
399998bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral,
400098bbf69aSVernon Mauery intel::general::cmdGetChassisIdentifier, NULL,
400198bbf69aSVernon Mauery ipmiOEMGetChassisIdentifier,
4002a835eaa0SJia, Chunhui PRIVILEGE_USER); // get chassis identifier
400398bbf69aSVernon Mauery
400498bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, intel::general::cmdSetSystemGUID,
400564796041SJason M. Bills NULL, ipmiOEMSetSystemGUID,
4006a835eaa0SJia, Chunhui PRIVILEGE_ADMIN); // set system guid
4007b02bf095SJason M. Bills
4008b02bf095SJason M. Bills // <Disable BMC System Reset Action>
400998bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
401098bbf69aSVernon Mauery intel::general::cmdDisableBMCSystemReset, Privilege::Admin,
401198bbf69aSVernon Mauery ipmiOEMDisableBMCSystemReset);
401298bbf69aSVernon Mauery
4013b02bf095SJason M. Bills // <Get BMC Reset Disables>
401498bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
401598bbf69aSVernon Mauery intel::general::cmdGetBMCResetDisables, Privilege::Admin,
401698bbf69aSVernon Mauery ipmiOEMGetBMCResetDisables);
4017b02bf095SJason M. Bills
401898bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral, intel::general::cmdSetBIOSID,
401964796041SJason M. Bills NULL, ipmiOEMSetBIOSID, PRIVILEGE_ADMIN);
4020cc49b54bSJia, Chunhui
40217a04f3a4SChen Yugang registerHandler(prioOemBase, intel::netFnGeneral,
40227a04f3a4SChen Yugang intel::general::cmdGetOEMDeviceInfo, Privilege::User,
40237a04f3a4SChen Yugang ipmiOEMGetDeviceInfo);
4024cc49b54bSJia, Chunhui
402598bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral,
402698bbf69aSVernon Mauery intel::general::cmdGetAICSlotFRUIDSlotPosRecords, NULL,
402798bbf69aSVernon Mauery ipmiOEMGetAICFRU, PRIVILEGE_USER);
4028d509eb91SSuryakanth Sekar
402998bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral,
403098bbf69aSVernon Mauery intel::general::cmdSendEmbeddedFWUpdStatus,
403198bbf69aSVernon Mauery Privilege::Operator, ipmiOEMSendEmbeddedFwUpdStatus);
4032d509eb91SSuryakanth Sekar
40332b664d5aSRajashekar Gade Reddy registerHandler(prioOpenBmcBase, intel::netFnApp, intel::app::cmdSlotIpmb,
40342b664d5aSRajashekar Gade Reddy Privilege::Admin, ipmiOEMSlotIpmb);
40352b664d5aSRajashekar Gade Reddy
403698bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral,
403798bbf69aSVernon Mauery intel::general::cmdSetPowerRestoreDelay, NULL,
403898bbf69aSVernon Mauery ipmiOEMSetPowerRestoreDelay, PRIVILEGE_OPERATOR);
403998bbf69aSVernon Mauery
404098bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral,
404198bbf69aSVernon Mauery intel::general::cmdGetPowerRestoreDelay, NULL,
404298bbf69aSVernon Mauery ipmiOEMGetPowerRestoreDelay, PRIVILEGE_USER);
404398bbf69aSVernon Mauery
404498bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral,
404598bbf69aSVernon Mauery intel::general::cmdSetOEMUser2Activation,
404698bbf69aSVernon Mauery Privilege::Callback, ipmiOEMSetUser2Activation);
404798bbf69aSVernon Mauery
404898bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral,
404998bbf69aSVernon Mauery intel::general::cmdSetSpecialUserPassword,
405098bbf69aSVernon Mauery Privilege::Callback, ipmiOEMSetSpecialUserPassword);
4051fc5e985bSRichard Marian Thomaiyar
405242bd9c8eSJason M. Bills // <Get Processor Error Config>
405398bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
405498bbf69aSVernon Mauery intel::general::cmdGetProcessorErrConfig, Privilege::User,
405598bbf69aSVernon Mauery ipmiOEMGetProcessorErrConfig);
405698bbf69aSVernon Mauery
405742bd9c8eSJason M. Bills // <Set Processor Error Config>
405898bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
405998bbf69aSVernon Mauery intel::general::cmdSetProcessorErrConfig, Privilege::Admin,
406098bbf69aSVernon Mauery ipmiOEMSetProcessorErrConfig);
406142bd9c8eSJason M. Bills
406298bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral,
406398bbf69aSVernon Mauery intel::general::cmdSetShutdownPolicy, NULL,
406498bbf69aSVernon Mauery ipmiOEMSetShutdownPolicy, PRIVILEGE_ADMIN);
406591244a6aSJames Feist
406698bbf69aSVernon Mauery ipmiPrintAndRegister(intel::netFnGeneral,
406798bbf69aSVernon Mauery intel::general::cmdGetShutdownPolicy, NULL,
406898bbf69aSVernon Mauery ipmiOEMGetShutdownPolicy, PRIVILEGE_ADMIN);
406998bbf69aSVernon Mauery
4070f945eee0Sanil kumar appana registerHandler(prioOemBase, intel::netFnGeneral,
4071f945eee0Sanil kumar appana intel::general::cmdSetFanConfig, Privilege::User,
4072f945eee0Sanil kumar appana ipmiOEMSetFanConfig);
407391244a6aSJames Feist
407498bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
407598bbf69aSVernon Mauery intel::general::cmdGetFanConfig, Privilege::User,
407698bbf69aSVernon Mauery ipmiOEMGetFanConfig);
407791244a6aSJames Feist
407898bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
407998bbf69aSVernon Mauery intel::general::cmdGetFanSpeedOffset, Privilege::User,
408098bbf69aSVernon Mauery ipmiOEMGetFanSpeedOffset);
40815f957cafSJames Feist
408298bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
408398bbf69aSVernon Mauery intel::general::cmdSetFanSpeedOffset, Privilege::User,
408498bbf69aSVernon Mauery ipmiOEMSetFanSpeedOffset);
4085acc8a4ebSJames Feist
408698bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
408798bbf69aSVernon Mauery intel::general::cmdSetFscParameter, Privilege::User,
408898bbf69aSVernon Mauery ipmiOEMSetFscParameter);
4089acc8a4ebSJames Feist
409098bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
409198bbf69aSVernon Mauery intel::general::cmdGetFscParameter, Privilege::User,
409298bbf69aSVernon Mauery ipmiOEMGetFscParameter);
40935f957cafSJames Feist
409498bbf69aSVernon Mauery registerHandler(prioOpenBmcBase, intel::netFnGeneral,
409598bbf69aSVernon Mauery intel::general::cmdReadBaseBoardProductId, Privilege::Admin,
409698bbf69aSVernon Mauery ipmiOEMReadBoardProductId);
4097ea537d53SRichard Marian Thomaiyar
409898bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
409998bbf69aSVernon Mauery intel::general::cmdGetNmiStatus, Privilege::User,
410098bbf69aSVernon Mauery ipmiOEMGetNmiSource);
410139736d59SChen Yugang
410298bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
410398bbf69aSVernon Mauery intel::general::cmdSetNmiStatus, Privilege::Operator,
410498bbf69aSVernon Mauery ipmiOEMSetNmiSource);
410539736d59SChen Yugang
410698bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
410798bbf69aSVernon Mauery intel::general::cmdGetEfiBootOptions, Privilege::User,
410898bbf69aSVernon Mauery ipmiOemGetEfiBootOptions);
41094f7e76bbSChen,Yugang
411098bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
411198bbf69aSVernon Mauery intel::general::cmdSetEfiBootOptions, Privilege::Operator,
411298bbf69aSVernon Mauery ipmiOemSetEfiBootOptions);
41134f7e76bbSChen,Yugang
411498bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
411598bbf69aSVernon Mauery intel::general::cmdGetSecurityMode, Privilege::User,
411698bbf69aSVernon Mauery ipmiGetSecurityMode);
4117d801e463SRichard Marian Thomaiyar
411898bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
411998bbf69aSVernon Mauery intel::general::cmdSetSecurityMode, Privilege::Admin,
412098bbf69aSVernon Mauery ipmiSetSecurityMode);
4121d801e463SRichard Marian Thomaiyar
4122abd11ca3SNITIN SHARMA registerHandler(prioOemBase, intel::netFnGeneral,
4123abd11ca3SNITIN SHARMA intel::general::cmdGetLEDStatus, Privilege::Admin,
4124abd11ca3SNITIN SHARMA ipmiOEMGetLEDStatus);
41254ac799d7SVernon Mauery
412698bbf69aSVernon Mauery ipmiPrintAndRegister(ipmi::intel::netFnPlatform,
412798bbf69aSVernon Mauery ipmi::intel::platform::cmdCfgHostSerialPortSpeed, NULL,
412898bbf69aSVernon Mauery ipmiOEMCfgHostSerialPortSpeed, PRIVILEGE_ADMIN);
4129773703a5SCheng C Yang
413098bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
413198bbf69aSVernon Mauery intel::general::cmdSetFaultIndication, Privilege::Operator,
413298bbf69aSVernon Mauery ipmiOEMSetFaultIndication);
413398bbf69aSVernon Mauery
413498bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
413598bbf69aSVernon Mauery intel::general::cmdSetColdRedundancyConfig, Privilege::User,
413698bbf69aSVernon Mauery ipmiOEMSetCRConfig);
413798bbf69aSVernon Mauery
413898bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
413998bbf69aSVernon Mauery intel::general::cmdGetColdRedundancyConfig, Privilege::User,
414098bbf69aSVernon Mauery ipmiOEMGetCRConfig);
414198bbf69aSVernon Mauery
414298bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
414398bbf69aSVernon Mauery intel::general::cmdRestoreConfiguration, Privilege::Admin,
41444ac799d7SVernon Mauery ipmiRestoreConfiguration);
414563efafacSJames Feist
414698bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
414798bbf69aSVernon Mauery intel::general::cmdSetDimmOffset, Privilege::Operator,
414898bbf69aSVernon Mauery ipmiOEMSetDimmOffset);
414963efafacSJames Feist
415098bbf69aSVernon Mauery registerHandler(prioOemBase, intel::netFnGeneral,
415198bbf69aSVernon Mauery intel::general::cmdGetDimmOffset, Privilege::Operator,
415298bbf69aSVernon Mauery ipmiOEMGetDimmOffset);
4153ca12a7beSChen Yugang
41544e6ee15bSCheng C Yang registerHandler(prioOemBase, intel::netFnGeneral,
41554e6ee15bSCheng C Yang intel::general::cmdGetPSUVersion, Privilege::User,
41564e6ee15bSCheng C Yang ipmiOEMGetPSUVersion);
415728972063SAppaRao Puli
415828972063SAppaRao Puli registerHandler(prioOemBase, intel::netFnGeneral,
415928972063SAppaRao Puli intel::general::cmdGetBufferSize, Privilege::User,
416028972063SAppaRao Puli ipmiOEMGetBufferSize);
41612030d7c8Ssrikanta mondal
41622030d7c8Ssrikanta mondal registerHandler(prioOemBase, intel::netFnGeneral,
41632030d7c8Ssrikanta mondal intel::general::cmdOEMGetReading, Privilege::User,
41642030d7c8Ssrikanta mondal ipmiOEMGetReading);
4165a165038fSAnkita Vilas Gawade
4166a165038fSAnkita Vilas Gawade registerHandler(prioOemBase, intel::netFnApp, intel::app::cmdPFRMailboxRead,
4167a165038fSAnkita Vilas Gawade Privilege::Admin, ipmiOEMReadPFRMailbox);
4168a835eaa0SJia, Chunhui }
4169a835eaa0SJia, Chunhui
4170a835eaa0SJia, Chunhui } // namespace ipmi
4171