blob: efe8e376e26431e6234850ef461f15e574abb10c [file] [log] [blame]
#include "config.h"
#include "file_io_by_type.hpp"
#include "file_io_type_lid.hpp"
#include "file_io_type_pel.hpp"
#include "libpldmresponder/utils.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
#include <stdint.h>
#include <unistd.h>
#include <exception>
#include <filesystem>
#include <fstream>
#include <phosphor-logging/elog-errors.hpp>
#include <phosphor-logging/log.hpp>
#include <vector>
#include <xyz/openbmc_project/Logging/Entry/server.hpp>
#include "libpldm/base.h"
#include "oem/ibm/libpldm/file_io.h"
namespace pldm
{
namespace responder
{
using namespace phosphor::logging;
using namespace sdbusplus::xyz::openbmc_project::Common::Error;
int FileHandler::transferFileData(const fs::path& path, bool upstream,
uint32_t offset, uint32_t& length,
uint64_t address)
{
if (upstream)
{
if (!fs::exists(path))
{
log<level::ERR>("File does not exist",
entry("PATH=%s", path.c_str()));
return PLDM_INVALID_FILE_HANDLE;
}
size_t fileSize = fs::file_size(path);
if (offset >= fileSize)
{
log<level::ERR>("Offset exceeds file size",
entry("OFFSET=%d", offset),
entry("FILE_SIZE=%d", fileSize));
return PLDM_DATA_OUT_OF_RANGE;
}
if (offset + length > fileSize)
{
length = fileSize - offset;
}
}
dma::DMA xdmaInterface;
while (length > dma::maxSize)
{
auto rc = xdmaInterface.transferDataHost(path, offset, dma::maxSize,
address, upstream);
if (rc < 0)
{
return PLDM_ERROR;
}
offset += dma::maxSize;
length -= dma::maxSize;
address += dma::maxSize;
}
auto rc =
xdmaInterface.transferDataHost(path, offset, length, address, upstream);
return rc < 0 ? PLDM_ERROR : PLDM_SUCCESS;
}
std::unique_ptr<FileHandler> getHandlerByType(uint16_t fileType,
uint32_t fileHandle)
{
switch (fileType)
{
case PLDM_FILE_TYPE_PEL:
{
return std::make_unique<PelHandler>(fileHandle);
break;
}
case PLDM_FILE_TYPE_LID_PERM:
{
return std::make_unique<LidHandler>(fileHandle, true);
break;
}
case PLDM_FILE_TYPE_LID_TEMP:
{
return std::make_unique<LidHandler>(fileHandle, false);
break;
}
default:
{
elog<InternalFailure>();
break;
}
}
return nullptr;
}
int FileHandler::readFile(const std::string& filePath, uint32_t offset,
uint32_t& length, Response& response)
{
if (!fs::exists(filePath))
{
log<level::ERR>("File does not exist", entry("HANDLE=%d", fileHandle),
entry("PATH=%s", filePath.c_str()));
return PLDM_INVALID_FILE_HANDLE;
}
size_t fileSize = fs::file_size(filePath);
if (offset >= fileSize)
{
log<level::ERR>("Offset exceeds file size", entry("OFFSET=%d", offset),
entry("FILE_SIZE=%d", fileSize));
return PLDM_DATA_OUT_OF_RANGE;
}
if (offset + length > fileSize)
{
length = fileSize - offset;
}
size_t currSize = response.size();
response.resize(currSize + length);
auto filePos = reinterpret_cast<char*>(response.data());
filePos += currSize;
std::ifstream stream(filePath, std::ios::in | std::ios::binary);
if (stream)
{
stream.seekg(offset);
stream.read(filePos, length);
return PLDM_SUCCESS;
}
log<level::ERR>("Unable to read file", entry("FILE=%s", filePath.c_str()));
return PLDM_ERROR;
}
} // namespace responder
} // namespace pldm