4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
37 #include <sys/utsname.h>
38 #include <sys/systeminfo.h>
39 #include <libnvpair.h>
41 #include "fru_data_impl.h"
43 #include "picld_pluginutil.h"
45 #pragma init(frudata_plugin_register) /* .init section */
47 static void frudata_plugin_init(void);
48 static void frudata_plugin_fini(void);
49 static container_tbl_t
*container_table
[TABLE_SIZE
];
53 * calling thread should hold the cont_tbl_lock during the course
54 * of container table lookup. release the cont_tbl_lock on lookup
55 * failure or on the condition wait.
57 * thread holding the container object rwlock should release lock
58 * and signal to unblock threads blocked on the condition variable
59 * upon i/o completion.
63 static pthread_mutex_t cont_tbl_lock
= PTHREAD_MUTEX_INITIALIZER
;
65 static int add_row_to_table(hash_obj_t
*, picl_nodehdl_t
,
66 packet_t
*, container_tbl_t
*);
68 static picld_plugin_reg_t frudata_reg_info
= {
69 PICLD_PLUGIN_VERSION_1
,
70 PICLD_PLUGIN_NON_CRITICAL
,
72 frudata_plugin_init
, /* init entry point */
73 frudata_plugin_fini
/* cleanup entry point */
76 /* initialization function */
78 frudata_plugin_register(void)
80 /* register plugin with daemon */
81 if (picld_plugin_register(&frudata_reg_info
) != PICL_SUCCESS
) {
82 syslog(LOG_ERR
, "SUNW_piclfrudata plugin registration failed");
87 map_access_err(int err
)
91 return (PICL_PROPEXISTS
);
93 return (PICL_NOSPACE
);
95 return (PICL_PERMDENIED
);
97 return (PICL_PROPEXISTS
);
99 return (PICL_FAILURE
);
104 * unlock_container_lock() should be always called by the thread holding the
105 * container object lock. it will signal block thread waiting on the condition
110 unlock_container_lock(container_tbl_t
*cont_hash
)
112 (void) pthread_rwlock_unlock(&cont_hash
->rwlock
);
113 (void) pthread_mutex_lock(&cont_tbl_lock
);
114 (void) pthread_cond_signal(&cont_hash
->cond_var
);
115 (void) pthread_mutex_unlock(&cont_tbl_lock
);
119 /* volatile callback read routine */
122 frudata_read_callback(ptree_rarg_t
*rarg
, void *buf
)
124 return (PICL_SUCCESS
);
128 * called to get hash object for specified node and object type from
131 static container_tbl_t
*
132 lookup_container_table(picl_nodehdl_t nodehdl
, int object_type
)
135 int retval
= PICL_SUCCESS
;
136 container_tbl_t
*first_hash
;
137 container_tbl_t
*next_hash
;
138 picl_nodehdl_t parenthdl
= 0;
140 switch (object_type
) {
142 retval
= ptree_get_propval_by_name(nodehdl
, PICL_PROP_PARENT
,
143 &parenthdl
, sizeof (picl_nodehdl_t
));
146 retval
= ptree_get_propval_by_name(nodehdl
, PICL_PROP_PARENT
,
147 &parenthdl
, sizeof (picl_nodehdl_t
));
148 retval
= ptree_get_propval_by_name(parenthdl
, PICL_PROP_PARENT
,
149 &parenthdl
, sizeof (picl_nodehdl_t
));
151 case CONTAINER_NODE
:
158 if (retval
!= PICL_SUCCESS
) {
162 index_to_hash
= (parenthdl
% TABLE_SIZE
);
164 first_hash
= container_table
[index_to_hash
];
166 for (next_hash
= first_hash
; next_hash
!= NULL
;
167 next_hash
= next_hash
->next
) {
168 if (parenthdl
== next_hash
->picl_hdl
) {
176 lock_readwrite_lock(container_tbl_t
*cont_obj
, int operation
)
178 /* if write operation */
179 if (operation
== PICL_WRITE
) {
180 return (pthread_rwlock_trywrlock(&cont_obj
->rwlock
));
183 return (pthread_rwlock_tryrdlock(&cont_obj
->rwlock
));
187 * lock the container table, do lookup for the container object
188 * in the container table. if container object found try to lock
189 * the container object, if lock on container object is busy wait
190 * on condition variable till the thread holding the container
191 * object lock signal it.
194 static container_tbl_t
*
195 lock_container_lock(picl_nodehdl_t nodehdl
, int object_type
, int operation
)
197 container_tbl_t
*cont_obj
= NULL
;
199 (void) pthread_mutex_lock(&cont_tbl_lock
);
201 while (((cont_obj
= lookup_container_table(nodehdl
, object_type
)) !=
202 NULL
) && (lock_readwrite_lock(cont_obj
, operation
) == EBUSY
)) {
203 pthread_cond_wait(&cont_obj
->cond_var
, &cont_tbl_lock
);
206 (void) pthread_mutex_unlock(&cont_tbl_lock
);
212 lookup_node_object(picl_nodehdl_t nodehdl
, int object_type
,
213 container_tbl_t
*cont_tbl
)
216 hash_obj_t
*first_hash
;
217 hash_obj_t
*next_hash
;
220 index_to_hash
= (nodehdl
% TABLE_SIZE
);
222 first_hash
= &cont_tbl
->hash_obj
[index_to_hash
];
224 for (next_hash
= first_hash
->next
; next_hash
!= NULL
;
225 next_hash
= next_hash
->next
) {
226 if ((nodehdl
== next_hash
->picl_hdl
) &&
227 (object_type
== next_hash
->object_type
)) {
235 * called to add newly created container hash table into container hash table.
239 add_tblobject_to_container_tbl(container_tbl_t
*cont_tbl
)
243 hash_obj_t
*hash_ptr
;
245 index_to_hash
= ((cont_tbl
->picl_hdl
) % TABLE_SIZE
);
247 cont_tbl
->next
= container_table
[index_to_hash
];
248 container_table
[index_to_hash
] = cont_tbl
;
249 hash_ptr
= cont_tbl
->hash_obj
;
251 /* initialize the bucket of this container hash table. */
253 for (cnt
= 0; cnt
< TABLE_SIZE
; cnt
++) {
254 hash_ptr
->next
= NULL
;
255 hash_ptr
->prev
= NULL
;
258 if (cont_tbl
->next
!= NULL
) {
259 cont_tbl
->next
->prev
= cont_tbl
;
264 add_nodeobject_to_hashtable(hash_obj_t
*hash_obj
, container_tbl_t
*cont_tbl
)
267 hash_obj_t
*hash_table
;
269 index_to_hash
= ((hash_obj
->picl_hdl
) % TABLE_SIZE
);
270 hash_table
= &cont_tbl
->hash_obj
[index_to_hash
];
272 hash_obj
->next
= hash_table
->next
;
273 hash_table
->next
= hash_obj
;
275 if (hash_obj
->next
!= NULL
) {
276 hash_obj
->next
->prev
= hash_obj
;
280 static container_tbl_t
*
281 alloc_container_table(picl_nodehdl_t nodehdl
)
283 container_tbl_t
*cont_tbl
;
285 cont_tbl
= malloc(sizeof (container_tbl_t
));
286 if (cont_tbl
== NULL
) {
290 cont_tbl
->picl_hdl
= nodehdl
;
292 cont_tbl
->hash_obj
= malloc(sizeof (hash_obj_t
[TABLE_SIZE
]));
293 cont_tbl
->next
= NULL
;
294 cont_tbl
->prev
= NULL
;
296 if (cont_tbl
->hash_obj
== NULL
) {
297 (void) free(cont_tbl
);
301 (void) pthread_rwlock_init(&cont_tbl
->rwlock
, NULL
);
302 (void) pthread_cond_init(&cont_tbl
->cond_var
, NULL
);
308 * called to allocate container node object for container property and a
313 alloc_container_node_object(picl_nodehdl_t nodehdl
)
315 hash_obj_t
*hash_obj
;
316 fru_access_hdl_t acc_hdl
;
317 container_node_t
*cont_node
;
319 /* open the container (call fruaccess) */
320 acc_hdl
= fru_open_container(nodehdl
);
321 if (acc_hdl
== (container_hdl_t
)0) {
325 /* allocate container node object */
326 cont_node
= malloc(sizeof (container_node_t
));
327 if (cont_node
== NULL
) {
331 /* allocate container hash object */
332 hash_obj
= malloc(sizeof (hash_obj_t
));
333 if (hash_obj
== NULL
) {
334 (void) free(cont_node
);
338 cont_node
->cont_hdl
= acc_hdl
; /* fruaccess handle */
339 cont_node
->section_list
= NULL
;
340 hash_obj
->picl_hdl
= nodehdl
; /* picl node handle */
341 hash_obj
->object_type
= CONTAINER_NODE
;
342 hash_obj
->u
.cont_node
= cont_node
;
343 hash_obj
->next
= NULL
;
344 hash_obj
->prev
= NULL
;
350 * called to allocate node object for section node.
354 alloc_section_node_object(picl_nodehdl_t nodehdl
, section_t
*section
)
356 hash_obj_t
*hash_obj
;
357 section_node_t
*sec_node
;
359 /* allocate section node object */
360 sec_node
= malloc(sizeof (section_node_t
));
361 if (sec_node
== NULL
) {
365 /* allocate section hash object */
366 hash_obj
= malloc(sizeof (hash_obj_t
));
367 if (hash_obj
== NULL
) {
368 (void) free(sec_node
);
372 sec_node
->section_hdl
= section
->handle
; /* fruaccess hdl. */
373 sec_node
->segment_list
= NULL
;
374 sec_node
->next
= NULL
;
375 sec_node
->num_of_segment
= -1;
377 hash_obj
->picl_hdl
= nodehdl
; /* picl node handle */
378 hash_obj
->object_type
= SECTION_NODE
;
379 hash_obj
->u
.sec_node
= sec_node
;
380 hash_obj
->next
= NULL
;
381 hash_obj
->prev
= NULL
;
387 * called to allocate segment node object.
391 alloc_segment_node_object(picl_nodehdl_t nodehdl
, segment_t
*segment
)
393 hash_obj_t
*hash_obj
;
394 segment_node_t
*seg_node
;
396 /* allocate segment node object */
397 seg_node
= malloc(sizeof (segment_node_t
));
398 if (seg_node
== NULL
) {
402 /* allocate segment hash object */
403 hash_obj
= malloc(sizeof (hash_obj_t
));
404 if (hash_obj
== NULL
) {
409 /* fruaccess handle */
410 seg_node
->segment_hdl
= segment
->handle
;
411 seg_node
->packet_list
= NULL
;
412 seg_node
->next
= NULL
;
413 seg_node
->num_of_pkt
= -1;
415 /* picl node handle */
416 hash_obj
->picl_hdl
= nodehdl
;
417 hash_obj
->object_type
= SEGMENT_NODE
;
418 hash_obj
->u
.seg_node
= seg_node
;
419 hash_obj
->next
= NULL
;
420 hash_obj
->prev
= NULL
;
426 * called to allocate node object for packet.
430 alloc_packet_node_object(picl_nodehdl_t nodehdl
, packet_t
*packet
)
432 hash_obj_t
*hash_obj
;
433 packet_node_t
*pkt_node
;
435 /* allocate packet node object */
436 pkt_node
= malloc(sizeof (packet_node_t
));
437 if (pkt_node
== NULL
) {
441 /* allocate packet hash object */
442 hash_obj
= malloc(sizeof (hash_obj_t
));
443 if (hash_obj
== NULL
) {
448 /* fruaccess handle */
449 pkt_node
->pkt_handle
= packet
->handle
;
450 pkt_node
->next
= NULL
;
452 hash_obj
->picl_hdl
= nodehdl
; /* picl node handle */
453 hash_obj
->object_type
= PACKET_NODE
;
454 hash_obj
->u
.pkt_node
= pkt_node
;
455 hash_obj
->next
= NULL
;
456 hash_obj
->prev
= NULL
;
461 /* add new section hash object to the section list */
463 add_to_section_list(hash_obj_t
*container_hash
, hash_obj_t
*sect_hash
)
465 hash_obj_t
*next_hash
;
467 sect_hash
->u
.sec_node
->container_hdl
= container_hash
->picl_hdl
;
468 if (container_hash
->u
.cont_node
->section_list
== NULL
) {
469 container_hash
->u
.cont_node
->section_list
= sect_hash
;
473 for (next_hash
= container_hash
->u
.cont_node
->section_list
;
474 next_hash
->u
.sec_node
->next
!= NULL
;
475 next_hash
= next_hash
->u
.sec_node
->next
) {
479 next_hash
->u
.sec_node
->next
= sect_hash
;
482 /* add new segment hash object to the existing list */
485 add_to_segment_list(hash_obj_t
*parent_obj
, hash_obj_t
*child_obj
)
487 hash_obj_t
*next_hash
;
489 child_obj
->u
.seg_node
->sec_nodehdl
= parent_obj
->picl_hdl
;
490 if (parent_obj
->u
.sec_node
->segment_list
== NULL
) {
491 parent_obj
->u
.sec_node
->segment_list
= child_obj
;
495 for (next_hash
= parent_obj
->u
.sec_node
->segment_list
;
496 next_hash
->u
.seg_node
->next
!= NULL
;
497 next_hash
= next_hash
->u
.seg_node
->next
) {
500 next_hash
->u
.seg_node
->next
= child_obj
;
504 * called to add packet node object to the existing packet list.
507 add_to_packet_list(hash_obj_t
*parent_obj
, hash_obj_t
*child_obj
)
509 hash_obj_t
*next_hash
;
511 if (parent_obj
->u
.seg_node
->packet_list
== NULL
) {
512 parent_obj
->u
.seg_node
->packet_list
= child_obj
;
516 for (next_hash
= parent_obj
->u
.seg_node
->packet_list
;
517 next_hash
->u
.pkt_node
->next
!= NULL
;
518 next_hash
= next_hash
->u
.pkt_node
->next
) {
521 next_hash
->u
.pkt_node
->next
= child_obj
;
525 * free the packet hash list.
529 free_packet_list(hash_obj_t
*hash_obj
, container_tbl_t
*cont_tbl
)
531 hash_obj_t
*next_obj
;
532 hash_obj_t
*free_obj
;
534 /* packet hash object list */
535 next_obj
= hash_obj
->u
.seg_node
->packet_list
;
536 while (next_obj
!= NULL
) {
538 next_obj
= next_obj
->u
.pkt_node
->next
;
539 if (free_obj
->prev
== NULL
) { /* first node object */
540 cont_tbl
->hash_obj
[(free_obj
->picl_hdl
%
541 TABLE_SIZE
)].next
= free_obj
->next
;
542 if (free_obj
->next
!= NULL
) {
543 free_obj
->next
->prev
= NULL
;
546 free_obj
->prev
->next
= free_obj
->next
;
547 if (free_obj
->next
!= NULL
) {
548 free_obj
->next
->prev
= free_obj
->prev
;
552 free(free_obj
->u
.pkt_node
);
555 hash_obj
->u
.seg_node
->packet_list
= NULL
;
559 * free the segment hash node object.
563 free_segment_node(hash_obj_t
*hash_obj
, picl_nodehdl_t nodehdl
,
564 container_tbl_t
*cont_tbl
)
566 hash_obj_t
*prev_hash_obj
;
567 hash_obj_t
*next_obj
;
569 /* segment hash object list */
570 next_obj
= hash_obj
->u
.sec_node
->segment_list
;
571 if (next_obj
== NULL
) {
575 /* find the segment hash from the segment list to be deleted. */
576 if (next_obj
->picl_hdl
== nodehdl
) {
577 hash_obj
->u
.sec_node
->segment_list
=
578 next_obj
->u
.seg_node
->next
;
580 while (next_obj
!= NULL
) {
581 if (next_obj
->picl_hdl
!= nodehdl
) {
582 prev_hash_obj
= next_obj
;
583 next_obj
= next_obj
->u
.seg_node
->next
;
585 prev_hash_obj
->u
.seg_node
->next
=
586 next_obj
->u
.seg_node
->next
;
591 if (next_obj
== NULL
) {
597 if (next_obj
->prev
== NULL
) {
598 cont_tbl
->hash_obj
[(next_obj
->picl_hdl
% TABLE_SIZE
)].next
=
600 if (next_obj
->next
!= NULL
)
601 next_obj
->next
->prev
= NULL
;
603 next_obj
->prev
->next
= next_obj
->next
;
604 if (next_obj
->next
!= NULL
) {
605 next_obj
->next
->prev
= next_obj
->prev
;
609 free_packet_list(next_obj
, cont_tbl
);
610 free(next_obj
->u
.seg_node
);
616 * Description : frudata_delete_segment is called when volatile property
617 * delete_segment under class segment is accessed.
619 * Arguments : ptree_warg_t is holds node handle of segment node and property
620 * handle of delete_segment property.
625 frudata_delete_segment(ptree_warg_t
*warg
, const void *buf
)
633 segment_t
*seg_buffer
;
634 hash_obj_t
*seg_hash
;
635 hash_obj_t
*pkt_hash
;
636 hash_obj_t
*hash_obj
;
638 picl_nodehdl_t sec_nodehdl
;
639 container_tbl_t
*cont_tbl
;
640 fru_access_hdl_t seg_acc_hdl
;
641 fru_access_hdl_t new_sec_acc_hdl
;
643 cont_tbl
= lock_container_lock(warg
->nodeh
, SEGMENT_NODE
, PICL_WRITE
);
645 return (PICL_FAILURE
);
649 hash_obj
= lookup_node_object(warg
->nodeh
, SEGMENT_NODE
, cont_tbl
);
650 if (hash_obj
== NULL
) {
651 unlock_container_lock(cont_tbl
);
652 return (PICL_FAILURE
);
655 /* fruaccess segment handle */
656 seg_acc_hdl
= hash_obj
->u
.seg_node
->segment_hdl
;
658 /* call fruaccess to get new section handle */
659 if (fru_delete_segment(seg_acc_hdl
, &new_sec_acc_hdl
, &warg
->cred
)
661 unlock_container_lock(cont_tbl
);
662 return (map_access_err(errno
));
665 if (ptree_delete_node(warg
->nodeh
) != PICL_SUCCESS
) {
666 unlock_container_lock(cont_tbl
);
667 return (PICL_FAILURE
);
670 if (ptree_destroy_node(warg
->nodeh
) != PICL_SUCCESS
) {
671 unlock_container_lock(cont_tbl
);
672 return (PICL_FAILURE
);
676 /* get section node handle */
677 sec_nodehdl
= hash_obj
->u
.seg_node
->sec_nodehdl
;
678 /* get section hash */
679 hash_obj
= lookup_node_object(sec_nodehdl
, SECTION_NODE
, cont_tbl
);
680 if (hash_obj
== NULL
) {
681 unlock_container_lock(cont_tbl
);
682 return (PICL_FAILURE
);
685 free_segment_node(hash_obj
, warg
->nodeh
, cont_tbl
);
687 hash_obj
->u
.sec_node
->num_of_segment
= 0;
689 /* call fruaccess with new section handle */
690 num_of_segment
= fru_get_num_segments(new_sec_acc_hdl
, &warg
->cred
);
691 if (num_of_segment
<= 0) {
692 unlock_container_lock(cont_tbl
);
693 return (PICL_SUCCESS
);
696 seg_buffer
= alloca(sizeof (segment_t
) * num_of_segment
);
697 if (seg_buffer
== NULL
) {
698 unlock_container_lock(cont_tbl
);
699 return (PICL_FAILURE
);
702 /* get all the segments */
703 retval
= fru_get_segments(new_sec_acc_hdl
, seg_buffer
,
704 num_of_segment
, &warg
->cred
);
706 unlock_container_lock(cont_tbl
);
707 return (PICL_FAILURE
);
710 seg_hash
= hash_obj
->u
.sec_node
->segment_list
;
711 if (seg_hash
== NULL
) {
712 unlock_container_lock(cont_tbl
);
713 return (PICL_SUCCESS
);
716 /* rebuild the segment list */
717 for (count
= 0; count
< num_of_segment
; count
++) {
718 desc
= (fru_segdesc_t
*)&seg_buffer
[count
].descriptor
;
719 if (!(desc
->field
.field_perm
& SEGMENT_READ
)) {
720 seg_hash
= seg_hash
->u
.seg_node
->next
;
724 if (desc
->field
.opaque
) {
725 seg_hash
= seg_hash
->u
.seg_node
->next
;
729 hash_obj
->u
.sec_node
->num_of_segment
++;
731 seg_hash
->u
.seg_node
->segment_hdl
= seg_buffer
[count
].handle
;
733 num_of_pkt
= fru_get_num_packets(seg_buffer
[count
].handle
,
735 if (num_of_pkt
<= 0) {
736 seg_hash
= seg_hash
->u
.seg_node
->next
;
740 pkt_buf
= alloca(sizeof (packet_t
) * num_of_pkt
);
741 if (pkt_buf
== NULL
) {
742 unlock_container_lock(cont_tbl
);
743 return (PICL_FAILURE
);
746 retval
= fru_get_packets(seg_buffer
[count
].handle
, pkt_buf
,
747 num_of_pkt
, &warg
->cred
);
749 seg_hash
= seg_hash
->u
.seg_node
->next
;
753 pkt_hash
= seg_hash
->u
.seg_node
->packet_list
;
754 if (pkt_hash
== NULL
) {
755 seg_hash
= seg_hash
->u
.seg_node
->next
;
759 /* rebuild the packet list */
760 for (pkt_cnt
= 0; pkt_cnt
< num_of_pkt
; pkt_cnt
++) {
761 pkt_hash
->u
.pkt_node
->pkt_handle
=
762 pkt_buf
[pkt_cnt
].handle
;
763 pkt_hash
= pkt_hash
->u
.pkt_node
->next
;
766 seg_hash
= seg_hash
->u
.seg_node
->next
;
767 if (seg_hash
== NULL
) {
772 /* updated with new section handle */
773 hash_obj
->u
.sec_node
->section_hdl
= new_sec_acc_hdl
;
775 unlock_container_lock(cont_tbl
);
777 return (PICL_SUCCESS
);
781 * Description : frudata_read_payload is called when volatile property
784 * Arguments : ptree_rarg_t holds node handle of the table property.
785 * and property handle of the payload cell.
786 * p_buf contains payload data when function returns.
788 * Returns : PICL_SUCCESS on success.
789 * PICL_FAILURE on failure.
793 frudata_read_payload(ptree_rarg_t
*rarg
, void *buf
)
796 hash_obj_t
*hash_obj
;
797 fru_access_hdl_t pkt_acc_hdl
;
798 container_tbl_t
*cont_tbl
;
801 cont_tbl
= lock_container_lock(rarg
->nodeh
, SEGMENT_NODE
, PICL_READ
);
803 return (PICL_FAILURE
);
806 hash_obj
= lookup_node_object(rarg
->proph
, PACKET_NODE
, cont_tbl
);
807 if (hash_obj
== NULL
) {
808 unlock_container_lock(cont_tbl
);
809 return (PICL_FAILURE
);
812 pkt_acc_hdl
= hash_obj
->u
.pkt_node
->pkt_handle
;
814 num_bytes
= fru_get_payload(pkt_acc_hdl
, buf
,
815 hash_obj
->u
.pkt_node
->paylen
, &rarg
->cred
);
816 if (num_bytes
!= hash_obj
->u
.pkt_node
->paylen
) {
817 unlock_container_lock(cont_tbl
);
818 return (PICL_FAILURE
);
821 unlock_container_lock(cont_tbl
);
823 return (PICL_SUCCESS
);
827 * Description : frudata_write_payload is called when payload property cell
830 * Arguments : ptree_warg_t holds node handle of the packet-table.
831 * and property handle of the payload cell.
832 * p_buf contains payload data.
834 * Returns : PICL_SUCCESS on success.
839 frudata_write_payload(ptree_warg_t
*warg
, const void *buf
)
842 hash_obj_t
*hash_obj
;
843 fru_access_hdl_t pkt_acc_hdl
;
844 container_tbl_t
*cont_tbl
;
846 cont_tbl
= lock_container_lock(warg
->nodeh
, SEGMENT_NODE
, PICL_WRITE
);
848 return (PICL_FAILURE
);
851 hash_obj
= lookup_node_object(warg
->proph
, PACKET_NODE
, cont_tbl
);
852 if (hash_obj
== NULL
) {
853 unlock_container_lock(cont_tbl
);
854 return (PICL_FAILURE
);
857 pkt_acc_hdl
= hash_obj
->u
.pkt_node
->pkt_handle
;
859 retval
= fru_update_payload(pkt_acc_hdl
, buf
,
860 hash_obj
->u
.pkt_node
->paylen
,
861 &pkt_acc_hdl
, &warg
->cred
);
863 unlock_container_lock(cont_tbl
);
864 return (map_access_err(errno
));
867 hash_obj
->u
.pkt_node
->pkt_handle
= pkt_acc_hdl
;
869 unlock_container_lock(cont_tbl
);
871 return (PICL_SUCCESS
);
875 * callback volatile function is called when tag volatile property
876 * is accessed. this routine holds a read lock over the hash table
877 * and do a lookup over the property handle i.e property handle of
878 * the tag property passed in rarg parameter.
879 * tag value is copied into the buffer (void *buf).
883 frudata_read_tag(ptree_rarg_t
*rarg
, void *buf
)
886 hash_obj_t
*hash_obj
;
887 picl_prophdl_t rowproph
;
888 container_tbl_t
*cont_tbl
;
890 cont_tbl
= lock_container_lock(rarg
->nodeh
, SEGMENT_NODE
, PICL_READ
);
892 return (PICL_FAILURE
);
895 retval
= ptree_get_next_by_row(rarg
->proph
, &rowproph
);
896 if (retval
!= PICL_SUCCESS
) {
897 unlock_container_lock(cont_tbl
);
901 hash_obj
= lookup_node_object(rowproph
, PACKET_NODE
, cont_tbl
);
902 if (hash_obj
== NULL
) {
903 unlock_container_lock(cont_tbl
);
904 return (PICL_FAILURE
);
907 (void) memcpy(buf
, &hash_obj
->u
.pkt_node
->tag
, sizeof (tag_t
));
909 unlock_container_lock(cont_tbl
);
910 return (PICL_SUCCESS
);
915 * Description : create_packet_table() is called by fru_delete_packet_row(),
916 * to create a packet-table volatile property. it's called after
917 * deleting the packet-table. fru_delete_packet_row() calls
918 * frudata_read_packet_table() to add rows into the table.
922 create_packet_table(picl_nodehdl_t seghdl
, picl_prophdl_t
*thdl
)
925 picl_prophdl_t tblhdl
;
926 picl_nodehdl_t prophdl
;
927 ptree_propinfo_t prop
;
929 retval
= ptree_create_table(&tblhdl
);
930 if (retval
!= PICL_SUCCESS
) {
934 prop
.version
= PTREE_PROPINFO_VERSION
;
935 prop
.piclinfo
.type
= PICL_PTYPE_TABLE
;
936 prop
.piclinfo
.accessmode
= PICL_READ
|PICL_WRITE
;
937 prop
.piclinfo
.size
= sizeof (picl_prophdl_t
);
940 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_PACKET_TABLE
);
942 retval
= ptree_create_and_add_prop(seghdl
, &prop
, &tblhdl
,
944 if (retval
!= PICL_SUCCESS
) {
948 /* hold the table handle */
951 return (PICL_SUCCESS
);
955 * Description : frudata_delete_packet is called when write operation is
956 * performed on tag volatile property.
959 * Arguments : ptree_warg_t holds node handle to the segment node.
960 * and property handle of the tag cell in the packet table to be
962 * buf contains the tag data + plus DELETE_KEY_TAG
964 * Returns : PICL_SUCCESS on success
969 frudata_delete_packet(ptree_warg_t
*warg
, const void *buf
)
976 hash_obj_t
*seg_hash_obj
;
977 hash_obj_t
*pkt_hash_obj
;
978 container_tbl_t
*cont_tbl
;
979 picl_prophdl_t tblhdl
;
980 picl_prophdl_t rowproph
;
981 fru_access_hdl_t new_seg_acc_hdl
;
983 cont_tbl
= lock_container_lock(warg
->nodeh
, SEGMENT_NODE
, PICL_WRITE
);
985 return (PICL_FAILURE
);
988 /* get the payload property handle */
989 retval
= ptree_get_next_by_row(warg
->proph
, &rowproph
);
990 if (retval
!= PICL_SUCCESS
) {
991 unlock_container_lock(cont_tbl
);
995 /* do lookup on payload property handle */
996 pkt_hash_obj
= lookup_node_object(rowproph
, PACKET_NODE
, cont_tbl
);
997 if (pkt_hash_obj
== NULL
) {
998 unlock_container_lock(cont_tbl
);
999 return (PICL_FAILURE
);
1002 /* verify the tag */
1003 tag
= pkt_hash_obj
->u
.pkt_node
->tag
.raw_data
;
1004 tag
&= FRUDATA_DELETE_TAG_MASK
;
1005 tag
|= FRUDATA_DELETE_TAG_KEY
;
1006 if (*(uint64_t *)buf
!= tag
) {
1007 unlock_container_lock(cont_tbl
);
1008 return (PICL_FAILURE
);
1011 /* call fruaccess module */
1012 retval
= fru_delete_packet(pkt_hash_obj
->u
.pkt_node
->pkt_handle
,
1013 &new_seg_acc_hdl
, &warg
->cred
);
1015 unlock_container_lock(cont_tbl
);
1016 return (map_access_err(errno
));
1019 /* delete the packet table */
1020 retval
= ptree_get_prop_by_name(warg
->nodeh
, PICL_PROP_PACKET_TABLE
,
1022 if (retval
!= PICL_SUCCESS
) {
1023 unlock_container_lock(cont_tbl
);
1027 retval
= ptree_delete_prop(tblhdl
);
1028 if (retval
!= PICL_SUCCESS
) {
1029 unlock_container_lock(cont_tbl
);
1033 retval
= ptree_destroy_prop(tblhdl
);
1034 if (retval
!= PICL_SUCCESS
) {
1035 unlock_container_lock(cont_tbl
);
1040 seg_hash_obj
= lookup_node_object(warg
->nodeh
, SEGMENT_NODE
,
1042 if (seg_hash_obj
== NULL
) {
1043 unlock_container_lock(cont_tbl
);
1044 return (PICL_FAILURE
);
1047 /* free all packet hash object */
1048 free_packet_list(seg_hash_obj
, cont_tbl
);
1050 /* recreate the packet table */
1051 retval
= create_packet_table(warg
->nodeh
, &tblhdl
);
1052 if (retval
!= PICL_SUCCESS
) {
1053 unlock_container_lock(cont_tbl
);
1057 seg_hash_obj
->u
.seg_node
->segment_hdl
= new_seg_acc_hdl
;
1059 seg_hash_obj
->u
.seg_node
->num_of_pkt
= 0;
1061 num_of_pkt
= fru_get_num_packets(new_seg_acc_hdl
, &warg
->cred
);
1062 if (num_of_pkt
== -1) {
1063 unlock_container_lock(cont_tbl
);
1064 return (PICL_FAILURE
);
1067 if (num_of_pkt
== 0) {
1068 unlock_container_lock(cont_tbl
);
1069 return (PICL_SUCCESS
);
1072 packet
= alloca(sizeof (packet_t
) * num_of_pkt
);
1073 if (packet
== NULL
) {
1074 unlock_container_lock(cont_tbl
);
1075 return (PICL_FAILURE
);
1078 retval
= fru_get_packets(new_seg_acc_hdl
, packet
,
1079 num_of_pkt
, &warg
->cred
);
1081 unlock_container_lock(cont_tbl
);
1082 return (PICL_FAILURE
);
1085 /* rebuild the packet hash object */
1086 for (count
= 0; count
< num_of_pkt
; count
++) {
1087 (void) add_row_to_table(seg_hash_obj
, tblhdl
, packet
+count
,
1091 seg_hash_obj
->u
.seg_node
->num_of_pkt
= num_of_pkt
;
1093 (void) ptree_update_propval_by_name(warg
->nodeh
, PICL_PROP_NUM_TAGS
,
1094 &num_of_pkt
, sizeof (uint32_t));
1096 unlock_container_lock(cont_tbl
);
1098 return (PICL_SUCCESS
);
1102 * called from frudata_delete_packet(), frudata_add_packet(),
1103 * frudata_read_packet() callback routine to add packet into
1104 * the packet table. it also create hash node object for each
1105 * individual packet and add the object to the packet list.
1109 add_row_to_table(hash_obj_t
*seg_obj
, picl_nodehdl_t tblhdl
, packet_t
*pkt
,
1110 container_tbl_t
*cont_tbl
)
1115 hash_obj_t
*hash_obj
;
1116 fru_tagtype_t tagtype
;
1117 picl_prophdl_t prophdl
[NUM_OF_COL_IN_PKT_TABLE
];
1118 ptree_propinfo_t prop
;
1120 prop
.version
= PTREE_PROPINFO_VERSION
;
1122 prop
.piclinfo
.type
= PICL_PTYPE_BYTEARRAY
;
1123 prop
.piclinfo
.accessmode
= PICL_READ
|PICL_WRITE
|PICL_VOLATILE
;
1124 prop
.piclinfo
.size
= sizeof (fru_tag_t
);
1125 prop
.read
= frudata_read_tag
;
1126 prop
.write
= frudata_delete_packet
;
1128 /* tag property node */
1129 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_TAG
);
1131 paylen
= get_payload_length((void *)&pkt
->tag
);
1133 return (PICL_FAILURE
);
1136 retval
= ptree_create_prop(&prop
, NULL
, &prophdl
[0]);
1137 if (retval
!= PICL_SUCCESS
) {
1142 /* payload property node */
1143 prop
.piclinfo
.type
= PICL_PTYPE_BYTEARRAY
;
1144 prop
.piclinfo
.size
= paylen
;
1145 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_PAYLOAD
);
1146 prop
.piclinfo
.accessmode
= PICL_READ
|PICL_WRITE
|PICL_VOLATILE
;
1147 prop
.read
= frudata_read_payload
;
1148 prop
.write
= frudata_write_payload
;
1150 retval
= ptree_create_prop(&prop
, NULL
, &prophdl
[1]);
1151 if (retval
!= PICL_SUCCESS
) {
1155 hash_obj
= alloc_packet_node_object(prophdl
[1], pkt
);
1156 if (hash_obj
== NULL
) {
1157 return (PICL_FAILURE
);
1160 retval
= ptree_add_row_to_table(tblhdl
, NUM_OF_COL_IN_PKT_TABLE
,
1162 if (retval
!= PICL_SUCCESS
) {
1167 tagtype
= get_tag_type((fru_tag_t
*)&pkt
->tag
);
1168 if (tagtype
== -1) {
1169 return (PICL_FAILURE
);
1172 tag_size
= get_tag_size(tagtype
);
1173 if (tag_size
== (size_t)-1) {
1174 return (PICL_FAILURE
);
1177 hash_obj
->u
.pkt_node
->paylen
= paylen
;
1178 hash_obj
->u
.pkt_node
->tag
.raw_data
= 0;
1179 (void) memcpy(&hash_obj
->u
.pkt_node
->tag
, &pkt
->tag
, tag_size
);
1181 add_nodeobject_to_hashtable(hash_obj
, cont_tbl
);
1183 add_to_packet_list(seg_obj
, hash_obj
);
1185 return (PICL_SUCCESS
);
1189 * called from frudata_read_segment() callback routine. it's called after
1190 * creating the packet table under class segment. this routine reads the
1191 * segment data to get total number of packets in the segments and add
1192 * the tag and payload data into the table. it calls add_row_to_table
1193 * routine to add individual row into the packet table.
1197 frudata_read_packet(picl_nodehdl_t nodeh
, picl_prophdl_t
*tblhdl
,
1198 container_tbl_t
*cont_tbl
, door_cred_t
*cred
)
1204 hash_obj_t
*hash_obj
;
1205 fru_access_hdl_t seg_acc_hdl
;
1207 hash_obj
= lookup_node_object(nodeh
, SEGMENT_NODE
, cont_tbl
);
1208 if (hash_obj
== NULL
) {
1209 return (PICL_FAILURE
);
1212 if (hash_obj
->u
.seg_node
->num_of_pkt
== -1) {
1213 /* get the access handle */
1214 seg_acc_hdl
= hash_obj
->u
.seg_node
->segment_hdl
;
1215 /* get total number of packets */
1216 num_of_pkt
= fru_get_num_packets(seg_acc_hdl
, cred
);
1217 if (num_of_pkt
< 0) {
1218 hash_obj
->u
.seg_node
->num_of_pkt
= 0;
1219 return (map_access_err(errno
));
1222 if (num_of_pkt
== 0) {
1223 hash_obj
->u
.seg_node
->num_of_pkt
= 0;
1227 /* allocate buffer */
1228 packet
= alloca(sizeof (packet_t
) * num_of_pkt
);
1229 if (packet
== NULL
) {
1230 hash_obj
->u
.seg_node
->num_of_pkt
= 0;
1234 /* get all the packet into the packet buffer */
1235 retval
= fru_get_packets(seg_acc_hdl
, packet
, num_of_pkt
, cred
);
1240 /* add payload and tag into the table. */
1241 for (cnt
= 0; cnt
< num_of_pkt
; cnt
++) {
1242 (void) add_row_to_table(hash_obj
, *tblhdl
, packet
+cnt
,
1246 hash_obj
->u
.seg_node
->num_of_pkt
= num_of_pkt
;
1253 * Description : frudata_add_packet is called when add-packet volatile
1254 * property is accessed.
1256 * Arguments : ptree_warg_t holds node handle of the segment node and
1257 * property handle of add-packet property.
1258 * p_buf- contains packet data to be added.
1260 * Return : PICL_SUCCESS on success.
1266 frudata_add_packet(ptree_warg_t
*warg
, const void *buf
)
1275 hash_obj_t
*hash_obj
;
1276 hash_obj_t
*pkt_hash
;
1277 container_tbl_t
*cont_tbl
;
1278 fru_tagtype_t tagtype
;
1279 picl_prophdl_t tblhdl
;
1280 fru_access_hdl_t seg_acc_hdl
;
1281 fru_access_hdl_t new_seg_acc_hdl
;
1283 cont_tbl
= lock_container_lock(warg
->nodeh
, SEGMENT_NODE
, PICL_WRITE
);
1285 return (PICL_FAILURE
);
1288 hash_obj
= lookup_node_object(warg
->nodeh
, SEGMENT_NODE
, cont_tbl
);
1289 if (hash_obj
== NULL
) {
1290 unlock_container_lock(cont_tbl
);
1291 return (PICL_FAILURE
);
1294 seg_acc_hdl
= hash_obj
->u
.seg_node
->segment_hdl
;
1296 tagtype
= get_tag_type((void *)buf
);
1297 if (tagtype
== -1) {
1298 unlock_container_lock(cont_tbl
);
1299 return (PICL_FAILURE
);
1302 tag_size
= get_tag_size(tagtype
);
1303 if (tag_size
== (size_t)-1) {
1304 unlock_container_lock(cont_tbl
);
1305 return (PICL_FAILURE
);
1308 paylen
= get_payload_length((void *)buf
);
1310 unlock_container_lock(cont_tbl
);
1311 return (PICL_FAILURE
);
1315 (void) memcpy(&packet
.tag
, buf
, tag_size
);
1317 retval
= fru_append_packet(seg_acc_hdl
, &packet
, (char *)buf
+ tag_size
,
1318 paylen
, &new_seg_acc_hdl
, &warg
->cred
);
1320 unlock_container_lock(cont_tbl
);
1321 return (map_access_err(errno
));
1324 retval
= ptree_get_propval_by_name(warg
->nodeh
,
1325 PICL_PROP_PACKET_TABLE
, &tblhdl
, sizeof (picl_prophdl_t
));
1326 if (retval
!= PICL_SUCCESS
) {
1327 unlock_container_lock(cont_tbl
);
1330 retval
= add_row_to_table(hash_obj
, tblhdl
, &packet
, cont_tbl
);
1331 if (retval
!= PICL_SUCCESS
) {
1332 unlock_container_lock(cont_tbl
);
1336 num_of_pkt
= fru_get_num_packets(new_seg_acc_hdl
, &warg
->cred
);
1337 if (num_of_pkt
== -1) {
1338 unlock_container_lock(cont_tbl
);
1339 return (PICL_FAILURE
);
1342 pkt_buf
= alloca(sizeof (packet_t
) * num_of_pkt
);
1343 if (pkt_buf
== NULL
) {
1344 unlock_container_lock(cont_tbl
);
1345 return (PICL_FAILURE
);
1348 retval
= fru_get_packets(new_seg_acc_hdl
, pkt_buf
,
1349 num_of_pkt
, &warg
->cred
);
1351 unlock_container_lock(cont_tbl
);
1352 return (PICL_FAILURE
);
1355 pkt_hash
= hash_obj
->u
.seg_node
->packet_list
;
1356 if (pkt_hash
== NULL
) {
1357 unlock_container_lock(cont_tbl
);
1358 return (PICL_FAILURE
);
1361 for (cnt
= 0; cnt
< num_of_pkt
; cnt
++) {
1362 pkt_hash
->u
.pkt_node
->pkt_handle
= pkt_buf
[cnt
].handle
;
1363 pkt_hash
= pkt_hash
->u
.pkt_node
->next
;
1366 hash_obj
->u
.seg_node
->num_of_pkt
= num_of_pkt
;
1368 (void) ptree_update_propval_by_name(warg
->nodeh
, PICL_PROP_NUM_TAGS
,
1369 &num_of_pkt
, sizeof (uint32_t));
1371 unlock_container_lock(cont_tbl
);
1373 return (PICL_SUCCESS
);
1377 freeup(picl_nodehdl_t nodeh
)
1379 (void) ptree_delete_node(nodeh
);
1380 (void) ptree_destroy_node(nodeh
);
1384 * called by frudata_read_segment() and fru_data_add_segment() callback routine.
1385 * it's called to create a segment node and all it's property beneith the
1386 * segment node in the picl tree.
1390 create_segment_node(hash_obj_t
*sec_obj
, picl_nodehdl_t sec_node
,
1391 segment_t
*segment
, container_tbl_t
*cont_tbl
, door_cred_t
*cred
)
1395 char segname
[SEG_NAME_LEN
+ 1];
1396 uint32_t numoftags
= 0;
1397 uint32_t protection
;
1398 hash_obj_t
*hash_obj
;
1399 picl_nodehdl_t nodehdl
;
1400 picl_prophdl_t prophdl
;
1401 picl_nodehdl_t tblhdl
;
1402 ptree_propinfo_t prop
;
1404 (void) strlcpy(segname
, segment
->name
, SEG_NAME_LEN
+ 1);
1405 segname
[SEG_NAME_LEN
] = '\0';
1407 if (!(isprint(segname
[0]) || isprint(segname
[1]))) {
1408 return (PICL_FAILURE
);
1411 if (ptree_create_node(segname
, PICL_CLASS_SEGMENT
, &nodehdl
)
1413 return (PICL_FAILURE
);
1417 /* create property node */
1418 prop
.version
= PTREE_PROPINFO_VERSION
;
1419 prop
.piclinfo
.accessmode
= PICL_READ
;
1423 prop
.piclinfo
.type
= PICL_PTYPE_UNSIGNED_INT
;
1424 prop
.piclinfo
.size
= sizeof (uint32_t);
1426 /* descriptor property */
1427 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_DESCRIPTOR
);
1428 if (ptree_create_and_add_prop(nodehdl
, &prop
, &segment
->descriptor
,
1429 &prophdl
) != PICL_SUCCESS
) {
1431 return (PICL_FAILURE
);
1435 /* offset property */
1436 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_OFFSET
);
1437 if (ptree_create_and_add_prop(nodehdl
, &prop
, &segment
->offset
,
1438 &prophdl
) != PICL_SUCCESS
) {
1440 return (PICL_FAILURE
);
1444 /* length property */
1445 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_LENGTH
);
1446 if (ptree_create_and_add_prop(nodehdl
, &prop
, &segment
->length
,
1447 &prophdl
) != PICL_SUCCESS
) {
1449 return (PICL_FAILURE
);
1452 /* Number of Tags */
1453 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_NUM_TAGS
);
1454 if (ptree_create_and_add_prop(nodehdl
, &prop
, &numoftags
, &prophdl
)
1457 return (PICL_FAILURE
);
1460 if (create_packet_table(nodehdl
, &tblhdl
) != PICL_SUCCESS
) {
1462 return (PICL_FAILURE
);
1465 retval
= ptree_get_propval_by_name(sec_node
,
1466 PICL_PROP_PROTECTED
, &protection
, sizeof (uint32_t));
1467 if (retval
!= PICL_SUCCESS
) {
1469 return (PICL_FAILURE
);
1472 if (protection
== 0) { /* to be added only read/write section */
1473 /* delete segment volatile property */
1474 prop
.piclinfo
.type
= PICL_PTYPE_UNSIGNED_INT
;
1475 prop
.piclinfo
.size
= sizeof (uint32_t);
1476 prop
.piclinfo
.accessmode
= PICL_WRITE
|PICL_VOLATILE
;
1477 prop
.write
= frudata_delete_segment
;
1478 prop
.read
= frudata_read_callback
;
1480 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_DELETE_SEGMENT
);
1481 if (ptree_create_and_add_prop(nodehdl
, &prop
, NULL
, &prophdl
)
1484 return (PICL_FAILURE
);
1488 /* add packet volatile property */
1489 prop
.piclinfo
.type
= PICL_PTYPE_BYTEARRAY
;
1490 prop
.piclinfo
.size
= segment
->length
; /* segment length */
1491 prop
.piclinfo
.accessmode
= PICL_READ
|PICL_WRITE
|PICL_VOLATILE
;
1492 prop
.read
= frudata_read_callback
;
1493 prop
.write
= frudata_add_packet
;
1495 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_ADD_PACKET
);
1496 if (ptree_create_and_add_prop(nodehdl
, &prop
, NULL
, &prophdl
)
1499 return (PICL_FAILURE
);
1503 if (ptree_add_node(sec_node
, nodehdl
) != PICL_SUCCESS
) {
1505 return (PICL_FAILURE
);
1508 hash_obj
= alloc_segment_node_object(nodehdl
, segment
);
1509 if (hash_obj
== NULL
) {
1511 return (PICL_FAILURE
);
1514 add_nodeobject_to_hashtable(hash_obj
, cont_tbl
);
1516 add_to_segment_list(sec_obj
, hash_obj
);
1518 retval
= frudata_read_packet(nodehdl
, &tblhdl
, cont_tbl
, cred
);
1520 return (PICL_SUCCESS
);
1523 (void) ptree_update_propval_by_name(nodehdl
, PICL_PROP_NUM_TAGS
,
1524 &hash_obj
->u
.seg_node
->num_of_pkt
, sizeof (uint32_t));
1526 return (PICL_SUCCESS
);
1530 * Description :frudata_read_segment is called when num_segment volatile
1531 * property is accessed.
1533 * Arguments : ptree_rarg_t contains node handle of the section node.
1534 * and property node of num_segments.
1535 * void * will hold number of segment.
1537 * Returns : PICL_SUCCESS on success.
1538 * PICL_FAILURE on failure.
1542 frudata_read_segment(ptree_rarg_t
*rarg
, void *buf
)
1548 hash_obj_t
*hash_obj
;
1549 fru_segdesc_t
*desc
;
1550 fru_access_hdl_t sec_acc_hdl
;
1551 container_tbl_t
*cont_tbl
;
1553 cont_tbl
= lock_container_lock(rarg
->nodeh
, SECTION_NODE
, PICL_READ
);
1555 return (PICL_FAILURE
);
1558 hash_obj
= lookup_node_object(rarg
->nodeh
, SECTION_NODE
, cont_tbl
);
1559 if (hash_obj
== NULL
) {
1560 unlock_container_lock(cont_tbl
);
1561 return (PICL_FAILURE
);
1564 if (hash_obj
->u
.sec_node
->num_of_segment
== -1) {
1565 sec_acc_hdl
= hash_obj
->u
.sec_node
->section_hdl
;
1567 hash_obj
->u
.sec_node
->num_of_segment
= 0;
1569 num_of_segment
= fru_get_num_segments(sec_acc_hdl
,
1571 if (num_of_segment
< 0) {
1573 unlock_container_lock(cont_tbl
);
1574 return (PICL_FAILURE
);
1577 if (num_of_segment
== 0) {
1579 unlock_container_lock(cont_tbl
);
1580 return (PICL_SUCCESS
);
1583 segment
= alloca(sizeof (segment_t
) * num_of_segment
);
1584 if (segment
== NULL
) {
1586 unlock_container_lock(cont_tbl
);
1587 return (PICL_SUCCESS
);
1590 retval
= fru_get_segments(sec_acc_hdl
, segment
,
1591 num_of_segment
, &rarg
->cred
);
1594 unlock_container_lock(cont_tbl
);
1595 return (PICL_SUCCESS
);
1598 for (cnt
= 0; cnt
< num_of_segment
; cnt
++) {
1600 desc
= (fru_segdesc_t
*)&segment
[cnt
].descriptor
;
1601 if (!(desc
->field
.field_perm
& SEGMENT_READ
)) {
1605 /* if opaque segment don't create segment node */
1606 if (desc
->field
.opaque
) {
1609 (void) create_segment_node(hash_obj
, rarg
->nodeh
,
1610 &segment
[cnt
], cont_tbl
, &rarg
->cred
);
1611 hash_obj
->u
.sec_node
->num_of_segment
++;
1615 /* return number of segment in the section */
1616 *(int *)buf
= hash_obj
->u
.sec_node
->num_of_segment
;
1618 unlock_container_lock(cont_tbl
);
1620 return (PICL_SUCCESS
);
1625 * Description : frudata_add_segment is called when volatile property
1626 * add_segment under class node section is accessed.
1628 * Arguments : ptree_warg_t holds node handle for the section node.
1629 * property handle for the add_segment property.
1631 * Returns : PICL_SUCCESS on success.
1632 * PICL_FAILURE on failure.
1636 frudata_add_segment(ptree_warg_t
*warg
, const void *buf
)
1643 hash_obj_t
*seg_hash
;
1644 hash_obj_t
*hash_obj
;
1645 container_tbl_t
*cont_tbl
;
1646 fru_segdef_t
*seg_def
;
1647 fru_segdesc_t
*desc
;
1648 fru_access_hdl_t new_sec_acc_hdl
;
1650 seg_def
= (fru_segdef_t
*)buf
;
1652 /* initialize segment_t */
1654 (void) memcpy(segment
.name
, seg_def
->name
, SEG_NAME_LEN
);
1655 segment
.descriptor
= seg_def
->desc
.raw_data
;
1656 segment
.length
= seg_def
->size
; /* segment length */
1657 segment
.offset
= seg_def
->address
; /* segment offset */
1659 desc
= (fru_segdesc_t
*)&segment
.descriptor
;
1660 if (!(desc
->field
.field_perm
& SEGMENT_READ
)) {
1661 return (PICL_PERMDENIED
);
1664 cont_tbl
= lock_container_lock(warg
->nodeh
, SECTION_NODE
, PICL_WRITE
);
1666 return (PICL_FAILURE
);
1669 hash_obj
= lookup_node_object(warg
->nodeh
, SECTION_NODE
, cont_tbl
);
1670 if (hash_obj
== NULL
) {
1671 unlock_container_lock(cont_tbl
);
1672 return (PICL_FAILURE
);
1675 /* call fruaccess module, get the new section handle. */
1676 retval
= fru_add_segment(hash_obj
->u
.sec_node
->section_hdl
,
1677 &segment
, &new_sec_acc_hdl
, &warg
->cred
);
1679 unlock_container_lock(cont_tbl
);
1680 return (map_access_err(errno
));
1683 /* call access module with new section handle */
1684 num_of_segment
= fru_get_num_segments(new_sec_acc_hdl
, &warg
->cred
);
1686 seg_buf
= alloca(sizeof (segment_t
) * num_of_segment
);
1687 if (seg_buf
== NULL
) {
1688 unlock_container_lock(cont_tbl
);
1689 return (PICL_FAILURE
);
1692 retval
= fru_get_segments(new_sec_acc_hdl
, seg_buf
,
1693 num_of_segment
, &warg
->cred
);
1695 unlock_container_lock(cont_tbl
);
1696 return (PICL_FAILURE
);
1699 segment
.offset
= seg_buf
[(num_of_segment
-1)].offset
;
1700 segment
.handle
= seg_buf
[(num_of_segment
-1)].handle
;
1702 (void) create_segment_node(hash_obj
, warg
->nodeh
, &segment
,
1703 cont_tbl
, &warg
->cred
);
1705 /* rebuild segment list */
1706 seg_hash
= hash_obj
->u
.sec_node
->segment_list
;
1707 if (seg_hash
== NULL
) {
1708 unlock_container_lock(cont_tbl
);
1709 return (PICL_FAILURE
);
1712 hash_obj
->u
.sec_node
->num_of_segment
= 0;
1714 for (cnt
= 0; cnt
< num_of_segment
; cnt
++) {
1715 desc
= (fru_segdesc_t
*)&seg_buf
[cnt
].descriptor
;
1716 if (!(desc
->field
.field_perm
& SEGMENT_READ
)) {
1720 /* if opaque segment don't create segment node */
1721 if (desc
->field
.opaque
) {
1725 seg_hash
->u
.seg_node
->segment_hdl
=
1726 seg_buf
[cnt
].handle
;
1727 seg_hash
= seg_hash
->u
.seg_node
->next
;
1728 hash_obj
->u
.sec_node
->num_of_segment
++;
1731 /* update with new section handle */
1732 hash_obj
->u
.sec_node
->section_hdl
= new_sec_acc_hdl
;
1734 unlock_container_lock(cont_tbl
);
1736 return (PICL_SUCCESS
);
1740 * called from frudata_write_section() callback routine to create
1741 * section node and all the property under class section. it also
1742 * allocate hash node object for each section in the container and
1743 * add the section node object in the section list.
1747 create_section_node(picl_nodehdl_t nodehdl
, int section_count
,
1748 section_t
*section
, container_tbl_t
*cont_tbl
)
1750 char sec_name
[SECNAMESIZE
];
1751 hash_obj_t
*hash_obj
;
1752 hash_obj_t
*cont_hash
;
1753 picl_nodehdl_t chld_node
;
1754 picl_prophdl_t prophdl
;
1755 ptree_propinfo_t prop
;
1757 (void) snprintf(sec_name
, SECNAMESIZE
, "section%d", section_count
);
1759 if (ptree_create_node(sec_name
, PICL_CLASS_SECTION
, &chld_node
)
1761 return (PICL_FAILURE
);
1763 prop
.version
= PTREE_PROPINFO_VERSION
;
1764 prop
.piclinfo
.type
= PICL_PTYPE_UNSIGNED_INT
;
1765 prop
.piclinfo
.accessmode
= PICL_READ
;
1766 prop
.piclinfo
.size
= sizeof (uint32_t);
1771 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_OFFSET
);
1772 if (ptree_create_and_add_prop(chld_node
, &prop
, §ion
->offset
,
1773 &prophdl
) != PICL_SUCCESS
) {
1775 return (PICL_FAILURE
);
1779 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_LENGTH
);
1780 if (ptree_create_and_add_prop(chld_node
, &prop
, §ion
->length
,
1781 &prophdl
) != PICL_SUCCESS
) {
1783 return (PICL_FAILURE
);
1788 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_PROTECTED
);
1789 if (ptree_create_and_add_prop(chld_node
, &prop
, §ion
->protection
,
1790 &prophdl
) != PICL_SUCCESS
) {
1792 return (PICL_FAILURE
);
1795 prop
.piclinfo
.accessmode
= PICL_READ
|PICL_VOLATILE
;
1796 prop
.read
= frudata_read_segment
;
1798 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_NUM_SEGMENTS
);
1800 if (ptree_create_and_add_prop(chld_node
, &prop
, NULL
, &prophdl
)
1803 return (PICL_FAILURE
);
1807 prop
.piclinfo
.type
= PICL_PTYPE_BYTEARRAY
;
1808 prop
.piclinfo
.size
= sizeof (fru_segdef_t
);
1810 prop
.piclinfo
.accessmode
= PICL_WRITE
|PICL_READ
|PICL_VOLATILE
;
1811 prop
.write
= frudata_add_segment
; /* callback routine */
1812 prop
.read
= frudata_read_callback
;
1814 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_ADD_SEGMENT
);
1815 /* add-segment prop if read/write section */
1816 if (section
->protection
== 0) {
1817 if (ptree_create_and_add_prop(chld_node
, &prop
, NULL
, &prophdl
)
1820 return (PICL_FAILURE
);
1824 if (ptree_add_node(nodehdl
, chld_node
) != PICL_SUCCESS
) {
1826 return (PICL_FAILURE
);
1829 /* lookup for container handle */
1830 cont_hash
= lookup_node_object(nodehdl
, CONTAINER_NODE
, cont_tbl
);
1831 if (cont_hash
== NULL
) {
1833 return (PICL_FAILURE
);
1836 hash_obj
= alloc_section_node_object(chld_node
, section
);
1837 if (hash_obj
== NULL
) {
1839 return (PICL_FAILURE
);
1842 add_nodeobject_to_hashtable(hash_obj
, cont_tbl
);
1844 add_to_section_list(cont_hash
, hash_obj
);
1845 return (PICL_SUCCESS
);
1850 * Description :frudata_write_section is called when volatile container
1851 * property is accessed. it reads the section table associated
1852 * with the specified node handle(container) in ptree_rarg_t.
1853 * it calls search_root_node to search the node handle to open the
1854 * device associated with the node handle. it creates section
1855 * node and it's associated property. it also creates
1856 * volatile property num_segments.
1858 * Argument : ptree_rarg_t : contains node handle of fru container the
1860 * property handle of the container.
1862 * Return : PICL_SUCCESS on success.
1869 frudata_write_section(ptree_warg_t
*warg
, const void *buf
)
1875 hash_obj_t
*hash_obj
;
1876 container_tbl_t
*cont_tbl
= NULL
;
1877 fru_access_hdl_t cont_acc_hdl
;
1879 (void) pthread_mutex_lock(&cont_tbl_lock
);
1882 * if lookup succeed return from this function with PICL_SUCCESS
1883 * because first write operation has already occurred on this container,
1884 * it also means that the container has been already initialzed.
1887 cont_tbl
= lookup_container_table(warg
->nodeh
, CONTAINER_NODE
);
1888 if (cont_tbl
!= NULL
) { /* found the hash obj in the hash table */
1889 (void) pthread_mutex_unlock(&cont_tbl_lock
);
1890 return (PICL_SUCCESS
);
1894 * lookup failed that means this is first write on the
1895 * container property. allocate a new container hash table for this
1896 * new container and add to the cont_tbl hash table.
1899 cont_tbl
= alloc_container_table(warg
->nodeh
);
1900 if (cont_tbl
== NULL
) {
1901 (void) pthread_mutex_unlock(&cont_tbl_lock
);
1902 return (map_access_err(errno
));
1905 hash_obj
= alloc_container_node_object(warg
->nodeh
);
1906 if (hash_obj
== NULL
) {
1907 (void) pthread_mutex_unlock(&cont_tbl_lock
);
1908 free(cont_tbl
->hash_obj
);
1910 return (map_access_err(errno
));
1913 /* add container table object to container table */
1914 add_tblobject_to_container_tbl(cont_tbl
);
1916 /* add the hash object to container hash table. */
1917 add_nodeobject_to_hashtable(hash_obj
, cont_tbl
);
1919 while (pthread_rwlock_trywrlock(&cont_tbl
->rwlock
) == EBUSY
) {
1920 pthread_cond_wait(&cont_tbl
->cond_var
, &cont_tbl_lock
);
1923 (void) pthread_mutex_unlock(&cont_tbl_lock
);
1925 /* fruaccess handle */
1926 cont_acc_hdl
= hash_obj
->u
.cont_node
->cont_hdl
;
1928 num_of_section
= fru_get_num_sections(cont_acc_hdl
, &warg
->cred
);
1930 if (num_of_section
== -1) {
1932 unlock_container_lock(cont_tbl
);
1933 return (PICL_FAILURE
);
1936 section
= alloca(num_of_section
* sizeof (section_t
));
1938 retval
= fru_get_sections(cont_acc_hdl
, section
,
1939 num_of_section
, &warg
->cred
);
1942 unlock_container_lock(cont_tbl
);
1943 return (PICL_FAILURE
);
1946 hash_obj
->u
.cont_node
->num_of_section
= num_of_section
;
1948 for (count
= 0; count
< num_of_section
; count
++) {
1949 (void) create_section_node(warg
->nodeh
, count
,
1950 section
+ count
, cont_tbl
);
1953 unlock_container_lock(cont_tbl
);
1955 return (PICL_SUCCESS
);
1958 /* create container and add-segment property */
1961 create_container_prop(picl_nodehdl_t fruhdl
)
1964 picl_prophdl_t prophdl
;
1965 ptree_propinfo_t prop
;
1967 prop
.version
= PTREE_PROPINFO_VERSION
;
1968 prop
.piclinfo
.type
= PICL_PTYPE_UNSIGNED_INT
;
1969 prop
.piclinfo
.size
= sizeof (uint32_t);
1970 prop
.piclinfo
.accessmode
= PICL_WRITE
|PICL_VOLATILE
;
1971 (void) strcpy(prop
.piclinfo
.name
, PICL_PROP_CONTAINER
);
1972 prop
.read
= frudata_read_callback
;
1973 prop
.write
= frudata_write_section
; /* callback routine */
1975 /* create a property */
1976 retval
= ptree_create_and_add_prop(fruhdl
, &prop
, NULL
, &prophdl
);
1981 /* search for FRUDataAvailable and create container and add segment property */
1984 create_frudata_props(picl_prophdl_t fruhdl
)
1987 picl_nodehdl_t chldhdl
;
1988 picl_nodehdl_t tmphdl
;
1990 for (retval
= ptree_get_propval_by_name(fruhdl
, PICL_PROP_CHILD
,
1991 &chldhdl
, sizeof (picl_nodehdl_t
)); retval
!= PICL_PROPNOTFOUND
;
1992 retval
= ptree_get_propval_by_name(chldhdl
, PICL_PROP_PEER
,
1993 &chldhdl
, sizeof (picl_nodehdl_t
))) {
1994 if (retval
!= PICL_SUCCESS
)
1997 /* Does it have a FRUDataAvailable property */
1998 retval
= ptree_get_prop_by_name(chldhdl
,
1999 PICL_PROP_FRUDATA_AVAIL
, &tmphdl
);
2000 if (retval
== PICL_SUCCESS
) {
2001 (void) create_container_prop(chldhdl
);
2004 /* Traverse tree recursively */
2005 (void) create_frudata_props(chldhdl
);
2010 * Search for the frutree config file from the platform specific
2011 * directory to the common directory.
2013 * The size of outfilename must be PATH_MAX
2016 get_config_file(char *outfilename
)
2018 char nmbuf
[SYS_NMLN
];
2019 char pname
[PATH_MAX
];
2021 if (sysinfo(SI_PLATFORM
, nmbuf
, sizeof (nmbuf
)) != -1) {
2022 (void) snprintf(pname
, PATH_MAX
, FRUDATA_CONFFILE_NAME
, nmbuf
);
2023 if (access(pname
, R_OK
) == 0) {
2024 (void) strlcpy(outfilename
, pname
, PATH_MAX
);
2029 if (sysinfo(SI_MACHINE
, nmbuf
, sizeof (nmbuf
)) != -1) {
2030 (void) snprintf(pname
, PATH_MAX
, FRUDATA_CONFFILE_NAME
, nmbuf
);
2031 if (access(pname
, R_OK
) == 0) {
2032 (void) strlcpy(outfilename
, pname
, PATH_MAX
);
2037 (void) snprintf(pname
, PATH_MAX
, "%s/%s", PICLD_COMMON_PLUGIN_DIR
,
2038 FRUDATA_CONFFILE_NAME
);
2039 if (access(pname
, R_OK
) == 0) {
2040 (void) strlcpy(outfilename
, pname
, PATH_MAX
);
2047 * called from delete_frudata_props(), this routine delete the section node
2048 * and free's the section hash object. it calls free_segment_node() to
2049 * delete segment node beneath it.
2053 free_section_node(hash_obj_t
*sec_hash
, container_tbl_t
*cont_tbl
)
2055 hash_obj_t
*seg_hash
;
2057 for (seg_hash
= sec_hash
->u
.sec_node
->segment_list
; seg_hash
!= NULL
;
2058 seg_hash
= seg_hash
->u
.seg_node
->next
) {
2059 free_segment_node(seg_hash
, seg_hash
->picl_hdl
, cont_tbl
);
2062 if (sec_hash
->prev
== NULL
) {
2063 cont_tbl
->hash_obj
[(sec_hash
->picl_hdl
% TABLE_SIZE
)].next
=
2065 if (sec_hash
->next
!= NULL
) {
2066 sec_hash
->next
->prev
= NULL
;
2069 sec_hash
->prev
->next
= sec_hash
->next
;
2070 if (sec_hash
->next
!= NULL
) {
2071 sec_hash
->next
->prev
= sec_hash
->prev
;
2075 /* delete & destroy section node */
2076 (void) ptree_delete_node(sec_hash
->picl_hdl
);
2077 (void) ptree_destroy_node(sec_hash
->picl_hdl
);
2079 free(sec_hash
->u
.sec_node
);
2084 * called from delete_frudata_props(), this routine free's the container
2089 unlink_container_node(container_tbl_t
*cont_hash
)
2091 if (cont_hash
->prev
== NULL
) {
2092 container_table
[(cont_hash
->picl_hdl
% TABLE_SIZE
)] =
2094 if (cont_hash
->next
!= NULL
) {
2095 cont_hash
->next
->prev
= NULL
;
2098 cont_hash
->prev
->next
= cont_hash
->next
;
2099 if (cont_hash
->next
!= NULL
) {
2100 cont_hash
->next
->prev
= cont_hash
->prev
;
2106 * called from frudata_event_handler() to free the corresponding hash object
2107 * of the removed fru.
2111 delete_frudata_props(picl_nodehdl_t fru_hdl
)
2113 hash_obj_t
*cont_hash
;
2114 hash_obj_t
*free_obj
;
2115 hash_obj_t
*sec_hash
;
2116 container_tbl_t
*cont_tbl
;
2118 (void) pthread_mutex_lock(&cont_tbl_lock
);
2120 cont_tbl
= lookup_container_table(fru_hdl
, CONTAINER_NODE
);
2121 if (cont_tbl
== NULL
) {
2122 (void) pthread_mutex_unlock(&cont_tbl_lock
);
2126 /* remove the container object from the container table */
2127 unlink_container_node(cont_tbl
);
2129 (void) pthread_cond_broadcast(&cont_tbl
->cond_var
);
2131 (void) pthread_mutex_unlock(&cont_tbl_lock
);
2134 * waiting/blocking calling thread for all I/O in
2135 * progress to complete. don't free the container
2136 * hash before all I/O is complete.
2138 (void) pthread_rwlock_wrlock(&cont_tbl
->rwlock
);
2140 (void) pthread_rwlock_unlock(&cont_tbl
->rwlock
);
2143 cont_hash
= lookup_node_object(fru_hdl
, CONTAINER_NODE
, cont_tbl
);
2144 if (cont_hash
== NULL
) {
2148 free_obj
= cont_hash
->u
.cont_node
->section_list
;
2149 /* walk through the section list */
2150 for (sec_hash
= free_obj
; sec_hash
!= NULL
; free_obj
= sec_hash
) {
2151 sec_hash
= sec_hash
->u
.sec_node
->next
;
2152 free_section_node(free_obj
, cont_tbl
);
2154 (void) fru_close_container(cont_hash
->u
.cont_node
->cont_hdl
);
2156 free(cont_hash
->u
.cont_node
);
2159 free(cont_tbl
->hash_obj
);
2164 * called when there is any state-change in location, fru, port nodes.
2165 * this event handler handles only location state-changes.
2169 frudata_state_change_evhandler(const char *event_name
, const void *event_arg
,
2170 size_t size
, void *cookie
)
2174 ptree_propinfo_t prop
;
2175 picl_nodehdl_t loch
, fruh
;
2176 picl_prophdl_t proph
, prophdl
;
2177 char *present_state
, *last_state
;
2178 char name
[PICL_PROPNAMELEN_MAX
];
2180 if (strcmp(event_name
, PICLEVENT_STATE_CHANGE
) != 0)
2183 if (nvlist_unpack((char *)event_arg
, size
, &nvlp
, NULL
)) {
2187 if (nvlist_lookup_uint64(nvlp
, PICLEVENTARG_NODEHANDLE
,
2193 if (ptree_get_propval_by_name(loch
, PICL_PROP_CLASSNAME
, name
,
2194 sizeof (name
)) != PICL_SUCCESS
) {
2199 /* handle only location events */
2200 if (strcmp(name
, PICL_CLASS_LOCATION
) != 0) {
2205 if (nvlist_lookup_string(nvlp
, PICLEVENTARG_STATE
,
2211 rc
= ptree_get_propval_by_name(loch
, PICL_PROP_CHILD
,
2212 &fruh
, sizeof (picl_nodehdl_t
));
2213 if (rc
!= PICL_SUCCESS
) {
2219 if (strcmp(present_state
, PICLEVENTARGVAL_EMPTY
) == 0) {
2220 delete_frudata_props(fruh
);
2225 if (nvlist_lookup_string(nvlp
, PICLEVENTARG_LAST_STATE
,
2232 if ((strcmp(last_state
, PICLEVENTARGVAL_EMPTY
) == 0) ||
2233 (strcmp(last_state
, PICLEVENTARGVAL_UNKNOWN
) == 0)) {
2234 rc
= ptree_get_prop_by_name(fruh
, PICL_PROP_FRUDATA_AVAIL
,
2236 if (rc
!= PICL_SUCCESS
) {
2237 if (fru_is_data_available(fruh
) == 0) {
2241 /* create the property */
2242 prop
.version
= PTREE_PROPINFO_VERSION
;
2243 prop
.piclinfo
.type
= PICL_PTYPE_VOID
;
2244 prop
.piclinfo
.accessmode
= PICL_READ
;
2245 prop
.piclinfo
.size
= 0;
2246 (void) strncpy(prop
.piclinfo
.name
,
2247 PICL_PROP_FRUDATA_AVAIL
,
2248 sizeof (prop
.piclinfo
.name
));
2250 rc
= ptree_create_prop(&prop
, NULL
, &prophdl
);
2251 if (rc
!= PICL_SUCCESS
) {
2255 rc
= ptree_add_prop(fruh
, prophdl
);
2256 if (rc
!= PICL_SUCCESS
) {
2261 (void) create_container_prop(fruh
);
2267 * called when event is posted when is fru is either added or removed from
2273 frudata_event_handler(const char *event_name
, const void *event_arg
,
2274 size_t size
, void *cookie
)
2277 char fullfilename
[PATH_MAX
];
2278 picl_nodehdl_t fru_picl_hdl
;
2279 picl_nodehdl_t roothdl
;
2281 if (strcmp(event_name
, PICL_FRU_REMOVED
) == 0) {
2283 retval
= nvlist_lookup_uint64((nvlist_t
*)event_arg
,
2284 PICLEVENTARG_FRUHANDLE
, &fru_picl_hdl
);
2285 if (retval
!= PICL_SUCCESS
) {
2289 /* free the hash object */
2290 delete_frudata_props(fru_picl_hdl
);
2292 } else if (strcmp(event_name
, PICL_FRU_ADDED
) == 0) {
2294 * reparse the configuration file to create
2295 * FRUDevicePath Prop.
2297 (void) get_config_file(fullfilename
);
2298 retval
= ptree_get_root(&roothdl
);
2299 if (retval
!= PICL_SUCCESS
) {
2303 (void) picld_pluginutil_parse_config_file(roothdl
,
2306 retval
= nvlist_lookup_uint64((nvlist_t
*)event_arg
,
2307 PICLEVENTARG_PARENTHANDLE
, &fru_picl_hdl
);
2308 if (retval
!= PICL_SUCCESS
) {
2312 /* create container property */
2313 create_frudata_props(fru_picl_hdl
);
2318 * Function : plugin_init() is called by daemon. this routine is specified
2319 * while registering with daemon. it performs the initialization
2324 frudata_plugin_init(void)
2328 char fullfilename
[PATH_MAX
];
2329 picl_nodehdl_t fru_nodehdl
;
2330 picl_nodehdl_t roothdl
;
2332 retval
= ptree_get_root(&roothdl
);
2333 if (retval
!= PICL_SUCCESS
) {
2337 (void) ptree_register_handler(PICL_FRU_ADDED
,
2338 frudata_event_handler
, NULL
);
2340 (void) ptree_register_handler(PICL_FRU_REMOVED
,
2341 frudata_event_handler
, NULL
);
2343 (void) ptree_register_handler(PICLEVENT_STATE_CHANGE
,
2344 frudata_state_change_evhandler
, NULL
);
2346 (void) pthread_mutex_lock(&cont_tbl_lock
);
2347 for (count
= 0; count
< TABLE_SIZE
; count
++) {
2348 container_table
[count
] = NULL
;
2350 (void) pthread_mutex_unlock(&cont_tbl_lock
);
2352 (void) get_config_file(fullfilename
);
2354 (void) picld_pluginutil_parse_config_file(roothdl
, fullfilename
);
2356 retval
= ptree_get_node_by_path(FRUTREE_PATH
, &fru_nodehdl
);
2358 if (retval
!= PICL_SUCCESS
) {
2362 create_frudata_props(fru_nodehdl
);
2367 free_packet_hash_object(hash_obj_t
*pkt_obj
)
2369 hash_obj_t
*tmp_obj
;
2371 while (pkt_obj
!= NULL
) {
2372 tmp_obj
= pkt_obj
->u
.pkt_node
->next
;
2373 free(pkt_obj
->u
.pkt_node
);
2380 free_segment_hash_object(hash_obj_t
*seg_obj
)
2382 hash_obj_t
*tmp_obj
;
2384 while (seg_obj
!= NULL
) {
2385 free_packet_hash_object(seg_obj
->u
.seg_node
->packet_list
);
2386 tmp_obj
= seg_obj
->u
.seg_node
->next
;
2387 free(seg_obj
->u
.seg_node
);
2394 free_hash_objects(hash_obj_t
*sec_obj
)
2396 hash_obj_t
*tmp_obj
;
2398 while (sec_obj
!= NULL
) {
2399 free_segment_hash_object(sec_obj
->u
.sec_node
->segment_list
);
2400 tmp_obj
= sec_obj
->u
.sec_node
->next
;
2401 free(sec_obj
->u
.sec_node
);
2408 * called from frudata_plugin_fini() this routine walks through
2409 * the hash table to free each and very hash object in the hash table.
2413 free_hash_table(void)
2416 picl_nodehdl_t nodehdl
;
2417 hash_obj_t
*next_obj
;
2418 hash_obj_t
*sec_obj
;
2419 container_tbl_t
*cont_tbl
;
2421 for (cnt
= 0; cnt
< TABLE_SIZE
; cnt
++) {
2423 while (container_table
[cnt
]) {
2425 (void) pthread_mutex_lock(&cont_tbl_lock
);
2427 cont_tbl
= container_table
[cnt
];
2428 nodehdl
= cont_tbl
->picl_hdl
;
2430 cont_tbl
= lookup_container_table(nodehdl
,
2432 if (cont_tbl
== NULL
) {
2433 (void) pthread_mutex_unlock(&cont_tbl_lock
);
2437 unlink_container_node(cont_tbl
);
2439 pthread_cond_broadcast(&cont_tbl
->cond_var
);
2441 (void) pthread_mutex_unlock(&cont_tbl_lock
);
2444 * waiting/blocking calling thread for all I/O in
2445 * progress to complete. don't free the container
2446 * hash until all I/O is complete.
2448 (void) pthread_rwlock_wrlock(&cont_tbl
->rwlock
);
2450 (void) pthread_rwlock_unlock(&cont_tbl
->rwlock
);
2452 next_obj
= cont_tbl
->hash_obj
->next
;
2453 if (next_obj
== NULL
) {
2457 if (next_obj
->object_type
== CONTAINER_NODE
) {
2458 sec_obj
= next_obj
->u
.cont_node
->section_list
;
2459 free_hash_objects(sec_obj
);
2462 free(next_obj
->u
.cont_node
);
2464 container_table
[cnt
] = cont_tbl
->next
;
2472 * called by the daemon and perform frudata cleanup. hold the write lock
2473 * over the entire hash table to free each and every hash object.
2477 frudata_plugin_fini(void)
2482 (void) ptree_unregister_handler(PICL_FRU_ADDED
,
2483 frudata_event_handler
, NULL
);
2485 (void) ptree_unregister_handler(PICL_FRU_REMOVED
,
2486 frudata_event_handler
, NULL
);
2488 (void) ptree_unregister_handler(PICLEVENT_STATE_CHANGE
,
2489 frudata_state_change_evhandler
, NULL
);