Add Intel-specific IPMI OEM commands

Includes various OEM commands to get and set info on Intel
platforms (e.g. processor error configuration, power restore
delay, PCIe add-in card info, etc.).

Change-Id: I65f1e610a57f127088cc09bf993c82e7247be193
Signed-off-by: Jason M. Bills <jason.m.bills@linux.intel.com>
diff --git a/include/oemcommands.hpp b/include/oemcommands.hpp
index ed4b57a..e988d03 100644
--- a/include/oemcommands.hpp
+++ b/include/oemcommands.hpp
@@ -16,16 +16,20 @@
 
 #pragma once
 
-enum IPMINetfnIntelOEMGeneralCmd
+enum class IPMINetfnIntelOEMGeneralCmd
 {
     cmdSetBIOSID = 0x26,
     cmdGetOEMDeviceInfo = 0x27,
-    cmdGetAICSlotFRUIDRecords = 0x31,
+    cmdGetAICSlotFRUIDSlotPosRecords = 0x31,
     cmdSetSystemGUID = 0x41,
+    cmdSetPowerRestoreDelay = 0x54,
+    cmdGetPowerRestoreDelay = 0x55,
     cmdGetChassisIdentifier = 0x92,
+    cmdGetProcessorErrConfig = 0x9A,
+    cmdSetProcessorErrConfig = 0x9B,
 };
 
-enum IPMIIntelOEMReturnCodes
+enum class IPMIIntelOEMReturnCodes
 {
     ipmiCCPayloadActive = 0x80,
     ipmiCCInvalidPCIESlotID = 0x80,
@@ -51,7 +55,7 @@
 
 };
 
-enum IPMIReturnCodeExt
+enum class IPMIReturnCodeExt
 {
     ipmiCCInvalidLUN = 0xC2,
     ipmiCCTimeout = 0xC3,
@@ -64,17 +68,28 @@
     ipmiCCParamterNotSupportInPresentState = 0xD5,
 };
 
-constexpr unsigned char netfunIntelAppOEM = 0x3E;
-static constexpr ipmi_netfn_t netfunIntcOEMGeneral =
+constexpr const uint8_t netfunIntelAppOEM = 0x3E;
+static constexpr ipmi_netfn_t netfnIntcOEMGeneral =
     NETFUN_NONE; // Netfun_none. In our platform, we use it as "intel oem
                  // general". The code is 0x30
-static constexpr unsigned char maxBiosIdLength = 0xFF;
-static constexpr char* biosObjPath = (char*)"/xyz/openbmc_project/bios";
-static constexpr char* biosIntf =
-    (char*)"xyz.openbmc_project.Inventory.Item.Bios";
-static constexpr char* biosProp = (char*)"BiosId";
+static constexpr const uint8_t maxBIOSIDLength = 0xFF;
+static constexpr const uint8_t maxCPUNum = 4;
+static constexpr const char* biosObjPath = "/xyz/openbmc_project/bios";
+static constexpr const char* biosIntf =
+    "xyz.openbmc_project.Inventory.Item.Bios";
+static constexpr const char* biosProp = "BiosId";
 
-enum IPMINetfnIntelOEMAppCmd
+static constexpr const char* powerRestoreDelayObjPath =
+    "/xyz/openbmc_project/control/power_restore_delay";
+static constexpr const char* powerRestoreDelayIntf =
+    "xyz.openbmc_project.Control.Power.RestoreDelay";
+static constexpr const char* powerRestoreDelayProp = "PowerRestoreDelay";
+static constexpr const char* processorErrConfigObjPath =
+    "/xyz/openbmc_project/control/processor_error_config";
+static constexpr const char* processorErrConfigIntf =
+    "xyz.openbmc_project.Control.Processor.ErrConfig";
+
+enum class IPMINetfnIntelOEMAppCmd
 {
     mdrStatus = 0x20,
     mdrComplete = 0x21,
@@ -96,32 +111,15 @@
     mdr2SendDataBlock = 0x3d,
 };
 
-typedef enum
+enum class OEMDevEntityType
 {
     biosId,
     devVer,
     sdrVer,
-} OEMDevEntityType;
+};
 
