1 #include "config.h" 2 3 #include "file_io.hpp" 4 5 #include "file_io_by_type.hpp" 6 #include "file_table.hpp" 7 #include "utils.hpp" 8 #include "xyz/openbmc_project/Common/error.hpp" 9 10 #include <fcntl.h> 11 #include <libpldm/base.h> 12 #include <sys/mman.h> 13 #include <sys/stat.h> 14 #include <sys/types.h> 15 #include <unistd.h> 16 17 #include <phosphor-logging/lg2.hpp> 18 19 #include <cstring> 20 #include <fstream> 21 #include <iostream> 22 #include <memory> 23 24 PHOSPHOR_LOG2_USING; 25 26 namespace pldm 27 { 28 using namespace pldm::responder::utils; 29 using namespace sdbusplus::xyz::openbmc_project::Common::Error; 30 31 namespace responder 32 { 33 namespace fs = std::filesystem; 34 35 namespace dma 36 { 37 /** @struct AspeedXdmaOp 38 * 39 * Structure representing XDMA operation 40 */ 41 struct AspeedXdmaOp 42 { 43 uint64_t hostAddr; //!< the DMA address on the host side, configured by 44 //!< PCI subsystem. 45 uint32_t len; //!< the size of the transfer in bytes, it should be a 46 //!< multiple of 16 bytes 47 uint32_t upstream; //!< boolean indicating the direction of the DMA 48 //!< operation, true means a transfer from BMC to host. 49 }; 50 51 constexpr auto xdmaDev = "/dev/aspeed-xdma"; 52 53 int DMA::transferHostDataToSocket(int fd, uint32_t length, uint64_t address) 54 { 55 static const size_t pageSize = getpagesize(); 56 uint32_t numPages = length / pageSize; 57 uint32_t pageAlignedLength = numPages * pageSize; 58 59 if (length > pageAlignedLength) 60 { 61 pageAlignedLength += pageSize; 62 } 63 64 auto mmapCleanup = [pageAlignedLength](void* vgaMem) { 65 munmap(vgaMem, pageAlignedLength); 66 }; 67 68 int dmaFd = -1; 69 int rc = 0; 70 dmaFd = open(xdmaDev, O_RDWR); 71 if (dmaFd < 0) 72 { 73 rc = -errno; 74 error( 75 "transferHostDataToSocket: Failed to open the XDMA device, RC={RC}", 76 "RC", rc); 77 return rc; 78 } 79 80 pldm::utils::CustomFD xdmaFd(dmaFd); 81 82 void* vgaMem; 83 vgaMem = 84 mmap(nullptr, pageAlignedLength, PROT_READ, MAP_SHARED, xdmaFd(), 0); 85 if (MAP_FAILED == vgaMem) 86 { 87 rc = -errno; 88 error( 89 "transferHostDataToSocket : Failed to mmap the XDMA device, RC={RC}", 90 "RC", rc); 91 return rc; 92 } 93 94 std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup); 95 96 AspeedXdmaOp xdmaOp; 97 xdmaOp.upstream = 0; 98 xdmaOp.hostAddr = address; 99 xdmaOp.len = length; 100 101 rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp)); 102 if (rc < 0) 103 { 104 rc = -errno; 105 error( 106 "transferHostDataToSocket: Failed to execute the DMA operation, RC={RC} ADDRESS={ADDR} LENGTH={LEN}", 107 "RC", rc, "ADDR", address, "LEN", length); 108 return rc; 109 } 110 111 rc = writeToUnixSocket(fd, static_cast<const char*>(vgaMemPtr.get()), 112 length); 113 if (rc < 0) 114 { 115 rc = -errno; 116 close(fd); 117 error( 118 "transferHostDataToSocket: Closing socket as writeToUnixSocket faile with RC={RC}", 119 "RC", rc); 120 return rc; 121 } 122 return 0; 123 } 124 125 int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length, 126 uint64_t address, bool upstream) 127 { 128 static const size_t pageSize = getpagesize(); 129 uint32_t numPages = length / pageSize; 130 uint32_t pageAlignedLength = numPages * pageSize; 131 132 if (length > pageAlignedLength) 133 { 134 pageAlignedLength += pageSize; 135 } 136 137 int rc = 0; 138 auto mmapCleanup = [pageAlignedLength, &rc](void* vgaMem) { 139 if (rc != -EINTR) 140 { 141 munmap(vgaMem, pageAlignedLength); 142 } 143 else 144 { 145 error( 146 "transferDataHost: Received interrupt during DMA transfer. Skipping Unmap."); 147 } 148 }; 149 150 int dmaFd = -1; 151 dmaFd = open(xdmaDev, O_RDWR); 152 if (dmaFd < 0) 153 { 154 rc = -errno; 155 error("transferDataHost : Failed to open the XDMA device, RC={RC}", 156 "RC", rc); 157 return rc; 158 } 159 160 pldm::utils::CustomFD xdmaFd(dmaFd); 161 162 void* vgaMem; 163 vgaMem = mmap(nullptr, pageAlignedLength, upstream ? PROT_WRITE : PROT_READ, 164 MAP_SHARED, xdmaFd(), 0); 165 if (MAP_FAILED == vgaMem) 166 { 167 rc = -errno; 168 error("transferDataHost : Failed to mmap the XDMA device, RC={RC}", 169 "RC", rc); 170 return rc; 171 } 172 173 std::unique_ptr<void, decltype(mmapCleanup)> vgaMemPtr(vgaMem, mmapCleanup); 174 175 if (upstream) 176 { 177 rc = lseek(fd, offset, SEEK_SET); 178 if (rc == -1) 179 { 180 error( 181 "transferDataHost upstream : lseek failed, ERROR={ERR}, UPSTREAM={UPSTREAM}, OFFSET={OFFSET}", 182 "ERR", errno, "UPSTREAM", upstream, "OFFSET", offset); 183 return rc; 184 } 185 186 // Writing to the VGA memory should be aligned at page boundary, 187 // otherwise write data into a buffer aligned at page boundary and 188 // then write to the VGA memory. 189 std::vector<char> buffer{}; 190 buffer.resize(pageAlignedLength); 191 rc = read(fd, buffer.data(), length); 192 if (rc == -1) 193 { 194 error( 195 "transferDataHost upstream : file read failed, ERROR={ERR}, UPSTREAM={UPSTREAM}, LENGTH={LEN}, OFFSET={OFFSET}", 196 "ERR", errno, "UPSTREAM", upstream, "LEN", length, "OFFSET", 197 offset); 198 return rc; 199 } 200 if (rc != static_cast<int>(length)) 201 { 202 error( 203 "transferDataHost upstream : mismatch between number of characters to read and the length read, LENGTH={LEN} COUNT={RC}", 204 "LEN", length, "RC", rc); 205 return -1; 206 } 207 memcpy(static_cast<char*>(vgaMemPtr.get()), buffer.data(), 208 pageAlignedLength); 209 } 210 211 AspeedXdmaOp xdmaOp; 212 xdmaOp.upstream = upstream ? 1 : 0; 213 xdmaOp.hostAddr = address; 214 xdmaOp.len = length; 215 216 rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp)); 217 if (rc < 0) 218 { 219 rc = -errno; 220 error( 221 "transferDataHost : Failed to execute the DMA operation, RC={RC} UPSTREAM={UPSTREAM} ADDRESS={ADDR} LENGTH={LEN}", 222 "RC", rc, "UPSTREAM", upstream, "ADDR", address, "LEN", length); 223 return rc; 224 } 225 226 if (!upstream) 227 { 228 rc = lseek(fd, offset, SEEK_SET); 229 if (rc == -1) 230 { 231 error( 232 "transferDataHost downstream : lseek failed, ERROR={ERR}, UPSTREAM={UPSTREAM}, OFFSET={OFFSET}", 233 "ERR", errno, "UPSTREAM", upstream, "OFFSET", offset); 234 return rc; 235 } 236 rc = write(fd, static_cast<const char*>(vgaMemPtr.get()), length); 237 if (rc == -1) 238 { 239 error( 240 "transferDataHost downstream : file write failed, ERROR={ERR}, UPSTREAM={UPSTREAM}, LENGTH={LEN}, OFFSET={OFFSET}", 241 "ERR", errno, "UPSTREAM", upstream, "LEN", length, "OFFSET", 242 offset); 243 return rc; 244 } 245 } 246 247 return 0; 248 } 249 250 } // namespace dma 251 252 namespace oem_ibm 253 { 254 Response Handler::readFileIntoMemory(const pldm_msg* request, 255 size_t payloadLength) 256 { 257 uint32_t fileHandle = 0; 258 uint32_t offset = 0; 259 uint32_t length = 0; 260 uint64_t address = 0; 261 262 Response response((sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES), 0); 263 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 264 265 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES) 266 { 267 encode_rw_file_memory_resp(request->hdr.instance_id, 268 PLDM_READ_FILE_INTO_MEMORY, 269 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 270 return response; 271 } 272 273 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset, 274 &length, &address); 275 276 using namespace pldm::filetable; 277 auto& table = buildFileTable(FILE_TABLE_JSON); 278 FileEntry value{}; 279 280 try 281 { 282 value = table.at(fileHandle); 283 } 284 catch (const std::exception& e) 285 { 286 error( 287 "File handle does not exist in the file table, HANDLE={FILE_HANDLE}", 288 "FILE_HANDLE", fileHandle); 289 encode_rw_file_memory_resp(request->hdr.instance_id, 290 PLDM_READ_FILE_INTO_MEMORY, 291 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 292 return response; 293 } 294 295 if (!fs::exists(value.fsPath)) 296 { 297 error("File does not exist, HANDLE={FILE_HANDLE}", "FILE_HANDLE", 298 fileHandle); 299 encode_rw_file_memory_resp(request->hdr.instance_id, 300 PLDM_READ_FILE_INTO_MEMORY, 301 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 302 return response; 303 } 304 305 auto fileSize = fs::file_size(value.fsPath); 306 if (offset >= fileSize) 307 { 308 error("Offset exceeds file size, OFFSET={OFFSTE} FILE_SIZE={FILE_SIZE}", 309 "OFFSET", offset, "FILE_SIZE", fileSize); 310 encode_rw_file_memory_resp(request->hdr.instance_id, 311 PLDM_READ_FILE_INTO_MEMORY, 312 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr); 313 return response; 314 } 315 316 if (offset + length > fileSize) 317 { 318 length = fileSize - offset; 319 } 320 321 if (length % dma::minSize) 322 { 323 error("Read length is not a multiple of DMA minSize, LENGTH={LEN}", 324 "LEN", length); 325 encode_rw_file_memory_resp(request->hdr.instance_id, 326 PLDM_READ_FILE_INTO_MEMORY, 327 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 328 return response; 329 } 330 331 using namespace dma; 332 DMA intf; 333 return transferAll<DMA>(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath, 334 offset, length, address, true, 335 request->hdr.instance_id); 336 } 337 338 Response Handler::writeFileFromMemory(const pldm_msg* request, 339 size_t payloadLength) 340 { 341 uint32_t fileHandle = 0; 342 uint32_t offset = 0; 343 uint32_t length = 0; 344 uint64_t address = 0; 345 346 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0); 347 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 348 349 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES) 350 { 351 encode_rw_file_memory_resp(request->hdr.instance_id, 352 PLDM_WRITE_FILE_FROM_MEMORY, 353 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 354 return response; 355 } 356 357 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset, 358 &length, &address); 359 360 if (length % dma::minSize) 361 { 362 error("Write length is not a multiple of DMA minSize, LENGTH={LEN}", 363 "LEN", length); 364 encode_rw_file_memory_resp(request->hdr.instance_id, 365 PLDM_WRITE_FILE_FROM_MEMORY, 366 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 367 return response; 368 } 369 370 using namespace pldm::filetable; 371 auto& table = buildFileTable(FILE_TABLE_JSON); 372 FileEntry value{}; 373 374 try 375 { 376 value = table.at(fileHandle); 377 } 378 catch (const std::exception& e) 379 { 380 error( 381 "File handle does not exist in the file table, HANDLE={FILE_HANDLE}", 382 "FILE_HANDLE", fileHandle); 383 encode_rw_file_memory_resp(request->hdr.instance_id, 384 PLDM_WRITE_FILE_FROM_MEMORY, 385 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 386 return response; 387 } 388 389 if (!fs::exists(value.fsPath)) 390 { 391 error("File does not exist, HANDLE={FILE_HANDLE}", "FILE_HANDLE", 392 fileHandle); 393 encode_rw_file_memory_resp(request->hdr.instance_id, 394 PLDM_WRITE_FILE_FROM_MEMORY, 395 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 396 return response; 397 } 398 399 auto fileSize = fs::file_size(value.fsPath); 400 if (offset >= fileSize) 401 { 402 error("Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE}", 403 "OFFSET", offset, "FILE_SIZE", fileSize); 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 = 618 reinterpret_cast<const char*>(request->payload) + 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