lib: remove unused libnvfru
[unleashed.git] / usr / src / lib / libfru / libfrupicltree / frupicltree.c
blob4e9f781fbd4e6eb870d532b7217b63c0affbe30a
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License, Version 1.0 only
6 * (the "License"). You may not use this file except in compliance
7 * with the License.
9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
10 * or http://www.opensolaris.org/os/licensing.
11 * See the License for the specific language governing permissions
12 * and limitations under the License.
14 * When distributing Covered Code, include this CDDL HEADER in each
15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
16 * If applicable, add the following below this CDDL HEADER, with the
17 * fields enclosed by brackets "[]" replaced with your own identifying
18 * information: Portions Copyright [yyyy] [name of copyright owner]
20 * CDDL HEADER END
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
29 #include <alloca.h>
30 #include <picl.h>
31 #include <picltree.h>
33 #include <string.h>
34 #include <stdlib.h>
35 #include <stdarg.h>
36 #include <stdio.h>
38 #include "picldefs.h"
39 #include "fru_data.h"
41 #include "libfruds.h"
42 #include "libfrup.h"
44 #define FRU_LABEL_PADDING 10
46 /* ========================================================================= */
47 #define TREEHDL_TO_PICLHDL(treehdl) ((picl_nodehdl_t)treehdl)
48 #define PICLHDL_TO_TREEHDL(piclhdl) ((fru_treehdl_t)piclhdl)
50 #define TREESEGHDL_TO_PICLHDL(treeseghdl) ((picl_nodehdl_t)treeseghdl)
51 #define PICLHDL_TO_TREESEGHDL(piclhdl) ((fru_treeseghdl_t)piclhdl)
53 /* Cache of the root node for quick checks */
54 static picl_nodehdl_t picl_root_node;
56 /* ========================================================================= */
58 * Map the PICL errors the plugin would give me to FRU errors
60 static fru_errno_t
61 map_plugin_err(int picl_err)
63 switch (picl_err) {
64 case PICL_SUCCESS:
65 return (FRU_SUCCESS);
66 case PICL_PERMDENIED:
67 return (FRU_INVALPERM);
68 case PICL_PROPEXISTS:
69 return (FRU_DUPSEG);
70 case PICL_NOSPACE:
71 return (FRU_NOSPACE);
72 case PICL_NORESPONSE:
73 return (FRU_NORESPONSE);
74 case PICL_PROPNOTFOUND:
75 return (FRU_NODENOTFOUND);
76 case PICL_ENDOFLIST:
77 return (FRU_DATANOTFOUND);
79 return (FRU_IOERROR);
82 /* ========================================================================= */
84 * cause a refresh of the sub-nodes by writing anything to the container
85 * property of the node.
87 static fru_errno_t
88 update_data_nodes(picl_nodehdl_t handle)
90 uint32_t container = FRUDATA_DELETE_TAG_KEY;
91 int picl_err = PICL_SUCCESS;
93 if ((picl_err = ptree_update_propval_by_name(handle,
94 PICL_PROP_CONTAINER, (void *)&container,
95 sizeof (container))) != PICL_SUCCESS) {
96 return (map_plugin_err(picl_err));
99 return (FRU_SUCCESS);
102 /* ========================================================================= */
104 * picl like function which gets a string property with the proper length
105 * NOTE: returns picl errno values NOT fru_errno_t
107 static int
108 get_strprop_by_name(picl_nodehdl_t handle, char *prop_name, char **string)
110 int picl_err = PICL_SUCCESS;
111 picl_prophdl_t proph;
113 size_t buf_size = 0;
114 char *tmp_buf = NULL;
116 ptree_propinfo_t prop_info;
118 if ((picl_err = ptree_get_prop_by_name(handle, prop_name, &proph))
119 != PICL_SUCCESS) {
120 return (picl_err);
122 if ((picl_err = ptree_get_propinfo(proph, &prop_info))
123 != PICL_SUCCESS) {
124 return (picl_err);
126 buf_size = prop_info.piclinfo.size;
128 tmp_buf = malloc((sizeof (*tmp_buf) * buf_size));
129 if (tmp_buf == NULL) {
130 return (PICL_FAILURE);
133 if ((picl_err = ptree_get_propval(proph, tmp_buf, buf_size))
134 != PICL_SUCCESS) {
135 free(tmp_buf);
136 return (picl_err);
139 *string = tmp_buf;
140 return (PICL_SUCCESS);
143 /* ========================================================================= */
144 static fru_errno_t
145 fpt_get_name_from_hdl(fru_treehdl_t node, char **name)
147 int picl_err = PICL_SUCCESS;
148 char *tmp_name = NULL;
149 char *label = NULL;
150 picl_nodehdl_t handle = TREEHDL_TO_PICLHDL(node);
152 /* get the name */
153 if ((picl_err = get_strprop_by_name(handle, PICL_PROP_NAME,
154 &tmp_name)) != PICL_SUCCESS) {
155 return (map_plugin_err(picl_err));
158 /* get the label, if any */
159 if ((picl_err = get_strprop_by_name(handle, PICL_PROP_LABEL,
160 &label)) != PICL_SUCCESS) {
161 if (picl_err != PICL_PROPNOTFOUND) {
162 free(tmp_name);
163 return (map_plugin_err(picl_err));
165 /* else PICL_PROPNOTFOUND is OK because not all nodes */
166 /* will have a label. */
169 /* construct the name as nessecary */
170 if (label == NULL) {
171 *name = strdup(tmp_name);
172 } else {
173 size_t buf_size = strlen(tmp_name) + strlen(label) +
174 FRU_LABEL_PADDING;
175 char *tmp = malloc(buf_size);
176 if (tmp == NULL) {
177 free(tmp_name);
178 free(label);
179 return (FRU_FAILURE);
181 snprintf(tmp, buf_size, "%s?%s=%s", tmp_name,
182 PICL_PROP_LABEL, label);
183 *name = tmp;
186 free(tmp_name);
187 free(label);
188 return (FRU_SUCCESS);
191 /* ========================================================================= */
192 /* compare the node name to the name passed */
193 static fru_errno_t
194 cmp_node_name(picl_nodehdl_t node, const char *name)
196 char *node_name = NULL;
198 if (get_strprop_by_name(node, PICL_PROP_NAME, &node_name)
199 != PICL_SUCCESS) {
200 return (FRU_FAILURE);
203 if (strcmp(node_name, name) == 0) {
204 free(node_name);
205 return (FRU_SUCCESS);
208 free(node_name);
209 return (FRU_FAILURE);
212 /* ========================================================================= */
213 /* compare the node class name to the name passed */
214 static fru_errno_t
215 cmp_class_name(picl_nodehdl_t node, const char *name)
217 char *class_name = NULL;
219 if (get_strprop_by_name(node, PICL_PROP_CLASSNAME, &class_name)
220 != PICL_SUCCESS) {
221 return (FRU_FAILURE);
224 if (strcmp(class_name, name) == 0) {
225 free(class_name);
226 return (FRU_SUCCESS);
229 free(class_name);
230 return (FRU_FAILURE);
234 /* ========================================================================= */
235 /* get the "frutree" root node */
236 static fru_errno_t
237 fpt_get_root(fru_treehdl_t *node)
239 picl_nodehdl_t picl_node;
240 int picl_err = PICL_SUCCESS;
242 picl_err = ptree_get_root(&picl_node);
243 if ((picl_err = ptree_get_propval_by_name(picl_node, PICL_PROP_CHILD,
244 (void *)&picl_node, sizeof (picl_node)))
245 != PICL_SUCCESS) {
246 return (map_plugin_err(picl_err));
249 while (cmp_node_name(picl_node, PICL_NODE_FRUTREE)
250 != FRU_SUCCESS) {
252 if ((picl_err = ptree_get_propval_by_name(picl_node,
253 PICL_PROP_PEER, (void *)&picl_node,
254 sizeof (picl_node))) == PICL_PROPNOTFOUND) {
255 return (FRU_NODENOTFOUND);
256 } else if (picl_err != PICL_SUCCESS) {
257 return (map_plugin_err(picl_err));
261 picl_root_node = picl_node;
262 *node = PICLHDL_TO_TREEHDL(picl_node);
263 return (FRU_SUCCESS);
266 /* ========================================================================= */
267 static fru_errno_t
268 fpt_get_peer(fru_treehdl_t sibling, fru_treehdl_t *peer)
270 int rc = PICL_SUCCESS;
271 picl_nodehdl_t handle = TREEHDL_TO_PICLHDL(sibling);
272 picl_nodehdl_t picl_peer;
274 rc = ptree_get_propval_by_name(handle, PICL_PROP_PEER,
275 (void *)&picl_peer, sizeof (picl_peer));
276 if (rc != PICL_SUCCESS) {
277 return (map_plugin_err(rc));
280 *peer = PICLHDL_TO_TREEHDL(picl_peer);
281 return (FRU_SUCCESS);
284 /* ========================================================================= */
285 static fru_errno_t
286 fpt_get_child(fru_treehdl_t handle, fru_treehdl_t *child)
288 picl_nodehdl_t p_child;
289 int rc = ptree_get_propval_by_name(TREEHDL_TO_PICLHDL(handle),
290 PICL_PROP_CHILD, (void *)&p_child, sizeof (p_child));
291 if (rc != PICL_SUCCESS) {
292 return (map_plugin_err(rc));
295 *child = PICLHDL_TO_TREEHDL(p_child);
296 return (FRU_SUCCESS);
299 /* ========================================================================= */
300 static fru_errno_t
301 fpt_get_parent(fru_treehdl_t handle, fru_treehdl_t *parent)
303 int rc = PICL_SUCCESS;
304 picl_nodehdl_t p_parent;
306 /* do not allow the libfru users to see the parent of the root */
307 if (TREEHDL_TO_PICLHDL(handle) == picl_root_node) {
308 return (FRU_NODENOTFOUND);
311 rc = ptree_get_propval_by_name(TREEHDL_TO_PICLHDL(handle),
312 PICL_PROP_PARENT, (void *)&p_parent, sizeof (p_parent));
313 if (rc != PICL_SUCCESS) {
314 return (map_plugin_err(rc));
317 *parent = PICLHDL_TO_TREEHDL(p_parent);
318 return (FRU_SUCCESS);
321 /* ========================================================================= */
322 static fru_errno_t
323 fpt_get_node_type(fru_treehdl_t node, fru_node_t *type)
325 int rc = PICL_SUCCESS;
326 char picl_class[PICL_PROPNAMELEN_MAX];
327 picl_nodehdl_t handle = TREEHDL_TO_PICLHDL(node);
329 if ((rc = ptree_get_propval_by_name(handle, PICL_PROP_CLASSNAME,
330 picl_class, sizeof (picl_class))) != PICL_SUCCESS) {
331 return (map_plugin_err(rc));
334 if (strcmp(picl_class, PICL_CLASS_LOCATION) == 0) {
335 *type = FRU_NODE_LOCATION;
336 return (FRU_SUCCESS);
337 } else if (strcmp(picl_class, PICL_CLASS_FRU) == 0) {
338 picl_prophdl_t proph;
340 /* check for the CONTAINER_PROP property which indicates */
341 /* there is data for this node. (ie fru is a container) */
342 if (ptree_get_prop_by_name(handle,
343 PICL_PROP_CONTAINER, &proph) == PICL_SUCCESS) {
344 *type = FRU_NODE_CONTAINER;
345 return (FRU_SUCCESS);
347 *type = FRU_NODE_FRU;
348 return (FRU_SUCCESS);
351 *type = FRU_NODE_UNKNOWN;
352 return (FRU_SUCCESS);
355 /* ========================================================================= */
356 /* find the next section or return NODENOTFOUND */
357 static fru_errno_t
358 find_next_section(picl_nodehdl_t current, picl_nodehdl_t *next)
360 picl_nodehdl_t rc_next;
362 if (ptree_get_propval_by_name(current, PICL_PROP_PEER,
363 (void *)&rc_next, sizeof (rc_next)) != PICL_SUCCESS) {
364 return (FRU_NODENOTFOUND);
367 /* Make sure this is a "Section" node */
368 if (cmp_class_name(rc_next, PICL_CLASS_SECTION)
369 == FRU_SUCCESS) {
370 *next = rc_next;
371 return (FRU_SUCCESS);
374 /* and if this is not good keep trying to find a peer which */
375 /* is a section */
376 return (find_next_section(rc_next, next));
379 /* ========================================================================= */
380 /* find the first section or return NODENOTFOUND */
381 static fru_errno_t
382 find_first_section(picl_nodehdl_t parent, picl_nodehdl_t *section)
384 picl_nodehdl_t rc_section;
386 if (ptree_get_propval_by_name(parent, PICL_PROP_CHILD,
387 (void *)&rc_section, sizeof (rc_section)) != PICL_SUCCESS) {
388 return (FRU_NODENOTFOUND);
391 /* Make sure this is a "Section" node */
392 if (cmp_class_name(rc_section, PICL_CLASS_SECTION)
393 == FRU_SUCCESS) {
394 *section = rc_section;
395 return (FRU_SUCCESS);
398 /* and if this is not good keep trying to find a peer which */
399 /* is a section */
400 return (find_next_section(rc_section, section));
403 /* ========================================================================= */
405 * Find the handle of the segment node "segment".
406 * also returns the hardware description of this segment. (read from the
407 * section this was found in.)
408 * If the ign_cor_flg is set this will still succeed even if the segment is
409 * corrupt, otherwise it will return FRU_SEGCORRUPT for corrupt segments
411 #define IGN_CORRUPT_YES 1
412 #define IGN_CORRUPT_NO 0
413 static fru_errno_t
414 get_segment_node(picl_nodehdl_t handle, const char *segment,
415 picl_nodehdl_t *seg_hdl, fru_seg_hwdesc_t *hw_desc, int ign_cor_flg)
417 fru_errno_t err = FRU_SUCCESS;
418 picl_nodehdl_t sect_node;
420 if ((err = update_data_nodes(handle)) != FRU_SUCCESS) {
421 return (err);
424 if ((err = find_first_section(handle, &sect_node)) != FRU_SUCCESS) {
425 return (err);
428 /* while there are sections. */
429 while (err == FRU_SUCCESS) {
430 uint32_t num_segs = 0;
431 int rc = PICL_SUCCESS;
432 picl_nodehdl_t seg_node;
434 /* do this just in case the Segments have not been built. */
435 if ((rc = ptree_get_propval_by_name(sect_node,
436 PICL_PROP_NUM_SEGMENTS,
437 (void *)&num_segs,
438 sizeof (num_segs))) != PICL_SUCCESS) {
439 return (map_plugin_err(rc));
442 /* while there are segments. */
443 rc = ptree_get_propval_by_name(sect_node, PICL_PROP_CHILD,
444 (void *)&seg_node, sizeof (seg_node));
445 while (rc == PICL_SUCCESS) {
446 char name[PICL_PROPNAMELEN_MAX];
447 ptree_get_propval_by_name(seg_node, PICL_PROP_NAME,
448 name, sizeof (name));
449 if (strcmp(segment, name) == 0) {
450 int dummy = 0;
451 int protection = 0;
452 /* NUM_TAGS prop exists iff segment is OK */
453 if ((ign_cor_flg == IGN_CORRUPT_NO) &&
454 (ptree_get_propval_by_name(seg_node,
455 PICL_PROP_NUM_TAGS,
456 (void *)&dummy,
457 sizeof (dummy)) != PICL_SUCCESS)) {
458 return (FRU_SEGCORRUPT);
460 /* get the HW protections of this section. */
461 if ((rc = ptree_get_propval_by_name(sect_node,
462 PICL_PROP_PROTECTED,
463 (void *)&protection,
464 sizeof (protection)))
465 != PICL_SUCCESS) {
466 return (map_plugin_err(rc));
468 hw_desc->all_bits = 0;
469 hw_desc->field.read_only = protection;
471 *seg_hdl = seg_node;
472 return (FRU_SUCCESS);
474 rc = ptree_get_propval_by_name(seg_node, PICL_PROP_PEER,
475 (void *)&seg_node, sizeof (seg_node));
478 /* Peer property not found is ok */
479 if (rc != PICL_PROPNOTFOUND) {
480 return (map_plugin_err(rc));
483 err = find_next_section(sect_node, &sect_node);
486 return (FRU_INVALSEG);
489 /* ========================================================================= */
491 * For the section handle passed add to list all the segment names found.
492 * Also incriments total by the number found.
494 static fru_errno_t
495 add_segs_for_section(picl_nodehdl_t section, fru_strlist_t *list)
497 int num_segments = 0;
498 int rc = PICL_SUCCESS;
500 if ((rc = ptree_get_propval_by_name(section,
501 PICL_PROP_NUM_SEGMENTS,
502 (void *)&num_segments,
503 sizeof (num_segments))) != PICL_SUCCESS) {
504 fru_destroy_strlist(list);
505 return (map_plugin_err(rc));
508 if (num_segments != 0) {
509 picl_nodehdl_t seg_node;
510 int total_space = list->num + num_segments;
512 list->strs = realloc(list->strs,
513 (sizeof (*(list->strs)) * (total_space)));
514 if (list->strs == NULL) {
515 return (FRU_FAILURE);
518 /* get the first segment */
519 rc = ptree_get_propval_by_name(section,
520 PICL_PROP_CHILD, (void *)&seg_node,
521 sizeof (seg_node));
523 /* while there are more segments. */
524 while (rc == PICL_SUCCESS) {
525 char name[FRU_SEGNAMELEN +1];
527 if ((rc = ptree_get_propval_by_name(seg_node,
528 PICL_PROP_NAME, name,
529 sizeof (name))) != PICL_SUCCESS) {
530 break;
533 /* check array bounds */
534 if (list->num >= total_space) {
535 /* PICL reported incorrect number of segs */
536 return (FRU_IOERROR);
538 list->strs[(list->num)++] = strdup(name);
540 rc = ptree_get_propval_by_name(seg_node,
541 PICL_PROP_PEER, (void *)&seg_node,
542 sizeof (seg_node));
545 /* Peer property not found is ok */
546 if (rc != PICL_PROPNOTFOUND) {
547 return (map_plugin_err(rc));
551 return (FRU_SUCCESS);
554 /* ========================================================================= */
555 static fru_errno_t
556 fpt_get_seg_list(fru_treehdl_t handle, fru_strlist_t *list)
558 fru_errno_t err;
559 picl_nodehdl_t sect_node;
560 fru_strlist_t rc_list;
561 rc_list.num = 0;
562 rc_list.strs = NULL;
564 if ((err = update_data_nodes(TREEHDL_TO_PICLHDL(handle)))
565 != FRU_SUCCESS) {
566 return (err);
569 if ((err = find_first_section(TREEHDL_TO_PICLHDL(handle), &sect_node))
570 != FRU_SUCCESS) {
571 return (err);
574 /* while there are sections. */
575 while (err == FRU_SUCCESS) {
576 if ((err = add_segs_for_section(sect_node, &rc_list))
577 != FRU_SUCCESS) {
578 fru_destroy_strlist(&rc_list);
579 return (err);
581 err = find_next_section(sect_node, &sect_node);
584 list->num = rc_list.num;
585 list->strs = rc_list.strs;
587 return (FRU_SUCCESS);
590 /* ========================================================================= */
591 static fru_errno_t
592 fpt_get_seg_def(fru_treehdl_t handle, const char *seg_name, fru_segdef_t *def)
594 fru_errno_t err = FRU_SUCCESS;
595 picl_nodehdl_t seg_node;
596 fru_seg_hwdesc_t hw_desc;
598 fru_segdesc_t desc;
599 uint32_t size;
600 uint32_t address;
601 /* LINTED */
602 int picl_err = PICL_SUCCESS;
604 if ((err = get_segment_node(TREEHDL_TO_PICLHDL(handle), seg_name,
605 &seg_node, &hw_desc, IGN_CORRUPT_YES)) != FRU_SUCCESS)
606 return (err);
608 if ((picl_err = ptree_get_propval_by_name(seg_node,
609 PICL_PROP_DESCRIPTOR,
610 &desc, sizeof (desc))) != PICL_SUCCESS) {
611 return (map_plugin_err(picl_err));
614 if ((picl_err = ptree_get_propval_by_name(seg_node,
615 PICL_PROP_LENGTH,
616 &size, sizeof (size))) != PICL_SUCCESS) {
617 return (map_plugin_err(picl_err));
620 if ((picl_err = ptree_get_propval_by_name(seg_node,
621 PICL_PROP_OFFSET,
622 &address, sizeof (address))) != PICL_SUCCESS) {
623 return (map_plugin_err(picl_err));
626 def->version = LIBFRU_VERSION;
627 strlcpy(def->name, seg_name, FRU_SEGNAMELEN+1);
628 def->desc = desc;
629 def->size = size;
630 def->address = address;
631 def->hw_desc = hw_desc;
633 return (FRU_SUCCESS);
636 /* ========================================================================= */
637 static fru_errno_t
638 fpt_add_seg(fru_treehdl_t handle, fru_segdef_t *def)
640 fru_errno_t err = FRU_SUCCESS;
641 int picl_err = PICL_SUCCESS;
642 picl_nodehdl_t section;
645 * for every section which has a ADD_SEGMENT_PROP try and add the segment
647 if ((err = find_first_section(TREEHDL_TO_PICLHDL(handle), &section))
648 != FRU_SUCCESS) {
649 return (err);
651 do {
652 fru_segdef_t dummy;
653 if ((picl_err = ptree_get_propval_by_name(section,
654 PICL_PROP_ADD_SEGMENT, &dummy, sizeof (dummy)))
655 == PICL_SUCCESS) {
657 picl_err = ptree_update_propval_by_name(section,
658 PICL_PROP_ADD_SEGMENT, def, sizeof (*def));
660 return (map_plugin_err(picl_err));
662 } while (find_next_section(section, &section) == FRU_SUCCESS);
664 return (map_plugin_err(picl_err));
667 /* ========================================================================= */
668 static fru_errno_t
669 fpt_delete_seg(fru_treehdl_t handle, const char *seg_name)
671 picl_nodehdl_t seg_hdl;
672 fru_seg_hwdesc_t hw_desc;
673 fru_errno_t err;
675 int dead_flag = FRUDATA_DELETE_TAG_KEY;
676 int rc = PICL_SUCCESS;
678 if ((err = get_segment_node(TREEHDL_TO_PICLHDL(handle), seg_name,
679 &seg_hdl, &hw_desc, IGN_CORRUPT_YES)) != FRU_SUCCESS) {
680 return (err);
683 rc = ptree_update_propval_by_name(seg_hdl, PICL_PROP_DELETE_SEGMENT,
684 &dead_flag, sizeof (dead_flag));
685 return (map_plugin_err(rc));
688 /* ========================================================================= */
689 static fru_errno_t
690 fpt_add_tag_to_seg(fru_treehdl_t handle, const char *seg_name,
691 fru_tag_t tag, uint8_t *data, size_t data_len)
693 fru_errno_t err = FRU_SUCCESS;
694 picl_nodehdl_t segHdl;
695 fru_seg_hwdesc_t hw_desc;
696 int picl_err = PICL_SUCCESS;
697 size_t buf_size = 0;
698 uint8_t *buffer = NULL;
699 picl_prophdl_t add_prop;
700 ptree_propinfo_t add_prop_info;
702 if ((err = get_segment_node(TREEHDL_TO_PICLHDL(handle), seg_name,
703 &segHdl, &hw_desc, IGN_CORRUPT_NO)) != FRU_SUCCESS) {
704 return (err);
707 /* get the length of the buffer required. */
708 if ((picl_err = ptree_get_prop_by_name(segHdl,
709 PICL_PROP_ADD_PACKET,
710 &add_prop)) != PICL_SUCCESS) {
711 return (map_plugin_err(picl_err));
714 if ((picl_err = ptree_get_propinfo(add_prop, &add_prop_info))
715 != PICL_SUCCESS) {
716 return (map_plugin_err(picl_err));
718 buf_size = add_prop_info.piclinfo.size;
720 if (data_len >= (buf_size - get_tag_size(get_tag_type(&tag)))) {
721 return (FRU_NOSPACE);
724 buffer = malloc(buf_size);
725 if (buffer == NULL) {
726 return (FRU_FAILURE);
728 /* write the tag and data into the buffer */
729 memcpy(buffer, &tag, get_tag_size(get_tag_type(&tag)));
730 memcpy((void *)(buffer+get_tag_size(get_tag_type(&tag))),
731 data, data_len);
733 picl_err = ptree_update_propval(add_prop, buffer, buf_size);
734 free(buffer);
735 return (map_plugin_err(picl_err));
738 /* ========================================================================= */
739 static fru_errno_t
740 fpt_get_tag_list(fru_treehdl_t handle, const char *seg_name,
741 fru_tag_t **tags, int *number)
743 picl_nodehdl_t seg_node;
744 fru_seg_hwdesc_t hw_desc;
745 fru_errno_t err = FRU_SUCCESS;
746 picl_prophdl_t tagTable;
747 int picl_err = PICL_SUCCESS;
748 unsigned int total_tags = 0;
750 /* return variables */
751 fru_tag_t *rc_tags = NULL;
752 unsigned int rc_num = 0;
754 if ((err = get_segment_node(TREEHDL_TO_PICLHDL(handle), seg_name,
755 &seg_node, &hw_desc, IGN_CORRUPT_NO)) != FRU_SUCCESS) {
756 return (err);
759 /* get the number of tags and allocate array for them */
760 if ((picl_err = ptree_get_propval_by_name(seg_node,
761 PICL_PROP_NUM_TAGS,
762 (void *)&total_tags,
763 sizeof (total_tags))) != PICL_SUCCESS) {
764 return (map_plugin_err(picl_err));
767 if (total_tags == 0) {
768 *tags = rc_tags;
769 *number = rc_num;
770 return (FRU_SUCCESS);
773 rc_tags = malloc((sizeof (*rc_tags) * total_tags));
774 if (rc_tags == NULL) {
775 return (FRU_FAILURE);
778 /* go through the tagTable and fill in the array */
779 if ((picl_err = ptree_get_propval_by_name(seg_node,
780 PICL_PROP_PACKET_TABLE,
781 &tagTable, sizeof (tagTable))) != PICL_SUCCESS) {
782 free(rc_tags);
783 return (map_plugin_err(picl_err));
785 picl_err = ptree_get_next_by_col(tagTable, &tagTable);
786 while (picl_err == PICL_SUCCESS) {
787 /* check array bounds */
788 if (rc_num >= total_tags) {
789 free(rc_tags);
790 return (FRU_FAILURE);
792 /* fill in the array */
793 if ((picl_err = ptree_get_propval(tagTable,
794 (void *)&(rc_tags[rc_num++]),
795 sizeof (fru_tag_t))) != PICL_SUCCESS) {
796 free(rc_tags);
797 return (map_plugin_err(picl_err));
799 /* get the next tag */
800 picl_err = ptree_get_next_by_col(tagTable, &tagTable);
803 if (picl_err == PICL_ENDOFLIST) {
804 *tags = rc_tags;
805 *number = rc_num;
806 return (FRU_SUCCESS);
808 return (map_plugin_err(picl_err));
811 /* ========================================================================= */
813 * From the handle, segment name, tag, and instance of the tag get me:
814 * segHdl: The segment handle for this segment.
815 * tagHdl: tag property handle in the tag table for this instance "tag"
817 static fru_errno_t
818 get_tag_handle(picl_nodehdl_t handle, const char *segment,
819 fru_tag_t tag, int instance,
820 picl_nodehdl_t *segHdl,
821 picl_prophdl_t *tagHdl)
823 fru_seg_hwdesc_t hw_desc;
824 fru_errno_t err;
825 picl_prophdl_t tagTable = 0;
826 int picl_err = PICL_SUCCESS;
827 picl_nodehdl_t tmp_seg;
829 fru_tag_t foundTag;
831 if ((err = get_segment_node(TREEHDL_TO_PICLHDL(handle), segment,
832 &tmp_seg, &hw_desc, IGN_CORRUPT_NO)) != FRU_SUCCESS) {
833 return (err);
836 foundTag.raw_data = 0;
837 if ((picl_err = ptree_get_propval_by_name(tmp_seg,
838 PICL_PROP_PACKET_TABLE,
839 &tagTable, sizeof (tagTable))) != PICL_SUCCESS) {
840 return (map_plugin_err(picl_err));
843 picl_err = ptree_get_next_by_col(tagTable, &tagTable);
844 while ((picl_err != PICL_ENDOFLIST) &&
845 (picl_err == PICL_SUCCESS)) {
846 if ((picl_err = ptree_get_propval(tagTable, (void *)&foundTag,
847 sizeof (foundTag))) != PICL_SUCCESS) {
848 return (map_plugin_err(picl_err));
850 if ((tags_equal(tag, foundTag) == 1) && (instance-- == 0)) {
851 *segHdl = tmp_seg;
852 *tagHdl = tagTable;
853 return (FRU_SUCCESS);
855 picl_err = ptree_get_next_by_col(tagTable, &tagTable);
858 return (map_plugin_err(picl_err));
861 /* ========================================================================= */
862 static fru_errno_t
863 fpt_get_tag_data(fru_treehdl_t handle, const char *seg_name,
864 fru_tag_t tag, int instance,
865 uint8_t **data, size_t *data_len)
867 fru_errno_t err = FRU_SUCCESS;
868 int picl_err = PICL_SUCCESS;
869 uint8_t *buffer;
870 int buf_len = 0;
872 picl_nodehdl_t seg;
873 picl_prophdl_t tagHdl;
875 if ((err = get_tag_handle(TREEHDL_TO_PICLHDL(handle), seg_name,
876 tag, instance, &seg, &tagHdl)) != FRU_SUCCESS) {
877 return (err);
880 if ((picl_err = ptree_get_next_by_row(tagHdl, &tagHdl))
881 != PICL_SUCCESS) {
882 return (map_plugin_err(picl_err));
885 buf_len = get_payload_length(&tag);
886 buffer = malloc(buf_len);
887 if (buffer == NULL) {
888 return (FRU_FAILURE);
891 if ((picl_err = ptree_get_propval(tagHdl, buffer, buf_len))
892 != PICL_SUCCESS) {
893 free(buffer);
894 return (map_plugin_err(picl_err));
897 *data = buffer;
898 *data_len = buf_len;
899 return (FRU_SUCCESS);
902 /* ========================================================================= */
903 static fru_errno_t
904 fpt_set_tag_data(fru_treehdl_t handle, const char *seg_name,
905 fru_tag_t tag, int instance,
906 uint8_t *data, size_t data_len)
908 fru_errno_t rc = FRU_SUCCESS;
909 int picl_err = PICL_SUCCESS;
911 picl_nodehdl_t seg;
912 picl_prophdl_t tagHdl;
914 if ((rc = get_tag_handle(TREEHDL_TO_PICLHDL(handle), seg_name,
915 tag, instance, &seg, &tagHdl)) != FRU_SUCCESS) {
916 return (rc);
919 if ((picl_err = ptree_get_next_by_row(tagHdl, &tagHdl))
920 != PICL_SUCCESS) {
921 return (map_plugin_err(picl_err));
924 if ((picl_err = ptree_update_propval(tagHdl, data, data_len))
925 != PICL_SUCCESS) {
926 return (map_plugin_err(picl_err));
929 return (FRU_SUCCESS);
932 /* ========================================================================= */
933 static fru_errno_t
934 fpt_delete_tag(fru_treehdl_t handle, const char *seg_name, fru_tag_t tag,
935 int instance)
937 fru_errno_t rc = FRU_SUCCESS;
938 int picl_err = PICL_SUCCESS;
940 picl_nodehdl_t segHdl;
941 picl_prophdl_t tagHdl;
943 /* get tag handle */
944 if ((rc = get_tag_handle(TREEHDL_TO_PICLHDL(handle), seg_name,
945 tag, instance, &segHdl, &tagHdl)) != FRU_SUCCESS) {
946 return (rc);
949 /* set up key */
950 tag.raw_data &= FRUDATA_DELETE_TAG_MASK;
951 tag.raw_data |= FRUDATA_DELETE_TAG_KEY;
953 /* Write back */
954 picl_err = ptree_update_propval(tagHdl, (void *)&(tag.raw_data),
955 sizeof (tag.raw_data));
956 return (map_plugin_err(picl_err));
959 /* ========================================================================= */
960 static fru_errno_t
961 fpt_for_each_segment(fru_treehdl_t treenode,
962 int (*function)(fru_treeseghdl_t segment, void *args),
963 void *args)
965 int num_segments = 0, status;
967 fru_errno_t saved_status = FRU_SUCCESS;
969 picl_nodehdl_t container = TREEHDL_TO_PICLHDL(treenode),
970 section, segment;
973 if ((status = update_data_nodes(container)) != FRU_SUCCESS)
974 return (status);
976 /* process each section */
977 for (status = ptree_get_propval_by_name(container, PICL_PROP_CHILD,
978 &section, sizeof (section));
979 status == PICL_SUCCESS;
980 status = ptree_get_propval_by_name(section, PICL_PROP_PEER,
981 &section,
982 sizeof (section))) {
984 if (cmp_class_name(section, PICL_CLASS_SECTION) != FRU_SUCCESS)
985 continue;
987 if ((status = ptree_get_propval_by_name(section,
988 PICL_PROP_NUM_SEGMENTS,
989 &num_segments,
990 sizeof (num_segments)))
991 == PICL_PROPNOTFOUND) {
992 continue;
993 } else if (status != PICL_SUCCESS) {
994 saved_status = map_plugin_err(status);
995 continue;
996 } else if (num_segments == 0) {
997 continue;
1000 /* process each segment */
1001 for (status = ptree_get_propval_by_name(section,
1002 PICL_PROP_CHILD,
1003 &segment,
1004 sizeof (segment));
1005 status == PICL_SUCCESS;
1006 status = ptree_get_propval_by_name(segment,
1007 PICL_PROP_PEER,
1008 &segment,
1009 sizeof (segment))) {
1011 if (cmp_class_name(segment, PICL_CLASS_SEGMENT)
1012 != FRU_SUCCESS) continue;
1014 if ((status = function(PICLHDL_TO_TREESEGHDL(segment),
1015 args))
1016 != FRU_SUCCESS) return (status);
1019 if (status != PICL_PROPNOTFOUND)
1020 saved_status = map_plugin_err(status);
1023 if (status != PICL_PROPNOTFOUND)
1024 saved_status = map_plugin_err(status);
1026 return (saved_status);
1029 /* ========================================================================= */
1030 static fru_errno_t
1031 fpt_get_segment_name(fru_treeseghdl_t segment, char **name)
1033 char *propval;
1035 int status;
1037 picl_prophdl_t proph = 0;
1039 ptree_propinfo_t propinfo;
1042 if ((status = ptree_get_prop_by_name(TREESEGHDL_TO_PICLHDL(segment),
1043 PICL_PROP_NAME, &proph))
1044 != PICL_SUCCESS)
1045 return (map_plugin_err(status));
1047 if (ptree_get_propinfo(proph, &propinfo) != PICL_SUCCESS)
1048 return (map_plugin_err(status));
1050 if (propinfo.piclinfo.size == 0)
1051 return (FRU_INVALDATASIZE);
1053 if ((propval = malloc(propinfo.piclinfo.size)) == NULL)
1054 return (FRU_NOSPACE);
1056 if ((status = ptree_get_propval(proph, propval, propinfo.piclinfo.size))
1057 != PICL_SUCCESS) {
1058 free(propval);
1059 return (map_plugin_err(status));
1062 *name = propval;
1064 return (FRU_SUCCESS);
1067 /* ========================================================================= */
1068 static fru_errno_t
1069 fpt_for_each_packet(fru_treeseghdl_t treesegment,
1070 int (*function)(fru_tag_t *tag, uint8_t *payload,
1071 size_t length,
1072 void *args),
1073 void *args)
1075 int status;
1077 uint8_t *payload;
1079 picl_nodehdl_t segment = TREESEGHDL_TO_PICLHDL(treesegment);
1081 picl_prophdl_t packet, payloadh = 0;
1083 ptree_propinfo_t propinfo;
1085 fru_segdesc_t descriptor;
1087 fru_tag_t tag;
1090 if ((status = ptree_get_propval_by_name(segment, PICL_PROP_DESCRIPTOR,
1091 &descriptor,
1092 sizeof (descriptor)))
1093 != PICL_SUCCESS) return (map_plugin_err(status));
1095 if (descriptor.field.opaque)
1096 return (FRU_SUCCESS);
1098 if (descriptor.field.encrypted && (encrypt_func == NULL))
1099 return (FRU_SUCCESS);
1101 if ((status = ptree_get_propval_by_name(segment, PICL_PROP_PACKET_TABLE,
1102 &packet, sizeof (packet)))
1103 == PICL_PROPNOTFOUND)
1104 return (FRU_SUCCESS);
1105 else if (status != PICL_SUCCESS)
1106 return (map_plugin_err(status));
1108 while ((status = ptree_get_next_by_col(packet, &packet))
1109 == PICL_SUCCESS) {
1110 if (((status = ptree_get_propval(packet, &tag, sizeof (tag)))
1111 != PICL_SUCCESS) ||
1112 ((status = ptree_get_next_by_row(packet, &payloadh))
1113 != PICL_SUCCESS) ||
1114 ((status = ptree_get_propinfo(payloadh, &propinfo))
1115 != PICL_SUCCESS))
1116 return (map_plugin_err(status));
1118 if (propinfo.piclinfo.size > 0) {
1119 payload = alloca(propinfo.piclinfo.size);
1120 if ((status = ptree_get_propval(payloadh, payload,
1121 propinfo.piclinfo.size))
1122 != PICL_SUCCESS) return (map_plugin_err(status));
1123 } else {
1124 payload = NULL;
1127 if ((descriptor.field.encrypted) &&
1128 ((status = encrypt_func(FRU_DECRYPT, payload,
1129 propinfo.piclinfo.size))
1130 != FRU_SUCCESS)) return status;
1132 if ((status = function(&tag, payload, propinfo.piclinfo.size,
1133 args))
1134 != FRU_SUCCESS) return (status);
1137 if (status == PICL_ENDOFLIST)
1138 return (FRU_SUCCESS);
1139 else
1140 return (map_plugin_err(status));
1143 /* ========================================================================= */
1144 /* ARGSUSED0 */
1145 static fru_errno_t
1146 initialize(int argc, char **argv)
1148 return (FRU_SUCCESS);
1151 /* ========================================================================= */
1152 static fru_errno_t
1153 shutdown(void)
1155 return (FRU_SUCCESS);
1158 /* ========================================================================= */
1159 /* object for libfru to link to */
1160 fru_datasource_t data_source =
1162 LIBFRU_DS_VER,
1163 initialize,
1164 shutdown,
1165 fpt_get_root,
1166 fpt_get_child,
1167 fpt_get_peer,
1168 fpt_get_parent,
1169 fpt_get_name_from_hdl,
1170 fpt_get_node_type,
1171 fpt_get_seg_list,
1172 fpt_get_seg_def,
1173 fpt_add_seg,
1174 fpt_delete_seg,
1175 fpt_for_each_segment,
1176 fpt_get_segment_name,
1177 fpt_add_tag_to_seg,
1178 fpt_get_tag_list,
1179 fpt_get_tag_data,
1180 fpt_set_tag_data,
1181 fpt_delete_tag,
1182 fpt_for_each_packet