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