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