base: decode_set_tid_req() in PLDM base

Add decode API for SetTID request based on DSP0240 1.2.0 Section
9.1.1 Table 8.

Change-Id: I448f76b810bfb5dbf2b84c85db266c32416a181a
Signed-off-by: Vishnu Santhosh <vishnu.santhosh@oss.qualcomm.com>
Signed-off-by: Deepak Kumar Singh <deepak.singh@oss.qualcomm.com>
Signed-off-by: Rameshwar Varaganti <rvaragan@qti.qualcomm.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 511ea85..0a62ae8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -26,6 +26,7 @@
 - platform: Add encode req & decode resp for GetEventReceiver
 - pdr: Add pldm_pdr_delete_by_sensor_id() API
 - pdr: Add pldm_entity_association_tree_delete_node() API
+- base: Add decode_set_tid_req() API
 
 - oem: ibm: Add boot side rename state set and enum
 
diff --git a/include/libpldm/base.h b/include/libpldm/base.h
index ae902ea..928c564 100644
--- a/include/libpldm/base.h
+++ b/include/libpldm/base.h
@@ -656,6 +656,19 @@
  */
 int encode_set_tid_req(uint8_t instance_id, uint8_t tid, struct pldm_msg *msg);
 
+/** @brief Decode a SetTID request message
+ *
+ *  @param[in] msg - Request message
+ *  @param[in] payload_length - length of request message payload
+ *  @param[out] tid - Terminus ID
+ *  @return 0 on success
+ *         -EINVAL if the input parameters' memory are not allocated,
+ *         or tid is invalid
+ *         -EOVERFLOW if the input message length is invalid
+ */
+int decode_set_tid_req(const struct pldm_msg *msg, size_t payload_length,
+		       uint8_t *tid);
+
 /* Responder */
 
 /* MultipartRecieve */
diff --git a/src/dsp/base.c b/src/dsp/base.c
index 35e3eb0..1b16381 100644
--- a/src/dsp/base.c
+++ b/src/dsp/base.c
@@ -502,6 +502,28 @@
 	return PLDM_SUCCESS;
 }
 
+LIBPLDM_ABI_TESTING
+int decode_set_tid_req(const struct pldm_msg *msg, size_t payload_length,
+		       uint8_t *tid)
+{
+	PLDM_MSGBUF_DEFINE_P(buf);
+	int rc;
+
+	if (!msg || !tid) {
+		return -EINVAL;
+	}
+
+	rc = pldm_msgbuf_init_errno(buf, PLDM_SET_TID_REQ_BYTES, msg->payload,
+				    payload_length);
+	if (rc) {
+		return rc;
+	}
+
+	pldm_msgbuf_extract_p(buf, tid);
+
+	return pldm_msgbuf_complete_consumed(buf);
+}
+
 LIBPLDM_ABI_STABLE
 int decode_multipart_receive_req(const struct pldm_msg *msg,
 				 size_t payload_length, uint8_t *pldm_type,
diff --git a/tests/dsp/base.cpp b/tests/dsp/base.cpp
index dafe09b..25536ec 100644
--- a/tests/dsp/base.cpp
+++ b/tests/dsp/base.cpp
@@ -1026,6 +1026,62 @@
 }
 
 #ifdef LIBPLDM_API_TESTING
+TEST(SetTID, testGoodDecodeRequest)
+{
+    uint8_t tid = 0x01;
+    uint8_t tidOut = 0x00;
+    std::array<uint8_t, sizeof(pldm_msg_hdr) + sizeof(tid)> requestMsg{};
+
+    requestMsg[sizeof(pldm_msg_hdr)] = tid;
+
+    pldm_msg* request = new (requestMsg.data()) pldm_msg;
+    auto rc = decode_set_tid_req(
+        request, requestMsg.size() - sizeof(pldm_msg_hdr), &tidOut);
+
+    EXPECT_EQ(rc, PLDM_SUCCESS);
+    EXPECT_EQ(tid, tidOut);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(SetTID, testBadDecodeRequestMsg)
+{
+    uint8_t tid = 0x01;
+    std::array<uint8_t, hdrSize + PLDM_SET_TID_REQ_BYTES> requestMsg{};
+
+    auto rc = decode_set_tid_req(
+        nullptr, requestMsg.size() - sizeof(pldm_msg_hdr), &tid);
+
+    EXPECT_EQ(rc, -EINVAL);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(SetTID, testBadDecodeRequestTid)
+{
+    std::array<uint8_t, hdrSize + PLDM_SET_TID_REQ_BYTES> requestMsg{};
+    pldm_msg* request = new (requestMsg.data()) pldm_msg;
+
+    auto rc = decode_set_tid_req(
+        request, requestMsg.size() - sizeof(pldm_msg_hdr), nullptr);
+
+    EXPECT_EQ(rc, -EINVAL);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
+TEST(SetTID, testBadDecodeRequestMsgSize)
+{
+    std::array<uint8_t, hdrSize + PLDM_SET_TID_REQ_BYTES> requestMsg{};
+    pldm_msg* request = new (requestMsg.data()) pldm_msg;
+
+    auto rc = decode_set_tid_req(request, -1, nullptr);
+
+    EXPECT_EQ(rc, -EINVAL);
+}
+#endif
+
+#ifdef LIBPLDM_API_TESTING
 TEST(PldmMsgHdr, correlateSuccess)
 {
     static const struct pldm_msg_hdr req = {