pdr: Add pldm_entity_association_pdr_add_from_node_with_record_handle()

This API adds the entity association PDR record from node to
the repo with record handle given as the input parameter by the
caller API.
Earlier the records where added in a sequential way alone, with
this change the entity association PDR records gets the new record
handle based on the input value.

Change-Id: Ib29ecf1ef493cbb45938502a670c68e2e0bbd6bb
Signed-off-by: Pavithra Barithaya <pavithra.b@ibm.com>
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 89ad2f3..0b1b249 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -24,6 +24,7 @@
 3. pdr: Introduce remote_container_id and associated APIs
 4. pdr: Add APIs for creating and locating remote PDRs
 5. pdr: Add pldm_pdr_find_last_in_range()
+6. pdr: Add pldm_entity_association_pdr_add_from_node_with_record_handle()
 
 ### Changed
 
diff --git a/include/libpldm/pdr.h b/include/libpldm/pdr.h
index dc4928c..c38f097 100644
--- a/include/libpldm/pdr.h
+++ b/include/libpldm/pdr.h
@@ -382,6 +382,24 @@
 	pldm_entity_node *node, pldm_pdr *repo, pldm_entity **entities,
 	size_t num_entities, bool is_remote, uint16_t terminus_handle);
 
+/** @brief Add entity association pdr record based on record handle
+ *  earlier the records where added in a sequential way alone, with
+ *  this change the entity association PDR records gets the new record
+ *  handle based on the input value given.
+ *
+ *  @param[in] node - opaque pointer acting as a handle to an entity node
+ *  @param[in] repo - PDR repo where entity association records should be added
+ *  @param[in] is_remote  - if true, then the PDR is not from this terminus
+ *  @param[in] terminus_handle - terminus handle of the terminus
+ *  @param[in] record_handle - record handle of the PDR
+ *
+ *  @return 0 on succes, -EINVAL if the provided arguments are invalid.
+ */
+int pldm_entity_association_pdr_add_from_node_with_record_handle(
+	pldm_entity_node *node, pldm_pdr *repo, pldm_entity **entities,
+	size_t num_entities, bool is_remote, uint16_t terminus_handle,
+	uint32_t record_handle);
+
 /** @brief Find entity reference in tree
  *
  *  @param[in] tree - opaque pointer to entity association tree
diff --git a/src/pdr.c b/src/pdr.c
index 600f789..0d6ce76 100644
--- a/src/pdr.c
+++ b/src/pdr.c
@@ -690,12 +690,10 @@
 	return false;
 }
 
-static void entity_association_pdr_add_children(pldm_entity_node *curr,
-						pldm_pdr *repo, uint16_t size,
-						uint8_t contained_count,
-						uint8_t association_type,
-						bool is_remote,
-						uint16_t terminus_handle)
+static void entity_association_pdr_add_children(
+	pldm_entity_node *curr, pldm_pdr *repo, uint16_t size,
+	uint8_t contained_count, uint8_t association_type, bool is_remote,
+	uint16_t terminus_handle, uint32_t record_handle)
 {
 	uint8_t pdr[size];
 	uint8_t *start = pdr;
@@ -737,12 +735,14 @@
 		node = node->next_sibling;
 	}
 
-	pldm_pdr_add(repo, pdr, size, 0, is_remote, terminus_handle);
+	pldm_pdr_add(repo, pdr, size, record_handle, is_remote,
+		     terminus_handle);
 }
 
 static void entity_association_pdr_add_entry(pldm_entity_node *curr,
 					     pldm_pdr *repo, bool is_remote,
-					     uint16_t terminus_handle)
+					     uint16_t terminus_handle,
+					     uint32_t record_handle)
 {
 	uint8_t num_logical_children = pldm_entity_get_num_children(
 		curr, PLDM_ENTITY_ASSOCIAION_LOGICAL);
@@ -758,7 +758,7 @@
 		entity_association_pdr_add_children(
 			curr, repo, logical_pdr_size, num_logical_children,
 			PLDM_ENTITY_ASSOCIAION_LOGICAL, is_remote,
-			terminus_handle);
+			terminus_handle, record_handle);
 	}
 
 	if (num_physical_children) {
@@ -770,7 +770,7 @@
 		entity_association_pdr_add_children(
 			curr, repo, physical_pdr_size, num_physical_children,
 			PLDM_ENTITY_ASSOCIAION_PHYSICAL, is_remote,
-			terminus_handle);
+			terminus_handle, record_handle);
 	}
 }
 
@@ -793,7 +793,8 @@
 static void entity_association_pdr_add(pldm_entity_node *curr, pldm_pdr *repo,
 				       pldm_entity **entities,
 				       size_t num_entities, bool is_remote,
-				       uint16_t terminus_handle)
+				       uint16_t terminus_handle,
+				       uint32_t record_handle)
 {
 	if (curr == NULL) {
 		return;
@@ -801,13 +802,15 @@
 	bool to_add = true;
 	to_add = is_present(curr->entity, entities, num_entities);
 	if (to_add) {
-		entity_association_pdr_add_entry(curr, repo, is_remote,
-						 terminus_handle);
+		entity_association_pdr_add_entry(
+			curr, repo, is_remote, terminus_handle, record_handle);
 	}
 	entity_association_pdr_add(curr->next_sibling, repo, entities,
-				   num_entities, is_remote, terminus_handle);
+				   num_entities, is_remote, terminus_handle,
+				   record_handle);
 	entity_association_pdr_add(curr->first_child, repo, entities,
-				   num_entities, is_remote, terminus_handle);
+				   num_entities, is_remote, terminus_handle,
+				   record_handle);
 }
 
 LIBPLDM_ABI_STABLE
@@ -819,7 +822,7 @@
 	assert(repo != NULL);
 
 	entity_association_pdr_add(tree->root, repo, NULL, 0, is_remote,
-				   terminus_handle);
+				   terminus_handle, 0);
 }
 
 LIBPLDM_ABI_STABLE
@@ -829,8 +832,25 @@
 {
 	assert(repo != NULL);
 
+	pldm_entity_association_pdr_add_from_node_with_record_handle(
+		node, repo, entities, num_entities, is_remote, terminus_handle,
+		0);
+}
+
+LIBPLDM_ABI_TESTING
+int pldm_entity_association_pdr_add_from_node_with_record_handle(
+	pldm_entity_node *node, pldm_pdr *repo, pldm_entity **entities,
+	size_t num_entities, bool is_remote, uint16_t terminus_handle,
+	uint32_t record_handle)
+{
+	if (!node || !repo || !entities) {
+		return -EINVAL;
+	}
+
 	entity_association_pdr_add(node, repo, entities, num_entities,
-				   is_remote, terminus_handle);
+				   is_remote, terminus_handle, record_handle);
+
+	return 0;
 }
 
 LIBPLDM_ABI_STABLE