-typedef union
-{
-    typedef struct
-    {
-        uint8_t bBrdSlotNum : 3;  // Bits 2:0
-        uint8_t riserSlotNum : 3; // Bits 5:3
-        uint8_t protocol : 1;     // Bit 6, FRU type
-        uint8_t reserved : 1;     // Bit 7
-    } bits;
-    uint8_t byte;
-} __attribute__((packed)) AICFruRec;
-
-typedef struct
-{
-    AICFruRec u8SlotPosition;
-    uint8_t u8FruID;
-} __attribute__((packed)) FRUSlotPosRecord;
-
-typedef struct
+#pragma pack(push, 1)
+struct GUIDData
 {
     uint8_t node1;
     uint8_t node2;
@@ -139,23 +137,76 @@
     uint8_t timeLow2;
     uint8_t timeLow3;
     uint8_t timeLow4;
-} __attribute__((packed)) GUIDData;
+};
 
-typedef struct
+struct DeviceInfo
 {
-    uint8_t biosIdLength;
-    uint8_t biosId[maxBiosIdLength];
-} __attribute__((packed)) DeviceInfo;
+    uint8_t biosIDLength;
+    uint8_t biosId[maxBIOSIDLength];
+};
 
-typedef struct
+struct SetPowerRestoreDelayReq
+{
+    uint8_t byteMSB;
+    uint8_t byteLSB;
+};
+
+struct GetPowerRestoreDelayRes
+{
+    uint8_t byteMSB;
+    uint8_t byteLSB;
+};
+
+struct GetOemDeviceInfoReq
 {
     uint8_t entityType;
     uint8_t countToRead;
     uint8_t offset;
-} __attribute__((packed)) GetOemDeviceInfoReq;
+};
 
-typedef struct
+struct GetOemDeviceInfoRes
 {
     uint8_t resDatalen;
-    uint8_t data[maxBiosIdLength];
-} __attribute__((packed)) GetOemDeviceInfoRes;
+    uint8_t data[maxBIOSIDLength];
+};
+
+struct SetProcessorErrConfigReq
+{
+    uint8_t resetCfg; // Reset Configuration
+                      //   [0]:   CATERR Reset Enabled
+                      //               0b: Disabled
+                      //               1b: Enabled
+                      //   [1]:   ERR2 Reset Enabled
+                      //               0b: Disabled
+                      //               1b: Enabled
+                      //   [7:2]: Reserved
+    uint8_t reserved; // Reserved
+    uint8_t
+        resetErrorOccurrenceCounts; // Reset Error Occurrence Counts
+                                    //[0]: Reset CPU Error Counts
+                                    //    0b: Keep CPU Error Counts
+                                    //    1b: Reset all CPU Error Counts to zero
+                                    //[7:1]: Reserved
+};
+
+struct GetProcessorErrConfigRes
+{
+    uint8_t resetCfg;             // Reset Configuration
+                                  //   [0]:   CATERR Reset Enabled
+                                  //               0b: Disabled
+                                  //               1b: Enabled
+                                  //   [1]:   ERR2 Reset Enabled
+                                  //               0b: Disabled
+                                  //               1b: Enabled
+                                  //   [7:2]: Reserved
+    uint8_t reserved;             // Reserved
+    char caterrStatus[maxCPUNum]; // for all CPUs including the non-legacy
+                                  // socket CPU CPU CATERR (Core Error)
+                                  // occurrence
+                                  //     [5:0]: Error Occurrence Count
+                                  //     [7:6]: CPU Status
+                                  //                 00b: Disabled
+                                  //                 01b: Enabled
+                                  //                 11b: Not Present
+};
+#pragma pack(pop)
\ No newline at end of file
diff --git a/src/oemcommands.cpp b/src/oemcommands.cpp
index 6b38579..781f6ba 100644
--- a/src/oemcommands.cpp
+++ b/src/oemcommands.cpp
@@ -14,24 +14,25 @@
 // limitations under the License.
 */
 
+#include "xyz/openbmc_project/Common/error.hpp"
+
 #include <host-ipmid/ipmid-api.h>
 
 #include <array>
+#include <commandutils.hpp>
 #include <iostream>
 #include <oemcommands.hpp>
 #include <phosphor-ipmi-host/utils.hpp>
 #include <phosphor-logging/log.hpp>
 #include <sdbusplus/bus.hpp>
