dsp: base: Add encode req & decode resp for NegotiateTransferParameters
Added encode/decode APIs for NegotiateTransferParameters command
(0x07) which is defined in DSP0240 Version 1.2.0 section 9.6.
Change-Id: I9920e1c9c9e6d9e5999d568d8d20b4c80a1d8726
Signed-off-by: Chau Ly <chaul@amperecomputing.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index e9dbd07..ab9ba44 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -49,6 +49,8 @@
- oem: ibm: Modified the state set id for slot effecter and sensor
+- base: Add encode req & decode resp for NegotiateTransferParameters.
+
### Changed
- dsp: firmware_update: Expand "params" in symbol names
diff --git a/include/libpldm/base.h b/include/libpldm/base.h
index 9088d80..ae902ea 100644
--- a/include/libpldm/base.h
+++ b/include/libpldm/base.h
@@ -131,6 +131,9 @@
#define PLDM_MULTIPART_RECEIVE_REQ_BYTES 18
#define PLDM_BASE_MULTIPART_RECEIVE_RESP_MIN_BYTES 10
+#define PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES 10
+#define PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES 11
+
#define PLDM_VERSION_0 0
#define PLDM_CURRENT_VERSION PLDM_VERSION_0
@@ -365,6 +368,25 @@
struct variable_field data;
};
+/** @struct pldm_base_negotiate_transfer_params_req
+ *
+ * Structure representing PLDM Negotiate Transfer Parameters request
+ */
+struct pldm_base_negotiate_transfer_params_req {
+ uint16_t requester_part_size;
+ bitfield8_t requester_protocol_support[8];
+};
+
+/** @struct pldm_base_negotiate_transfer_params_resp
+ *
+ * Structure representing PLDM Negotiate Transfer Parameters response
+ */
+struct pldm_base_negotiate_transfer_params_resp {
+ uint8_t completion_code;
+ uint16_t responder_part_size;
+ bitfield8_t responder_protocol_support[8];
+};
+
/**
* @brief Populate the PLDM message with the PLDM header.The caller of this API
* allocates buffer for the PLDM header when forming the PLDM message.
@@ -722,6 +744,42 @@
uint8_t pldm_type, uint8_t command,
struct pldm_msg *msg);
+/** @brief Encode a PLDM Negotiate Transfer Parameters request message
+ *
+ * @param[in] instance_id - Message's instance id
+ * @param[in] req - The pointer to the request message to be encoded
+ * @param[in,out] msg - Message will be written to this
+ * @param[in] payload_length - length of request message payload
+ * @return 0 on success
+ * -EINVAL if the input parameters' memory are not allocated,
+ * or message type or instance in request header is invalid
+ * -ENOMSG if the PLDM type in the request header is invalid
+ * -EOVERFLOW if the input message length is invalid
+ */
+int encode_pldm_base_negotiate_transfer_params_req(
+ uint8_t instance_id,
+ const struct pldm_base_negotiate_transfer_params_req *req,
+ struct pldm_msg *msg, size_t payload_length);
+
+/** @brief Decode a PLDM Negotiate Transfer Parameters response message
+ *
+ * @param[in] msg - Response message
+ * @param[in] payload_length - length of request message payload
+ * @param[out] resp - pointer to the decoded response message,
+ * excluding the data integrity checksum
+ * @return 0 on success
+ * -EINVAL if the input parameters' memory are not allocated
+ * -EOVERFLOW if the input message buffer is too short for the output
+ * response struct
+ * -EBADMSG if the input message buffer is too large for the output
+ * response struct
+ * @note Caller is responsible for memory alloc and dealloc of param
+ * 'msg.payload'
+ */
+int decode_pldm_base_negotiate_transfer_params_resp(
+ const struct pldm_msg *msg, size_t payload_length,
+ struct pldm_base_negotiate_transfer_params_resp *resp);
+
#ifdef __cplusplus
}
#endif
diff --git a/src/dsp/base.c b/src/dsp/base.c
index 42f33e2..35e3eb0 100644
--- a/src/dsp/base.c
+++ b/src/dsp/base.c
@@ -702,3 +702,85 @@
}
return PLDM_SUCCESS;
}
+
+LIBPLDM_ABI_TESTING
+int encode_pldm_base_negotiate_transfer_params_req(
+ uint8_t instance_id,
+ const struct pldm_base_negotiate_transfer_params_req *req,
+ struct pldm_msg *msg, size_t payload_length)
+{
+ PLDM_MSGBUF_DEFINE_P(buf);
+ int rc;
+
+ if (req == NULL || msg == NULL) {
+ return -EINVAL;
+ }
+
+ struct pldm_header_info header = { 0 };
+ header.instance = instance_id;
+ header.msg_type = PLDM_REQUEST;
+ header.pldm_type = PLDM_BASE;
+ header.command = PLDM_NEGOTIATE_TRANSFER_PARAMETERS;
+
+ rc = pack_pldm_header_errno(&header, &msg->hdr);
+ if (rc) {
+ return rc;
+ }
+
+ rc = pldm_msgbuf_init_errno(
+ buf, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES,
+ msg->payload, payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_insert(buf, req->requester_part_size);
+ rc = pldm_msgbuf_insert_array(
+ buf, sizeof(req->requester_protocol_support),
+ (uint8_t *)req->requester_protocol_support,
+ sizeof(req->requester_protocol_support));
+ if (rc) {
+ return pldm_msgbuf_discard(buf, rc);
+ }
+
+ return pldm_msgbuf_complete(buf);
+}
+
+LIBPLDM_ABI_TESTING
+int decode_pldm_base_negotiate_transfer_params_resp(
+ const struct pldm_msg *msg, size_t payload_length,
+ struct pldm_base_negotiate_transfer_params_resp *resp)
+{
+ PLDM_MSGBUF_DEFINE_P(buf);
+ int rc;
+
+ if (msg == NULL || resp == NULL) {
+ return -EINVAL;
+ }
+
+ rc = pldm_msg_has_error(msg, payload_length);
+
+ if (rc) {
+ resp->completion_code = rc;
+ return 0;
+ }
+
+ rc = pldm_msgbuf_init_errno(
+ buf, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES,
+ msg->payload, payload_length);
+ if (rc) {
+ return rc;
+ }
+
+ pldm_msgbuf_extract(buf, resp->completion_code);
+ pldm_msgbuf_extract(buf, resp->responder_part_size);
+ rc = pldm_msgbuf_extract_array(
+ buf, sizeof(resp->responder_protocol_support),
+ (uint8_t *)resp->responder_protocol_support,
+ sizeof(resp->responder_protocol_support));
+ if (rc) {
+ return pldm_msgbuf_discard(buf, rc);
+ }
+
+ return pldm_msgbuf_complete_consumed(buf);
+}
diff --git a/tests/dsp/base.cpp b/tests/dsp/base.cpp
index 7b5bfcf..dafe09b 100644
--- a/tests/dsp/base.cpp
+++ b/tests/dsp/base.cpp
@@ -1180,3 +1180,194 @@
ASSERT_EQ(pldm_msg_hdr_correlate_response(&req, &resp), false);
}
#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(EncodeNegotiateTransferParamsRequest, GoodTest)
+{
+ uint8_t instance_id = 0;
+
+ const struct pldm_base_negotiate_transfer_params_req req_data = {
+ 0x0001, // BE 256
+ {{0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x81}}};
+
+ std::array<uint8_t, PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES>
+ requestMsg = {0x01, 0x00, // requester_part_size = 256
+ 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x81}; // requester_protocol_support =
+ // PLDM_BASE & PLDM_FILE
+
+ PLDM_MSG_DEFINE_P(requestPtr,
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES);
+ auto rc = encode_pldm_base_negotiate_transfer_params_req(
+ instance_id, &req_data, requestPtr,
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES);
+
+ ASSERT_EQ(rc, 0);
+ EXPECT_EQ(
+ 0, memcmp(requestPtr->payload, requestMsg.data(), sizeof(requestMsg)));
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(EncodeNegotiateTransferParamsRequest, BadTestUnAllocatedPtrParams)
+{
+ int rc;
+ uint8_t instance_id = 0;
+ const struct pldm_base_negotiate_transfer_params_req req_data = {
+ 0x0001, // BE 256
+ {{0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x81}}};
+
+ PLDM_MSG_DEFINE_P(requestPtr,
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES);
+ rc = encode_pldm_base_negotiate_transfer_params_req(
+ instance_id, nullptr, requestPtr,
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES);
+ EXPECT_EQ(rc, -EINVAL);
+
+ rc = encode_pldm_base_negotiate_transfer_params_req(
+ instance_id, &req_data, nullptr,
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES);
+ EXPECT_EQ(rc, -EINVAL);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(EncodeNegotiateTransferParamsRequest,
+ BadTestInvalidExpectedOutputMsgLength)
+{
+ int rc;
+ uint8_t instance_id = 0;
+ const struct pldm_base_negotiate_transfer_params_req req_data = {
+ 0x0001, // BE 256
+ {{0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x00}, {0x81}}};
+
+ PLDM_MSG_DEFINE_P(requestPtr,
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_REQ_BYTES);
+
+ rc = encode_pldm_base_negotiate_transfer_params_req(instance_id, &req_data,
+ requestPtr, 1);
+ EXPECT_EQ(rc, -EOVERFLOW);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(DecodeNegotiateTransferParamsResponse, GoodTest)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint16_t responderPartSize = 128;
+ std::array<uint8_t, 8> responderProtocolSupport = {0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x81};
+
+ struct pldm_base_negotiate_transfer_params_resp resp_data = {};
+
+ PLDM_MSGBUF_DEFINE_P(buf);
+ int rc;
+
+ static constexpr const size_t payload_length =
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES;
+ PLDM_MSG_DEFINE_P(responseMsg, payload_length);
+
+ rc = pldm_msgbuf_init_errno(buf, 0, responseMsg->payload, payload_length);
+ ASSERT_EQ(rc, 0);
+
+ pldm_msgbuf_insert_uint8(buf, completionCode);
+ pldm_msgbuf_insert_uint16(buf, responderPartSize);
+ rc = pldm_msgbuf_insert_array_uint8(
+ buf, sizeof(resp_data.responder_protocol_support),
+ responderProtocolSupport.data(),
+ sizeof(resp_data.responder_protocol_support));
+ EXPECT_EQ(rc, 0);
+
+ ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
+
+ rc = decode_pldm_base_negotiate_transfer_params_resp(
+ responseMsg, payload_length, &resp_data);
+
+ ASSERT_EQ(rc, 0);
+ EXPECT_EQ(resp_data.completion_code, completionCode);
+ EXPECT_EQ(resp_data.responder_part_size, responderPartSize);
+ EXPECT_EQ(0, memcmp(responderProtocolSupport.data(),
+ resp_data.responder_protocol_support,
+ sizeof(resp_data.responder_protocol_support)));
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(DecodeNegotiateTransferParamsResponse, BadTestUnAllocatedPtrParams)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint16_t responderPartSize = 128;
+ std::array<uint8_t, 8> responderProtocolSupport = {0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x81};
+
+ struct pldm_base_negotiate_transfer_params_resp resp_data = {};
+
+ PLDM_MSGBUF_DEFINE_P(buf);
+ int rc;
+
+ static constexpr const size_t payload_length =
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES;
+ PLDM_MSG_DEFINE_P(responseMsg, payload_length);
+
+ rc = pldm_msgbuf_init_errno(buf, 0, responseMsg->payload, payload_length);
+ ASSERT_EQ(rc, 0);
+
+ pldm_msgbuf_insert_uint8(buf, completionCode);
+ pldm_msgbuf_insert_uint16(buf, responderPartSize);
+ rc = pldm_msgbuf_insert_array_uint8(
+ buf, sizeof(resp_data.responder_protocol_support),
+ responderProtocolSupport.data(),
+ sizeof(resp_data.responder_protocol_support));
+ EXPECT_EQ(rc, 0);
+
+ ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
+
+ rc = decode_pldm_base_negotiate_transfer_params_resp(
+ nullptr, payload_length, &resp_data);
+
+ EXPECT_EQ(rc, -EINVAL);
+
+ rc = decode_pldm_base_negotiate_transfer_params_resp(
+ responseMsg, payload_length, nullptr);
+
+ EXPECT_EQ(rc, -EINVAL);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(DecodeNegotiateTransferParamsResponse,
+ BadTestInvalidExpectedInputMsgLength)
+{
+ uint8_t completionCode = PLDM_SUCCESS;
+ uint16_t responderPartSize = 128;
+ std::array<uint8_t, 8> responderProtocolSupport = {0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x81};
+
+ struct pldm_base_negotiate_transfer_params_resp resp_data = {};
+
+ PLDM_MSGBUF_DEFINE_P(buf);
+ int rc;
+
+ static constexpr const size_t payload_length =
+ PLDM_BASE_NEGOTIATE_TRANSFER_PARAMETERS_RESP_BYTES;
+ PLDM_MSG_DEFINE_P(responseMsg, payload_length);
+
+ rc = pldm_msgbuf_init_errno(buf, 0, responseMsg->payload, payload_length);
+ ASSERT_EQ(rc, 0);
+
+ pldm_msgbuf_insert_uint8(buf, completionCode);
+ pldm_msgbuf_insert_uint16(buf, responderPartSize);
+ rc = pldm_msgbuf_insert_array_uint8(
+ buf, sizeof(resp_data.responder_protocol_support),
+ responderProtocolSupport.data(),
+ sizeof(resp_data.responder_protocol_support));
+ EXPECT_EQ(rc, 0);
+
+ ASSERT_EQ(pldm_msgbuf_complete_consumed(buf), 0);
+
+ rc = decode_pldm_base_negotiate_transfer_params_resp(responseMsg, 0,
+ &resp_data);
+
+ EXPECT_EQ(rc, -EOVERFLOW);
+}
+#endif
\ No newline at end of file