diff options
Diffstat (limited to 'meta-yadro/meta-nicole/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch')
-rw-r--r-- | meta-yadro/meta-nicole/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch | 477 |
1 files changed, 0 insertions, 477 deletions
diff --git a/meta-yadro/meta-nicole/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch b/meta-yadro/meta-nicole/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch deleted file mode 100644 index 922426ef4..000000000 --- a/meta-yadro/meta-nicole/recipes-phosphor/ipmi/phosphor-ipmi-host/0002-Add-support-for-boot-initiator-mailbox.patch +++ /dev/null @@ -1,477 +0,0 @@ -From f19ca89265616e14ba2bb16d9a5418f23157c943 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 - -Add handlers to process the chassis system option 7 -(boot initiator mailbox). The format of mailbox is -specific to the machine/bootloader. This commit only -adds generic handlers to process getting and setting -of the mailbox data regardless of the content. - -Only the IANA Enterprise number is checked in the data -block 0. Also checked are the data boundaries. - -It is expected that a machine-specific override for -phosphor-settingsd sets the supported state and -the IANA number according to the used bootloader. - -Resolves openbmc/openbmc#3391 - -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(-) - -diff --git a/chassishandler.cpp b/chassishandler.cpp -index 0326806..538154c 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 - { - - constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode"; -+constexpr auto bootMboxIntf = "xyz.openbmc_project.Control.Boot.Mailbox"; - 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() - if (objectsPtr == nullptr) - { - objectsPtr = std::make_unique<settings::Objects>( -- dbus, std::vector<std::string>{bootModeIntf, bootSourceIntf, -- powerRestoreIntf}); -+ dbus, std::vector<std::string>{bootMboxIntf, bootModeIntf, -+ bootSourceIntf, powerRestoreIntf}); - } - 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; - } - -+using MboxVec = std::vector<uint8_t>; -+ -+// Check if Boot Mailbox is supported. -+static std::optional<bool> isBootMboxSupported() -+{ -+ using namespace chassis::internal; -+ using namespace chassis::internal::cache; -+ -+ try -+ { -+ settings::Objects& objects = getObjects(); -+ auto bootMbox = settings::boot::setting(objects, bootMboxIntf); -+ const auto& bootMboxSetting = std::get<settings::Path>(bootMbox); -+ auto method = dbus.new_method_call( -+ objects.service(bootMboxSetting, bootMboxIntf).c_str(), -+ bootMboxSetting.c_str(), ipmi::PROP_INTF, "Get"); -+ -+ method.append(bootMboxIntf, "Supported"); -+ auto reply = dbus.call(method); -+ std::variant<bool> result; -+ reply.read(result); -+ return std::get<bool>(result); -+ } -+ catch (const std::exception& e) -+ { -+ log<level::ERR>("Error getting Boot/Mailbox/Supported", -+ entry("ERROR=%s", e.what())); -+ report<InternalFailure>(); -+ return std::nullopt; -+ } -+} -+ -+static std::optional<uint24_t> getBootMboxIANA() -+{ -+ using namespace chassis::internal; -+ using namespace chassis::internal::cache; -+ -+ try -+ { -+ settings::Objects& objects = getObjects(); -+ auto bootMbox = settings::boot::setting(objects, bootMboxIntf); -+ const auto& bootMboxSetting = std::get<settings::Path>(bootMbox); -+ auto method = dbus.new_method_call( -+ objects.service(bootMboxSetting, bootMboxIntf).c_str(), -+ bootMboxSetting.c_str(), ipmi::PROP_INTF, "Get"); -+ -+ method.append(bootMboxIntf, "IANAEnterpriseNumber"); -+ auto reply = dbus.call(method); -+ std::variant<uint32_t> result; -+ reply.read(result); -+ return std::get<uint32_t>(result); -+ } -+ catch (const std::exception& e) -+ { -+ log<level::ERR>("Error getting Boot/Mailbox/IANAEnterpriseNumber", -+ entry("ERROR=%s", e.what())); -+ report<InternalFailure>(); -+ return std::nullopt; -+ } -+} -+ -+static std::optional<MboxVec> getBootMbox() -+{ -+ using namespace chassis::internal; -+ using namespace chassis::internal::cache; -+ -+ try -+ { -+ settings::Objects& objects = getObjects(); -+ auto bootMbox = settings::boot::setting(objects, bootMboxIntf); -+ const auto& bootMboxSetting = std::get<settings::Path>(bootMbox); -+ auto method = dbus.new_method_call( -+ objects.service(bootMboxSetting, bootMboxIntf).c_str(), -+ bootMboxSetting.c_str(), ipmi::PROP_INTF, "Get"); -+ -+ method.append(bootMboxIntf, "Data"); -+ auto reply = dbus.call(method); -+ std::variant<MboxVec> result; -+ reply.read(result); -+ return std::get<MboxVec>(result); -+ } -+ catch (const std::exception& e) -+ { -+ log<level::ERR>("Error getting Boot/Mailbox/Data", -+ entry("ERROR=%s", e.what())); -+ report<InternalFailure>(); -+ return std::nullopt; -+ } -+} -+ -+static bool setBootMbox(MboxVec data) -+{ -+ using namespace chassis::internal; -+ using namespace chassis::internal::cache; -+ -+ try -+ { -+ settings::Objects& objects = getObjects(); -+ std::variant<MboxVec> property(data); -+ auto bootMbox = settings::boot::setting(objects, bootMboxIntf); -+ const auto& bootMboxSetting = std::get<settings::Path>(bootMbox); -+ auto method = dbus.new_method_call( -+ objects.service(bootMboxSetting, bootMboxIntf).c_str(), -+ bootMboxSetting.c_str(), ipmi::PROP_INTF, "Set"); -+ -+ method.append(bootMboxIntf, "Data", property); -+ dbus.call(method); -+ return true; -+ } -+ catch (const std::exception& e) -+ { -+ log<level::ERR>("Error setting Boot/Mailbox/Data", -+ entry("ERROR=%s", e.what())); -+ report<InternalFailure>(); -+ return false; -+ } -+} -+ - 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; - } - } -+ else if (reqptr->parameter == -+ static_cast<uint8_t>(BootOptionParameter::BOOT_INITIATOR_MBOX)) -+ { -+ // Only allow reading the boot initiator mailbox if Mailbox is supported -+ // -+ // Algorithm: -+ // 1. Get 'Supported' property from the Control.Boot.Mailbox interface -+ // 2. If {1} is 'false', report Parameter not supported (0x80) -+ // 3. Get Block Selector from request -+ // 4. Get 'Data' vector from Control.Boot.Mailbox -+ // 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; -+ } -+ -+ if (!*isSupported) -+ { -+ log<level::INFO>("Attempt to read unsupported Boot/Mailbox"); -+ return IPMI_CC_PARM_NOT_SUPPORTED; -+ } -+ 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); -+ -+ // Adjust pointers and sizes for block 0, and fill in the IANA PEN -+ if (0 == reqBlock) -+ { -+ ipmi::message::Payload tmpPayload; -+ std::optional<uint24_t> IANAEnterprise = getBootMboxIANA(); -+ if (!IANAEnterprise) -+ { -+ return IPMI_CC_INVALID; -+ } -+ tmpPayload.pack((uint32_t)*IANAEnterprise); -+ std::copy(tmpPayload.raw.begin(), tmpPayload.raw.end(), -+ rspMboxData->ipmiIANAEnterprise); -+ -+ rspBlockPtr = rspMboxData->blockZeroData; -+ blockDataSize = sizeof(rspMboxData->blockZeroData); -+ dataVecStartOffset = 0; -+ } -+ -+ // Get the total data size -+ std::optional<MboxVec> dataVec = getBootMbox(); -+ if (!dataVec) -+ { -+ return IPMI_CC_INVALID; -+ } -+ -+ // 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); -+ 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; -+ } -+ -+ // 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); -+ } -+ catch (InternalFailure& e) -+ { -+ report<InternalFailure>(); -+ return IPMI_CC_UNSPECIFIED_ERROR; -+ } -+ } - else if (reqptr->parameter == - static_cast<uint8_t>(BootOptionParameter::OPAL_NETWORK_SETTINGS)) - { -@@ -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; - -- /* 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; - } - } -+ else if (reqptr->parameter == -+ static_cast<uint8_t>(BootOptionParameter::BOOT_INITIATOR_MBOX)) -+ { -+ // Only allow writing to boot initiator mailbox if: -+ // 1. Mailbox is supported -+ // 2. IANA PEN matches. -+ // -+ // Algorithm: -+ // 1. Get 'Supported' property from Control.Boot.Mailbox interface -+ // 2. If {1} is 'false', report Parameter not supported (0x80) -+ // 3. Get Block Selector from request -+ // 4. Get 'Data' array from Control.Boot.Mailbox -+ // 5. If requested block {3} exceeds total vector size {4}, -+ // report Out of range (0xC9) -+ // 6. If requsted block {3} is 0: -+ // 4.1. Get IANA PEN from request -+ // 4.2. Get 'IANAEnterpriseNumber' property from Control.Boot.Mailbox -+ // 4.3. If {4.1} doesn't match {4.2}, report 0xCC error (Invalid -+ // data field in request) -+ // 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; -+ } -+ -+ if (!*isSupported) -+ { -+ log<level::INFO>("Attempt to read unsupported Boot/Mailbox"); -+ return IPMI_CC_PARM_NOT_SUPPORTED; -+ } -+ -+ // Requested block -+ IpmiValue reqBlock = reqMboxData->block; -+ -+ // 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); -+ -+ // 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) -+ { -+ return unpackError; -+ } -+ -+ std::optional<uint24_t> IANAEnterprise = getBootMboxIANA(); -+ if (!IANAEnterprise) -+ { -+ return IPMI_CC_INVALID; -+ } -+ -+ if (*IANAEnterprise != reqIANAEnterprise) -+ { -+ log<level::ERR>( -+ "Unsupported IANA Enterprise number", -+ entry("REQUESTED_IANA=%d", -+ static_cast<uint32_t>(reqIANAEnterprise)), -+ entry("SUPPORTED_IANA=%d", -+ static_cast<uint32_t>(*IANAEnterprise))); -+ return IPMI_CC_INVALID_FIELD_REQUEST; -+ } -+ -+ // For block 0 operate on data after IANA PEN -+ reqBlockPtr = reqMboxData->blockZeroData; -+ blockDataSize = sizeof(reqMboxData->blockZeroData); -+ dataVecStartOffset = 0; -+ } -+ -+ // Get the data vector from d-bus -+ std::optional<MboxVec> dataVec = getBootMbox(); -+ if (!dataVec) -+ { -+ return IPMI_CC_INVALID; -+ } -+ -+ // Does the requested block exist? -+ if ((*dataVec).size() < dataVecStartOffset + blockDataSize) -+ { -+ size_t total_size = -+ (*dataVec).size() + sizeof(reqMboxData->ipmiIANAEnterprise); -+ size_t normalBlockSize = sizeof(reqMboxData->data); -+ 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; -+ } -+ -+ // Copy the data from request to specified offset in d-bus vector -+ for (size_t i = 0; i < blockDataSize; ++i) -+ { -+ (*dataVec)[dataVecStartOffset + i] = reqBlockPtr[i]; -+ } -+ if (setBootMbox(*dataVec)) -+ { -+ rc = IPMI_CC_OK; -+ } -+ } -+ catch (InternalFailure& e) -+ { -+ report<InternalFailure>(); -+ return IPMI_CC_UNSPECIFIED_ERROR; -+ } -+ } - else if (reqptr->parameter == - (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) - { -diff --git a/chassishandler.hpp b/chassishandler.hpp -index dcaf06c..0e738e9 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 - { - BOOT_FLAGS = 5, -+ BOOT_INITIATOR_MBOX = 17, - OPAL_NETWORK_SETTINGS = 50 - }; - --- -2.21.1 - |