blob: 65a25916b83f0414a028c4ba82ba3f43eb923ed0 [file] [log] [blame]
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -06001#include "pdr.h"
2#include "platform.h"
3#include <assert.h>
4#include <stdlib.h>
5#include <string.h>
6
7typedef struct pldm_pdr_record {
8 uint32_t record_handle;
9 uint32_t size;
10 uint8_t *data;
11 struct pldm_pdr_record *next;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050012 bool is_remote;
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060013} pldm_pdr_record;
14
15typedef struct pldm_pdr {
16 uint32_t record_count;
17 uint32_t size;
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060018 pldm_pdr_record *first;
19 pldm_pdr_record *last;
20} pldm_pdr;
21
22static inline uint32_t get_next_record_handle(const pldm_pdr *repo,
23 const pldm_pdr_record *record)
24{
25 assert(repo != NULL);
26 assert(record != NULL);
27
28 if (record == repo->last) {
29 return 0;
30 }
31 return record->next->record_handle;
32}
33
34static void add_record(pldm_pdr *repo, pldm_pdr_record *record)
35{
36 assert(repo != NULL);
37 assert(record != NULL);
38
39 if (repo->first == NULL) {
40 assert(repo->last == NULL);
41 repo->first = record;
42 repo->last = record;
43 } else {
44 repo->last->next = record;
45 repo->last = record;
46 }
47 repo->size += record->size;
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060048 ++repo->record_count;
49}
50
51static inline uint32_t get_new_record_handle(const pldm_pdr *repo)
52{
53 assert(repo != NULL);
Deepak Kodihallib9848732020-04-21 23:34:01 -050054 uint32_t last_used_hdl =
55 repo->last != NULL ? repo->last->record_handle : 0;
56 assert(last_used_hdl != UINT32_MAX);
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060057
Deepak Kodihallib9848732020-04-21 23:34:01 -050058 return last_used_hdl + 1;
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060059}
60
61static pldm_pdr_record *make_new_record(const pldm_pdr *repo,
62 const uint8_t *data, uint32_t size,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050063 uint32_t record_handle, bool is_remote)
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060064{
65 assert(repo != NULL);
66 assert(size != 0);
67
68 pldm_pdr_record *record = malloc(sizeof(pldm_pdr_record));
69 assert(record != NULL);
70 record->record_handle =
71 record_handle == 0 ? get_new_record_handle(repo) : record_handle;
72 record->size = size;
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050073 record->is_remote = is_remote;
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060074 if (data != NULL) {
75 record->data = malloc(size);
76 assert(record->data != NULL);
77 memcpy(record->data, data, size);
78 /* If record handle is 0, that is an indication for this API to
79 * compute a new handle. For that reason, the computed handle
80 * needs to be populated in the PDR header. For a case where the
81 * caller supplied the record handle, it would exist in the
82 * header already.
83 */
84 if (!record_handle) {
85 struct pldm_pdr_hdr *hdr =
86 (struct pldm_pdr_hdr *)(record->data);
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -050087 hdr->record_handle = htole32(record->record_handle);
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060088 }
89 }
90 record->next = NULL;
91
92 return record;
93}
94
95uint32_t pldm_pdr_add(pldm_pdr *repo, const uint8_t *data, uint32_t size,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -050096 uint32_t record_handle, bool is_remote)
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -060097{
98 assert(size != 0);
99 assert(data != NULL);
100
101 pldm_pdr_record *record =
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500102 make_new_record(repo, data, size, record_handle, is_remote);
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -0600103 add_record(repo, record);
104
105 return record->record_handle;
106}
107
108pldm_pdr *pldm_pdr_init()
109{
110 pldm_pdr *repo = malloc(sizeof(pldm_pdr));
111 assert(repo != NULL);
112 repo->record_count = 0;
113 repo->size = 0;
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -0600114 repo->first = NULL;
115 repo->last = NULL;
116
117 return repo;
118}
119
120void pldm_pdr_destroy(pldm_pdr *repo)
121{
122 assert(repo != NULL);
123
124 pldm_pdr_record *record = repo->first;
125 while (record != NULL) {
126 pldm_pdr_record *next = record->next;
127 if (record->data) {
128 free(record->data);
129 record->data = NULL;
130 }
131 free(record);
132 record = next;
133 }
134 free(repo);
135}
136
137const pldm_pdr_record *pldm_pdr_find_record(const pldm_pdr *repo,
138 uint32_t record_handle,
139 uint8_t **data, uint32_t *size,
140 uint32_t *next_record_handle)
141{
142 assert(repo != NULL);
143 assert(data != NULL);
144 assert(size != NULL);
145 assert(next_record_handle != NULL);
146
147 if (!record_handle && (repo->first != NULL)) {
148 record_handle = repo->first->record_handle;
149 }
150 pldm_pdr_record *record = repo->first;
151 while (record != NULL) {
152 if (record->record_handle == record_handle) {
153 *size = record->size;
154 *data = record->data;
155 *next_record_handle =
156 get_next_record_handle(repo, record);
157 return record;
158 }
159 record = record->next;
160 }
161
162 *size = 0;
163 *next_record_handle = 0;
164 return NULL;
165}
166
167const pldm_pdr_record *
168pldm_pdr_get_next_record(const pldm_pdr *repo,
169 const pldm_pdr_record *curr_record, uint8_t **data,
170 uint32_t *size, uint32_t *next_record_handle)
171{
172 assert(repo != NULL);
173 assert(curr_record != NULL);
174 assert(data != NULL);
175 assert(size != NULL);
176 assert(next_record_handle != NULL);
177
178 if (curr_record == repo->last) {
179 *data = NULL;
180 *size = 0;
181 *next_record_handle = get_next_record_handle(repo, curr_record);
182 return NULL;
183 }
184
185 *next_record_handle = get_next_record_handle(repo, curr_record->next);
186 *data = curr_record->next->data;
187 *size = curr_record->next->size;
188 return curr_record->next;
189}
190
191const pldm_pdr_record *
192pldm_pdr_find_record_by_type(const pldm_pdr *repo, uint8_t pdr_type,
193 const pldm_pdr_record *curr_record, uint8_t **data,
194 uint32_t *size)
195{
196 assert(repo != NULL);
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -0600197
198 pldm_pdr_record *record = repo->first;
199 if (curr_record != NULL) {
200 record = curr_record->next;
201 }
202 while (record != NULL) {
203 struct pldm_pdr_hdr *hdr = (struct pldm_pdr_hdr *)record->data;
204 if (hdr->type == pdr_type) {
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500205 if (data && size) {
206 *size = record->size;
207 *data = record->data;
208 }
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -0600209 return record;
210 }
211 record = record->next;
212 }
213
Pavithra Barithayae8beb892020-04-14 23:24:25 -0500214 if (size) {
215 *size = 0;
216 }
Deepak Kodihalli3b02ed82020-02-06 01:18:25 -0600217 return NULL;
218}
219
220uint32_t pldm_pdr_get_record_count(const pldm_pdr *repo)
221{
222 assert(repo != NULL);
223
224 return repo->record_count;
225}
226
227uint32_t pldm_pdr_get_repo_size(const pldm_pdr *repo)
228{
229 assert(repo != NULL);
230
231 return repo->size;
232}
233
234uint32_t pldm_pdr_get_record_handle(const pldm_pdr *repo,
235 const pldm_pdr_record *record)
236{
237 assert(repo != NULL);
238 assert(record != NULL);
239
240 return record->record_handle;
241}
Deepak Kodihallidb914672020-02-07 02:47:45 -0600242
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500243inline bool pldm_pdr_record_is_remote(const pldm_pdr_record *record)
244{
245 assert(record != NULL);
246
247 return record->is_remote;
248}
249
Deepak Kodihallidb914672020-02-07 02:47:45 -0600250uint32_t pldm_pdr_add_fru_record_set(pldm_pdr *repo, uint16_t terminus_handle,
251 uint16_t fru_rsi, uint16_t entity_type,
252 uint16_t entity_instance_num,
253 uint16_t container_id)
254{
255 uint32_t size = sizeof(struct pldm_pdr_hdr) +
256 sizeof(struct pldm_pdr_fru_record_set);
257 uint8_t data[size];
258
259 struct pldm_pdr_hdr *hdr = (struct pldm_pdr_hdr *)&data;
260 hdr->version = 1;
261 hdr->record_handle = 0;
262 hdr->type = PLDM_PDR_FRU_RECORD_SET;
263 hdr->record_change_num = 0;
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500264 hdr->length = htole16(sizeof(struct pldm_pdr_fru_record_set));
Deepak Kodihallidb914672020-02-07 02:47:45 -0600265 struct pldm_pdr_fru_record_set *fru =
266 (struct pldm_pdr_fru_record_set *)((uint8_t *)hdr +
267 sizeof(struct pldm_pdr_hdr));
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500268 fru->terminus_handle = htole16(terminus_handle);
269 fru->fru_rsi = htole16(fru_rsi);
270 fru->entity_type = htole16(entity_type);
271 fru->entity_instance_num = htole16(entity_instance_num);
272 fru->container_id = htole16(container_id);
Deepak Kodihallidb914672020-02-07 02:47:45 -0600273
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500274 return pldm_pdr_add(repo, data, size, 0, false);
Deepak Kodihallidb914672020-02-07 02:47:45 -0600275}
276
277const pldm_pdr_record *pldm_pdr_fru_record_set_find_by_rsi(
278 const pldm_pdr *repo, uint16_t fru_rsi, uint16_t *terminus_handle,
279 uint16_t *entity_type, uint16_t *entity_instance_num,
280 uint16_t *container_id)
281{
282 assert(terminus_handle != NULL);
283 assert(entity_type != NULL);
284 assert(entity_instance_num != NULL);
285 assert(container_id != NULL);
286
287 uint8_t *data = NULL;
288 uint32_t size = 0;
289 const pldm_pdr_record *curr_record = pldm_pdr_find_record_by_type(
290 repo, PLDM_PDR_FRU_RECORD_SET, NULL, &data, &size);
291 while (curr_record != NULL) {
292 struct pldm_pdr_fru_record_set *fru =
293 (struct pldm_pdr_fru_record_set
294 *)(data + sizeof(struct pldm_pdr_hdr));
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500295 if (fru->fru_rsi == htole16(fru_rsi)) {
296 *terminus_handle = le16toh(fru->terminus_handle);
297 *entity_type = le16toh(fru->entity_type);
298 *entity_instance_num =
299 le16toh(fru->entity_instance_num);
300 *container_id = le16toh(fru->container_id);
Deepak Kodihallidb914672020-02-07 02:47:45 -0600301 return curr_record;
302 }
303 data = NULL;
304 curr_record = pldm_pdr_find_record_by_type(
305 repo, PLDM_PDR_FRU_RECORD_SET, curr_record, &data, &size);
306 }
307
308 *terminus_handle = 0;
309 *entity_type = 0;
310 *entity_instance_num = 0;
311 *container_id = 0;
312
313 return NULL;
314}
Deepak Kodihalli05787052020-03-10 01:54:08 -0500315
316typedef struct pldm_entity_association_tree {
317 pldm_entity_node *root;
318 uint16_t last_used_container_id;
319} pldm_entity_association_tree;
320
321typedef struct pldm_entity_node {
322 pldm_entity entity;
George Liufe77eea2021-04-28 15:08:07 +0800323 pldm_entity_node *parent;
Deepak Kodihalli05787052020-03-10 01:54:08 -0500324 pldm_entity_node *first_child;
325 pldm_entity_node *next_sibling;
326 uint8_t association_type;
327} pldm_entity_node;
328
329static inline uint16_t next_container_id(pldm_entity_association_tree *tree)
330{
331 assert(tree != NULL);
332 assert(tree->last_used_container_id != UINT16_MAX);
333
334 return ++tree->last_used_container_id;
335}
336
George Liud9855ab2021-05-13 09:41:31 +0800337pldm_entity pldm_entity_extract(pldm_entity_node *node)
338{
339 assert(node != NULL);
340
341 return node->entity;
342}
343
Deepak Kodihalli05787052020-03-10 01:54:08 -0500344pldm_entity_association_tree *pldm_entity_association_tree_init()
345{
346 pldm_entity_association_tree *tree =
347 malloc(sizeof(pldm_entity_association_tree));
348 assert(tree != NULL);
349 tree->root = NULL;
350 tree->last_used_container_id = 0;
351
352 return tree;
353}
354
355static pldm_entity_node *find_insertion_at(pldm_entity_node *start,
356 uint16_t entity_type)
357{
358 assert(start != NULL);
359
360 /* Insert after the the last node that matches the input entity type, or
361 * at the end if no such match occurrs
362 */
363 while (start->next_sibling != NULL) {
364 uint16_t this_type = start->entity.entity_type;
365 pldm_entity_node *next = start->next_sibling;
366 if (this_type == entity_type &&
367 (this_type != next->entity.entity_type)) {
368 break;
369 }
370 start = start->next_sibling;
371 }
372
373 return start;
374}
375
376pldm_entity_node *
377pldm_entity_association_tree_add(pldm_entity_association_tree *tree,
378 pldm_entity *entity, pldm_entity_node *parent,
379 uint8_t association_type)
380{
381 assert(tree != NULL);
382 assert(association_type == PLDM_ENTITY_ASSOCIAION_PHYSICAL ||
383 association_type == PLDM_ENTITY_ASSOCIAION_LOGICAL);
384 pldm_entity_node *node = malloc(sizeof(pldm_entity_node));
385 assert(node != NULL);
George Liufe77eea2021-04-28 15:08:07 +0800386 node->parent = NULL;
Deepak Kodihalli05787052020-03-10 01:54:08 -0500387 node->first_child = NULL;
388 node->next_sibling = NULL;
389 node->entity.entity_type = entity->entity_type;
390 node->entity.entity_instance_num = 1;
391 node->association_type = association_type;
392
393 if (tree->root == NULL) {
394 assert(parent == NULL);
395 tree->root = node;
396 /* container_id 0 here indicates this is the top-most entry */
397 node->entity.entity_container_id = 0;
398 } else if (parent != NULL && parent->first_child == NULL) {
399 parent->first_child = node;
George Liufe77eea2021-04-28 15:08:07 +0800400 node->parent = parent;
Deepak Kodihalli05787052020-03-10 01:54:08 -0500401 node->entity.entity_container_id = next_container_id(tree);
402 } else {
403 pldm_entity_node *start =
404 parent == NULL ? tree->root : parent->first_child;
405 pldm_entity_node *prev =
406 find_insertion_at(start, entity->entity_type);
407 assert(prev != NULL);
408 pldm_entity_node *next = prev->next_sibling;
409 if (prev->entity.entity_type == entity->entity_type) {
410 assert(prev->entity.entity_instance_num != UINT16_MAX);
411 node->entity.entity_instance_num =
412 prev->entity.entity_instance_num + 1;
413 }
414 prev->next_sibling = node;
George Liufe77eea2021-04-28 15:08:07 +0800415 node->parent = prev->parent;
Deepak Kodihalli05787052020-03-10 01:54:08 -0500416 node->next_sibling = next;
417 node->entity.entity_container_id =
418 prev->entity.entity_container_id;
419 }
420 entity->entity_instance_num = node->entity.entity_instance_num;
421 entity->entity_container_id = node->entity.entity_container_id;
422
423 return node;
424}
425
426static void get_num_nodes(pldm_entity_node *node, size_t *num)
427{
428 if (node == NULL) {
429 return;
430 }
431
432 ++(*num);
433 get_num_nodes(node->next_sibling, num);
434 get_num_nodes(node->first_child, num);
435}
436
437static void entity_association_tree_visit(pldm_entity_node *node,
438 pldm_entity *entities, size_t *index)
439{
440 if (node == NULL) {
441 return;
442 }
443
444 pldm_entity *entity = &entities[*index];
445 ++(*index);
446 entity->entity_type = node->entity.entity_type;
447 entity->entity_instance_num = node->entity.entity_instance_num;
448 entity->entity_container_id = node->entity.entity_container_id;
449
450 entity_association_tree_visit(node->next_sibling, entities, index);
451 entity_association_tree_visit(node->first_child, entities, index);
452}
453
454void pldm_entity_association_tree_visit(pldm_entity_association_tree *tree,
455 pldm_entity **entities, size_t *size)
456{
457 assert(tree != NULL);
458
459 *size = 0;
460 if (tree->root == NULL) {
461 return;
462 }
463
464 get_num_nodes(tree->root, size);
465 *entities = malloc(*size * sizeof(pldm_entity));
466 size_t index = 0;
467 entity_association_tree_visit(tree->root, *entities, &index);
468}
469
470static void entity_association_tree_destroy(pldm_entity_node *node)
471{
472 if (node == NULL) {
473 return;
474 }
475
476 entity_association_tree_destroy(node->next_sibling);
477 entity_association_tree_destroy(node->first_child);
478 free(node);
479}
480
481void pldm_entity_association_tree_destroy(pldm_entity_association_tree *tree)
482{
483 assert(tree != NULL);
484
485 entity_association_tree_destroy(tree->root);
486 free(tree);
487}
488
489inline bool pldm_entity_is_node_parent(pldm_entity_node *node)
490{
491 assert(node != NULL);
492
493 return node->first_child != NULL;
494}
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500495
George Liufe77eea2021-04-28 15:08:07 +0800496inline pldm_entity_node *pldm_entity_get_parent(pldm_entity_node *node)
497{
498 assert(node != NULL);
499
500 return node->parent;
501}
502
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500503uint8_t pldm_entity_get_num_children(pldm_entity_node *node,
504 uint8_t association_type)
505{
506 assert(node != NULL);
507 assert(association_type == PLDM_ENTITY_ASSOCIAION_PHYSICAL ||
508 association_type == PLDM_ENTITY_ASSOCIAION_LOGICAL);
509
510 size_t count = 0;
511 pldm_entity_node *curr = node->first_child;
512 while (curr != NULL) {
513 if (curr->association_type == association_type) {
514 ++count;
515 }
516 curr = curr->next_sibling;
517 }
518
519 assert(count < UINT8_MAX);
520 return count;
521}
522
523static void _entity_association_pdr_add_entry(pldm_entity_node *curr,
524 pldm_pdr *repo, uint16_t size,
525 uint8_t contained_count,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500526 uint8_t association_type,
527 bool is_remote)
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500528{
529 uint8_t pdr[size];
530 uint8_t *start = pdr;
531
532 struct pldm_pdr_hdr *hdr = (struct pldm_pdr_hdr *)start;
533 hdr->version = 1;
534 hdr->record_handle = 0;
535 hdr->type = PLDM_PDR_ENTITY_ASSOCIATION;
536 hdr->record_change_num = 0;
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500537 hdr->length = htole16(size - sizeof(struct pldm_pdr_hdr));
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500538 start += sizeof(struct pldm_pdr_hdr);
539
540 uint16_t *container_id = (uint16_t *)start;
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500541 *container_id = htole16(curr->first_child->entity.entity_container_id);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500542 start += sizeof(uint16_t);
543 *start = association_type;
544 start += sizeof(uint8_t);
545
546 pldm_entity *entity = (pldm_entity *)start;
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500547 entity->entity_type = htole16(curr->entity.entity_type);
548 entity->entity_instance_num = htole16(curr->entity.entity_instance_num);
549 entity->entity_container_id = htole16(curr->entity.entity_container_id);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500550 start += sizeof(pldm_entity);
551
552 *start = contained_count;
553 start += sizeof(uint8_t);
554
555 pldm_entity_node *node = curr->first_child;
556 while (node != NULL) {
557 if (node->association_type == association_type) {
558 pldm_entity *entity = (pldm_entity *)start;
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500559 entity->entity_type = htole16(node->entity.entity_type);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500560 entity->entity_instance_num =
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500561 htole16(node->entity.entity_instance_num);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500562 entity->entity_container_id =
Deepak Kodihallifb4dd7b2020-03-17 03:27:22 -0500563 htole16(node->entity.entity_container_id);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500564 start += sizeof(pldm_entity);
565 }
566 node = node->next_sibling;
567 }
568
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500569 pldm_pdr_add(repo, pdr, size, 0, is_remote);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500570}
571
572static void entity_association_pdr_add_entry(pldm_entity_node *curr,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500573 pldm_pdr *repo, bool is_remote)
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500574{
575 uint8_t num_logical_children =
576 pldm_entity_get_num_children(curr, PLDM_ENTITY_ASSOCIAION_LOGICAL);
577 uint8_t num_physical_children =
578 pldm_entity_get_num_children(curr, PLDM_ENTITY_ASSOCIAION_PHYSICAL);
579
580 if (num_logical_children) {
581 uint16_t logical_pdr_size =
582 sizeof(struct pldm_pdr_hdr) + sizeof(uint16_t) +
583 sizeof(uint8_t) + sizeof(pldm_entity) + sizeof(uint8_t) +
584 (num_logical_children * sizeof(pldm_entity));
585 _entity_association_pdr_add_entry(
586 curr, repo, logical_pdr_size, num_logical_children,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500587 PLDM_ENTITY_ASSOCIAION_LOGICAL, is_remote);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500588 }
589
590 if (num_physical_children) {
591 uint16_t physical_pdr_size =
592 sizeof(struct pldm_pdr_hdr) + sizeof(uint16_t) +
593 sizeof(uint8_t) + sizeof(pldm_entity) + sizeof(uint8_t) +
594 (num_physical_children * sizeof(pldm_entity));
595 _entity_association_pdr_add_entry(
596 curr, repo, physical_pdr_size, num_physical_children,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500597 PLDM_ENTITY_ASSOCIAION_PHYSICAL, is_remote);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500598 }
599}
600
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500601static void entity_association_pdr_add(pldm_entity_node *curr, pldm_pdr *repo,
602 bool is_remote)
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500603{
604 if (curr == NULL) {
605 return;
606 }
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500607 entity_association_pdr_add_entry(curr, repo, is_remote);
608 entity_association_pdr_add(curr->next_sibling, repo, is_remote);
609 entity_association_pdr_add(curr->first_child, repo, is_remote);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500610}
611
612void pldm_entity_association_pdr_add(pldm_entity_association_tree *tree,
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500613 pldm_pdr *repo, bool is_remote)
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500614{
615 assert(tree != NULL);
616 assert(repo != NULL);
617
Deepak Kodihalli87514cc2020-04-16 09:08:38 -0500618 entity_association_pdr_add(tree->root, repo, is_remote);
Deepak Kodihalli0a738f02020-03-10 01:56:21 -0500619}
Deepak Kodihalli3b28ba82020-03-30 07:39:47 -0500620
Deepak Kodihalli4a680932020-04-22 03:31:17 -0500621void pldm_pdr_remove_remote_pdrs(pldm_pdr *repo)
622{
623 assert(repo != NULL);
624 bool removed = false;
625
626 pldm_pdr_record *record = repo->first;
627 pldm_pdr_record *prev = NULL;
628 while (record != NULL) {
629 pldm_pdr_record *next = record->next;
630 if (record->is_remote == true) {
631 if (repo->first == record) {
632 repo->first = next;
633 } else {
634 prev->next = next;
635 }
636 if (repo->last == record) {
637 repo->last = prev;
638 }
639 if (record->data) {
640 free(record->data);
641 }
642 --repo->record_count;
643 repo->size -= record->size;
644 free(record);
645 removed = true;
646 } else {
647 prev = record;
648 }
649 record = next;
650 }
651
652 if (removed == true) {
653 record = repo->first;
654 uint32_t record_handle = 0;
655 while (record != NULL) {
656 record->record_handle = ++record_handle;
657 if (record->data != NULL) {
658 struct pldm_pdr_hdr *hdr =
659 (struct pldm_pdr_hdr *)(record->data);
660 hdr->record_handle =
661 htole32(record->record_handle);
662 }
663 record = record->next;
664 }
665 }
666}
667
Deepak Kodihalli3b28ba82020-03-30 07:39:47 -0500668void entity_association_tree_find(pldm_entity_node *node, pldm_entity *entity,
669 pldm_entity_node **out)
670{
671 if (node == NULL) {
672 return;
673 }
674
675 if (node->entity.entity_type == entity->entity_type &&
676 node->entity.entity_instance_num == entity->entity_instance_num) {
677 entity->entity_container_id = node->entity.entity_container_id;
678 *out = node;
679 return;
680 }
681
682 entity_association_tree_find(node->next_sibling, entity, out);
683 entity_association_tree_find(node->first_child, entity, out);
684}
685
686pldm_entity_node *
687pldm_entity_association_tree_find(pldm_entity_association_tree *tree,
688 pldm_entity *entity)
689{
690 assert(tree != NULL);
691
692 pldm_entity_node *node = NULL;
693 entity_association_tree_find(tree->root, entity, &node);
694 return node;
695}
696
697void pldm_entity_association_pdr_extract(const uint8_t *pdr, uint16_t pdr_len,
698 size_t *num_entities,
699 pldm_entity **entities)
700{
701 assert(pdr != NULL);
702 assert(pdr_len >= sizeof(struct pldm_pdr_hdr) +
703 sizeof(struct pldm_pdr_entity_association));
704
705 struct pldm_pdr_hdr *hdr = (struct pldm_pdr_hdr *)pdr;
706 assert(hdr->type == PLDM_PDR_ENTITY_ASSOCIATION);
707
708 const uint8_t *start = (uint8_t *)pdr;
709 const uint8_t *end =
710 start + sizeof(struct pldm_pdr_hdr) + le16toh(hdr->length);
711 start += sizeof(struct pldm_pdr_hdr);
712 struct pldm_pdr_entity_association *entity_association_pdr =
713 (struct pldm_pdr_entity_association *)start;
714 *num_entities = entity_association_pdr->num_children + 1;
715 assert(*num_entities >= 2);
716 *entities = malloc(sizeof(pldm_entity) * *num_entities);
717 assert(*entities != NULL);
718 assert(start + sizeof(struct pldm_pdr_entity_association) +
719 sizeof(pldm_entity) * (*num_entities - 2) ==
720 end);
721 (*entities)->entity_type =
722 le16toh(entity_association_pdr->container.entity_type);
723 (*entities)->entity_instance_num =
724 le16toh(entity_association_pdr->container.entity_instance_num);
725 (*entities)->entity_container_id =
726 le16toh(entity_association_pdr->container.entity_container_id);
727 pldm_entity *curr_entity = entity_association_pdr->children;
728 size_t i = 1;
729 while (i < *num_entities) {
730 (*entities + i)->entity_type =
731 le16toh(curr_entity->entity_type);
732 (*entities + i)->entity_instance_num =
733 le16toh(curr_entity->entity_instance_num);
734 (*entities + i)->entity_container_id =
735 le16toh(curr_entity->entity_container_id);
736 ++curr_entity;
737 ++i;
738 }
739}