Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 1 | From ec6765e9aa35871f8d02cb0b5b47d96be18f4804 Mon Sep 17 00:00:00 2001 |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 2 | From: Alexander Amelkin <a.amelkin@yadro.com> |
| 3 | Date: Mon, 8 Apr 2019 17:58:42 +0300 |
| 4 | Subject: [PATCH] Add support for boot initiator mailbox |
| 5 | |
| 6 | Add handlers to process the chassis system option 7 |
| 7 | (boot initiator mailbox). The format of mailbox is |
| 8 | specific to the machine/bootloader. This commit only |
| 9 | adds generic handlers to process getting and setting |
| 10 | of the mailbox data regardless of the content. |
| 11 | |
| 12 | Only the IANA Enterprise number is checked in the data |
| 13 | block 0. Also checked are the data boundaries. |
| 14 | |
| 15 | It is expected that a machine-specific override for |
| 16 | phosphor-settingsd sets the supported state and |
| 17 | the IANA number according to the used bootloader. |
| 18 | |
| 19 | Resolves openbmc/openbmc#3391 |
| 20 | |
| 21 | Change-Id: Iccbf74c0775f20c70e8deaa7b0a8bd995ebbffea |
| 22 | Signed-off-by: Alexander Amelkin <a.amelkin@yadro.com> |
| 23 | Signed-off-by: Ivan Mikhaylov <i.mikhaylov@yadro.com> |
| 24 | --- |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 25 | chassishandler.cpp | 328 ++++++++++++++++++++++++++++++++++++++++++++- |
| 26 | chassishandler.hpp | 1 + |
| 27 | 2 files changed, 325 insertions(+), 4 deletions(-) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 28 | |
| 29 | diff --git a/chassishandler.cpp b/chassishandler.cpp |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 30 | index 3250b2c..48cda21 100644 |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 31 | --- a/chassishandler.cpp |
| 32 | +++ b/chassishandler.cpp |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 33 | @@ -136,6 +136,7 @@ namespace internal |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 34 | { |
| 35 | |
| 36 | constexpr auto bootModeIntf = "xyz.openbmc_project.Control.Boot.Mode"; |
| 37 | +constexpr auto bootMboxIntf = "xyz.openbmc_project.Control.Boot.Mailbox"; |
| 38 | constexpr auto bootSourceIntf = "xyz.openbmc_project.Control.Boot.Source"; |
| 39 | constexpr auto powerRestoreIntf = |
| 40 | "xyz.openbmc_project.Control.Power.RestorePolicy"; |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 41 | @@ -151,8 +152,8 @@ settings::Objects& getObjects() |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 42 | if (objectsPtr == nullptr) |
| 43 | { |
| 44 | objectsPtr = std::make_unique<settings::Objects>( |
| 45 | - dbus, std::vector<std::string>{bootModeIntf, bootSourceIntf, |
| 46 | - powerRestoreIntf}); |
| 47 | + dbus, std::vector<std::string>{bootMboxIntf, bootModeIntf, |
| 48 | + bootSourceIntf, powerRestoreIntf}); |
| 49 | } |
| 50 | return *objectsPtr; |
| 51 | } |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 52 | @@ -1670,6 +1671,127 @@ static ipmi::Cc setBootMode(const Mode::Modes& mode) |
| 53 | return ipmi::ccSuccess; |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 54 | } |
| 55 | |
| 56 | +using MboxVec = std::vector<uint8_t>; |
| 57 | + |
| 58 | +// Check if Boot Mailbox is supported. |
| 59 | +static std::optional<bool> isBootMboxSupported() |
| 60 | +{ |
| 61 | + using namespace chassis::internal; |
| 62 | + using namespace chassis::internal::cache; |
| 63 | + |
| 64 | + try |
| 65 | + { |
| 66 | + settings::Objects& objects = getObjects(); |
| 67 | + auto bootMbox = settings::boot::setting(objects, bootMboxIntf); |
| 68 | + const auto& bootMboxSetting = std::get<settings::Path>(bootMbox); |
| 69 | + auto method = dbus.new_method_call( |
| 70 | + objects.service(bootMboxSetting, bootMboxIntf).c_str(), |
| 71 | + bootMboxSetting.c_str(), ipmi::PROP_INTF, "Get"); |
| 72 | + |
| 73 | + method.append(bootMboxIntf, "Supported"); |
| 74 | + auto reply = dbus.call(method); |
| 75 | + std::variant<bool> result; |
| 76 | + reply.read(result); |
| 77 | + return std::get<bool>(result); |
| 78 | + } |
| 79 | + catch (const std::exception& e) |
| 80 | + { |
| 81 | + log<level::ERR>("Error getting Boot/Mailbox/Supported", |
| 82 | + entry("ERROR=%s", e.what())); |
| 83 | + report<InternalFailure>(); |
| 84 | + return std::nullopt; |
| 85 | + } |
| 86 | +} |
| 87 | + |
| 88 | +static std::optional<uint24_t> getBootMboxIANA() |
| 89 | +{ |
| 90 | + using namespace chassis::internal; |
| 91 | + using namespace chassis::internal::cache; |
| 92 | + |
| 93 | + try |
| 94 | + { |
| 95 | + settings::Objects& objects = getObjects(); |
| 96 | + auto bootMbox = settings::boot::setting(objects, bootMboxIntf); |
| 97 | + const auto& bootMboxSetting = std::get<settings::Path>(bootMbox); |
| 98 | + auto method = dbus.new_method_call( |
| 99 | + objects.service(bootMboxSetting, bootMboxIntf).c_str(), |
| 100 | + bootMboxSetting.c_str(), ipmi::PROP_INTF, "Get"); |
| 101 | + |
| 102 | + method.append(bootMboxIntf, "IANAEnterpriseNumber"); |
| 103 | + auto reply = dbus.call(method); |
| 104 | + std::variant<uint32_t> result; |
| 105 | + reply.read(result); |
| 106 | + return std::get<uint32_t>(result); |
| 107 | + } |
| 108 | + catch (const std::exception& e) |
| 109 | + { |
| 110 | + log<level::ERR>("Error getting Boot/Mailbox/IANAEnterpriseNumber", |
| 111 | + entry("ERROR=%s", e.what())); |
| 112 | + report<InternalFailure>(); |
| 113 | + return std::nullopt; |
| 114 | + } |
| 115 | +} |
| 116 | + |
| 117 | +static std::optional<MboxVec> getBootMbox() |
| 118 | +{ |
| 119 | + using namespace chassis::internal; |
| 120 | + using namespace chassis::internal::cache; |
| 121 | + |
| 122 | + try |
| 123 | + { |
| 124 | + settings::Objects& objects = getObjects(); |
| 125 | + auto bootMbox = settings::boot::setting(objects, bootMboxIntf); |
| 126 | + const auto& bootMboxSetting = std::get<settings::Path>(bootMbox); |
| 127 | + auto method = dbus.new_method_call( |
| 128 | + objects.service(bootMboxSetting, bootMboxIntf).c_str(), |
| 129 | + bootMboxSetting.c_str(), ipmi::PROP_INTF, "Get"); |
| 130 | + |
| 131 | + method.append(bootMboxIntf, "Data"); |
| 132 | + auto reply = dbus.call(method); |
| 133 | + std::variant<MboxVec> result; |
| 134 | + reply.read(result); |
| 135 | + return std::get<MboxVec>(result); |
| 136 | + } |
| 137 | + catch (const std::exception& e) |
| 138 | + { |
| 139 | + log<level::ERR>("Error getting Boot/Mailbox/Data", |
| 140 | + entry("ERROR=%s", e.what())); |
| 141 | + report<InternalFailure>(); |
| 142 | + return std::nullopt; |
| 143 | + } |
| 144 | +} |
| 145 | + |
| 146 | +static bool setBootMbox(MboxVec data) |
| 147 | +{ |
| 148 | + using namespace chassis::internal; |
| 149 | + using namespace chassis::internal::cache; |
| 150 | + |
| 151 | + try |
| 152 | + { |
| 153 | + settings::Objects& objects = getObjects(); |
| 154 | + std::variant<MboxVec> property(data); |
| 155 | + auto bootMbox = settings::boot::setting(objects, bootMboxIntf); |
| 156 | + const auto& bootMboxSetting = std::get<settings::Path>(bootMbox); |
| 157 | + auto method = dbus.new_method_call( |
| 158 | + objects.service(bootMboxSetting, bootMboxIntf).c_str(), |
| 159 | + bootMboxSetting.c_str(), ipmi::PROP_INTF, "Set"); |
| 160 | + |
| 161 | + method.append(bootMboxIntf, "Data", property); |
| 162 | + dbus.call(method); |
| 163 | + return true; |
| 164 | + } |
| 165 | + catch (const std::exception& e) |
| 166 | + { |
| 167 | + log<level::ERR>("Error setting Boot/Mailbox/Data", |
| 168 | + entry("ERROR=%s", e.what())); |
| 169 | + report<InternalFailure>(); |
| 170 | + return false; |
| 171 | + } |
| 172 | +} |
| 173 | + |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 174 | +static constexpr size_t normalBlockSize = 16; |
| 175 | +static constexpr size_t IANAEnterpriseLength = 3; |
| 176 | + |
| 177 | /** @brief implements the Get Chassis system boot option |
| 178 | * @param bootOptionParameter - boot option parameter selector |
| 179 | * @param reserved1 - reserved bit |
| 180 | @@ -1783,6 +1905,87 @@ ipmi::RspType<ipmi::message::Payload> |
| 181 | return ipmi::responseUnspecifiedError(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 182 | } |
| 183 | } |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 184 | + else if (static_cast<uint8_t>(bootOptionParameter) == |
| 185 | + static_cast<uint8_t>(BootOptionParameter::bootInitiatorMbox)) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 186 | + { |
| 187 | + // Only allow reading the boot initiator mailbox if Mailbox is supported |
| 188 | + // |
| 189 | + // Algorithm: |
| 190 | + // 1. Get 'Supported' property from the Control.Boot.Mailbox interface |
| 191 | + // 2. If {1} is 'false', report Parameter not supported (0x80) |
| 192 | + // 3. Get Block Selector from request |
| 193 | + // 4. Get 'Data' vector from Control.Boot.Mailbox |
| 194 | + // 5. If requested block {3} exceeds total vector size {4}, |
| 195 | + // report Out of space (0xC4) |
| 196 | + // 6. Return the selected block (16 bytes) from the vector |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 197 | + try |
| 198 | + { |
| 199 | + // Check whether this option is supported |
| 200 | + std::optional<bool> isSupported = isBootMboxSupported(); |
| 201 | + if (!isSupported) |
| 202 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 203 | + return ipmi::responseUnspecifiedError(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 204 | + } |
| 205 | + |
| 206 | + if (!*isSupported) |
| 207 | + { |
| 208 | + log<level::INFO>("Attempt to read unsupported Boot/Mailbox"); |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 209 | + return ipmi::responseParmNotSupported(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 210 | + } |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 211 | + |
| 212 | + // Initially assume it's block 1+ |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 213 | + std::optional<uint24_t> IANAEnterprise; |
| 214 | + size_t blockDataSize = normalBlockSize; |
| 215 | + size_t dataVecStartOffset = |
| 216 | + setSelector * normalBlockSize - IANAEnterpriseLength; |
| 217 | + |
| 218 | + response.pack(bootOptionParameter, reserved1, setSelector); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 219 | + |
| 220 | + // Adjust pointers and sizes for block 0, and fill in the IANA PEN |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 221 | + if (0 == setSelector) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 222 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 223 | + IANAEnterprise = getBootMboxIANA(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 224 | + if (!IANAEnterprise) |
| 225 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 226 | + return ipmi::responseInvalidCommand(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 227 | + } |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 228 | + |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 229 | + blockDataSize = normalBlockSize - IANAEnterpriseLength; |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 230 | + dataVecStartOffset = 0; |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 231 | + |
| 232 | + response.pack(*IANAEnterprise); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 233 | + } |
| 234 | + |
| 235 | + // Get the total data size |
| 236 | + std::optional<MboxVec> dataVec = getBootMbox(); |
| 237 | + if (!dataVec) |
| 238 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 239 | + return ipmi::responseInvalidCommand(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 240 | + } |
| 241 | + |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 242 | + if ((*dataVec).size() < dataVecStartOffset + blockDataSize) |
| 243 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 244 | + size_t totalSize = (*dataVec).size() + IANAEnterpriseLength; |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 245 | + log<level::ERR>( |
| 246 | + "Attempt to read unsupported block", |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 247 | + entry("REQUESTED_BLOCK=%d", setSelector), |
| 248 | + entry("MAX_BLOCK=%d", totalSize / normalBlockSize)); |
| 249 | + return ipmi::responseParmOutOfRange(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 250 | + } |
| 251 | + |
| 252 | + // Copy the data to response from specified offset in d-bus vector |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 253 | + response.append((*dataVec).data() + dataVecStartOffset, |
| 254 | + (*dataVec).data() + dataVecStartOffset + |
| 255 | + blockDataSize); |
| 256 | + |
| 257 | + return ipmi::responseSuccess(std::move(response)); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 258 | + } |
| 259 | + catch (InternalFailure& e) |
| 260 | + { |
| 261 | + report<InternalFailure>(); |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 262 | + return ipmi::responseUnspecifiedError(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 263 | + } |
| 264 | + } |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 265 | else |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 266 | { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 267 | if ((bootOptionParameter >= oemParmStart) && |
| 268 | @@ -1825,9 +2028,8 @@ ipmi::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx, |
| 269 | using namespace boot_options; |
| 270 | ipmi::Cc rc; |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 271 | |
| 272 | - /* 000101 |
| 273 | + /* |
| 274 | * Parameter #5 means boot flags. Please refer to 28.13 of ipmi doc. |
| 275 | - * This is the only parameter used by petitboot. |
| 276 | */ |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 277 | |
| 278 | if (parameterSelector == |
| 279 | @@ -1954,6 +2156,124 @@ ipmi::RspType<> ipmiChassisSetSysBootOptions(ipmi::Context::ptr ctx, |
| 280 | return ipmi::responseUnspecifiedError(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 281 | } |
| 282 | } |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 283 | + else if (parameterSelector == |
| 284 | + static_cast<uint7_t>(BootOptionParameter::bootInitiatorMbox)) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 285 | + { |
| 286 | + // Only allow writing to boot initiator mailbox if: |
| 287 | + // 1. Mailbox is supported |
| 288 | + // 2. IANA PEN matches. |
| 289 | + // |
| 290 | + // Algorithm: |
| 291 | + // 1. Get 'Supported' property from Control.Boot.Mailbox interface |
| 292 | + // 2. If {1} is 'false', report Parameter not supported (0x80) |
| 293 | + // 3. Get Block Selector from request |
| 294 | + // 4. Get 'Data' array from Control.Boot.Mailbox |
| 295 | + // 5. If requested block {3} exceeds total vector size {4}, |
| 296 | + // report Out of range (0xC9) |
| 297 | + // 6. If requsted block {3} is 0: |
| 298 | + // 4.1. Get IANA PEN from request |
| 299 | + // 4.2. Get 'IANAEnterpriseNumber' property from Control.Boot.Mailbox |
| 300 | + // 4.3. If {4.1} doesn't match {4.2}, report 0xCC error (Invalid |
| 301 | + // data field in request) |
| 302 | + // 7. Overwrite the 16 bytes at offset {3}*16 with the data from request |
| 303 | + // 8. Update the 'Data' array in Control.Boot.Mailbox |
| 304 | + |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 305 | + try |
| 306 | + { |
| 307 | + std::optional<bool> isSupported = isBootMboxSupported(); |
| 308 | + if (!isSupported) |
| 309 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 310 | + return ipmi::responseUnspecifiedError(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 311 | + } |
| 312 | + |
| 313 | + if (!*isSupported) |
| 314 | + { |
| 315 | + log<level::INFO>("Attempt to read unsupported Boot/Mailbox"); |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 316 | + return ipmi::responseParmNotSupported(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 317 | + } |
| 318 | + |
| 319 | + // Requested block |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 320 | + uint8_t reqBlock; |
| 321 | + if (data.unpack(reqBlock) != 0) |
| 322 | + { |
| 323 | + return ipmi::responseReqDataLenInvalid(); |
| 324 | + } |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 325 | + |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 326 | + // Initially assume it's blcok 1+ |
| 327 | + uint24_t reqIANAEnterprise; |
| 328 | + std::vector<uint8_t> blockData(normalBlockSize); |
| 329 | + size_t dataVecStartOffset = |
| 330 | + reqBlock * normalBlockSize - IANAEnterpriseLength; |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 331 | + |
| 332 | + // Adjust pointers and sizes for block 0, and fill in the IANA PEN |
| 333 | + if (0 == reqBlock) |
| 334 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 335 | + if (data.unpack(reqIANAEnterprise) != 0) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 336 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 337 | + return ipmi::responseReqDataLenInvalid(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 338 | + } |
| 339 | + |
| 340 | + std::optional<uint24_t> IANAEnterprise = getBootMboxIANA(); |
| 341 | + if (!IANAEnterprise) |
| 342 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 343 | + return ipmi::responseInvalidCommand(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 344 | + } |
| 345 | + |
| 346 | + if (*IANAEnterprise != reqIANAEnterprise) |
| 347 | + { |
| 348 | + log<level::ERR>( |
| 349 | + "Unsupported IANA Enterprise number", |
| 350 | + entry("REQUESTED_IANA=%d", |
| 351 | + static_cast<uint32_t>(reqIANAEnterprise)), |
| 352 | + entry("SUPPORTED_IANA=%d", |
| 353 | + static_cast<uint32_t>(*IANAEnterprise))); |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 354 | + return ipmi::responseInvalidFieldRequest(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 355 | + } |
| 356 | + |
| 357 | + // For block 0 operate on data after IANA PEN |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 358 | + blockData.resize(normalBlockSize - IANAEnterpriseLength); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 359 | + dataVecStartOffset = 0; |
| 360 | + } |
| 361 | + |
| 362 | + // Get the data vector from d-bus |
| 363 | + std::optional<MboxVec> dataVec = getBootMbox(); |
| 364 | + if (!dataVec) |
| 365 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 366 | + return ipmi::responseInvalidCommand(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 367 | + } |
| 368 | + |
| 369 | + // Does the requested block exist? |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 370 | + if ((*dataVec).size() < dataVecStartOffset + blockData.size()) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 371 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 372 | + size_t totalSize = (*dataVec).size() + IANAEnterpriseLength; |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 373 | + log<level::ERR>( |
| 374 | + "Attempt to read unsupported block", |
| 375 | + entry("REQUESTED_BLOCK=%d", reqBlock), |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 376 | + entry("MAX_BLOCK=%d", totalSize / normalBlockSize)); |
| 377 | + return ipmi::responseParmOutOfRange(); |
| 378 | + } |
| 379 | + |
| 380 | + if (data.unpack(blockData) != 0 || !data.fullyUnpacked()) |
| 381 | + { |
| 382 | + return ipmi::responseReqDataLenInvalid(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 383 | + } |
| 384 | + |
| 385 | + // Copy the data from request to specified offset in d-bus vector |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 386 | + for (size_t i = 0; i < blockData.size(); ++i) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 387 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 388 | + (*dataVec)[dataVecStartOffset + i] = blockData[i]; |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 389 | + } |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 390 | + if (!setBootMbox(*dataVec)) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 391 | + { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 392 | + return ipmi::responseUnspecifiedError(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 393 | + } |
| 394 | + } |
| 395 | + catch (InternalFailure& e) |
| 396 | + { |
| 397 | + report<InternalFailure>(); |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 398 | + return ipmi::responseUnspecifiedError(); |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 399 | + } |
| 400 | + } |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 401 | else if (parameterSelector == |
| 402 | static_cast<uint7_t>(BootOptionParameter::bootInfo)) |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 403 | { |
| 404 | diff --git a/chassishandler.hpp b/chassishandler.hpp |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 405 | index 93de2c0..33ad25f 100644 |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 406 | --- a/chassishandler.hpp |
| 407 | +++ b/chassishandler.hpp |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 408 | @@ -48,6 +48,7 @@ enum class BootOptionParameter : size_t |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 409 | { |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 410 | bootInfo = 0x4, |
| 411 | bootFlags = 0x5, |
| 412 | + bootInitiatorMbox = 0x07, |
| 413 | opalNetworkSettings = 0x61 |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 414 | }; |
| 415 | |
| 416 | -- |
Alexander Filippov | 916f828 | 2020-09-28 20:06:50 +0300 | [diff] [blame^] | 417 | 2.26.2 |
Ivan Mikhaylov | 4eeaf86 | 2020-06-30 19:53:07 +0300 | [diff] [blame] | 418 | |