chassishandler: SetSystemBootOptions to new API

Rewrite ipmiChassisSetSysBootOptions to use newly introduced IPMI
provider API

Tested:
verified using IPMI chassis bootparam command and raw commands

Command:  ipmitool chassis bootparam set bootflag force_disk
Response: Set Boot Device to force_disk
Command:  ipmitool chassis bootparam set bootflag force_pxe
Response: Set Boot Device to force_pxe
Command:  ipmitool chassis bootdev pxe options=persistent
Response: Set Boot Device to pxe
Command:  ipmitool chassis bootparam set bootflag force_bios
Response: Set Boot Device to force_bios
Command:  ipmitool chassis bootparam set bootflag force_safe
Response: Set Chassis Boot Parameter 5 failed: Invalid data field in
          request

Command:  ipmitool raw 0 8 0x5 0 0 0 0 0 //setBootOptions param 5
Response:                           //Success
Command:  ipmitool raw 0 8 0x4 0 0  //setBootOptions param 4
Response:                           //Success
Command:  ipmitool raw 0 8 0x61 0x21 0x70 0x62 0x21 0x00 0x01
          0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
          0x01 0x01 0x04 0 0 0 0 1 1 1 1 //setBootOptions param 61
Response:                           //Success
Command:  ipmitool raw 0 8 0 0      //setBootOptions param 0
Response: Unable to send RAW command (channel=0x0 netfn=0x0 lun=0x0
          cmd=0x8 rsp=0x80): Unknown (0x80)

Signed-off-by: jayaprakash Mutyala <mutyalax.jayaprakash@intel.com>
Signed-off-by: srikanta mondal <srikantax.mondal@intel.com>
Change-Id: I6faa0b5162ba02bbe0e8a3acaba092888ed48acc
diff --git a/chassishandler.cpp b/chassishandler.cpp
index 46a4707..28cb756 100644
--- a/chassishandler.cpp
+++ b/chassishandler.cpp
@@ -34,37 +34,33 @@
 #include <xyz/openbmc_project/State/Host/server.hpp>
 #include <xyz/openbmc_project/State/PowerOnHours/server.hpp>
 
-// Defines
-#define SET_PARM_VERSION 0x01
-#define SET_PARM_BOOT_FLAGS_PERMANENT 0x40
-#define SET_PARM_BOOT_FLAGS_VALID_ONE_TIME 0x80
-#define SET_PARM_BOOT_FLAGS_VALID_PERMANENT 0xC0
-
 std::unique_ptr<phosphor::Timer> identifyTimer
     __attribute__((init_priority(101)));
 
 static ChassisIDState chassisIDState = ChassisIDState::reserved;
+static constexpr uint8_t setParmVersion = 0x01;
+static constexpr uint8_t setParmBootFlagsPermanent = 0x40;
+static constexpr uint8_t setParmBootFlagsValidOneTime = 0x80;
+static constexpr uint8_t setParmBootFlagsValidPermanent = 0xC0;
 
-constexpr size_t SIZE_MAC = 18;
-constexpr size_t SIZE_BOOT_OPTION = (uint8_t)
-    BootOptionResponseSize::OPAL_NETWORK_SETTINGS; // Maximum size of the boot
-                                                   // option parametrs
-constexpr size_t SIZE_PREFIX = 7;
-constexpr size_t MAX_PREFIX_VALUE = 32;
-constexpr size_t SIZE_COOKIE = 4;
-constexpr size_t SIZE_VERSION = 2;
+constexpr size_t SIZE_BOOT_OPTION = static_cast<size_t>(
+    BootOptionResponseSize::opalNetworkSettings); // Maximum size of the boot
+                                                  // option parameters
+constexpr size_t sizeVersion = 2;
 constexpr size_t DEFAULT_IDENTIFY_TIME_OUT = 15;
 
 // PetiBoot-Specific
-static constexpr uint8_t net_conf_initial_bytes[] = {0x80, 0x21, 0x70, 0x62,
-                                                     0x21, 0x00, 0x01, 0x06};
+static constexpr uint8_t netConfInitialBytes[] = {0x80, 0x21, 0x70, 0x62,
+                                                  0x21, 0x00, 0x01, 0x06};
+static constexpr uint8_t oemParmStart = 96;
+static constexpr uint8_t oemParmEnd = 127;
 
