diff options
Diffstat (limited to 'meta-yadro/recipes-phosphor')
-rw-r--r-- | meta-yadro/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch | 251 |
1 files changed, 96 insertions, 155 deletions
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 922426ef4..dd7610975 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 @@ Change-Id: Iccbf74c0775f20c70e8deaa7b0a8bd995ebbffea 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 @@ index 0326806..538154c 100644 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 @@ index 0326806..538154c 100644 } 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 @@ index 0326806..538154c 100644 + } +} + - 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 @@ index 0326806..538154c 100644 + // 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 @@ index 0326806..538154c 100644 + // 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 @@ index 0326806..538154c 100644 + 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 @@ index 0326806..538154c 100644 + 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 - { - BOOT_INFO = 0x4, - BOOT_FLAGS = 0x5, -+ BOOT_INITIATOR_MBOX = 0x07, - OPAL_NETWORK_SETTINGS = 0x61 - }; - - enum class BootOptionResponseSize : size_t +@@ -48,6 +48,7 @@ enum class BootOptionParameter : 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 |