pdr: Add pldm_pdr_get_terminus_handle() API

Adds a new libpldm API to get the terminus handle of the
particular record given as input from the PDR repo.

Change-Id: I3694cc3974a564296f4584b70de7d6d1dad2a866
Signed-off-by: Pavithra Barithaya <pavithrabarithaya07@gmail.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index a5c3f90..776b2d0 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -23,6 +23,7 @@
 2. pdr: Add pldm_entity_association_pdr_add_contained_entity_to_remote_pdr()
 3. pdr: Add pldm_entity_association_pdr_create_new()
 4. platform: Define macros for the responded transferflags
+5. pdr: Add pldm_pdr_get_terminus_handle() API
 
 ### Deprecated
 
diff --git a/include/libpldm/pdr.h b/include/libpldm/pdr.h
index 579797c..e829717 100644
--- a/include/libpldm/pdr.h
+++ b/include/libpldm/pdr.h
@@ -94,6 +94,19 @@
 uint32_t pldm_pdr_get_record_handle(const pldm_pdr *repo,
 				    const pldm_pdr_record *record);
 
+/** @brief Get terminus handle of a PDR record
+ *
+ *  @pre repo must point to a valid object
+ *  @pre record must point to a valid object
+ *
+ *  @param[in] repo - opaque pointer acting as a PDR repo handle
+ *  @param[in] reocrd - opaque pointer acting as a PDR record handle
+ *
+ *  @return uint16_t - terminus handle assigned to PDR record
+ */
+uint16_t pldm_pdr_get_terminus_handle(const pldm_pdr *repo,
+				      const pldm_pdr_record *record);
+
 /** @brief Find PDR record by record handle
  *
  *  @param[in] repo - opaque pointer acting as a PDR repo handle
diff --git a/src/dsp/pdr.c b/src/dsp/pdr.c
index d5b3173..3f80d6a 100644
--- a/src/dsp/pdr.c
+++ b/src/dsp/pdr.c
@@ -263,6 +263,17 @@
 	return record->record_handle;
 }
 
+LIBPLDM_ABI_TESTING
+uint16_t pldm_pdr_get_terminus_handle(const pldm_pdr *repo
+				      __attribute__((unused)),
+				      const pldm_pdr_record *record)
+{
+	assert(repo != NULL);
+	assert(record != NULL);
+
+	return record->terminus_handle;
+}
+
 LIBPLDM_ABI_STABLE
 bool pldm_pdr_record_is_remote(const pldm_pdr_record *record)
 {
diff --git a/tests/dsp/pdr.cpp b/tests/dsp/pdr.cpp
index f98f21f..a75184f 100644
--- a/tests/dsp/pdr.cpp
+++ b/tests/dsp/pdr.cpp
@@ -724,6 +724,57 @@
 }
 #endif
 
+#ifdef LIBPLDM_API_TESTING
+TEST(PDRAccess, testGetTerminusHandle)
+{
+
+    auto repo = pldm_pdr_init();
+
+    pldm_pdr_hdr hdr;
+
+    hdr.type = 1;
+    uint16_t firstTerminusHandle = 1;
+    EXPECT_EQ(pldm_pdr_add_check(repo, reinterpret_cast<const uint8_t*>(&hdr),
+                                 sizeof(hdr), false, firstTerminusHandle, NULL),
+              0);
+
+    hdr.type = 2;
+    uint16_t secondTerminusHandle = 2;
+    EXPECT_EQ(pldm_pdr_add_check(repo, reinterpret_cast<const uint8_t*>(&hdr),
+                                 sizeof(hdr), true, secondTerminusHandle, NULL),
+              0);
+
+    hdr.type = 3;
+    uint16_t thirdTerminusHandle = 3;
+    EXPECT_EQ(pldm_pdr_add_check(repo, reinterpret_cast<const uint8_t*>(&hdr),
+                                 sizeof(hdr), true, thirdTerminusHandle, NULL),
+              0);
+
+    uint8_t* outData = nullptr;
+    uint32_t size{};
+
+    auto firstRec =
+        pldm_pdr_find_record_by_type(repo, 1, nullptr, &outData, &size);
+    EXPECT_EQ(pldm_pdr_get_terminus_handle(repo, firstRec),
+              firstTerminusHandle);
+    outData = nullptr;
+
+    auto secondRec =
+        pldm_pdr_find_record_by_type(repo, 2, nullptr, &outData, &size);
+    EXPECT_EQ(pldm_pdr_get_terminus_handle(repo, secondRec),
+              secondTerminusHandle);
+    outData = nullptr;
+
+    auto thirdRec =
+        pldm_pdr_find_record_by_type(repo, 3, nullptr, &outData, &size);
+    EXPECT_EQ(pldm_pdr_get_terminus_handle(repo, thirdRec),
+              thirdTerminusHandle);
+    outData = nullptr;
+
+    pldm_pdr_destroy(repo);
+}
+#endif
+
 TEST(EntityAssociationPDR, testInit)
 {
     auto tree = pldm_entity_association_tree_init();