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