meta-yadro: ipmid: Fix bootmbox support

The phosphor-host-ipmid was modified by the upstream and our patch is
now conflicted with those changes.

This commit brings the refactored patch file and fixes the
phosphor-host-ipmid building.

(From meta-yadro rev: f0ea8198fe547003cb96f5c9c1d393fe0ef67bc4)

Change-Id: I670138248cd49955053dc594108b0c482df94efe
Signed-off-by: Alexander Filippov <a.filippov@yadro.com>
Signed-off-by: Andrew Geissler <geissonator@yahoo.com>
diff --git a/meta-yadro/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch b/meta-yadro/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch
index 922426e..dd76109 100644
--- a/meta-yadro/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch
+++ b/meta-yadro/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch
@@ -1,4 +1,4 @@
-From f19ca89265616e14ba2bb16d9a5418f23157c943 Mon Sep 17 00:00:00 2001
+From ec6765e9aa35871f8d02cb0b5b47d96be18f4804 Mon Sep 17 00:00:00 2001
 From: Alexander Amelkin <a.amelkin@yadro.com>
 Date: Mon, 8 Apr 2019 17:58:42 +0300
 Subject: [PATCH] Add support for boot initiator mailbox
@@ -22,23 +22,15 @@
 Signed-off-by: Alexander Amelkin <a.amelkin@yadro.com>
 Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com>
 ---
- chassishandler.cpp | 365 ++++++++++++++++++++++++++++++++++++++++++++-
- chassishandler.hpp |   2 +
- 2 files changed, 362 insertions(+), 5 deletions(-)
+ chassishandler.cpp | 328 ++++++++++++++++++++++++++++++++++++++++++++-
+ chassishandler.hpp |   1 +
+ 2 files changed, 325 insertions(+), 4 deletions(-)
 
 diff --git a/chassishandler.cpp b/chassishandler.cpp
-index 0326806..538154c 100644
+index 3250b2c..48cda21 100644
 --- a/chassishandler.cpp
 +++ b/chassishandler.cpp
-@@ -27,6 +27,7 @@
- #include <settings.hpp>
- #include <sstream>
- #include <string>
-+#include <vector>
- #include <xyz/openbmc_project/Common/error.hpp>
- #include <xyz/openbmc_project/Control/Boot/Mode/server.hpp>
- #include <xyz/openbmc_project/Control/Boot/Source/server.hpp>
-@@ -125,6 +126,7 @@ namespace internal
+@@ -136,6 +136,7 @@ namespace internal
  {
  
  constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode";
@@ -46,7 +38,7 @@
  constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source";
  constexpr auto powerRestoreIntf =
      "xyz.openbmc_project.Control.Power.RestorePolicy";
-@@ -140,8 +142,8 @@ settings::Objects& getObjects()
+@@ -151,8 +152,8 @@ settings::Objects& getObjects()
      if (objectsPtr == nullptr)
      {
          objectsPtr = std::make_unique<settings::Objects>(
@@ -57,29 +49,8 @@
      }
      return *objectsPtr;
  }
-@@ -177,6 +179,20 @@ struct set_sys_boot_options_t
-     uint8_t data[SIZE_BOOT_OPTION];
- } __attribute__((packed));
- 
-+struct BootMboxBlock
-+{
-+    uint8_t block;
-+    union
-+    {
-+        struct
-+        {
-+            uint8_t ipmiIANAEnterprise[3];
-+            uint8_t blockZeroData[13];
-+        };
-+        uint8_t data[16];
-+    };
-+} __attribute__((packed));
-+
- int getHostNetworkData(get_sys_boot_options_response_t* respptr)
- {
-     ipmi::PropertyMap properties;
-@@ -1443,6 +1459,124 @@ static ipmi_ret_t setBootMode(const Mode::Modes& mode)
-     return IPMI_CC_OK;
+@@ -1670,6 +1671,127 @@ static ipmi::Cc setBootMode(const Mode::Modes& mode)
+     return ipmi::ccSuccess;
  }
  
 +using MboxVec = std::vector<uint8_t>;
@@ -200,15 +171,18 @@
 +    }
 +}
 +
- ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-                                              ipmi_request_t request,
-                                              ipmi_response_t response,
-@@ -1543,6 +1677,106 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-             return IPMI_CC_UNSPECIFIED_ERROR;
++static constexpr size_t normalBlockSize = 16;
++static constexpr size_t IANAEnterpriseLength = 3;
++
+ /** @brief implements the Get Chassis system boot option
+  *  @param bootOptionParameter   - boot option parameter selector
+  *  @param reserved1    - reserved bit
+@@ -1783,6 +1905,87 @@ ipmi::RspType<ipmi::message::Payload>
+             return ipmi::responseUnspecifiedError();
          }
      }
-+    else if (reqptr->parameter ==
-+             static_cast<uint8_t>(BootOptionParameter::BOOT_INITIATOR_MBOX))
++    else if (static_cast<uint8_t>(bootOptionParameter) ==
++             static_cast<uint8_t>(BootOptionParameter::bootInitiatorMbox))
 +    {
 +        // Only allow reading the boot initiator mailbox if Mailbox is supported
 +        //
@@ -220,115 +194,94 @@
 +        // 5. If requested block {3} exceeds total vector size {4},
 +        //    report Out of space (0xC4)
 +        // 6. Return the selected block (16 bytes) from the vector
-+
-+        BootMboxBlock* rspMboxData =
-+            reinterpret_cast<BootMboxBlock*>(resp->data);
-+
-+        *data_len = 0; // Assume an error and no data
-+
-+        resp->parm =
-+            static_cast<uint8_t>(BootOptionParameter::BOOT_INITIATOR_MBOX);
-+
 +        try
 +        {
 +            // Check whether this option is supported
 +            std::optional<bool> isSupported = isBootMboxSupported();
 +            if (!isSupported)
 +            {
-+                return IPMI_CC_UNSPECIFIED_ERROR;
++                return ipmi::responseUnspecifiedError();
 +            }
 +
 +            if (!*isSupported)
 +            {
 +                log<level::INFO>("Attempt to read unsupported Boot/Mailbox");
-+                return IPMI_CC_PARM_NOT_SUPPORTED;
++                return ipmi::responseParmNotSupported();
 +            }
-+            rc = IPMI_CC_OK;
-+
-+            // Requested block
-+            IpmiValue reqBlock = reqptr->set; // Use "set selector"
-+            rspMboxData->block = reqBlock;
 +
 +            // Initially assume it's block 1+
-+            uint8_t* rspBlockPtr = rspMboxData->data;
-+            size_t blockDataSize = sizeof(rspMboxData->data);
-+            size_t dataVecStartOffset = reqBlock * blockDataSize -
-+                                        sizeof(rspMboxData->ipmiIANAEnterprise);
++            std::optional<uint24_t> IANAEnterprise;
++            size_t blockDataSize = normalBlockSize;
++            size_t dataVecStartOffset =
++                setSelector * normalBlockSize - IANAEnterpriseLength;
++
++            response.pack(bootOptionParameter, reserved1, setSelector);
 +
 +            // Adjust pointers and sizes for block 0, and fill in the IANA PEN
-+            if (0 == reqBlock)
++            if (0 == setSelector)
 +            {
-+                ipmi::message::Payload tmpPayload;
-+                std::optional<uint24_t> IANAEnterprise = getBootMboxIANA();
++                IANAEnterprise = getBootMboxIANA();
 +                if (!IANAEnterprise)
 +                {
-+                    return IPMI_CC_INVALID;
++                    return ipmi::responseInvalidCommand();
 +                }
-+                tmpPayload.pack((uint32_t)*IANAEnterprise);
-+                std::copy(tmpPayload.raw.begin(), tmpPayload.raw.end(),
-+                          rspMboxData->ipmiIANAEnterprise);
 +
-+                rspBlockPtr = rspMboxData->blockZeroData;
-+                blockDataSize = sizeof(rspMboxData->blockZeroData);
++                blockDataSize = normalBlockSize - IANAEnterpriseLength;
 +                dataVecStartOffset = 0;
++
++                response.pack(*IANAEnterprise);
 +            }
 +
 +            // Get the total data size
 +            std::optional<MboxVec> dataVec = getBootMbox();
 +            if (!dataVec)
 +            {
-+                return IPMI_CC_INVALID;
++                return ipmi::responseInvalidCommand();
 +            }
 +
-+            // Does the requested block exist?
 +            if ((*dataVec).size() < dataVecStartOffset + blockDataSize)
 +            {
-+                size_t total_size =
-+                    (*dataVec).size() + sizeof(rspMboxData->ipmiIANAEnterprise);
-+                size_t normalBlockSize = sizeof(rspMboxData->data);
++                size_t totalSize = (*dataVec).size() + IANAEnterpriseLength;
 +                log<level::ERR>(
 +                    "Attempt to read unsupported block",
-+                    entry("REQUESTED_BLOCK=%d", reqBlock),
-+                    entry("MAX_BLOCK=%d", total_size / normalBlockSize));
-+                return IPMI_CC_PARM_OUT_OF_RANGE;
++                    entry("REQUESTED_BLOCK=%d", setSelector),
++                    entry("MAX_BLOCK=%d", totalSize / normalBlockSize));
++                return ipmi::responseParmOutOfRange();
 +            }
 +
 +            // Copy the data to response from specified offset in d-bus vector
-+            for (size_t i = 0; i < blockDataSize; ++i)
-+            {
-+                rspBlockPtr[i] = (*dataVec)[dataVecStartOffset + i];
-+            }
-+            *data_len = static_cast<uint8_t>(
-+                BootOptionResponseSize::BOOT_INITIATOR_MBOX);
++            response.append((*dataVec).data() + dataVecStartOffset,
++                            (*dataVec).data() + dataVecStartOffset +
++                                blockDataSize);
++
++            return ipmi::responseSuccess(std::move(response));
 +        }
 +        catch (InternalFailure& e)
 +        {
 +            report<InternalFailure>();
-+            return IPMI_CC_UNSPECIFIED_ERROR;
++            return ipmi::responseUnspecifiedError();
 +        }
 +    }
-     else if (reqptr->parameter ==
-              static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS))
+     else
      {
-@@ -1599,11 +1833,9 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-     // This IPMI command does not have any resposne data
-     *data_len = 0;
+         if ((bootOptionParameter >= oemParmStart) &&
+@@ -1825,9 +2028,8 @@ ipmi::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx,
+     using namespace boot_options;
+     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)
-     {
-         IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2);
-@@ -1697,6 +1929,129 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd,
-             return IPMI_CC_UNSPECIFIED_ERROR;
+ 
+     if (parameterSelector ==
+@@ -1954,6 +2156,124 @@ ipmi::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx,
+             return ipmi::responseUnspecifiedError();
          }
      }
-+    else if (reqptr->parameter ==
-+             static_cast<uint8_t>(BootOptionParameter::BOOT_INITIATOR_MBOX))
++    else if (parameterSelector ==
++             static_cast<uint7_t>(BootOptionParameter::bootInitiatorMbox))
 +    {
 +        // Only allow writing to boot initiator mailbox if:
 +        // 1. Mailbox is supported
@@ -349,52 +302,45 @@
 +        // 7. Overwrite the 16 bytes at offset {3}*16 with the data from request
 +        // 8. Update the 'Data' array in Control.Boot.Mailbox
 +
-+        BootMboxBlock* reqMboxData =
-+            reinterpret_cast<BootMboxBlock*>(reqptr->data);
-+
 +        try
 +        {
 +            std::optional<bool> isSupported = isBootMboxSupported();
 +            if (!isSupported)
 +            {
-+                return IPMI_CC_UNSPECIFIED_ERROR;
++                return ipmi::responseUnspecifiedError();
 +            }
 +
 +            if (!*isSupported)
 +            {
 +                log<level::INFO>("Attempt to read unsupported Boot/Mailbox");
-+                return IPMI_CC_PARM_NOT_SUPPORTED;
++                return ipmi::responseParmNotSupported();
 +            }
 +
 +            // Requested block
-+            IpmiValue reqBlock = reqMboxData->block;
++            uint8_t reqBlock;
++            if (data.unpack(reqBlock) != 0)
++            {
++                return ipmi::responseReqDataLenInvalid();
++            }
 +
-+            // Initially assume it's block 1+
-+            uint8_t* reqBlockPtr = reqMboxData->data;
-+            size_t blockDataSize = sizeof(reqMboxData->data);
-+            size_t dataVecStartOffset = reqBlock * blockDataSize -
-+                                        sizeof(reqMboxData->ipmiIANAEnterprise);
++            // Initially assume it's blcok 1+
++            uint24_t reqIANAEnterprise;
++            std::vector<uint8_t> blockData(normalBlockSize);
++            size_t dataVecStartOffset =
++                reqBlock * normalBlockSize - IANAEnterpriseLength;
 +
 +            // Adjust pointers and sizes for block 0, and fill in the IANA PEN
 +            if (0 == reqBlock)
 +            {
-+                uint24_t reqIANAEnterprise;
-+                std::vector<uint8_t> tmp(
-+                    &reqMboxData->ipmiIANAEnterprise[0],
-+                    &reqMboxData->ipmiIANAEnterprise[0] +
-+                        sizeof(reqMboxData->ipmiIANAEnterprise));
-+                ipmi::message::Payload tmpPayload(
-+                    std::forward<std::vector<uint8_t>>(tmp));
-+                ipmi::Cc unpackError = tmpPayload.unpack(reqIANAEnterprise);
-+                if (unpackError != ipmi::ccSuccess)
++                if (data.unpack(reqIANAEnterprise) != 0)
 +                {
-+                    return unpackError;
++                    return ipmi::responseReqDataLenInvalid();
 +                }
 +
 +                std::optional<uint24_t> IANAEnterprise = getBootMboxIANA();
 +                if (!IANAEnterprise)
 +                {
-+                    return IPMI_CC_INVALID;
++                    return ipmi::responseInvalidCommand();
 +                }
 +
 +                if (*IANAEnterprise != reqIANAEnterprise)
@@ -405,12 +351,11 @@
 +                              static_cast<uint32_t>(reqIANAEnterprise)),
 +                        entry("SUPPORTED_IANA=%d",
 +                              static_cast<uint32_t>(*IANAEnterprise)));
-+                    return IPMI_CC_INVALID_FIELD_REQUEST;
++                    return ipmi::responseInvalidFieldRequest();
 +                }
 +
 +                // For block 0 operate on data after IANA PEN
-+                reqBlockPtr = reqMboxData->blockZeroData;
-+                blockDataSize = sizeof(reqMboxData->blockZeroData);
++                blockData.resize(normalBlockSize - IANAEnterpriseLength);
 +                dataVecStartOffset = 0;
 +            }
 +
@@ -418,60 +363,56 @@
 +            std::optional<MboxVec> dataVec = getBootMbox();
 +            if (!dataVec)
 +            {
-+                return IPMI_CC_INVALID;
++                return ipmi::responseInvalidCommand();
 +            }
 +
 +            // Does the requested block exist?
-+            if ((*dataVec).size() < dataVecStartOffset + blockDataSize)
++            if ((*dataVec).size() < dataVecStartOffset + blockData.size())
 +            {
-+                size_t total_size =
-+                    (*dataVec).size() + sizeof(reqMboxData->ipmiIANAEnterprise);
-+                size_t normalBlockSize = sizeof(reqMboxData->data);
++                size_t totalSize = (*dataVec).size() + IANAEnterpriseLength;
 +                log<level::ERR>(
 +                    "Attempt to read unsupported block",
 +                    entry("REQUESTED_BLOCK=%d", reqBlock),
-+                    entry("MAX_BLOCK=%d", total_size / normalBlockSize));
-+                return IPMI_CC_PARM_OUT_OF_RANGE;
++                    entry("MAX_BLOCK=%d", totalSize / normalBlockSize));
++                return ipmi::responseParmOutOfRange();
++            }
++
++            if (data.unpack(blockData) != 0 || !data.fullyUnpacked())
++            {
++                return ipmi::responseReqDataLenInvalid();
 +            }
 +
 +            // Copy the data from request to specified offset in d-bus vector
-+            for (size_t i = 0; i < blockDataSize; ++i)
++            for (size_t i = 0; i < blockData.size(); ++i)
 +            {
-+                (*dataVec)[dataVecStartOffset + i] = reqBlockPtr[i];
++                (*dataVec)[dataVecStartOffset + i] = blockData[i];
 +            }
-+            if (setBootMbox(*dataVec))
++            if (!setBootMbox(*dataVec))
 +            {
-+                rc = IPMI_CC_OK;
++                return ipmi::responseUnspecifiedError();
 +            }
 +        }
 +        catch (InternalFailure& e)
 +        {
 +            report<InternalFailure>();
-+            return IPMI_CC_UNSPECIFIED_ERROR;
++            return ipmi::responseUnspecifiedError();
 +        }
 +    }
-     else if (reqptr->parameter ==
-              (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS)
+     else if (parameterSelector ==
+              static_cast<uint7_t>(BootOptionParameter::bootInfo))
      {
 diff --git a/chassishandler.hpp b/chassishandler.hpp
-index dcaf06c..0e738e9 100644
+index 93de2c0..33ad25f 100644
 --- a/chassishandler.hpp
 +++ b/chassishandler.hpp
-@@ -48,12 +48,14 @@ enum class BootOptionParameter : size_t
+@@ -48,6 +48,7 @@ enum class BootOptionParameter : size_t
  {
-     BOOT_INFO = 0x4,
-     BOOT_FLAGS = 0x5,
-+    BOOT_INITIATOR_MBOX = 0x07,
-     OPAL_NETWORK_SETTINGS = 0x61
- };
- 
- enum class BootOptionResponseSize : size_t
- {
-     BOOT_FLAGS = 5,
-+    BOOT_INITIATOR_MBOX = 17,
-     OPAL_NETWORK_SETTINGS = 50
+     bootInfo = 0x4,
+     bootFlags = 0x5,
++    bootInitiatorMbox = 0x07,
+     opalNetworkSettings = 0x61
  };
  
 -- 
-2.21.1
+2.26.2