-#include <sstream>
 #include <string>
 #include <vector>
-#include <xyz/openbmc_project/Common/error.hpp>
 
 namespace ipmi
 {
-static void register_netfn_firmware_functions() __attribute__((constructor));
-sdbusplus::bus::bus _dbus(ipmid_get_sd_bus_connection()); // from ipmid-api.h
-static constexpr size_t maxFruStringLength = 0x3F;
+static void registerOEMFunctions() __attribute__((constructor));
+sdbusplus::bus::bus dbus(ipmid_get_sd_bus_connection()); // from ipmid-api.h
+static constexpr size_t maxFRUStringLength = 0x3F;
 
 // return code: 0 successful
 int8_t getChassisSerialNumber(sdbusplus::bus::bus& bus, std::string& serial)
@@ -48,7 +49,7 @@
         return -1;
     }
 
-    for (auto& item : valueTree)
+    for (const auto& item : valueTree)
     {
         auto interface = item.second.find("xyz.openbmc_project.FruDevice");
         if (interface == item.second.end())
@@ -65,39 +66,34 @@
         try
         {
             Value variant = property->second;
-            std::string& result = variant.get<std::string>();
-            if (result.size() > maxFruStringLength)
+            std::string& result =
+                sdbusplus::message::variant_ns::get<std::string>(variant);
+            if (result.size() > maxFRUStringLength)
             {
                 phosphor::logging::log<phosphor::logging::level::ERR>(
                     "FRU serial number exceed maximum length");
-
                 return -1;
             }
-            else
-            {
-                serial = result;
-            }
+            serial = result;
             return 0;
         }
-        catch (mapbox::util::bad_variant_access& e)
+        catch (sdbusplus::message::variant_ns::bad_variant_access& e)
         {
-            std::cerr << e.what() << std::endl;
+            phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
             return -1;
         }
     }
     return -1;
 }
+
 ipmi_ret_t ipmiOEMWildcard(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                            ipmi_request_t request, ipmi_response_t response,
-                           ipmi_data_len_t data_len, ipmi_context_t context)
+                           ipmi_data_len_t dataLen, ipmi_context_t context)
 {
-    phosphor::logging::log<phosphor::logging::level::INFO>(
-        "Handling OEM WILDCARD", phosphor::logging::entry("NETFN=%x", netfn),
-        phosphor::logging::entry("CMD=%x", cmd));
-
+    printCommand(+netfn, +cmd);
     // Status code.
     ipmi_ret_t rc = IPMI_CC_INVALID;
-    *data_len = 0;
+    *dataLen = 0;
     return rc;
 }
 
