oem ibm: support reading LIDs based on type

This commit reads the LIDs requested by Host. Host
sends request as T or P side. This commit evaluates the
current boot side and reads the appropriate LIDs.

Also this commit stores the image LIDs sent by Host
during an inband code update

Change-Id: Ia4bae68fa95f19bc228ef7002493d54abab3dc93
Signed-off-by: Sampa Misra <sampmisr@in.ibm.com>
diff --git a/oem/ibm/libpldmresponder/file_io_type_lid.hpp b/oem/ibm/libpldmresponder/file_io_type_lid.hpp
index 3086158..531d762 100644
--- a/oem/ibm/libpldmresponder/file_io_type_lid.hpp
+++ b/oem/ibm/libpldmresponder/file_io_type_lid.hpp
@@ -28,6 +28,8 @@
      */
     LidHandler(uint32_t fileHandle, bool permSide) : FileHandler(fileHandle)
     {
+        sideToRead = permSide ? Pside : Tside;
+        isPatchDir = false;
         std::string dir = permSide ? LID_ALTERNATE_DIR : LID_RUNNING_DIR;
         std::stringstream stream;
         stream << std::hex << fileHandle;
@@ -38,6 +40,7 @@
         if (fs::is_regular_file(patch))
         {
             lidPath = patch;
+            isPatchDir = true;
         }
         else
         {
@@ -45,27 +48,183 @@
         }
     }
 
-    virtual int writeFromMemory(uint32_t /*offset*/, uint32_t /*length*/,
-                                uint64_t /*address*/)
+    /** @brief Method to construct the LID path based on current boot side
+     *  @param[in] oemPlatformHandler - OEM platform handler
+     *  @return bool - true if a new path is constructed
+     */
+    bool constructLIDPath(oem_platform::Handler* oemPlatformHandler)
     {
-        return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+        if (oemPlatformHandler != nullptr)
+        {
+            pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
+                dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
+                    oemPlatformHandler);
+            std::string dir = LID_ALTERNATE_DIR;
+            if (isPatchDir)
+            {
+                dir = LID_ALTERNATE_PATCH_DIR;
+            }
+            if (oemIbmPlatformHandler->codeUpdate->fetchCurrentBootSide() ==
+                sideToRead)
+            {
+                if (isPatchDir)
+                {
+                    dir = LID_RUNNING_PATCH_DIR;
+                }
+                else
+                {
+                    dir = LID_RUNNING_DIR;
+                }
+            }
+            else if (oemIbmPlatformHandler->codeUpdate
+                         ->isCodeUpdateInProgress())
+            {
+                return false;
+            }
+
+            std::stringstream stream;
+            stream << std::hex << fileHandle;
+            auto lidName = stream.str() + ".lid";
+            lidPath = std::move(dir) + '/' + lidName;
+        }
+        return true;
+    }
+
+    virtual int writeFromMemory(uint32_t offset, uint32_t length,
+                                uint64_t address,
+                                oem_platform::Handler* oemPlatformHandler)
+    {
+        if (oemPlatformHandler != nullptr)
+        {
+            pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
+                dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
+                    oemPlatformHandler);
+            if (oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress())
+            {
+                std::string dir = LID_STAGING_DIR;
+                std::stringstream stream;
+                stream << std::hex << fileHandle;
+                auto lidName = stream.str() + ".lid";
+                lidPath = std::move(dir) + '/' + lidName;
+            }
+        }
+        std::cout << "got writeFromMemory() for LID " << lidPath.c_str()
+                  << " and offset " << offset << " and length " << length
+                  << "\n";
+        bool fileExists = fs::exists(lidPath);
+        int flags{};
+        if (fileExists)
+        {
+            flags = O_RDWR;
+        }
+        else
+        {
+            flags = O_WRONLY | O_CREAT | O_TRUNC | O_SYNC;
+        }
+        auto fd = open(lidPath.c_str(), flags);
+        if (fd == -1)
+        {
+            std::cerr << "Could not open file for writing  " << lidPath.c_str()
+                      << "\n";
+            return PLDM_ERROR;
+        }
+        close(fd);
+
+        auto rc = transferFileData(lidPath, false, offset, length, address);
+        if (rc != PLDM_SUCCESS)
+        {
+            std::cout << "writeFileFromMemory failed with rc= " << rc << " \n";
+            return rc;
+        }
+        return rc;
     }
 
     virtual int readIntoMemory(uint32_t offset, uint32_t& length,
-                               uint64_t address)
+                               uint64_t address,
+                               oem_platform::Handler* oemPlatformHandler)
     {
-        return transferFileData(lidPath, true, offset, length, address);
+        if (constructLIDPath(oemPlatformHandler))
+        {
+            return transferFileData(lidPath, true, offset, length, address);
+        }
+        return PLDM_ERROR;
     }
 
