oem-ibm : Support New record to the backplane vpd
This commit is to support a new VPD record called PSPD that contains
few keywords called #D and VM. Since these keywords are typically
larger in size (4K bytes) than what is managed by PLDM, we are adding
a file into which these keywords will be extracted. This keyword file
is transferred to the HB PLDM layer with a readFileByType request
from HB.
This also includes transfer of PSPD record data via PLDM with
offset included.
Tested by using pldmtool to send read request command to PLDM
Change-Id: Iba814a802cbbd2c2d641ee5a4c81919c3b8bdf20
Signed-off-by: Varsha Kaverappa <vkaverap@in.ibm.com>
diff --git a/libpldmresponder/meson.build b/libpldmresponder/meson.build
index c1b1b7f..65d4b99 100644
--- a/libpldmresponder/meson.build
+++ b/libpldmresponder/meson.build
@@ -48,6 +48,7 @@
'../oem/ibm/libpldmresponder/inband_code_update.cpp',
'../oem/ibm/requester/dbus_to_file_handler.cpp',
'../oem/ibm/libpldmresponder/file_io_type_progress_src.cpp',
+ '../oem/ibm/libpldmresponder/file_io_type_vpd.cpp',
]
endif
diff --git a/oem/ibm/libpldmresponder/file_io_by_type.cpp b/oem/ibm/libpldmresponder/file_io_by_type.cpp
index 5a43bd6..7a4429c 100644
--- a/oem/ibm/libpldmresponder/file_io_by_type.cpp
+++ b/oem/ibm/libpldmresponder/file_io_by_type.cpp
@@ -6,6 +6,7 @@
#include "file_io_type_lid.hpp"
#include "file_io_type_pel.hpp"
#include "file_io_type_progress_src.hpp"
+#include "file_io_type_vpd.hpp"
#include "xyz/openbmc_project/Common/error.hpp"
#include <libpldm/base.h>
@@ -167,6 +168,10 @@
return std::make_unique<LidHandler>(fileHandle, false,
PLDM_FILE_TYPE_LID_RUNNING);
}
+ case PLDM_FILE_TYPE_PSPD_VPD_PDD_KEYWORD:
+ {
+ return std::make_unique<keywordHandler>(fileHandle, fileType);
+ }
default:
{
throw InternalFailure();
diff --git a/oem/ibm/libpldmresponder/file_io_type_vpd.cpp b/oem/ibm/libpldmresponder/file_io_type_vpd.cpp
new file mode 100644
index 0000000..783683e
--- /dev/null
+++ b/oem/ibm/libpldmresponder/file_io_type_vpd.cpp
@@ -0,0 +1,118 @@
+#include "file_io_type_vpd.hpp"
+
+#include "libpldm/base.h"
+#include "libpldm/file_io.h"
+
+#include "common/utils.hpp"
+
+#include <stdint.h>
+
+#include <iostream>
+
+typedef uint8_t byte;
+
+namespace pldm
+{
+namespace responder
+{
+int keywordHandler::read(uint32_t offset, uint32_t& length, Response& response,
+ oem_platform::Handler* /*oemPlatformHandler*/)
+{
+ const char* keywrdObjPath =
+ "/xyz/openbmc_project/inventory/system/chassis/motherboard";
+ const char* keywrdPropName = "PD_D";
+ const char* keywrdInterface = "com.ibm.ipzvpd.PSPD";
+
+ std::variant<std::vector<byte>> keywrd;
+
+ try
+ {
+ auto& bus = pldm::utils::DBusHandler::getBus();
+ auto service = pldm::utils::DBusHandler().getService(keywrdObjPath,
+ keywrdInterface);
+ auto method = bus.new_method_call(service.c_str(), keywrdObjPath,
+ "org.freedesktop.DBus.Properties",
+ "Get");
+ method.append(keywrdInterface, keywrdPropName);
+ auto reply = bus.call(method);
+ reply.read(keywrd);
+ }
+ catch (const std::exception& e)
+ {
+ std::cerr << "Get keyword error from dbus interface : "
+ << keywrdInterface << " ERROR= " << e.what() << std::endl;
+ }
+
+ uint32_t keywrdSize = std::get<std::vector<byte>>(keywrd).size();
+
+ if (length < keywrdSize)
+ {
+ std::cerr << "length requested is less the keyword size, length: "
+ << length << " keyword size: " << keywrdSize << std::endl;
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ namespace fs = std::filesystem;
+ constexpr auto keywrdDirPath = "/tmp/pldm/";
+ constexpr auto keywrdFilePath = "/tmp/pldm/vpdKeywrd.bin";
+
+ if (!fs::exists(keywrdDirPath))
+ {
+ fs::create_directories(keywrdDirPath);
+ fs::permissions(keywrdDirPath,
+ fs::perms::others_read | fs::perms::owner_write);
+ }
+
+ std::ofstream keywrdFile(keywrdFilePath);
+ auto fd = open(keywrdFilePath, std::ios::out | std::ofstream::binary);
+ if (!keywrdFile)
+ {
+ std::cerr << "VPD keyword file open error: " << keywrdFilePath
+ << " errno: " << errno << std::endl;
+ pldm::utils::reportError(
+ "xyz.openbmc_project.PLDM.Error.readKeywordHandler.keywordFileOpenError");
+ return PLDM_ERROR;
+ }
+
+ if (offset > keywrdSize)
+ {
+ std::cerr << "Offset exceeds file size, OFFSET=" << offset
+ << " FILE_SIZE=" << keywrdSize << std::endl;
+ return PLDM_DATA_OUT_OF_RANGE;
+ }
+
+ // length of keyword data should be same as keyword data size in dbus object
+ length = static_cast<uint32_t>(keywrdSize) - offset;
+
+ auto returnCode = lseek(fd, offset, SEEK_SET);
+ if (returnCode == -1)
+ {
+ std::cerr
+ << "Could not find keyword data at given offset. File Seek failed"
+ << std::endl;
+ return PLDM_ERROR;
+ }
+
+ keywrdFile.write((const char*)std::get<std::vector<byte>>(keywrd).data(),
+ keywrdSize);
+ if (keywrdFile.bad())
+ {
+ std::cerr << "Error while writing to file: " << keywrdFilePath
+ << std::endl;
+ }
+ keywrdFile.close();
+
+ auto rc = readFile(keywrdFilePath, offset, keywrdSize, response);
+ fs::remove(keywrdFilePath);
+ if (rc)
+ {
+ std::cerr << "Read error for keyword file with size: " << keywrdSize
+ << std::endl;
+ pldm::utils::reportError(
+ "xyz.openbmc_project.PLDM.Error.readKeywordHandler.keywordFileReadError");
+ return PLDM_ERROR;
+ }
+ return PLDM_SUCCESS;
+}
+} // namespace responder
+} // namespace pldm
diff --git a/oem/ibm/libpldmresponder/file_io_type_vpd.hpp b/oem/ibm/libpldmresponder/file_io_type_vpd.hpp
new file mode 100644
index 0000000..d5cf412
--- /dev/null
+++ b/oem/ibm/libpldmresponder/file_io_type_vpd.hpp
@@ -0,0 +1,75 @@
+#pragma once
+
+#include "file_io_by_type.hpp"
+
+namespace pldm
+{
+namespace responder
+{
+using vpdFileType = uint16_t;
+/** @class keywordFileHandler
+ *
+ * @brief Inherits and implements FileHandler. This class is used
+ * to read #D keyword file
+ */
+class keywordHandler : public FileHandler
+{
+ public:
+ /** @brief Handler constructor
+ */
+ 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*/)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+ virtual int readIntoMemory(uint32_t /*offset*/, uint32_t& /*length*/,
+ uint64_t /*address*/,
+ oem_platform::Handler* /*oemPlatformHandler*/)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+ virtual int read(uint32_t offset, uint32_t& length, Response& response,
+ oem_platform::Handler* /*oemPlatformHandler*/);
+ virtual int write(const char* /*buffer*/, uint32_t /*offset*/,
+ uint32_t& /*length*/,
+ oem_platform::Handler* /*oemPlatformHandler*/)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+ virtual int fileAck(uint8_t /*fileStatus*/)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+ virtual int newFileAvailable(uint64_t /*length*/)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+ virtual int fileAckWithMetaData(uint8_t /*fileStatus*/,
+ uint32_t /*metaDataValue1*/,
+ uint32_t /*metaDataValue2*/,
+ uint32_t /*metaDataValue3*/,
+ uint32_t /*metaDataValue4*/)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+ virtual int newFileAvailableWithMetaData(uint64_t /*length*/,
+ uint32_t /*metaDataValue1*/,
+ uint32_t /*metaDataValue2*/,
+ uint32_t /*metaDataValue3*/,
+ uint32_t /*metaDataValue4*/)
+ {
+ return PLDM_ERROR_UNSUPPORTED_PLDM_CMD;
+ }
+ /** @brief keywordHandler destructor
+ */
+ ~keywordHandler() {}
+
+ private:
+ uint16_t vpdFileType; //!< type of the VPD file
+};
+} // namespace responder
+} // namespace pldm