diff --git a/common/utils.hpp b/common/utils.hpp index ed02b1410..73dffd529 100644 --- a/common/utils.hpp +++ b/common/utils.hpp @@ -61,11 +61,13 @@ struct CustomFD CustomFD(CustomFD&&) = delete; CustomFD& operator=(CustomFD&&) = delete; - CustomFD(int fd) : fd(fd) {} + CustomFD(int fd, bool closeOnOutScope = true) : + fd(fd), closeOnOutScope(closeOnOutScope) + {} ~CustomFD() { - if (fd >= 0) + if (fd >= 0 && closeOnOutScope) { close(fd); } @@ -78,6 +80,7 @@ struct CustomFD private: int fd = -1; + bool closeOnOutScope; }; /** @brief Calculate the pad for PLDM data diff --git a/oem/ibm/libpldmresponder/file_io.cpp b/oem/ibm/libpldmresponder/file_io.cpp index 361c47975..2f87f2614 100644 --- a/oem/ibm/libpldmresponder/file_io.cpp +++ b/oem/ibm/libpldmresponder/file_io.cpp @@ -2,12 +2,12 @@ #include "libpldm/base.h" +#include "common/utils.hpp" #include "file_io_by_type.hpp" #include "file_table.hpp" #include "utils.hpp" #include "xyz/openbmc_project/Common/error.hpp" -#include #include #include #include @@ -27,11 +27,10 @@ namespace pldm { using namespace pldm::responder::utils; using namespace sdbusplus::xyz::openbmc_project::Common::Error; - namespace responder { -extern SocketWriteStatus socketWriteStatus; namespace fs = std::filesystem; + namespace dma { /** @struct AspeedXdmaOp @@ -48,35 +47,21 @@ struct AspeedXdmaOp //!< operation, true means a transfer from BMC to host. }; -constexpr auto xdmaDev = "/dev/aspeed-xdma"; - int DMA::transferHostDataToSocket(int fd, uint32_t length, uint64_t address) { - socketWriteStatus = NotReady; - static const size_t pageSize = getpagesize(); - uint32_t numPages = length / pageSize; - uint32_t pageAlignedLength = numPages * pageSize; - - if (length > pageAlignedLength) - { - pageAlignedLength += pageSize; - } - int dmaFd = -1; + uint32_t pageAlLength = getpageAlignedLength(); int rc = 0; - dmaFd = open(xdmaDev, O_RDWR); - if (dmaFd < 0) + int xdmaFd = getXdmaFd(); + if (xdmaFd < 0) { rc = -errno; error( - "transferHostDataToSocket : Failed to open the XDMA device, RC={RC}", + "transferHostDataToSocket: Failed to open the XDMA device, RC={RC}", "RC", rc); return rc; } - pldm::utils::CustomFD xdmaFd(dmaFd); - void* vgaMemDump = NULL; - vgaMemDump = mmap(nullptr, pageAlignedLength, PROT_READ, MAP_SHARED, - xdmaFd(), 0); + void* vgaMemDump = getXDMAsharedlocation(); if (MAP_FAILED == vgaMemDump) { rc = -errno; @@ -85,91 +70,94 @@ int DMA::transferHostDataToSocket(int fd, uint32_t length, uint64_t address) "RC", rc); return rc; } + auto mmapCleanup = [pageAlLength, &rc, this](void* vgaMem) { + if (rc != -EINTR) + { + munmap(vgaMem, pageAlLength); + memAddr = nullptr; + } + else + { + error( + "transferHostDataToSocket : Received interrupt during dump DMA transfer. Skipping Unmap"); + } + }; + std::unique_ptr vgaMemPtr(vgaMemDump, + mmapCleanup); AspeedXdmaOp xdmaOp; xdmaOp.upstream = 0; xdmaOp.hostAddr = address; xdmaOp.len = length; - - rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp)); + rc = write(xdmaFd, &xdmaOp, sizeof(xdmaOp)); if (rc < 0) { rc = -errno; error( - "transferHostDataToSocket : Failed to execute the DMA operation, RC={RC} ADDRESS={ADDR} LENGTH={LEN}", + "transferHostDataToSocket: Failed to execute the DMA operation, RC={RC} ADDRESS={ADDR} LENGTH={LEN}", "RC", rc, "ADDR", address, "LEN", length); - if (rc != -EINTR) - { - munmap(vgaMemDump, pageAlignedLength); - } - else - { - error( - "transferHostDataToSocket : Received interrupt during dump DMA transfer. Skipping Unmap"); - } return rc; } - std::thread dumpOffloadThread(writeToUnixSocket, fd, - static_cast(vgaMemDump), length); - dumpOffloadThread.detach(); + rc = writeToUnixSocket(fd, static_cast(vgaMemDump), length); + if (rc < 0) + { + rc = -errno; + close(fd); + error( + "transferHostDataToSocket: Closing socket as writeToUnixSocket faile with RC={RC}", + "RC", rc); + return rc; + } + rc = length; - return 0; + return rc; } int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length, uint64_t address, bool upstream) { - static const size_t pageSize = getpagesize(); - uint32_t numPages = length / pageSize; - uint32_t pageAlignedLength = numPages * pageSize; - - if (length > pageAlignedLength) - { - pageAlignedLength += pageSize; - } + uint32_t pageAlLength = getpageAlignedLength(); int rc = 0; - auto mmapCleanup = [pageAlignedLength, &rc](void* vgaMem) { - if (rc != -EINTR) - { - munmap(vgaMem, pageAlignedLength); - } - else - { - error("Received interrupt during DMA transfer. Skipping Unmap"); - } - }; - - int dmaFd = -1; - dmaFd = open(xdmaDev, O_RDWR); - if (dmaFd < 0) + int responseByte = 0; + int xdmaFd = getXdmaFd(); + if (xdmaFd < 0) { rc = -errno; error("transferDataHost : Failed to open the XDMA device, RC={RC}", "RC", rc); - return rc; + return -1; } - pldm::utils::CustomFD xdmaFd(dmaFd); - - void* vgaMem; - vgaMem = mmap(nullptr, pageAlignedLength, upstream ? PROT_WRITE : PROT_READ, - MAP_SHARED, xdmaFd(), 0); - if (MAP_FAILED == vgaMem) + void* vgaMem = getXDMAsharedlocation(); + if (vgaMem == MAP_FAILED) { rc = -errno; - error("transferDataHost : Failed to mmap the XDMA device, RC={RC}", - "RC", rc); - return rc; + error( + "transferDataHost : Failed to mmap the XDMA device address, RC={RC}", + "RC", rc); + return -1; } + auto mmapCleanup = [pageAlLength, &rc, this](void* vgaMem) { + if (rc != -EINTR) + { + munmap(vgaMem, pageAlLength); + memAddr = nullptr; + } + else + { + error( + "transferDataHost: Received interrupt during DMA transfer. Skipping Unmap."); + } + }; std::unique_ptr vgaMemPtr(vgaMem, mmapCleanup); - if (upstream) { rc = lseek(fd, offset, SEEK_SET); if (rc == -1) { + rc = -errno; error( "transferDataHost upstream : lseek failed, ERROR={ERR}, UPSTREAM={UP_STRM}, OFFSET={KEY2}", "ERR", errno, "UP_STRM", upstream, "OFFSET", offset); @@ -184,6 +172,7 @@ int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length, rc = read(fd, buffer.data(), length); if (rc == -1) { + rc = -errno; error( "transferDataHost upstream : file read failed, ERROR={ERR}, UPSTREAM={UP_STRM}, LENGTH={LEN}, OFFSET={OFFSET}", "ERR", errno, "UP_STRM", upstream, "LEN", length, "OFFSET", @@ -197,6 +186,7 @@ int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length, "LEN", length, "RC", rc); return -1; } + responseByte = rc; memcpy(static_cast(vgaMemPtr.get()), buffer.data(), pageAlignedLength); } @@ -206,7 +196,7 @@ int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length, xdmaOp.hostAddr = address; xdmaOp.len = length; - rc = write(xdmaFd(), &xdmaOp, sizeof(xdmaOp)); + rc = write(xdmaFd, &xdmaOp, sizeof(xdmaOp)); if (rc < 0) { rc = -errno; @@ -221,23 +211,34 @@ int DMA::transferDataHost(int fd, uint32_t offset, uint32_t length, rc = lseek(fd, offset, SEEK_SET); if (rc == -1) { + rc = -errno; error( "transferDataHost downstream : lseek failed, ERROR={ERR}, UPSTREAM={UP_STRM}, OFFSET={OFFSET}", "ERR", errno, "UP_STRM", upstream, "OFFSET", offset); return rc; } + rc = write(fd, static_cast(vgaMemPtr.get()), length); if (rc == -1) { + rc = -errno; error( "transferDataHost downstream : file write failed, ERROR={ERR}, UPSTREAM={UP_STRM}, LENGTH={LEN}, OFFSET={OFFSET}", "ERR", errno, "UP_STRM", upstream, "LEN", length, "OFFSET", offset); return rc; } + responseByte = rc; } - return 0; + if (responseByte != static_cast(length)) + { + error( + "transferDataHost Response : mismatch between number of characters to transfer and the length transferred, LENGTH={LEN} COUNT={RC}", + "LEN", length, "RC", rc); + return -1; + } + return responseByte; } } // namespace dma @@ -319,14 +320,28 @@ Response Handler::readFileIntoMemory(const pldm_msg* request, encode_rw_file_memory_resp(request->hdr.instance_id, PLDM_READ_FILE_INTO_MEMORY, PLDM_ERROR_INVALID_LENGTH, 0, responsePtr); + } + int file = open(value.fsPath.c_str(), O_NONBLOCK | O_RDONLY); + if (file == -1) + { + error("File does not exist, path ={PATH}", "PATH", + value.fsPath.string()); + encode_rw_file_memory_resp(request->hdr.instance_id, + PLDM_READ_FILE_INTO_MEMORY, PLDM_ERROR, 0, + responsePtr); return response; } - using namespace dma; - DMA intf; - return transferAll(&intf, PLDM_READ_FILE_INTO_MEMORY, value.fsPath, - offset, length, address, true, - request->hdr.instance_id); + responseHdr.instance_id = request->hdr.instance_id; + responseHdr.command = PLDM_READ_FILE_INTO_MEMORY; + responseHdr.functionPtr = nullptr; + responseHdr.key = responseHdr.respInterface->getRequestHeaderIndex(); + pldm::utils::CustomFD fd(file, false); + sdeventplus::Event event = sdeventplus::Event::get_default(); + std::shared_ptr intf = std::make_shared(length); + transferAll(std::move(intf), fd(), offset, length, address, true, + responseHdr, event); + return {}; } Response Handler::writeFileFromMemory(const pldm_msg* request, @@ -336,7 +351,6 @@ Response Handler::writeFileFromMemory(const pldm_msg* request, uint32_t offset = 0; uint32_t length = 0; uint64_t address = 0; - Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0); auto responsePtr = reinterpret_cast(response.data()); @@ -350,7 +364,6 @@ Response Handler::writeFileFromMemory(const pldm_msg* request, decode_rw_file_memory_req(request, payloadLength, &fileHandle, &offset, &length, &address); - if ((length == 0) || (length % dma::minSize)) { error("Write length is not a multiple of DMA minSize, LENGTH={LEN}", @@ -402,11 +415,36 @@ Response Handler::writeFileFromMemory(const pldm_msg* request, return response; } + int flags{}; + if (fs::exists(value.fsPath)) + { + flags = O_RDWR; + } + else + { + flags = O_WRONLY; + } + int file = open(value.fsPath.c_str(), O_NONBLOCK | flags); + if (file == -1) + { + error("File does not exist, path ={PATH}", "PATH", + value.fsPath.string()); + encode_rw_file_memory_resp(request->hdr.instance_id, + PLDM_WRITE_FILE_FROM_MEMORY, PLDM_ERROR, 0, + responsePtr); + return response; + } using namespace dma; - DMA intf; - return transferAll(&intf, PLDM_WRITE_FILE_FROM_MEMORY, value.fsPath, - offset, length, address, false, - request->hdr.instance_id); + responseHdr.instance_id = request->hdr.instance_id; + responseHdr.command = PLDM_WRITE_FILE_FROM_MEMORY; + responseHdr.functionPtr = nullptr; + responseHdr.key = responseHdr.respInterface->getRequestHeaderIndex(); + pldm::utils::CustomFD fd(file, false); + sdeventplus::Event event = sdeventplus::Event::get_default(); + std::shared_ptr intf = std::make_shared(length); + transferAll(std::move(intf), fd(), offset, length, address, false, + responseHdr, event); + return {}; } Response Handler::getFileTable(const pldm_msg* request, size_t payloadLength) @@ -626,7 +664,8 @@ Response Handler::writeFile(const pldm_msg* request, size_t payloadLength) Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request, size_t payloadLength, - oem_platform::Handler* oemPlatformHandler) + oem_platform::Handler* oemPlatformHandler, + ResponseHdr& responseHdr) { Response response( sizeof(pldm_msg_hdr) + PLDM_RW_FILE_BY_TYPE_MEM_RESP_BYTES, 0); @@ -664,43 +703,55 @@ Response rwFileByTypeIntoMemory(uint8_t cmd, const pldm_msg* request, return response; } - std::unique_ptr handler{}; + std::shared_ptr handler{}; try { - handler = getHandlerByType(fileType, fileHandle); + handler = getSharedHandlerByType(fileType, fileHandle); } catch (const InternalFailure& e) { - error("unknown file type, TYPE={LEN} ERROR={ERR_EXCEP}", "LEN", - fileType, "ERR_EXCEP", e.what()); + error("Unknown file type {TYPE}: {ERROR}", "TYPE", fileType, "ERROR", + e); encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, PLDM_INVALID_FILE_TYPE, 0, responsePtr); return response; } - rc = cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY - ? handler->writeFromMemory(offset, length, address, - oemPlatformHandler) - : handler->readIntoMemory(offset, length, address, - oemPlatformHandler); - encode_rw_file_by_type_memory_resp(request->hdr.instance_id, cmd, rc, - length, responsePtr); - return response; + responseHdr.functionPtr = handler; + responseHdr.instance_id = request->hdr.instance_id; + responseHdr.command = cmd; + responseHdr.key = responseHdr.respInterface->getRequestHeaderIndex(); + sdeventplus::Event event = sdeventplus::Event::get_default(); + + if (cmd == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY) + { + handler->writeFromMemory(offset, length, address, oemPlatformHandler, + responseHdr, event); + } + else + { + handler->readIntoMemory(offset, length, address, oemPlatformHandler, + responseHdr, event); + } + + return {}; } Response Handler::writeFileByTypeFromMemory(const pldm_msg* request, size_t payloadLength) { return rwFileByTypeIntoMemory(PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY, request, - payloadLength, oemPlatformHandler); + payloadLength, oemPlatformHandler, + responseHdr); } Response Handler::readFileByTypeIntoMemory(const pldm_msg* request, size_t payloadLength) { return rwFileByTypeIntoMemory(PLDM_READ_FILE_BY_TYPE_INTO_MEMORY, request, - payloadLength, oemPlatformHandler); + payloadLength, oemPlatformHandler, + responseHdr); } Response Handler::writeFileByType(const pldm_msg* request, size_t payloadLength) @@ -737,8 +788,8 @@ Response Handler::writeFileByType(const pldm_msg* request, size_t payloadLength) } catch (const InternalFailure& e) { - error("unknown file type, TYPE={FILE_TYP} ERROR={ERR_EXCEP}", - "FILE_TYP", fileType, "ERR_EXCEP", e.what()); + error("Unknown file type {TYPE}: {ERROR}", "TYPE", fileType, "ERROR", + e); encode_rw_file_by_type_resp(request->hdr.instance_id, PLDM_WRITE_FILE_BY_TYPE, PLDM_INVALID_FILE_TYPE, 0, responsePtr); @@ -787,8 +838,8 @@ Response Handler::readFileByType(const pldm_msg* request, size_t payloadLength) } catch (const InternalFailure& e) { - error("unknown file type, TYPE={FILE_TYP} ERROR={ERR_EXCEP}", - "FILE_TYP", fileType, "ERR_EXCEP", e.what()); + error("Unknown file type {TYPE}: {ERROR}", "TYPE", fileType, "ERROR", + e); encode_rw_file_by_type_resp(request->hdr.instance_id, PLDM_READ_FILE_BY_TYPE, PLDM_INVALID_FILE_TYPE, 0, responsePtr); @@ -910,8 +961,8 @@ Response Handler::newFileAvailable(const pldm_msg* request, } catch (const InternalFailure& e) { - error("unknown file type, TYPE={FILE_TYP} ERROR={ERR_EXCEP}", - "FILE_TYP", fileType, "ERR_EXCEP", e.what()); + error("Unknown file type {TYPE}: {ERROR}", "TYPE", fileType, "ERROR", + e); return CmdHandler::ccOnlyResponse(request, PLDM_INVALID_FILE_TYPE); } diff --git a/oem/ibm/libpldmresponder/file_io.hpp b/oem/ibm/libpldmresponder/file_io.hpp index 4bd6f43db..5a80e6ca7 100644 --- a/oem/ibm/libpldmresponder/file_io.hpp +++ b/oem/ibm/libpldmresponder/file_io.hpp @@ -1,9 +1,11 @@ #pragma once #include "common/utils.hpp" +#include "file_io_by_type.hpp" #include "oem/ibm/requester/dbus_to_file_handler.hpp" #include "oem_ibm_handler.hpp" #include "pldmd/handler.hpp" +#include "pldmd/pldm_resp_interface.hpp" #include "requester/handler.hpp" #include @@ -11,6 +13,7 @@ #include #include #include +#include #include #include #include @@ -18,6 +21,7 @@ #include #include +#include #include #include @@ -29,6 +33,15 @@ namespace responder { namespace dma { +constexpr auto xdmaDev = "/dev/aspeed-xdma"; + +struct FileMetaData +{ + uint32_t length; + uint32_t offset; + uint64_t address; +}; + // The minimum data size of dma transfer in bytes constexpr uint32_t minSize = 16; @@ -39,23 +52,249 @@ namespace fs = std::filesystem; /** * @class DMA * - * Expose API to initiate transfer of data by DMA + * Expose API to initiate data transfer by DMA asynchronously * * This class only exposes the public API transferDataHost to transfer data - * between BMC and host using DMA. This allows for mocking the transferDataHost - * for unit testing purposes. + * between BMC and host using DMA using non blocking socket. + * */ class DMA { + /** @brief DMA constructor is private to avoid object creation + * without lengh. + */ + DMA() {} + public: + /** @brief DMA constructor + * @param length - using length allocating shared memory to transfer data. + */ + DMA(uint32_t length) + { + responseReceived = false; + memAddr = nullptr; + xdmaFd = -1; + sourceFd = -1; + rc = 0; + iotPtr = nullptr; + iotPtrbc = nullptr; + timer = nullptr; + m_length = length; + static const size_t pageSize = getpagesize(); + uint32_t numPages = m_length / pageSize; + pageAlignedLength = numPages * pageSize; + if (m_length > pageAlignedLength) + { + pageAlignedLength += pageSize; + } + } + + /** @brief DMA destructor + */ + ~DMA() + { + if (iotPtr != nullptr) + { + iotPtrbc = iotPtr.release(); + } + + if (iotPtrbc != nullptr) + { + delete iotPtrbc; + iotPtrbc = nullptr; + } + + if (timer != nullptr) + { + auto time = timer.release(); + delete time; + } + + if (xdmaFd > 0) + { + close(xdmaFd); + xdmaFd = -1; + } + if (sourceFd > 0) + { + close(sourceFd); + sourceFd = -1; + } + } + /** @brief Method to fetch the shared memory file descriptor for data + * transfer + * @return returns shared memory file descriptor + */ + int getNewXdmaFd() + { + try + { + xdmaFd = open(xdmaDev, O_RDWR | O_NONBLOCK); + } + catch (...) + { + xdmaFd = -1; + } + return xdmaFd; + } + /** @brief Method to fetch the existing shared memory file descriptor for + * data transfer + * @return returns existing shared memory file descriptor + */ + int getXdmaFd() + { + if (xdmaFd > 0) + { + return xdmaFd; + } + return getNewXdmaFd(); + } + + /** @brief function will keep one copy of fd for exception case so it + * can close it. + * @param[in] fd- source path file descriptor + */ + void setDMASourceFd(int fd) + { + sourceFd = fd; + } + + /** @brief function will keep one copy of shared memory fd for exception + * case so it can close it. + * @param[in] fd - xdma shared memory path file descriptor + */ + void setXDMASourceFd(int fd) + { + xdmaFd = fd; + } + + /** @brief function will return pagealignedlength to allocate memory for + * data transfer. + */ + int32_t getpageAlignedLength() + { + return pageAlignedLength; + } + + /** @brief function will return shared memory address + * from XDMA drive path + */ + void* getXDMAsharedlocation() + { + if (xdmaFd < 0) + { + error( + "DMA : Failed to get memory location due to invalid file descriptor."); + return MAP_FAILED; + } + + memAddr = mmap(nullptr, pageAlignedLength, PROT_WRITE | PROT_READ, + MAP_SHARED, xdmaFd, 0); + if (MAP_FAILED == memAddr) + { + rc = -errno; + return MAP_FAILED; + } + + return memAddr; + } + + /** @brief Method to update file related metadata + */ + void setFileMetaData(FileMetaData& data) + { + fileMetaData.address = data.address; + fileMetaData.offset = data.offset; + fileMetaData.length = data.length; + } + + /** @brief Method to get file related metadata + */ + FileMetaData& getFileMetaData() + { + return fileMetaData; + } + + /** @brief Method to initialize IO instance for event loop + * @param[in] ioptr - pointer to manage eventloop + */ + void insertIOInstance(std::unique_ptr&& ioptr) + { + iotPtr = std::move(ioptr); + } + + /** @brief Method to initialize timer for each tranfer + * + * @return returns true if timer creation success else false + * + */ + bool initTimer( + sdeventplus::Event& event, + fu2::unique_function&& callback) + { + try + { + timer = std::make_unique( + event, (Clock(event).now() + std::chrono::seconds{20}), + std::chrono::seconds{1}, std::move(callback)); + } + catch (const std::runtime_error& e) + { + error("Failed to start the timer for event loop. error = {ERROR}", + "ERROR", e.what()); + return false; + } + return true; + } + + /** @brief Method to delete cyclic dependecy while deleting object + * DMA interface and IO event loop has cyclic dependecy + * + * @return void + */ + void deleteIOInstance() + { + if (timer != nullptr) + { + auto time = timer.release(); + delete time; + } + if (iotPtr != nullptr) + { + iotPtrbc = iotPtr.release(); + } + } + + /** @brief Method to set value for response received + * + * @return returns void + * + */ + void setResponseReceived(bool bresponse) + { + responseReceived = bresponse; + } + + /** @brief Method to get value of responseReceived to know tranfer + * success/fail. + * + * @return returns true if transfer success else false. + * + */ + bool getResponseReceived() + { + return responseReceived; + } + /** @brief API to transfer data between BMC and host using DMA * - * @param[in] path - pathname of the file to transfer data from or to + * @param[in] path - pathname of the file to transfer data from or + * to * @param[in] offset - offset in the file * @param[in] length - length of the data to transfer * @param[in] address - DMA address on the host - * @param[in] upstream - indicates direction of the transfer; true indicates - * transfer to the host + * @param[in] upstream - indicates direction of the transfer; true + * indicates transfer to the host * * @return returns 0 on success, negative errno on failure */ @@ -64,13 +303,27 @@ class DMA /** @brief API to transfer data on to unix socket from host using DMA * - * @param[in] path - pathname of the file to transfer data from or to + * @param[in] path - pathname of the file to transfer data from or + * to * @param[in] length - length of the data to transfer * @param[in] address - DMA address on the host * * @return returns 0 on success, negative errno on failure */ int transferHostDataToSocket(int fd, uint32_t length, uint64_t address); + + private: + bool responseReceived; + void* memAddr; + int xdmaFd; + int sourceFd; + uint32_t pageAlignedLength; + int rc; + std::unique_ptr iotPtr; + IO* iotPtrbc; + std::unique_ptr timer; + uint32_t m_length; + FileMetaData fileMetaData; }; /** @brief Transfer the data between BMC and host using DMA. @@ -89,69 +342,181 @@ class DMA * @param[in] upstream - indicates direction of the transfer; true indicates * transfer to the host * @param[in] instanceId - Message's instance id + * @param[in] responseHdr- contain response interface related data * @return PLDM response message */ template -Response transferAll(DMAInterface* intf, uint8_t command, fs::path& path, +Response transferAll(std::shared_ptr intf, int32_t file, uint32_t offset, uint32_t length, uint64_t address, - bool upstream, uint8_t instanceId) + bool upstream, ResponseHdr& responseHdr, + sdeventplus::Event& event) { - uint32_t origLength = length; - Response response(sizeof(pldm_msg_hdr) + PLDM_RW_FILE_MEM_RESP_BYTES, 0); - auto responsePtr = reinterpret_cast(response.data()); - - int flags{}; - if (upstream) - { - flags = O_RDONLY; - } - else if (fs::exists(path)) - { - flags = O_RDWR; - } - else - { - flags = O_WRONLY; - } - int file = open(path.string().c_str(), flags); - if (file == -1) + uint8_t command = responseHdr.command; + uint8_t instance_id = responseHdr.instance_id; + int key = responseHdr.key; + if (nullptr == intf) { - error("File does not exist, path = {FILE_PATH}", "FILE_PATH", - path.string()); - encode_rw_file_memory_resp(instanceId, command, PLDM_ERROR, 0, + Response response(sizeof(pldm_msg_hdr) + command, 0); + auto responsePtr = reinterpret_cast(response.data()); + encode_rw_file_memory_resp(instance_id, command, PLDM_ERROR, 0, responsePtr); - return response; + error("transferAll : xdma interface initialization failed.\n"); + if (responseHdr.respInterface != nullptr) + { + responseHdr.respInterface->sendPLDMRespMsg(response, key); + } + close(file); + return {}; } - pldm::utils::CustomFD fd(file); + intf->setDMASourceFd(file); + uint32_t origLength = length; + static auto& bus = pldm::utils::DBusHandler::getBus(); + bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); + std::weak_ptr wInterface = intf; + + dma::FileMetaData data; + data.length = length; + data.offset = offset; + data.address = address; + intf->setFileMetaData(data); + auto timerCb = [=](Timer& /*source*/, Timer::TimePoint /*time*/) { + if (!intf->getResponseReceived()) + { + error( + "transferAll : EventLoop Timeout..!! Terminating data tranfer file operation.\n"); + Response response(sizeof(pldm_msg_hdr) + command, 0); + auto responsePtr = reinterpret_cast(response.data()); + encode_rw_file_memory_resp(instance_id, command, PLDM_ERROR, 0, + responsePtr); + if (responseHdr.respInterface != nullptr) + { + responseHdr.respInterface->sendPLDMRespMsg(response, key); + } + intf->deleteIOInstance(); + (static_cast>(intf)).reset(); + } + return; + }; - while (length > dma::maxSize) - { - auto rc = intf->transferDataHost(fd(), offset, dma::maxSize, address, - upstream); + auto callback = [=](IO&, int, uint32_t revents) { + if (!(revents & (EPOLLIN | EPOLLOUT))) + { + return; + } + auto weakPtr = wInterface.lock(); + dma::FileMetaData& data = weakPtr->getFileMetaData(); + Response response(sizeof(pldm_msg_hdr) + command, 0); + auto responsePtr = reinterpret_cast(response.data()); + int rc = 0; + + while (data.length > dma::maxSize) + { + rc = weakPtr->transferDataHost(file, data.offset, dma::maxSize, + data.address, upstream); + + data.length -= dma::maxSize; + data.offset += dma::maxSize; + data.address += dma::maxSize; + if (rc < 0) + { + encode_rw_file_memory_resp(instance_id, command, PLDM_ERROR, 0, + responsePtr); + error( + "transferAll : Failed to transfer muliple chunks of data to host.\n"); + if (responseHdr.respInterface != nullptr) + { + responseHdr.respInterface->sendPLDMRespMsg(response, key); + } + weakPtr->deleteIOInstance(); + (static_cast>(wInterface)).reset(); + return; + } + } + rc = weakPtr->transferDataHost(file, data.offset, data.length, + data.address, upstream); if (rc < 0) { - encode_rw_file_memory_resp(instanceId, command, PLDM_ERROR, 0, + encode_rw_file_memory_resp(instance_id, command, PLDM_ERROR, 0, responsePtr); - return response; + error( + "transferAll : Failed to transfer single chunks of data to host.\n"); + if (responseHdr.respInterface != nullptr) + { + responseHdr.respInterface->sendPLDMRespMsg(response, key); + } + weakPtr->deleteIOInstance(); + (static_cast>(wInterface)).reset(); + return; } + if (static_cast(data.length) == rc) + { + weakPtr->setResponseReceived(true); + encode_rw_file_memory_resp(instance_id, command, PLDM_SUCCESS, + origLength, responsePtr); + if (responseHdr.respInterface != nullptr) + { + responseHdr.respInterface->sendPLDMRespMsg(response, key); + } + weakPtr->deleteIOInstance(); + (static_cast>(wInterface)).reset(); + return; + } + }; - offset += dma::maxSize; - length -= dma::maxSize; - address += dma::maxSize; + try + { + int xdmaFd = intf->getNewXdmaFd(); + if (xdmaFd < 0) + { + Response response(sizeof(pldm_msg_hdr) + command, 0); + auto responsePtr = reinterpret_cast(response.data()); + error("transferAll : Failed to get the XDMA file descriptor.\n"); + encode_rw_file_memory_resp(instance_id, command, PLDM_ERROR, 0, + responsePtr); + if (responseHdr.respInterface != nullptr) + { + responseHdr.respInterface->sendPLDMRespMsg(response, key); + } + intf->deleteIOInstance(); + (static_cast>(intf)).reset(); + return {}; + } + if (intf->initTimer(event, std::move(timerCb)) == false) + { + Response response(sizeof(pldm_msg_hdr) + command, 0); + auto responsePtr = reinterpret_cast(response.data()); + encode_rw_file_memory_resp(instance_id, command, PLDM_ERROR, 0, + responsePtr); + error("transferAll : Failed to start the event timer."); + if (responseHdr.respInterface != nullptr) + { + responseHdr.respInterface->sendPLDMRespMsg(response, key); + } + intf->deleteIOInstance(); + (static_cast>(intf)).reset(); + return {}; + } + intf->insertIOInstance(std::move(std::make_unique( + event, xdmaFd, EPOLLIN | EPOLLOUT, std::move(callback)))); } - - auto rc = intf->transferDataHost(fd(), offset, length, address, upstream); - if (rc < 0) + catch (const std::runtime_error& e) { - encode_rw_file_memory_resp(instanceId, command, PLDM_ERROR, 0, + Response response(sizeof(pldm_msg_hdr) + command, 0); + auto responsePtr = reinterpret_cast(response.data()); + error( + "transferAll : Failed to start the event loop. error ={ERR_EXCEP} ", + "ERR_EXCEP", e.what()); + encode_rw_file_memory_resp(instance_id, command, PLDM_ERROR, 0, responsePtr); - return response; + if (responseHdr.respInterface != nullptr) + { + responseHdr.respInterface->sendPLDMRespMsg(response, key); + } + intf->deleteIOInstance(); + (static_cast>(intf)).reset(); } - - encode_rw_file_memory_resp(instanceId, command, PLDM_SUCCESS, origLength, - responsePtr); - return response; + return {}; } } // namespace dma @@ -167,15 +532,18 @@ static constexpr auto certAuthority = static constexpr auto codLicObjPath = "/com/ibm/license"; static constexpr auto codLicInterface = "com.ibm.License.LicenseManager"; + class Handler : public CmdHandler { public: Handler(oem_platform::Handler* oemPlatformHandler, int hostSockFd, uint8_t hostEid, dbus_api::Requester* dbusImplReqester, - pldm::requester::Handler* handler) : + pldm::requester::Handler* handler, + pldm::response_api::Transport* respInterface) : oemPlatformHandler(oemPlatformHandler), hostSockFd(hostSockFd), hostEid(hostEid), - dbusImplReqester(dbusImplReqester), handler(handler) + dbusImplReqester(dbusImplReqester), handler(handler), + responseHdr({0, 0, respInterface, 0, -1}) { handlers.emplace(PLDM_READ_FILE_INTO_MEMORY, [this](const pldm_msg* request, size_t payloadLength) { @@ -490,6 +858,7 @@ class Handler : public CmdHandler pldm::requester::Handler* handler; std::vector> dbusToFileHandlers; + ResponseHdr responseHdr; }; } // namespace oem_ibm diff --git a/oem/ibm/libpldmresponder/file_io_by_type.cpp b/oem/ibm/libpldmresponder/file_io_by_type.cpp index ce030358e..1cf889ea0 100644 --- a/oem/ibm/libpldmresponder/file_io_by_type.cpp +++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp @@ -4,6 +4,7 @@ #include "libpldm/file_io.h" #include "common/utils.hpp" +#include "file_io.hpp" #include "file_io_type_cert.hpp" #include "file_io_type_chap.hpp" #include "file_io_type_dump.hpp" @@ -25,6 +26,7 @@ #include #include #include +#include #include PHOSPHOR_LOG2_USING; @@ -34,50 +36,318 @@ namespace pldm namespace responder { using namespace sdbusplus::xyz::openbmc_project::Common::Error; +using namespace sdeventplus; +using namespace sdeventplus::source; -int FileHandler::transferFileData(int32_t fd, bool upstream, uint32_t offset, - uint32_t& length, uint64_t address) +void FileHandler::dmaResponseToHost(const ResponseHdr& responseHdr, + const pldm_completion_codes rStatus, + uint32_t length) { - dma::DMA xdmaInterface; - while (length > dma::maxSize) + Response response(sizeof(pldm_msg_hdr) + responseHdr.command, 0); + auto responsePtr = reinterpret_cast(response.data()); + encode_rw_file_by_type_memory_resp(responseHdr.instance_id, + responseHdr.command, rStatus, length, + responsePtr); + if (nullptr != responseHdr.respInterface) { - auto rc = xdmaInterface.transferDataHost(fd, offset, dma::maxSize, - address, upstream); + responseHdr.respInterface->sendPLDMRespMsg(response, responseHdr.key); + } +} + +void FileHandler::dmaResponseToHost(const ResponseHdr& responseHdr, + const pldm_fileio_completion_codes rStatus, + uint32_t length) +{ + Response response(sizeof(pldm_msg_hdr) + responseHdr.command, 0); + auto responsePtr = reinterpret_cast(response.data()); + encode_rw_file_by_type_memory_resp(responseHdr.instance_id, + responseHdr.command, rStatus, length, + responsePtr); + if (nullptr != responseHdr.respInterface) + { + responseHdr.respInterface->sendPLDMRespMsg(response, responseHdr.key); + } +} + +void FileHandler::deleteAIOobjects( + const std::shared_ptr& xdmaInterface, + const ResponseHdr& responseHdr) +{ + if (nullptr != xdmaInterface) + { + xdmaInterface->deleteIOInstance(); + (static_cast>(xdmaInterface)).reset(); + } + + if (nullptr != responseHdr.functionPtr) + { + (static_cast>(responseHdr.functionPtr)) + .reset(); + } +} + +void FileHandler::transferFileData(int32_t fd, bool upstream, uint32_t offset, + uint32_t& length, uint64_t address, + ResponseHdr& responseHdr, + sdeventplus::Event& event) +{ + std::shared_ptr xdmaInterface = + std::make_shared(length); + if (nullptr == xdmaInterface) + { + error("transferFileData : xdma interface initialization failed.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + deleteAIOobjects(nullptr, responseHdr); + close(fd); + return; + } + xdmaInterface->setDMASourceFd(fd); + uint32_t origLength = length; + uint8_t command = responseHdr.command; + static auto& bus = pldm::utils::DBusHandler::getBus(); + bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); + dma::FileMetaData data; + data.length = length; + data.offset = offset; + data.address = address; + xdmaInterface->setFileMetaData(data); + std::weak_ptr wxInterface = xdmaInterface; + auto timerCb = [=, this](Timer& /*source*/, Timer::TimePoint /*time*/) { + if (!xdmaInterface->getResponseReceived()) + { + error( + "transferFileData : EventLoop Timeout..!! Terminating FileHandler data tranfer operation.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + deleteAIOobjects(xdmaInterface, responseHdr); + } + return; + }; + + auto callback = [=, this](IO&, int, uint32_t revents) { + if (!(revents & (EPOLLIN | EPOLLOUT))) + { + return; + } + auto wInterface = wxInterface.lock(); + dma::FileMetaData& data = wInterface->getFileMetaData(); + int rc = 0; + while (data.length > dma::maxSize) + { + rc = wInterface->transferDataHost(fd, data.offset, dma::maxSize, + data.address, upstream); + data.length -= dma::maxSize; + data.offset += dma::maxSize; + data.address += dma::maxSize; + if (rc < 0) + { + error( + "transferFileData : Failed to transfer muliple chunks of data to host.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + deleteAIOobjects(wInterface, responseHdr); + return; + } + } + rc = wInterface->transferDataHost(fd, data.offset, data.length, + data.address, upstream); if (rc < 0) { - return PLDM_ERROR; + error( + "transferFileData : Failed to transfer single chunks of data to host.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + deleteAIOobjects(wInterface, responseHdr); + return; } - offset += dma::maxSize; - length -= dma::maxSize; - address += dma::maxSize; + if (static_cast(data.length) == rc) + { + wInterface->setResponseReceived(true); + dmaResponseToHost(responseHdr, PLDM_SUCCESS, origLength); + if (responseHdr.functionPtr != nullptr) + { + responseHdr.functionPtr->postDataTransferCallBack( + command == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY); + } + deleteAIOobjects(wInterface, responseHdr); + return; + } + }; + try + { + int xdmaFd = xdmaInterface->getNewXdmaFd(); + if (xdmaFd < 0) + { + error("transferFileData : Failed to get the XDMA file descriptor."); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + deleteAIOobjects(xdmaInterface, responseHdr); + return; + } + if (xdmaInterface->initTimer(event, std::move(timerCb)) == false) + { + error("transferFileData : Failed to start the event timer.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + deleteAIOobjects(xdmaInterface, responseHdr); + return; + } + xdmaInterface->insertIOInstance(std::move(std::make_unique( + event, xdmaFd, EPOLLIN | EPOLLOUT, std::move(callback)))); + } + catch (const std::runtime_error& e) + { + error( + "transferFileData : Failed to start the event loop. error ={ERR_EXCEP} ", + "ERR_EXCEP", e.what()); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + deleteAIOobjects(xdmaInterface, responseHdr); } - auto rc = xdmaInterface.transferDataHost(fd, offset, length, address, - upstream); - return rc < 0 ? PLDM_ERROR : PLDM_SUCCESS; } -int FileHandler::transferFileDataToSocket(int32_t fd, uint32_t& length, - uint64_t address) +void FileHandler::transferFileDataToSocket(int32_t fd, uint32_t& length, + uint64_t address, + ResponseHdr& responseHdr, + sdeventplus::Event& event) { - dma::DMA xdmaInterface; - while (length > dma::maxSize) + std::shared_ptr xdmaInterface = + std::make_shared(length); + uint8_t command = responseHdr.command; + if (nullptr == xdmaInterface) { - auto rc = xdmaInterface.transferHostDataToSocket(fd, dma::maxSize, - address); + error( + "transferFileDataToSocket : xdma interface initialization failed.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + if (responseHdr.functionPtr != nullptr) + { + responseHdr.functionPtr->postDataTransferCallBack( + command == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY); + } + deleteAIOobjects(nullptr, responseHdr); + return; + } + uint32_t origLength = length; + static auto& bus = pldm::utils::DBusHandler::getBus(); + bus.attach_event(event.get(), SD_EVENT_PRIORITY_NORMAL); + dma::FileMetaData data; + data.length = length; + data.address = address; + xdmaInterface->setFileMetaData(data); + std::weak_ptr wxInterface = xdmaInterface; + std::weak_ptr wxfunctionPtr = responseHdr.functionPtr; + auto timerCb = [=, this](Timer& /*source*/, Timer::TimePoint /*time*/) { + if (!xdmaInterface->getResponseReceived()) + { + error( + "EventLoop Timeout...Terminating socket data tranfer operation\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + if (responseHdr.functionPtr != nullptr) + { + responseHdr.functionPtr->postDataTransferCallBack( + command == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY); + } + deleteAIOobjects(xdmaInterface, responseHdr); + } + return; + }; + auto callback = [=, this](IO&, int, uint32_t revents) { + if (!(revents & (EPOLLIN | EPOLLOUT))) + { + return; + } + auto wInterface = wxInterface.lock(); + dma::FileMetaData& data = wInterface->getFileMetaData(); + int rc = 0; + while (data.length > dma::maxSize) + { + rc = wInterface->transferHostDataToSocket(fd, dma::maxSize, + data.address); + data.length -= dma::maxSize; + data.address += dma::maxSize; + if (rc < 0) + { + error( + "transferFileDataToSocket : Failed to transfer muliple chunks of data to host.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + if (responseHdr.functionPtr != nullptr) + { + responseHdr.functionPtr->postDataTransferCallBack( + command == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY); + } + deleteAIOobjects(wInterface, responseHdr); + return; + } + } + rc = wInterface->transferHostDataToSocket(fd, data.length, + data.address); if (rc < 0) { - return PLDM_ERROR; + error( + "transferFileDataToSocket : Failed to transfer single chunks of data to host.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + if (responseHdr.functionPtr != nullptr) + { + responseHdr.functionPtr->postDataTransferCallBack( + command == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY); + } + deleteAIOobjects(wInterface, responseHdr); + return; + } + if (static_cast(data.length) == rc) + { + wInterface->setResponseReceived(true); + dmaResponseToHost(responseHdr, PLDM_SUCCESS, origLength); + deleteAIOobjects(wInterface, responseHdr); + return; + } + }; + try + { + int xdmaFd = xdmaInterface->getNewXdmaFd(); + if (xdmaFd < 0) + { + error( + "transferFileDataToSocket : Failed to open shared memory location."); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + if (responseHdr.functionPtr != nullptr) + { + responseHdr.functionPtr->postDataTransferCallBack( + command == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY); + } + deleteAIOobjects(xdmaInterface, responseHdr); + return; + } + if (xdmaInterface->initTimer(event, std::move(timerCb)) == false) + { + error( + "transferFileDataToSocket : Failed to start the event timer.\n"); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + if (responseHdr.functionPtr != nullptr) + { + responseHdr.functionPtr->postDataTransferCallBack( + command == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY); + } + deleteAIOobjects(xdmaInterface, responseHdr); + return; + } + xdmaInterface->insertIOInstance(std::move(std::make_unique( + event, xdmaFd, EPOLLIN | EPOLLOUT, std::move(callback)))); + } + catch (const std::runtime_error& e) + { + error( + "transferFileDataToSocket : Failed to start the event loop. error ={ERR_EXCEP} ", + "ERR_EXCEP", e.what()); + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + if (responseHdr.functionPtr != nullptr) + { + responseHdr.functionPtr->postDataTransferCallBack( + command == PLDM_WRITE_FILE_BY_TYPE_FROM_MEMORY); } - length -= dma::maxSize; - address += dma::maxSize; + deleteAIOobjects(xdmaInterface, responseHdr); } - auto rc = xdmaInterface.transferHostDataToSocket(fd, length, address); - return rc < 0 ? PLDM_ERROR : PLDM_SUCCESS; + return; } -int FileHandler::transferFileData(const fs::path& path, bool upstream, - uint32_t offset, uint32_t& length, - uint64_t address) +void FileHandler::transferFileData(const fs::path& path, bool upstream, + uint32_t offset, uint32_t& length, + uint64_t address, ResponseHdr& responseHdr, + sdeventplus::Event& event) { bool fileExists = false; if (upstream) @@ -86,17 +356,21 @@ int FileHandler::transferFileData(const fs::path& path, bool upstream, if (!fileExists) { error("File does not exist. PATH={PATH}", "PATH", path.c_str()); - return PLDM_INVALID_FILE_HANDLE; + dmaResponseToHost(responseHdr, PLDM_INVALID_FILE_HANDLE, length); + deleteAIOobjects(nullptr, responseHdr); + return; } size_t fileSize = fs::file_size(path); if (offset >= fileSize) { error( - "FileHandler::transferFileData: Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE} FILE_HANDLE={FILE_HANDLE}", + " transferFileData : FileHandler::transferFileData: Offset exceeds file size, OFFSET={OFFSET} FILE_SIZE={FILE_SIZE} FILE_HANDLE={FILE_HANDLE}", "OFFSET", offset, "FILE_SIZE", fileSize, "FILE_HANDLE", fileHandle); - return PLDM_DATA_OUT_OF_RANGE; + dmaResponseToHost(responseHdr, PLDM_DATA_OUT_OF_RANGE, length); + deleteAIOobjects(nullptr, responseHdr); + return; } if (offset + length > fileSize) { @@ -117,15 +391,17 @@ int FileHandler::transferFileData(const fs::path& path, bool upstream, { flags = O_WRONLY; } - int file = open(path.string().c_str(), flags); + int file = open(path.string().c_str(), flags | O_NONBLOCK); if (file == -1) { error("File does not exist, PATH = {PATH}", "PATH", path.string()); - return PLDM_ERROR; + dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + deleteAIOobjects(nullptr, responseHdr); + return; } - pldm::utils::CustomFD fd(file); - - return transferFileData(fd(), upstream, offset, length, address); + pldm::utils::CustomFD fd(file, false); + transferFileData(fd(), upstream, offset, length, address, responseHdr, + event); } std::unique_ptr getHandlerByType(uint16_t fileType, @@ -202,6 +478,76 @@ std::unique_ptr getHandlerByType(uint16_t fileType, return nullptr; } +std::shared_ptr getSharedHandlerByType(uint16_t fileType, + uint32_t fileHandle) +{ + switch (fileType) + { + case PLDM_FILE_TYPE_PEL: + { + return std::make_shared(fileHandle); + } + case PLDM_FILE_TYPE_LID_PERM: + { + return std::make_shared(fileHandle, true); + } + case PLDM_FILE_TYPE_LID_TEMP: + { + return std::make_shared(fileHandle, false); + } + case PLDM_FILE_TYPE_LID_MARKER: + { + return std::make_shared(fileHandle, false, + PLDM_FILE_TYPE_LID_MARKER); + } + case PLDM_FILE_TYPE_LID_RUNNING: + { + return std::make_shared(fileHandle, false, + PLDM_FILE_TYPE_LID_RUNNING); + } + case PLDM_FILE_TYPE_DUMP: + case PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS: + case PLDM_FILE_TYPE_RESOURCE_DUMP: + case PLDM_FILE_TYPE_BMC_DUMP: + case PLDM_FILE_TYPE_SBE_DUMP: + case PLDM_FILE_TYPE_HOSTBOOT_DUMP: + case PLDM_FILE_TYPE_HARDWARE_DUMP: + { + return std::make_shared(fileHandle, fileType); + } + case PLDM_FILE_TYPE_CERT_SIGNING_REQUEST: + case PLDM_FILE_TYPE_SIGNED_CERT: + case PLDM_FILE_TYPE_ROOT_CERT: + { + return std::make_shared(fileHandle, fileType); + } + case PLDM_FILE_TYPE_COD_LICENSE_KEY: + case PLDM_FILE_TYPE_COD_LICENSED_RESOURCES: + { + return std::make_shared(fileHandle, fileType); + } + case PLDM_FILE_TYPE_PROGRESS_SRC: + { + return std::make_shared(fileHandle); + } + case PLDM_FILE_TYPE_PCIE_TOPOLOGY: + case PLDM_FILE_TYPE_CABLE_INFO: + { + return std::make_shared(fileHandle, fileType); + } + case PLDM_FILE_TYPE_PSPD_VPD_PDD_KEYWORD: + { + return std::make_shared(fileHandle, fileType); + } + default: + { + throw InternalFailure(); + break; + } + } + return nullptr; +} + int FileHandler::readFile(const std::string& filePath, uint32_t offset, uint32_t& length, Response& response) { diff --git a/oem/ibm/libpldmresponder/file_io_by_type.hpp b/oem/ibm/libpldmresponder/file_io_by_type.hpp index e4416a2c6..284edd771 100644 --- a/oem/ibm/libpldmresponder/file_io_by_type.hpp +++ b/oem/ibm/libpldmresponder/file_io_by_type.hpp @@ -1,12 +1,49 @@ #pragma once -#include "file_io.hpp" +#include "libpldm/file_io.h" +#include "oem_ibm_handler.hpp" +#include "pldmd/pldm_resp_interface.hpp" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include namespace pldm { namespace responder { +using namespace sdeventplus; +using namespace sdeventplus::source; +constexpr auto clockId = sdeventplus::ClockId::RealTime; +using Timer = Time; +using Clock = Clock; + +class FileHandler; +namespace dma +{ +class DMA; +} // namespace dma + +struct ResponseHdr +{ + uint8_t instance_id; + uint8_t command; + pldm::response_api::Transport* respInterface; + std::shared_ptr functionPtr = nullptr; + int key; +}; namespace fs = std::filesystem; @@ -17,6 +54,34 @@ namespace fs = std::filesystem; */ class FileHandler { + protected: + /** @brief method to send response to host after completion of DMA operation + * @param[in] responseHdr - contain response related data + * @param[in] rStatus - operation status either success/fail/not suppoted. + * @param[in] length - length to be read/write mentioned by Host + */ + virtual void dmaResponseToHost(const ResponseHdr& responseHdr, + const pldm_completion_codes rStatus, + uint32_t length); + + /** @brief method to send response to host after completion of DMA operation + * @param[in] responseHdr - contain response related data + * @param[in] rStatus - operation status either success/fail/not suppoted. + * @param[in] length - length to be read/write mentioned by Host + */ + virtual void dmaResponseToHost(const ResponseHdr& responseHdr, + const pldm_fileio_completion_codes rStatus, + uint32_t length); + + /** @brief method to delete all shared pointer object + * @param[in] responseHdr - contain response related data + * @param[in] xdmaInterface - interface to transfer data between BMc and + * Host + */ + virtual void + deleteAIOobjects(const std::shared_ptr& xdmaInterface, + const ResponseHdr& responseHdr); + public: /** @brief Method to write an oem file type from host memory. Individual * file types need to override this method to do the file specific @@ -28,9 +93,11 @@ class FileHandler * tasks * @return PLDM status code */ - virtual int writeFromMemory(uint32_t offset, uint32_t length, - uint64_t address, - oem_platform::Handler* oemPlatformHandler) = 0; + virtual void writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* oemPlatformHandler, + ResponseHdr& responseHdr, + sdeventplus::Event& event) = 0; /** @brief Method to read an oem file type into host memory. Individual * file types need to override this method to do the file specific @@ -42,9 +109,11 @@ class FileHandler * tasks * @return PLDM status code */ - virtual int readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* oemPlatformHandler) = 0; + virtual void readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* oemPlatformHandler, + ResponseHdr& responseHdr, + sdeventplus::Event& event) = 0; /** @brief Method to read an oem file type's content into the PLDM response. * @param[in] offset - offset to read @@ -135,15 +204,28 @@ class FileHandler * * @return PLDM status code */ - virtual int transferFileData(const fs::path& path, bool upstream, - uint32_t offset, uint32_t& length, - uint64_t address); + virtual void transferFileData(const fs::path& path, bool upstream, + uint32_t offset, uint32_t& length, + uint64_t address, ResponseHdr& responseHdr, + sdeventplus::Event& event); + + virtual void transferFileData(int fd, bool upstream, uint32_t offset, + uint32_t& length, uint64_t address, + ResponseHdr& responseHdr, + sdeventplus::Event& event); - virtual int transferFileData(int fd, bool upstream, uint32_t offset, - uint32_t& length, uint64_t address); + virtual void transferFileDataToSocket(int fd, uint32_t& length, + uint64_t address, + ResponseHdr& responseHdr, + sdeventplus::Event& event); - virtual int transferFileDataToSocket(int fd, uint32_t& length, - uint64_t address); + /** @brief method to do necessary operation according different + * file type and being call when data transfer completed. + * + * @param[in] IsWriteToMemOp - type of operation to decide what operation + * needs to be done after data transfer. + */ + virtual void postDataTransferCallBack(bool IsWriteToMemOp) = 0; /** @brief Constructor to create a FileHandler object */ @@ -165,5 +247,13 @@ class FileHandler std::unique_ptr getHandlerByType(uint16_t fileType, uint32_t fileHandle); + +/** @brief Method to create shared file handler objects based on file type + * + * @param[in] fileType - type of file + * @param[in] fileHandle - file handle + */ +std::shared_ptr getSharedHandlerByType(uint16_t fileType, + uint32_t fileHandle); } // namespace responder } // namespace pldm diff --git a/oem/ibm/libpldmresponder/file_io_type_cert.cpp b/oem/ibm/libpldmresponder/file_io_type_cert.cpp index 12ccde47a..70030c590 100644 --- a/oem/ibm/libpldmresponder/file_io_type_cert.cpp +++ b/oem/ibm/libpldmresponder/file_io_type_cert.cpp @@ -25,9 +25,11 @@ static constexpr auto certFilePath = "/var/lib/ibm/bmcweb/"; CertMap CertHandler::certMap; -int CertHandler::writeFromMemory(uint32_t offset, uint32_t length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/) +void CertHandler::writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event) { auto it = certMap.find(certType); if (it == certMap.end()) @@ -35,41 +37,63 @@ int CertHandler::writeFromMemory(uint32_t offset, uint32_t length, error( "CertHandler::writeFromMemory:file for type {CERT_TYP} doesn't exist", "CERT_TYP", certType); - return PLDM_ERROR; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } - + m_length = length; auto fd = std::get<0>(it->second); - auto& remSize = std::get<1>(it->second); - auto rc = transferFileData(fd, false, offset, length, address); - if (rc == PLDM_SUCCESS) + transferFileData(fd, false, offset, length, address, responseHdr, event); + + return; +} + +void CertHandler::postDataTransferCallBack(bool IsWriteToMemOp) +{ + if (IsWriteToMemOp) { - remSize -= length; + auto it = certMap.find(certType); + if (it == certMap.end()) + { + error( + "CertHandler::writeFromMemory:file for type {TYPE} doesn't exist", + "TYPE", certType); + return; + } + // auto fd = std::get<0>(it->second); + auto& remSize = std::get<1>(it->second); + remSize -= m_length; if (!remSize) { - close(fd); + // close(fd); certMap.erase(it); } } - return rc; + else + { + fs::remove(certfilePath); + } + return; } -int CertHandler::readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/) +void CertHandler::readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event) { std::string filePath = certFilePath; filePath += "CSR_" + std::to_string(fileHandle); if (certType != PLDM_FILE_TYPE_CERT_SIGNING_REQUEST) { - return PLDM_ERROR_INVALID_DATA; - } - auto rc = transferFileData(filePath.c_str(), true, offset, length, address); - fs::remove(filePath); - if (rc) - { - return PLDM_ERROR; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR_INVALID_DATA, + length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } - return PLDM_SUCCESS; + certfilePath = filePath; + transferFileData(filePath.c_str(), true, offset, length, address, + responseHdr, event); } int CertHandler::read(uint32_t offset, uint32_t& length, Response& response, diff --git a/oem/ibm/libpldmresponder/file_io_type_cert.hpp b/oem/ibm/libpldmresponder/file_io_type_cert.hpp index cfc09985c..c90055457 100644 --- a/oem/ibm/libpldmresponder/file_io_type_cert.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_cert.hpp @@ -1,6 +1,6 @@ #pragma once -#include "file_io_by_type.hpp" +#include "file_io.hpp" #include @@ -29,12 +29,16 @@ class CertHandler : public FileHandler FileHandler(fileHandle), certType(fileType) {} - virtual int writeFromMemory(uint32_t offset, uint32_t length, + virtual void writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event); + virtual void readIntoMemory(uint32_t offset, uint32_t& length, uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); - virtual int readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event); virtual int read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/); @@ -60,6 +64,8 @@ class CertHandler : public FileHandler uint32_t /*metaDataValue3*/, uint32_t /*metaDataValue4*/); + virtual void postDataTransferCallBack(bool IsWriteToMemOp); + /** @brief CertHandler destructor */ ~CertHandler() {} @@ -68,7 +74,8 @@ class CertHandler : public FileHandler uint16_t certType; //!< type of the certificate static CertMap certMap; //!< holds the fd and remaining read/write size for //!< each certificate - + uint32_t m_length; + std::string certfilePath; enum SignedCertStatus { PLDM_INVALID_CERT_DATA = 0X03 diff --git a/oem/ibm/libpldmresponder/file_io_type_chap.hpp b/oem/ibm/libpldmresponder/file_io_type_chap.hpp index 56d36247e..413b40e64 100644 --- a/oem/ibm/libpldmresponder/file_io_type_chap.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_chap.hpp @@ -1,6 +1,6 @@ #pragma once -#include "file_io_by_type.hpp" +#include "file_io.hpp" namespace pldm { @@ -21,18 +21,26 @@ class ChapHandler : public FileHandler FileHandler(fileHandle), chapType(fileType) {} - virtual int writeFromMemory(uint32_t /*offset*/, uint32_t /*length*/, - uint64_t /*address*/, - oem_platform::Handler* /*oemPlatformHandle*/) + virtual void writeFromMemory(uint32_t /*offset*/, uint32_t length, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandle*/, + ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/) { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, + PLDM_ERROR_UNSUPPORTED_PLDM_CMD, length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); } - virtual int readIntoMemory(uint32_t /*offset*/, uint32_t& /*length*/, - uint64_t /*address*/, - oem_platform::Handler* /*oemPlatformHandler*/) + virtual void readIntoMemory(uint32_t /*offset*/, uint32_t& length, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/) { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, + PLDM_ERROR_UNSUPPORTED_PLDM_CMD, length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); } virtual int read(uint32_t offset, uint32_t& length, Response& response, @@ -70,6 +78,8 @@ class ChapHandler : public FileHandler return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; } + virtual void postDataTransferCallBack(bool /*IsWriteToMemOp*/) {} + /** @brief ChapHandler destructor */ ~ChapHandler() {} diff --git a/oem/ibm/libpldmresponder/file_io_type_dump.cpp b/oem/ibm/libpldmresponder/file_io_type_dump.cpp index f4ef5e71d..a2b2c6e17 100644 --- a/oem/ibm/libpldmresponder/file_io_type_dump.cpp +++ b/oem/ibm/libpldmresponder/file_io_type_dump.cpp @@ -21,6 +21,7 @@ #include PHOSPHOR_LOG2_USING; + using namespace pldm::responder::utils; using namespace pldm::utils; @@ -44,7 +45,6 @@ static constexpr auto hardwareDumpObjPath = int DumpHandler::fd = -1; namespace fs = std::filesystem; -extern SocketWriteStatus socketWriteStatus; std::string DumpHandler::findDumpObjPath(uint32_t fileHandle) { @@ -257,45 +257,12 @@ std::string DumpHandler::getOffloadUri(uint32_t fileHandle) return socketInterface; } -int DumpHandler::writeFromMemory(uint32_t, uint32_t length, uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/) +void DumpHandler::postDataTransferCallBack(bool IsWriteToMemOp) { - if (DumpHandler::fd == -1) + /// execute when DMA transfer failed. + if (IsWriteToMemOp) { - auto socketInterface = getOffloadUri(fileHandle); - int sock = setupUnixSocket(socketInterface); - if (sock < 0) - { - sock = -errno; - close(DumpHandler::fd); - error("DumpHandler::writeFromMemory: setupUnixSocket() failed"); - std::remove(socketInterface.c_str()); - resetOffloadUri(); - return PLDM_ERROR; - } - - DumpHandler::fd = sock; - auto rc = transferFileDataToSocket(DumpHandler::fd, length, address); - if (rc < 0) - { - error( - "DumpHandler::writeFromMemory: transferFileDataToSocket failed"); - if (DumpHandler::fd >= 0) - { - close(DumpHandler::fd); - DumpHandler::fd = -1; - } - std::remove(socketInterface.c_str()); - resetOffloadUri(); - return PLDM_ERROR; - } - return rc < 0 ? PLDM_ERROR : PLDM_SUCCESS; - } - - if (socketWriteStatus == Error) - { - error( - "DumpHandler::writeFromMemory: Error while writing to Unix socket"); + error("DumpHandler::writeFromMemory: transferFileDataToSocket failed"); if (DumpHandler::fd >= 0) { close(DumpHandler::fd); @@ -304,28 +271,39 @@ int DumpHandler::writeFromMemory(uint32_t, uint32_t length, uint64_t address, auto socketInterface = getOffloadUri(fileHandle); std::remove(socketInterface.c_str()); resetOffloadUri(); - return PLDM_ERROR; - } - else if (socketWriteStatus == InProgress || socketWriteStatus == NotReady) - { - return PLDM_ERROR_NOT_READY; + return; } +} - auto rc = transferFileDataToSocket(DumpHandler::fd, length, address); - if (rc < 0) +void DumpHandler::writeFromMemory(uint32_t, uint32_t length, uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event) +{ + if (DumpHandler::fd == -1) { - error("DumpHandler::writeFromMemory: transferFileDataToSocket failed"); - if (DumpHandler::fd >= 0) + auto socketInterface = getOffloadUri(fileHandle); + int sock = setupUnixSocket(socketInterface); + if (sock < 0) { close(DumpHandler::fd); - DumpHandler::fd = -1; + error( + "DumpHandler::writeFromMemory: setupUnixSocket() failed errno:{ERR}", + "ERR", errno); + std::remove(socketInterface.c_str()); + resetOffloadUri(); + + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + + return; } - auto socketInterface = getOffloadUri(fileHandle); - std::remove(socketInterface.c_str()); - resetOffloadUri(); - return PLDM_ERROR; + + DumpHandler::fd = sock; } - return rc < 0 ? PLDM_ERROR : PLDM_SUCCESS; + + transferFileDataToSocket(DumpHandler::fd, length, address, responseHdr, + event); } int DumpHandler::write(const char* buffer, uint32_t, uint32_t& length, @@ -335,22 +313,8 @@ int DumpHandler::write(const char* buffer, uint32_t, uint32_t& length, "Enter DumpHandler::write length = {LEN} DumpHandler::fd ={FILE_DESCRIPTION}", "LEN", length, "FILE_DESCRIPTION", DumpHandler::fd); - if (socketWriteStatus == Error) - { - error("DumpHandler::write: Error while writing to Unix socket"); - close(fd); - auto socketInterface = getOffloadUri(fileHandle); - std::remove(socketInterface.c_str()); - resetOffloadUri(); - return PLDM_ERROR; - } - else if (socketWriteStatus == InProgress) - { - return PLDM_ERROR_NOT_READY; - } - - writeToUnixSocket(DumpHandler::fd, buffer, length); - if (socketWriteStatus == Error) + int rc = writeToUnixSocket(DumpHandler::fd, buffer, length); + if (rc < 0) { error("DumpHandler::write: Error while writing to Unix socket"); close(fd); @@ -457,11 +421,6 @@ int DumpHandler::fileAck(uint8_t fileStatus) if (dumpType == PLDM_FILE_TYPE_DUMP || dumpType == PLDM_FILE_TYPE_RESOURCE_DUMP) { - if (socketWriteStatus == InProgress) - { - return PLDM_ERROR_NOT_READY; - } - PropertyValue value{true}; DBusMapping dbusMapping{path, dumpEntry, "Offloaded", "bool"}; try @@ -495,9 +454,11 @@ int DumpHandler::fileAck(uint8_t fileStatus) return PLDM_ERROR; } -int DumpHandler::readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/) +void DumpHandler::readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event) { auto path = findDumpObjPath(fileHandle); static constexpr auto dumpFilepathInterface = @@ -505,7 +466,10 @@ int DumpHandler::readIntoMemory(uint32_t offset, uint32_t& length, if ((dumpType == PLDM_FILE_TYPE_DUMP) || (dumpType == PLDM_FILE_TYPE_RESOURCE_DUMP)) { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, + PLDM_ERROR_UNSUPPORTED_PLDM_CMD, length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } else if (dumpType != PLDM_FILE_TYPE_RESOURCE_DUMP_PARMS) { @@ -514,9 +478,9 @@ int DumpHandler::readIntoMemory(uint32_t offset, uint32_t& length, auto filePath = pldm::utils::DBusHandler().getDbusProperty( path.c_str(), "Path", dumpFilepathInterface); - auto rc = transferFileData(fs::path(filePath), true, offset, length, - address); - return rc; + transferFileData(fs::path(filePath), true, offset, length, address, + responseHdr, event); + return; } catch (const sdbusplus::exception_t& e) { @@ -526,11 +490,13 @@ int DumpHandler::readIntoMemory(uint32_t offset, uint32_t& length, pldm::utils::reportError( "xyz.openbmc_project.PLDM.Error.readIntoMemory.GetFilepathFail", pldm::PelSeverity::ERROR); - return PLDM_ERROR; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } } - return transferFileData(resDumpRequestDirPath, true, offset, length, - address); + transferFileData(resDumpRequestDirPath, true, offset, length, address, + responseHdr, event); } int DumpHandler::read(uint32_t offset, uint32_t& length, Response& response, diff --git a/oem/ibm/libpldmresponder/file_io_type_dump.hpp b/oem/ibm/libpldmresponder/file_io_type_dump.hpp index d1e62b406..1a3b7fef4 100644 --- a/oem/ibm/libpldmresponder/file_io_type_dump.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_dump.hpp @@ -21,13 +21,17 @@ class DumpHandler : public FileHandler FileHandler(fileHandle), dumpType(fileType) {} - virtual int writeFromMemory(uint32_t offset, uint32_t length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + virtual void writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event); - virtual int readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + virtual void readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event); virtual int read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/); @@ -53,6 +57,7 @@ class DumpHandler : public FileHandler std::string findDumpObjPath(uint32_t fileHandle); std::string getOffloadUri(uint32_t fileHandle); + virtual void postDataTransferCallBack(bool IsWriteToMemOp); void resetOffloadUri(); /** @brief DumpHandler destructor */ diff --git a/oem/ibm/libpldmresponder/file_io_type_lic.cpp b/oem/ibm/libpldmresponder/file_io_type_lic.cpp index 0089d6fc0..bc59da14c 100644 --- a/oem/ibm/libpldmresponder/file_io_type_lic.cpp +++ b/oem/ibm/libpldmresponder/file_io_type_lic.cpp @@ -33,7 +33,6 @@ int LicenseHandler::updateBinFileAndLicObjs(const fs::path& newLicJsonFilePath) int rc = PLDM_SUCCESS; fs::path newLicFilePath(fs::path(licFilePath) / newLicenseFile); std::ifstream jsonFileNew(newLicJsonFilePath); - auto dataNew = Json::parse(jsonFileNew, nullptr, false); if (dataNew.is_discarded()) { @@ -55,9 +54,10 @@ int LicenseHandler::updateBinFileAndLicObjs(const fs::path& newLicJsonFilePath) return PLDM_SUCCESS; } -int LicenseHandler::writeFromMemory( +void LicenseHandler::writeFromMemory( uint32_t offset, uint32_t length, uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/) + oem_platform::Handler* /*oemPlatformHandler*/, ResponseHdr& responseHdr, + sdeventplus::Event& event) { namespace fs = std::filesystem; if (!fs::exists(licFilePath)) @@ -73,28 +73,30 @@ int LicenseHandler::writeFromMemory( { error("license json file create error: {NEW_LIC_JSON}", "NEW_LIC_JSON", newLicJsonFilePath.c_str()); - return -1; - } - - auto rc = transferFileData(newLicJsonFilePath, false, offset, length, - address); - if (rc != PLDM_SUCCESS) - { - error("transferFileData failed with rc= {RC}", "RC", rc); - return rc; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } + m_length = length; + transferFileData(newLicJsonFilePath, false, offset, length, address, + responseHdr, event); +} - if (length == licLength) +void LicenseHandler::postDataTransferCallBack(bool IsWriteToMemOp) +{ + if (IsWriteToMemOp) { - rc = updateBinFileAndLicObjs(newLicJsonFilePath); - if (rc != PLDM_SUCCESS) + fs::path newLicJsonFilePath(fs::path(licFilePath) / newLicenseJsonFile); + if (m_length == licLength) { - error("updateBinFileAndLicObjs failed with rc= {RC}", "RC", rc); - return rc; + int rc = updateBinFileAndLicObjs(newLicJsonFilePath); + if (rc != PLDM_SUCCESS) + { + error("updateBinFileAndLicObjs failed with rc= {RC}", "RC", rc); + return; + } } } - - return PLDM_SUCCESS; } int LicenseHandler::write(const char* buffer, uint32_t /*offset*/, @@ -118,7 +120,6 @@ int LicenseHandler::write(const char* buffer, uint32_t /*offset*/, licJsonFile.write(buffer, length); } licJsonFile.close(); - updateBinFileAndLicObjs(newLicJsonFilePath); if (rc != PLDM_SUCCESS) { diff --git a/oem/ibm/libpldmresponder/file_io_type_lic.hpp b/oem/ibm/libpldmresponder/file_io_type_lic.hpp index fcb901ca1..91d8103ea 100644 --- a/oem/ibm/libpldmresponder/file_io_type_lic.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_lic.hpp @@ -1,6 +1,6 @@ #pragma once -#include "file_io_by_type.hpp" +#include "file_io.hpp" namespace pldm { @@ -23,15 +23,22 @@ class LicenseHandler : public FileHandler FileHandler(fileHandle), licType(fileType) {} - virtual int writeFromMemory(uint32_t offset, uint32_t length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + virtual void writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/); - virtual int readIntoMemory(uint32_t /*offset*/, uint32_t& /*length*/, - uint64_t /*address*/, - oem_platform::Handler* /*oemPlatformHandler*/) + virtual void readIntoMemory(uint32_t /*offset*/, uint32_t& length, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/) { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, + PLDM_ERROR_UNSUPPORTED_PLDM_CMD, length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } virtual int read(uint32_t offset, uint32_t& length, Response& response, @@ -46,6 +53,7 @@ class LicenseHandler : public FileHandler } virtual int newFileAvailable(uint64_t length); + virtual void postDataTransferCallBack(bool IsWriteToMemOp); virtual int fileAckWithMetaData(uint8_t /*fileStatus*/, uint32_t metaDataValue1, @@ -70,6 +78,7 @@ class LicenseHandler : public FileHandler private: uint16_t licType; //!< type of the license uint64_t licLength; //!< length of the full license data + uint32_t m_length; enum Status { diff --git a/oem/ibm/libpldmresponder/file_io_type_lid.hpp b/oem/ibm/libpldmresponder/file_io_type_lid.hpp index 8b10907fa..d4cd7cae5 100644 --- a/oem/ibm/libpldmresponder/file_io_type_lid.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_lid.hpp @@ -1,7 +1,5 @@ #pragma once - -#include "file_io_by_type.hpp" -#include "xyz/openbmc_project/Common/error.hpp" +#include "file_io.hpp" #include #include @@ -11,7 +9,6 @@ #include #include #include - PHOSPHOR_LOG2_USING; namespace pldm @@ -171,20 +168,21 @@ class LidHandler : public FileHandler } } - virtual int writeFromMemory(uint32_t offset, uint32_t length, - uint64_t address, - oem_platform::Handler* oemPlatformHandler) + virtual void writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* oemPlatformHandler, + ResponseHdr& responseHdr, + sdeventplus::Event& event) { - int rc = PLDM_SUCCESS; - bool codeUpdateInProgress = false; + moemPlatformHandler = oemPlatformHandler; if (oemPlatformHandler != nullptr) { pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler = dynamic_cast( oemPlatformHandler); - codeUpdateInProgress = + mcodeUpdateInProgress = oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress(); - if (codeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER) + if (mcodeUpdateInProgress || lidType == PLDM_FILE_TYPE_LID_MARKER) { std::string dir = LID_STAGING_DIR; std::stringstream stream; @@ -208,44 +206,63 @@ class LidHandler : public FileHandler { error("Could not open file for writing {LID_PATH}", "LID_PATH", lidPath.c_str()); - return PLDM_ERROR; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } close(fd); - rc = transferFileData(lidPath, false, offset, length, address); - if (rc != PLDM_SUCCESS) - { - error("writeFileFromMemory failed with rc= {RC}", "RC", rc); - return rc; - } - if (lidType == PLDM_FILE_TYPE_LID_MARKER) + transferFileData(lidPath, false, offset, length, address, responseHdr, + event); + m_length = length; + } + + virtual void postDataTransferCallBack(bool IsWriteToMemOp) + { + int rc = -1; + if (IsWriteToMemOp) { - markerLIDremainingSize -= length; - if (markerLIDremainingSize == 0) + if (lidType == PLDM_FILE_TYPE_LID_MARKER) { - rc = processCodeUpdateLid(lidPath); - if (rc == PLDM_SUCCESS) + markerLIDremainingSize -= m_length; + if (markerLIDremainingSize == 0) { - validateMarkerLid(oemPlatformHandler); + rc = processCodeUpdateLid(lidPath); + if (rc == PLDM_SUCCESS) + { + validateMarkerLid(moemPlatformHandler); + } } } + else if (mcodeUpdateInProgress) + { + rc = processCodeUpdateLid(lidPath); + } + if (rc < 0) + { + error( + "Post DataTransfer CallBack Failed while lid transfer {LID_PATH}", + "LID_PATH", lidPath.c_str()); + } } - else if (codeUpdateInProgress) - { - rc = processCodeUpdateLid(lidPath); - } - return rc; } - virtual int readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* oemPlatformHandler) + virtual void readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* oemPlatformHandler, + ResponseHdr& responseHdr, + sdeventplus::Event& event) { if (constructLIDPath(oemPlatformHandler)) { - return transferFileData(lidPath, true, offset, length, address); + transferFileData(lidPath, true, offset, length, address, + responseHdr, event); + } + else + { + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); } - return PLDM_ERROR; } virtual int write(const char* buffer, uint32_t offset, uint32_t& length, @@ -400,6 +417,9 @@ class LidHandler : public FileHandler bool isPatchDir; static inline MarkerLIDremainingSize markerLIDremainingSize; uint8_t lidType; + uint32_t m_length; + bool mcodeUpdateInProgress = false; + oem_platform::Handler* moemPlatformHandler; }; } // namespace responder diff --git a/oem/ibm/libpldmresponder/file_io_type_pcie.cpp b/oem/ibm/libpldmresponder/file_io_type_pcie.cpp index eca1f729b..b2c6cc68d 100644 --- a/oem/ibm/libpldmresponder/file_io_type_pcie.cpp +++ b/oem/ibm/libpldmresponder/file_io_type_pcie.cpp @@ -68,9 +68,11 @@ PCIeInfoHandler::PCIeInfoHandler(uint32_t fileHandle, uint16_t fileType) : deleteTopologyFiles(); receivedFiles.emplace(infoType, false); } -int PCIeInfoHandler::writeFromMemory( + +void PCIeInfoHandler::writeFromMemory( uint32_t offset, uint32_t length, uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/) + oem_platform::Handler* /*oemPlatformHandler*/, ResponseHdr& responseHdr, + sdeventplus::Event& event) { if (!fs::exists(pciePath)) { @@ -89,17 +91,13 @@ int PCIeInfoHandler::writeFromMemory( if (!pcieData) { error("PCIe Info file creation error "); - return PLDM_ERROR; - } - - auto rc = transferFileData(infoFile, false, offset, length, address); - if (rc != PLDM_SUCCESS) - { - error("transferFileData failed with rc= {RC}", "RC", rc); - return rc; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } - return PLDM_SUCCESS; + transferFileData(infoFile, false, offset, length, address, responseHdr, + event); } int PCIeInfoHandler::write(const char* buffer, uint32_t, uint32_t& length, @@ -1112,11 +1110,15 @@ int PCIeInfoHandler::newFileAvailable(uint64_t) return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; } -int PCIeInfoHandler::readIntoMemory( - uint32_t, uint32_t&, uint64_t, - oem_platform::Handler* /*oemPlatformHandler*/) +void PCIeInfoHandler::readIntoMemory( + uint32_t, uint32_t& length, uint64_t, + oem_platform::Handler* /*oemPlatformHandler*/, ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/) { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR_UNSUPPORTED_PLDM_CMD, + length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } int PCIeInfoHandler::read(uint32_t, uint32_t&, Response&, diff --git a/oem/ibm/libpldmresponder/file_io_type_pcie.hpp b/oem/ibm/libpldmresponder/file_io_type_pcie.hpp index 031314b5e..624d8f84f 100644 --- a/oem/ibm/libpldmresponder/file_io_type_pcie.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_pcie.hpp @@ -182,13 +182,17 @@ class PCIeInfoHandler : public FileHandler */ PCIeInfoHandler(uint32_t fileHandle, uint16_t fileType); - virtual int writeFromMemory(uint32_t offset, uint32_t length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + virtual void writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event); - virtual int readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + virtual void readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& /*responseHdr*/, + sdeventplus::Event& event); virtual int read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/); @@ -259,7 +263,7 @@ class PCIeInfoHandler : public FileHandler virtual std::string getDownStreamChassis(const std::string& slotOrConnecterPath); virtual void parseSpeciallink(linkId_t linkId, linkId_t parentLinkId); - + virtual void postDataTransferCallBack(bool /*IsWriteToMemOp*/) {} /** @brief PCIeInfoHandler destructor */ ~PCIeInfoHandler() {} diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.cpp b/oem/ibm/libpldmresponder/file_io_type_pel.cpp index 2e49d98fa..601270b6f 100644 --- a/oem/ibm/libpldmresponder/file_io_type_pel.cpp +++ b/oem/ibm/libpldmresponder/file_io_type_pel.cpp @@ -93,9 +93,11 @@ Entry::Level getEntryLevelFromPEL(const std::string& pelFileName) } } // namespace detail -int PelHandler::readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/) +void PelHandler::readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event) { static constexpr auto logObjPath = "/xyz/openbmc_project/logging"; static constexpr auto logInterface = "org.open_power.Logging.PEL"; @@ -110,20 +112,27 @@ int PelHandler::readIntoMemory(uint32_t offset, uint32_t& length, logInterface, "GetPEL"); method.append(fileHandle); auto reply = bus.call(method, dbusTimeout); - sdbusplus::message::unix_fd fd{}; - reply.read(fd); - auto rc = transferFileData(fd, true, offset, length, address); - return rc; + sdbusplus::message::unix_fd unixfd; + reply.read(unixfd); + fd = dup(unixfd); + if (fd == -1) + { + error("Error: Cloning pel file descriptor failed...ERROR ={ERR}", + "ERR", errno); + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; + } + transferFileData(fd, true, offset, length, address, responseHdr, event); } catch (const std::exception& e) { error( "GetPEL D-Bus call failed, PEL id = 0x{FILE_HNDL}, error ={ERR_EXCEP}", "FILE_HNDL", lg2::hex, fileHandle, "ERR_EXCEP", e.what()); - return PLDM_ERROR; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); } - - return PLDM_SUCCESS; } int PelHandler::read(uint32_t offset, uint32_t& length, Response& response, @@ -196,9 +205,11 @@ int PelHandler::read(uint32_t offset, uint32_t& length, Response& response, return PLDM_SUCCESS; } -int PelHandler::writeFromMemory(uint32_t offset, uint32_t length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/) +void PelHandler::writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event) { char tmpFile[] = "/tmp/pel.XXXXXX"; int fd = mkstemp(tmpFile); @@ -206,17 +217,29 @@ int PelHandler::writeFromMemory(uint32_t offset, uint32_t length, { error("failed to create a temporary pel, ERROR={ERR_EXCEP}", "ERR_EXCEP", errno); - return PLDM_ERROR; + FileHandler::dmaResponseToHost(responseHdr, PLDM_ERROR, 0); + FileHandler::deleteAIOobjects(nullptr, responseHdr); + return; } close(fd); fs::path path(tmpFile); + Pelpath = path; - auto rc = transferFileData(path, false, offset, length, address); - if (rc == PLDM_SUCCESS) + transferFileData(path, false, offset, length, address, responseHdr, event); +} + +void PelHandler::postDataTransferCallBack(bool IsWriteToMemOp) +{ + if (IsWriteToMemOp) { - rc = storePel(path.string()); + auto rc = storePel(Pelpath.string()); + if (rc != PLDM_SUCCESS) + { + error( + "failed to storing a pel's Post DMA operation,Pelpath:{PEL_PATH}, ERROR={ERR_EXCEP}", + "ERR_EXCEP", errno, "PEL_PATH", Pelpath.string()); + } } - return rc; } int PelHandler::fileAck(uint8_t fileStatus) @@ -329,7 +352,6 @@ int PelHandler::storePel(std::string&& pelFileName) "ERR_EXCEP", e.what()); return PLDM_ERROR; } - return PLDM_SUCCESS; } @@ -369,7 +391,7 @@ int PelHandler::write(const char* buffer, uint32_t offset, uint32_t& length, { error( "file write failed, ERROR={ERR_EXCEP}, LENGTH={LEN}, OFFSET={OFFSET}", - "ERR_EXCEP", errno, "LEN", length, "ERR_EXCEP", offset); + "ERR_EXCEP", errno, "LEN", length, "OFFSET", offset); fs::remove(tmpFile); return PLDM_ERROR; } @@ -380,7 +402,7 @@ int PelHandler::write(const char* buffer, uint32_t offset, uint32_t& length, rc = storePel(path.string()); if (rc != PLDM_SUCCESS) { - error("save PEL failed, ERROR = {RC} tmpFile = {TMP_FILE}", "KEY0", + error("save PEL failed, ERROR = {RC} tmpFile = {TMP_FILE}", "RC", rc, "TMP_FILE", tmpFile); } } diff --git a/oem/ibm/libpldmresponder/file_io_type_pel.hpp b/oem/ibm/libpldmresponder/file_io_type_pel.hpp index 7cf19e29f..09965bb74 100644 --- a/oem/ibm/libpldmresponder/file_io_type_pel.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_pel.hpp @@ -19,13 +19,17 @@ class PelHandler : public FileHandler */ PelHandler(uint32_t fileHandle) : FileHandler(fileHandle) {} - virtual int writeFromMemory(uint32_t offset, uint32_t length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + virtual void writeFromMemory(uint32_t offset, uint32_t length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event); - virtual int readIntoMemory(uint32_t offset, uint32_t& length, - uint64_t address, - oem_platform::Handler* /*oemPlatformHandler*/); + virtual void readIntoMemory(uint32_t offset, uint32_t& length, + uint64_t address, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& event); virtual int read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/); @@ -42,6 +46,7 @@ class PelHandler : public FileHandler * @param[in] pelFileName - the pel file path */ virtual int storePel(std::string&& pelFileName); + virtual void postDataTransferCallBack(bool IsWriteToMemOp); virtual int newFileAvailable(uint64_t /*length*/) { @@ -69,6 +74,10 @@ class PelHandler : public FileHandler /** @brief PelHandler destructor */ ~PelHandler() {} + + private: + fs::path Pelpath; + int fd; }; } // namespace responder diff --git a/oem/ibm/libpldmresponder/file_io_type_progress_src.hpp b/oem/ibm/libpldmresponder/file_io_type_progress_src.hpp index 85276b5b5..4e1b7bd8b 100644 --- a/oem/ibm/libpldmresponder/file_io_type_progress_src.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_progress_src.hpp @@ -20,21 +20,29 @@ class ProgressCodeHandler : public FileHandler */ ProgressCodeHandler(uint32_t fileHandle) : FileHandler(fileHandle) {} - int writeFromMemory(uint32_t /*offset*/, uint32_t /*length*/, - uint64_t /*address*/, - oem_platform::Handler* /*oemPlatformHandler*/) override + void writeFromMemory(uint32_t /*offset*/, uint32_t length, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/) override { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, + PLDM_ERROR_UNSUPPORTED_PLDM_CMD, length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); } int write(const char* buffer, uint32_t offset, uint32_t& length, oem_platform::Handler* oemPlatformHandler) override; - int readIntoMemory(uint32_t /*offset*/, uint32_t& /*length*/, - uint64_t /*address*/, - oem_platform::Handler* /*oemPlatformHandler*/) override + void readIntoMemory(uint32_t /*offset*/, uint32_t& length, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/) override { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, + PLDM_ERROR_UNSUPPORTED_PLDM_CMD, length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); } int read(uint32_t /*offset*/, uint32_t& /*length*/, Response& /*response*/, @@ -70,6 +78,13 @@ class ProgressCodeHandler : public FileHandler { return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; } + /** @brief method to do necessary operation according different + * file type and being call when data transfer completed. + * + * @param[in] IsWriteToMemOp - type of operation to decide what operation + * needs to be done after data transfer. + */ + virtual void postDataTransferCallBack(bool /*IsWriteToMemOp*/) {} /** @brief method to set the dbus Raw value Property with * the obtained progress code from the host. diff --git a/oem/ibm/libpldmresponder/file_io_type_vpd.hpp b/oem/ibm/libpldmresponder/file_io_type_vpd.hpp index d5cf41211..f585da75b 100644 --- a/oem/ibm/libpldmresponder/file_io_type_vpd.hpp +++ b/oem/ibm/libpldmresponder/file_io_type_vpd.hpp @@ -1,6 +1,6 @@ #pragma once -#include "file_io_by_type.hpp" +#include "file_io.hpp" namespace pldm { @@ -20,17 +20,25 @@ class keywordHandler : public FileHandler keywordHandler(uint32_t fileHandle, uint16_t fileType) : FileHandler(fileHandle), vpdFileType(fileType) {} - virtual int writeFromMemory(uint32_t /*offset*/, uint32_t /*length*/, - uint64_t /*address*/, - oem_platform::Handler* /*oemPlatformHandler*/) + virtual void writeFromMemory(uint32_t /*offset*/, uint32_t length, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/) { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, + PLDM_ERROR_UNSUPPORTED_PLDM_CMD, length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); } - virtual int readIntoMemory(uint32_t /*offset*/, uint32_t& /*length*/, - uint64_t /*address*/, - oem_platform::Handler* /*oemPlatformHandler*/) + virtual void readIntoMemory(uint32_t /*offset*/, uint32_t& length, + uint64_t /*address*/, + oem_platform::Handler* /*oemPlatformHandler*/, + ResponseHdr& responseHdr, + sdeventplus::Event& /*event*/) { - return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; + FileHandler::dmaResponseToHost(responseHdr, + PLDM_ERROR_UNSUPPORTED_PLDM_CMD, length); + FileHandler::deleteAIOobjects(nullptr, responseHdr); } virtual int read(uint32_t offset, uint32_t& length, Response& response, oem_platform::Handler* /*oemPlatformHandler*/); @@ -64,6 +72,8 @@ class keywordHandler : public FileHandler { return PLDM_ERROR_UNSUPPORTED_PLDM_CMD; } + virtual void postDataTransferCallBack(bool /*IsWriteToMemOp*/) {} + /** @brief keywordHandler destructor */ ~keywordHandler() {} diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp index 33444fdf8..64e6fc55d 100644 --- a/oem/ibm/libpldmresponder/oem_ibm_handler.cpp +++ b/oem/ibm/libpldmresponder/oem_ibm_handler.cpp @@ -5,7 +5,6 @@ #include "collect_slot_vpd.hpp" #include "file_io_type_lid.hpp" -#include "libpldmresponder/file_io.hpp" #include "libpldmresponder/pdr_utils.hpp" #include diff --git a/oem/ibm/libpldmresponder/oem_ibm_handler.hpp b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp index 8441dda6e..13b5648ea 100644 --- a/oem/ibm/libpldmresponder/oem_ibm_handler.hpp +++ b/oem/ibm/libpldmresponder/oem_ibm_handler.hpp @@ -152,7 +152,7 @@ class Handler : public oem_platform::Handler setEventReceiverCnt = 0; disableWatchDogTimer(); pldm::responder::utils::clearLicenseStatus(); - pldm::responder::utils::clearDumpSocketWriteStatus(); + // pldm::responder::utils::clearDumpSocketWriteStatus(); } else if (propVal == "xyz.openbmc_project.State.Host.HostState.Running") diff --git a/oem/ibm/libpldmresponder/utils.cpp b/oem/ibm/libpldmresponder/utils.cpp index d5263c3dd..dfec9bc0a 100644 --- a/oem/ibm/libpldmresponder/utils.cpp +++ b/oem/ibm/libpldmresponder/utils.cpp @@ -26,7 +26,6 @@ namespace pldm using namespace pldm::dbus; namespace responder { -std::atomic socketWriteStatus = Free; std::mutex lockMutex; namespace utils @@ -121,16 +120,9 @@ int setupUnixSocket(const std::string& socketInterface) return fd; } -void writeToUnixSocket(const int sock, const char* buf, - const uint64_t blockSize) +int writeToUnixSocket(const int sock, const char* buf, const uint64_t blockSize) { const std::lock_guard lock(lockMutex); - if (socketWriteStatus == Error) - { - munmap((void*)buf, blockSize); - return; - } - socketWriteStatus = InProgress; uint64_t i; int nwrite = 0; @@ -150,9 +142,7 @@ void writeToUnixSocket(const int sock, const char* buf, { error("writeToUnixSocket: select call failed {ERR}", "ERR", errno); close(sock); - socketWriteStatus = Error; - munmap((void*)buf, blockSize); - return; + return -1; } if (retval == 0) { @@ -162,7 +152,6 @@ void writeToUnixSocket(const int sock, const char* buf, if ((retval > 0) && (FD_ISSET(sock, &wfd))) { nwrite = write(sock, buf + i, blockSize - i); - if (nwrite < 0) { if (errno == EAGAIN || errno == EWOULDBLOCK || errno == EINTR) @@ -174,9 +163,7 @@ void writeToUnixSocket(const int sock, const char* buf, } error("writeToUnixSocket: Failed to write {ERR}", "ERR", errno); close(sock); - socketWriteStatus = Error; - munmap((void*)buf, blockSize); - return; + return -1; } } else @@ -185,15 +172,7 @@ void writeToUnixSocket(const int sock, const char* buf, } } - munmap((void*)buf, blockSize); - socketWriteStatus = Completed; - return; -} - -void clearDumpSocketWriteStatus() -{ - socketWriteStatus = Free; - return; + return 0; } Json convertBinFileToJson(const fs::path& path) diff --git a/oem/ibm/libpldmresponder/utils.hpp b/oem/ibm/libpldmresponder/utils.hpp index f1743b022..732507946 100644 --- a/oem/ibm/libpldmresponder/utils.hpp +++ b/oem/ibm/libpldmresponder/utils.hpp @@ -15,14 +15,6 @@ namespace pldm namespace responder { -enum SocketWriteStatus -{ - Completed, - InProgress, - Free, - Error, - NotReady -}; namespace utils { namespace fs = std::filesystem; @@ -51,8 +43,8 @@ int setupUnixSocket(const std::string& socketInterface); * on failure returns -1 */ -void writeToUnixSocket(const int sock, const char* buf, - const uint64_t blockSize); +int writeToUnixSocket(const int sock, const char* buf, + const uint64_t blockSize); /** @brief Converts a binary file to json data * This function converts bson data stored in a binary file to @@ -84,14 +76,6 @@ void convertJsonToBinaryFile(const Json& jsonData, const fs::path& path); */ void clearLicenseStatus(); -/** @brief Clear Dump Socket Write Status - * This function clears all the dump socket write status to "Free" during - * reset reload operation or when host is coming down to off state. - * - * @return None - */ -void clearDumpSocketWriteStatus(); - /** @brief Create or update the d-bus license data * This function creates or updates the d-bus license details. If the input * input flag is 1, then new license data will be created and if the the input diff --git a/oem/ibm/test/libpldmresponder_fileio_test.cpp b/oem/ibm/test/libpldmresponder_fileio_test.cpp index 1d83ee0e6..bfb4cdb7c 100644 --- a/oem/ibm/test/libpldmresponder_fileio_test.cpp +++ b/oem/ibm/test/libpldmresponder_fileio_test.cpp @@ -225,7 +225,7 @@ TEST(ReadFileIntoMemory, BadPath) // Pass invalid payload length std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.readFileIntoMemory(request, 0); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); @@ -259,7 +259,7 @@ TEST_F(TestFileTable, ReadFileInvalidFileHandle) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.readFileIntoMemory(request, requestPayloadLength); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE); @@ -294,7 +294,7 @@ TEST_F(TestFileTable, ReadFileInvalidOffset) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.readFileIntoMemory(request, requestPayloadLength); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE); @@ -329,7 +329,7 @@ TEST_F(TestFileTable, ReadFileInvalidLength) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.readFileIntoMemory(request, requestPayloadLength); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); @@ -367,7 +367,7 @@ TEST_F(TestFileTable, ReadFileInvalidEffectiveLength) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.readFileIntoMemory(request, requestPayloadLength); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); @@ -399,7 +399,7 @@ TEST(WriteFileFromMemory, BadPath) // Pass invalid payload length std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.writeFileFromMemory(request, 0); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); @@ -438,7 +438,7 @@ TEST_F(TestFileTable, WriteFileInvalidFileHandle) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.writeFileFromMemory(request, requestPayloadLength); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_HANDLE); @@ -474,7 +474,7 @@ TEST_F(TestFileTable, WriteFileInvalidOffset) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.writeFileFromMemory(request, requestPayloadLength); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_DATA_OUT_OF_RANGE); @@ -547,7 +547,7 @@ TEST_F(TestFileTable, GetFileTableCommand) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.getFileTable(requestMsgPtr, requestPayloadLength); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_SUCCESS); @@ -574,7 +574,7 @@ TEST_F(TestFileTable, GetFileTableCommandReqLengthMismatch) // Pass invalid command payload length std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.getFileTable(request, 0); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); @@ -600,7 +600,7 @@ TEST_F(TestFileTable, GetFileTableCommandOEMAttrTable) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.getFileTable(requestMsgPtr, requestPayloadLength); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_INVALID_FILE_TABLE_TYPE); @@ -632,7 +632,7 @@ TEST_F(TestFileTable, ReadFileBadPath) // Invalid payload length std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.readFile(requestMsgPtr, 0); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); @@ -686,7 +686,7 @@ TEST_F(TestFileTable, ReadFileGoodPath) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto responseMsg = handler.readFile(requestMsgPtr, payload_length); auto response = reinterpret_cast( responseMsg.data() + sizeof(pldm_msg_hdr)); @@ -740,7 +740,7 @@ TEST_F(TestFileTable, WriteFileBadPath) // Invalid payload length std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.writeFile(requestMsgPtr, 0); auto responsePtr = reinterpret_cast(response.data()); ASSERT_EQ(responsePtr->payload[0], PLDM_ERROR_INVALID_LENGTH); @@ -791,7 +791,7 @@ TEST_F(TestFileTable, WriteFileGoodPath) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto responseMsg = handler.writeFile(requestMsgPtr, payload_length); auto response = reinterpret_cast( responseMsg.data() + sizeof(pldm_msg_hdr)); @@ -829,7 +829,7 @@ TEST(writeFileByTypeFromMemory, testBadPath) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.writeFileByTypeFromMemory(req, 0); auto responsePtr = reinterpret_cast(response.data()); @@ -909,7 +909,7 @@ TEST(readFileByTypeIntoMemory, testBadPath) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.readFileByTypeIntoMemory(req, 0); auto responsePtr = reinterpret_cast(response.data()); struct pldm_read_write_file_by_type_memory_resp* resp = @@ -951,7 +951,7 @@ TEST(readFileByType, testBadPath) std::unique_ptr oemPlatformHandler{}; oem_ibm::Handler handler(oemPlatformHandler.get(), hostSocketFd, host_eid, - nullptr, nullptr); + nullptr, nullptr, nullptr); auto response = handler.readFileByType(req, 0); auto responsePtr = reinterpret_cast(response.data()); struct pldm_read_write_file_by_type_resp* resp = diff --git a/pldmd/pldm_resp_interface.hpp b/pldmd/pldm_resp_interface.hpp new file mode 100644 index 000000000..509b9407f --- /dev/null +++ b/pldmd/pldm_resp_interface.hpp @@ -0,0 +1,136 @@ +#pragma once + +#include "common/flight_recorder.hpp" +#include "common/utils.hpp" + +#include + +#include + +#include +#include +#include +#include +using namespace pldm; +using namespace pldm::utils; +using namespace pldm::flightrecorder; + +PHOSPHOR_LOG2_USING; + +namespace pldm +{ +namespace response_api +{ + +/** @class Transport + * + * @brief This class performs the necessary operation in pldm for + * responding remote pldm. This class is mostly designed in special case + * when pldm need to send reply to host after FILE IO operation + * completed. + */ +class Transport +{ + public: + /** @brief Transport constructor + */ + Transport() = delete; + Transport(const Transport&) = delete; + Transport(int socketFd, bool verbose = false) : + sockFd(socketFd), verbose(verbose) + {} + + /** @brief method to send response to remote pldm using transport interface + * @param response - response of each request + * @param index - index to delete header from maintained map + * @returns returns 0 if success else -1 + */ + int sendPLDMRespMsg(Response& response, int index) + { + struct iovec iov[2]{}; + struct msghdr msg + {}; + + FlightRecorder::GetInstance().saveRecord(response, true); + if (verbose) + { + printBuffer(Tx, response); + } + + iov[0].iov_base = &requestMap[index][0]; + iov[0].iov_len = sizeof(requestMap[index][0]) + + sizeof(requestMap[index][1]); + iov[1].iov_base = response.data(); + iov[1].iov_len = response.size(); + msg.msg_iov = iov; + msg.msg_iovlen = sizeof(iov) / sizeof(iov[0]); + + int rc = sendmsg(sockFd, &msg, 0); + removeHeader(index); + if (rc < 0) + { + rc = errno; + error("sendto system call failed, errno= {ERRNO}", "ERRNO", rc); + } + return rc; + } + + /** @brief method to acquire one copy of request header into request map. + * @param reqMsg - overwrite each request header into existing mRequestMsg + * variable + */ + void setRequestMsgRef(std::vector& reqMsg) + { + mRequestMsg = reqMsg; + } + + /** @brief method to store request header into map when DMA data transfer + * request received. + */ + int getRequestHeaderIndex() + { + int index = getUniqueKey(); + requestMap[index] = mRequestMsg; + return index; + } + + private: + /** @brief method to remove request header after sending response to host + */ + void removeHeader(int index) + { + requestMap.erase(index); + } + + /** @brief method to generate unique key to store request header into map + * @returns available nearest key value as integer + */ + int getUniqueKey() + { + int key = 0; + for (size_t index = 0; index <= requestMap.size(); index++) + { + if (!requestMap.contains(index)) + { + key = index; + break; + } + } + return key; + } + + private: + std::vector mRequestMsg; + std::map> requestMap; + int sockFd; + bool verbose; +}; + +struct Interfaces +{ + std::unique_ptr transport = nullptr; +}; + +} // namespace response_api + +} // namespace pldm diff --git a/pldmd/pldmd.cpp b/pldmd/pldmd.cpp index f63a06244..87d209e32 100644 --- a/pldmd/pldmd.cpp +++ b/pldmd/pldmd.cpp @@ -9,6 +9,7 @@ #include "fw-update/manager.hpp" #include "host-bmc/dbus/deserialize.hpp" #include "invoker.hpp" +#include "pldm_resp_interface.hpp" #include "requester/handler.hpp" #include "requester/mctp_endpoint_discovery.hpp" #include "requester/request.hpp" @@ -216,7 +217,7 @@ int main(int argc, char** argv) Invoker invoker{}; requester::Handler reqHandler( sockfd, event, dbusImplReq, currentSendbuffSize, verbose); - + pldm::response_api::Interfaces respInterface; #ifdef LIBPLDMRESPONDER using namespace pldm::state_sensor; dbus_api::Host dbusImplHost(bus, "/xyz/openbmc_project/pldm"); @@ -272,6 +273,8 @@ int main(int argc, char** argv) } #ifdef OEM_IBM + respInterface.transport = + std::make_unique(sockfd, verbose); std::unique_ptr codeUpdate = std::make_unique(&dbusHandler); std::unique_ptr slotHandler = @@ -287,7 +290,8 @@ int main(int argc, char** argv) slotHandler->setOemPlatformHandler(oemPlatformHandler.get()); invoker.registerHandler(PLDM_OEM, std::make_unique( oemPlatformHandler.get(), sockfd, - hostEID, &dbusImplReq, &reqHandler)); + hostEID, &dbusImplReq, &reqHandler, + respInterface.transport.get())); // host lamp test std::unique_ptr hostLampTest = @@ -382,7 +386,8 @@ int main(int argc, char** argv) std::make_unique(bus, fwManager.get()); auto callback = [verbose, &invoker, &reqHandler, currentSendbuffSize, - &fwManager](IO& io, int fd, uint32_t revents) mutable { + &fwManager, + &respInterface](IO& io, int fd, uint32_t revents) mutable { if (!(revents & EPOLLIN)) { return; @@ -432,6 +437,18 @@ int main(int argc, char** argv) } else { + if (respInterface.transport) + { + using type = uint8_t; + uint8_t eid = requestMsg[0]; + auto hdr = reinterpret_cast( + requestMsg.data() + sizeof(eid) + sizeof(type)); + if (hdr->type == PLDM_OEM) + { + respInterface.transport->setRequestMsgRef( + requestMsg); + } + } // process message and send response auto response = processRxMsg(requestMsg, invoker, reqHandler, fwManager.get());