@@ -105,46 +101,43 @@
 ipmi_ret_t ipmiOEMGetChassisIdentifier(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                        ipmi_request_t request,
                                        ipmi_response_t response,
-                                       ipmi_data_len_t data_len,
+                                       ipmi_data_len_t dataLen,
                                        ipmi_context_t context)
 {
     std::string serial;
-    if (*data_len != 0) // invalid request if there are extra parameters
+    if (*dataLen != 0) // invalid request if there are extra parameters
     {
+        *dataLen = 0;
         return IPMI_CC_REQ_DATA_LEN_INVALID;
     }
-    if (getChassisSerialNumber(_dbus, serial) == 0)
+    if (getChassisSerialNumber(dbus, serial) == 0)
     {
-        *data_len = serial.size(); // length will never exceed response length
-                                   // as it is checked in getChassisSerialNumber
+        *dataLen = serial.size(); // length will never exceed response length
+                                  // as it is checked in getChassisSerialNumber
         char* resp = static_cast<char*>(response);
-        serial.copy(resp, *data_len);
+        serial.copy(resp, *dataLen);
         return IPMI_CC_OK;
     }
-    else
-    {
-        *data_len = 0;
-        return IPMI_CC_RESPONSE_ERROR;
-    }
+    *dataLen = 0;
+    return IPMI_CC_RESPONSE_ERROR;
 }
 
 ipmi_ret_t ipmiOEMSetSystemGUID(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
                                 ipmi_request_t request,
                                 ipmi_response_t response,
-                                ipmi_data_len_t data_len,
-                                ipmi_context_t context)
+                                ipmi_data_len_t dataLen, ipmi_context_t context)
 {
     static constexpr size_t safeBufferLength = 50;
     char buf[safeBufferLength] = {0};
     GUIDData* Data = reinterpret_cast<GUIDData*>(request);
 
-    if (*data_len != sizeof(GUIDData)) // 16bytes
+    if (*dataLen != sizeof(GUIDData)) // 16bytes
     {
-        *data_len = 0;
+        *dataLen = 0;
         return IPMI_CC_REQ_DATA_LEN_INVALID;
     }
 
-    *data_len = 0;
+    *dataLen = 0;
 
     snprintf(
         buf, safeBufferLength,
@@ -155,13 +148,11 @@
         Data->node3, Data->node2, Data->node1);
     // UUID is in RFC4122 format. Ex: 61a39523-78f2-11e5-9862-e6402cfc3223
     std::string guid = buf;
-    phosphor::logging::log<phosphor::logging::level::INFO>(
-        "Set System GUID", phosphor::logging::entry("GUID=%s", guid.c_str()));
 
     std::string objpath = "/xyz/openbmc_project/control/host0/systemGUID";
     std::string intf = "xyz.openbmc_project.Common.UUID";
-    std::string service = getService(_dbus, intf, objpath);
-    setDbusProperty(_dbus, service, objpath, intf, "UUID", guid);
+    std::string service = getService(dbus, intf, objpath);
+    setDbusProperty(dbus, service, objpath, intf, "UUID", guid);
     return IPMI_CC_OK;
 }
 
@@ -171,22 +162,18 @@
 {
     DeviceInfo* data = reinterpret_cast<DeviceInfo*>(request);
 
-    if ((*dataLen < 2) || (*dataLen != (1 + data->biosIdLength)))
+    if ((*dataLen < 2) || (*dataLen != (1 + data->biosIDLength)))
     {
-        phosphor::logging::log<phosphor::logging::level::ERR>(
-            "Invalid parameter", phosphor::logging::entry("LEN=%d", *dataLen),
-            phosphor::logging::entry("BIOSIDLEN=%d", data->biosIdLength));
-
         *dataLen = 0;
         return IPMI_CC_REQ_DATA_LEN_INVALID;
     }
-    std::string idString((char*)data->biosId, data->biosIdLength);
+    std::string idString((char*)data->biosId, data->biosIDLength);
 
-    std::string service = getService(_dbus, biosIntf, biosObjPath);
-    setDbusProperty(_dbus, service, biosObjPath, biosIntf, biosProp, idString);
+    std::string service = getService(dbus, biosIntf, biosObjPath);
+    setDbusProperty(dbus, service, biosObjPath, biosIntf, biosProp, idString);
     uint8_t* bytesWritten = static_cast<uint8_t*>(response);
     *bytesWritten =
-        data->biosIdLength; // how many bytes are written into storage
+        data->biosIDLength; // how many bytes are written into storage
     *dataLen = 1;
     return IPMI_CC_OK;
 }
@@ -201,71 +188,55 @@
 
     if (*dataLen == 0)
     {
-        phosphor::logging::log<phosphor::logging::level::ERR>(
-            "Paramter length should be at least one byte");
+        *dataLen = 0;
         return IPMI_CC_REQ_DATA_LEN_INVALID;
     }
 
     size_t reqDataLen = *dataLen;
     *dataLen = 0;
-    if (req->entityType > OEMDevEntityType::sdrVer)
+    if (req->entityType > static_cast<uint8_t>(OEMDevEntityType::sdrVer))
     {
-        phosphor::logging::log<phosphor::logging::level::ERR>(
-            "Out of range",
-            phosphor::logging::entry("TYPE=%x", req->entityType));
-
         return IPMI_CC_INVALID_FIELD_REQUEST;
     }
 
     // handle OEM command items