-static constexpr size_t COOKIE_OFFSET = 1;
-static constexpr size_t VERSION_OFFSET = 5;
-static constexpr size_t ADDR_SIZE_OFFSET = 8;
-static constexpr size_t MAC_OFFSET = 9;
-static constexpr size_t ADDRTYPE_OFFSET = 16;
-static constexpr size_t IPADDR_OFFSET = 17;
+static constexpr size_t cookieOffset = 1;
+static constexpr size_t versionOffset = 5;
+static constexpr size_t addrSizeOffset = 8;
+static constexpr size_t macOffset = 9;
+static constexpr size_t addrTypeOffset = 16;
+static constexpr size_t ipAddrOffset = 17;
 
 static constexpr uint4_t RESERVED = 0;
 static constexpr uint8_t CHANNEL_NOT_SUPPORTED = 0;
@@ -74,6 +70,16 @@
 static constexpr size_t identifyIntervalPos = 0;
 static constexpr size_t forceIdentifyPos = 1;
 
+namespace ipmi
+{
+constexpr Cc ccParmNotSupported = 0x80;
+
+static inline auto responseParmNotSupported()
+{
+    return response(ccParmNotSupported);
+}
+} // namespace ipmi
+
 void register_netfn_chassis_functions() __attribute__((constructor));
 
 // Host settings in dbus
@@ -179,12 +185,6 @@
     uint8_t data[SIZE_BOOT_OPTION];
 } __attribute__((packed));
 
-struct set_sys_boot_options_t
-{
-    uint8_t parameter;
-    uint8_t data[SIZE_BOOT_OPTION];
-} __attribute__((packed));
-
 int getHostNetworkData(get_sys_boot_options_response_t* respptr)
 {
     ipmi::PropertyMap properties;
@@ -254,15 +254,15 @@
             }
         }
 
-        sscanf(
-            MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
-            (respptr->data + MAC_OFFSET), (respptr->data + MAC_OFFSET + 1),
-            (respptr->data + MAC_OFFSET + 2), (respptr->data + MAC_OFFSET + 3),
-            (respptr->data + MAC_OFFSET + 4), (respptr->data + MAC_OFFSET + 5));
+        sscanf(MACAddress.c_str(), ipmi::network::MAC_ADDRESS_FORMAT,
+               (respptr->data + macOffset), (respptr->data + macOffset + 1),
+               (respptr->data + macOffset + 2), (respptr->data + macOffset + 3),
+               (respptr->data + macOffset + 4),
+               (respptr->data + macOffset + 5));
 
-        respptr->data[MAC_OFFSET + 6] = 0x00;
+        respptr->data[macOffset + 6] = 0x00;
 
-        std::memcpy(respptr->data + ADDRTYPE_OFFSET, &isStatic,
+        std::memcpy(respptr->data + addrTypeOffset, &isStatic,
                     sizeof(isStatic));
 
         uint8_t addressFamily = (std::get<std::string>(properties["Type"]) ==
@@ -276,9 +276,9 @@
 
         // ipaddress and gateway would be in IPv4 format
         inet_pton(addressFamily, ipAddress.c_str(),
-                  (respptr->data + IPADDR_OFFSET));
+                  (respptr->data + ipAddrOffset));
 
-        uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
+        uint8_t prefixOffset = ipAddrOffset + addrSize;
 
         std::memcpy(respptr->data + prefixOffset, &prefix, sizeof(prefix));
 
@@ -297,10 +297,10 @@
 
     // PetiBoot-Specific
     // If success then copy the first 9 bytes to the data
-    std::memcpy(respptr->data, net_conf_initial_bytes,
-                sizeof(net_conf_initial_bytes));
+    std::memcpy(respptr->data, netConfInitialBytes,
+                sizeof(netConfInitialBytes));
 
-    std::memcpy(respptr->data + ADDR_SIZE_OFFSET, &addrSize, sizeof(addrSize));
+    std::memcpy(respptr->data + addrSizeOffset, &addrSize, sizeof(addrSize));
 
 #ifdef _IPMI_DEBUG_
     std::printf("\n===Printing the IPMI Formatted Data========\n");
@@ -360,19 +360,18 @@
     return ipAddr;
 }
 
