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
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
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
61 map_plugin_err(int picl_err
)
67 return (FRU_INVALPERM
);
73 return (FRU_NORESPONSE
);
74 case PICL_PROPNOTFOUND
:
75 return (FRU_NODENOTFOUND
);
77 return (FRU_DATANOTFOUND
);
82 /* ========================================================================= */
84 * cause a refresh of the sub-nodes by writing anything to the container
85 * property of the node.
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
));
102 /* ========================================================================= */
104 * picl like function which gets a string property with the proper length
105 * NOTE: returns picl errno values NOT fru_errno_t
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
;
114 char *tmp_buf
= NULL
;
116 ptree_propinfo_t prop_info
;
118 if ((picl_err
= ptree_get_prop_by_name(handle
, prop_name
, &proph
))
122 if ((picl_err
= ptree_get_propinfo(proph
, &prop_info
))
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
))
140 return (PICL_SUCCESS
);
143 /* ========================================================================= */
145 fpt_get_name_from_hdl(fru_treehdl_t node
, char **name
)
147 int picl_err
= PICL_SUCCESS
;
148 char *tmp_name
= NULL
;
150 picl_nodehdl_t handle
= TREEHDL_TO_PICLHDL(node
);
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
) {
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 */
171 *name
= strdup(tmp_name
);
173 size_t buf_size
= strlen(tmp_name
) + strlen(label
) +
175 char *tmp
= malloc(buf_size
);
179 return (FRU_FAILURE
);
181 snprintf(tmp
, buf_size
, "%s?%s=%s", tmp_name
,
182 PICL_PROP_LABEL
, label
);
188 return (FRU_SUCCESS
);
191 /* ========================================================================= */
192 /* compare the node name to the name passed */
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
)
200 return (FRU_FAILURE
);
203 if (strcmp(node_name
, name
) == 0) {
205 return (FRU_SUCCESS
);
209 return (FRU_FAILURE
);
212 /* ========================================================================= */
213 /* compare the node class name to the name passed */
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
)
221 return (FRU_FAILURE
);
224 if (strcmp(class_name
, name
) == 0) {
226 return (FRU_SUCCESS
);
230 return (FRU_FAILURE
);
234 /* ========================================================================= */
235 /* get the "frutree" root node */
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
)))
246 return (map_plugin_err(picl_err
));
249 while (cmp_node_name(picl_node
, PICL_NODE_FRUTREE
)
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 /* ========================================================================= */
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 /* ========================================================================= */
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 /* ========================================================================= */
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 /* ========================================================================= */
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 */
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
)
371 return (FRU_SUCCESS
);
374 /* and if this is not good keep trying to find a peer which */
376 return (find_next_section(rc_next
, next
));
379 /* ========================================================================= */
380 /* find the first section or return NODENOTFOUND */
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
)
394 *section
= rc_section
;
395 return (FRU_SUCCESS
);
398 /* and if this is not good keep trying to find a peer which */
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
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
) {
424 if ((err
= find_first_section(handle
, §_node
)) != FRU_SUCCESS
) {
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
,
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) {
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
,
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
,
464 sizeof (protection
)))
466 return (map_plugin_err(rc
));
468 hw_desc
->all_bits
= 0;
469 hw_desc
->field
.read_only
= protection
;
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
, §_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.
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
,
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
) {
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
,
545 /* Peer property not found is ok */
546 if (rc
!= PICL_PROPNOTFOUND
) {
547 return (map_plugin_err(rc
));
551 return (FRU_SUCCESS
);
554 /* ========================================================================= */
556 fpt_get_seg_list(fru_treehdl_t handle
, fru_strlist_t
*list
)
559 picl_nodehdl_t sect_node
;
560 fru_strlist_t rc_list
;
564 if ((err
= update_data_nodes(TREEHDL_TO_PICLHDL(handle
)))
569 if ((err
= find_first_section(TREEHDL_TO_PICLHDL(handle
), §_node
))
574 /* while there are sections. */
575 while (err
== FRU_SUCCESS
) {
576 if ((err
= add_segs_for_section(sect_node
, &rc_list
))
578 fru_destroy_strlist(&rc_list
);
581 err
= find_next_section(sect_node
, §_node
);
584 list
->num
= rc_list
.num
;
585 list
->strs
= rc_list
.strs
;
587 return (FRU_SUCCESS
);
590 /* ========================================================================= */
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
;
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
)
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
,
616 &size
, sizeof (size
))) != PICL_SUCCESS
) {
617 return (map_plugin_err(picl_err
));
620 if ((picl_err
= ptree_get_propval_by_name(seg_node
,
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);
630 def
->address
= address
;
631 def
->hw_desc
= hw_desc
;
633 return (FRU_SUCCESS
);
636 /* ========================================================================= */
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
), §ion
))
653 if ((picl_err
= ptree_get_propval_by_name(section
,
654 PICL_PROP_ADD_SEGMENT
, &dummy
, sizeof (dummy
)))
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
, §ion
) == FRU_SUCCESS
);
664 return (map_plugin_err(picl_err
));
667 /* ========================================================================= */
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
;
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
) {
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 /* ========================================================================= */
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
;
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
) {
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
))
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
))),
733 picl_err
= ptree_update_propval(add_prop
, buffer
, buf_size
);
735 return (map_plugin_err(picl_err
));
738 /* ========================================================================= */
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
) {
759 /* get the number of tags and allocate array for them */
760 if ((picl_err
= ptree_get_propval_by_name(seg_node
,
763 sizeof (total_tags
))) != PICL_SUCCESS
) {
764 return (map_plugin_err(picl_err
));
767 if (total_tags
== 0) {
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
) {
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
) {
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
) {
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
) {
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"
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
;
825 picl_prophdl_t tagTable
= 0;
826 int picl_err
= PICL_SUCCESS
;
827 picl_nodehdl_t tmp_seg
;
831 if ((err
= get_segment_node(TREEHDL_TO_PICLHDL(handle
), segment
,
832 &tmp_seg
, &hw_desc
, IGN_CORRUPT_NO
)) != FRU_SUCCESS
) {
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)) {
853 return (FRU_SUCCESS
);
855 picl_err
= ptree_get_next_by_col(tagTable
, &tagTable
);
858 return (map_plugin_err(picl_err
));
861 /* ========================================================================= */
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
;
873 picl_prophdl_t tagHdl
;
875 if ((err
= get_tag_handle(TREEHDL_TO_PICLHDL(handle
), seg_name
,
876 tag
, instance
, &seg
, &tagHdl
)) != FRU_SUCCESS
) {
880 if ((picl_err
= ptree_get_next_by_row(tagHdl
, &tagHdl
))
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
))
894 return (map_plugin_err(picl_err
));
899 return (FRU_SUCCESS
);
902 /* ========================================================================= */
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
;
912 picl_prophdl_t tagHdl
;
914 if ((rc
= get_tag_handle(TREEHDL_TO_PICLHDL(handle
), seg_name
,
915 tag
, instance
, &seg
, &tagHdl
)) != FRU_SUCCESS
) {
919 if ((picl_err
= ptree_get_next_by_row(tagHdl
, &tagHdl
))
921 return (map_plugin_err(picl_err
));
924 if ((picl_err
= ptree_update_propval(tagHdl
, data
, data_len
))
926 return (map_plugin_err(picl_err
));
929 return (FRU_SUCCESS
);
932 /* ========================================================================= */
934 fpt_delete_tag(fru_treehdl_t handle
, const char *seg_name
, fru_tag_t tag
,
937 fru_errno_t rc
= FRU_SUCCESS
;
938 int picl_err
= PICL_SUCCESS
;
940 picl_nodehdl_t segHdl
;
941 picl_prophdl_t tagHdl
;
944 if ((rc
= get_tag_handle(TREEHDL_TO_PICLHDL(handle
), seg_name
,
945 tag
, instance
, &segHdl
, &tagHdl
)) != FRU_SUCCESS
) {
950 tag
.raw_data
&= FRUDATA_DELETE_TAG_MASK
;
951 tag
.raw_data
|= FRUDATA_DELETE_TAG_KEY
;
954 picl_err
= ptree_update_propval(tagHdl
, (void *)&(tag
.raw_data
),
955 sizeof (tag
.raw_data
));
956 return (map_plugin_err(picl_err
));
959 /* ========================================================================= */
961 fpt_for_each_segment(fru_treehdl_t treenode
,
962 int (*function
)(fru_treeseghdl_t segment
, 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
),
973 if ((status
= update_data_nodes(container
)) != FRU_SUCCESS
)
976 /* process each section */
977 for (status
= ptree_get_propval_by_name(container
, PICL_PROP_CHILD
,
978 §ion
, sizeof (section
));
979 status
== PICL_SUCCESS
;
980 status
= ptree_get_propval_by_name(section
, PICL_PROP_PEER
,
984 if (cmp_class_name(section
, PICL_CLASS_SECTION
) != FRU_SUCCESS
)
987 if ((status
= ptree_get_propval_by_name(section
,
988 PICL_PROP_NUM_SEGMENTS
,
990 sizeof (num_segments
)))
991 == PICL_PROPNOTFOUND
) {
993 } else if (status
!= PICL_SUCCESS
) {
994 saved_status
= map_plugin_err(status
);
996 } else if (num_segments
== 0) {
1000 /* process each segment */
1001 for (status
= ptree_get_propval_by_name(section
,
1005 status
== PICL_SUCCESS
;
1006 status
= ptree_get_propval_by_name(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
),
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 /* ========================================================================= */
1031 fpt_get_segment_name(fru_treeseghdl_t segment
, char **name
)
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
))
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
))
1059 return (map_plugin_err(status
));
1064 return (FRU_SUCCESS
);
1067 /* ========================================================================= */
1069 fpt_for_each_packet(fru_treeseghdl_t treesegment
,
1070 int (*function
)(fru_tag_t
*tag
, 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
;
1090 if ((status
= ptree_get_propval_by_name(segment
, PICL_PROP_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
))
1110 if (((status
= ptree_get_propval(packet
, &tag
, sizeof (tag
)))
1112 ((status
= ptree_get_next_by_row(packet
, &payloadh
))
1114 ((status
= ptree_get_propinfo(payloadh
, &propinfo
))
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
));
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
,
1134 != FRU_SUCCESS
) return (status
);
1137 if (status
== PICL_ENDOFLIST
)
1138 return (FRU_SUCCESS
);
1140 return (map_plugin_err(status
));
1143 /* ========================================================================= */
1146 initialize(int argc
, char **argv
)
1148 return (FRU_SUCCESS
);
1151 /* ========================================================================= */
1155 return (FRU_SUCCESS
);
1158 /* ========================================================================= */
1159 /* object for libfru to link to */
1160 fru_datasource_t data_source
=
1169 fpt_get_name_from_hdl
,
1175 fpt_for_each_segment
,
1176 fpt_get_segment_name
,