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