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