libpldm/base: Add MultipartReceive req decoding
Adds MultipartReceive (0x09) request decoding, per DSP0240 v1.1.0
section 8.6.5.
Signed-off-by: Joe Komlodi <komlodi@google.com>
Change-Id: I8d37a9abb7361cc7a238b5b322907739343ff473
diff --git a/libpldm/tests/libpldm_base_test.cpp b/libpldm/tests/libpldm_base_test.cpp
index b8b25d3..b3b1383 100644
--- a/libpldm/tests/libpldm_base_test.cpp
+++ b/libpldm/tests/libpldm_base_test.cpp
@@ -524,6 +524,221 @@
EXPECT_EQ(tid, 1);
}
+TEST(MultipartReceive, testDecodeRequestPass)
+{
+ constexpr uint8_t kPldmType = PLDM_BASE;
+ constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
+ constexpr uint32_t kTransferCtx = 0x01;
+ constexpr uint32_t kTransferHandle = 0x10;
+ constexpr uint32_t kSectionOffset = 0x0;
+ constexpr uint32_t kSectionLength = 0x10;
+ uint8_t pldm_type = 0x0;
+ uint8_t flag = PLDM_GET_FIRSTPART;
+ uint32_t transfer_ctx;
+ uint32_t transfer_handle;
+ uint32_t section_offset;
+ uint32_t section_length;
+
+ // Header values don't matter for this test.
+ pldm_msg_hdr hdr{};
+ // Assign values to the packet struct and memcpy to ensure correct byte
+ // ordering.
+ pldm_multipart_receive_req req_pkt = {
+ .pldm_type = kPldmType,
+ .transfer_opflag = kFlag,
+ .transfer_ctx = kTransferCtx,
+ .transfer_handle = kTransferHandle,
+ .section_offset = kSectionOffset,
+ .section_length = kSectionLength,
+ };
+ std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+ std::memcpy(req.data(), &hdr, sizeof(hdr));
+ std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
+
+ pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
+ int rc = decode_multipart_receive_req(
+ pldm_request, req.size() - hdrSize, &pldm_type, &flag, &transfer_ctx,
+ &transfer_handle, §ion_offset, §ion_length);
+
+ EXPECT_EQ(rc, PLDM_SUCCESS);
+ EXPECT_EQ(pldm_type, kPldmType);
+ EXPECT_EQ(flag, kFlag);
+ EXPECT_EQ(transfer_ctx, kTransferCtx);
+ EXPECT_EQ(transfer_handle, kTransferHandle);
+ EXPECT_EQ(section_offset, kSectionOffset);
+ EXPECT_EQ(section_length, kSectionLength);
+}
+
+TEST(MultipartReceive, testDecodeRequestFailNullData)
+{
+ EXPECT_EQ(decode_multipart_receive_req(NULL, 0, NULL, NULL, NULL, NULL,
+ NULL, NULL),
+ PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(MultipartReceive, testDecodeRequestFailBadLength)
+{
+ constexpr uint8_t kPldmType = PLDM_BASE;
+ constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
+ uint8_t pldm_type;
+ uint8_t flag;
+ uint32_t transfer_ctx;
+ uint32_t transfer_handle;
+ uint32_t section_offset;
+ uint32_t section_length;
+
+ // Header values don't matter for this test.
+ pldm_msg_hdr hdr{};
+ // Assign values to the packet struct and memcpy to ensure correct byte
+ // ordering.
+ pldm_multipart_receive_req req_pkt{};
+ req_pkt.pldm_type = kPldmType;
+ req_pkt.transfer_opflag = kFlag;
+
+ std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+ std::memcpy(req.data(), &hdr, sizeof(hdr));
+ std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
+
+ pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
+ EXPECT_EQ(decode_multipart_receive_req(
+ pldm_request, (req.size() - hdrSize) + 1, &pldm_type, &flag,
+ &transfer_ctx, &transfer_handle, §ion_offset,
+ §ion_length),
+ PLDM_ERROR_INVALID_LENGTH);
+}
+
+TEST(MultipartReceive, testDecodeRequestFailBadPldmType)
+{
+ constexpr uint8_t kPldmType = 0xff;
+ constexpr uint8_t kFlag = PLDM_XFER_FIRST_PART;
+ uint8_t pldm_type;
+ uint8_t flag;
+ uint32_t transfer_ctx;
+ uint32_t transfer_handle;
+ uint32_t section_offset;
+ uint32_t section_length;
+
+ // Header values don't matter for this test.
+ pldm_msg_hdr hdr{};
+ // Assign values to the packet struct and memcpy to ensure correct byte
+ // ordering.
+ pldm_multipart_receive_req req_pkt{};
+ req_pkt.pldm_type = kPldmType;
+ req_pkt.transfer_opflag = kFlag;
+
+ std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+ std::memcpy(req.data(), &hdr, sizeof(hdr));
+ std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
+
+ pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
+ EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
+ &pldm_type, &flag, &transfer_ctx,
+ &transfer_handle, §ion_offset,
+ §ion_length),
+ PLDM_ERROR_INVALID_PLDM_TYPE);
+}
+
+TEST(MultipartReceive, testDecodeRequestFailBadTransferFlag)
+{
+ constexpr uint8_t kPldmType = PLDM_BASE;
+ constexpr uint8_t kFlag = PLDM_XFER_CURRENT_PART + 0x10;
+ uint8_t pldm_type;
+ uint8_t flag;
+ uint32_t transfer_ctx;
+ uint32_t transfer_handle;
+ uint32_t section_offset;
+ uint32_t section_length;
+
+ // Header values don't matter for this test.
+ pldm_msg_hdr hdr{};
+ // Assign values to the packet struct and memcpy to ensure correct byte
+ // ordering.
+ pldm_multipart_receive_req req_pkt{};
+ req_pkt.pldm_type = kPldmType;
+ req_pkt.transfer_opflag = kFlag;
+
+ std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+ std::memcpy(req.data(), &hdr, sizeof(hdr));
+ std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
+
+ pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
+ EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
+ &pldm_type, &flag, &transfer_ctx,
+ &transfer_handle, §ion_offset,
+ §ion_length),
+ PLDM_INVALID_TRANSFER_OPERATION_FLAG);
+}
+
+TEST(MultipartReceive, testDecodeRequestFailBadOffset)
+{
+ constexpr uint8_t kPldmType = PLDM_BASE;
+ constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
+ constexpr uint32_t kTransferHandle = 0x01;
+ constexpr uint32_t kSectionOffset = 0x0;
+ uint8_t pldm_type;
+ uint8_t flag;
+ uint32_t transfer_ctx;
+ uint32_t transfer_handle;
+ uint32_t section_offset;
+ uint32_t section_length;
+
+ // Header values don't matter for this test.
+ pldm_msg_hdr hdr{};
+ // Assign values to the packet struct and memcpy to ensure correct byte
+ // ordering.
+ pldm_multipart_receive_req req_pkt{};
+ req_pkt.pldm_type = kPldmType;
+ req_pkt.transfer_opflag = kFlag;
+ req_pkt.transfer_handle = kTransferHandle;
+ req_pkt.section_offset = kSectionOffset;
+
+ std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+ std::memcpy(req.data(), &hdr, sizeof(hdr));
+ std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
+
+ pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
+ EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
+ &pldm_type, &flag, &transfer_ctx,
+ &transfer_handle, §ion_offset,
+ §ion_length),
+ PLDM_ERROR_INVALID_DATA);
+}
+
+TEST(MultipartReceive, testDecodeRequestFailBadHandle)
+{
+ constexpr uint8_t kPldmType = PLDM_BASE;
+ constexpr uint8_t kFlag = PLDM_XFER_NEXT_PART;
+ constexpr uint32_t kSectionOffset = 0x100;
+ constexpr uint32_t kTransferHandle = 0x0;
+ uint8_t pldm_type;
+ uint8_t flag;
+ uint32_t transfer_ctx;
+ uint32_t transfer_handle;
+ uint32_t section_offset;
+ uint32_t section_length;
+
+ // Header values don't matter for this test.
+ pldm_msg_hdr hdr{};
+ // Assign values to the packet struct and memcpy to ensure correct byte
+ // ordering.
+ pldm_multipart_receive_req req_pkt{};
+ req_pkt.pldm_type = kPldmType;
+ req_pkt.transfer_opflag = kFlag;
+ req_pkt.transfer_handle = kTransferHandle;
+ req_pkt.section_offset = kSectionOffset;
+
+ std::vector<uint8_t> req(sizeof(hdr) + PLDM_MULTIPART_RECEIVE_REQ_BYTES);
+ std::memcpy(req.data(), &hdr, sizeof(hdr));
+ std::memcpy(req.data() + sizeof(hdr), &req_pkt, sizeof(req_pkt));
+
+ pldm_msg* pldm_request = reinterpret_cast<pldm_msg*>(req.data());
+ EXPECT_EQ(decode_multipart_receive_req(pldm_request, req.size() - hdrSize,
+ &pldm_type, &flag, &transfer_ctx,
+ &transfer_handle, §ion_offset,
+ §ion_length),
+ PLDM_ERROR_INVALID_DATA);
+}
+
TEST(CcOnlyResponse, testEncode)
{
struct pldm_msg responseMsg;