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("Handle ({HANDLE}) does not exist in the file table: {ERROR}", 285 "HANDLE", fileHandle, "ERROR", e); 286 encode_rw_file_memory_resp(request->hdr.instance_id, 287 PLDM_READ_FILE_INTO_MEMORY, 288 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 289 return response; 290 } 291 292 if (!fs::exists(value.fsPath)) 293 { 294 error("File does not exist, HANDLE={FILE_HANDLE}", "FILE_HANDLE", 295 fileHandle); 296 encode_rw_file_memory_resp(request->hdr.instance_id, 297 PLDM_READ_FILE_INTO_MEMORY, 298 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 299 return response; 300 } 301 302 auto fileSize = fs::file_size(value.fsPath); 303 if (offset >= fileSize) 304 { 305 error( 306 "Offset exceeds file size, OFFSET={OFFSTE} FILE_SIZE={FILE_SIZE} FILE_HANDLE{FILE_HANDLE}", 307 "OFFSET", offset, "FILE_SIZE", fileSize, "FILE_HANDLE", fileHandle); 308 encode_rw_file_memory_resp(request->hdr.instance_id, 309 PLDM_READ_FILE_INTO_MEMORY, 310 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr); 311 return response; 312 } 313 314 if (offset + length > fileSize) 315 { 316 length = fileSize - offset; 317 } 318 319 if (length % dma::minSize) 320 { 321 error("Read length is not a multiple of DMA minSize, LENGTH={LEN}", 322 "LEN", length); 323 encode_rw_file_memory_resp(request->hdr.instance_id, 324 PLDM_READ_FILE_INTO_MEMORY, 325 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 326 return response; 327 } 328 329 using namespace dma; 330 DMA intf; 331 return transferAll<DMA>(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath, 332 offset, length, address, true, 333 request->hdr.instance_id); 334 } 335 336 Response Handler::writeFileFromMemory(const pldm_msg* request, 337 size_t payloadLength) 338 { 339 uint32_t fileHandle = 0; 340 uint32_t offset = 0; 341 uint32_t length = 0; 342 uint64_t address = 0; 343 344 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0); 345 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 346 347 if (payloadLength != PLDM_RW_FILE_MEM_REQ_BYTES) 348 { 349 encode_rw_file_memory_resp(request->hdr.instance_id, 350 PLDM_WRITE_FILE_FROM_MEMORY, 351 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 352 return response; 353 } 354 355 decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset, 356 &length, &address); 357 358 if (length % dma::minSize) 359 { 360 error("Write length is not a multiple of DMA minSize, LENGTH={LEN}", 361 "LEN", length); 362 encode_rw_file_memory_resp(request->hdr.instance_id, 363 PLDM_WRITE_FILE_FROM_MEMORY, 364 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 365 return response; 366 } 367 368 using namespace pldm::filetable; 369 auto& table = buildFileTable(FILE_TABLE_JSON); 370 FileEntry value{}; 371 372 try 373 { 374 value = table.at(fileHandle); 375 } 376 catch (const std::exception& e) 377 { 378 error("Handle ({HANDLE}) does not exist in the file table: {ERROR}", 379 "HANDLE", fileHandle, "ERROR", e); 380 encode_rw_file_memory_resp(request->hdr.instance_id, 381 PLDM_WRITE_FILE_FROM_MEMORY, 382 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 383 return response; 384 } 385 386 if (!fs::exists(value.fsPath)) 387 { 388 error("File does not exist, HANDLE={FILE_HANDLE}", "FILE_HANDLE", 389 fileHandle); 390 encode_rw_file_memory_resp(request->hdr.instance_id, 391 PLDM_WRITE_FILE_FROM_MEMORY, 392 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 393 return response; 394 } 395 396 auto fileSize = fs::file_size(value.fsPath); 397 if (offset >= fileSize) 398 { 399 error( 400 "Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE} FILE_HANDLE{FILE_HANDLE}", 401 "OFFSET", offset, "FILE_SIZE", fileSize, "FILE_HANDLE", fileHandle); 402 encode_rw_file_memory_resp(request->hdr.instance_id, 403 PLDM_WRITE_FILE_FROM_MEMORY, 404 PLDM_DATA_OUT_OF_RANGE, 0, responsePtr); 405 return response; 406 } 407 408 using namespace dma; 409 DMA intf; 410 return transferAll<DMA>(&intf, PLDM_WRITE_FILE_FROM_MEMORY, value.fsPath, 411 offset, length, address, false, 412 request->hdr.instance_id); 413 } 414 415 Response Handler::getFileTable(const pldm_msg* request, size_t payloadLength) 416 { 417 uint32_t transferHandle = 0; 418 uint8_t transferFlag = 0; 419 uint8_t tableType = 0; 420 421 Response response(sizeof(pldm_msg_hdr) + 422 PLDM_GET_FILE_TABLE_MIN_RESP_BYTES); 423 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 424 425 if (payloadLength != PLDM_GET_FILE_TABLE_REQ_BYTES) 426 { 427 encode_get_file_table_resp(request->hdr.instance_id, 428 PLDM_ERROR_INVALID_LENGTH, 0, 0, nullptr, 0, 429 responsePtr); 430 return response; 431 } 432 433 auto rc = decode_get_file_table_req(request, payloadLength, &transferHandle, 434 &transferFlag, &tableType); 435 if (rc) 436 { 437 encode_get_file_table_resp(request->hdr.instance_id, rc, 0, 0, nullptr, 438 0, responsePtr); 439 return response; 440 } 441 442 if (tableType != PLDM_FILE_ATTRIBUTE_TABLE) 443 { 444 encode_get_file_table_resp(request->hdr.instance_id, 445 PLDM_INVALID_FILE_TABLE_TYPE, 0, 0, nullptr, 446 0, responsePtr); 447 return response; 448 } 449 450 using namespace pldm::filetable; 451 auto table = buildFileTable(FILE_TABLE_JSON); 452 auto attrTable = table(); 453 response.resize(response.size() + attrTable.size()); 454 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 455 456 if (attrTable.empty()) 457 { 458 encode_get_file_table_resp(request->hdr.instance_id, 459 PLDM_FILE_TABLE_UNAVAILABLE, 0, 0, nullptr, 460 0, responsePtr); 461 return response; 462 } 463 464 encode_get_file_table_resp(request->hdr.instance_id, PLDM_SUCCESS, 0, 465 PLDM_START_AND_END, attrTable.data(), 466 attrTable.size(), responsePtr); 467 return response; 468 } 469 470 Response Handler::readFile(const pldm_msg* request, size_t payloadLength) 471 { 472 uint32_t fileHandle = 0; 473 uint32_t offset = 0; 474 uint32_t length = 0; 475 476 Response response(sizeof(pldm_msg_hdr) + PLDM_READ_FILE_RESP_BYTES); 477 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 478 479 if (payloadLength != PLDM_READ_FILE_REQ_BYTES) 480 { 481 encode_read_file_resp(request->hdr.instance_id, 482 PLDM_ERROR_INVALID_LENGTH, length, responsePtr); 483 return response; 484 } 485 486 auto rc = decode_read_file_req(request, payloadLength, &fileHandle, &offset, 487 &length); 488 489 if (rc) 490 { 491 encode_read_file_resp(request->hdr.instance_id, rc, 0, responsePtr); 492 return response; 493 } 494 495 using namespace pldm::filetable; 496 auto& table = buildFileTable(FILE_TABLE_JSON); 497 FileEntry value{}; 498 499 try 500 { 501 value = table.at(fileHandle); 502 } 503 catch (const std::exception& e) 504 { 505 error("Handle ({HANDLE}) does not exist in the file table: {ERROR}", 506 "HANDLE", fileHandle, "ERROR", e); 507 508 encode_read_file_resp(request->hdr.instance_id, 509 PLDM_INVALID_FILE_HANDLE, length, responsePtr); 510 return response; 511 } 512 513 if (!fs::exists(value.fsPath)) 514 { 515 error("File does not exist, HANDLE={FILE_HANDLE}", "FILE_HANDLE", 516 fileHandle); 517 encode_read_file_resp(request->hdr.instance_id, 518 PLDM_INVALID_FILE_HANDLE, length, responsePtr); 519 return response; 520 } 521 522 auto fileSize = fs::file_size(value.fsPath); 523 if (offset >= fileSize) 524 { 525 error("Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE}", 526 "OFFSET", offset, "FILE_SIZE", fileSize); 527 encode_read_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE, 528 length, responsePtr); 529 return response; 530 } 531 532 if (offset + length > fileSize) 533 { 534 length = fileSize - offset; 535 } 536 537 response.resize(response.size() + length); 538 responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 539 auto fileDataPos = reinterpret_cast<char*>(responsePtr); 540 fileDataPos += sizeof(pldm_msg_hdr) + sizeof(uint8_t) + sizeof(length); 541 542 std::ifstream stream(value.fsPath, std::ios::in | std::ios::binary); 543 stream.seekg(offset); 544 stream.read(fileDataPos, length); 545 546 encode_read_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length, 547 responsePtr); 548 549 return response; 550 } 551 552 Response Handler::writeFile(const pldm_msg* request, size_t payloadLength) 553 { 554 uint32_t fileHandle = 0; 555 uint32_t offset = 0; 556 uint32_t length = 0; 557 size_t fileDataOffset = 0; 558 559 Response response(sizeof(pldm_msg_hdr) + PLDM_WRITE_FILE_RESP_BYTES); 560 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 561 562 if (payloadLength < PLDM_WRITE_FILE_REQ_BYTES) 563 { 564 encode_write_file_resp(request->hdr.instance_id, 565 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 566 return response; 567 } 568 569 auto rc = decode_write_file_req(request, payloadLength, &fileHandle, 570 &offset, &length, &fileDataOffset); 571 572 if (rc) 573 { 574 encode_write_file_resp(request->hdr.instance_id, rc, 0, responsePtr); 575 return response; 576 } 577 578 using namespace pldm::filetable; 579 auto& table = buildFileTable(FILE_TABLE_JSON); 580 FileEntry value{}; 581 582 try 583 { 584 value = table.at(fileHandle); 585 } 586 catch (const std::exception& e) 587 { 588 error("Handle ({HANDLE}) does not exist in the file table: {ERROR}", 589 "HANDLE", fileHandle, "ERROR", e); 590 encode_write_file_resp(request->hdr.instance_id, 591 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 592 return response; 593 } 594 595 if (!fs::exists(value.fsPath)) 596 { 597 error("File does not exist, HANDLE={FILE_HANDLE}", "FILE_HANDLE", 598 fileHandle); 599 encode_write_file_resp(request->hdr.instance_id, 600 PLDM_INVALID_FILE_HANDLE, 0, responsePtr); 601 return response; 602 } 603 604 auto fileSize = fs::file_size(value.fsPath); 605 if (offset >= fileSize) 606 { 607 error("Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE}", 608 "OFFSET", offset, "FILE_SIZE", fileSize); 609 encode_write_file_resp(request->hdr.instance_id, PLDM_DATA_OUT_OF_RANGE, 610 0, responsePtr); 611 return response; 612 } 613 614 auto fileDataPos = reinterpret_cast<const char*>(request->payload) + 615 fileDataOffset; 616 617 std::ofstream stream(value.fsPath, 618 std::ios::in | std::ios::out | std::ios::binary); 619 stream.seekp(offset); 620 stream.write(fileDataPos, length); 621 622 encode_write_file_resp(request->hdr.instance_id, PLDM_SUCCESS, length, 623 responsePtr); 624 625 return response; 626 } 627 628 Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request, 629 size_t payloadLength, 630 oem_platform::Handler* oemPlatformHandler) 631 { 632 Response response( 633 sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0); 634 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 635 636 if (payloadLength != PLDM_RW_FILE_BY_TYPE_MEM_REQ_BYTES) 637 { 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 uint16_t fileType{}; 645 uint32_t fileHandle{}; 646 uint32_t offset{}; 647 uint32_t length{}; 648 uint64_t address{}; 649 auto rc = decode_rw_file_by_type_memory_req(request, payloadLength, 650 &fileType, &fileHandle, &offset, 651 &length, &address); 652 if (rc != PLDM_SUCCESS) 653 { 654 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 0, 655 responsePtr); 656 return response; 657 } 658 if (length % dma::minSize) 659 { 660 error("Length is not a multiple of DMA minSize, LENGTH={LEN}", "LEN", 661 length); 662 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, 663 PLDM_ERROR_INVALID_LENGTH, 0, 664 responsePtr); 665 return response; 666 } 667 668 std::unique_ptr<FileHandler> handler{}; 669 try 670 { 671 handler = getHandlerByType(fileType, fileHandle); 672 } 673 catch (const InternalFailure& e) 674 { 675 error("Unknown file type '{FILE_TYPE}': {ERROR} ", "FILE_TYPE", 676 fileType, "ERROR", e); 677 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, 678 PLDM_INVALID_FILE_TYPE, 0, 679 responsePtr); 680 return response; 681 } 682 683 rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY 684 ? handler->writeFromMemory(offset, length, address, 685 oemPlatformHandler) 686 : handler->readIntoMemory(offset, length, address, 687 oemPlatformHandler); 688 encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, 689 length, responsePtr); 690 return response; 691 } 692 693 Response Handler::writeFileByTypeFromMemory(const pldm_msg* request, 694 size_t payloadLength) 695 { 696 return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request, 697 payloadLength, oemPlatformHandler); 698 } 699 700 Response Handler::readFileByTypeIntoMemory(const pldm_msg* request, 701 size_t payloadLength) 702 { 703 return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request, 704 payloadLength, oemPlatformHandler); 705 } 706 707 Response Handler::writeFileByType(const pldm_msg* request, size_t payloadLength) 708 { 709 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES); 710 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 711 712 if (payloadLength < PLDM_RW_FILE_BY_TYPE_REQ_BYTES) 713 { 714 encode_rw_file_by_type_resp(request->hdr.instance_id, 715 PLDM_WRITE_FILE_BY_TYPE, 716 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 717 return response; 718 } 719 uint16_t fileType{}; 720 uint32_t fileHandle{}; 721 uint32_t offset{}; 722 uint32_t length{}; 723 724 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType, 725 &fileHandle, &offset, &length); 726 if (rc != PLDM_SUCCESS) 727 { 728 encode_rw_file_by_type_resp(request->hdr.instance_id, 729 PLDM_WRITE_FILE_BY_TYPE, rc, 0, 730 responsePtr); 731 return response; 732 } 733 734 std::unique_ptr<FileHandler> handler{}; 735 try 736 { 737 handler = getHandlerByType(fileType, fileHandle); 738 } 739 catch (const InternalFailure& e) 740 { 741 error("Unknown file type '{FILE_TYPE}': {ERROR}", "FILE_TYPE", fileType, 742 "ERROR", e); 743 encode_rw_file_by_type_resp(request->hdr.instance_id, 744 PLDM_WRITE_FILE_BY_TYPE, 745 PLDM_INVALID_FILE_TYPE, 0, responsePtr); 746 return response; 747 } 748 749 rc = handler->write(reinterpret_cast<const char*>( 750 request->payload + PLDM_RW_FILE_BY_TYPE_REQ_BYTES), 751 offset, length, oemPlatformHandler); 752 encode_rw_file_by_type_resp(request->hdr.instance_id, 753 PLDM_WRITE_FILE_BY_TYPE, rc, length, 754 responsePtr); 755 return response; 756 } 757 758 Response Handler::readFileByType(const pldm_msg* request, size_t payloadLength) 759 { 760 Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_RESP_BYTES); 761 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 762 763 if (payloadLength != PLDM_RW_FILE_BY_TYPE_REQ_BYTES) 764 { 765 encode_rw_file_by_type_resp(request->hdr.instance_id, 766 PLDM_READ_FILE_BY_TYPE, 767 PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); 768 return response; 769 } 770 uint16_t fileType{}; 771 uint32_t fileHandle{}; 772 uint32_t offset{}; 773 uint32_t length{}; 774 775 auto rc = decode_rw_file_by_type_req(request, payloadLength, &fileType, 776 &fileHandle, &offset, &length); 777 if (rc != PLDM_SUCCESS) 778 { 779 encode_rw_file_by_type_resp(request->hdr.instance_id, 780 PLDM_READ_FILE_BY_TYPE, rc, 0, responsePtr); 781 return response; 782 } 783 784 std::unique_ptr<FileHandler> handler{}; 785 try 786 { 787 handler = getHandlerByType(fileType, fileHandle); 788 } 789 catch (const InternalFailure& e) 790 { 791 error("Unknown file type '{FILE_TYPE}': {ERROR}", "FILE_TYPE", fileType, 792 "ERROR", e); 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 error("Unknown file type '{FILE_TYPE}': {ERROR}", "FILE_TYPE", fileType, 839 "ERROR", e); 840 encode_file_ack_resp(request->hdr.instance_id, PLDM_INVALID_FILE_TYPE, 841 responsePtr); 842 return response; 843 } 844 845 rc = handler->fileAck(fileStatus); 846 encode_file_ack_resp(request->hdr.instance_id, rc, responsePtr); 847 return response; 848 } 849 850 Response Handler::getAlertStatus(const pldm_msg* request, size_t payloadLength) 851 { 852 Response response(sizeof(pldm_msg_hdr) + PLDM_GET_ALERT_STATUS_RESP_BYTES); 853 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 854 if (payloadLength != PLDM_GET_ALERT_STATUS_REQ_BYTES) 855 { 856 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 857 } 858 859 uint8_t versionId{}; 860 861 auto rc = decode_get_alert_status_req(request, payloadLength, &versionId); 862 if (rc != PLDM_SUCCESS) 863 { 864 return CmdHandler::ccOnlyResponse(request, rc); 865 } 866 867 if (versionId != 0) 868 { 869 return CmdHandler::ccOnlyResponse(request, 870 PLDM_HOST_UNSUPPORTED_FORMAT_VERSION); 871 } 872 873 constexpr uint32_t rackEntry = 0xFF000030; 874 constexpr uint32_t priCecNode = 0x00008030; 875 rc = encode_get_alert_status_resp(request->hdr.instance_id, PLDM_SUCCESS, 876 rackEntry, priCecNode, responsePtr, 877 PLDM_GET_ALERT_STATUS_RESP_BYTES); 878 if (rc != PLDM_SUCCESS) 879 { 880 return CmdHandler::ccOnlyResponse(request, rc); 881 } 882 883 return response; 884 } 885 886 Response Handler::newFileAvailable(const pldm_msg* request, 887 size_t payloadLength) 888 { 889 Response response(sizeof(pldm_msg_hdr) + PLDM_NEW_FILE_RESP_BYTES); 890 891 if (payloadLength != PLDM_NEW_FILE_REQ_BYTES) 892 { 893 return CmdHandler::ccOnlyResponse(request, PLDM_ERROR_INVALID_LENGTH); 894 } 895 uint16_t fileType{}; 896 uint32_t fileHandle{}; 897 uint64_t length{}; 898 899 auto rc = decode_new_file_req(request, payloadLength, &fileType, 900 &fileHandle, &length); 901 902 if (rc != PLDM_SUCCESS) 903 { 904 return CmdHandler::ccOnlyResponse(request, rc); 905 } 906 907 std::unique_ptr<FileHandler> handler{}; 908 try 909 { 910 handler = getHandlerByType(fileType, fileHandle); 911 } 912 catch (const InternalFailure& e) 913 { 914 error("Unknown file type '{FILE_TYPE}': {ERROR}", "FILE_TYPE", fileType, 915 "ERROR", e); 916 return CmdHandler::ccOnlyResponse(request, PLDM_INVALID_FILE_TYPE); 917 } 918 919 rc = handler->newFileAvailable(length); 920 auto responsePtr = reinterpret_cast<pldm_msg*>(response.data()); 921 encode_new_file_resp(request->hdr.instance_id, rc, responsePtr); 922 return response; 923 } 924 925 } // namespace oem_ibm 926 } // namespace responder 927 } // namespace pldm 928