xref: /openbmc/libpldm/include/libpldm/pdr.h (revision 5192e2e26f26ffbbf4256429ea5ae42237e011cc)
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 /** @brief Delete record using its record handle
238  *
239  *  @param[in] repo - opaque pointer acting as a PDR repo handle
240  *  @param[in] record_handle - record handle of input PDR record
241  *  @param[in] is_remote - if true, then the PDR is not from this terminus
242  *
243  *  @return 0 if deleted successful else returns -EINVAL when repo is NULL
244  *  or -ENOENT if the record handle is not found in the repo.
245  */
246 int pldm_pdr_delete_by_record_handle(pldm_pdr *repo, uint32_t record_handle,
247 				     bool is_remote);
248 
249 /* ======================= */
250 /* FRU Record Set PDR APIs */
251 /* ======================= */
252 
253 /** @brief Add a FRU record set PDR record to a PDR repository, or return an error
254  *
255  *  @param[in/out] repo - opaque pointer acting as a PDR repo handle
256  *  @param[in] terminus_handle - PLDM terminus handle of terminus owning the PDR
257  *  record
258  *  @param[in] fru_rsi - FRU record set identifier
259  *  @param[in] entity_type - entity type of FRU
260  *  @param[in] entity_instance_num - entity instance number of FRU
261  *  @param[in] container_id - container id of FRU
262  *  @param[in,out] bmc_record_handle - A pointer to the handle used to construct the next record. If
263  *  		   the value is zero on input then a new handle is automatically allocated.
264  *  		   Otherwise, the provided handle is used. If a new handle is automatically
265  *  		   allocated then the object pointed to by bmc_record_handle will contain its value
266  *  		   as output.
267  *  @return 0 on success, -EINVAL if the arguments are invalid, or -ENOMEM if an internal allocation
268  *  	    fails.
269  */
270 int pldm_pdr_add_fru_record_set(pldm_pdr *repo, uint16_t terminus_handle,
271 				uint16_t fru_rsi, uint16_t entity_type,
272 				uint16_t entity_instance_num,
273 				uint16_t container_id,
274 				uint32_t *bmc_record_handle);
275 
276 /** @brief Find a FRU record set PDR by FRU record set identifier
277  *
278  *  @param[in] repo - opaque pointer acting as a PDR repo handle
279  *  @param[in] fru_rsi - FRU record set identifier
280  *  @param[in] terminus_handle - *terminus_handle will be FRU terminus handle of
281  *  found PDR, or 0 if not found
282  *  @param[in] entity_type - *entity_type will be FRU entity type of found PDR,
283  *  or 0 if not found
284  *  @param[in] entity_instance_num - *entity_instance_num will be FRU entity
285  *  instance number of found PDR, or 0 if not found
286  *  @param[in] container_id - *cintainer_id will be FRU container id of found
287  *  PDR, or 0 if not found
288  *
289  *  @return An opaque pointer to the PDR record on success, or NULL on failure
290  */
291 const pldm_pdr_record *pldm_pdr_fru_record_set_find_by_rsi(
292 	const pldm_pdr *repo, uint16_t fru_rsi, uint16_t *terminus_handle,
293 	uint16_t *entity_type, uint16_t *entity_instance_num,
294 	uint16_t *container_id);
295 
296 /* =========================== */
297 /* Entity Association PDR APIs */
298 /* =========================== */
299 
300 typedef struct pldm_entity {
301 	uint16_t entity_type;
302 	uint16_t entity_instance_num;
303 	uint16_t entity_container_id;
304 } __attribute__((packed)) pldm_entity;
305 
306 enum entity_association_containment_type {
307 	PLDM_ENTITY_ASSOCIAION_PHYSICAL = 0x0,
308 	PLDM_ENTITY_ASSOCIAION_LOGICAL = 0x1,
309 };
310 
311 /** @struct pldm_entity_association_tree
312  *  opaque structure that represents the entity association hierarchy
313  */
314 typedef struct pldm_entity_association_tree pldm_entity_association_tree;
315 
316 /** @struct pldm_entity_node
317  *  opaque structure that represents a node in the entity association hierarchy
318  */
319 typedef struct pldm_entity_node pldm_entity_node;
320 
321 /** @brief Make a new entity association tree
322  *
323  *  @return opaque pointer that acts as a handle to the tree; NULL if no
324  *  tree could be created
325  */
326 pldm_entity_association_tree *pldm_entity_association_tree_init(void);
327 
328 /** @brief Add a local entity into the entity association tree
329  *
330  *  @param[in/out] tree - opaque pointer acting as a handle to the tree
331  *  @param[in/out] entity - pointer to the entity to be added. Input has the
332  *                          entity type. On output, instance number and the
333  *                          container id are populated.
334  *  @param[in] entity_instance_number - entity instance number, we can use the
335  *                                      entity instance number of the entity by
336  *                                      default if its value is equal 0xffff.
337  *  @param[in] parent - pointer to the node that should be the parent of input
338  *                      entity. If this is NULL, then the entity is the root
339  *  @param[in] association_type - relation with the parent : logical or physical
340  *
341  *  @return pldm_entity_node* - opaque pointer to added entity
342  */
343 pldm_entity_node *pldm_entity_association_tree_add(
344 	pldm_entity_association_tree *tree, pldm_entity *entity,
345 	uint16_t entity_instance_number, pldm_entity_node *parent,
346 	uint8_t association_type);
347 
348 /** @brief Add an entity into the entity association tree based on remote field
349  *  set or unset.
350  *
351  *  @param[in/out] tree - opaque pointer acting as a handle to the tree
352  *  @param[in/out] entity - pointer to the entity to be added. Input has the
353  *                          entity type. On output, instance number and the
354  *                          container id are populated.
355  *  @param[in] entity_instance_number - entity instance number, we can use the
356  *                                      entity instance number of the entity by
357  *                                      default if its value is equal 0xffff.
358  *  @param[in] parent - pointer to the node that should be the parent of input
359  *                      entity. If this is NULL, then the entity is the root
360  *  @param[in] association_type - relation with the parent : logical or physical
361  *  @param[in] is_remote - used to denote whether we are adding a BMC entity to
362  *                         the tree or a host entity
363  *  @param[in] is_update_contanier_id - Used to determine whether need to update
364  *                                      contanier id.
365  *                                      true: should be changed
366  *                                      false: should not be changed
367  *  @param[in] container_id - container id of the entity added.
368  *
369  *  @return pldm_entity_node* - opaque pointer to added entity
370  */
371 pldm_entity_node *pldm_entity_association_tree_add_entity(
372 	pldm_entity_association_tree *tree, pldm_entity *entity,
373 	uint16_t entity_instance_number, pldm_entity_node *parent,
374 	uint8_t association_type, bool is_remote, bool is_update_container_id,
375 	uint16_t container_id);
376 
377 /** @brief Visit and note each entity in the entity association tree
378  *
379  *  @pre `*entities == NULL` and `*size == 0` must hold at the time of invocation.
380  *
381  *  Callers must inspect the values of `*entities` and `*size` post-invocation to determine if the
382  *  invocation was a success or failure.
383  *
384  *  @param[in] tree - opaque pointer acting as a handle to the tree
385  *  @param[out] entities - pointer to list of pldm_entity's. To be free()'d by
386  *                         the caller
387  *  @param[out] size - number of pldm_entity's
388  */
389 void pldm_entity_association_tree_visit(pldm_entity_association_tree *tree,
390 					pldm_entity **entities, size_t *size);
391 
392 /** @brief Extract pldm entity by the pldm_entity_node
393  *
394  *  @pre node must point to a valid object
395  *
396  *  @param[in] node     - opaque pointer to added entity
397  *
398  *  @return pldm_entity - pldm entity
399  */
400 pldm_entity pldm_entity_extract(pldm_entity_node *node);
401 
402 /** @brief Extract remote container id from the pldm_entity_node
403  *
404  *  @pre entity must point to a valid object
405  *
406  *  @param[in] entity - pointer to existing entity
407  *
408  *  @return The remote container id
409  */
410 uint16_t
411 pldm_entity_node_get_remote_container_id(const pldm_entity_node *entity);
412 
413 /** @brief Destroy entity association tree
414  *
415  *  @param[in] tree - opaque pointer acting as a handle to the tree
416  */
417 void pldm_entity_association_tree_destroy(pldm_entity_association_tree *tree);
418 
419 /** @brief Check if input entity node is a parent
420  *
421  *  @pre node must point to a valid object
422  *
423  *  @param[in] node - opaque pointer acting as a handle to an entity node
424  *
425  *  @return bool true if node is a parent, false otherwise
426  */
427 bool pldm_entity_is_node_parent(pldm_entity_node *node);
428 
429 /** @brief Get parent of entity
430  *
431  *  @pre node must point to a valid object
432  *
433  *  @param[in] node - opaque pointer acting as a handle to an entity node
434  *
435  *  @return pldm_entity - pldm entity
436  */
437 pldm_entity pldm_entity_get_parent(pldm_entity_node *node);
438 
439 /** @brief Check the current pldm entity is exist parent
440  *
441  *  @pre node must point to a valid object
442  *
443  *  @param[in] node - opaque pointer acting as a handle to an entity node
444  *
445  *  @return bool true if exist parent, false otherwise
446  */
447 bool pldm_entity_is_exist_parent(pldm_entity_node *node);
448 
449 /** @brief Convert entity association tree to PDR, or return an error
450  *
451  *  No conversion takes place if one or both of tree or repo are NULL.
452  *
453  *  If an error is returned then the state and consistency of the PDR repository is undefined.
454  *
455  *  @param[in] tree - opaque pointer to entity association tree
456  *  @param[in] repo - PDR repo where entity association records should be added
457  *  @param[in] is_remote - if true, then the PDR is not from this terminus
458  *  @param[in] terminus_handle - terminus handle of the terminus
459  *
460  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
461  *  allocation fails, or -EOVERFLOW if a record handle could not be allocated
462  */
463 int pldm_entity_association_pdr_add(pldm_entity_association_tree *tree,
464 				    pldm_pdr *repo, bool is_remote,
465 				    uint16_t terminus_handle);
466 
467 /** @brief Add a contained entity as a remote PDR to an existing entity association PDR.
468  *
469  *  Remote PDRs are PDRs added as a child to an entity in the entity association tree and
470  *  not to the tree directly. This means remote PDRs have a parent PDR in the entity
471  *  association tree to which they are linked.
472  *
473  *  @param[in] repo - opaque pointer to pldm PDR repo
474  *  @param[in] entity - the contained entity to be added
475  *  @param[in] pdr_record_handle - record handle of the container entity to which the remote
476  *  PDR is to be added as a child
477  *
478  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
479  *  allocation fails, or -EOVERFLOW if a record handle could not be allocated
480  */
481 int pldm_entity_association_pdr_add_contained_entity_to_remote_pdr(
482 	pldm_pdr *repo, pldm_entity *entity, uint32_t pdr_record_handle);
483 
484 /** @brief Creates a new entity association PDR with contained entity & its parent.
485  *
486  *  @param[in] repo - opaque pointer to pldm PDR repo
487  *  @param[in] pdr_record_handle - record handle of the PDR after which the new container
488  *  entity has to be added
489  *  @param[in] parent - the container entity
490  *  @param[in] entity - the contained entity to be added
491  *  @param[in-out] entity_record_handle - record handle of a container entity added to the
492  *  entity association PDR
493  *
494  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
495  *  allocation fails, or -EOVERFLOW if a record handle could not be allocated
496  */
497 int pldm_entity_association_pdr_create_new(pldm_pdr *repo,
498 					   uint32_t pdr_record_handle,
499 					   pldm_entity *parent,
500 					   pldm_entity *entity,
501 					   uint32_t *entity_record_handle);
502 
503 /** @brief Add entity association pdr from node, or return an error
504  *
505  *  @param[in] node - opaque pointer acting as a handle to an entity node
506  *  @param[in] repo - PDR repo where entity association records should be added
507  *  @param[in] is_remote  - if true, then the PDR is not from this terminus
508  *  @param[in] terminus_handle - terminus handle of the terminus
509  *
510  *  @return 0 on success, -EINVAL if the provided arguments are invalid.
511  */
512 int pldm_entity_association_pdr_add_from_node(
513 	pldm_entity_node *node, pldm_pdr *repo, pldm_entity **entities,
514 	size_t num_entities, bool is_remote, uint16_t terminus_handle);
515 
516 /** @brief Add entity association pdr record based on record handle
517  *  earlier the records where added in a sequential way alone, with
518  *  this change the entity association PDR records gets the new record
519  *  handle based on the input value given.
520  *
521  *  @param[in] node - opaque pointer acting as a handle to an entity node
522  *  @param[in] repo - PDR repo where entity association records should be added
523  *  @param[in] is_remote  - if true, then the PDR is not from this terminus
524  *  @param[in] terminus_handle - terminus handle of the terminus
525  *  @param[in] record_handle - record handle of the PDR
526  *
527  *  @return 0 on success, -EINVAL if the provided arguments are invalid.
528  */
529 int pldm_entity_association_pdr_add_from_node_with_record_handle(
530 	pldm_entity_node *node, pldm_pdr *repo, pldm_entity **entities,
531 	size_t num_entities, bool is_remote, uint16_t terminus_handle,
532 	uint32_t record_handle);
533 
534 /** @brief Find entity reference in tree
535  *
536  *  @param[in] tree - opaque pointer to entity association tree
537  *  @param[in] entity - PLDM entity
538  *  @param[in] node - node to the entity
539  */
540 void pldm_find_entity_ref_in_tree(pldm_entity_association_tree *tree,
541 				  pldm_entity entity, pldm_entity_node **node);
542 
543 /** @brief Get number of children of entity
544  *
545  *  @param[in] node - opaque pointer acting as a handle to an entity node
546  *  @param[in] association_type - relation type filter : logical or physical
547  *
548  *  @return uint8_t number of children. The returned value is zero if node is NULL or
549  *  	    association_type is not one of PLDM_ENTITY_ASSOCIAION_PHYSICAL or
550  *  	    PLDM_ENTITY_ASSOCIAION_LOGICAL.
551  */
552 uint8_t pldm_entity_get_num_children(pldm_entity_node *node,
553 				     uint8_t association_type);
554 
555 /** @brief Verify that the current node is a child of the current parent
556  *
557  *  @pre parent must point to a valid object
558  *  @pre node must point to a valid object
559  *
560  *  @param[in] parent    - opaque pointer acting as a handle to an entity parent
561  *  @param[in] node      - pointer to the node of the pldm entity
562  *
563  *  @return True if the node is a child of parent, false otherwise, including if one or both of
564  *  parent or node are NULL.
565  */
566 bool pldm_is_current_parent_child(pldm_entity_node *parent, pldm_entity *node);
567 
568 /** @brief Find an entity in the entity association tree
569  *
570  *  @param[in] tree - pointer to entity association tree
571  *  @param[in/out] entity - entity type and instance id set on input, container
572  *                 id set on output
573  *  @return pldm_entity_node* pointer to entity if found, NULL otherwise
574  *
575  *  There are no entity nodes to search if tree is NULL, nor are there entity nodes to find if the
576  *  search criteria are unspecified when entity is NULL.
577  */
578 pldm_entity_node *
579 pldm_entity_association_tree_find(pldm_entity_association_tree *tree,
580 				  pldm_entity *entity);
581 
582 /** @brief Find an entity in the entity association tree with locality specified,
583  *         ie - remote entity or local entity
584  *
585  *  @param[in] tree - pointer to entity association tree
586  *  @param[in/out] entity - entity type and instance id set on input, container
587  *                          id set on output
588  *  @param[in] is_remote - variable to denote whether we are finding a remote
589  *                         entity or a local entity
590  *
591  *  @return pldm_entity_node* pointer to entity if found, NULL otherwise
592  */
593 pldm_entity_node *pldm_entity_association_tree_find_with_locality(
594 	pldm_entity_association_tree *tree, pldm_entity *entity,
595 	bool is_remote);
596 
597 /** @brief Create a copy of an existing entity association tree
598  *
599  *  @pre org_tree must point to a valid object
600  *  @pre new_tree must point to a valid object
601  *
602  *  @param[in] org_tree - pointer to source tree
603  *  @param[in/out] new_tree - pointer to destination tree
604  */
605 void pldm_entity_association_tree_copy_root(
606 	pldm_entity_association_tree *org_tree,
607 	pldm_entity_association_tree *new_tree);
608 
609 /** @brief Create a copy of an existing entity association tree
610  *
611  *  @param[in] org_tree - pointer to source tree
612  *  @param[in/out] new_tree - pointer to destination tree
613  *
614  *  @return 0 if the entity association tree was copied, -EINVAL if the argument
615  *          values are invalid, or -ENOMEM if memory required for the copy
616  *          cannot be allocated.
617  */
618 int pldm_entity_association_tree_copy_root_check(
619 	pldm_entity_association_tree *org_tree,
620 	pldm_entity_association_tree *new_tree);
621 
622 /** @brief Destroy all the nodes of the entity association tree
623  *
624  *  @param[in] tree - pointer to entity association tree
625  *
626  *  There is no tree to destroy if tree is NULL.
627  */
628 void pldm_entity_association_tree_destroy_root(
629 	pldm_entity_association_tree *tree);
630 
631 /** @brief Check whether the entity association tree is empty
632  *
633  *  @pre tree must point to a valid object
634  *
635  *  @param[in] tree - pointer to entity association tree
636  *  @return bool, true if tree is empty
637  */
638 bool pldm_is_empty_entity_assoc_tree(pldm_entity_association_tree *tree);
639 
640 /** @brief Extract entities from entity association PDR
641  *
642  *  @pre `*entities == NULL` and `*num_entities == 0` must hold at the time of invocation.
643  *
644  *  @param[in] pdr - entity association PDR
645  *  @param[in] pdr_len - size of entity association PDR in bytes
646  *  @param[out] num_entities - number of entities found, including the container
647  *  @param[out] entities - extracted entities, container is *entities[0]. Caller
648  *              must free *entities
649  */
650 void pldm_entity_association_pdr_extract(const uint8_t *pdr, uint16_t pdr_len,
651 					 size_t *num_entities,
652 					 pldm_entity **entities);
653 
654 /** @brief Remove a contained entity from an entity association PDR
655  *
656  *  @param[in] repo - opaque pointer acting as a PDR repo handle
657  *  @param[in] entity - the pldm entity to be deleted. Data inside the entity struct must be
658  *  			host-endianess format
659  *  @param[in] is_remote - indicates which PDR to remove, local or remote
660  *  @param[in-out] pdr_record_handle - record handle of the container entity which has to be removed.
661  *                                     PLDM will use this record handle to updated the PDR repo so
662  *                                     that entry corresponding to this entity is removed from PDR
663  *                                     table.
664  *
665  *  @return 0 on success, -EINVAL if the arguments are invalid, -ENOMEM if an internal memory
666  *  allocation fails, or -EOVERFLOW if given data is too large for memory allocated
667  */
668 int pldm_entity_association_pdr_remove_contained_entity(
669 	pldm_pdr *repo, pldm_entity *entity, bool is_remote,
670 	uint32_t *pdr_record_handle);
671 
672 /** @brief removes a PLDM PDR record if it matches given record set identifier
673  *  @param[in] repo - opaque pointer acting as a PDR repo handle
674  *  @param[in] fru_rsi - FRU record set identifier
675  *  @param[in] is_remote - indicates which PDR to remove, local or remote
676  *  @param[out] record_handle - record handle of the fru record to be removed
677  *
678  *  @return 0 on success, -EINVAL if the arguments are invalid or -EOVERFLOW if value is too
679  *  large for defined type
680  */
681 int pldm_pdr_remove_fru_record_set_by_rsi(pldm_pdr *repo, uint16_t fru_rsi,
682 					  bool is_remote,
683 					  uint32_t *record_handle);
684 
685 #ifdef __cplusplus
686 }
687 #endif
688 
689 #endif /* PDR_H */
690