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 { 607 Response response( 608 sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0); 609 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 610 611 if (payloadLength != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES) 612 { 613 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, 614 PLDM_ERROR_INVALID_LENGTH, 0, 615 responsePtr); 616 return response; 617 } 618 619 uint16_t fileType{}; 620 uint32_t fileHandle{}; 621 uint32_t offset{}; 622 uint32_t length{}; 623 uint64_t address{}; 624 auto rc = decode_rw_file_by_type_memory_req(request, payloadLength, 625 &fileType, &fileHandle, &offset, 626 &length, &address); 627 if (rc != PLDM_SUCCESS) 628 { 629 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0, 630 responsePtr); 631 return response; 632 } 633 if (length % dma::minSize) 634 { 635 std::cerr << "Length is not a multiple of DMA minSize, LENGTH=" 636 << length << "\n"; 637 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, 638 PLDM_ERROR_INVALID_LENGTH, 0, 639 responsePtr); 640 return response; 641 } 642 643 std::unique_ptr<FileHandler> handler{}; 644 try 645 { 646 handler = getHandlerByType(fileType, fileHandle); 647 } 648 catch (const InternalFailure& e) 649 { 650 std::cerr << "unknown file type, TYPE=" << fileType << "\n"; 651 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, 652 PLDM_INVALID_FILE_TYPE, 0, 653 responsePtr); 654 return response; 655 } 656 657 rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY 658 ? handler->writeFromMemory(offset, length, address) 659 : handler->readIntoMemory(offset, length, address); 660 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 661 length, responsePtr); 662 return response; 663 } 664 665 Response Handler::writeFileByTypeFromMemory(const pldm_msg* request, 666 size_t payloadLength) 667 { 668 return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request, 669 payloadLength); 670 } 671 672 Response Handler::readFileByTypeIntoMemory(const pldm_msg* request, 673 size_t payloadLength) 674 { 675 return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request, 676 payloadLength); 677 } 678 679 Response Handler::writeFileByType(const pldm_msg* request, size_t payloadLength) 680 { 681 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES); 682 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 683 684 if (payloadLength < PLDM_RW_FILE_BY_TYPE_REQ_BYTES) 685 { 686 encode_rw_file_by_type_resp(request->hdr.instance_id, 687 PLDM_WRITE_FILE_BY_TYPE, 688 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 689 return response; 690 } 691 uint16_t fileType{}; 692 uint32_t fileHandle{}; 693 uint32_t offset{}; 694 uint32_t length{}; 695 696 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType, 697 &fileHandle, &offset, &length); 698 if (rc != PLDM_SUCCESS) 699 { 700 encode_rw_file_by_type_resp(request->hdr.instance_id, 701 PLDM_WRITE_FILE_BY_TYPE, rc, 0, 702 responsePtr); 703 return response; 704 } 705 706 std::unique_ptr<FileHandler> handler{}; 707 try 708 { 709 handler = getHandlerByType(fileType, fileHandle); 710 } 711 catch (const InternalFailure& e) 712 { 713 std::cerr << "unknown file type, TYPE=" << fileType << "\n"; 714 encode_rw_file_by_type_resp(request->hdr.instance_id, 715 PLDM_WRITE_FILE_BY_TYPE, 716 PLDM_INVALID_FILE_TYPE, 0, responsePtr); 717 return response; 718 } 719 720 rc = handler->write(reinterpret_cast<const char*>( 721 request->payload + PLDM_RW_FILE_BY_TYPE_REQ_BYTES), 722 offset, length); 723 encode_rw_file_by_type_resp(request->hdr.instance_id, 724 PLDM_WRITE_FILE_BY_TYPE, rc, length, 725 responsePtr); 726 return response; 727 } 728 729 Response Handler::readFileByType(const pldm_msg* request, size_t payloadLength) 730 { 731 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES); 732 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 733 734 if (payloadLength != PLDM_RW_FILE_BY_TYPE_REQ_BYTES) 735 { 736 encode_rw_file_by_type_resp(request->hdr.instance_id, 737 PLDM_READ_FILE_BY_TYPE, 738 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 739 return response; 740 } 741 uint16_t fileType{}; 742 uint32_t fileHandle{}; 743 uint32_t offset{}; 744 uint32_t length{}; 745 746 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType, 747 &fileHandle, &offset, &length); 748 if (rc != PLDM_SUCCESS) 749 { 750 encode_rw_file_by_type_resp(request->hdr.instance_id, 751 PLDM_READ_FILE_BY_TYPE, rc, 0, responsePtr); 752 return response; 753 } 754 755 std::unique_ptr<FileHandler> handler{}; 756 try 757 { 758 handler = getHandlerByType(fileType, fileHandle); 759 } 760 catch (const InternalFailure& e) 761 { 762 std::cerr << "unknown file type, TYPE=" << fileType << "\n"; 763 encode_rw_file_by_type_resp(request->hdr.instance_id, 764 PLDM_READ_FILE_BY_TYPE, 765 PLDM_INVALID_FILE_TYPE, 0, responsePtr); 766 return response; 767 } 768 769 rc = handler->read(offset, length, response); 770 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 771 encode_rw_file_by_type_resp(request->hdr.instance_id, 772 PLDM_READ_FILE_BY_TYPE, rc, length, 773 responsePtr); 774 return response; 775 } 776 777 Response Handler::fileAck(const pldm_msg* request, size_t payloadLength) 778 { 779 Response response(sizeof(pldm_msg_hdr) + PLDM_FILE_ACK_RESP_BYTES); 780 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 781 782 if (payloadLength != PLDM_FILE_ACK_REQ_BYTES) 783 { 784 encode_file_ack_resp(request->hdr.instance_id, 785 PLDM_ERROR_INVALID_LENGTH, responsePtr); 786 return response; 787 } 788 uint16_t fileType{}; 789 uint32_t fileHandle{}; 790 uint8_t fileStatus{}; 791 792 auto rc = decode_file_ack_req(request, payloadLength, &fileType, 793 &fileHandle, &fileStatus); 794 if (rc != PLDM_SUCCESS) 795 { 796 encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr); 797 return response; 798 } 799 800 std::unique_ptr<FileHandler> handler{}; 801 try 802 { 803 handler = getHandlerByType(fileType, fileHandle); 804 } 805 806 catch (const InternalFailure& e) 807 { 808 encode_file_ack_resp(request->hdr.instance_id, PLDM_INVALID_FILE_TYPE, 809 responsePtr); 810 return response; 811 } 812 813 rc = handler->fileAck(fileStatus); 814 encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr); 815 return response; 816 } 817 818 Response Handler::getAlertStatus(const pldm_msg* request, size_t payloadLength) 819 { 820 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_ALERT_STATUS_RESP_BYTES); 821 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 822 if (payloadLength != PLDM_GET_ALERT_STATUS_REQ_BYTES) 823 { 824 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 825 } 826 827 uint8_t versionId{}; 828 829 auto rc = decode_get_alert_status_req(request, payloadLength, &versionId); 830 if (rc != PLDM_SUCCESS) 831 { 832 return CmdHandler::ccOnlyResponse(request, rc); 833 } 834 835 if (versionId != 0) 836 { 837 return CmdHandler::ccOnlyResponse(request, 838 PLDM_HOST_UNSUPPORTED_FORMAT_VERSION); 839 } 840 841 constexpr uint32_t rackEntry = 0xFF000030; 842 constexpr uint32_t priCecNode = 0x00008030; 843 rc = encode_get_alert_status_resp(request->hdr.instance_id, PLDM_SUCCESS, 844 rackEntry, priCecNode, responsePtr, 845 PLDM_GET_ALERT_STATUS_RESP_BYTES); 846 if (rc != PLDM_SUCCESS) 847 { 848 return CmdHandler::ccOnlyResponse(request, rc); 849 } 850 851 return response; 852 } 853 854 Response Handler::newFileAvailable(const pldm_msg* request, 855 size_t payloadLength) 856 { 857 Response response(sizeof(pldm_msg_hdr) + PLDM_NEW_FILE_RESP_BYTES); 858 859 if (payloadLength != PLDM_NEW_FILE_REQ_BYTES) 860 { 861 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 862 } 863 uint16_t fileType{}; 864 uint32_t fileHandle{}; 865 uint64_t length{}; 866 867 auto rc = decode_new_file_req(request, payloadLength, &fileType, 868 &fileHandle, &length); 869 870 if (rc != PLDM_SUCCESS) 871 { 872 return CmdHandler::ccOnlyResponse(request, rc); 873 } 874 875 std::unique_ptr<FileHandler> handler{}; 876 try 877 { 878 handler = getHandlerByType(fileType, fileHandle); 879 } 880 catch (const InternalFailure& e) 881 { 882 std::cerr << "unknown file type, TYPE=" << fileType << "\n"; 883 return CmdHandler::ccOnlyResponse(request, PLDM_INVALID_FILE_TYPE); 884 } 885 886 rc = handler->newFileAvailable(length); 887 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 888 encode_new_file_resp(request->hdr.instance_id, rc, responsePtr); 889 return response; 890 } 891 892 } // namespace oem_ibm 893 } // namespace responder 894 } // namespace pldm 895