1 /* 2 // Copyright (c) 2018 Intel Corporation 3 // 4 // Licensed under the Apache License, Version 2.0 (the "License"); 5 // you may not use this file except in compliance with the License. 6 // You may obtain a copy of the License at 7 // 8 // http://www.apache.org/licenses/LICENSE-2.0 9 // 10 // Unless required by applicable law or agreed to in writing, software 11 // distributed under the License is distributed on an "AS IS" BASIS, 12 // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 // See the License for the specific language governing permissions and 14 // limitations under the License. 15 */ 16 17 #include <errno.h> 18 #include <fcntl.h> 19 #include <limits.h> 20 #include <sys/stat.h> 21 #include <sys/types.h> 22 #include <unistd.h> 23 24 #include <commandutils.hpp> 25 #include <ipmid/api.hpp> 26 #include <ipmid/utils.hpp> 27 #include <oemcommands.hpp> 28 #include <phosphor-logging/log.hpp> 29 #include <sdbusplus/message/types.hpp> 30 #include <smbiosmdrv2handler.hpp> 31 #include <xyz/openbmc_project/Common/error.hpp> 32 33 #include <cstdint> 34 #include <fstream> 35 #include <string> 36 #include <vector> 37 38 std::unique_ptr<MDRV2> mdrv2 = nullptr; 39 static constexpr const uint8_t ccOemInvalidChecksum = 0x85; 40 static constexpr size_t dataInfoSize = 16; 41 static constexpr const uint8_t ccStorageLeak = 0xC4; 42 43 static void register_netfn_smbiosmdrv2_functions() __attribute__((constructor)); 44 agentLookup(const uint16_t & agentId)45 int MDRV2::agentLookup(const uint16_t& agentId) 46 { 47 int agentIndex = -1; 48 49 if (lastAgentId == agentId) 50 { 51 return lastAgentIndex; 52 } 53 54 if (agentId == smbiosAgentId) 55 { 56 return firstAgentIndex; 57 } 58 59 return agentIndex; 60 } 61 sdplusMdrv2GetProperty(const std::string & name,ipmi::DbusVariant & value,const std::string & service)62 int MDRV2::sdplusMdrv2GetProperty(const std::string& name, 63 ipmi::DbusVariant& value, 64 const std::string& service) 65 { 66 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 67 sdbusplus::message_t method = 68 bus->new_method_call(service.c_str(), mdrv2Path, dbusProperties, "Get"); 69 method.append(mdrv2Interface, name); 70 71 sdbusplus::message_t reply = bus->call(method); 72 73 try 74 { 75 sdbusplus::message_t reply = bus->call(method); 76 reply.read(value); 77 } 78 catch (const sdbusplus::exception_t& e) 79 { 80 phosphor::logging::log<phosphor::logging::level::ERR>( 81 "Error get property, sdbusplus call failed", 82 phosphor::logging::entry("ERROR=%s", e.what())); 83 return -1; 84 } 85 86 return 0; 87 } 88 syncDirCommonData(uint8_t idIndex,uint32_t size,const std::string & service)89 int MDRV2::syncDirCommonData(uint8_t idIndex, uint32_t size, 90 const std::string& service) 91 { 92 std::vector<uint32_t> commonData; 93 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 94 sdbusplus::message_t method = 95 bus->new_method_call(service.c_str(), mdrv2Path, mdrv2Interface, 96 "SynchronizeDirectoryCommonData"); 97 method.append(idIndex, size); 98 99 try 100 { 101 sdbusplus::message_t reply = bus->call(method); 102 reply.read(commonData); 103 } 104 catch (const sdbusplus::exception_t& e) 105 { 106 phosphor::logging::log<phosphor::logging::level::ERR>( 107 "Error sync dir common data with service", 108 phosphor::logging::entry("ERROR=%s", e.what())); 109 return -1; 110 } 111 112 if (commonData.size() < syncDirCommonSize) 113 { 114 phosphor::logging::log<phosphor::logging::level::ERR>( 115 "Error sync dir common data - data length invalid"); 116 return -1; 117 } 118 smbiosDir.dir[idIndex].common.dataSetSize = commonData.at(0); 119 smbiosDir.dir[idIndex].common.dataVersion = commonData.at(1); 120 smbiosDir.dir[idIndex].common.timestamp = commonData.at(2); 121 122 return 0; 123 } 124 findDataId(const uint8_t * dataInfo,const size_t & len,const std::string & service)125 int MDRV2::findDataId(const uint8_t* dataInfo, const size_t& len, 126 const std::string& service) 127 { 128 int idIndex = -1; 129 130 if (dataInfo == nullptr) 131 { 132 phosphor::logging::log<phosphor::logging::level::ERR>( 133 "Error dataInfo, input is null point"); 134 return -1; 135 } 136 137 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 138 sdbusplus::message_t method = bus->new_method_call( 139 service.c_str(), mdrv2Path, mdrv2Interface, "FindIdIndex"); 140 std::vector<uint8_t> info; 141 info.resize(len); 142 std::copy(dataInfo, dataInfo + len, info.data()); 143 method.append(info); 144 145 try 146 { 147 sdbusplus::message_t reply = bus->call(method); 148 reply.read(idIndex); 149 } 150 catch (const sdbusplus::exception_t& e) 151 { 152 phosphor::logging::log<phosphor::logging::level::ERR>( 153 "Error find id index", 154 phosphor::logging::entry("ERROR=%s", e.what()), 155 phosphor::logging::entry("SERVICE=%s", service.c_str()), 156 phosphor::logging::entry("PATH=%s", mdrv2Path)); 157 return -1; 158 } 159 160 return idIndex; 161 } 162 getSessionHandle(Mdr2DirStruct * dir)163 uint16_t MDRV2::getSessionHandle(Mdr2DirStruct* dir) 164 { 165 if (dir == NULL) 166 { 167 phosphor::logging::log<phosphor::logging::level::ERR>( 168 "Empty dir point"); 169 return 0; 170 } 171 dir->sessionHandle++; 172 if (dir->sessionHandle == 0) 173 { 174 dir->sessionHandle = 1; 175 } 176 177 return dir->sessionHandle; 178 } 179 findLockHandle(const uint16_t & lockHandle)180 int MDRV2::findLockHandle(const uint16_t& lockHandle) 181 { 182 int idIndex = -1; 183 184 for (int index = 0; index < smbiosDir.dirEntries; index++) 185 { 186 if (lockHandle == smbiosDir.dir[index].lockHandle) 187 { 188 return index; 189 } 190 } 191 192 return idIndex; 193 } 194 smbiosIsUpdating(uint8_t index)195 bool MDRV2::smbiosIsUpdating(uint8_t index) 196 { 197 if (index >= maxDirEntries) 198 { 199 return false; 200 } 201 if (smbiosDir.dir[index].stage == MDR2SMBIOSStatusEnum::mdr2Updating) 202 { 203 return true; 204 } 205 206 return false; 207 } 208 calcChecksum32(uint8_t * buf,uint32_t len)209 uint32_t MDRV2::calcChecksum32(uint8_t* buf, uint32_t len) 210 { 211 uint32_t sum = 0; 212 213 if (buf == nullptr) 214 { 215 return invalidChecksum; 216 } 217 218 for (uint32_t index = 0; index < len; index++) 219 { 220 sum += buf[index]; 221 } 222 223 return sum; 224 } 225 226 /** @brief implements mdr2 agent status command 227 * @param agentId 228 * @param dirVersion 229 * 230 * @returns IPMI completion code plus response data 231 * - mdrVersion 232 * - agentVersion 233 * - dirVersion 234 * - dirEntries 235 * - dataRequest 236 */ 237 ipmi::RspType<uint8_t, uint8_t, uint8_t, uint8_t, uint8_t> mdr2AgentStatus(uint16_t agentId,uint8_t dirVersion)238 mdr2AgentStatus(uint16_t agentId, uint8_t dirVersion) 239 { 240 if (mdrv2 == nullptr) 241 { 242 mdrv2 = std::make_unique<MDRV2>(); 243 } 244 245 int agentIndex = mdrv2->agentLookup(agentId); 246 if (agentIndex == -1) 247 { 248 phosphor::logging::log<phosphor::logging::level::ERR>( 249 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 250 return ipmi::responseParmOutOfRange(); 251 } 252 253 constexpr uint8_t mdrVersion = mdr2Version; 254 constexpr uint8_t agentVersion = smbiosAgentVersion; 255 uint8_t dirVersionResp = mdrv2->smbiosDir.dirVersion; 256 uint8_t dirEntries = mdrv2->smbiosDir.dirEntries; 257 uint8_t dataRequest; 258 259 if (mdrv2->smbiosDir.remoteDirVersion != dirVersion) 260 { 261 mdrv2->smbiosDir.remoteDirVersion = dirVersion; 262 dataRequest = 263 static_cast<uint8_t>(DirDataRequestEnum::dirDataRequested); 264 } 265 else 266 { 267 dataRequest = 268 static_cast<uint8_t>(DirDataRequestEnum::dirDataNotRequested); 269 } 270 271 return ipmi::responseSuccess(mdrVersion, agentVersion, dirVersionResp, 272 dirEntries, dataRequest); 273 } 274 275 /** @brief implements mdr2 get directory command 276 * @param agentId 277 * @param dirIndex 278 * @returns IPMI completion code plus response data 279 * - dataOut 280 */ 281 ipmi::RspType<std::vector<uint8_t>> mdr2GetDir(uint16_t agentId,uint8_t dirIndex)282 mdr2GetDir(uint16_t agentId, uint8_t dirIndex) 283 { 284 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 285 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path); 286 287 if (mdrv2 == nullptr) 288 { 289 mdrv2 = std::make_unique<MDRV2>(); 290 } 291 292 int agentIndex = mdrv2->agentLookup(agentId); 293 if (agentIndex == -1) 294 { 295 phosphor::logging::log<phosphor::logging::level::ERR>( 296 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 297 return ipmi::responseParmOutOfRange(); 298 } 299 300 ipmi::DbusVariant value = static_cast<uint8_t>(0); 301 if (0 != mdrv2->sdplusMdrv2GetProperty("DirectoryEntries", value, service)) 302 { 303 phosphor::logging::log<phosphor::logging::level::ERR>( 304 "Error getting DirEnries"); 305 return ipmi::responseUnspecifiedError(); 306 } 307 if (std::get<uint8_t>(value) == 0) 308 { 309 phosphor::logging::log<phosphor::logging::level::ERR>( 310 "Error getting directory entries", 311 phosphor::logging::entry("VALUE=%x", std::get<uint8_t>(value))); 312 return ipmi::responseUnspecifiedError(); 313 } 314 if (dirIndex > std::get<uint8_t>(value)) 315 { 316 return ipmi::responseParmOutOfRange(); 317 } 318 319 sdbusplus::message_t method = bus->new_method_call( 320 service.c_str(), mdrv2Path, mdrv2Interface, "GetDirectoryInformation"); 321 322 method.append(dirIndex); 323 324 std::vector<uint8_t> dataOut; 325 try 326 { 327 sdbusplus::message_t reply = bus->call(method); 328 reply.read(dataOut); 329 } 330 catch (const sdbusplus::exception_t& e) 331 { 332 phosphor::logging::log<phosphor::logging::level::ERR>( 333 "Error get dir", phosphor::logging::entry("ERROR=%s", e.what()), 334 phosphor::logging::entry("SERVICE=%s", service.c_str()), 335 phosphor::logging::entry("PATH=%s", mdrv2Path)); 336 return ipmi::responseResponseError(); 337 } 338 339 constexpr size_t getDirRespSize = 6; 340 if (dataOut.size() < getDirRespSize) 341 { 342 phosphor::logging::log<phosphor::logging::level::ERR>( 343 "Error get dir, response length invalid"); 344 return ipmi::responseUnspecifiedError(); 345 } 346 347 if (dataOut.size() > MAX_IPMI_BUFFER) // length + completion code should no 348 // more than MAX_IPMI_BUFFER 349 { 350 phosphor::logging::log<phosphor::logging::level::ERR>( 351 "Data length send from service is invalid"); 352 return ipmi::responseResponseError(); 353 } 354 355 return ipmi::responseSuccess(dataOut); 356 } 357 358 /** @brief implements mdr2 send directory info command 359 * @param agentId 360 * @param dirVersion 361 * @param dirIndex 362 * @param returnedEntries 363 * @param remainingEntries 364 * @param dataInfo 365 * dataInfo is 32 Bytes in size and contains below parameters 366 * - dataInfo, size, dataSetSize, dataVersion, timestamp 367 * 368 * @returns IPMI completion code plus response data 369 * - bool 370 */ 371 372 ipmi::RspType<bool> mdr2SendDir(uint16_t agentId,uint8_t dirVersion,uint8_t dirIndex,uint8_t returnedEntries,uint8_t remainingEntries,std::vector<uint8_t> dataInfo)373 mdr2SendDir(uint16_t agentId, uint8_t dirVersion, uint8_t dirIndex, 374 uint8_t returnedEntries, uint8_t remainingEntries, 375 std::vector<uint8_t> dataInfo) 376 { 377 if ((static_cast<size_t>(returnedEntries) * dataInfoSize) != 378 dataInfo.size()) 379 { 380 return ipmi::responseReqDataLenInvalid(); 381 } 382 383 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 384 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path); 385 386 if (mdrv2 == nullptr) 387 { 388 mdrv2 = std::make_unique<MDRV2>(); 389 } 390 391 int agentIndex = mdrv2->agentLookup(agentId); 392 if (agentIndex == -1) 393 { 394 phosphor::logging::log<phosphor::logging::level::ERR>( 395 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 396 return ipmi::responseParmOutOfRange(); 397 } 398 399 if ((dirIndex + returnedEntries) > maxDirEntries) 400 { 401 phosphor::logging::log<phosphor::logging::level::ERR>( 402 "Too many directory entries"); 403 return ipmi::response(ccStorageLeak); 404 } 405 406 sdbusplus::message_t method = bus->new_method_call( 407 service.c_str(), mdrv2Path, mdrv2Interface, "SendDirectoryInformation"); 408 method.append(dirVersion, dirIndex, returnedEntries, remainingEntries, 409 dataInfo); 410 411 bool terminate = false; 412 try 413 { 414 sdbusplus::message_t reply = bus->call(method); 415 reply.read(terminate); 416 } 417 catch (const sdbusplus::exception_t& e) 418 { 419 phosphor::logging::log<phosphor::logging::level::ERR>( 420 "Error send dir", phosphor::logging::entry("ERROR=%s", e.what()), 421 phosphor::logging::entry("SERVICE=%s", service.c_str()), 422 phosphor::logging::entry("PATH=%s", mdrv2Path)); 423 return ipmi::responseResponseError(); 424 } 425 426 return ipmi::responseSuccess(terminate); 427 } 428 429 /** @brief implements mdr2 get data info command 430 * @param agentId 431 * @param dataInfo 432 * 433 * @returns IPMI completion code plus response data 434 * - response - mdrVersion, data info, validFlag, 435 * dataLength, dataVersion, timeStamp 436 */ 437 ipmi::RspType<std::vector<uint8_t>> mdr2GetDataInfo(uint16_t agentId,std::vector<uint8_t> dataInfo)438 mdr2GetDataInfo(uint16_t agentId, std::vector<uint8_t> dataInfo) 439 { 440 constexpr size_t getDataInfoReqSize = 16; 441 442 if (dataInfo.size() < getDataInfoReqSize) 443 { 444 return ipmi::responseReqDataLenInvalid(); 445 } 446 447 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 448 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path); 449 450 if (mdrv2 == nullptr) 451 { 452 mdrv2 = std::make_unique<MDRV2>(); 453 } 454 455 int agentIndex = mdrv2->agentLookup(agentId); 456 if (agentIndex == -1) 457 { 458 phosphor::logging::log<phosphor::logging::level::ERR>( 459 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 460 return ipmi::responseParmOutOfRange(); 461 } 462 463 int idIndex = mdrv2->findDataId(dataInfo.data(), dataInfo.size(), service); 464 465 if ((idIndex < 0) || (idIndex >= maxDirEntries)) 466 { 467 phosphor::logging::log<phosphor::logging::level::ERR>( 468 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex)); 469 return ipmi::responseParmOutOfRange(); 470 } 471 472 sdbusplus::message_t method = bus->new_method_call( 473 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataInformation"); 474 475 method.append(static_cast<uint8_t>(idIndex)); 476 477 std::vector<uint8_t> res; 478 try 479 { 480 sdbusplus::message_t reply = bus->call(method); 481 reply.read(res); 482 } 483 catch (const sdbusplus::exception_t& e) 484 { 485 phosphor::logging::log<phosphor::logging::level::ERR>( 486 "Error get data info", 487 phosphor::logging::entry("ERROR=%s", e.what()), 488 phosphor::logging::entry("SERVICE=%s", service.c_str()), 489 phosphor::logging::entry("PATH=%s", mdrv2Path)); 490 return ipmi::responseResponseError(); 491 } 492 493 if (res.size() != sizeof(MDRiiGetDataInfoResponse)) 494 { 495 phosphor::logging::log<phosphor::logging::level::ERR>( 496 "Get data info response length not invalid"); 497 return ipmi::responseResponseError(); 498 } 499 500 return ipmi::responseSuccess(res); 501 } 502 503 /** @brief implements mdr2 data info offer command 504 * @param agentId - Offer a agent ID to get the "Data Set ID" 505 * 506 * @returns IPMI completion code plus response data 507 * - dataOut - data Set Id 508 */ mdr2DataInfoOffer(uint16_t agentId)509 ipmi::RspType<std::vector<uint8_t>> mdr2DataInfoOffer(uint16_t agentId) 510 { 511 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 512 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path); 513 514 if (mdrv2 == nullptr) 515 { 516 mdrv2 = std::make_unique<MDRV2>(); 517 } 518 519 int agentIndex = mdrv2->agentLookup(agentId); 520 if (agentIndex == -1) 521 { 522 phosphor::logging::log<phosphor::logging::level::ERR>( 523 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 524 return ipmi::responseParmOutOfRange(); 525 } 526 527 sdbusplus::message_t method = bus->new_method_call( 528 service.c_str(), mdrv2Path, mdrv2Interface, "GetDataOffer"); 529 530 std::vector<uint8_t> dataOut; 531 try 532 { 533 sdbusplus::message_t reply = bus->call(method); 534 reply.read(dataOut); 535 } 536 catch (const sdbusplus::exception_t& e) 537 { 538 phosphor::logging::log<phosphor::logging::level::ERR>( 539 "Error send data info offer", 540 phosphor::logging::entry("ERROR=%s", e.what()), 541 phosphor::logging::entry("SERVICE=%s", service.c_str()), 542 phosphor::logging::entry("PATH=%s", mdrv2Path)); 543 return ipmi::responseResponseError(); 544 } 545 546 constexpr size_t respInfoSize = 16; 547 if (dataOut.size() != respInfoSize) 548 { 549 phosphor::logging::log<phosphor::logging::level::ERR>( 550 "Error send data info offer, return length invalid"); 551 return ipmi::responseUnspecifiedError(); 552 } 553 554 return ipmi::responseSuccess(dataOut); 555 } 556 557 /** @brief implements mdr2 send data info command 558 * @param agentId 559 * @param dataInfo 560 * @param validFlag 561 * @param dataLength 562 * @param dataVersion 563 * @param timeStamp 564 * 565 * @returns IPMI completion code plus response data 566 * - bool 567 */ mdr2SendDataInfo(uint16_t agentId,std::array<uint8_t,dataInfoSize> dataInfo,uint8_t validFlag,uint32_t dataLength,uint32_t dataVersion,uint32_t timeStamp)568 ipmi::RspType<bool> mdr2SendDataInfo(uint16_t agentId, 569 std::array<uint8_t, dataInfoSize> dataInfo, 570 uint8_t validFlag, uint32_t dataLength, 571 uint32_t dataVersion, uint32_t timeStamp) 572 { 573 if (dataLength > smbiosTableStorageSize) 574 { 575 phosphor::logging::log<phosphor::logging::level::ERR>( 576 "Requested data length is out of SMBIOS Table storage size."); 577 return ipmi::responseParmOutOfRange(); 578 } 579 580 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 581 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path); 582 583 if (mdrv2 == nullptr) 584 { 585 mdrv2 = std::make_unique<MDRV2>(); 586 } 587 588 int agentIndex = mdrv2->agentLookup(agentId); 589 if (agentIndex == -1) 590 { 591 phosphor::logging::log<phosphor::logging::level::ERR>( 592 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 593 return ipmi::responseParmOutOfRange(); 594 } 595 596 int idIndex = mdrv2->findDataId(dataInfo.data(), dataInfo.size(), service); 597 598 if ((idIndex < 0) || (idIndex >= maxDirEntries)) 599 { 600 phosphor::logging::log<phosphor::logging::level::ERR>( 601 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex)); 602 return ipmi::responseParmOutOfRange(); 603 } 604 605 sdbusplus::message_t method = bus->new_method_call( 606 service.c_str(), mdrv2Path, mdrv2Interface, "SendDataInformation"); 607 608 method.append((uint8_t)idIndex, validFlag, dataLength, dataVersion, 609 timeStamp); 610 611 bool entryChanged = true; 612 try 613 { 614 sdbusplus::message_t reply = bus->call(method); 615 reply.read(entryChanged); 616 } 617 catch (const sdbusplus::exception_t& e) 618 { 619 phosphor::logging::log<phosphor::logging::level::ERR>( 620 "Error send data info", 621 phosphor::logging::entry("ERROR=%s", e.what()), 622 phosphor::logging::entry("SERVICE=%s", service.c_str()), 623 phosphor::logging::entry("PATH=%s", mdrv2Path)); 624 return ipmi::responseResponseError(); 625 } 626 627 return ipmi::responseSuccess(entryChanged); 628 } 629 630 /** 631 @brief This command is MDR related get data block command. 632 633 @param - agentId 634 @param - lockHandle 635 @param - xferOffset 636 @param - xferLength 637 638 @return on success 639 - xferLength 640 - checksum 641 - data 642 **/ 643 ipmi::RspType<uint32_t, // xferLength 644 uint32_t, // Checksum 645 std::vector<uint8_t> // data 646 > mdr2GetDataBlock(uint16_t agentId,uint16_t lockHandle,uint32_t xferOffset,uint32_t xferLength)647 mdr2GetDataBlock(uint16_t agentId, uint16_t lockHandle, uint32_t xferOffset, 648 uint32_t xferLength) 649 { 650 if (mdrv2 == nullptr) 651 { 652 mdrv2 = std::make_unique<MDRV2>(); 653 } 654 655 int agentIndex = mdrv2->agentLookup(agentId); 656 if (agentIndex == -1) 657 { 658 phosphor::logging::log<phosphor::logging::level::ERR>( 659 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 660 return ipmi::responseParmOutOfRange(); 661 } 662 663 int idIndex = mdrv2->findLockHandle(lockHandle); 664 665 if ((idIndex < 0) || (idIndex >= maxDirEntries)) 666 { 667 phosphor::logging::log<phosphor::logging::level::ERR>( 668 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex)); 669 return ipmi::responseParmOutOfRange(); 670 } 671 672 if (xferOffset >= mdrv2->smbiosDir.dir[idIndex].common.size) 673 { 674 phosphor::logging::log<phosphor::logging::level::ERR>( 675 "Offset is outside of range."); 676 return ipmi::responseParmOutOfRange(); 677 } 678 679 size_t outSize = (xferLength > mdrv2->smbiosDir.dir[idIndex].xferSize) 680 ? mdrv2->smbiosDir.dir[idIndex].xferSize 681 : xferLength; 682 if (outSize > UINT_MAX - xferOffset) 683 { 684 phosphor::logging::log<phosphor::logging::level::ERR>( 685 "Out size and offset are out of range"); 686 return ipmi::responseParmOutOfRange(); 687 } 688 if ((xferOffset + outSize) > mdrv2->smbiosDir.dir[idIndex].common.size) 689 { 690 outSize = mdrv2->smbiosDir.dir[idIndex].common.size - xferOffset; 691 } 692 693 uint32_t respXferLength = outSize; 694 695 if (respXferLength > xferLength) 696 { 697 phosphor::logging::log<phosphor::logging::level::ERR>( 698 "Get data block unexpected error."); 699 return ipmi::responseUnspecifiedError(); 700 } 701 702 if ((xferOffset + outSize) > 703 UINT_MAX - 704 reinterpret_cast<size_t>(mdrv2->smbiosDir.dir[idIndex].dataStorage)) 705 { 706 phosphor::logging::log<phosphor::logging::level::ERR>( 707 "Input data to calculate checksum is out of range"); 708 return ipmi::responseParmOutOfRange(); 709 } 710 711 uint32_t u32Checksum = mdrv2->calcChecksum32( 712 mdrv2->smbiosDir.dir[idIndex].dataStorage + xferOffset, outSize); 713 if (u32Checksum == invalidChecksum) 714 { 715 phosphor::logging::log<phosphor::logging::level::ERR>( 716 "Get data block failed - invalid checksum"); 717 return ipmi::response(ccOemInvalidChecksum); 718 } 719 std::vector<uint8_t> data(outSize); 720 721 std::copy(&mdrv2->smbiosDir.dir[idIndex].dataStorage[xferOffset], 722 &mdrv2->smbiosDir.dir[idIndex].dataStorage[xferOffset + outSize], 723 data.begin()); 724 725 return ipmi::responseSuccess(respXferLength, u32Checksum, data); 726 } 727 728 /** @brief implements mdr2 send data block command 729 * @param agentId 730 * @param lockHandle 731 * @param xferOffset 732 * @param xferLength 733 * @param checksum 734 * 735 * @returns IPMI completion code 736 */ mdr2SendDataBlock(uint16_t agentId,uint16_t lockHandle,uint32_t xferOffset,uint32_t xferLength,uint32_t checksum)737 ipmi::RspType<> mdr2SendDataBlock(uint16_t agentId, uint16_t lockHandle, 738 uint32_t xferOffset, uint32_t xferLength, 739 uint32_t checksum) 740 { 741 if (mdrv2 == nullptr) 742 { 743 mdrv2 = std::make_unique<MDRV2>(); 744 } 745 746 int agentIndex = mdrv2->agentLookup(agentId); 747 if (agentIndex == -1) 748 { 749 phosphor::logging::log<phosphor::logging::level::ERR>( 750 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 751 return ipmi::responseParmOutOfRange(); 752 } 753 754 int idIndex = mdrv2->findLockHandle(lockHandle); 755 756 if ((idIndex < 0) || (idIndex >= maxDirEntries)) 757 { 758 phosphor::logging::log<phosphor::logging::level::ERR>( 759 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex)); 760 return ipmi::responseParmOutOfRange(); 761 } 762 763 if (mdrv2->smbiosIsUpdating(idIndex)) 764 { 765 if (xferOffset > UINT_MAX - xferLength) 766 { 767 phosphor::logging::log<phosphor::logging::level::ERR>( 768 "Offset and length are out of range"); 769 return ipmi::responseParmOutOfRange(); 770 } 771 if (((xferOffset + xferLength) > 772 mdrv2->smbiosDir.dir[idIndex].maxDataSize) || 773 ((xferOffset + xferLength) > 774 mdrv2->smbiosDir.dir[idIndex].common.dataSetSize)) 775 { 776 phosphor::logging::log<phosphor::logging::level::ERR>( 777 "Send data block Invalid offset/length"); 778 return ipmi::responseReqDataLenExceeded(); 779 } 780 if (reinterpret_cast<size_t>( 781 mdrv2->smbiosDir.dir[idIndex].dataStorage) > 782 UINT_MAX - xferOffset) 783 { 784 phosphor::logging::log<phosphor::logging::level::ERR>( 785 "Offset is out of range"); 786 return ipmi::responseParmOutOfRange(); 787 } 788 uint8_t* destAddr = 789 mdrv2->smbiosDir.dir[idIndex].dataStorage + xferOffset; 790 uint8_t* sourceAddr = reinterpret_cast<uint8_t*>(mdrv2->area->vPtr); 791 uint32_t calcChecksum = mdrv2->calcChecksum32(sourceAddr, xferLength); 792 if (calcChecksum != checksum) 793 { 794 phosphor::logging::log<phosphor::logging::level::ERR>( 795 "Send data block Invalid checksum"); 796 return ipmi::response(ccOemInvalidChecksum); 797 } 798 else 799 { 800 if (reinterpret_cast<size_t>(sourceAddr) > UINT_MAX - xferLength) 801 { 802 phosphor::logging::log<phosphor::logging::level::ERR>( 803 "Length is out of range"); 804 return ipmi::responseParmOutOfRange(); 805 } 806 std::copy(sourceAddr, sourceAddr + xferLength, destAddr); 807 } 808 } 809 else 810 { 811 phosphor::logging::log<phosphor::logging::level::ERR>( 812 "Send data block failed, other data is updating"); 813 return ipmi::responseDestinationUnavailable(); 814 } 815 816 return ipmi::responseSuccess(); 817 } 818 storeDatatoFlash(MDRSMBIOSHeader * mdrHdr,uint8_t * data)819 bool MDRV2::storeDatatoFlash(MDRSMBIOSHeader* mdrHdr, uint8_t* data) 820 { 821 std::ofstream smbiosFile(mdrType2File, 822 std::ios_base::binary | std::ios_base::trunc); 823 if (!smbiosFile.good()) 824 { 825 phosphor::logging::log<phosphor::logging::level::ERR>( 826 "Write data from flash error - Open MDRV2 table file failure"); 827 return false; 828 } 829 830 try 831 { 832 smbiosFile.write(reinterpret_cast<char*>(mdrHdr), 833 sizeof(MDRSMBIOSHeader)); 834 smbiosFile.write(reinterpret_cast<char*>(data), mdrHdr->dataSize); 835 } 836 catch (const std::ofstream::failure& e) 837 { 838 phosphor::logging::log<phosphor::logging::level::ERR>( 839 "Write data from flash error - write data error", 840 phosphor::logging::entry("ERROR=%s", e.what())); 841 return false; 842 } 843 844 return true; 845 } 846 Initialize(uint32_t addr,uint32_t areaSize)847 void SharedMemoryArea::Initialize(uint32_t addr, uint32_t areaSize) 848 { 849 int memDriver = 0; 850 851 // open mem driver for the system memory access 852 memDriver = open("/dev/vgasharedmem", O_RDONLY); 853 if (memDriver < 0) 854 { 855 phosphor::logging::log<phosphor::logging::level::ERR>( 856 "Cannot access mem driver"); 857 throw std::system_error(EIO, std::generic_category()); 858 } 859 860 // map the system memory 861 vPtr = mmap(NULL, // where to map to: don't mind 862 areaSize, // how many bytes ? 863 PROT_READ, // want to read and write 864 MAP_SHARED, // no copy on write 865 memDriver, // handle to /dev/mem 866 (physicalAddr & pageMask)); // hopefully the Text-buffer :-) 867 868 close(memDriver); 869 if (vPtr == MAP_FAILED) 870 { 871 phosphor::logging::log<phosphor::logging::level::ERR>( 872 "Failed to map share memory"); 873 throw std::system_error(EIO, std::generic_category()); 874 } 875 size = areaSize; 876 physicalAddr = addr; 877 } 878 smbiosUnlock(uint8_t index)879 bool MDRV2::smbiosUnlock(uint8_t index) 880 { 881 bool ret = false; 882 switch (smbiosDir.dir[index].stage) 883 { 884 case MDR2SMBIOSStatusEnum::mdr2Updating: 885 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updated; 886 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock; 887 888 timer->stop(); 889 smbiosDir.dir[index].lockHandle = 0; 890 ret = true; 891 break; 892 893 case MDR2SMBIOSStatusEnum::mdr2Updated: 894 case MDR2SMBIOSStatusEnum::mdr2Loaded: 895 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock; 896 897 timer->stop(); 898 899 smbiosDir.dir[index].lockHandle = 0; 900 ret = true; 901 break; 902 903 default: 904 break; 905 } 906 907 return ret; 908 } 909 smbiosTryLock(uint8_t flag,uint8_t index,uint16_t * session,uint16_t timeout)910 bool MDRV2::smbiosTryLock(uint8_t flag, uint8_t index, uint16_t* session, 911 uint16_t timeout) 912 { 913 bool ret = false; 914 915 if (timeout == 0) 916 { 917 timeout = defaultTimeout; 918 } 919 std::chrono::microseconds usec(timeout * sysClock); 920 921 switch (smbiosDir.dir[index].stage) 922 { 923 case MDR2SMBIOSStatusEnum::mdr2Updating: 924 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock) 925 { 926 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock; 927 timer->start(usec); 928 lockIndex = index; 929 930 *session = getSessionHandle(&smbiosDir); 931 smbiosDir.dir[index].lockHandle = *session; 932 ret = true; 933 } 934 break; 935 case MDR2SMBIOSStatusEnum::mdr2Init: 936 if (flag) 937 { 938 smbiosDir.dir[index].stage = MDR2SMBIOSStatusEnum::mdr2Updating; 939 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock; 940 timer->start(usec); 941 lockIndex = index; 942 943 *session = getSessionHandle(&smbiosDir); 944 smbiosDir.dir[index].lockHandle = *session; 945 ret = true; 946 } 947 break; 948 949 case MDR2SMBIOSStatusEnum::mdr2Updated: 950 case MDR2SMBIOSStatusEnum::mdr2Loaded: 951 if (smbiosDir.dir[index].lock != MDR2DirLockEnum::mdr2DirLock) 952 { 953 if (flag) 954 { 955 smbiosDir.dir[index].stage = 956 MDR2SMBIOSStatusEnum::mdr2Updating; 957 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirUnlock; 958 } 959 else 960 { 961 smbiosDir.dir[index].lock = MDR2DirLockEnum::mdr2DirLock; 962 } 963 964 timer->start(usec); 965 lockIndex = index; 966 967 *session = getSessionHandle(&smbiosDir); 968 smbiosDir.dir[index].lockHandle = *session; 969 ret = true; 970 } 971 break; 972 973 default: 974 break; 975 } 976 return ret; 977 } 978 timeoutHandler()979 void MDRV2::timeoutHandler() 980 { 981 smbiosUnlock(lockIndex); 982 mdrv2->area.reset(nullptr); 983 } 984 985 /** @brief implements mdr2 lock data command 986 * @param agentId 987 * @param dataInfo 988 * @param timeout 989 * 990 * @returns IPMI completion code plus response data 991 * - mdr2Version 992 * - session 993 * - dataLength 994 * - xferAddress 995 * - xferLength 996 */ 997 ipmi::RspType<uint8_t, // mdr2Version 998 uint16_t, // session 999 uint32_t, // dataLength 1000 uint32_t, // xferAddress 1001 uint32_t // xferLength 1002 > mdr2LockData(uint16_t agentId,std::array<uint8_t,dataInfoSize> dataInfo,uint16_t timeout)1003 mdr2LockData(uint16_t agentId, std::array<uint8_t, dataInfoSize> dataInfo, 1004 uint16_t timeout) 1005 { 1006 if (mdrv2 == nullptr) 1007 { 1008 mdrv2 = std::make_unique<MDRV2>(); 1009 } 1010 1011 int agentIndex = mdrv2->agentLookup(agentId); 1012 if (agentIndex == -1) 1013 { 1014 phosphor::logging::log<phosphor::logging::level::ERR>( 1015 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 1016 return ipmi::responseParmOutOfRange(); 1017 } 1018 1019 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 1020 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path); 1021 1022 int idIndex = mdrv2->findDataId(dataInfo.data(), dataInfo.size(), service); 1023 1024 if ((idIndex < 0) || (idIndex >= maxDirEntries)) 1025 { 1026 phosphor::logging::log<phosphor::logging::level::ERR>( 1027 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex)); 1028 return ipmi::responseParmOutOfRange(); 1029 } 1030 1031 uint16_t session = 0; 1032 if (!mdrv2->smbiosTryLock(0, idIndex, &session, timeout)) 1033 { 1034 phosphor::logging::log<phosphor::logging::level::ERR>( 1035 "Lock Data failed - cannot lock idIndex"); 1036 return ipmi::responseCommandNotAvailable(); 1037 } 1038 1039 uint32_t dataLength = mdrv2->smbiosDir.dir[idIndex].common.size; 1040 uint32_t xferAddress = mdrv2->smbiosDir.dir[idIndex].xferBuff; 1041 uint32_t xferLength = mdrv2->smbiosDir.dir[idIndex].xferSize; 1042 1043 return ipmi::responseSuccess(mdr2Version, session, dataLength, xferAddress, 1044 xferLength); 1045 } 1046 1047 /** @brief implements mdr2 unlock data command 1048 * @param agentId 1049 * @param lockHandle 1050 * 1051 * @returns IPMI completion code 1052 */ mdr2UnlockData(uint16_t agentId,uint16_t lockHandle)1053 ipmi::RspType<> mdr2UnlockData(uint16_t agentId, uint16_t lockHandle) 1054 { 1055 phosphor::logging::log<phosphor::logging::level::ERR>("unlock data"); 1056 1057 if (mdrv2 == nullptr) 1058 { 1059 mdrv2 = std::make_unique<MDRV2>(); 1060 } 1061 1062 int agentIndex = mdrv2->agentLookup(agentId); 1063 if (agentIndex == -1) 1064 { 1065 phosphor::logging::log<phosphor::logging::level::ERR>( 1066 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 1067 return ipmi::responseParmOutOfRange(); 1068 } 1069 1070 int idIndex = mdrv2->findLockHandle(lockHandle); 1071 1072 if ((idIndex < 0) || (idIndex >= maxDirEntries)) 1073 { 1074 phosphor::logging::log<phosphor::logging::level::ERR>( 1075 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex)); 1076 return ipmi::responseParmOutOfRange(); 1077 } 1078 1079 if (!mdrv2->smbiosUnlock(idIndex)) 1080 { 1081 phosphor::logging::log<phosphor::logging::level::ERR>( 1082 "Unlock Data failed - cannot unlock idIndex"); 1083 return ipmi::responseCommandNotAvailable(); 1084 } 1085 1086 return ipmi::responseSuccess(); 1087 } 1088 1089 /** 1090 @brief This command is executed after POST BIOS to get the session info. 1091 1092 @param - agentId, dataInfo, dataLength, xferAddress, xferLength, timeout. 1093 1094 @return xferStartAck and session on success. 1095 **/ cmd_mdr2_data_start(uint16_t agentId,std::array<uint8_t,16> dataInfo,uint32_t dataLength,uint32_t xferAddress,uint32_t xferLength,uint16_t timeout)1096 ipmi::RspType<uint8_t, uint16_t> cmd_mdr2_data_start( 1097 uint16_t agentId, std::array<uint8_t, 16> dataInfo, uint32_t dataLength, 1098 uint32_t xferAddress, uint32_t xferLength, uint16_t timeout) 1099 { 1100 uint16_t session = 0; 1101 1102 if (dataLength > smbiosTableStorageSize) 1103 { 1104 phosphor::logging::log<phosphor::logging::level::ERR>( 1105 "Requested data length is out of SMBIOS Table storage size."); 1106 return ipmi::responseParmOutOfRange(); 1107 } 1108 if ((xferLength + xferAddress) > mdriiSMSize) 1109 { 1110 phosphor::logging::log<phosphor::logging::level::ERR>( 1111 "Invalid data address and size"); 1112 return ipmi::responseParmOutOfRange(); 1113 } 1114 1115 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 1116 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path); 1117 1118 if (mdrv2 == nullptr) 1119 { 1120 mdrv2 = std::make_unique<MDRV2>(); 1121 } 1122 1123 int agentIndex = mdrv2->agentLookup(agentId); 1124 if (agentIndex == -1) 1125 { 1126 phosphor::logging::log<phosphor::logging::level::ERR>( 1127 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 1128 return ipmi::responseParmOutOfRange(); 1129 } 1130 1131 int idIndex = mdrv2->findDataId(dataInfo.data(), dataInfo.size(), service); 1132 1133 if ((idIndex < 0) || (idIndex >= maxDirEntries)) 1134 { 1135 phosphor::logging::log<phosphor::logging::level::ERR>( 1136 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex)); 1137 return ipmi::responseParmOutOfRange(); 1138 } 1139 1140 if (mdrv2->smbiosTryLock(1, idIndex, &session, timeout)) 1141 { 1142 try 1143 { 1144 mdrv2->area = 1145 std::make_unique<SharedMemoryArea>(xferAddress, xferLength); 1146 } 1147 catch (const std::system_error& e) 1148 { 1149 mdrv2->smbiosUnlock(idIndex); 1150 phosphor::logging::log<phosphor::logging::level::ERR>( 1151 "Unable to access share memory", 1152 phosphor::logging::entry("ERROR=%s", e.what())); 1153 return ipmi::responseUnspecifiedError(); 1154 } 1155 mdrv2->smbiosDir.dir[idIndex].common.size = dataLength; 1156 mdrv2->smbiosDir.dir[idIndex].lockHandle = session; 1157 if (-1 == 1158 mdrv2->syncDirCommonData( 1159 idIndex, mdrv2->smbiosDir.dir[idIndex].common.size, service)) 1160 { 1161 phosphor::logging::log<phosphor::logging::level::ERR>( 1162 "Unable to sync data to service"); 1163 return ipmi::responseResponseError(); 1164 } 1165 } 1166 else 1167 { 1168 phosphor::logging::log<phosphor::logging::level::ERR>( 1169 "Canot lock smbios"); 1170 return ipmi::responseUnspecifiedError(); 1171 } 1172 1173 static constexpr uint8_t xferStartAck = 1; 1174 1175 return ipmi::responseSuccess(xferStartAck, session); 1176 } 1177 1178 /** 1179 @brief This command is executed to close the session. 1180 1181 @param - agentId, lockHandle. 1182 1183 @return completion code on success. 1184 **/ cmd_mdr2_data_done(uint16_t agentId,uint16_t lockHandle)1185 ipmi::RspType<> cmd_mdr2_data_done(uint16_t agentId, uint16_t lockHandle) 1186 { 1187 if (mdrv2 == nullptr) 1188 { 1189 mdrv2 = std::make_unique<MDRV2>(); 1190 } 1191 1192 int agentIndex = mdrv2->agentLookup(agentId); 1193 if (agentIndex == -1) 1194 { 1195 phosphor::logging::log<phosphor::logging::level::ERR>( 1196 "Unknown agent id", phosphor::logging::entry("ID=%x", agentId)); 1197 return ipmi::responseParmOutOfRange(); 1198 } 1199 1200 int idIndex = mdrv2->findLockHandle(lockHandle); 1201 1202 if ((idIndex < 0) || (idIndex >= maxDirEntries)) 1203 { 1204 phosphor::logging::log<phosphor::logging::level::ERR>( 1205 "Invalid Data ID", phosphor::logging::entry("IDINDEX=%x", idIndex)); 1206 return ipmi::responseParmOutOfRange(); 1207 } 1208 1209 if (!mdrv2->smbiosUnlock(idIndex)) 1210 { 1211 phosphor::logging::log<phosphor::logging::level::ERR>( 1212 "Send data done failed - cannot unlock idIndex"); 1213 return ipmi::responseDestinationUnavailable(); 1214 } 1215 1216 mdrv2->area.reset(nullptr); 1217 MDRSMBIOSHeader mdr2Smbios; 1218 mdr2Smbios.mdrType = mdrTypeII; 1219 mdr2Smbios.dirVer = mdrv2->smbiosDir.dir[0].common.dataVersion; 1220 mdr2Smbios.timestamp = mdrv2->smbiosDir.dir[0].common.timestamp; 1221 mdr2Smbios.dataSize = mdrv2->smbiosDir.dir[0].common.size; 1222 1223 if (access(smbiosPath, 0) == -1) 1224 { 1225 int flag = mkdir(smbiosPath, S_IRWXU); 1226 if (flag != 0) 1227 { 1228 phosphor::logging::log<phosphor::logging::level::ERR>( 1229 "create folder failed for writting smbios file"); 1230 } 1231 } 1232 if (!mdrv2->storeDatatoFlash( 1233 &mdr2Smbios, mdrv2->smbiosDir.dir[smbiosDirIndex].dataStorage)) 1234 { 1235 phosphor::logging::log<phosphor::logging::level::ERR>( 1236 "MDR2 Store data to flash failed"); 1237 return ipmi::responseDestinationUnavailable(); 1238 } 1239 bool status = false; 1240 std::shared_ptr<sdbusplus::asio::connection> bus = getSdBus(); 1241 std::string service = ipmi::getService(*bus, mdrv2Interface, mdrv2Path); 1242 sdbusplus::message_t method = bus->new_method_call( 1243 service.c_str(), mdrv2Path, mdrv2Interface, "AgentSynchronizeData"); 1244 1245 try 1246 { 1247 sdbusplus::message_t reply = bus->call(method); 1248 reply.read(status); 1249 } 1250 catch (const sdbusplus::exception_t& e) 1251 { 1252 phosphor::logging::log<phosphor::logging::level::ERR>( 1253 "Error Sync data with service", 1254 phosphor::logging::entry("ERROR=%s", e.what()), 1255 phosphor::logging::entry("SERVICE=%s", service.c_str()), 1256 phosphor::logging::entry("PATH=%s", mdrv2Path)); 1257 return ipmi::responseResponseError(); 1258 } 1259 1260 if (!status) 1261 { 1262 phosphor::logging::log<phosphor::logging::level::ERR>( 1263 "Sync data with service failure"); 1264 return ipmi::responseUnspecifiedError(); 1265 } 1266 1267 return ipmi::responseSuccess(); 1268 } 1269 register_netfn_smbiosmdrv2_functions(void)1270 static void register_netfn_smbiosmdrv2_functions(void) 1271 { 1272 // MDR V2 Command 1273 // <Get MDRII Status Command> 1274 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1275 ipmi::intel::app::cmdMdrIIAgentStatus, 1276 ipmi::Privilege::Operator, mdr2AgentStatus); 1277 1278 // <Get MDRII Directory Command> 1279 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1280 ipmi::intel::app::cmdMdrIIGetDir, 1281 ipmi::Privilege::Operator, mdr2GetDir); 1282 1283 // <Send MDRII Directory Command> 1284 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1285 ipmi::intel::app::cmdMdrIISendDir, 1286 ipmi::Privilege::Operator, mdr2SendDir); 1287 1288 // <Get MDRII Data Info Command> 1289 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1290 ipmi::intel::app::cmdMdrIIGetDataInfo, 1291 ipmi::Privilege::Operator, mdr2GetDataInfo); 1292 1293 // <Send MDRII Info Offer> 1294 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1295 ipmi::intel::app::cmdMdrIISendDataInfoOffer, 1296 ipmi::Privilege::Operator, mdr2DataInfoOffer); 1297 1298 // <Send MDRII Data Info> 1299 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1300 ipmi::intel::app::cmdMdrIISendDataInfo, 1301 ipmi::Privilege::Operator, mdr2SendDataInfo); 1302 1303 // <Get MDRII Data Block Command> 1304 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1305 ipmi::intel::app::cmdMdrIIGetDataBlock, 1306 ipmi::Privilege::Operator, mdr2GetDataBlock); 1307 1308 // <Send MDRII Data Block> 1309 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1310 ipmi::intel::app::cmdMdrIISendDataBlock, 1311 ipmi::Privilege::Operator, mdr2SendDataBlock); 1312 1313 // <Lock MDRII Data Command> 1314 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1315 ipmi::intel::app::cmdMdrIILockData, 1316 ipmi::Privilege::Operator, mdr2LockData); 1317 1318 // <Unlock MDRII Data Command> 1319 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1320 ipmi::intel::app::cmdMdrIIUnlockData, 1321 ipmi::Privilege::Operator, mdr2UnlockData); 1322 1323 // <Send MDRII Data Start> 1324 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1325 ipmi::intel::app::cmdMdrIIDataStart, 1326 ipmi::Privilege::Operator, cmd_mdr2_data_start); 1327 1328 // <Send MDRII Data Done> 1329 ipmi::registerHandler(ipmi::prioOemBase, ipmi::intel::netFnApp, 1330 ipmi::intel::app::cmdMdrIIDataDone, 1331 ipmi::Privilege::Operator, cmd_mdr2_data_done); 1332 } 1333