oem: meta: Add decode_oem_meta_file_io_req()
Support decode_oem_meta_file_io_req() cmd to decode the incoming post
code.
PLDM OEM Meta Write File IO cmd:
Example:
Request:
Byte 0: 0x3F (OEM cmd)
Byte 1: 0x02 (FILE IO)
Byte 2: 0x00 (File io type : POST CODE)
Byte 3-6: 0x04 (Data length)
Byte 7-10: 0x93 0xE0 0x00 0xEA (post code)
Response:
Byte 0: 0x00 (success)
Tested:
- Unit Tests passed.
Change-Id: I85437698642dd3cbe6084acf1feada842d206eac
Signed-off-by: Delphine CC Chiu <Delphine_CC_Chiu@wiwynn.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 636e20a..e06258c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@
2. transport: af-mctp: Add pldm_transport_af_mctp_bind()
3. oem: ibm: Add chapdata file type support
4. base: Added PLDM_SMBIOS & PLDM_RDE message types
+5. oem: meta: Add decode_oem_meta_file_io_req()
### Changed
diff --git a/include/libpldm/meson.build b/include/libpldm/meson.build
index f1988cd..235a7a6 100644
--- a/include/libpldm/meson.build
+++ b/include/libpldm/meson.build
@@ -36,4 +36,11 @@
install_symlink('state_set_oem_ibm.h', pointing_to: 'oem/ibm/state_set.h', install_dir: 'include/libpldm')
endif
+if get_option('oem-meta').allowed()
+ libpldm_headers += files(
+ 'oem/meta/file_io.h',
+ )
+endif
+
+
install_headers(libpldm_headers, subdir: 'libpldm', preserve_path: true)
diff --git a/include/libpldm/oem/meta/file_io.h b/include/libpldm/oem/meta/file_io.h
new file mode 100644
index 0000000..32a7109
--- /dev/null
+++ b/include/libpldm/oem/meta/file_io.h
@@ -0,0 +1,44 @@
+/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
+#ifndef LIBPLDM_OEM_META_FILE_IO_H
+#define LIBPLDM_OEM_META_FILE_IO_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include <stddef.h>
+#include <stdint.h>
+
+struct pldm_msg;
+/** @brief PLDM Commands in OEM META type
+ */
+
+enum pldm_oem_meta_fileio_commands {
+ PLDM_OEM_META_FILEIO_CMD_WRITE_FILE = 0x2,
+ PLDM_OEM_META_FILEIO_CMD_READ_FILE = 0x3,
+};
+
+struct pldm_oem_meta_write_file_req {
+ uint8_t file_handle;
+ uint32_t length;
+ uint8_t file_data[1];
+};
+
+/** @brief Decode OEM meta file io req
+ *
+ * @param[in] msg - Pointer to PLDM request message
+ * @param[in] payload_length - Length of request payload
+ * @param[out] file_handle - The handle of data
+ * @param[out] length - Total size of data
+ * @param[out] data - Message will be written to this
+ * @return pldm_completion_codes
+ */
+int decode_oem_meta_file_io_req(const struct pldm_msg *msg,
+ size_t payload_length, uint8_t *file_handle,
+ uint32_t *length, uint8_t *data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif /*LIBPLDM_OEM_META_FILE_IO_H*/
diff --git a/meson.options b/meson.options
index 7f39b00..26a7544 100644
--- a/meson.options
+++ b/meson.options
@@ -2,3 +2,4 @@
option('tests', type: 'feature', description: 'Build tests')
option('oem-ibm', type: 'feature', description: 'Enable IBM OEM PLDM')
option('abi-compliance-check', type: 'feature', description: 'Detect public ABI/API changes')
+option('oem-meta', type: 'feature', description: 'Enable Meta OEM PLDM')
\ No newline at end of file
diff --git a/src/meson.build b/src/meson.build
index 99e79a2..9f4487c 100644
--- a/src/meson.build
+++ b/src/meson.build
@@ -17,6 +17,10 @@
subdir('oem/ibm')
endif
+if get_option('oem-meta').allowed()
+ subdir('oem/meta')
+endif
+
libpldm = library(
'pldm',
libpldm_sources,
diff --git a/src/oem/meta/file_io.c b/src/oem/meta/file_io.c
new file mode 100644
index 0000000..6662e8f
--- /dev/null
+++ b/src/oem/meta/file_io.c
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
+#include <libpldm/oem/meta/file_io.h>
+#include <endian.h>
+#include <string.h>
+#include <stdio.h>
+#include "msgbuf.h"
+
+#define PLDM_OEM_META_DECODE_WRITE_FILE_IO_MIN_SIZE 6
+LIBPLDM_ABI_TESTING
+int decode_oem_meta_file_io_req(const struct pldm_msg *msg,
+ size_t payload_length, uint8_t *file_handle,
+ uint32_t *length, uint8_t *data)
+{
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || file_handle == NULL || length == NULL ||
+ data == NULL) {
+ return PLDM_ERROR_INVALID_DATA;
+ }
+
+ int rc = pldm_msgbuf_init(buf,
+ PLDM_OEM_META_DECODE_WRITE_FILE_IO_MIN_SIZE,
+ msg->payload, payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_extract(buf, file_handle);
+ pldm_msgbuf_extract(buf, length);
+ pldm_msgbuf_extract_array_uint8(buf, data, *length);
+
+ return pldm_msgbuf_destroy_consumed(buf);
+}
diff --git a/src/oem/meta/meson.build b/src/oem/meta/meson.build
new file mode 100644
index 0000000..6c89286
--- /dev/null
+++ b/src/oem/meta/meson.build
@@ -0,0 +1,3 @@
+libpldm_sources += files(
+ 'file_io.c'
+ )
diff --git a/tests/meson.build b/tests/meson.build
index 76ca6ee..dba7870 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -45,6 +45,12 @@
]
endif
+if get_option('oem-meta').allowed()
+ tests += [
+ 'oem/meta/libpldm_fileio_test',
+ ]
+endif
+
test_include_dirs = [ libpldm_include_dir, include_directories('../src') ]
foreach t : tests
diff --git a/tests/oem/meta/libpldm_fileio_test.cpp b/tests/oem/meta/libpldm_fileio_test.cpp
new file mode 100644
index 0000000..663ed65
--- /dev/null
+++ b/tests/oem/meta/libpldm_fileio_test.cpp
@@ -0,0 +1,92 @@
+/* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
+#include <endian.h>
+#include <libpldm/oem/meta/file_io.h>
+
+#include "msgbuf.h"
+
+#include <gtest/gtest.h>
+
+static constexpr size_t oemMetaDecodeWriteFileIoReqBytes = 9;
+static constexpr size_t postCodeSize = 4;
+static constexpr size_t invalidDataSize = 0;
+
+TEST(DecodeOemMetaFileIoReq, testGoodDecodeRequest)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+ uint8_t fileHandle = 0x00;
+ int32_t dataLengthLE = 0x04;
+ uint8_t postCode[4] = {0x93, 0xE0, 0x00, 0xEA};
+
+ constexpr auto hdrSize = sizeof(pldm_msg_hdr);
+
+ uint8_t buf[hdrSize + sizeof(uint8_t) + sizeof(int32_t) +
+ (postCodeSize * sizeof(uint8_t))] = {};
+
+ pldm_msgbuf_init(ctx, 0, &buf[hdrSize], sizeof(buf) - hdrSize);
+
+ pldm_msgbuf_insert_uint8(ctx, fileHandle);
+ pldm_msgbuf_insert_int32(ctx, dataLengthLE);
+ pldm_msgbuf_insert_array_uint8(ctx, postCode, sizeof(postCode));
+
+ std::array<uint8_t, oemMetaDecodeWriteFileIoReqBytes> retDataField{};
+
+ uint8_t retfileHandle = 0;
+ uint32_t retFileDataCnt = 0;
+
+ auto request = reinterpret_cast<pldm_msg*>(buf);
+
+ auto rc = decode_oem_meta_file_io_req(request, sizeof(buf) - hdrSize,
+ &retfileHandle, &retFileDataCnt,
+ retDataField.data());
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(retfileHandle, fileHandle);
+ EXPECT_EQ(retFileDataCnt, dataLengthLE);
+ EXPECT_EQ(retDataField[0], postCode[0]);
+ EXPECT_EQ(retDataField[1], postCode[1]);
+ EXPECT_EQ(retDataField[2], postCode[2]);
+ EXPECT_EQ(retDataField[3], postCode[3]);
+}
+
+TEST(DecodeOemMetaFileIoReq, testInvalidFieldsDecodeRequest)
+{
+ std::array<uint8_t, oemMetaDecodeWriteFileIoReqBytes> requestMsg{};
+ auto request = reinterpret_cast<pldm_msg*>(requestMsg.data());
+
+ auto rc = decode_oem_meta_file_io_req(request, requestMsg.size(), NULL,
+ NULL, NULL);
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(DecodeOemMetaFileIoReq, testInvalidLengthDecodeRequest)
+{
+ uint8_t retfileHandle = 0;
+ uint32_t retFileDataCnt = 0;
+ uint8_t buf[1] = {};
+ std::array<uint8_t, oemMetaDecodeWriteFileIoReqBytes> retDataField{};
+
+ auto request = reinterpret_cast<pldm_msg*>(buf);
+
+ auto rc = decode_oem_meta_file_io_req(request, 0, &retfileHandle,
+ &retFileDataCnt, retDataField.data());
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(DecodeOemMetaFileIoReq, testInvalidDataRequest)
+{
+ uint8_t buf[1] = {};
+ uint8_t retfileHandle = 0;
+ uint32_t retFileDataCnt = 0;
+
+ std::array<uint8_t, invalidDataSize> retDataField{};
+
+ auto request = reinterpret_cast<pldm_msg*>(buf);
+
+ auto rc = decode_oem_meta_file_io_req(request, sizeof(buf), &retfileHandle,
+ &retFileDataCnt, retDataField.data());
+
+ EXPECT_EQ(rc, PLDM_ERROR_INVALID_DATA);
+}
\ No newline at end of file