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