-    virtual int write(const char* /*buffer*/, uint32_t /*offset*/,
-                      uint32_t& /*length*/)
+    virtual int write(const char* buffer, uint32_t offset, uint32_t& length,
+                      oem_platform::Handler* oemPlatformHandler)
     {
-        return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+        if (oemPlatformHandler != nullptr)
+        {
+            pldm::responder::oem_ibm_platform::Handler* oemIbmPlatformHandler =
+                dynamic_cast<pldm::responder::oem_ibm_platform::Handler*>(
+                    oemPlatformHandler);
+            if (oemIbmPlatformHandler->codeUpdate->isCodeUpdateInProgress())
+            {
+                std::string dir = LID_STAGING_DIR;
+                std::stringstream stream;
+                stream << std::hex << fileHandle;
+                auto lidName = stream.str() + ".lid";
+                lidPath = std::move(dir) + '/' + lidName;
+            }
+        }
+        std::cout << "got write() call for LID " << lidPath.c_str()
+                  << " and offset " << offset << " and length " << length
+                  << "\n";
+        bool fileExists = fs::exists(lidPath);
+        int flags{};
+        if (fileExists)
+        {
+            flags = O_RDWR;
+            size_t fileSize = fs::file_size(lidPath);
+            if (offset > fileSize)
+            {
+                std::cerr << "Offset exceeds file size, OFFSET=" << offset
+                          << " FILE_SIZE=" << fileSize << "\n";
+                return PLDM_DATA_OUT_OF_RANGE;
+            }
+        }
+        else
+        {
+            flags = O_WRONLY | O_CREAT | O_TRUNC | O_SYNC;
+            if (offset > 0)
+            {
+                std::cerr << "Offset is non zero in a new file \n";
+                return PLDM_DATA_OUT_OF_RANGE;
+            }
+        }
+        auto fd = open(lidPath.c_str(), flags);
+        if (fd == -1)
+        {
+            std::cerr << "could not open file " << lidPath.c_str() << "\n";
+            return PLDM_ERROR;
+        }
+        auto rc = lseek(fd, offset, SEEK_SET);
+        if (rc == -1)
+        {
+            std::cerr << "lseek failed, ERROR=" << errno
+                      << ", OFFSET=" << offset << "\n";
+            return PLDM_ERROR;
+        }
+        std::cout << "lseek returned " << rc << "\n";
+        rc = ::write(fd, buffer, length);
+        if (rc == -1)
+        {
+            std::cerr << "file write failed, ERROR=" << errno
+                      << ", LENGTH=" << length << ", OFFSET=" << offset << "\n";
+            return PLDM_ERROR;
+        }
+        close(fd);
+        return rc;
     }
 
-    virtual int read(uint32_t offset, uint32_t& length, Response& response)
+    virtual int read(uint32_t offset, uint32_t& length, Response& response,
+                     oem_platform::Handler* oemPlatformHandler)
     {
-        return readFile(lidPath, offset, length, response);
+        if (constructLIDPath(oemPlatformHandler))
+        {
+            return readFile(lidPath, offset, length, response);
+        }
+        return PLDM_ERROR;
     }
 
     virtual int fileAck(uint8_t /*fileStatus*/)
@@ -86,6 +245,8 @@
 
   protected:
     std::string lidPath;
+    std::string sideToRead;
+    bool isPatchDir;
 };
 
 } // namespace responder