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