oem: meta: Add decode_oem_meta_file_io_read_req()
Add decode_oem_meta_file_io_read_req function.
This function is used to decode the message of reading file IO.
Need to include read_option (read file attributes or data), length
(the length of the read data) and read_info (The information
needed to read the file).
Take reading file data as an example:
read_info needs to contain transferFlag, offset to know the
starting position and transfer progress of the read file.
Change-Id: I425476d36e3cd69d2da45beceff1c4a2362640dc
Signed-off-by: Lora Lin <lora.lin.wiwynn@gmail.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index ae80421..95ff5db 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -20,6 +20,7 @@
### Added
1. oem: meta: Add decode_oem_meta_file_io_write_req()
+2. oem: meta: Add decode_oem_meta_file_io_read_req()
### Deprecated
diff --git a/docs/oem/meta/file-io.md b/docs/oem/meta/file-io.md
new file mode 100644
index 0000000..5bc2f4f
--- /dev/null
+++ b/docs/oem/meta/file-io.md
@@ -0,0 +1,54 @@
+# Description of file IO messages
+
+## Read Message Format
+
+### Table 1. Read Request
+
+| Offset | Type | Name | Description |
+| -------- | ------ | -------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| 0 | uint8 | Handle | This field is a handle that is used to identify PLDM command type. |
+| 1 | enum8 | Option | This field is a read option is used to identify the read file option. <br> See Table 3 for the option. |
+| 2:3 | uint16 | Length | The length in bytes N of data being sent in this part in the ReadInfo field. |
+| Variable | uint8 | ReadInfo | Portion of reading information. <br> There will be different reading information according to different ReadOption. <br> See Table 4 and Table 5 for details |
+
+### Table 2. Read response
+
+| Offset | Type | Name | Description |
+| -------- | ----- | -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ |
+| 0 | int | CompletionCode | value: { PLDM_SUCCESS, PLDM_ERROR_INVALID_DATA, PLDM_ERROR_INVALID_LENGTH } |
+| Variable | uint8 | ReadResponse | Portion of reading response. <br> There will be different reading response according to different ReadOption. <br> See Table 6 and Table 7 for details |
+
+### Table 3. Option of message type
+
+| Value | Name | Description |
+| ----- | ----------------- | -------------------------- |
+| 0x00 | ReadFileAttribute | Get file size and checksum |
+| 0x01 | ReadFileData | Get file data |
+
+### Table 4. ReadInfo Definition when ReadOption is ReadFileAttribute in message type
+
+| Offset | Type | Name | Description |
+| ------ | ---- | ---- | --------------- |
+| 0 | - | - | No request data |
+
+### Table 5. ReadInfo Definition when ReadOption is ReadFileData in message type
+
+| Offset | Type | Name | Description |
+| ------ | ------ | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 0 | uint8 | TransferFlag | The transfer flag that indiates what part of the transfer this request represents. <br> Possible values: {Start=0x01, Middle=0x02, End=0x04, StartAndEnd=0x05} |
+| 1:2 | uint16 | Offset | Offset in read file. |
+
+### Table 6. ReadResponse Definition when ReadOption is ReadFileAttribute in message type
+
+| Offset | Type | Name | Description |
+| ------ | ------ | -------- | ----------------------------------------------------------- |
+| 0:1 | uint16 | Size | This field indicates the size of the entire file, in bytes. |
+| 2:5 | uint32 | Checksum | This field indicates the checksum of the entire file. |
+
+### Table 7. ReadResponse Definition when ReadOption is ReadFileData in message type
+
+| Offset | Type | Name | Description |
+| -------- | ------ | ------------ | --------------------------------------------------------------------------------------------------------------------------------------------------------------- |
+| 0 | uint8 | TransferFlag | The transfer flag that indiates what part of the transfer this response represents. <br> Possible values: {Start=0x01, Middle=0x02, End=0x04, StartAndEnd=0x05} |
+| 1:2 | uint16 | Offset | Offset in read file. |
+| Variable | uint8 | FileData | File data can be up to 255 bytes. |
diff --git a/include/libpldm/oem/meta/file_io.h b/include/libpldm/oem/meta/file_io.h
index e30ab47..47077f1 100644
--- a/include/libpldm/oem/meta/file_io.h
+++ b/include/libpldm/oem/meta/file_io.h
@@ -20,6 +20,15 @@
PLDM_OEM_META_FILE_IO_CMD_READ_FILE = 0x3,
};
+/** @brief read options in read file io command
+ */
+enum pldm_oem_meta_file_io_read_option {
+ // Read file attribute
+ PLDM_OEM_META_FILE_IO_READ_ATTR = 0x00,
+ // Read file data
+ PLDM_OEM_META_FILE_IO_READ_DATA = 0x01,
+};
+
struct pldm_oem_meta_file_io_write_req {
uint8_t handle;
uint32_t length;
@@ -29,6 +38,41 @@
};
#define PLDM_OEM_META_FILE_IO_WRITE_REQ_MIN_LENGTH 5u
+/** @struct pldm_oem_meta_file_io_read_data_info
+ *
+ * Structure representing PLDM read file data info
+ */
+struct pldm_oem_meta_file_io_read_data_info {
+ uint8_t transferFlag;
+ uint16_t offset;
+};
+#define PLDM_OEM_META_FILE_IO_READ_DATA_INFO_LENGTH 3u
+
+/** @struct pldm_oem_meta_file_io_read_attr_info
+ *
+ * Structure representing PLDM read file attribute info
+ */
+struct pldm_oem_meta_file_io_read_attr_info {
+ uint16_t size;
+ uint32_t crc32;
+};
+#define PLDM_OEM_META_FILE_IO_READ_ATTR_INFO_LENGTH 6u
+
+/** @struct pldm_oem_meta_file_io_read_req
+ *
+ * Structure representing PLDM read file request
+ */
+struct pldm_oem_meta_file_io_read_req {
+ size_t version;
+ uint8_t handle;
+ uint8_t option;
+ uint8_t length;
+ union {
+ struct pldm_oem_meta_file_io_read_data_info data;
+ } info;
+};
+#define PLDM_OEM_META_FILE_IO_READ_REQ_MIN_LENGTH 3u
+
/** @brief Obtain the pointer to the data array of a write request
*
* @param[in] req - The pointer to the write request struct
@@ -63,6 +107,17 @@
size_t payload_length, uint8_t *file_handle,
uint32_t *length, uint8_t *data);
+/** @brief Decode OEM meta read file io req
+ *
+ * @param[in] msg - Pointer to PLDM request message
+ * @param[in] payload_length - Length of request payload
+ * @param[out] req - Pointer to the structure to store the decoded response data
+ * @return 0 on success, negative errno value on failure
+ */
+int decode_oem_meta_file_io_read_req(const struct pldm_msg *msg,
+ size_t payload_length,
+ struct pldm_oem_meta_file_io_read_req *req);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/oem/meta/file_io.c b/src/oem/meta/file_io.c
index ce7d9e3..0c82f82 100644
--- a/src/oem/meta/file_io.c
+++ b/src/oem/meta/file_io.c
@@ -89,3 +89,54 @@
return 0;
}
+
+LIBPLDM_ABI_TESTING
+int decode_oem_meta_file_io_read_req(const struct pldm_msg *msg,
+ size_t payload_length,
+ struct pldm_oem_meta_file_io_read_req *req)
+{
+ struct pldm_msgbuf _buf;
+ struct pldm_msgbuf *buf = &_buf;
+
+ if (msg == NULL || req == NULL) {
+ return -EINVAL;
+ }
+
+ if (req->version > sizeof(struct pldm_oem_meta_file_io_read_req)) {
+ return -E2BIG;
+ }
+
+ int rc = pldm_msgbuf_init_errno(
+ buf, PLDM_OEM_META_FILE_IO_READ_REQ_MIN_LENGTH, msg->payload,
+ payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_extract(buf, req->handle);
+ rc = pldm_msgbuf_extract(buf, req->option);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pldm_msgbuf_extract(buf, req->length);
+ if (rc) {
+ return rc;
+ }
+
+ switch (req->option) {
+ case PLDM_OEM_META_FILE_IO_READ_ATTR:
+ if (req->length != 0) {
+ return -EPROTO;
+ }
+ break;
+ case PLDM_OEM_META_FILE_IO_READ_DATA:
+ pldm_msgbuf_extract(buf, req->info.data.transferFlag);
+ pldm_msgbuf_extract(buf, req->info.data.offset);
+ break;
+ default:
+ return -EPROTO;
+ }
+
+ return pldm_msgbuf_destroy_consumed(buf);
+}
diff --git a/tests/oem/meta/fileio.cpp b/tests/oem/meta/fileio.cpp
index 48c0778..a40e43b 100644
--- a/tests/oem/meta/fileio.cpp
+++ b/tests/oem/meta/fileio.cpp
@@ -87,3 +87,74 @@
EXPECT_EQ(rc, -EOVERFLOW);
}
#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(DecodeOemMetaFileIoReadReq, testGoodDecodeRequest)
+{
+ struct pldm_msgbuf _ctx;
+ struct pldm_msgbuf* ctx = &_ctx;
+ int rc;
+
+ constexpr size_t payloadLen = PLDM_OEM_META_FILE_IO_READ_REQ_MIN_LENGTH +
+ PLDM_OEM_META_FILE_IO_READ_DATA_INFO_LENGTH;
+ alignas(pldm_msg) unsigned char buf[sizeof(pldm_msg_hdr) + payloadLen]{};
+ auto* msg = new (buf) pldm_msg;
+
+ rc = pldm_msgbuf_init_errno(ctx, 0, msg->payload, payloadLen);
+ ASSERT_EQ(rc, 0);
+
+ pldm_msgbuf_insert_uint8(ctx, 0);
+ pldm_msgbuf_insert_uint8(ctx, PLDM_OEM_META_FILE_IO_READ_DATA);
+ pldm_msgbuf_insert_uint8(ctx, PLDM_OEM_META_FILE_IO_READ_DATA_INFO_LENGTH);
+ pldm_msgbuf_insert_uint8(ctx, 1);
+ pldm_msgbuf_insert_uint16(ctx, 1223);
+
+ rc = pldm_msgbuf_destroy_consumed(ctx);
+ ASSERT_EQ(rc, 0);
+
+ struct pldm_oem_meta_file_io_read_req req = {};
+ req.version = sizeof(req);
+ rc = decode_oem_meta_file_io_read_req(msg, payloadLen, &req);
+ ASSERT_EQ(rc, 0);
+
+ EXPECT_EQ(req.handle, 0);
+ EXPECT_EQ(req.option, PLDM_OEM_META_FILE_IO_READ_DATA);
+ EXPECT_EQ(req.length, PLDM_OEM_META_FILE_IO_READ_DATA_INFO_LENGTH);
+ EXPECT_EQ(req.info.data.transferFlag, 1);
+ EXPECT_EQ(req.info.data.offset, 1223);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(DecodeOemMetaFileIoReadReq, testInvalidFieldsDecodeRequest)
+{
+ struct pldm_msg msg = {};
+
+ auto rc = decode_oem_meta_file_io_read_req(
+ &msg, PLDM_OEM_META_FILE_IO_READ_REQ_MIN_LENGTH, NULL);
+ EXPECT_EQ(rc, -EINVAL);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(DecodeOemMetaFileIoReadReq, testInvalidLengthDecodeRequest)
+{
+ struct pldm_oem_meta_file_io_read_req req = {};
+ struct pldm_msg msg = {};
+
+ auto rc = decode_oem_meta_file_io_read_req(&msg, 0, &req);
+ EXPECT_EQ(rc, -EOVERFLOW);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(DecodeOemMetaFileIoReadReq, testInvalidDataRequest)
+{
+ struct pldm_oem_meta_file_io_read_req req = {};
+ struct pldm_msg msg = {};
+
+ auto rc = decode_oem_meta_file_io_read_req(
+ &msg, PLDM_OEM_META_FILE_IO_READ_REQ_MIN_LENGTH - 1, &req);
+ EXPECT_EQ(rc, -EOVERFLOW);
+}
+#endif