1 #include "config.h" 2 3 #include "file_io.hpp" 4 5 #include "file_io_by_type.hpp" 6 #include "file_table.hpp" 7 #include "utils.hpp" 8 #include "xyz/openbmc_project/Common/error.hpp" 9 10 #include <fcntl.h> 11 #include <libpldm/base.h> 12 #include <sys/mman.h> 13 #include <sys/stat.h> 14 #include <sys/types.h> 15 #include <unistd.h> 16 17 #include <cstring> 18 #include <fstream> 19 #include <iostream> 20 #include <memory> 21 22 namespace pldm 23 { 24 using namespace pldm::responder::utils; 25 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 26 27 namespace responder 28 { 29 namespace fs = std::filesystem; 30 31 namespace dma 32 { 33 /** @struct AspeedXdmaOp 34 * 35 * Structure representing XDMA operation 36 */ 37 struct AspeedXdmaOp 38 { 39 uint64_t hostAddr; //!< the DMA address on the host side, configured by 40 //!< PCI subsystem. 41 uint32_t len; //!< the size of the transfer in bytes, it should be a 42 //!< multiple of 16 bytes 43 uint32_t upstream; //!< boolean indicating the direction of the DMA 44 //!< operation, true means a transfer from BMC to host. 45 }; 46 47 constexpr auto xdmaDev = "/dev/aspeed-xdma"; 48 49 int DMA::transferHostDataToSocket(int fd, uint32_t length, uint64_t address) 50 { 51 static const size_t pageSize = getpagesize(); 52 uint32_t numPages = length / pageSize; 53 uint32_t pageAlignedLength = numPages * pageSize; 54 55 if (length > pageAlignedLength) 56 { 57 pageAlignedLength += pageSize; 58 } 59 60 auto mmapCleanup = [pageAlignedLength](void* vgaMem) { 61 munmap(vgaMem, pageAlignedLength); 62 }; 63 64 int dmaFd = -1; 65 int rc = 0; 66 dmaFd = open(xdmaDev, O_RDWR); 67 if (dmaFd < 0) 68 { 69 rc = -errno; 70 std::cerr << "transferHostDataToSocket: Failed to open the XDMA device," 71 " RC=" 72 << rc << "\n"; 73 return rc; 74 } 75 76 pldm::utils::CustomFD xdmaFd(dmaFd); 77 78 void* vgaMem; 79 vgaMem = 80 mmap(nullptr, pageAlignedLength, PROT_READ, MAP_SHARED, xdmaFd(), 0); 81 if (MAP_FAILED == vgaMem) 82 { 83 rc = -errno; 84 std::cerr << "transferHostDataToSocket: Failed to mmap the XDMA device," 85 " RC=" 86 << rc << "\n"; 87 return rc; 88 } 89 90 std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup); 91 92 AspeedXdmaOp xdmaOp; 93 xdmaOp.upstream = 0; 94 xdmaOp.hostAddr = address; 95 xdmaOp.len = length; 96 97 rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp)); 98 if (rc < 0) 99 { 100 rc = -errno; 101 std::cerr << "transferHostDataToSocket: Failed to execute the DMA " 102 "operation, RC=" 103 << rc << " ADDRESS=" << address << " LENGTH=" << length 104 << "\n"; 105 return rc; 106 } 107 108 rc = writeToUnixSocket(fd, static_cast<const char*>(vgaMemPtr.get()), 109 length); 110 if (rc < 0) 111 { 112 rc = -errno; 113 close(fd); 114 std::cerr << "transferHostDataToSocket: Closing socket as " 115 "writeToUnixSocket faile with RC=" 116 << rc << std::endl; 117 return rc; 118 } 119 return 0; 120 } 121 122 int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length, 123 uint64_t address, bool upstream) 124 { 125 static const size_t pageSize = getpagesize(); 126 uint32_t numPages = length / pageSize; 127 uint32_t pageAlignedLength = numPages * pageSize; 128 129 if (length > pageAlignedLength) 130 { 131 pageAlignedLength += pageSize; 132 } 133 134 int rc = 0; 135 auto mmapCleanup = [pageAlignedLength, &rc](void* vgaMem) { 136 if (rc != -EINTR) 137 { 138 munmap(vgaMem, pageAlignedLength); 139 } 140 else 141 { 142 std::cerr 143 << "transferDataHost: Received interrupt during DMA transfer." 144 " Skipping Unmap." 145 << std::endl; 146 } 147 }; 148 149 int dmaFd = -1; 150 dmaFd = open(xdmaDev, O_RDWR); 151 if (dmaFd < 0) 152 { 153 rc = -errno; 154 std::cerr << "transferDataHost: Failed to open the XDMA device, RC=" 155 << rc << "\n"; 156 return rc; 157 } 158 159 pldm::utils::CustomFD xdmaFd(dmaFd); 160 161 void* vgaMem; 162 vgaMem = mmap(nullptr, pageAlignedLength, upstream ? PROT_WRITE : PROT_READ, 163 MAP_SHARED, xdmaFd(), 0); 164 if (MAP_FAILED == vgaMem) 165 { 166 rc = -errno; 167 std::cerr << "transferDataHost: Failed to mmap the XDMA device, RC=" 168 << rc << "\n"; 169 return rc; 170 } 171 172 std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup); 173 174 if (upstream) 175 { 176 rc = lseek(fd, offset, SEEK_SET); 177 if (rc == -1) 178 { 179 std::cerr << "transferDataHost upstream: lseek failed, ERROR=" 180 << errno << ", UPSTREAM=" << upstream 181 << ", OFFSET=" << offset << "\n"; 182 return rc; 183 } 184 185 // Writing to the VGA memory should be aligned at page boundary, 186 // otherwise write data into a buffer aligned at page boundary and 187 // then write to the VGA memory. 188 std::vector<char> buffer{}; 189 buffer.resize(pageAlignedLength); 190 rc = read(fd, buffer.data(), length); 191 if (rc == -1) 192 { 193 std::cerr << "transferDataHost upstream: file read failed, ERROR=" 194 << errno << ", UPSTREAM=" << upstream 195 << ", LENGTH=" << length << ", OFFSET=" << offset << "\n"; 196 return rc; 197 } 198 if (rc != static_cast<int>(length)) 199 { 200 std::cerr << "transferDataHost upstream: mismatch between number of" 201 << "characters to read and the length read, LENGTH=" 202 << length << " COUNT=" << rc << "\n"; 203 return -1; 204 } 205 memcpy(static_cast<char*>(vgaMemPtr.get()), buffer.data(), 206 pageAlignedLength); 207 } 208 209 AspeedXdmaOp xdmaOp; 210 xdmaOp.upstream = upstream ? 1 : 0; 211 xdmaOp.hostAddr = address; 212 xdmaOp.len = length; 213 214 rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp)); 215 if (rc < 0) 216 { 217 rc = -errno; 218 std::cerr << "transferDataHost: Failed to execute the DMA operation," 219 " RC=" 220 << rc << " UPSTREAM=" << upstream << " ADDRESS=" << address 221 << " LENGTH=" << length << "\n"; 222 return rc; 223 } 224 225 if (!upstream) 226 { 227 rc = lseek(fd, offset, SEEK_SET); 228 if (rc == -1) 229 { 230 std::cerr << "transferDataHost downstream: lseek failed, ERROR=" 231 << errno << ", UPSTREAM=" << upstream 232 << ", OFFSET=" << offset << "\n"; 233 return rc; 234 } 235 rc = write(fd, static_cast<const char*>(vgaMemPtr.get()), length); 236 if (rc == -1) 237 { 238 std::cerr << "transferDataHost downstream: file write failed," 239 " ERROR=" 240 << errno << ", UPSTREAM=" << upstream 241 << ", LENGTH=" << length << ", OFFSET=" << offset << "\n"; 242 return rc; 243 } 244 } 245 246 return 0; 247 } 248 249 } // namespace dma 250 251 namespace oem_ibm 252 { 253 Response Handler::readFileIntoMemory(const pldm_msg* request, 254 size_t payloadLength) 255 { 256 uint32_t fileHandle = 0; 257 uint32_t offset = 0; 258 uint32_t length = 0; 259 uint64_t address = 0; 260 261 Response response((sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES), 0); 262 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 263 264 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES) 265 { 266 encode_rw_file_memory_resp(request->hdr.instance_id, 267 PLDM_READ_FILE_INTO_MEMORY, 268 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 269 return response; 270 } 271 272 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset, 273 &length, &address); 274 275 using namespace pldm::filetable; 276 auto& table = buildFileTable(FILE_TABLE_JSON); 277 FileEntry value{}; 278 279 try 280 { 281 value = table.at(fileHandle); 282 } 283 catch (const std::exception& e) 284 { 285 std::cerr << "File handle does not exist in the file table, HANDLE=" 286 << fileHandle << "\n"; 287 encode_rw_file_memory_resp(request->hdr.instance_id, 288 PLDM_READ_FILE_INTO_MEMORY, 289 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 290 return response; 291 } 292 293 if (!fs::exists(value.fsPath)) 294 { 295 std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n"; 296 encode_rw_file_memory_resp(request->hdr.instance_id, 297 PLDM_READ_FILE_INTO_MEMORY, 298 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 299 return response; 300 } 301 302 auto fileSize = fs::file_size(value.fsPath); 303 if (offset >= fileSize) 304 { 305 std::cerr << "Offset exceeds file size, OFFSET=" << offset 306 << " FILE_SIZE=" << fileSize << "\n"; 307 encode_rw_file_memory_resp(request->hdr.instance_id, 308 PLDM_READ_FILE_INTO_MEMORY, 309 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr); 310 return response; 311 } 312 313 if (offset + length > fileSize) 314 { 315 length = fileSize - offset; 316 } 317 318 if (length % dma::minSize) 319 { 320 std::cerr << "Read length is not a multiple of DMA minSize, LENGTH=" 321 << length << "\n"; 322 encode_rw_file_memory_resp(request->hdr.instance_id, 323 PLDM_READ_FILE_INTO_MEMORY, 324 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 325 return response; 326 } 327 328 using namespace dma; 329 DMA intf; 330 return transferAll<DMA>(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath, 331 offset, length, address, true, 332 request->hdr.instance_id); 333 } 334 335 Response Handler::writeFileFromMemory(const pldm_msg* request, 336 size_t payloadLength) 337 { 338 uint32_t fileHandle = 0; 339 uint32_t offset = 0; 340 uint32_t length = 0; 341 uint64_t address = 0; 342 343 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0); 344 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 345 346 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES) 347 { 348 encode_rw_file_memory_resp(request->hdr.instance_id, 349 PLDM_WRITE_FILE_FROM_MEMORY, 350 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 351 return response; 352 } 353 354 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset, 355 &length, &address); 356 357 if (length % dma::minSize) 358 { 359 std::cerr << "Write length is not a multiple of DMA minSize, LENGTH=" 360 << length << "\n"; 361 encode_rw_file_memory_resp(request->hdr.instance_id, 362 PLDM_WRITE_FILE_FROM_MEMORY, 363 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 364 return response; 365 } 366 367 using namespace pldm::filetable; 368 auto& table = buildFileTable(FILE_TABLE_JSON); 369 FileEntry value{}; 370 371 try 372 { 373 value = table.at(fileHandle); 374 } 375 catch (const std::exception& e) 376 { 377 std::cerr << "File handle does not exist in the file table, HANDLE=" 378 << fileHandle << "\n"; 379 encode_rw_file_memory_resp(request->hdr.instance_id, 380 PLDM_WRITE_FILE_FROM_MEMORY, 381 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 382 return response; 383 } 384 385 if (!fs::exists(value.fsPath)) 386 { 387 std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n"; 388 encode_rw_file_memory_resp(request->hdr.instance_id, 389 PLDM_WRITE_FILE_FROM_MEMORY, 390 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 391 return response; 392 } 393 394 auto fileSize = fs::file_size(value.fsPath); 395 if (offset >= fileSize) 396 { 397 std::cerr << "Offset exceeds file size, OFFSET=" << offset 398 << " FILE_SIZE=" << fileSize << "\n"; 399 encode_rw_file_memory_resp(request->hdr.instance_id, 400 PLDM_WRITE_FILE_FROM_MEMORY, 401 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr); 402 return response; 403 } 404 405 using namespace dma; 406 DMA intf; 407 return transferAll<DMA>(&intf, PLDM_WRITE_FILE_FROM_MEMORY, value.fsPath, 408 offset, length, address, false, 409 request->hdr.instance_id); 410 } 411 412 Response Handler::getFileTable(const pldm_msg* request, size_t payloadLength) 413 { 414 uint32_t transferHandle = 0; 415 uint8_t transferFlag = 0; 416 uint8_t tableType = 0; 417 418 Response response(sizeof(pldm_msg_hdr) + 419 PLDM_GET_FILE_TABLE_MIN_RESP_BYTES); 420 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 421 422 if (payloadLength != PLDM_GET_FILE_TABLE_REQ_BYTES) 423 { 424 encode_get_file_table_resp(request->hdr.instance_id, 425 PLDM_ERROR_INVALID_LENGTH, 0, 0, nullptr, 0, 426 responsePtr); 427 return response; 428 } 429 430 auto rc = decode_get_file_table_req(request, payloadLength, &transferHandle, 431 &transferFlag, &tableType); 432 if (rc) 433 { 434 encode_get_file_table_resp(request->hdr.instance_id, rc, 0, 0, nullptr, 435 0, responsePtr); 436 return response; 437 } 438 439 if (tableType != PLDM_FILE_ATTRIBUTE_TABLE) 440 { 441 encode_get_file_table_resp(request->hdr.instance_id, 442 PLDM_INVALID_FILE_TABLE_TYPE, 0, 0, nullptr, 443 0, responsePtr); 444 return response; 445 } 446 447 using namespace pldm::filetable; 448 auto table = buildFileTable(FILE_TABLE_JSON); 449 auto attrTable = table(); 450 response.resize(response.size() + attrTable.size()); 451 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 452 453 if (attrTable.empty()) 454 { 455 encode_get_file_table_resp(request->hdr.instance_id, 456 PLDM_FILE_TABLE_UNAVAILABLE, 0, 0, nullptr, 457 0, responsePtr); 458 return response; 459 } 460 461 encode_get_file_table_resp(request->hdr.instance_id, PLDM_SUCCESS, 0, 462 PLDM_START_AND_END, attrTable.data(), 463 attrTable.size(), responsePtr); 464 return response; 465 } 466 467 Response Handler::readFile(const pldm_msg* request, size_t payloadLength) 468 { 469 uint32_t fileHandle = 0; 470 uint32_t offset = 0; 471 uint32_t length = 0; 472 473 Response response(sizeof(pldm_msg_hdr) + PLDM_READ_FILE_RESP_BYTES); 474 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 475 476 if (payloadLength != PLDM_READ_FILE_REQ_BYTES) 477 { 478 encode_read_file_resp(request->hdr.instance_id, 479 PLDM_ERROR_INVALID_LENGTH, length, responsePtr); 480 return response; 481 } 482 483 auto rc = decode_read_file_req(request, payloadLength, &fileHandle, &offset, 484 &length); 485 486 if (rc) 487 { 488 encode_read_file_resp(request->hdr.instance_id, rc, 0, responsePtr); 489 return response; 490 } 491 492 using namespace pldm::filetable; 493 auto& table = buildFileTable(FILE_TABLE_JSON); 494 FileEntry value{}; 495 496 try 497 { 498 value = table.at(fileHandle); 499 } 500 catch (const std::exception& e) 501 { 502 std::cerr << "File handle does not exist in the file table, HANDLE=" 503 << fileHandle << "\n"; 504 encode_read_file_resp(request->hdr.instance_id, 505 PLDM_INVALID_FILE_HANDLE, length, responsePtr); 506 return response; 507 } 508 509 if (!fs::exists(value.fsPath)) 510 { 511 std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n"; 512 encode_read_file_resp(request->hdr.instance_id, 513 PLDM_INVALID_FILE_HANDLE, length, responsePtr); 514 return response; 515 } 516 517 auto fileSize = fs::file_size(value.fsPath); 518 if (offset >= fileSize) 519 { 520 std::cerr << "Offset exceeds file size, OFFSET=" << offset 521 << " FILE_SIZE=" << fileSize << "\n"; 522 encode_read_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE, 523 length, responsePtr); 524 return response; 525 } 526 527 if (offset + length > fileSize) 528 { 529 length = fileSize - offset; 530 } 531 532 response.resize(response.size() + length); 533 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 534 auto fileDataPos = reinterpret_cast<char*>(responsePtr); 535 fileDataPos += sizeof(pldm_msg_hdr) + sizeof(uint8_t) + sizeof(length); 536 537 std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary); 538 stream.seekg(offset); 539 stream.read(fileDataPos, length); 540 541 encode_read_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length, 542 responsePtr); 543 544 return response; 545 } 546 547 Response Handler::writeFile(const pldm_msg* request, size_t payloadLength) 548 { 549 uint32_t fileHandle = 0; 550 uint32_t offset = 0; 551 uint32_t length = 0; 552 size_t fileDataOffset = 0; 553 554 Response response(sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_RESP_BYTES); 555 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 556 557 if (payloadLength < PLDM_WRITE_FILE_REQ_BYTES) 558 { 559 encode_write_file_resp(request->hdr.instance_id, 560 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 561 return response; 562 } 563 564 auto rc = decode_write_file_req(request, payloadLength, &fileHandle, 565 &offset, &length, &fileDataOffset); 566 567 if (rc) 568 { 569 encode_write_file_resp(request->hdr.instance_id, rc, 0, responsePtr); 570 return response; 571 } 572 573 using namespace pldm::filetable; 574 auto& table = buildFileTable(FILE_TABLE_JSON); 575 FileEntry value{}; 576 577 try 578 { 579 value = table.at(fileHandle); 580 } 581 catch (const std::exception& e) 582 { 583 std::cerr << "File handle does not exist in the file table, HANDLE=" 584 << fileHandle << "\n"; 585 encode_write_file_resp(request->hdr.instance_id, 586 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 587 return response; 588 } 589 590 if (!fs::exists(value.fsPath)) 591 { 592 std::cerr << "File does not exist, HANDLE=" << fileHandle << "\n"; 593 encode_write_file_resp(request->hdr.instance_id, 594 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 595 return response; 596 } 597 598 auto fileSize = fs::file_size(value.fsPath); 599 if (offset >= fileSize) 600 { 601 std::cerr << "Offset exceeds file size, OFFSET=" << offset 602 << " FILE_SIZE=" << fileSize << "\n"; 603 encode_write_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE, 604 0, responsePtr); 605 return response; 606 } 607 608 auto fileDataPos = 609 reinterpret_cast<const char*>(request->payload) + fileDataOffset; 610 611 std::ofstream stream(value.fsPath, 612 std::ios::in | std::ios::out | std::ios::binary); 613 stream.seekp(offset); 614 stream.write(fileDataPos, length); 615 616 encode_write_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length, 617 responsePtr); 618 619 return response; 620 } 621 622 Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request, 623 size_t payloadLength, 624 oem_platform::Handler* oemPlatformHandler) 625 { 626 Response response( 627 sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0); 628 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 629 630 if (payloadLength != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES) 631 { 632 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, 633 PLDM_ERROR_INVALID_LENGTH, 0, 634 responsePtr); 635 return response; 636 } 637 638 uint16_t fileType{}; 639 uint32_t fileHandle{}; 640 uint32_t offset{}; 641 uint32_t length{}; 642 uint64_t address{}; 643 auto rc = decode_rw_file_by_type_memory_req(request, payloadLength, 644 &fileType, &fileHandle, &offset, 645 &length, &address); 646 if (rc != PLDM_SUCCESS) 647 { 648 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0, 649 responsePtr); 650 return response; 651 } 652 if (length % dma::minSize) 653 { 654 std::cerr << "Length is not a multiple of DMA minSize, LENGTH=" 655 << length << "\n"; 656 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, 657 PLDM_ERROR_INVALID_LENGTH, 0, 658 responsePtr); 659 return response; 660 } 661 662 std::unique_ptr<FileHandler> handler{}; 663 try 664 { 665 handler = getHandlerByType(fileType, fileHandle); 666 } 667 catch (const InternalFailure& e) 668 { 669 std::cerr << "unknown file type, TYPE=" << fileType << "\n"; 670 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, 671 PLDM_INVALID_FILE_TYPE, 0, 672 responsePtr); 673 return response; 674 } 675 676 rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY 677 ? handler->writeFromMemory(offset, length, address, 678 oemPlatformHandler) 679 : handler->readIntoMemory(offset, length, address, 680 oemPlatformHandler); 681 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 682 length, responsePtr); 683 return response; 684 } 685 686 Response Handler::writeFileByTypeFromMemory(const pldm_msg* request, 687 size_t payloadLength) 688 { 689 return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request, 690 payloadLength, oemPlatformHandler); 691 } 692 693 Response Handler::readFileByTypeIntoMemory(const pldm_msg* request, 694 size_t payloadLength) 695 { 696 return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request, 697 payloadLength, oemPlatformHandler); 698 } 699 700 Response Handler::writeFileByType(const pldm_msg* request, size_t payloadLength) 701 { 702 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES); 703 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 704 705 if (payloadLength < PLDM_RW_FILE_BY_TYPE_REQ_BYTES) 706 { 707 encode_rw_file_by_type_resp(request->hdr.instance_id, 708 PLDM_WRITE_FILE_BY_TYPE, 709 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 710 return response; 711 } 712 uint16_t fileType{}; 713 uint32_t fileHandle{}; 714 uint32_t offset{}; 715 uint32_t length{}; 716 717 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType, 718 &fileHandle, &offset, &length); 719 if (rc != PLDM_SUCCESS) 720 { 721 encode_rw_file_by_type_resp(request->hdr.instance_id, 722 PLDM_WRITE_FILE_BY_TYPE, rc, 0, 723 responsePtr); 724 return response; 725 } 726 727 std::unique_ptr<FileHandler> handler{}; 728 try 729 { 730 handler = getHandlerByType(fileType, fileHandle); 731 } 732 catch (const InternalFailure& e) 733 { 734 std::cerr << "unknown file type, TYPE=" << fileType << "\n"; 735 encode_rw_file_by_type_resp(request->hdr.instance_id, 736 PLDM_WRITE_FILE_BY_TYPE, 737 PLDM_INVALID_FILE_TYPE, 0, responsePtr); 738 return response; 739 } 740 741 rc = handler->write(reinterpret_cast<const char*>( 742 request->payload + PLDM_RW_FILE_BY_TYPE_REQ_BYTES), 743 offset, length, oemPlatformHandler); 744 encode_rw_file_by_type_resp(request->hdr.instance_id, 745 PLDM_WRITE_FILE_BY_TYPE, rc, length, 746 responsePtr); 747 return response; 748 } 749 750 Response Handler::readFileByType(const pldm_msg* request, size_t payloadLength) 751 { 752 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES); 753 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 754 755 if (payloadLength != PLDM_RW_FILE_BY_TYPE_REQ_BYTES) 756 { 757 encode_rw_file_by_type_resp(request->hdr.instance_id, 758 PLDM_READ_FILE_BY_TYPE, 759 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 760 return response; 761 } 762 uint16_t fileType{}; 763 uint32_t fileHandle{}; 764 uint32_t offset{}; 765 uint32_t length{}; 766 767 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType, 768 &fileHandle, &offset, &length); 769 if (rc != PLDM_SUCCESS) 770 { 771 encode_rw_file_by_type_resp(request->hdr.instance_id, 772 PLDM_READ_FILE_BY_TYPE, rc, 0, responsePtr); 773 return response; 774 } 775 776 std::unique_ptr<FileHandler> handler{}; 777 try 778 { 779 handler = getHandlerByType(fileType, fileHandle); 780 } 781 catch (const InternalFailure& e) 782 { 783 std::cerr << "unknown file type, TYPE=" << fileType << "\n"; 784 encode_rw_file_by_type_resp(request->hdr.instance_id, 785 PLDM_READ_FILE_BY_TYPE, 786 PLDM_INVALID_FILE_TYPE, 0, responsePtr); 787 return response; 788 } 789 790 rc = handler->read(offset, length, response, oemPlatformHandler); 791 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 792 encode_rw_file_by_type_resp(request->hdr.instance_id, 793 PLDM_READ_FILE_BY_TYPE, rc, length, 794 responsePtr); 795 return response; 796 } 797 798 Response Handler::fileAck(const pldm_msg* request, size_t payloadLength) 799 { 800 Response response(sizeof(pldm_msg_hdr) + PLDM_FILE_ACK_RESP_BYTES); 801 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 802 803 if (payloadLength != PLDM_FILE_ACK_REQ_BYTES) 804 { 805 encode_file_ack_resp(request->hdr.instance_id, 806 PLDM_ERROR_INVALID_LENGTH, responsePtr); 807 return response; 808 } 809 uint16_t fileType{}; 810 uint32_t fileHandle{}; 811 uint8_t fileStatus{}; 812 813 auto rc = decode_file_ack_req(request, payloadLength, &fileType, 814 &fileHandle, &fileStatus); 815 if (rc != PLDM_SUCCESS) 816 { 817 encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr); 818 return response; 819 } 820 821 std::unique_ptr<FileHandler> handler{}; 822 try 823 { 824 handler = getHandlerByType(fileType, fileHandle); 825 } 826 827 catch (const InternalFailure& e) 828 { 829 encode_file_ack_resp(request->hdr.instance_id, PLDM_INVALID_FILE_TYPE, 830 responsePtr); 831 return response; 832 } 833 834 rc = handler->fileAck(fileStatus); 835 encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr); 836 return response; 837 } 838 839 Response Handler::getAlertStatus(const pldm_msg* request, size_t payloadLength) 840 { 841 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_ALERT_STATUS_RESP_BYTES); 842 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 843 if (payloadLength != PLDM_GET_ALERT_STATUS_REQ_BYTES) 844 { 845 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 846 } 847 848 uint8_t versionId{}; 849 850 auto rc = decode_get_alert_status_req(request, payloadLength, &versionId); 851 if (rc != PLDM_SUCCESS) 852 { 853 return CmdHandler::ccOnlyResponse(request, rc); 854 } 855 856 if (versionId != 0) 857 { 858 return CmdHandler::ccOnlyResponse(request, 859 PLDM_HOST_UNSUPPORTED_FORMAT_VERSION); 860 } 861 862 constexpr uint32_t rackEntry = 0xFF000030; 863 constexpr uint32_t priCecNode = 0x00008030; 864 rc = encode_get_alert_status_resp(request->hdr.instance_id, PLDM_SUCCESS, 865 rackEntry, priCecNode, responsePtr, 866 PLDM_GET_ALERT_STATUS_RESP_BYTES); 867 if (rc != PLDM_SUCCESS) 868 { 869 return CmdHandler::ccOnlyResponse(request, rc); 870 } 871 872 return response; 873 } 874 875 Response Handler::newFileAvailable(const pldm_msg* request, 876 size_t payloadLength) 877 { 878 Response response(sizeof(pldm_msg_hdr) + PLDM_NEW_FILE_RESP_BYTES); 879 880 if (payloadLength != PLDM_NEW_FILE_REQ_BYTES) 881 { 882 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 883 } 884 uint16_t fileType{}; 885 uint32_t fileHandle{}; 886 uint64_t length{}; 887 888 auto rc = decode_new_file_req(request, payloadLength, &fileType, 889 &fileHandle, &length); 890 891 if (rc != PLDM_SUCCESS) 892 { 893 return CmdHandler::ccOnlyResponse(request, rc); 894 } 895 896 std::unique_ptr<FileHandler> handler{}; 897 try 898 { 899 handler = getHandlerByType(fileType, fileHandle); 900 } 901 catch (const InternalFailure& e) 902 { 903 std::cerr << "unknown file type, TYPE=" << fileType << "\n"; 904 return CmdHandler::ccOnlyResponse(request, PLDM_INVALID_FILE_TYPE); 905 } 906 907 rc = handler->newFileAvailable(length); 908 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 909 encode_new_file_resp(request->hdr.instance_id, rc, responsePtr); 910 return response; 911 } 912 913 } // namespace oem_ibm 914 } // namespace responder 915 } // namespace pldm 916