-int setHostNetworkData(set_sys_boot_options_t* reqptr)
+ipmi::Cc setHostNetworkData(ipmi::message::Payload& data)
 {
     using namespace std::string_literals;
-    std::string host_network_config;
-    char mac[]{"00:00:00:00:00:00"};
+    std::string hostNetworkConfig;
+    std::string mac("00:00:00:00:00:00");
     std::string ipAddress, gateway;
-    char addrOrigin{0};
+    std::string addrOrigin{0};
     uint8_t addrSize{0};
     std::string addressOrigin =
         "xyz.openbmc_project.Network.IP.AddressOrigin.DHCP";
     std::string addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv4";
     uint8_t prefix{0};
-    uint32_t zeroCookie = 0;
     uint8_t family = AF_INET;
 
     // cookie starts from second byte
@@ -383,13 +382,33 @@
         do
         {
             // cookie ==  0x21 0x70 0x62 0x21
-            if (memcmp(&(reqptr->data[COOKIE_OFFSET]),
-                       (net_conf_initial_bytes + COOKIE_OFFSET),
-                       SIZE_COOKIE) != 0)
+            data.trailingOk = true;
+            auto msgLen = data.size();
+            std::vector<uint8_t> msgPayloadBytes(msgLen);
+            if (data.unpack(msgPayloadBytes) != 0 || !data.fullyUnpacked())
             {
-                // cookie == 0
-                if (memcmp(&(reqptr->data[COOKIE_OFFSET]), &zeroCookie,
-                           SIZE_COOKIE) == 0)
+                log<level::ERR>(
+                    "Error in unpacking message of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
+
+            uint8_t* msgPayloadStartingPos = msgPayloadBytes.data();
+            constexpr size_t cookieSize = 4;
+            if (msgLen < cookieOffset + cookieSize)
+            {
+                log<level::ERR>(
+                    "Error in cookie getting of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
+            if (std::equal(msgPayloadStartingPos + cookieOffset,
+                           msgPayloadStartingPos + cookieOffset + cookieSize,
+                           (netConfInitialBytes + cookieOffset)) != 0)
+            {
+                // all cookie == 0
+                if (std::all_of(msgPayloadStartingPos + cookieOffset,
+                                msgPayloadStartingPos + cookieOffset +
+                                    cookieSize,
+                                [](int i) { return i == 0; }) == true)
                 {
                     // need to zero out the network settings.
                     break;
@@ -400,59 +419,106 @@
             }
 
             // vesion == 0x00 0x01
-            if (memcmp(&(reqptr->data[VERSION_OFFSET]),
-                       (net_conf_initial_bytes + VERSION_OFFSET),
-                       SIZE_VERSION) != 0)
+            if (msgLen < versionOffset + sizeVersion)
             {
-
+                log<level::ERR>(
+                    "Error in version getting of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
+            if (std::equal(msgPayloadStartingPos + versionOffset,
+                           msgPayloadStartingPos + versionOffset + sizeVersion,
+                           (netConfInitialBytes + versionOffset)) != 0)
+            {
                 log<level::ERR>("Invalid Version");
                 elog<InternalFailure>();
             }
 
-            std::snprintf(
-                mac, SIZE_MAC, ipmi::network::MAC_ADDRESS_FORMAT,
-                reqptr->data[MAC_OFFSET], reqptr->data[MAC_OFFSET + 1],
-                reqptr->data[MAC_OFFSET + 2], reqptr->data[MAC_OFFSET + 3],
-                reqptr->data[MAC_OFFSET + 4], reqptr->data[MAC_OFFSET + 5]);
+            if (msgLen < macOffset + 6)
+            {
+                log<level::ERR>(
+                    "Error in mac address getting of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
+            std::stringstream result;
+            std::copy((msgPayloadStartingPos + macOffset),
+                      (msgPayloadStartingPos + macOffset + 5),
+                      std::ostream_iterator<int>(result, ":"));
+            mac = result.str();
 
-            std::memcpy(&addrOrigin, &(reqptr->data[ADDRTYPE_OFFSET]),
-                        sizeof(decltype(addrOrigin)));
+            if (msgLen < addrTypeOffset + sizeof(decltype(addrOrigin)))
+            {
+                log<level::ERR>(
+                    "Error in original address getting of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
+            std::copy(msgPayloadStartingPos + addrTypeOffset,
+                      msgPayloadStartingPos + addrTypeOffset +
+                          sizeof(decltype(addrOrigin)),
+                      std::ostream_iterator<int>(result, ""));
+            addrOrigin = result.str();
 
-            if (addrOrigin)
+            if (!addrOrigin.empty())
             {
                 addressOrigin =
                     "xyz.openbmc_project.Network.IP.AddressOrigin.Static";
             }
 
+            if (msgLen < addrSizeOffset + sizeof(decltype(addrSize)))
+            {
+                log<level::ERR>(
+                    "Error in address size getting of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
             // Get the address size
-            std::memcpy(&addrSize, &reqptr->data[ADDR_SIZE_OFFSET],
-                        sizeof(addrSize));
+            std::copy(msgPayloadStartingPos + addrSizeOffset,
+                      (msgPayloadStartingPos + addrSizeOffset +
+                       sizeof(decltype(addrSize))),
+                      &addrSize);
 
-            uint8_t prefixOffset = IPADDR_OFFSET + addrSize;
-
-            std::memcpy(&prefix, &(reqptr->data[prefixOffset]),
-                        sizeof(decltype(prefix)));
+            uint8_t prefixOffset = ipAddrOffset + addrSize;
+            if (msgLen < prefixOffset + sizeof(decltype(prefix)))
+            {
+                log<level::ERR>(
+                    "Error in prefix getting of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
+            std::copy(msgPayloadStartingPos + prefixOffset,
+                      (msgPayloadStartingPos + prefixOffset +
+                       sizeof(decltype(prefix))),
+                      &prefix);
 
             uint8_t gatewayOffset = prefixOffset + sizeof(decltype(prefix));
-
             if (addrSize != ipmi::network::IPV4_ADDRESS_SIZE_BYTE)
             {
                 addressType = "xyz.openbmc_project.Network.IP.Protocol.IPv6";
                 family = AF_INET6;
             }
 
-            ipAddress =
-                getAddrStr(family, reqptr->data, IPADDR_OFFSET, addrSize);
+            if (msgLen < ipAddrOffset + addrSize)
+            {
+                log<level::ERR>(
+                    "Error in IP address getting of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
+            ipAddress = getAddrStr(family, msgPayloadStartingPos, ipAddrOffset,
+                                   addrSize);
 
-            gateway = getAddrStr(family, reqptr->data, gatewayOffset, addrSize);
+            if (msgLen < gatewayOffset + addrSize)
+            {
+                log<level::ERR>(
+                    "Error in gateway address getting of setHostNetworkData");
+                return ipmi::ccReqDataLenInvalid;
+            }
+            gateway = getAddrStr(family, msgPayloadStartingPos, gatewayOffset,
+                                 addrSize);
 
         } while (0);
 
         // Cookie == 0 or it is a valid cookie
-        host_network_config += "ipaddress="s + ipAddress + ",prefix="s +
-                               std::to_string(prefix) + ",gateway="s + gateway +
-                               ",mac="s + mac + ",addressOrigin="s +
-                               addressOrigin;
+        hostNetworkConfig += "ipaddress="s + ipAddress + ",prefix="s +
+                             std::to_string(prefix) + ",gateway="s + gateway +
+                             ",mac="s + mac + ",addressOrigin="s +
+                             addressOrigin;
 
         sdbusplus::bus::bus bus(ipmid_get_sd_bus_connection());
 
@@ -475,17 +541,17 @@
         ipmi::setDbusProperty(bus, macObjectInfo.second, macObjectInfo.first,
                               MAC_INTERFACE, "MACAddress", std::string(mac));
 
-        log<level::DEBUG>(
-            "Network configuration changed",
-            entry("NETWORKCONFIG=%s", host_network_config.c_str()));
+        log<level::DEBUG>("Network configuration changed",
+                          entry("NETWORKCONFIG=%s", hostNetworkConfig.c_str()));
     }
-    catch (InternalFailure& e)
+    catch (sdbusplus::exception_t& e)
     {
         commit<InternalFailure>();
-        return -1;
+        log<level::ERR>("Error in  ipmiChassisSetSysBootOptions call");
+        return ipmi::ccUnspecifiedError;
     }
 
-    return 0;
+    return ipmi::ccSuccess;
 }
 
 uint32_t getPOHCounter()
@@ -1576,7 +1642,7 @@
  *  @param[in] mode - boot mode value
  *  @return On failure return IPMI error.
  */
-static ipmi_ret_t setBootMode(const Mode::Modes& mode)
+static ipmi::Cc setBootMode(const Mode::Modes& mode)
 {
     using namespace chassis::internal;
     using namespace chassis::internal::cache;
@@ -1593,9 +1659,9 @@
     {
         log<level::ERR>("Error in BootMode Set");
         report<InternalFailure>();
-        return IPMI_CC_UNSPECIFIED_ERROR;
+        return ipmi::ccUnspecifiedError;
     }
-    return IPMI_CC_OK;
+    return ipmi::ccSuccess;
 }
 
 ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
@@ -1613,19 +1679,18 @@
     IpmiValue bootOption = ipmiDefault;
 
     std::memset(resp, 0, sizeof(*resp));
-    resp->version = SET_PARM_VERSION;
+    resp->version = setParmVersion;
     resp->parm = 5;
-    resp->data[0] = SET_PARM_BOOT_FLAGS_VALID_ONE_TIME;
-
+    resp->data[0] = setParmBootFlagsValidOneTime;
     /*
      * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
      * This is the only parameter used by petitboot.
      */
     if (reqptr->parameter ==
-        static_cast<uint8_t>(BootOptionParameter::BOOT_FLAGS))
+        static_cast<uint8_t>(BootOptionParameter::bootFlags))
     {
 
-        *data_len = static_cast<uint8_t>(BootOptionResponseSize::BOOT_FLAGS);
+        *data_len = static_cast<uint8_t>(BootOptionResponseSize::bootFlags);
         using namespace chassis::internal;
         using namespace chassis::internal::cache;
 
@@ -1684,9 +1749,8 @@
             }
             resp->data[1] = (bootOption << 2);
 
-            resp->data[0] = oneTimeEnabled
-                                ? SET_PARM_BOOT_FLAGS_VALID_ONE_TIME
-                                : SET_PARM_BOOT_FLAGS_VALID_PERMANENT;
+            resp->data[0] = oneTimeEnabled ? setParmBootFlagsValidOneTime
+                                           : setParmBootFlagsValidPermanent;
 
             rc = IPMI_CC_OK;
         }
@@ -1699,14 +1763,14 @@
         }
     }
     else if (reqptr->parameter ==
-             static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS))
+             static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings))
     {
 
         *data_len =
-            static_cast<uint8_t>(BootOptionResponseSize::OPAL_NETWORK_SETTINGS);
+            static_cast<uint8_t>(BootOptionResponseSize::opalNetworkSettings);
 
         resp->parm =
-            static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS);
+            static_cast<uint8_t>(BootOptionParameter::opalNetworkSettings);
 
         int ret = getHostNetworkData(resp);
 
@@ -1738,30 +1802,50 @@
     return rc;
 }
 
-ipmi_ret_t ipmi_chassis_set_sys_boot_options(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::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx,
+                                             uint7_t parameterSelector,
+                                             bool parameterIsValid,
+                                             ipmi::message::Payload& data)
 {
     using namespace boot_options;
-    ipmi_ret_t rc = IPMI_CC_OK;
-    set_sys_boot_options_t* reqptr = (set_sys_boot_options_t*)request;
-
-    std::printf("IPMI SET_SYS_BOOT_OPTIONS reqptr->parameter =[%d]\n",
-                reqptr->parameter);
-
-    // This IPMI command does not have any resposne data
-    *data_len = 0;
+    ipmi::Cc rc;
 
     /*  000101
      * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc.
      * This is the only parameter used by petitboot.
      */
 
-    if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS)
+    if (parameterSelector ==
+        static_cast<uint7_t>(BootOptionParameter::bootFlags))
     {
-        IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
+        uint5_t rsvd;
+        bool validFlag;
+        bool permanent;
+        bool biosBootType;
+        bool lockOutResetButton;
+        bool screenBlank;
+        uint4_t bootDeviceSelector;
+        bool lockKeyboard;
+        bool cmosClear;
+        uint8_t data3;
+        uint4_t biosInfo;
+        uint4_t rsvd1;
+        uint5_t deviceInstance;
+        uint3_t rsvd2;
+
+        if (data.unpack(rsvd, biosBootType, permanent, validFlag,
+                        lockOutResetButton, screenBlank, bootDeviceSelector,
+                        lockKeyboard, cmosClear, data3, biosInfo, rsvd1,
+                        deviceInstance, rsvd2) != 0 ||
+            !data.fullyUnpacked())
+        {
+            return ipmi::responseReqDataLenInvalid();
+        }
+        if (rsvd || rsvd1 || rsvd2)
+        {
+            return ipmi::responseInvalidFieldRequest();
+        }
+
         using namespace chassis::internal;
         using namespace chassis::internal::cache;
         auto oneTimeEnabled = false;
@@ -1771,10 +1855,6 @@
 
         try
         {
-            bool permanent =
-                (reqptr->data[0] & SET_PARM_BOOT_FLAGS_PERMANENT) ==
-                SET_PARM_BOOT_FLAGS_PERMANENT;
-
             settings::Objects& objects = getObjects();
 
             auto bootSetting = settings::boot::setting(objects, bootSourceIntf);
@@ -1800,15 +1880,18 @@
                                       "Enabled", !permanent);
             }
 
-            auto modeItr = modeIpmiToDbus.find(bootOption);
-            auto sourceItr = sourceIpmiToDbus.find(bootOption);
+            auto modeItr =
+                modeIpmiToDbus.find(static_cast<uint8_t>(bootDeviceSelector));
+            auto sourceItr =
+                sourceIpmiToDbus.find(static_cast<uint8_t>(bootDeviceSelector));
             if (sourceIpmiToDbus.end() != sourceItr)
             {
                 rc = setBootSource(sourceItr->second);
-                if (rc != IPMI_CC_OK)
+                if (rc != ipmi::ccSuccess)
                 {
-                    *data_len = 0;
-                    return rc;
+                    log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
+                                    "setting boot source");
+                    return ipmi::responseUnspecifiedError();
                 }
                 // If a set boot device is mapping to a boot source, then reset
                 // the boot mode D-Bus property to default.
@@ -1822,10 +1905,11 @@
             if (modeIpmiToDbus.end() != modeItr)
             {
                 rc = setBootMode(modeItr->second);
-                if (rc != IPMI_CC_OK)
+                if (rc != ipmi::ccSuccess)
                 {
-                    *data_len = 0;
-                    return rc;
+                    log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
+                                    "setting boot mode");
+                    return ipmi::responseUnspecifiedError();
                 }
                 // If a set boot device is mapping to a boot mode, then reset
                 // the boot source D-Bus property to default.
@@ -1840,48 +1924,79 @@
                 (sourceIpmiToDbus.end() == sourceItr))
             {
                 // return error if boot option is not supported
-                *data_len = 0;
-                return IPMI_CC_INVALID_FIELD_REQUEST;
+                log<level::ERR>(
+                    "ipmiChassisSetSysBootOptions: Boot option not supported");
+                return ipmi::responseInvalidFieldRequest();
             }
         }
-        catch (InternalFailure& e)
+        catch (sdbusplus::exception_t& e)
         {
             objectsPtr.reset();
             report<InternalFailure>();
-            *data_len = 0;
-            return IPMI_CC_UNSPECIFIED_ERROR;
-        }
-    }
-    else if (reqptr->parameter ==
-             (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS)
-    {
-
-        int ret = setHostNetworkData(reqptr);
-        if (ret < 0)
-        {
             log<level::ERR>(
-                "setHostNetworkData failed for set_sys_boot_options");
-            rc = IPMI_CC_UNSPECIFIED_ERROR;
+                "ipmiChassisSetSysBootOptions: Error in setting Boot "
+                "flag parameters");
+            return ipmi::responseUnspecifiedError();
         }
     }
-    else if (reqptr->parameter ==
-             static_cast<uint8_t>(BootOptionParameter::BOOT_INFO))
+    else if (parameterSelector ==
+             static_cast<uint7_t>(BootOptionParameter::bootInfo))
     {
-        // Handle parameter #4 and return command completed normally
-        // (IPMI_CC_OK). There is no implementation in OpenBMC for this
+        uint8_t writeMak;
+        uint5_t bootInitiatorAckData;
+        uint3_t rsvd;
+
+        if (data.unpack(writeMak, bootInitiatorAckData, rsvd) != 0 ||
+            !data.fullyUnpacked())
+        {
+            return ipmi::responseReqDataLenInvalid();
+        }
+        if (rsvd)
+        {
+            return ipmi::responseInvalidFieldRequest();
+        }
+        // (ccSuccess). There is no implementation in OpenBMC for this
         // parameter. This is added to support the ipmitool command `chassis
         // bootdev` which sends set on parameter #4, before setting the boot
         // flags.
-        rc = IPMI_CC_OK;
+        log<level::INFO>("ipmiChassisSetSysBootOptions: bootInfo parameter set "
+                         "successfully");
+        data.trailingOk = true;
+        return ipmi::responseSuccess();
     }
     else
     {
-        log<level::ERR>("Unsupported parameter",
-                        entry("PARAM=0x%x", reqptr->parameter));
-        rc = IPMI_CC_PARM_NOT_SUPPORTED;
+        if ((parameterSelector >= static_cast<uint7_t>(oemParmStart)) &&
+            (parameterSelector <= static_cast<uint7_t>(oemParmEnd)))
+        {
+            if (parameterSelector ==
+                static_cast<uint7_t>(BootOptionParameter::opalNetworkSettings))
+            {
+                ipmi::Cc ret = setHostNetworkData(data);
+                if (ret != ipmi::ccSuccess)
+                {
+                    log<level::ERR>("ipmiChassisSetSysBootOptions: Error in "
+                                    "setHostNetworkData");
+                    data.trailingOk = true;
+                    return ipmi::response(ret);
+                }
+                data.trailingOk = true;
+                return ipmi::responseSuccess();
+            }
+            else
+            {
+                log<level::ERR>(
+                    "ipmiChassisSetSysBootOptions: Unsupported parameters",
+                    entry("PARAM=0x%x",
+                          static_cast<uint8_t>(parameterSelector)));
+                data.trailingOk = true;
+                return ipmi::responseParmNotSupported();
+            }
+        }
+        data.trailingOk = true;
+        return ipmi::responseParmNotSupported();
     }
-
-    return rc;
+    return ipmi::responseSuccess();
 }
 
 /** @brief implements Get POH counter command
@@ -2043,9 +2158,11 @@
                           ipmi::Privilege::Operator, ipmiChassisIdentify);
 
     // <Set System Boot Options>
-    ipmi_register_callback(NETFUN_CHASSIS, IPMI_CMD_SET_SYS_BOOT_OPTIONS, NULL,
-                           ipmi_chassis_set_sys_boot_options,
-                           PRIVILEGE_OPERATOR);
+    ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
+                          ipmi::chassis::cmdSetSystemBootOptions,
+                          ipmi::Privilege::Operator,
+                          ipmiChassisSetSysBootOptions);
+
     // <Get POH Counter>
     ipmi::registerHandler(ipmi::prioOpenBmcBase, ipmi::netFnChassis,
                           ipmi::chassis::cmdGetPohCounter,
diff --git a/chassishandler.hpp b/chassishandler.hpp
index dcaf06c..93de2c0 100644
--- a/chassishandler.hpp
+++ b/chassishandler.hpp
@@ -46,15 +46,15 @@
 };
 enum class BootOptionParameter : size_t
 {
-    BOOT_INFO = 0x4,
-    BOOT_FLAGS = 0x5,
-    OPAL_NETWORK_SETTINGS = 0x61
+    bootInfo = 0x4,
+    bootFlags = 0x5,
+    opalNetworkSettings = 0x61
 };
 
 enum class BootOptionResponseSize : size_t
 {
-    BOOT_FLAGS = 5,
-    OPAL_NETWORK_SETTINGS = 50
+    bootFlags = 5,
+    opalNetworkSettings = 50
 };
 
 enum class ChassisIDState : uint8_t