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