xref: /openbmc/libpldm/include/libpldm/pdr.h (revision ae05d5e564fc5a6c622c1d85196420e097b448ad)
1 /* SPDX-License-Identifier: Apache-2.0 OR GPL-2.0-or-later */
2 #ifndef PDR_H
3 #define PDR_H
4 
5 #ifdef __cplusplus
6 extern "C" {
7 #endif
8 
9 #include <stdbool.h>
10 #include <stddef.h>
11 #include <stdint.h>
12 
13 /** @struct pldm_pdr
14  *  opaque structure that acts as a handle to a PDR repository
15  */
16 typedef struct pldm_pdr pldm_pdr;
17 
18 /** @struct pldm_pdr_record
19  *  opaque structure that acts as a handle to a PDR record
20  */
21 typedef struct pldm_pdr_record pldm_pdr_record;
22 
23 /* ====================== */
24 /* Common PDR access APIs */
25 /* ====================== */
26 
27 /** @brief Make a new PDR repository
28  *
29  *  @return opaque pointer that acts as a handle to the repository; NULL if no
30  *  repository could be created
31  *
32  *  @note  Caller may make multiple repositories (for its own PDRs, as well as
33  *  for PDRs received by other entities) and can associate the returned handle
34  *  to a PLDM terminus id.
35  */
36 pldm_pdr *pldm_pdr_init(void);
37 
38 /** @brief Destroy a PDR repository (and free up associated resources)
39  *
40  *  @param[in/out] repo - pointer to opaque pointer acting as a PDR repo handle
41  */
42 void pldm_pdr_destroy(pldm_pdr *repo);
43 
44 /** @brief Get number of records in a PDR repository
45  *
46  *  @pre repo must point to a valid object
47  *
48  *  @param[in] repo - opaque pointer acting as a PDR repo handle
49  *
50  *  @return uint32_t - number of records
51  */
52 uint32_t pldm_pdr_get_record_count(const pldm_pdr *repo);
53 
54 /** @brief Get size of a PDR repository, in bytes
55  *
56  *  @pre repo must point to a valid object
57  *
58  *  @param[in] repo - opaque pointer acting as a PDR repo handle
59  *
60  *  @return uint32_t - size in bytes
61  */
62 uint32_t pldm_pdr_get_repo_size(const pldm_pdr *repo);
63 
64 /** @brief Add a PDR record to a PDR repository, or return an error
65  *
66  *  @param[in/out] repo - opaque pointer acting as a PDR repo handle
67  *  @param[in] data - pointer to a PDR record, pointing to a PDR definition as
68  *  per DSP0248. This data is memcpy'd.
69  *  @param[in] size - size of input PDR record in bytes
70  *  @param[in] is_remote - if true, then the PDR is not from this terminus
71  *  @param[in] terminus_handle - terminus handle of the input PDR record
72  *  @param[in,out] record_handle - record handle of input PDR record. If this is set to 0 then a
73  *  record handle is computed. The computed handle is assigned to both the PDR record and back into
74  *  record_handle for the caller to consume.
75  *
76  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
77  *  allocation fails, or -EOVERFLOW if a record handle could not be allocated
78  */
79 int pldm_pdr_add(pldm_pdr *repo, const uint8_t *data, uint32_t size,
80 		 bool is_remote, uint16_t terminus_handle,
81 		 uint32_t *record_handle);
82 
83 /** @brief Get record handle of a PDR record
84  *
85  *  @pre repo must point to a valid object
86  *  @pre record must point to a valid object
87  *
88  *  @param[in] repo - opaque pointer acting as a PDR repo handle
89  *  @param[in] record - opaque pointer acting as a PDR record handle
90  *
91  *  @return uint32_t - record handle assigned to PDR record; 0 if record is not
92  *  found
93  */
94 uint32_t pldm_pdr_get_record_handle(const pldm_pdr *repo,
95 				    const pldm_pdr_record *record);
96 
97 /** @brief Get terminus handle of a PDR record
98  *
99  *  @pre repo must point to a valid object
100  *  @pre record must point to a valid object
101  *
102  *  @param[in] repo - opaque pointer acting as a PDR repo handle
103  *  @param[in] reocrd - opaque pointer acting as a PDR record handle
104  *
105  *  @return uint16_t - terminus handle assigned to PDR record
106  */
107 uint16_t pldm_pdr_get_terminus_handle(const pldm_pdr *repo,
108 				      const pldm_pdr_record *record);
109 
110 /** @brief Find PDR record by record handle
111  *
112  *  @param[in] repo - opaque pointer acting as a PDR repo handle
113  *  @param[in] record_handle - input record handle
114  *  @param[in/out] data - will point to PDR record data (as per DSP0248) on
115  *                        return
116  *  @param[out] size - *size will be size of PDR record
117  *  @param[out] next_record_handle - *next_record_handle will be the record
118  *  handle of record next to the returned PDR record
119  *
120  *  @return opaque pointer acting as PDR record handle, will be NULL if record
121  *  was not found
122  */
123 const pldm_pdr_record *pldm_pdr_find_record(const pldm_pdr *repo,
124 					    uint32_t record_handle,
125 					    uint8_t **data, uint32_t *size,
126 					    uint32_t *next_record_handle);
127 
128 /** @brief Get PDR record next to input PDR record
129  *
130  *  @param[in] repo - opaque pointer acting as a PDR repo handle
131  *  @param[in] curr_record - opaque pointer acting as a PDR record handle
132  *  @param[in/out] data - will point to PDR record data (as per DSP0248) on
133  *                        return
134  *  @param[out] size - *size will be size of PDR record
135  *  @param[out] next_record_handle - *next_record_handle will be the record
136  *  handle of record nect to the returned PDR record
137  *
138  *  @return opaque pointer acting as PDR record handle, will be NULL if record
139  *  was not found
140  */
141 const pldm_pdr_record *
142 pldm_pdr_get_next_record(const pldm_pdr *repo,
143 			 const pldm_pdr_record *curr_record, uint8_t **data,
144 			 uint32_t *size, uint32_t *next_record_handle);
145 
146 /** @brief Find (first) PDR record by PDR type
147  *
148  *  @param[in] repo - opaque pointer acting as a PDR repo handle
149  *  @param[in] pdr_type - PDR type number as per DSP0248
150  *  @param[in] curr_record - opaque pointer acting as a PDR record handle; if
151  *  not NULL, then search will begin from this record's next record
152  *  @param[in/out] data - will point to PDR record data (as per DSP0248) on
153  *                        return, if input is not NULL
154  *  @param[out] size - *size will be size of PDR record, if input is not NULL
155  *
156  *  @return opaque pointer acting as PDR record handle, will be NULL if record
157  *  was not found
158  */
159 const pldm_pdr_record *
160 pldm_pdr_find_record_by_type(const pldm_pdr *repo, uint8_t pdr_type,
161 			     const pldm_pdr_record *curr_record, uint8_t **data,
162 			     uint32_t *size);
163 
164 /** @brief Determine if a record is a remote record
165  *
166  *  @pre record must point to a valid object
167  *
168  *  @return true if the record is a remote record, false otherwise.
169  */
170 bool pldm_pdr_record_is_remote(const pldm_pdr_record *record);
171 
172 /** @brief Remove all PDR records that belong to a remote terminus
173  *
174  *  @param[in] repo - opaque pointer acting as a PDR repo handle
175  *
176  *  If repo is NULL then there are no PDRs that can be removed.
177  */
178 void pldm_pdr_remove_remote_pdrs(pldm_pdr *repo);
179 
180 /** @brief Remove all remote PDR's that belong to a specific terminus
181  *         handle
182  *  @param[in] repo - opaque pointer acting as a PDR repo handle
183  *  @param[in] terminus_handle - Terminus Handle of the remove PLDM terminus
184  *
185  *  If repo is NULL there are no PDRs that can be removed.
186  */
187 void pldm_pdr_remove_pdrs_by_terminus_handle(pldm_pdr *repo,
188 					     uint16_t terminus_handle);
189 
190 /** @brief Update the validity of TL PDR - the validity is decided based on
191  * whether the valid bit is set or not as per the spec DSP0248
192  *
193  * @param[in] repo - opaque pointer acting as a PDR repo handle
194  * @param[in] terminus_handle - PLDM terminus handle
195  * @param[in] tid - Terminus ID
196  * @param[in] tl_eid - MCTP endpoint EID
197  * @param[in] valid - validity bit of TLPDR
198  */
199 /* NOLINTNEXTLINE(readability-identifier-naming) */
200 void pldm_pdr_update_TL_pdr(const pldm_pdr *repo, uint16_t terminus_handle,
201 			    uint8_t tid, uint8_t tl_eid, bool valid);
202 
203 /** @brief Find the last record within the particular range
204  * of record handles
205  *
206  *  @param[in] repo - pointer acting as a PDR repo handle
207  *  @param[in] first - first record handle value of the records in the range
208  *  @param[in] last - last record handle value of the records in the range
209  *
210  *  @return pointer to the PDR record,will be NULL if record was not
211  *  found
212  */
213 pldm_pdr_record *pldm_pdr_find_last_in_range(const pldm_pdr *repo,
214 					     uint32_t first, uint32_t last);
215 
216 /** @brief find the container ID of the contained entity which is not in the
217  *  particular range of record handles given
218  *
219  * @param[in] repo - opaque pointer acting as a PDR repo handle
220  * @param[in] entity_type - entity type
221  * @param[in] entity_instance - instance of the entity
222  * @param[in] child_index - index of the child entity whose container id needs to be found
223  * @param[in] range_exclude_start_handle - first record handle in the range of the remote endpoint
224  * 	      which is ignored
225  * @param[in] range_exclude_end_handle - last record handle in the range of the remote endpoint
226  * 	      which is ignored
227  * @param[out] container_id - container id of the contained entity
228  *
229  * @return container id of the PDR record found on success,-EINVAL when repo is NULL
230  * or -ENOENT if the container id is not found.
231  */
232 int pldm_pdr_find_child_container_id_index_range_exclude(
233 	const pldm_pdr *repo, uint16_t entity_type, uint16_t entity_instance,
234 	uint8_t child_index, uint32_t range_exclude_start_handle,
235 	uint32_t range_exclude_end_handle, uint16_t *container_id);
236 
237 /* ======================= */
238 /* FRU Record Set PDR APIs */
239 /* ======================= */
240 
241 /** @brief Add a FRU record set PDR record to a PDR repository, or return an error
242  *
243  *  @param[in/out] repo - opaque pointer acting as a PDR repo handle
244  *  @param[in] terminus_handle - PLDM terminus handle of terminus owning the PDR
245  *  record
246  *  @param[in] fru_rsi - FRU record set identifier
247  *  @param[in] entity_type - entity type of FRU
248  *  @param[in] entity_instance_num - entity instance number of FRU
249  *  @param[in] container_id - container id of FRU
250  *  @param[in,out] bmc_record_handle - A pointer to the handle used to construct the next record. If
251  *  		   the value is zero on input then a new handle is automatically allocated.
252  *  		   Otherwise, the provided handle is used. If a new handle is automatically
253  *  		   allocated then the object pointed to by bmc_record_handle will contain its value
254  *  		   as output.
255  *  @return 0 on success, -EINVAL if the arguments are invalid, or -ENOMEM if an internal allocation
256  *  	    fails.
257  */
258 int pldm_pdr_add_fru_record_set(pldm_pdr *repo, uint16_t terminus_handle,
259 				uint16_t fru_rsi, uint16_t entity_type,
260 				uint16_t entity_instance_num,
261 				uint16_t container_id,
262 				uint32_t *bmc_record_handle);
263 
264 /** @brief Find a FRU record set PDR by FRU record set identifier
265  *
266  *  @param[in] repo - opaque pointer acting as a PDR repo handle
267  *  @param[in] fru_rsi - FRU record set identifier
268  *  @param[in] terminus_handle - *terminus_handle will be FRU terminus handle of
269  *  found PDR, or 0 if not found
270  *  @param[in] entity_type - *entity_type will be FRU entity type of found PDR,
271  *  or 0 if not found
272  *  @param[in] entity_instance_num - *entity_instance_num will be FRU entity
273  *  instance number of found PDR, or 0 if not found
274  *  @param[in] container_id - *cintainer_id will be FRU container id of found
275  *  PDR, or 0 if not found
276  *
277  *  @return An opaque pointer to the PDR record on success, or NULL on failure
278  */
279 const pldm_pdr_record *pldm_pdr_fru_record_set_find_by_rsi(
280 	const pldm_pdr *repo, uint16_t fru_rsi, uint16_t *terminus_handle,
281 	uint16_t *entity_type, uint16_t *entity_instance_num,
282 	uint16_t *container_id);
283 
284 /* =========================== */
285 /* Entity Association PDR APIs */
286 /* =========================== */
287 
288 typedef struct pldm_entity {
289 	uint16_t entity_type;
290 	uint16_t entity_instance_num;
291 	uint16_t entity_container_id;
292 } __attribute__((packed)) pldm_entity;
293 
294 enum entity_association_containment_type {
295 	PLDM_ENTITY_ASSOCIAION_PHYSICAL = 0x0,
296 	PLDM_ENTITY_ASSOCIAION_LOGICAL = 0x1,
297 };
298 
299 /** @struct pldm_entity_association_tree
300  *  opaque structure that represents the entity association hierarchy
301  */
302 typedef struct pldm_entity_association_tree pldm_entity_association_tree;
303 
304 /** @struct pldm_entity_node
305  *  opaque structure that represents a node in the entity association hierarchy
306  */
307 typedef struct pldm_entity_node pldm_entity_node;
308 
309 /** @brief Make a new entity association tree
310  *
311  *  @return opaque pointer that acts as a handle to the tree; NULL if no
312  *  tree could be created
313  */
314 pldm_entity_association_tree *pldm_entity_association_tree_init(void);
315 
316 /** @brief Add a local entity into the entity association tree
317  *
318  *  @param[in/out] tree - opaque pointer acting as a handle to the tree
319  *  @param[in/out] entity - pointer to the entity to be added. Input has the
320  *                          entity type. On output, instance number and the
321  *                          container id are populated.
322  *  @param[in] entity_instance_number - entity instance number, we can use the
323  *                                      entity instance number of the entity by
324  *                                      default if its value is equal 0xffff.
325  *  @param[in] parent - pointer to the node that should be the parent of input
326  *                      entity. If this is NULL, then the entity is the root
327  *  @param[in] association_type - relation with the parent : logical or physical
328  *
329  *  @return pldm_entity_node* - opaque pointer to added entity
330  */
331 pldm_entity_node *pldm_entity_association_tree_add(
332 	pldm_entity_association_tree *tree, pldm_entity *entity,
333 	uint16_t entity_instance_number, pldm_entity_node *parent,
334 	uint8_t association_type);
335 
336 /** @brief Add an entity into the entity association tree based on remote field
337  *  set or unset.
338  *
339  *  @param[in/out] tree - opaque pointer acting as a handle to the tree
340  *  @param[in/out] entity - pointer to the entity to be added. Input has the
341  *                          entity type. On output, instance number and the
342  *                          container id are populated.
343  *  @param[in] entity_instance_number - entity instance number, we can use the
344  *                                      entity instance number of the entity by
345  *                                      default if its value is equal 0xffff.
346  *  @param[in] parent - pointer to the node that should be the parent of input
347  *                      entity. If this is NULL, then the entity is the root
348  *  @param[in] association_type - relation with the parent : logical or physical
349  *  @param[in] is_remote - used to denote whether we are adding a BMC entity to
350  *                         the tree or a host entity
351  *  @param[in] is_update_contanier_id - Used to determine whether need to update
352  *                                      contanier id.
353  *                                      true: should be changed
354  *                                      false: should not be changed
355  *  @param[in] container_id - container id of the entity added.
356  *
357  *  @return pldm_entity_node* - opaque pointer to added entity
358  */
359 pldm_entity_node *pldm_entity_association_tree_add_entity(
360 	pldm_entity_association_tree *tree, pldm_entity *entity,
361 	uint16_t entity_instance_number, pldm_entity_node *parent,
362 	uint8_t association_type, bool is_remote, bool is_update_container_id,
363 	uint16_t container_id);
364 
365 /** @brief Visit and note each entity in the entity association tree
366  *
367  *  @pre `*entities == NULL` and `*size == 0` must hold at the time of invocation.
368  *
369  *  Callers must inspect the values of `*entities` and `*size` post-invocation to determine if the
370  *  invocation was a success or failure.
371  *
372  *  @param[in] tree - opaque pointer acting as a handle to the tree
373  *  @param[out] entities - pointer to list of pldm_entity's. To be free()'d by
374  *                         the caller
375  *  @param[out] size - number of pldm_entity's
376  */
377 void pldm_entity_association_tree_visit(pldm_entity_association_tree *tree,
378 					pldm_entity **entities, size_t *size);
379 
380 /** @brief Extract pldm entity by the pldm_entity_node
381  *
382  *  @pre node must point to a valid object
383  *
384  *  @param[in] node     - opaque pointer to added entity
385  *
386  *  @return pldm_entity - pldm entity
387  */
388 pldm_entity pldm_entity_extract(pldm_entity_node *node);
389 
390 /** @brief Extract remote container id from the pldm_entity_node
391  *
392  *  @pre entity must point to a valid object
393  *
394  *  @param[in] entity - pointer to existing entity
395  *
396  *  @return The remote container id
397  */
398 uint16_t
399 pldm_entity_node_get_remote_container_id(const pldm_entity_node *entity);
400 
401 /** @brief Destroy entity association tree
402  *
403  *  @param[in] tree - opaque pointer acting as a handle to the tree
404  */
405 void pldm_entity_association_tree_destroy(pldm_entity_association_tree *tree);
406 
407 /** @brief Check if input entity node is a parent
408  *
409  *  @pre node must point to a valid object
410  *
411  *  @param[in] node - opaque pointer acting as a handle to an entity node
412  *
413  *  @return bool true if node is a parent, false otherwise
414  */
415 bool pldm_entity_is_node_parent(pldm_entity_node *node);
416 
417 /** @brief Get parent of entity
418  *
419  *  @pre node must point to a valid object
420  *
421  *  @param[in] node - opaque pointer acting as a handle to an entity node
422  *
423  *  @return pldm_entity - pldm entity
424  */
425 pldm_entity pldm_entity_get_parent(pldm_entity_node *node);
426 
427 /** @brief Check the current pldm entity is exist parent
428  *
429  *  @pre node must point to a valid object
430  *
431  *  @param[in] node - opaque pointer acting as a handle to an entity node
432  *
433  *  @return bool true if exist parent, false otherwise
434  */
435 bool pldm_entity_is_exist_parent(pldm_entity_node *node);
436 
437 /** @brief Convert entity association tree to PDR, or return an error
438  *
439  *  No conversion takes place if one or both of tree or repo are NULL.
440  *
441  *  If an error is returned then the state and consistency of the PDR repository is undefined.
442  *
443  *  @param[in] tree - opaque pointer to entity association tree
444  *  @param[in] repo - PDR repo where entity association records should be added
445  *  @param[in] is_remote - if true, then the PDR is not from this terminus
446  *  @param[in] terminus_handle - terminus handle of the terminus
447  *
448  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
449  *  allocation fails, or -EOVERFLOW if a record handle could not be allocated
450  */
451 int pldm_entity_association_pdr_add(pldm_entity_association_tree *tree,
452 				    pldm_pdr *repo, bool is_remote,
453 				    uint16_t terminus_handle);
454 
455 /** @brief Add a contained entity as a remote PDR to an existing entity association PDR.
456  *
457  *  Remote PDRs are PDRs added as a child to an entity in the entity association tree and
458  *  not to the tree directly. This means remote PDRs have a parent PDR in the entity
459  *  association tree to which they are linked.
460  *
461  *  @param[in] repo - opaque pointer to pldm PDR repo
462  *  @param[in] entity - the contained entity to be added
463  *  @param[in] pdr_record_handle - record handle of the container entity to which the remote
464  *  PDR is to be added as a child
465  *
466  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
467  *  allocation fails, or -EOVERFLOW if a record handle could not be allocated
468  */
469 int pldm_entity_association_pdr_add_contained_entity_to_remote_pdr(
470 	pldm_pdr *repo, pldm_entity *entity, uint32_t pdr_record_handle);
471 
472 /** @brief Creates a new entity association PDR with contained entity & its parent.
473  *
474  *  @param[in] repo - opaque pointer to pldm PDR repo
475  *  @param[in] pdr_record_handle - record handle of the PDR after which the new container
476  *  entity has to be added
477  *  @param[in] parent - the container entity
478  *  @param[in] entity - the contained entity to be added
479  *  @param[in-out] entity_record_handle - record handle of a container entity added to the
480  *  entity association PDR
481  *
482  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
483  *  allocation fails, or -EOVERFLOW if a record handle could not be allocated
484  */
485 int pldm_entity_association_pdr_create_new(pldm_pdr *repo,
486 					   uint32_t pdr_record_handle,
487 					   pldm_entity *parent,
488 					   pldm_entity *entity,
489 					   uint32_t *entity_record_handle);
490 
491 /** @brief Add entity association pdr from node, or return an error
492  *
493  *  @param[in] node - opaque pointer acting as a handle to an entity node
494  *  @param[in] repo - PDR repo where entity association records should be added
495  *  @param[in] is_remote  - if true, then the PDR is not from this terminus
496  *  @param[in] terminus_handle - terminus handle of the terminus
497  *
498  *  @return 0 on success, -EINVAL if the provided arguments are invalid.
499  */
500 int pldm_entity_association_pdr_add_from_node(
501 	pldm_entity_node *node, pldm_pdr *repo, pldm_entity **entities,
502 	size_t num_entities, bool is_remote, uint16_t terminus_handle);
503 
504 /** @brief Add entity association pdr record based on record handle
505  *  earlier the records where added in a sequential way alone, with
506  *  this change the entity association PDR records gets the new record
507  *  handle based on the input value given.
508  *
509  *  @param[in] node - opaque pointer acting as a handle to an entity node
510  *  @param[in] repo - PDR repo where entity association records should be added
511  *  @param[in] is_remote  - if true, then the PDR is not from this terminus
512  *  @param[in] terminus_handle - terminus handle of the terminus
513  *  @param[in] record_handle - record handle of the PDR
514  *
515  *  @return 0 on success, -EINVAL if the provided arguments are invalid.
516  */
517 int pldm_entity_association_pdr_add_from_node_with_record_handle(
518 	pldm_entity_node *node, pldm_pdr *repo, pldm_entity **entities,
519 	size_t num_entities, bool is_remote, uint16_t terminus_handle,
520 	uint32_t record_handle);
521 
522 /** @brief Find entity reference in tree
523  *
524  *  @param[in] tree - opaque pointer to entity association tree
525  *  @param[in] entity - PLDM entity
526  *  @param[in] node - node to the entity
527  */
528 void pldm_find_entity_ref_in_tree(pldm_entity_association_tree *tree,
529 				  pldm_entity entity, pldm_entity_node **node);
530 
531 /** @brief Get number of children of entity
532  *
533  *  @param[in] node - opaque pointer acting as a handle to an entity node
534  *  @param[in] association_type - relation type filter : logical or physical
535  *
536  *  @return uint8_t number of children. The returned value is zero if node is NULL or
537  *  	    association_type is not one of PLDM_ENTITY_ASSOCIAION_PHYSICAL or
538  *  	    PLDM_ENTITY_ASSOCIAION_LOGICAL.
539  */
540 uint8_t pldm_entity_get_num_children(pldm_entity_node *node,
541 				     uint8_t association_type);
542 
543 /** @brief Verify that the current node is a child of the current parent
544  *
545  *  @pre parent must point to a valid object
546  *  @pre node must point to a valid object
547  *
548  *  @param[in] parent    - opaque pointer acting as a handle to an entity parent
549  *  @param[in] node      - pointer to the node of the pldm entity
550  *
551  *  @return True if the node is a child of parent, false otherwise, including if one or both of
552  *  parent or node are NULL.
553  */
554 bool pldm_is_current_parent_child(pldm_entity_node *parent, pldm_entity *node);
555 
556 /** @brief Find an entity in the entity association tree
557  *
558  *  @param[in] tree - pointer to entity association tree
559  *  @param[in/out] entity - entity type and instance id set on input, container
560  *                 id set on output
561  *  @return pldm_entity_node* pointer to entity if found, NULL otherwise
562  *
563  *  There are no entity nodes to search if tree is NULL, nor are there entity nodes to find if the
564  *  search criteria are unspecified when entity is NULL.
565  */
566 pldm_entity_node *
567 pldm_entity_association_tree_find(pldm_entity_association_tree *tree,
568 				  pldm_entity *entity);
569 
570 /** @brief Find an entity in the entity association tree with locality specified,
571  *         ie - remote entity or local entity
572  *
573  *  @param[in] tree - pointer to entity association tree
574  *  @param[in/out] entity - entity type and instance id set on input, container
575  *                          id set on output
576  *  @param[in] is_remote - variable to denote whether we are finding a remote
577  *                         entity or a local entity
578  *
579  *  @return pldm_entity_node* pointer to entity if found, NULL otherwise
580  */
581 pldm_entity_node *pldm_entity_association_tree_find_with_locality(
582 	pldm_entity_association_tree *tree, pldm_entity *entity,
583 	bool is_remote);
584 
585 /** @brief Create a copy of an existing entity association tree
586  *
587  *  @pre org_tree must point to a valid object
588  *  @pre new_tree must point to a valid object
589  *
590  *  @param[in] org_tree - pointer to source tree
591  *  @param[in/out] new_tree - pointer to destination tree
592  */
593 void pldm_entity_association_tree_copy_root(
594 	pldm_entity_association_tree *org_tree,
595 	pldm_entity_association_tree *new_tree);
596 
597 /** @brief Create a copy of an existing entity association tree
598  *
599  *  @param[in] org_tree - pointer to source tree
600  *  @param[in/out] new_tree - pointer to destination tree
601  *
602  *  @return 0 if the entity association tree was copied, -EINVAL if the argument
603  *          values are invalid, or -ENOMEM if memory required for the copy
604  *          cannot be allocated.
605  */
606 int pldm_entity_association_tree_copy_root_check(
607 	pldm_entity_association_tree *org_tree,
608 	pldm_entity_association_tree *new_tree);
609 
610 /** @brief Destroy all the nodes of the entity association tree
611  *
612  *  @param[in] tree - pointer to entity association tree
613  *
614  *  There is no tree to destroy if tree is NULL.
615  */
616 void pldm_entity_association_tree_destroy_root(
617 	pldm_entity_association_tree *tree);
618 
619 /** @brief Check whether the entity association tree is empty
620  *
621  *  @pre tree must point to a valid object
622  *
623  *  @param[in] tree - pointer to entity association tree
624  *  @return bool, true if tree is empty
625  */
626 bool pldm_is_empty_entity_assoc_tree(pldm_entity_association_tree *tree);
627 
628 /** @brief Extract entities from entity association PDR
629  *
630  *  @pre `*entities == NULL` and `*num_entities == 0` must hold at the time of invocation.
631  *
632  *  @param[in] pdr - entity association PDR
633  *  @param[in] pdr_len - size of entity association PDR in bytes
634  *  @param[out] num_entities - number of entities found, including the container
635  *  @param[out] entities - extracted entities, container is *entities[0]. Caller
636  *              must free *entities
637  */
638 void pldm_entity_association_pdr_extract(const uint8_t *pdr, uint16_t pdr_len,
639 					 size_t *num_entities,
640 					 pldm_entity **entities);
641 
642 /** @brief Remove a contained entity from an entity association PDR
643  *
644  *  @param[in] repo - opaque pointer acting as a PDR repo handle
645  *  @param[in] entity - the pldm entity to be deleted. Data inside the entity struct must be
646  *  			host-endianess format
647  *  @param[in] is_remote - indicates which PDR to remove, local or remote
648  *  @param[in-out] pdr_record_handle - record handle of the container entity which has to be removed.
649  *                                     PLDM will use this record handle to updated the PDR repo so
650  *                                     that entry corresponding to this entity is removed from PDR
651  *                                     table.
652  *
653  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
654  *  allocation fails, or -EOVERFLOW if given data is too large for memory allocated
655  */
656 int pldm_entity_association_pdr_remove_contained_entity(
657 	pldm_pdr *repo, pldm_entity *entity, bool is_remote,
658 	uint32_t *pdr_record_handle);
659 
660 /** @brief removes a PLDM PDR record if it matches given record set identifier
661  *  @param[in] repo - opaque pointer acting as a PDR repo handle
662  *  @param[in] fru_rsi - FRU record set identifier
663  *  @param[in] is_remote - indicates which PDR to remove, local or remote
664  *  @param[out] record_handle - record handle of the fru record to be removed
665  *
666  *  @return 0 on success, -EINVAL if the arguments are invalid or -EOVERFLOW if value is too
667  *  large for defined type
668  */
669 int pldm_pdr_remove_fru_record_set_by_rsi(pldm_pdr *repo, uint16_t fru_rsi,
670 					  bool is_remote,
671 					  uint32_t *record_handle);
672 
673 #ifdef __cplusplus
674 }
675 #endif
676 
677 #endif /* PDR_H */
678