diff options
Diffstat (limited to 'meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch')
-rw-r--r-- | meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch | 821 |
1 files changed, 821 insertions, 0 deletions
diff --git a/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch new file mode 100644 index 000000000..f6a9e9f35 --- /dev/null +++ b/meta-openbmc-mods/meta-common/recipes-phosphor/ipmi/phosphor-ipmi-host/0071-chassishandler-SetSystemBootOptions-to-new-API.patch @@ -0,0 +1,821 @@ +From 8133e8bd818f986a9c5d373b3c56683560103214 Mon Sep 17 00:00:00 2001 +From: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com> +Date: Thu, 3 Sep 2020 19:53:10 +0000 +Subject: [PATCH] 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: //Success + +Signed-off-by: srikanta mondal <srikantax.mondal@intel.com> +Signed-off-by: Jayaprakash Mutyala <mutyalax.jayaprakash@intel.com> + +%% original patch: 0071-chassishandler-SetSystemBootOptions-to-new-API.patch +--- + chassishandler.cpp | 465 +++++++++++++++++++++++++++++---------------- + chassishandler.hpp | 15 +- + 2 files changed, 305 insertions(+), 175 deletions(-) + +diff --git a/chassishandler.cpp b/chassishandler.cpp +index f5e7375..ca7cd2c 100644 +--- a/chassishandler.cpp ++++ b/chassishandler.cpp +@@ -35,37 +35,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; +- +-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; ++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_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 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 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 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; +@@ -75,6 +71,16 @@ static constexpr size_t chassisIdentifyReqLength = 2; + 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 +@@ -180,12 +186,6 @@ struct get_sys_boot_options_response_t + 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; +@@ -255,15 +255,15 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr) + } + } + +- 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"]) == +@@ -277,9 +277,9 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr) + + // 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)); + +@@ -298,10 +298,10 @@ int getHostNetworkData(get_sys_boot_options_response_t* respptr) + + // 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"); +@@ -361,19 +361,18 @@ std::string getAddrStr(uint8_t family, uint8_t* data, uint8_t offset, + 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 +@@ -384,13 +383,33 @@ int setHostNetworkData(set_sys_boot_options_t* reqptr) + 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()) ++ { ++ 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) + { +- // cookie == 0 +- if (memcmp(&(reqptr->data[COOKIE_OFFSET]), &zeroCookie, +- SIZE_COOKIE) == 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; +@@ -401,59 +420,106 @@ int setHostNetworkData(set_sys_boot_options_t* reqptr) + } + + // 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()); + +@@ -476,17 +542,17 @@ int setHostNetworkData(set_sys_boot_options_t* reqptr) + 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() +@@ -1444,7 +1510,7 @@ std::map<Mode::Modes, IpmiValue> modeDbusToIpmi = { + * @param[in] source - boot source value + * @return On failure return IPMI error. + */ +-static ipmi_ret_t setBootSource(const Source::Sources& source) ++static ipmi::Cc setBootSource(const Source::Sources& source) + { + using namespace chassis::internal; + using namespace chassis::internal::cache; +@@ -1461,16 +1527,16 @@ static ipmi_ret_t setBootSource(const Source::Sources& source) + { + log<level::ERR>("Error in BootSource Set"); + report<InternalFailure>(); +- return IPMI_CC_UNSPECIFIED_ERROR; ++ return ipmi::ccUnspecifiedError; + } +- return IPMI_CC_OK; ++ return ipmi::ccSuccess; + } + + /** @brief Set the property value for boot mode + * @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; +@@ -1487,9 +1553,9 @@ static ipmi_ret_t setBootMode(const Mode::Modes& mode) + { + log<level::ERR>("Error in BootMode Set"); + report<InternalFailure>(); +- return IPMI_CC_UNSPECIFIED_ERROR; ++ return ipmi::ccUnspecifiedError; + } +- return IPMI_CC_OK; ++ return ipmi::ccSuccess; + } + + static constexpr uint8_t setComplete = 0x0; +@@ -1511,29 +1577,28 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + IpmiValue bootOption = ipmiDefault; + + if (reqptr->parameter == +- static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS)) ++ static_cast<uint8_t>(BootOptionParameter::setInProgress)) + { +- *data_len = +- static_cast<uint8_t>(BootOptionResponseSize::SET_IN_PROGRESS); +- resp->version = SET_PARM_VERSION; +- resp->parm = static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS); ++ *data_len = static_cast<uint8_t>(BootOptionResponseSize::setInProgress); ++ resp->version = setParmVersion; ++ resp->parm = static_cast<uint8_t>(BootOptionParameter::setInProgress); + resp->data[0] = transferStatus; + return IPMI_CC_OK; + } + + 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; + +@@ -1592,9 +1657,8 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + } + 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; + } +@@ -1607,14 +1671,14 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + } + } + 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); + +@@ -1646,32 +1710,37 @@ ipmi_ret_t ipmi_chassis_get_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + 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; + +- if (reqptr->parameter == +- static_cast<uint8_t>(BootOptionParameter::SET_IN_PROGRESS)) ++ if (parameterSelector == ++ static_cast<uint7_t>(BootOptionParameter::setInProgress)) + { ++ uint2_t setStatus; ++ uint6_t rsvd; ++ ++ if (data.unpack(rsvd, setStatus) != 0 || !data.fullyUnpacked()) ++ { ++ return ipmi::responseReqDataLenInvalid(); ++ } ++ if (rsvd || setStatus != static_cast<uint2_t>(setComplete)) ++ { ++ return ipmi::responseInvalidFieldRequest(); ++ } + if ((transferStatus == setInProgress) && +- (reqptr->data[0] != setComplete)) ++ (static_cast<uint8_t>(setStatus) != setComplete)) + { +- return IPMI_CC_FAIL_SET_IN_PROGRESS; ++ constexpr ipmi::Cc ccFailSetInProgress = 0x81; ++ return ipmi::response(ccFailSetInProgress); + } +- transferStatus = reqptr->data[0]; +- return IPMI_CC_OK; ++ transferStatus = static_cast<uint8_t>(setStatus); ++ ++ return ipmi::responseSuccess(); + } + + /* 000101 +@@ -1679,9 +1748,37 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + * This is the only parameter used by petitboot. + */ + +- if (reqptr->parameter == (uint8_t)BootOptionParameter::BOOT_FLAGS) +- { +- IpmiValue bootOption = ((reqptr->data[1] & 0x3C) >> 2); ++ if (parameterSelector == ++ static_cast<uint7_t>(BootOptionParameter::bootFlags)) ++ { ++ 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; +@@ -1691,10 +1788,6 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + + 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); +@@ -1720,15 +1813,19 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + "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. +@@ -1742,10 +1839,11 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + 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. +@@ -1760,48 +1858,79 @@ ipmi_ret_t ipmi_chassis_set_sys_boot_options(ipmi_netfn_t netfn, ipmi_cmd_t cmd, + (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; ++ log<level::ERR>( ++ "ipmiChassisSetSysBootOptions: Error in setting Boot " ++ "flag parameters"); ++ return ipmi::responseUnspecifiedError(); + } + } +- else if (reqptr->parameter == +- (uint8_t)BootOptionParameter::OPAL_NETWORK_SETTINGS) ++ else if (parameterSelector == ++ static_cast<uint7_t>(BootOptionParameter::bootInfo)) + { ++ uint8_t writeMak; ++ uint5_t bootInitiatorAckData; ++ uint3_t rsvd; + +- int ret = setHostNetworkData(reqptr); +- if (ret < 0) ++ if (data.unpack(writeMak, bootInitiatorAckData, rsvd) != 0 || ++ !data.fullyUnpacked()) + { +- log<level::ERR>( +- "setHostNetworkData failed for set_sys_boot_options"); +- rc = IPMI_CC_UNSPECIFIED_ERROR; ++ return ipmi::responseReqDataLenInvalid(); + } +- } +- else if (reqptr->parameter == +- static_cast<uint8_t>(BootOptionParameter::BOOT_INFO)) +- { +- // Handle parameter #4 and return command completed normally +- // (IPMI_CC_OK). There is no implementation in OpenBMC for this ++ 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 +@@ -1963,9 +2092,11 @@ void register_netfn_chassis_functions() + 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 353a929..479563a 100644 +--- a/chassishandler.hpp ++++ b/chassishandler.hpp +@@ -25,7 +25,6 @@ enum ipmi_chassis_return_codes + { + IPMI_OK = 0x0, + IPMI_CC_PARM_NOT_SUPPORTED = 0x80, +- IPMI_CC_FAIL_SET_IN_PROGRESS = 0x81, + }; + + // Generic completion codes, +@@ -47,17 +46,17 @@ enum ipmi_chassis_control_cmds : uint8_t + }; + enum class BootOptionParameter : size_t + { +- SET_IN_PROGRESS = 0x0, +- BOOT_INFO = 0x4, +- BOOT_FLAGS = 0x5, +- OPAL_NETWORK_SETTINGS = 0x61 ++ setInProgress = 0x0, ++ bootInfo = 0x4, ++ bootFlags = 0x5, ++ opalNetworkSettings = 0x61 + }; + + enum class BootOptionResponseSize : size_t + { +- SET_IN_PROGRESS = 3, +- BOOT_FLAGS = 5, +- OPAL_NETWORK_SETTINGS = 50 ++ setInProgress = 3, ++ bootFlags = 5, ++ opalNetworkSettings = 50 + }; + + enum class ChassisIDState : uint8_t +-- +2.17.1 + |