-    switch (req->entityType)
+    switch (OEMDevEntityType(req->entityType))
     {
         case OEMDevEntityType::biosId:
         {
             if (sizeof(GetOemDeviceInfoReq) != reqDataLen)
             {
-                phosphor::logging::log<phosphor::logging::level::ERR>(
-                    "Data length does not match request",
-                    phosphor::logging::entry("REQLEN=%d", reqDataLen),
-                    phosphor::logging::entry("LEN=%d",
-                                             sizeof(GetOemDeviceInfoReq)));
                 return IPMI_CC_REQ_DATA_LEN_INVALID;
             }
 
-            std::string service = getService(_dbus, biosIntf, biosObjPath);
+            std::string service = getService(dbus, biosIntf, biosObjPath);
             try
             {
-                Value variant = getDbusProperty(_dbus, service, biosObjPath,
+                Value variant = getDbusProperty(dbus, service, biosObjPath,
                                                 biosIntf, biosProp);
-                std::string& idString = variant.get<std::string>();
+                std::string& idString =
+                    sdbusplus::message::variant_ns::get<std::string>(variant);
                 if (req->offset >= idString.size())
                 {
-                    phosphor::logging::log<phosphor::logging::level::ERR>(
-                        "offset exceed range",
-                        phosphor::logging::entry("OFFSET=%d", req->offset),
-                        phosphor::logging::entry("IDLEN=%d", idString.size()));
                     return IPMI_CC_PARM_OUT_OF_RANGE;
                 }
+                size_t length = 0;
+                if (req->countToRead > (idString.size() - req->offset))
+                {
+                    length = idString.size() - req->offset;
+                }
                 else
                 {
-                    size_t length = 0;
-                    if (req->countToRead > (idString.size() - req->offset))
-                    {
-                        length = idString.size() - req->offset;
-                    }
-                    else
-                    {
-                        length = req->countToRead;
-                    }
-                    std::copy(idString.begin() + req->offset, idString.end(),
-                              res->data);
-                    res->resDatalen = length;
-                    *dataLen = res->resDatalen + 1;
+                    length = req->countToRead;
                 }
+                std::copy(idString.begin() + req->offset, idString.end(),
+                          res->data);
+                res->resDatalen = length;
+                *dataLen = res->resDatalen + 1;
             }
-            catch (mapbox::util::bad_variant_access& e)
+            catch (sdbusplus::message::variant_ns::bad_variant_access& e)
             {
-                std::cerr << e.what() << std::endl;
+                phosphor::logging::log<phosphor::logging::level::ERR>(e.what());
                 return IPMI_CC_UNSPECIFIED_ERROR;
             }
         }
@@ -287,8 +258,7 @@
 {
     if (*dataLen != 0)
     {
-        phosphor::logging::log<phosphor::logging::level::ERR>(
-            "This command should not have any paramter");
+        *dataLen = 0;
         return IPMI_CC_REQ_DATA_LEN_INVALID;
     }
 
@@ -301,35 +271,196 @@
     return IPMI_CC_OK;
 }
 
-void ipmi_register(ipmi_netfn_t netfn, ipmi_cmd_t cmd, ipmi_context_t context,
-                   ipmid_callback_t handler, ipmi_cmd_privilege_t priv)
+ipmi_ret_t ipmiOEMGetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                       ipmi_request_t request,
+                                       ipmi_response_t response,
+                                       ipmi_data_len_t dataLen,
+                                       ipmi_context_t context)
 {
-    std::ostringstream os;
-    os << "Registering NetFn:[0x" << std::hex << std::uppercase << netfn
-       << "], Cmd:[0x" << cmd << "]\n";
-    phosphor::logging::log<phosphor::logging::level::INFO>(os.str().c_str());
-    ipmi_register_callback(netfn, cmd, context, handler, priv);
+    GetPowerRestoreDelayRes* resp =
+        reinterpret_cast<GetPowerRestoreDelayRes*>(response);
+
+    if (*dataLen != 0)
+    {
+        *dataLen = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    std::string service =
+        getService(dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath);
+    Value variant =
+        getDbusProperty(dbus, service, powerRestoreDelayObjPath,
+                        powerRestoreDelayIntf, powerRestoreDelayProp);
+
+    uint16_t delay = sdbusplus::message::variant_ns::get<uint16_t>(variant);
+    resp->byteLSB = delay;
+    resp->byteMSB = delay >> 8;
+
+    *dataLen = sizeof(GetPowerRestoreDelayRes);
+
+    return IPMI_CC_OK;
 }
 
-static void register_netfn_firmware_functions(void)
+ipmi_ret_t ipmiOEMSetPowerRestoreDelay(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                       ipmi_request_t request,
+                                       ipmi_response_t response,
+                                       ipmi_data_len_t dataLen,
+                                       ipmi_context_t context)
+{
+    SetPowerRestoreDelayReq* data =
+        reinterpret_cast<SetPowerRestoreDelayReq*>(request);
+    uint16_t delay = 0;
+
+    if (*dataLen != sizeof(SetPowerRestoreDelayReq))
+    {
+        *dataLen = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+    delay = data->byteMSB;
+    delay = (delay << 8) | data->byteLSB;
+    std::string service =
+        getService(dbus, powerRestoreDelayIntf, powerRestoreDelayObjPath);
+    setDbusProperty(dbus, service, powerRestoreDelayObjPath,
+                    powerRestoreDelayIntf, powerRestoreDelayProp, delay);
+    *dataLen = 0;
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t ipmiOEMGetProcessorErrConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                        ipmi_request_t request,
+                                        ipmi_response_t response,
+                                        ipmi_data_len_t dataLen,
+                                        ipmi_context_t context)
+{
+    GetProcessorErrConfigRes* resp =
+        reinterpret_cast<GetProcessorErrConfigRes*>(response);
+
+    if (*dataLen != 0)
+    {
+        *dataLen = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+
+    std::string service =
+        getService(dbus, processorErrConfigIntf, processorErrConfigObjPath);
+    Value variant = getDbusProperty(dbus, service, processorErrConfigObjPath,
+                                    processorErrConfigIntf, "ResetCfg");
+    resp->resetCfg = sdbusplus::message::variant_ns::get<uint8_t>(variant);
+
+    std::vector<uint8_t> caterrStatus;
+
+    auto method =
+        dbus.new_method_call(service.c_str(), processorErrConfigObjPath,
+                             "org.freedesktop.DBus.Properties", "Get");
+
+    method.append(processorErrConfigIntf, "CATERRStatus");
+
+    try
+    {
+        auto reply = dbus.call(method);
+        reply.read(caterrStatus);
+    }
+    catch (sdbusplus::exception_t&)
+    {
+        phosphor::logging::log<phosphor::logging::level::DEBUG>(
+            "ipmiOEMGetProcessorErrConfig: error on dbus",
+            phosphor::logging::entry("PRORPERTY=CATERRStatus"),
+            phosphor::logging::entry("PATH=%s", processorErrConfigObjPath),
+            phosphor::logging::entry("INTERFACE=%s", processorErrConfigIntf));
+        return IPMI_CC_UNSPECIFIED_ERROR;
+    }
+
+    size_t len =
+        maxCPUNum <= caterrStatus.size() ? maxCPUNum : caterrStatus.size();
+    caterrStatus.resize(len);
+    std::copy(caterrStatus.begin(), caterrStatus.end(), resp->caterrStatus);
+    *dataLen = sizeof(GetProcessorErrConfigRes);
+
+    return IPMI_CC_OK;
+}
+
+ipmi_ret_t ipmiOEMSetProcessorErrConfig(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
+                                        ipmi_request_t request,
+                                        ipmi_response_t response,
+                                        ipmi_data_len_t dataLen,
+                                        ipmi_context_t context)
+{
+    SetProcessorErrConfigReq* req =
+        reinterpret_cast<SetProcessorErrConfigReq*>(request);
+
+    if (*dataLen != sizeof(SetProcessorErrConfigReq))
+    {
+        *dataLen = 0;
+        return IPMI_CC_REQ_DATA_LEN_INVALID;
+    }
+    std::string service =
+        getService(dbus, processorErrConfigIntf, processorErrConfigObjPath);
+    setDbusProperty(dbus, service, processorErrConfigObjPath,
+                    processorErrConfigIntf, "ResetCfg", req->resetCfg);
+
+    setDbusProperty(dbus, service, processorErrConfigObjPath,
+                    processorErrConfigIntf, "ResetErrorOccurrenceCounts",
+                    req->resetErrorOccurrenceCounts);
+    *dataLen = 0;
+
+    return IPMI_CC_OK;
+}
+
+static void registerOEMFunctions(void)
 {
     phosphor::logging::log<phosphor::logging::level::INFO>(
         "Registering OEM commands");
-    ipmi_register(netfunIntcOEMGeneral, IPMI_CMD_WILDCARD, NULL,
-                  ipmiOEMWildcard,
-                  PRIVILEGE_USER); // wildcard default handler
-    ipmi_register(netfunIntcOEMGeneral, cmdGetChassisIdentifier, NULL,
-                  ipmiOEMGetChassisIdentifier,
-                  PRIVILEGE_USER); // get chassis identifier
-    ipmi_register(netfunIntcOEMGeneral, cmdSetSystemGUID, NULL,
-                  ipmiOEMSetSystemGUID,
-                  PRIVILEGE_ADMIN); // set system guid
-    ipmi_register(netfunIntcOEMGeneral, cmdSetBIOSID, NULL, ipmiOEMSetBIOSID,
-                  PRIVILEGE_ADMIN);
-    ipmi_register(netfunIntcOEMGeneral, cmdGetOEMDeviceInfo, NULL,
-                  ipmiOEMGetDeviceInfo, PRIVILEGE_USER);
-    ipmi_register(netfunIntcOEMGeneral, cmdGetAICSlotFRUIDRecords, NULL,
-                  ipmiOEMGetAICFRU, PRIVILEGE_USER);
+    ipmiPrintAndRegister(netfnIntcOEMGeneral, IPMI_CMD_WILDCARD, NULL,
+                         ipmiOEMWildcard,
+                         PRIVILEGE_USER); // wildcard default handler
+    ipmiPrintAndRegister(netfunIntelAppOEM, IPMI_CMD_WILDCARD, NULL,
+                         ipmiOEMWildcard,
+                         PRIVILEGE_USER); // wildcard default handler
+    ipmiPrintAndRegister(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(
+            IPMINetfnIntelOEMGeneralCmd::cmdGetChassisIdentifier),
+        NULL, ipmiOEMGetChassisIdentifier,
+        PRIVILEGE_USER); // get chassis identifier
+    ipmiPrintAndRegister(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdSetSystemGUID),
+        NULL, ipmiOEMSetSystemGUID,
+        PRIVILEGE_ADMIN); // set system guid
+    ipmiPrintAndRegister(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(IPMINetfnIntelOEMGeneralCmd::cmdSetBIOSID),
+        NULL, ipmiOEMSetBIOSID, PRIVILEGE_ADMIN);
+    ipmiPrintAndRegister(netfnIntcOEMGeneral,
+                         static_cast<ipmi_cmd_t>(
+                             IPMINetfnIntelOEMGeneralCmd::cmdGetOEMDeviceInfo),
+                         NULL, ipmiOEMGetDeviceInfo, PRIVILEGE_USER);
+    ipmiPrintAndRegister(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(
+            IPMINetfnIntelOEMGeneralCmd::cmdGetAICSlotFRUIDSlotPosRecords),
+        NULL, ipmiOEMGetAICFRU, PRIVILEGE_USER);
+    ipmiPrintAndRegister(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(
+            IPMINetfnIntelOEMGeneralCmd::cmdSetPowerRestoreDelay),
+        NULL, ipmiOEMSetPowerRestoreDelay, PRIVILEGE_OPERATOR);
+    ipmiPrintAndRegister(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(
+            IPMINetfnIntelOEMGeneralCmd::cmdGetPowerRestoreDelay),
+        NULL, ipmiOEMGetPowerRestoreDelay, PRIVILEGE_USER);
+    ipmiPrintAndRegister(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(
+            IPMINetfnIntelOEMGeneralCmd::cmdGetProcessorErrConfig),
+        NULL, ipmiOEMGetProcessorErrConfig, PRIVILEGE_USER);
+    ipmiPrintAndRegister(
+        netfnIntcOEMGeneral,
+        static_cast<ipmi_cmd_t>(
+            IPMINetfnIntelOEMGeneralCmd::cmdSetProcessorErrConfig),
+        NULL, ipmiOEMSetProcessorErrConfig, PRIVILEGE_ADMIN);
     return;
 }