cmd: remove sparc-only virtinfo
[unleashed.git] / usr / src / cmd / picl / plugins / sun4u / snowbird / lib / fruaccess / libfruaccess.c
blob3a48dcbf5ee8af7e984dba08fb3677504f04cfe7
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 2004 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
26 #pragma ident "%Z%%M% %I% %E% SMI"
28 #include <picl.h>
29 #include <limits.h>
30 #include <alloca.h>
31 #include <stdarg.h>
32 #include "smc_if.h"
33 #include "fru_access_impl.h"
35 #pragma init(initialize_fruaccess) /* .init section */
38 * This module translates all the frudata plugin requests into platform
39 * specific commands and provides information back to frudata plugin.
43 * precedence for format.
44 * define an ENV variable (SUNW_FRUACCESS_IPMI_PRECEDENCE) to make
45 * ipmi format has more precedence than sun format.
47 static int precedence = SUN_FORMAT; /* by default */
48 #define FRUACCESS_PRECEDENCE "SUNW_FRUACCESS_IPMI_PRECEDENCE"
50 extern ssize_t pread_new(int, void *, size_t, off_t, format_t *);
51 extern ssize_t pwrite_new(int, const void *, size_t, off_t, format_t *);
52 extern int get_manr(format_t *, payload_t *);
53 extern int is_fru_data_available(int, int, format_t *);
54 extern picl_errno_t fruaccess_platmod_init_format(uint8_t, format_t *);
55 extern int fruaccess_platmod_check_chassis();
56 extern int fruaccess_platmod_check_fru(picl_nodehdl_t parenth);
58 static container_hdl_t sun_fru_open_container(picl_nodehdl_t);
59 static int sun_fru_close_container(container_hdl_t);
60 static int sun_fru_get_num_sections(container_hdl_t, door_cred_t *);
61 static int sun_fru_get_sections(container_hdl_t, section_t *,
62 int, door_cred_t *);
63 static int sun_fru_get_num_segments(section_hdl_t, door_cred_t *);
64 static int sun_fru_get_segments(section_hdl_t, segment_t *,
65 int, door_cred_t *);
66 static int sun_fru_add_segment(section_hdl_t, segment_t *,
67 section_hdl_t *, door_cred_t *);
68 static int sun_fru_delete_segment(segment_hdl_t, section_hdl_t *,
69 door_cred_t *);
70 static ssize_t sun_fru_read_segment(segment_hdl_t, void *, size_t,
71 door_cred_t *);
72 static int sun_fru_write_segment(segment_hdl_t, const void *, size_t,
73 segment_hdl_t *, door_cred_t *);
74 static int sun_fru_get_num_packets(segment_hdl_t, door_cred_t *);
75 static int sun_fru_get_packets(segment_hdl_t, packet_t *,
76 int, door_cred_t *);
77 static ssize_t sun_fru_get_payload(packet_hdl_t, void *, size_t,
78 door_cred_t *);
79 static int sun_fru_update_payload(packet_hdl_t, const void *, size_t,
80 packet_hdl_t *, door_cred_t *);
81 static int sun_fru_append_packet(segment_hdl_t, packet_t *,
82 const void *, size_t, segment_hdl_t *,
83 door_cred_t *);
84 static int sun_fru_delete_packet(packet_hdl_t, segment_hdl_t *, door_cred_t *);
86 static container_hdl_t ipmi_fru_open_container(picl_nodehdl_t);
87 static int ipmi_fru_close_container(container_hdl_t);
88 static int ipmi_fru_get_num_sections(container_hdl_t, door_cred_t *);
89 static int ipmi_fru_get_sections(container_hdl_t, section_t *,
90 int, door_cred_t *);
91 static int ipmi_fru_get_num_segments(section_hdl_t, door_cred_t *);
92 static int ipmi_fru_get_segments(section_hdl_t, segment_t *,
93 int, door_cred_t *);
94 static int ipmi_fru_add_segment(section_hdl_t, segment_t *,
95 section_hdl_t *, door_cred_t *);
96 static int ipmi_fru_delete_segment(segment_hdl_t, section_hdl_t *,
97 door_cred_t *);
98 static ssize_t ipmi_fru_read_segment(segment_hdl_t, void *, size_t,
99 door_cred_t *);
100 static int ipmi_fru_write_segment(segment_hdl_t, const void *, size_t,
101 segment_hdl_t *, door_cred_t *);
102 static int ipmi_fru_get_num_packets(segment_hdl_t, door_cred_t *);
103 static int ipmi_fru_get_packets(segment_hdl_t, packet_t *,
104 int, door_cred_t *);
105 static ssize_t ipmi_fru_get_payload(packet_hdl_t, void *, size_t,
106 door_cred_t *);
107 static int ipmi_fru_update_payload(packet_hdl_t, const void *, size_t,
108 packet_hdl_t *, door_cred_t *);
109 static int ipmi_fru_append_packet(segment_hdl_t, packet_t *,
110 const void *, size_t, segment_hdl_t *,
111 door_cred_t *);
112 static int ipmi_fru_delete_packet(packet_hdl_t, segment_hdl_t *, door_cred_t *);
114 typedef struct {
115 container_hdl_t (* open_container)(picl_nodehdl_t);
116 int (* close_container)(container_hdl_t);
117 int (* get_num_sections)(container_hdl_t, door_cred_t *);
118 int (* get_sections)(container_hdl_t, section_t *,
119 int, door_cred_t *);
120 int (* get_num_segments)(section_hdl_t, door_cred_t *);
121 int (* get_segments)(section_hdl_t, segment_t *,
122 int, door_cred_t *);
123 int (* add_segment)(section_hdl_t, segment_t *,
124 section_hdl_t *, door_cred_t *);
125 int (* delete_segment)(segment_hdl_t, section_hdl_t *,
126 door_cred_t *);
127 ssize_t (* read_segment)(segment_hdl_t, void *, size_t,
128 door_cred_t *);
129 int (* write_segment)(segment_hdl_t, const void *, size_t,
130 segment_hdl_t *, door_cred_t *);
131 int (* get_num_packets)(segment_hdl_t, door_cred_t *);
132 int (* get_packets)(segment_hdl_t, packet_t *,
133 int, door_cred_t *);
134 ssize_t (* get_payload)(packet_hdl_t, void *, size_t,
135 door_cred_t *);
136 int (* update_payload)(packet_hdl_t, const void *, size_t,
137 packet_hdl_t *, door_cred_t *);
138 int (* append_packet)(segment_hdl_t, packet_t *,
139 const void *, size_t, segment_hdl_t *,
140 door_cred_t *);
141 int (* delete_packet)(packet_hdl_t, segment_hdl_t *, door_cred_t *);
142 } fruaccess_func_ptrs_t;
144 static fruaccess_func_ptrs_t fruaccess_func[2] = {
146 ipmi_fru_open_container,
147 ipmi_fru_close_container,
148 ipmi_fru_get_num_sections,
149 ipmi_fru_get_sections,
150 ipmi_fru_get_num_segments,
151 ipmi_fru_get_segments,
152 ipmi_fru_add_segment,
153 ipmi_fru_delete_segment,
154 ipmi_fru_read_segment,
155 ipmi_fru_write_segment,
156 ipmi_fru_get_num_packets,
157 ipmi_fru_get_packets,
158 ipmi_fru_get_payload,
159 ipmi_fru_update_payload,
160 ipmi_fru_append_packet,
161 ipmi_fru_delete_packet,
164 sun_fru_open_container,
165 sun_fru_close_container,
166 sun_fru_get_num_sections,
167 sun_fru_get_sections,
168 sun_fru_get_num_segments,
169 sun_fru_get_segments,
170 sun_fru_add_segment,
171 sun_fru_delete_segment,
172 sun_fru_read_segment,
173 sun_fru_write_segment,
174 sun_fru_get_num_packets,
175 sun_fru_get_packets,
176 sun_fru_get_payload,
177 sun_fru_update_payload,
178 sun_fru_append_packet,
179 sun_fru_delete_packet,
183 static int is_valid_chassis = -1;
184 static hash_obj_t *hash_table[TABLE_SIZE];
186 static void
187 initialize_fruaccess(void)
189 int count;
190 for (count = 0; count < TABLE_SIZE; count++) {
191 hash_table[count] = NULL;
194 /* check if ipmi format has precedence */
195 if (getenv(FRUACCESS_PRECEDENCE)) {
196 precedence = IPMI_FORMAT;
200 /* called to lookup hash object for specified handle in the hash table. */
201 static hash_obj_t *
202 lookup_handle_object(handle_t handle, int object_type)
204 handle_t index_to_hash;
205 hash_obj_t *first_hash_obj;
206 hash_obj_t *next_hash_obj;
208 index_to_hash = (handle % TABLE_SIZE);
210 first_hash_obj = hash_table[index_to_hash];
211 for (next_hash_obj = first_hash_obj; next_hash_obj != NULL;
212 next_hash_obj = next_hash_obj->next) {
213 if ((handle == next_hash_obj->obj_hdl) &&
214 (object_type == next_hash_obj->object_type)) {
215 return (next_hash_obj);
218 return (NULL);
221 /* called to allocate container hash object */
222 static hash_obj_t *
223 create_container_hash_object(void)
225 hash_obj_t *hash_obj;
226 container_obj_t *cont_obj;
228 cont_obj = malloc(sizeof (container_obj_t));
229 if (cont_obj == NULL) {
230 return (NULL);
233 hash_obj = malloc(sizeof (hash_obj_t));
234 if (hash_obj == NULL) {
235 free(cont_obj);
236 return (NULL);
239 cont_obj->sec_obj_list = NULL;
241 hash_obj->object_type = CONTAINER_TYPE;
242 hash_obj->u.cont_obj = cont_obj;
243 hash_obj->next = NULL;
244 hash_obj->prev = NULL;
246 return (hash_obj);
249 /* called to allocate section hash object */
250 static hash_obj_t *
251 create_section_hash_object(void)
253 hash_obj_t *hash_obj;
254 section_obj_t *sec_obj;
256 sec_obj = malloc(sizeof (section_obj_t));
257 if (sec_obj == NULL) {
258 return (NULL);
261 hash_obj = malloc(sizeof (hash_obj_t));
262 if (hash_obj == NULL) {
263 free(sec_obj);
264 return (NULL);
267 sec_obj->next = NULL;
268 sec_obj->seg_obj_list = NULL;
270 hash_obj->u.sec_obj = sec_obj;
271 hash_obj->object_type = SECTION_TYPE;
272 hash_obj->next = NULL;
273 hash_obj->prev = NULL;
275 return (hash_obj);
278 /* called to allocate segment hash object */
279 static hash_obj_t *
280 create_segment_hash_object(void)
282 hash_obj_t *hash_obj;
283 segment_obj_t *seg_obj;
285 seg_obj = malloc(sizeof (segment_obj_t));
286 if (seg_obj == NULL) {
287 return (NULL);
290 hash_obj = malloc(sizeof (hash_obj_t));
291 if (hash_obj == NULL) {
292 free(seg_obj);
293 return (NULL);
296 seg_obj->next = NULL;
297 seg_obj->pkt_obj_list = NULL;
299 hash_obj->object_type = SEGMENT_TYPE;
300 hash_obj->u.seg_obj = seg_obj;
301 hash_obj->next = NULL;
302 hash_obj->prev = NULL;
304 return (hash_obj);
307 /* called to allocate packet hash object */
308 static hash_obj_t *
309 create_packet_hash_object(void)
311 hash_obj_t *hash_obj;
312 packet_obj_t *pkt_obj;
314 pkt_obj = malloc(sizeof (packet_obj_t));
315 if (pkt_obj == NULL) {
316 return (NULL);
319 hash_obj = malloc(sizeof (hash_obj_t));
320 if (hash_obj == NULL) {
321 free(pkt_obj);
322 return (NULL);
325 pkt_obj->next = NULL;
327 hash_obj->object_type = PACKET_TYPE;
328 hash_obj->u.pkt_obj = pkt_obj;
329 hash_obj->next = NULL;
330 hash_obj->prev = NULL;
332 return (hash_obj);
335 /* called to add allocated hash object into the hash table */
336 static void
337 add_hashobject_to_hashtable(hash_obj_t *hash_obj, int object_type)
339 handle_t index_to_hash;
340 static uint64_t handle_count = 0;
342 if (object_type != CONTAINER_TYPE) {
343 hash_obj->obj_hdl = ++handle_count;
346 /* where to add ? */
347 index_to_hash = ((hash_obj->obj_hdl) % TABLE_SIZE);
349 hash_obj->next = hash_table[index_to_hash];
350 hash_table[index_to_hash] = hash_obj; /* hash obj. added */
352 if (hash_obj->next != NULL) {
353 hash_obj->next->prev = hash_obj;
357 /* called to add section object list into the section list */
358 static void
359 add_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
361 hash_obj_t *next_hash;
363 child_obj->u.sec_obj->cont_hdl = parent_obj->obj_hdl;
364 if (parent_obj->u.cont_obj->sec_obj_list == NULL) {
365 parent_obj->u.cont_obj->sec_obj_list = child_obj;
366 return;
369 for (next_hash = parent_obj->u.cont_obj->sec_obj_list;
370 next_hash->u.sec_obj->next != NULL;
371 next_hash = next_hash->u.sec_obj->next) {
375 next_hash->u.sec_obj->next = child_obj;
378 /* called to add segment object list into segment list */
379 static void
380 add_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
382 hash_obj_t *next_hash;
384 child_obj->u.seg_obj->section_hdl = parent_obj->obj_hdl;
385 if (parent_obj->u.sec_obj->seg_obj_list == NULL) {
386 parent_obj->u.sec_obj->seg_obj_list = child_obj;
387 return;
390 for (next_hash = parent_obj->u.sec_obj->seg_obj_list;
391 next_hash->u.seg_obj->next != NULL;
392 next_hash = next_hash->u.seg_obj->next) {
396 next_hash->u.seg_obj->next = child_obj;
399 /* called to add packet object list into packet list */
400 static void
401 add_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
403 hash_obj_t *next_hash;
405 /* add the packet object in the end of list */
406 child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl;
408 if (parent_obj->u.seg_obj->pkt_obj_list == NULL) {
409 parent_obj->u.seg_obj->pkt_obj_list = child_obj;
410 return;
413 for (next_hash = parent_obj->u.seg_obj->pkt_obj_list;
414 next_hash->u.pkt_obj->next != NULL;
415 next_hash = next_hash->u.pkt_obj->next) {
419 next_hash->u.pkt_obj->next = child_obj;
422 /* fill the information, payload in the conatiner */
423 /*ARGSUSED*/
424 static int
425 initialize_ipmi_container(picl_nodehdl_t fru, hash_obj_t *cont_hash_obj)
427 payload_t manr;
428 hash_obj_t *seg_hash_obj, *sec_hash_obj, *pkt_hash_obj;
429 format_t format;
431 format = cont_hash_obj->u.cont_obj->format;
432 /* plug to SMC driver to fetch the data */
433 if (get_manr(&format, &manr) != 0) {
434 return (-1);
437 cont_hash_obj->u.cont_obj->num_of_section = 1;
438 cont_hash_obj->u.cont_obj->sec_obj_list = NULL;
440 sec_hash_obj = create_section_hash_object();
441 if (sec_hash_obj == NULL) {
442 return (-1);
445 add_hashobject_to_hashtable(sec_hash_obj, SECTION_TYPE);
447 /* create fake section info here */
448 sec_hash_obj->u.sec_obj->num_of_segment = 1;
449 sec_hash_obj->u.sec_obj->section.handle = sec_hash_obj->obj_hdl;
450 sec_hash_obj->u.sec_obj->section.offset = 0;
451 sec_hash_obj->u.sec_obj->section.protection = READ_ONLY_SECTION;
453 sec_hash_obj->u.sec_obj->section.length = STATIC_LENGTH;
454 sec_hash_obj->u.sec_obj->section.version = SECTION_HDR_VER;
455 add_to_sec_object_list(cont_hash_obj, sec_hash_obj);
457 seg_hash_obj = create_segment_hash_object();
458 if (seg_hash_obj == NULL) {
459 return (-1);
462 add_hashobject_to_hashtable(seg_hash_obj, SEGMENT_TYPE);
464 seg_hash_obj->u.seg_obj->num_of_packets = 1;
465 seg_hash_obj->u.seg_obj->segment.handle = seg_hash_obj->obj_hdl;
466 (void) strncpy(seg_hash_obj->u.seg_obj->segment.name,
467 SD_SEGMENT_NAME,
468 sizeof (seg_hash_obj->u.seg_obj->segment.name));
469 seg_hash_obj->u.seg_obj->segment.descriptor = SD_SEGMENT_DESCRIPTOR;
470 /* tag + payload */
471 seg_hash_obj->u.seg_obj->segment.length = MANR_SIZE +
472 SEGMENT_TRAILER_LEN + SEGMENT_CHKSM_LEN;
473 add_to_seg_object_list(sec_hash_obj, seg_hash_obj);
475 pkt_hash_obj = create_packet_hash_object();
476 if (pkt_hash_obj == NULL) {
477 return (-1);
479 add_hashobject_to_hashtable(pkt_hash_obj, PACKET_TYPE);
481 pkt_hash_obj->u.pkt_obj->payload_data = manr;
482 if (mk_tag(FRU_F, 0x001, 0x0B7, &pkt_hash_obj->u.pkt_obj->tag) == 4) {
483 add_to_pkt_object_list(seg_hash_obj, pkt_hash_obj);
485 return (0);
488 /* Look up the container_hdl in the PICL tree. */
489 static container_hdl_t
490 ipmi_fru_open_container(picl_nodehdl_t fruh)
492 int err;
493 hash_obj_t *cont_hash_obj;
495 err = ptree_get_propval_by_name(fruh, PICL_PROP_FRUDATA_AVAIL,
496 NULL, NULL);
497 if (err != PICL_SUCCESS) {
498 return (0);
501 cont_hash_obj = lookup_handle_object((handle_t)fruh, CONTAINER_TYPE);
502 if (cont_hash_obj == NULL) {
503 return (0);
506 /* initialize the container */
507 if (initialize_ipmi_container(fruh, cont_hash_obj) != 0) {
508 return (0);
510 return (cont_hash_obj->obj_hdl);
513 /*ARGSUSED*/
514 static int
515 ipmi_fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
517 hash_obj_t *cont_hash_obj;
519 cont_hash_obj = lookup_handle_object((handle_t)container,
520 CONTAINER_TYPE);
521 if (cont_hash_obj == NULL) {
522 return (-1);
524 return (cont_hash_obj->u.cont_obj->num_of_section);
527 /*ARGSUSED*/
528 static int
529 ipmi_fru_get_sections(container_hdl_t container, section_t *section,
530 int max_sections, door_cred_t *cred)
532 int count;
533 hash_obj_t *cont_object;
534 hash_obj_t *sec_hash;
536 cont_object = lookup_handle_object((handle_t)container,
537 CONTAINER_TYPE);
538 if (cont_object == NULL) {
539 return (-1);
542 if (cont_object->u.cont_obj->num_of_section > max_sections) {
543 return (-1);
545 sec_hash = cont_object->u.cont_obj->sec_obj_list;
547 for (count = 0; count < cont_object->u.cont_obj->num_of_section &&
548 sec_hash != NULL; count++, section++) {
549 /* populate section_t */
550 section->handle = sec_hash->u.sec_obj->section.handle;
551 section->offset = sec_hash->u.sec_obj->section.offset;
552 section->length = sec_hash->u.sec_obj->section.length;
553 section->protection = sec_hash->u.sec_obj->section.protection;
554 section->version = sec_hash->u.sec_obj->section.version;
555 sec_hash = sec_hash->u.sec_obj->next;
557 return (count);
560 /*ARGSUSED*/
561 static int
562 ipmi_fru_get_num_segments(section_hdl_t section, door_cred_t *cred)
564 hash_obj_t *sec_object;
566 sec_object = lookup_handle_object((handle_t)section, SECTION_TYPE);
567 if (sec_object == NULL) {
568 return (-1);
570 return (sec_object->u.sec_obj->num_of_segment);
573 /*ARGSUSED*/
574 static int
575 ipmi_fru_get_segments(section_hdl_t section, segment_t *segment,
576 int max_segments, door_cred_t *cred)
578 int count;
579 hash_obj_t *seg_hash;
580 hash_obj_t *sec_object;
582 sec_object = lookup_handle_object((handle_t)section, SECTION_TYPE);
583 if (sec_object == NULL) {
584 return (-1);
587 if (sec_object->u.sec_obj->num_of_segment > max_segments) {
588 return (-1);
591 seg_hash = sec_object->u.sec_obj->seg_obj_list;
593 for (count = 0; count < sec_object->u.sec_obj->num_of_segment &&
594 seg_hash != NULL; count++, segment++) {
595 /* populate the segment info */
596 segment->handle = seg_hash->u.seg_obj->segment.handle;
597 (void) memcpy(segment->name, seg_hash->u.seg_obj->segment.name,
598 SEG_NAME_LEN);
599 segment->descriptor = seg_hash->u.seg_obj->segment.descriptor;
600 segment->offset = seg_hash->u.seg_obj->segment.offset;
601 segment->length = seg_hash->u.seg_obj->segment.length;
602 seg_hash = seg_hash->u.seg_obj->next;
604 return (count);
607 /*ARGSUSED*/
608 static int
609 ipmi_fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
611 hash_obj_t *seg_object;
613 seg_object = lookup_handle_object((handle_t)segment, SEGMENT_TYPE);
614 if (seg_object == NULL) {
615 return (-1);
617 return (seg_object->u.seg_obj->num_of_packets);
620 /*ARGSUSED*/
621 static int
622 ipmi_fru_get_packets(segment_hdl_t segment, packet_t *packet,
623 int max_packets, door_cred_t *cred)
625 int count;
626 hash_obj_t *pkt_hash;
627 hash_obj_t *seg_object;
629 seg_object = lookup_handle_object((handle_t)segment, SEGMENT_TYPE);
630 if (seg_object == NULL) {
631 return (-1);
634 if (seg_object->u.seg_obj->num_of_packets > max_packets) {
635 return (-1);
638 pkt_hash = seg_object->u.seg_obj->pkt_obj_list;
640 for (count = 0; count < seg_object->u.seg_obj->num_of_packets &&
641 pkt_hash != NULL; count++, packet++) {
642 /* populate the segment info */
643 packet->handle = pkt_hash->obj_hdl;
644 (void) memcpy(&packet->tag, &pkt_hash->u.pkt_obj->tag, 4);
645 pkt_hash = pkt_hash->u.pkt_obj->next;
648 return (count);
651 /*ARGSUSED*/
652 static ssize_t
653 ipmi_fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes,
654 door_cred_t *cred)
656 hash_obj_t *seg_hash;
657 hash_obj_t *pkt_hash;
659 /* segment hash object */
660 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
661 if (seg_hash == NULL) {
662 return (-1);
665 if (seg_hash->u.seg_obj->segment.length < nbytes) {
666 return (-1);
669 pkt_hash = seg_hash->u.seg_obj->pkt_obj_list;
671 if (pkt_hash == NULL) {
672 return (-1);
675 (void) memcpy(buffer, &pkt_hash->u.pkt_obj->payload_data,
676 sizeof (payload_t));
677 return (nbytes);
680 /*ARGSUSED*/
681 static ssize_t
682 ipmi_fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes,
683 door_cred_t *cred)
685 hash_obj_t *packet_hash_obj;
687 /* size = size of ManR */
688 if (nbytes != MANR_SIZE) {
689 return (-1);
692 /* packet hash object */
693 packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE);
694 if (packet_hash_obj == NULL) {
695 return (-1);
698 (void) memcpy(buffer, &(packet_hash_obj->u.pkt_obj->payload_data),
699 MANR_SIZE);
700 return (nbytes);
703 /*ARGSUSED*/
704 static int
705 ipmi_fru_add_segment(section_hdl_t section, segment_t *segment,
706 section_hdl_t *newsection, door_cred_t *cred)
708 errno = ENOTSUP;
709 return (-1);
712 /*ARGSUSED*/
713 static int
714 ipmi_fru_delete_segment(segment_hdl_t segment,
715 section_hdl_t *newsection, door_cred_t *cred)
717 errno = ENOTSUP;
718 return (-1);
722 /*ARGSUSED*/
723 static ssize_t
724 ipmi_fru_write_segment(segment_hdl_t segment, const void *data,
725 size_t nbytes, segment_hdl_t *newsegment, door_cred_t *cred)
727 errno = ENOTSUP;
728 return (-1);
731 /*ARGSUSED*/
732 static int
733 ipmi_fru_update_payload(packet_hdl_t packet, const void *data,
734 size_t nbytes, packet_hdl_t *newpacket, door_cred_t *cred)
736 errno = ENOTSUP;
737 return (-1);
740 /*ARGSUSED*/
741 static int
742 ipmi_fru_append_packet(segment_hdl_t segment, packet_t *packet,
743 const void *payload, size_t nbytes, segment_hdl_t *newsegment,
744 door_cred_t *cred)
746 errno = ENOTSUP;
747 return (-1);
750 /*ARGSUSED*/
751 static int
752 ipmi_fru_delete_packet(packet_hdl_t packet,
753 segment_hdl_t *newsegment, door_cred_t *cred)
755 errno = ENOTSUP;
756 return (-1);
759 static void
760 free_pkt_object_list(hash_obj_t *hash_obj)
762 hash_obj_t *next_obj;
763 hash_obj_t *free_obj;
765 next_obj = hash_obj->u.seg_obj->pkt_obj_list;
766 while (next_obj != NULL) {
767 free_obj = next_obj;
768 next_obj = next_obj->u.pkt_obj->next;
769 /* if prev is NULL it's the first object in the list */
770 if (free_obj->prev == NULL) {
771 hash_table[(free_obj->obj_hdl % TABLE_SIZE)] =
772 free_obj->next;
773 if (free_obj->next != NULL) {
774 free_obj->next->prev = free_obj->prev;
776 } else {
777 free_obj->prev->next = free_obj->next;
778 if (free_obj->next != NULL) {
779 free_obj->next->prev = free_obj->prev;
783 free(free_obj->u.pkt_obj);
784 free(free_obj);
787 hash_obj->u.seg_obj->pkt_obj_list = NULL;
790 static void
791 free_segment_hash(handle_t handle, hash_obj_t *sec_hash)
793 hash_obj_t *seg_hash;
794 hash_obj_t *next_hash;
796 seg_hash = sec_hash->u.sec_obj->seg_obj_list;
797 if (seg_hash == NULL) {
798 return;
801 if (seg_hash->obj_hdl == handle) {
802 sec_hash->u.sec_obj->seg_obj_list = seg_hash->u.seg_obj->next;
803 } else {
804 while (seg_hash->obj_hdl != handle) {
805 next_hash = seg_hash;
806 seg_hash = seg_hash->u.seg_obj->next;
807 if (seg_hash == NULL) {
808 return;
811 next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next;
814 if (seg_hash->prev == NULL) {
815 hash_table[(seg_hash->obj_hdl % TABLE_SIZE)] = seg_hash->next;
816 if (seg_hash->next != NULL) {
817 seg_hash->next->prev = NULL;
819 } else {
820 seg_hash->prev->next = seg_hash->next;
821 if (seg_hash->next != NULL) {
822 seg_hash->next->prev = seg_hash->prev;
826 free_pkt_object_list(seg_hash);
827 free(seg_hash->u.seg_obj);
828 free(seg_hash);
831 static int
832 ipmi_fru_close_container(container_hdl_t container)
834 hash_obj_t *hash_obj;
835 hash_obj_t *prev_hash;
836 hash_obj_t *sec_hash_obj;
837 handle_t obj_hdl;
839 /* lookup for container hash object */
840 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
841 if (hash_obj == NULL) {
842 return (0);
845 /* points to section object list */
846 sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list;
848 /* traverse section object list */
849 while (sec_hash_obj != NULL) {
851 /* traverse segment hash object in the section */
852 while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) {
853 /* object handle of the segment hash object */
854 obj_hdl =
855 sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl;
856 free_segment_hash(obj_hdl, sec_hash_obj);
859 /* going to free section hash object, relink the hash object */
860 if (sec_hash_obj->prev == NULL) {
861 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)]
862 = sec_hash_obj->next;
863 if (sec_hash_obj->next != NULL) {
864 sec_hash_obj->next->prev = NULL;
866 } else {
867 sec_hash_obj->prev->next = sec_hash_obj->next;
868 if (sec_hash_obj->next != NULL) {
869 sec_hash_obj->next->prev = sec_hash_obj->prev;
873 free(sec_hash_obj->u.sec_obj); /* free section hash object */
875 prev_hash = sec_hash_obj;
877 sec_hash_obj = sec_hash_obj->u.sec_obj->next;
879 free(prev_hash); /* free section hash */
882 /* free container hash object */
883 if (hash_obj->prev == NULL) {
884 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] =
885 hash_obj->next;
886 if (hash_obj->next != NULL) {
887 hash_obj->next->prev = NULL;
889 } else {
890 hash_obj->prev->next = hash_obj->next;
891 if (hash_obj->next != NULL) {
892 hash_obj->next->prev = hash_obj->prev;
896 free(hash_obj->u.cont_obj);
897 free(hash_obj);
898 return (0);
901 /* opens the binary file and returns the file descriptor */
902 static int
903 open_file()
905 int fd;
907 if ((fd = open(INPUT_FILE, O_RDWR)) == -1) {
908 return (-1);
910 return (fd);
913 static void
914 copy_segment_layout(segment_t *seghdr, void *layout)
916 segment_layout_t *seg_layout;
918 seg_layout = (segment_layout_t *)layout;
919 (void) memcpy(seghdr->name, &seg_layout->name, SEG_NAME_LEN);
920 seghdr->descriptor = GET_SEGMENT_DESCRIPTOR;
921 seghdr->offset = seg_layout->offset;
922 seghdr->length = seg_layout->length;
925 static hash_obj_t *
926 get_container_hash_object(int object_type, handle_t handle)
928 hash_obj_t *hash_obj;
930 switch (object_type) {
931 case CONTAINER_TYPE :
932 break;
934 case SECTION_TYPE :
935 hash_obj = lookup_handle_object(handle, CONTAINER_TYPE);
936 if (hash_obj == NULL) {
937 return (NULL);
939 break;
940 case SEGMENT_TYPE :
941 hash_obj = lookup_handle_object(handle, SECTION_TYPE);
942 if (hash_obj == NULL) {
943 return (NULL);
945 hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl,
946 CONTAINER_TYPE);
947 break;
948 case PACKET_TYPE :
950 hash_obj = lookup_handle_object(handle, SEGMENT_TYPE);
951 if (hash_obj == NULL) {
952 return (NULL);
954 hash_obj = lookup_handle_object(
955 hash_obj->u.seg_obj->section_hdl, SECTION_TYPE);
956 if (hash_obj == NULL) {
957 return (NULL);
959 hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl,
960 CONTAINER_TYPE);
961 break;
962 default :
963 return (NULL);
965 return (hash_obj);
968 static void
969 sort_offsettbl(int segcnt, seg_info_t *offset_tbl)
971 int cntx;
972 int cnty;
973 seg_info_t tmp;
975 for (cntx = 0; cntx < segcnt+2; cntx++) {
976 for (cnty = cntx+1; cnty < segcnt + 2; cnty++) {
977 if (offset_tbl[cntx].offset >
978 offset_tbl[cnty].offset) {
979 (void) memcpy(&tmp, &offset_tbl[cnty],
980 sizeof (seg_info_t));
981 (void) memcpy(&offset_tbl[cnty],
982 &offset_tbl[cntx],
983 sizeof (seg_info_t));
985 (void) memcpy(&offset_tbl[cntx], &tmp,
986 sizeof (seg_info_t));
993 * Description : move_segment_data() reads the segment data and writes it
994 * back to the new segment offset.
997 static void
998 move_segment_data(void *seghdr, int newoffset, container_hdl_t contfd)
1000 int ret;
1001 char *buffer;
1002 segment_layout_t *segment;
1003 format_t format;
1004 hash_obj_t *cont_hash;
1006 segment = (segment_layout_t *)seghdr;
1008 buffer = alloca(segment->length);
1009 if (buffer == NULL) {
1010 return;
1013 cont_hash = lookup_handle_object((handle_t)contfd, CONTAINER_TYPE);
1014 if (cont_hash == NULL) {
1015 return;
1018 format = cont_hash->u.cont_obj->format;
1020 ret = pread_new(contfd, buffer,
1021 segment->length, segment->offset, &format);
1022 if (ret != segment->length) {
1023 return;
1026 segment->offset = newoffset;
1028 ret = pwrite_new(contfd, buffer, segment->length, segment->offset,
1029 &format);
1030 if (ret != segment->length) {
1031 return;
1036 * Description : pack_segment_data() moves the segment data if there is
1037 * a hole between two segments.
1040 static void
1041 pack_segment_data(char *seghdr, int segcnt, container_hdl_t contfd,
1042 seg_info_t *offset_tbl)
1044 int cnt;
1045 int diff;
1046 int newoffset;
1048 for (cnt = segcnt + 1; cnt > 0; cnt--) {
1049 if (!offset_tbl[cnt - 1].fixed) {
1050 if (offset_tbl[cnt].offset
1051 - (offset_tbl[cnt -1 ].offset
1052 + offset_tbl[cnt - 1].length) > 0) {
1054 diff = offset_tbl[cnt].offset -
1055 (offset_tbl[cnt - 1].offset
1056 + offset_tbl[cnt - 1].length);
1057 newoffset = offset_tbl[cnt - 1].offset
1058 + diff;
1060 move_segment_data(seghdr, newoffset,
1061 contfd);
1063 offset_tbl[cnt - 1].offset = newoffset;
1065 sort_offsettbl(segcnt, offset_tbl);
1072 * Description : build_offset_tbl() builds the offset table by reading all the
1073 * segment header. it makes two more entry into the table one for
1074 * section size and another with start of the section after the
1075 * segment header.
1078 static int
1079 build_offset_tbl(void *seghdr, int segcnt, int secsize,
1080 seg_info_t *offset_tbl)
1082 int cnt;
1083 fru_segdesc_t segdesc;
1084 segment_layout_t *segment;
1086 for (cnt = 0; cnt < segcnt; cnt++) {
1087 segment = (segment_layout_t *)(seghdr) + cnt;
1089 (void) memcpy(&segdesc, &segment->descriptor,
1090 sizeof (uint32_t));
1091 offset_tbl[cnt].segnum = cnt;
1092 offset_tbl[cnt].offset = segment->offset;
1093 offset_tbl[cnt].length = segment->length;
1094 offset_tbl[cnt].fixed = segdesc.field.fixed;
1097 /* upper boundary of segment area (lower address bytes) */
1098 offset_tbl[cnt].segnum = -1;
1099 offset_tbl[cnt].offset = sizeof (section_layout_t) + ((cnt + 1)
1100 * sizeof (segment_layout_t));
1102 offset_tbl[cnt].length = 0;
1103 offset_tbl[cnt].fixed = 1;
1104 /* lower boundary of segment area (higher address bytes) */
1106 offset_tbl[cnt+1].segnum = -1;
1107 offset_tbl[cnt+1].offset = secsize;
1108 offset_tbl[cnt+1].length = 0;
1109 offset_tbl[cnt+1].fixed = 1;
1110 return (0);
1113 static int
1114 hole_discovery(int bytes, int segcnt, int *totsize, seg_info_t *offset_tbl)
1116 int cnt = 0;
1118 *totsize = 0;
1119 for (cnt = segcnt + 1; cnt > 0; cnt--) {
1120 if (bytes <= offset_tbl[cnt].offset -
1121 (offset_tbl[cnt - 1].offset +
1122 offset_tbl[cnt - 1].length)) {
1123 return (offset_tbl[cnt].offset - bytes);
1126 *totsize += offset_tbl[cnt].offset -
1127 (offset_tbl[cnt - 1].offset +
1128 offset_tbl[cnt - 1].length);
1130 return (0);
1135 * Description : segment_hdr_present() verify space for new segment header to
1136 * be added.
1139 static int
1140 segment_hdr_present(int segoffset, int size, seg_info_t *offset_tbl)
1142 if ((segoffset + size) <= offset_tbl[0].offset)
1143 return (0);
1144 else
1145 return (-1);
1149 * Description : find_offset() is called from fru_add_segment routine to find
1150 * a valid offset.
1153 static int
1154 find_offset(char *seghdr, int segcnt, int secsize, int *sectionoffset,
1155 int segsize, int fix, container_hdl_t contfd)
1157 int ret;
1158 int newoffset;
1159 int totsize = 0;
1160 seg_info_t *offset_tbl;
1162 if (segcnt == 0) {
1163 if (!fix) { /* if not fixed segment */
1164 *sectionoffset = secsize - segsize;
1166 return (0);
1170 * two extra segment info structure are allocated for start of segment
1171 * and other end of segment. first segment offset is first available
1172 * space and length is 0. second segment offset is is segment length and
1173 * offset is 0. build_offset_tbl() explains how upper boundary and lower
1174 * boudary segment area are initialized in seg_info_t table.
1177 offset_tbl = malloc((segcnt + 2) * sizeof (seg_info_t));
1178 if (offset_tbl == NULL) {
1179 return (-1);
1182 /* read all the segment header to make offset table */
1183 ret = build_offset_tbl(seghdr, segcnt, secsize, offset_tbl);
1184 if (ret != 0) {
1185 free(offset_tbl);
1186 return (-1);
1189 /* sort the table */
1190 sort_offsettbl(segcnt, offset_tbl);
1192 /* new segment header offset */
1193 newoffset = sizeof (section_layout_t) + segcnt *
1194 sizeof (segment_layout_t);
1196 /* do? new segment header overlap any existing data */
1197 ret = segment_hdr_present(newoffset, sizeof (segment_layout_t),
1198 offset_tbl);
1199 if (ret != 0) { /* make room for new segment if possible */
1201 /* look for hole in order to move segment data */
1202 if (offset_tbl[0].fixed == SEGMENT_FIXED) { /* fixed segment */
1203 free(offset_tbl);
1204 return (-1);
1207 newoffset = hole_discovery(offset_tbl[0].length,
1208 segcnt, &totsize, offset_tbl);
1209 if (newoffset != 0) { /* found new offset */
1210 /* now new offset */
1211 offset_tbl[0].offset = newoffset;
1213 /* move the segment data */
1214 move_segment_data(seghdr, newoffset, contfd);
1215 /* again sort the offset table */
1216 sort_offsettbl(segcnt, offset_tbl);
1217 } else {
1218 /* pack the existing hole */
1219 if (totsize > offset_tbl[0].length) {
1220 pack_segment_data(seghdr, segcnt,
1221 contfd, offset_tbl);
1222 } else {
1223 free(offset_tbl);
1224 return (-1);
1229 totsize = 0;
1230 newoffset = hole_discovery(segsize, segcnt, &totsize, offset_tbl);
1232 if (newoffset == 0) { /* No hole found */
1233 if (totsize >= segsize) {
1234 pack_segment_data(seghdr, segcnt, contfd,
1235 offset_tbl);
1236 newoffset = hole_discovery(segsize, segcnt,
1237 &totsize, offset_tbl);
1238 if (newoffset != 0) {
1239 *sectionoffset = newoffset;
1240 free(offset_tbl);
1241 return (0);
1244 } else {
1245 *sectionoffset = newoffset;
1246 free(offset_tbl);
1247 return (0);
1249 free(offset_tbl);
1250 return (-1);
1254 * Description :sun_fru_open_container() opens the container associated with
1255 * a fru. it's called by data plugin module before creating
1256 * container property. it calls picltree library routine to get
1257 * the device path and driver binding name for the fru to get the
1258 * corresponding fru name that describe the fru layout.
1260 * Arguments :picl_hdl_t fru
1261 * A handle for PICL tree node of class "fru" representing the
1262 * FRU with the container to open.
1264 * Return :
1265 * On Success, a Positive integer container handle. is returned
1266 * for use in subsequent fru operations;on error, 0 is returned
1267 * and "errno" is set appropriately.
1269 static container_hdl_t
1270 sun_fru_open_container(picl_nodehdl_t fruhdl)
1272 int count;
1273 hash_obj_t *cont_hash_obj;
1274 hash_obj_t *sec_hash_obj;
1276 cont_hash_obj = lookup_handle_object((handle_t)fruhdl, CONTAINER_TYPE);
1277 if (cont_hash_obj == NULL) {
1278 return (NULL);
1281 cont_hash_obj->u.cont_obj->num_of_section = NUM_OF_SECTIONS;
1282 cont_hash_obj->u.cont_obj->sec_obj_list = NULL;
1284 for (count = 0; count < NUM_OF_SECTIONS; count++) {
1285 sec_hash_obj = create_section_hash_object();
1286 if (sec_hash_obj == NULL) {
1287 return (NULL);
1290 add_hashobject_to_hashtable(sec_hash_obj, SECTION_TYPE);
1292 if (count == 0) {
1293 sec_hash_obj->u.sec_obj->section.offset =
1294 DYNAMIC_OFFSET;
1295 sec_hash_obj->u.sec_obj->section.protection =
1296 WRITE_SECTION;
1297 sec_hash_obj->u.sec_obj->section.length =
1298 DYNAMIC_LENGTH;
1299 } else {
1300 sec_hash_obj->u.sec_obj->section.offset = STATIC_OFFSET;
1301 sec_hash_obj->u.sec_obj->section.protection =
1302 READ_ONLY_SECTION;
1303 sec_hash_obj->u.sec_obj->section.length = STATIC_LENGTH;
1306 sec_hash_obj->u.sec_obj->section.version = SECTION_HDR_VER;
1308 add_to_sec_object_list(cont_hash_obj, sec_hash_obj);
1311 return (cont_hash_obj->obj_hdl);
1314 static int
1315 verify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length)
1317 int crc_offset = 0;
1318 unsigned char orig_crc8 = 0;
1319 unsigned char calc_crc8 = 0;
1321 switch (head_ver) {
1322 case SECTION_HDR_VER:
1323 crc_offset = 4;
1324 break;
1325 default:
1326 errno = EINVAL;
1327 return (0);
1330 orig_crc8 = bytes[crc_offset];
1331 bytes[crc_offset] = 0x00; /* clear for calc */
1332 calc_crc8 = compute_crc8(bytes, length);
1333 bytes[crc_offset] = orig_crc8; /* restore */
1335 return (orig_crc8 == calc_crc8);
1339 * Description :
1340 * sun_fru_get_num_sections() returns number of sections in a
1341 * container. it calls get_container_index() to get the container
1342 * index number in the container list.
1344 * Arguments :
1345 * container_hdl_t : container handle.
1347 * Return :
1348 * int
1349 * On success, returns number of sections in a container.
1352 /*ARGSUSED*/
1353 static int
1354 sun_fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
1356 hash_obj_t *hash_object;
1358 hash_object = lookup_handle_object(container, CONTAINER_TYPE);
1359 if (hash_object == NULL) {
1360 return (-1);
1363 return (hash_object->u.cont_obj->num_of_section);
1367 * called from fru_get_sections()
1370 static void
1371 get_section(int fd, hash_obj_t *sec_hash, section_t *section)
1373 int retval;
1374 int size;
1375 int count;
1376 uint16_t hdrver;
1377 hash_obj_t *seg_hash;
1378 unsigned char *buffer;
1379 section_obj_t *sec_obj;
1380 section_layout_t sec_hdr;
1381 segment_layout_t *seg_hdr;
1382 segment_layout_t *seg_buf;
1383 format_t format;
1384 hash_obj_t *cont_hash;
1386 sec_obj = sec_hash->u.sec_obj;
1387 if (sec_obj == NULL) {
1388 return;
1391 /* populate section_t */
1392 section->handle = sec_hash->obj_hdl;
1393 section->offset = sec_obj->section.offset;
1394 section->length = sec_obj->section.length;
1395 section->protection = sec_obj->section.protection;
1396 section->version = sec_obj->section.version;
1397 sec_obj->num_of_segment = 0;
1399 cont_hash = get_container_hash_object(SEGMENT_TYPE, sec_hash->obj_hdl);
1400 if (cont_hash == NULL) {
1401 return;
1404 format = cont_hash->u.cont_obj->format;
1406 /* read section header layout */
1407 retval = pread_new(fd, &sec_hdr, sizeof (sec_hdr),
1408 sec_obj->section.offset, &format);
1409 if (retval != sizeof (sec_hdr)) {
1410 return;
1413 hdrver = GET_SECTION_HDR_VERSION;
1415 if ((sec_hdr.headertag != SECTION_HDR_TAG) &&
1416 (hdrver != section->version)) {
1417 return;
1420 /* size = section layout + total sizeof segment header */
1421 size = sizeof (sec_hdr) + ((sec_hdr.segmentcount)
1422 * sizeof (segment_layout_t));
1423 buffer = alloca(size);
1424 if (buffer == NULL) {
1425 return;
1428 /* segment header buffer */
1429 seg_buf = alloca(size - sizeof (sec_hdr));
1430 if (seg_buf == NULL) {
1431 return;
1434 /* read segment header */
1435 retval = pread_new(fd, seg_buf, size - sizeof (sec_hdr),
1436 sec_obj->section.offset + sizeof (sec_hdr), &format);
1437 if (retval != (size - sizeof (sec_hdr))) {
1438 return;
1441 /* copy section header layout */
1442 (void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr));
1444 /* copy segment header layout */
1445 (void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size -
1446 sizeof (sec_hdr));
1448 /* verify crc8 */
1449 retval = verify_header_crc8(hdrver, buffer, size);
1450 if (retval != TRUE) {
1451 return;
1454 section->version = hdrver;
1455 sec_obj->section.version = hdrver;
1457 seg_hdr = (segment_layout_t *)seg_buf;
1459 for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) {
1460 seg_hash = create_segment_hash_object();
1461 if (seg_hash == NULL) {
1462 return;
1465 add_hashobject_to_hashtable(seg_hash, SEGMENT_TYPE);
1467 copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_hdr);
1469 add_to_seg_object_list(sec_hash, seg_hash);
1471 sec_obj->num_of_segment++;
1476 * Description :
1477 * sun_fru_get_sections() fills an array of section structures
1478 * passed as an argument.
1480 * Arguments :
1481 * container_hdl_t : container handle(device descriptor).
1482 * section_t : array of section structure.
1483 * int : maximum number of section in a container.
1485 * Returns :
1486 * int
1487 * On success,the number of section structures written is returned;
1488 * on error, -1 is returned and "errno" is set appropriately.
1491 /*ARGSUSED*/
1492 static int
1493 sun_fru_get_sections(container_hdl_t container, section_t *section, int maxsec,
1494 door_cred_t *cred)
1496 int device_fd;
1497 int count;
1498 hash_obj_t *cont_object;
1499 hash_obj_t *sec_hash;
1501 cont_object = lookup_handle_object(container, CONTAINER_TYPE);
1502 if (cont_object == NULL) {
1503 return (-1);
1506 if (cont_object->u.cont_obj->num_of_section > maxsec) {
1507 return (-1);
1510 sec_hash = cont_object->u.cont_obj->sec_obj_list;
1511 if (sec_hash == NULL) {
1512 return (-1);
1515 device_fd = open_file();
1517 if (device_fd < 0) {
1518 return (-1);
1521 for (count = 0; count < cont_object->u.cont_obj->num_of_section;
1522 count++, section++) {
1523 section->version = -1;
1524 /* populate section_t */
1525 get_section(device_fd, sec_hash, section);
1526 sec_hash = sec_hash->u.sec_obj->next;
1529 (void) close(device_fd);
1531 return (count);
1535 * Description :
1536 * sun_fru_get_num_segments() returns the current number of
1537 * segments in a section.
1539 * Arguments :
1540 * section_hdl_t : section header holding section information.
1542 * Return :
1543 * int
1544 * On success, the number of segments in the argument section is
1545 * returned; on error -1 is returned.
1547 /*ARGSUSED*/
1548 static int
1549 sun_fru_get_num_segments(section_hdl_t section, door_cred_t *cred)
1551 hash_obj_t *sec_object;
1552 section_obj_t *sec_obj;
1554 sec_object = lookup_handle_object(section, SECTION_TYPE);
1555 if (sec_object == NULL) {
1556 return (-1);
1559 sec_obj = sec_object->u.sec_obj;
1560 if (sec_obj == NULL) {
1561 return (-1);
1564 return (sec_obj->num_of_segment);
1568 * Description :
1569 * sun_fru_get_segments() fills an array of structures
1570 * representing the segments in a section.
1572 * Arguments :
1573 * section_hdl_t : holds section number.
1574 * segment_t : on success will hold segment information.
1575 * int : maximum number of segment.
1577 * Return :
1578 * int
1579 * On success, the number of segment structures written is
1580 * returned; on errno -1 is returned.
1582 /* ARGSUSED */
1583 static int
1584 sun_fru_get_segments(section_hdl_t section, segment_t *segment, int maxseg,
1585 door_cred_t *cred)
1587 int count;
1588 hash_obj_t *sec_object;
1589 hash_obj_t *seg_object;
1590 section_obj_t *sec_obj;
1592 sec_object = lookup_handle_object(section, SECTION_TYPE);
1593 if (sec_object == NULL) {
1594 return (-1);
1597 sec_obj = sec_object->u.sec_obj;
1598 if (sec_obj == NULL) {
1599 return (-1);
1602 if (sec_obj->num_of_segment > maxseg) {
1603 return (-1);
1606 seg_object = sec_object->u.sec_obj->seg_obj_list;
1607 if (seg_object == NULL) {
1608 return (-1);
1611 for (count = 0; count < sec_obj->num_of_segment; count++) {
1613 /* populate segment_t */
1614 segment->handle = seg_object->obj_hdl;
1615 (void) memcpy(segment->name,
1616 seg_object->u.seg_obj->segment.name, SEG_NAME_LEN);
1617 segment->descriptor = seg_object->u.seg_obj->segment.descriptor;
1618 segment->offset = seg_object->u.seg_obj->segment.offset;
1619 segment->length = seg_object->u.seg_obj->segment.length;
1620 seg_object = seg_object->u.seg_obj->next;
1621 segment++;
1623 return (0);
1627 * Description :
1628 * sun_fru_add_segment() adds a segment to a section.
1630 * Arguments :
1631 * section_hdl_t section
1632 * A handle for the section in which to add the segment.
1634 * segment_t *segment
1635 * On entry, the "handle" component of "segment" is ignored and the
1636 * remaining components specify the parameters of the segment to be
1637 * added. On return, the "handle" component is set to the handle
1638 * for the added segment. The segment offset is mandatory for FIXED
1639 * segments; otherwise, the offset is advisory.
1641 * Return :
1642 * int
1643 * On success, 0 is returned; on error -1 is returned.
1646 static int
1647 sun_fru_add_segment(section_hdl_t section, segment_t *segment,
1648 section_hdl_t *newsection, door_cred_t *cred)
1650 int fd;
1651 int retval;
1652 int offset;
1653 int sec_size;
1654 int seg_cnt;
1655 int bufsize;
1656 int new_seg_offset;
1657 int new_seg_length;
1658 int fixed_segment;
1659 char trailer[] = { 0x0c, 0x00, 0x00, 0x00, 0x00 };
1660 hash_obj_t *cont_hash;
1661 hash_obj_t *sec_hash;
1662 hash_obj_t *seg_hash;
1663 fru_segdesc_t *new_seg_desc;
1664 unsigned char *crcbuf;
1665 section_layout_t sec_layout;
1666 segment_layout_t *seg_layout;
1667 segment_layout_t *segment_buf;
1668 format_t format;
1670 /* check the effective uid of the client */
1671 if (cred->dc_euid != 0) {
1672 errno = EPERM;
1673 return (-1); /* not a root */
1676 /* section hash */
1677 sec_hash = lookup_handle_object(section, SECTION_TYPE);
1678 if (sec_hash == NULL) {
1679 return (-1);
1682 /* check for read-only section */
1683 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
1684 errno = EPERM;
1685 return (-1);
1688 /* look for duplicate segment */
1689 seg_hash = sec_hash->u.sec_obj->seg_obj_list;
1690 while (seg_hash != NULL) {
1691 if (strncmp(segment->name, seg_hash->u.seg_obj->segment.name,
1692 SEG_NAME_LEN) == 0) {
1693 errno = EEXIST;
1694 return (-1); /* can't add duplicate segment */
1696 seg_hash = seg_hash->u.seg_obj->next;
1699 /* get the container hash */
1700 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
1701 CONTAINER_TYPE);
1702 if (cont_hash == NULL) {
1703 return (-1);
1706 format = cont_hash->u.cont_obj->format;
1708 /* open the container */
1709 fd = open_file();
1710 if (fd < 0) {
1711 return (-1);
1714 /* section start here */
1715 offset = sec_hash->u.sec_obj->section.offset;
1717 /* read section header layout */
1718 retval = pread_new(fd, &sec_layout, sizeof (sec_layout), offset,
1719 &format);
1720 if (retval != sizeof (sec_layout)) {
1721 (void) close(fd);
1722 return (-1);
1725 /* check for valid section header */
1726 if (sec_layout.headertag != SECTION_HDR_TAG) {
1727 /* write a new one */
1728 sec_layout.headertag = SECTION_HDR_TAG;
1729 sec_layout.headerversion[0] = SECTION_HDR_VER_BIT0;
1730 sec_layout.headerversion[1] = SECTION_HDR_VER_BIT1;
1731 sec_layout.headerlength = sizeof (sec_layout);
1732 sec_layout.segmentcount = 0;
1735 /* section size */
1736 sec_size = sec_hash->u.sec_obj->section.length;
1738 /* number of segment in the section */
1739 seg_cnt = sec_layout.segmentcount;
1741 /* total sizeof segment + new segment */
1742 bufsize = sizeof (segment_layout_t) * (seg_cnt + 1);
1743 segment_buf = alloca(bufsize);
1744 if (segment_buf == NULL) {
1745 return (-1);
1748 /* read entire segment header */
1749 retval = pread_new(fd, segment_buf,
1750 (bufsize - sizeof (segment_layout_t)),
1751 offset + sizeof (section_layout_t), &format);
1752 if (retval != (bufsize - sizeof (segment_layout_t))) {
1753 (void) close(fd);
1754 return (-1);
1757 new_seg_offset = segment->offset; /* new segment offset */
1758 new_seg_length = segment->length; /* new segment length */
1760 new_seg_desc = (fru_segdesc_t *)&segment->descriptor;
1762 fixed_segment = new_seg_desc->field.fixed;
1764 /* get new offset for new segment to be addedd */
1765 retval = find_offset((char *)segment_buf, seg_cnt, sec_size,
1766 &new_seg_offset, new_seg_length, fixed_segment, fd);
1768 if (retval != 0) {
1769 (void) close(fd);
1770 errno = EAGAIN;
1771 return (-1);
1774 /* copy new segment data in segment layout */
1775 seg_layout = (segment_layout_t *)(segment_buf + seg_cnt);
1776 (void) memcpy(&seg_layout->name, segment->name, SEG_NAME_LEN);
1777 (void) memcpy(seg_layout->descriptor, &segment->descriptor,
1778 sizeof (uint32_t));
1779 seg_layout->length = segment->length;
1780 seg_layout->offset = new_seg_offset; /* new segment offset */
1782 sec_layout.segmentcount += 1;
1784 crcbuf = alloca(sizeof (section_layout_t) + bufsize);
1785 if (crcbuf == NULL) {
1786 (void) close(fd);
1787 return (-1);
1790 sec_layout.headercrc8 = 0;
1791 sec_layout.headerlength += sizeof (segment_layout_t);
1793 (void) memcpy(crcbuf, (char *)&sec_layout, sizeof (section_layout_t));
1794 (void) memcpy(crcbuf + sizeof (section_layout_t), segment_buf, bufsize);
1796 sec_layout.headercrc8 = compute_crc8(crcbuf, bufsize +
1797 sizeof (section_layout_t));
1799 /* write section header */
1800 retval = pwrite_new(fd, &sec_layout, sizeof (section_layout_t),
1801 offset, &format);
1802 if (retval != sizeof (section_layout_t)) {
1803 (void) close(fd);
1804 return (-1);
1807 /* write segment header */
1808 retval = pwrite_new(fd, segment_buf, bufsize, offset +
1809 sizeof (section_layout_t), &format);
1810 if (retval != bufsize) {
1811 (void) close(fd);
1812 return (-1);
1815 /* write segment trailer */
1816 retval = pwrite_new(fd, &trailer, sizeof (trailer), new_seg_offset,
1817 &format);
1818 if (retval != sizeof (trailer)) {
1819 (void) close(fd);
1820 return (-1);
1823 (void) close(fd);
1825 /* create new segment hash object */
1826 seg_hash = create_segment_hash_object();
1827 if (seg_hash == NULL) {
1828 return (-1);
1831 add_hashobject_to_hashtable(seg_hash, SEGMENT_TYPE);
1833 copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_layout);
1835 add_to_seg_object_list(sec_hash, seg_hash);
1837 sec_hash->u.sec_obj->num_of_segment += 1;
1838 seg_hash->u.seg_obj->trailer_offset = new_seg_offset;
1839 *newsection = section; /* return the new section handle */
1840 return (0);
1844 * Description :
1845 * sun_fru_delete_segment() deletes a segment from a section; the
1846 * associated container data is not altered.
1848 * Arguments : segment_hdl_t segment handle.
1849 * section_hdl_t new section handle.
1851 * Return :
1852 * int
1853 * On success, 0 returned; On error -1 is returned.
1855 static int
1856 sun_fru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection,
1857 door_cred_t *cred)
1859 int num_of_seg;
1860 int bufsize;
1861 int count;
1862 int retval;
1863 int fd;
1864 int segnum;
1865 hash_obj_t *seg_hash;
1866 hash_obj_t *sec_hash;
1867 hash_obj_t *cont_hash;
1868 hash_obj_t *tmp_hash;
1869 unsigned char *buffer;
1870 fru_segdesc_t *desc;
1871 segment_layout_t *seg_buf;
1872 section_layout_t *sec_layout;
1873 segment_layout_t *seg_layout;
1874 segment_layout_t *next_layout;
1875 format_t format;
1877 /* check the effective uid of the client */
1878 if (cred->dc_euid != 0) {
1879 errno = EPERM;
1880 return (-1); /* not a root */
1883 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
1884 if (seg_hash == NULL) {
1885 return (-1);
1888 desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
1889 if (!(desc->field.field_perm & SEGMENT_DELETE)) {
1890 errno = EPERM;
1891 return (-1); /* can't delete this segment */
1894 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
1895 SECTION_TYPE);
1896 if (sec_hash == NULL) {
1897 return (-1);
1900 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
1901 errno = EPERM;
1902 return (-1);
1905 num_of_seg = sec_hash->u.sec_obj->num_of_segment;
1907 bufsize = (sizeof (segment_layout_t) * num_of_seg);
1909 seg_buf = alloca(bufsize);
1910 if (seg_buf == NULL) {
1911 return (-1);
1914 segnum = 0;
1915 for (tmp_hash = sec_hash->u.sec_obj->seg_obj_list; tmp_hash != NULL;
1916 tmp_hash = tmp_hash->u.seg_obj->next) {
1917 if (tmp_hash->obj_hdl == segment) {
1918 break;
1920 segnum++;
1923 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
1924 CONTAINER_TYPE);
1925 if (cont_hash == NULL) {
1926 return (-1);
1928 format = cont_hash->u.cont_obj->format;
1930 fd = open_file();
1931 if (fd < 0) {
1932 return (-1);
1935 sec_layout = alloca(sizeof (section_layout_t));
1936 if (sec_layout == NULL) {
1937 (void) close(fd);
1938 return (-1);
1941 /* read section layout header */
1942 retval = pread_new(fd, sec_layout, sizeof (section_layout_t),
1943 sec_hash->u.sec_obj->section.offset, &format);
1944 if (retval != sizeof (section_layout_t)) {
1945 (void) close(fd);
1946 return (-1);
1949 /* read segment header layout */
1950 retval = pread_new(fd, seg_buf, bufsize,
1951 sec_hash->u.sec_obj->section.offset +
1952 sizeof (section_layout_t), &format);
1953 if (retval != bufsize) {
1954 (void) close(fd);
1955 return (-1);
1958 seg_layout = (segment_layout_t *)(seg_buf + segnum);
1959 next_layout = seg_layout;
1960 for (count = segnum; count < sec_hash->u.sec_obj->num_of_segment-1;
1961 count++) {
1962 next_layout++;
1963 (void) memcpy(seg_layout, next_layout,
1964 sizeof (segment_layout_t));
1965 seg_layout++;
1968 (void) memset(seg_layout, '\0', sizeof (segment_layout_t));
1970 sec_layout->headercrc8 = 0;
1972 sec_layout->headerlength -= sizeof (segment_layout_t);
1973 sec_layout->segmentcount -= 1;
1975 buffer = alloca(sec_layout->headerlength);
1976 if (buffer == NULL) {
1977 (void) close(fd);
1978 return (-1);
1981 (void) memcpy(buffer, sec_layout, sizeof (section_layout_t));
1982 (void) memcpy(buffer + sizeof (section_layout_t), seg_buf, bufsize
1983 - sizeof (segment_layout_t));
1984 sec_layout->headercrc8 = compute_crc8(buffer,
1985 sec_layout->headerlength);
1987 /* write section header with update crc8 and header length */
1988 retval = pwrite_new(fd, sec_layout, sizeof (section_layout_t),
1989 sec_hash->u.sec_obj->section.offset, &format);
1990 if (retval != sizeof (section_layout_t)) {
1991 (void) close(fd);
1992 return (-1);
1995 /* write the update segment header */
1996 retval = pwrite_new(fd, seg_buf, bufsize,
1997 sec_hash->u.sec_obj->section.offset +
1998 sizeof (section_layout_t), &format);
1999 (void) close(fd);
2000 if (retval != bufsize) {
2001 return (-1);
2004 free_segment_hash(segment, sec_hash);
2006 *newsection = sec_hash->obj_hdl;
2007 sec_hash->u.sec_obj->num_of_segment = sec_layout->segmentcount;
2009 return (0);
2013 * Description :
2014 * sun_fru_read_segment() reads the raw contents of a segment.
2016 * Arguments : segment_hdl_t : segment handle.
2017 * void * : buffer containing segment data when function returns.
2018 * size_t :number of bytes.
2020 * Return :
2021 * int
2022 * On success, the number of bytes read is returned;
2024 * Notes :
2025 * Segments containing packets can be read in structured fashion
2026 * using the fru_get_packets() and fru_get_payload() primitives;the
2027 * entire byte range of a segment can be read using
2028 * fru_read_segment().
2030 /*ARGSUSED*/
2031 static ssize_t
2032 sun_fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes,
2033 door_cred_t *cred)
2035 int fd;
2036 int retval;
2037 hash_obj_t *seg_hash;
2038 hash_obj_t *sec_hash;
2039 hash_obj_t *cont_hash;
2040 format_t format;
2042 /* segment hash object */
2043 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
2044 if (seg_hash == NULL) {
2045 return (-1);
2048 /* section hash object */
2049 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2050 SECTION_TYPE);
2051 if (sec_hash == NULL) {
2052 return (-1);
2055 /* container hash object */
2056 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
2057 CONTAINER_TYPE);
2058 if (cont_hash == NULL) {
2059 return (-1);
2061 format = cont_hash->u.cont_obj->format;
2063 if (seg_hash->u.seg_obj->segment.length < nbytes) {
2064 return (-1);
2067 fd = open_file();
2068 if (fd < 0) {
2069 return (-1);
2072 retval = pread_new(fd, buffer, nbytes,
2073 seg_hash->u.seg_obj->segment.offset, &format);
2074 (void) close(fd);
2075 if (retval != nbytes) {
2076 return (-1);
2078 return (nbytes);
2082 * Description :
2083 * sun_fru_write_segment() writes a raw segment.
2085 * Arguments : segment_hdl_t :segment handle.
2086 * const void * : data buffer.
2087 * size_t : number of bytes.
2088 * segment_hdl_t : new segment handle.
2090 * Returns :
2091 * int
2092 * On success, the number of bytes written is returned
2095 /*ARGSUSED*/
2096 static int
2097 sun_fru_write_segment(segment_hdl_t segment, const void *data, size_t nbytes,
2098 segment_hdl_t *newsegment, door_cred_t *cred)
2100 return (ENOTSUP);
2104 static int
2105 get_packet(int device_fd, void *buffer, int size, int offset, format_t *format)
2107 int retval;
2109 retval = pread_new(device_fd, (char *)buffer, size, offset, format);
2110 if (retval != -1) {
2111 return (0);
2113 return (-1);
2116 static uint32_t
2117 get_checksum_crc(hash_obj_t *seg_hash, int data_size)
2119 int protection;
2120 int offset = 0;
2121 uint32_t crc;
2122 hash_obj_t *sec_hash;
2123 hash_obj_t *pkt_hash;
2124 unsigned char *buffer;
2126 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2127 SECTION_TYPE);
2128 if (sec_hash == NULL) {
2129 return ((uint32_t)-1);
2132 buffer = alloca(data_size);
2133 if (buffer == NULL) {
2134 return ((uint32_t)-1);
2137 /* traverse the packet object list for all the tags and payload */
2138 for (pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; pkt_hash != NULL;
2139 pkt_hash = pkt_hash->u.pkt_obj->next) {
2140 (void) memcpy(buffer + offset, &pkt_hash->u.pkt_obj->tag,
2141 pkt_hash->u.pkt_obj->tag_size);
2142 offset += pkt_hash->u.pkt_obj->tag_size;
2143 (void) memcpy(buffer + offset, pkt_hash->u.pkt_obj->payload,
2144 pkt_hash->u.pkt_obj->paylen);
2145 offset += pkt_hash->u.pkt_obj->paylen;
2148 protection = sec_hash->u.sec_obj->section.protection;
2150 if (protection == READ_ONLY_SECTION) { /* read-only section */
2151 crc = compute_crc32(buffer, data_size);
2152 } else { /* read/write section */
2153 crc = compute_checksum32(buffer, data_size);
2155 return (crc); /* computed crc */
2158 static int
2159 get_packets(hash_obj_t *seg_hash, int device_fd, int offset, int length)
2161 int tag_size;
2162 int paylen;
2163 int retval;
2164 int seg_limit = 0;
2165 int pktcnt = 0;
2166 char *data;
2167 uint32_t crc;
2168 uint32_t origcrc;
2169 fru_tag_t tag;
2170 hash_obj_t *pkt_hash_obj;
2171 fru_segdesc_t *segdesc;
2172 fru_tagtype_t tagtype;
2173 format_t format;
2174 hash_obj_t *cont_hash;
2176 cont_hash = get_container_hash_object(PACKET_TYPE, seg_hash->obj_hdl);
2177 if (cont_hash == NULL) {
2178 return (NULL);
2180 format = cont_hash->u.cont_obj->format;
2182 retval = get_packet(device_fd, &tag, sizeof (fru_tag_t), offset,
2183 &format);
2184 if (retval == -1) {
2185 return (-1);
2188 seg_hash->u.seg_obj->trailer_offset = offset;
2190 data = (char *)&tag;
2191 while (data[0] != SEG_TRAILER_TAG) {
2192 tagtype = get_tag_type(&tag); /* verify tag type */
2193 if (tagtype == -1) {
2194 return (-1);
2197 tag_size = get_tag_size(tagtype);
2198 if (tag_size == -1) {
2199 return (-1);
2202 seg_limit += tag_size;
2203 if (seg_limit > length) {
2204 return (-1);
2207 paylen = get_payload_length((void *)&tag);
2208 if (paylen == -1) {
2209 return (-1);
2212 seg_limit += paylen;
2213 if (seg_limit > length) {
2214 return (-1);
2217 pkt_hash_obj = create_packet_hash_object();
2218 if (pkt_hash_obj == NULL) {
2219 return (-1);
2222 pkt_hash_obj->u.pkt_obj->payload = malloc(paylen);
2223 if (pkt_hash_obj->u.pkt_obj->payload == NULL) {
2224 free(pkt_hash_obj);
2225 return (-1);
2228 offset += tag_size;
2229 retval = pread_new(device_fd, pkt_hash_obj->u.pkt_obj->payload,
2230 paylen, offset, &format);
2231 if (retval != paylen) {
2232 free(pkt_hash_obj->u.pkt_obj->payload);
2233 free(pkt_hash_obj);
2234 return (-1);
2237 /* don't change this */
2238 pkt_hash_obj->u.pkt_obj->tag.raw_data = 0;
2239 (void) memcpy(&pkt_hash_obj->u.pkt_obj->tag, &tag, tag_size);
2240 pkt_hash_obj->u.pkt_obj->paylen = paylen;
2241 pkt_hash_obj->u.pkt_obj->tag_size = tag_size;
2242 pkt_hash_obj->u.pkt_obj->payload_offset = offset;
2244 offset += paylen;
2246 add_hashobject_to_hashtable(pkt_hash_obj, PACKET_TYPE);
2247 add_to_pkt_object_list(seg_hash, pkt_hash_obj);
2249 pktcnt++;
2251 retval = get_packet(device_fd, &tag, sizeof (fru_tag_t),
2252 offset, &format);
2253 if (retval == -1) {
2254 return (retval);
2257 data = (char *)&tag;
2260 segdesc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
2262 seg_hash->u.seg_obj->trailer_offset = offset;
2264 if (!segdesc->field.ignore_checksum) {
2265 crc = get_checksum_crc(seg_hash, seg_limit);
2266 offset = seg_hash->u.seg_obj->segment.offset;
2268 retval = pread_new(device_fd, &origcrc, sizeof (origcrc),
2269 offset + seg_limit + 1, &format);
2270 if (retval != sizeof (origcrc)) {
2271 return (-1);
2274 if (origcrc != crc) {
2275 seg_hash->u.seg_obj->trailer_offset = offset;
2276 return (-1);
2279 return (pktcnt);
2283 * Description :
2284 * sun_fru_get_num_packets() returns the current number of packets
2285 * in a segment.
2287 * Arguments : segment_hdl_t : segment handle.
2289 * Return :
2290 * int
2291 * On success, the number of packets is returned;
2292 * -1 on failure.
2294 /*ARGSUSED*/
2295 static int
2296 sun_fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
2298 int device_fd;
2299 int pktcnt;
2300 int length;
2301 uint16_t offset;
2302 hash_obj_t *cont_hash_obj;
2303 hash_obj_t *seg_hash;
2304 fru_segdesc_t *segdesc;
2305 segment_obj_t *segment_object;
2307 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
2308 if (seg_hash == NULL) {
2309 return (-1);
2312 segment_object = seg_hash->u.seg_obj;
2313 if (segment_object == NULL) {
2314 return (-1);
2318 segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor;
2319 if (segdesc->field.opaque) {
2320 return (0);
2323 offset = segment_object->segment.offset;
2324 length = segment_object->segment.length;
2326 cont_hash_obj = get_container_hash_object(SEGMENT_TYPE,
2327 segment_object->section_hdl);
2329 if (cont_hash_obj == NULL) {
2330 return (-1);
2333 if (seg_hash->u.seg_obj->pkt_obj_list != NULL) {
2334 return (segment_object->num_of_packets);
2337 segment_object->num_of_packets = 0;
2338 device_fd = open_file();
2339 if (device_fd < 0) {
2340 return (-1);
2343 pktcnt = get_packets(seg_hash, device_fd, offset,
2344 length);
2345 if (pktcnt == -1) {
2346 free_pkt_object_list(seg_hash);
2347 seg_hash->u.seg_obj->pkt_obj_list = NULL;
2350 segment_object->num_of_packets = pktcnt;
2351 (void) close(device_fd);
2353 return (segment_object->num_of_packets);
2357 * Description :
2358 * sun_fru_get_packets() fills an array of structures
2359 * representing the packets in a segment.
2361 * Arguments : segment_hdl_t : segment handle.
2362 * packet_t : packet buffer.
2363 * int : maximum number of packets.
2365 * Return :
2366 * int
2367 * On success, the number of packet structures written is returned;
2368 * On failure -1 is returned;
2371 /*ARGSUSED*/
2372 static int
2373 sun_fru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets,
2374 door_cred_t *cred)
2376 int count;
2377 hash_obj_t *seg_hash_obj;
2378 hash_obj_t *pkt_hash_obj;
2380 /* segment hash object */
2381 seg_hash_obj = lookup_handle_object(segment, SEGMENT_TYPE);
2382 if (seg_hash_obj == NULL) {
2383 return (-1);
2386 if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) {
2387 return (-1);
2390 pkt_hash_obj = seg_hash_obj->u.seg_obj->pkt_obj_list;
2391 if (pkt_hash_obj == NULL) {
2392 return (-1);
2395 for (count = 0; count < maxpackets; count++, packet++) {
2396 packet->handle = pkt_hash_obj->obj_hdl;
2397 packet->tag = 0;
2398 (void) memcpy(&packet->tag, &pkt_hash_obj->u.pkt_obj->tag,
2399 pkt_hash_obj->u.pkt_obj->tag_size);
2400 pkt_hash_obj = pkt_hash_obj->u.pkt_obj->next;
2403 return (0);
2407 * Description :
2408 * sun_fru_get_payload() copies the contents of a packet's payload.
2410 * Arguments : packet_hdl_t : packet handle.
2411 * void * : payload buffer.
2412 * size_t : sizeof the buffer.
2414 * Return :
2415 * int
2416 * On success, the number of bytes copied is returned; On error
2417 * -1 returned.
2419 /*ARGSUSED*/
2420 static ssize_t
2421 sun_fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes,
2422 door_cred_t *cred)
2424 hash_obj_t *packet_hash_obj;
2426 /* packet hash object */
2427 packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE);
2428 if (packet_hash_obj == NULL) {
2429 return (-1);
2432 /* verify payload length */
2433 if (nbytes != packet_hash_obj->u.pkt_obj->paylen) {
2434 return (-1);
2437 (void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes);
2438 return (nbytes);
2442 * Description :
2443 * sun_fru_update_payload() writes the contents of a packet's
2444 * payload.
2446 * Arguments : packet_hdl_t : packet handle.
2447 * const void * : data buffer.
2448 * size_t : buffer size.
2449 * packet_hdl_t : new packet handle.
2451 * Return :
2452 * int
2453 * On success, 0 is returned; on failure
2454 * -1 is returned.
2456 /*ARGSUSED*/
2457 static int
2458 sun_fru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes,
2459 packet_hdl_t *newpacket, door_cred_t *cred)
2461 int fd;
2462 int segment_offset;
2463 int trailer_offset;
2464 int retval;
2465 uint32_t crc;
2466 hash_obj_t *pkt_hash;
2467 hash_obj_t *seg_hash;
2468 hash_obj_t *sec_hash;
2469 hash_obj_t *cont_hash;
2470 fru_segdesc_t *desc;
2471 format_t format;
2473 /* check the effective uid of the client */
2474 if (cred->dc_euid != 0) {
2475 errno = EPERM;
2476 return (-1); /* not a root */
2479 /* packet hash object */
2480 pkt_hash = lookup_handle_object(packet, PACKET_TYPE);
2481 if (pkt_hash == NULL) {
2482 return (-1);
2485 /* segment hash object */
2486 seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl,
2487 SEGMENT_TYPE);
2488 if (seg_hash == NULL) {
2489 return (-1);
2492 /* check for write perm. */
2493 desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
2494 if (!(desc->field.field_perm & SEGMENT_WRITE)) {
2495 errno = EPERM;
2496 return (-1); /* write not allowed */
2499 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2500 SECTION_TYPE);
2501 if (sec_hash == NULL) {
2502 return (-1);
2505 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
2506 errno = EPERM;
2507 return (-1); /* read-only section */
2510 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
2511 CONTAINER_TYPE);
2512 if (cont_hash == NULL) {
2513 return (-1);
2516 format = cont_hash->u.cont_obj->format;
2518 if (pkt_hash->u.pkt_obj->paylen != nbytes) {
2519 return (-1);
2522 (void) memcpy(pkt_hash->u.pkt_obj->payload, (char *)data, nbytes);
2523 fd = open_file();
2524 if (fd < 0) {
2525 return (-1);
2528 trailer_offset = seg_hash->u.seg_obj->trailer_offset;
2529 segment_offset = seg_hash->u.seg_obj->segment.offset;
2531 crc = get_checksum_crc(seg_hash, (trailer_offset - segment_offset));
2532 retval = pwrite_new(fd, data, nbytes,
2533 pkt_hash->u.pkt_obj->payload_offset, &format);
2534 if (retval != nbytes) {
2535 (void) close(fd);
2536 return (-1);
2539 retval = pwrite_new(fd, &crc, sizeof (crc),
2540 trailer_offset + 1, &format);
2541 (void) close(fd);
2542 if (retval != sizeof (crc)) {
2543 return (-1);
2545 *newpacket = packet;
2546 return (0);
2550 * Description :
2551 * sun_fru_append_packet() appends a packet to a segment.
2553 * Arguments :
2554 * segment_hdl_t segment
2555 * A handle for the segment to which the packet will be appended.
2557 * packet_t *packet
2558 * On entry, the "tag" component of "packet" specifies the tag
2559 * value for the added packet; the "handle" component is ignored.
2560 * On return, the "handle" component is set to the handle of the
2561 * appended packet.
2563 * const void *payload
2564 * A pointer to the caller's buffer containing the payload data for
2565 * the appended packet.
2567 * size_t nbytes
2568 * The size of the caller buffer.
2570 * Return :
2571 * int
2572 * On success, 0 is returned; on error -1 is returned;
2574 static int
2575 sun_fru_append_packet(segment_hdl_t segment, packet_t *packet,
2576 const void *payload, size_t nbytes, segment_hdl_t *newsegment,
2577 door_cred_t *cred)
2579 int trailer_offset;
2580 int tag_size;
2581 int fd;
2582 int retval;
2583 char trailer[] = {0x0c, 0x00, 0x00, 0x00, 0x00};
2584 uint32_t crc;
2585 hash_obj_t *seg_hash;
2586 hash_obj_t *sec_hash;
2587 hash_obj_t *pkt_hash;
2588 hash_obj_t *cont_hash;
2589 fru_tagtype_t tagtype;
2590 fru_segdesc_t *desc;
2591 format_t format;
2593 /* check the effective uid of the client */
2594 if (cred->dc_euid != 0) {
2595 errno = EPERM;
2596 return (-1); /* not a root */
2599 seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
2600 if (seg_hash == NULL) {
2601 return (-1);
2604 /* check for write perm. */
2605 desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
2606 if (!(desc->field.field_perm & SEGMENT_WRITE)) {
2607 errno = EPERM;
2608 return (-1); /* write not allowed */
2611 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2612 SECTION_TYPE);
2613 if (sec_hash == NULL) {
2614 return (-1);
2617 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
2618 errno = EPERM;
2619 return (-1); /* read-only section */
2622 trailer_offset = seg_hash->u.seg_obj->trailer_offset;
2625 * if trailer offset is 0 than parse the segment data to get the trailer
2626 * offset to compute the remaining space left in the segment area for
2627 * new packet to be added.
2629 if (trailer_offset == 0) {
2630 (void) sun_fru_get_num_packets(segment, cred);
2631 trailer_offset = seg_hash->u.seg_obj->trailer_offset;
2634 tagtype = get_tag_type((void *)&packet->tag);
2635 if (tagtype == -1) {
2636 return (-1);
2639 tag_size = get_tag_size(tagtype);
2640 if (tag_size == -1) {
2641 return (-1);
2644 if (seg_hash->u.seg_obj->segment.length >
2645 ((trailer_offset - seg_hash->u.seg_obj->segment.offset) +
2646 tag_size + nbytes +
2647 sizeof (char) + sizeof (uint32_t))) {
2648 /* create new packet hash */
2649 pkt_hash = create_packet_hash_object();
2650 if (pkt_hash == NULL) {
2651 return (-1);
2654 /* tag initialization */
2655 (void) memcpy(&pkt_hash->u.pkt_obj->tag, &packet->tag,
2656 tag_size);
2657 pkt_hash->u.pkt_obj->tag_size = tag_size;
2659 /* payload inititalization */
2660 pkt_hash->u.pkt_obj->payload = malloc(nbytes);
2661 if (pkt_hash->u.pkt_obj->payload == NULL) {
2662 free(pkt_hash);
2663 return (-1);
2666 (void) memcpy(pkt_hash->u.pkt_obj->payload, payload, nbytes);
2667 pkt_hash->u.pkt_obj->paylen = nbytes;
2668 pkt_hash->u.pkt_obj->payload_offset = trailer_offset + tag_size;
2670 /* add to hash table */
2671 add_hashobject_to_hashtable(pkt_hash, PACKET_TYPE);
2673 add_to_pkt_object_list(seg_hash, pkt_hash);
2675 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
2676 CONTAINER_TYPE);
2677 if (cont_hash == NULL) {
2678 return (-1);
2680 format = cont_hash->u.cont_obj->format;
2682 fd = open_file();
2683 if (fd < 0) {
2684 return (-1);
2687 /* update the trailer offset */
2688 trailer_offset += tag_size + nbytes;
2690 /* calculate new checksum */
2691 crc = get_checksum_crc(seg_hash, (trailer_offset -
2692 seg_hash->u.seg_obj->segment.offset));
2694 retval = pwrite_new(fd, &packet->tag, tag_size, trailer_offset
2695 - (tag_size + nbytes), &format);
2696 if (retval != tag_size) {
2697 (void) close(fd);
2698 return (-1);
2701 retval = pwrite_new(fd, payload, nbytes,
2702 trailer_offset - nbytes, &format);
2703 if (retval != nbytes) {
2704 (void) close(fd);
2705 return (-1);
2708 retval = pwrite_new(fd, trailer, sizeof (trailer),
2709 trailer_offset, &format);
2710 if (retval != sizeof (trailer)) {
2711 (void) close(fd);
2712 return (-1);
2715 retval = pwrite_new(fd, &crc, sizeof (crc),
2716 trailer_offset + 1, &format);
2717 (void) close(fd);
2718 if (retval != sizeof (crc)) {
2719 return (-1);
2722 seg_hash->u.seg_obj->trailer_offset = trailer_offset;
2723 seg_hash->u.seg_obj->num_of_packets += 1;
2725 *newsegment = segment; /* return new segment handle */
2726 return (0);
2727 } else {
2728 errno = EAGAIN;
2731 return (-1);
2734 static void
2735 adjust_packets(int fd, hash_obj_t *free_obj, hash_obj_t *object_list)
2737 int retval;
2738 uint32_t new_offset;
2739 hash_obj_t *hash_ptr;
2740 format_t format;
2741 hash_obj_t *hash_obj;
2743 hash_obj = lookup_handle_object(free_obj->obj_hdl, PACKET_TYPE);
2744 if (hash_obj == NULL) {
2745 return;
2747 hash_obj = get_container_hash_object(PACKET_TYPE,
2748 hash_obj->u.pkt_obj->segment_hdl);
2749 if (hash_obj == NULL) {
2750 return;
2752 format = hash_obj->u.cont_obj->format;
2754 new_offset = free_obj->u.pkt_obj->payload_offset
2755 - free_obj->u.pkt_obj->tag_size;
2756 for (hash_ptr = object_list; hash_ptr != NULL;
2757 hash_ptr = hash_ptr->u.pkt_obj->next) {
2758 retval = pwrite_new(fd, &hash_ptr->u.pkt_obj->tag,
2759 hash_ptr->u.pkt_obj->tag_size, new_offset, &format);
2760 if (retval != hash_ptr->u.pkt_obj->tag_size) {
2761 return;
2763 new_offset += hash_ptr->u.pkt_obj->tag_size;
2764 hash_ptr->u.pkt_obj->payload_offset = new_offset;
2765 retval = pwrite_new(fd, hash_ptr->u.pkt_obj->payload,
2766 hash_ptr->u.pkt_obj->paylen, new_offset, &format);
2767 if (retval != hash_ptr->u.pkt_obj->paylen) {
2768 return;
2770 new_offset += hash_ptr->u.pkt_obj->paylen;
2774 static void
2775 free_packet_object(handle_t handle, hash_obj_t *seg_hash)
2777 hash_obj_t *pkt_hash;
2778 hash_obj_t *next_hash;
2780 pkt_hash = seg_hash->u.seg_obj->pkt_obj_list;
2781 if (pkt_hash == NULL) {
2782 return;
2785 if (pkt_hash->obj_hdl == handle) {
2786 seg_hash->u.seg_obj->pkt_obj_list = pkt_hash->u.pkt_obj->next;
2787 } else {
2788 while (pkt_hash->obj_hdl != handle) {
2789 next_hash = pkt_hash;
2790 pkt_hash = pkt_hash->u.pkt_obj->next;
2791 if (pkt_hash == NULL) {
2792 return;
2795 next_hash->u.pkt_obj->next = pkt_hash->u.pkt_obj->next;
2798 if (pkt_hash->prev == NULL) {
2799 hash_table[(pkt_hash->obj_hdl % TABLE_SIZE)] = pkt_hash->next;
2800 if (pkt_hash->next != NULL) {
2801 pkt_hash->next->prev = NULL;
2803 } else {
2804 pkt_hash->prev->next = pkt_hash->next;
2805 if (pkt_hash->next != NULL) {
2806 pkt_hash->next->prev = pkt_hash->prev;
2810 free(pkt_hash->u.pkt_obj->payload);
2811 free(pkt_hash->u.pkt_obj);
2812 free(pkt_hash);
2816 * Description :
2817 * sun_fru_delete_packet() deletes a packet from a segment.
2819 * Arguments : packet_hdl_t : packet number to be deleted.
2820 * segment_hdl_t : new segment handler.
2822 * Return :
2823 * int
2824 * On success, 0 is returned; on error, -1.
2826 * NOTES
2827 * Packets are adjacent; thus, deleting a packet requires moving
2828 * succeeding packets to compact the resulting hole.
2830 static int
2831 sun_fru_delete_packet(packet_hdl_t packet, segment_hdl_t *newsegment,
2832 door_cred_t *cred)
2834 int retval;
2835 int fd;
2836 char trailer[] = { 0x0c, 0x00, 0x00, 0x00, 0x00};
2837 uint32_t crc;
2838 hash_obj_t *tmp_obj;
2839 hash_obj_t *pkt_hash;
2840 hash_obj_t *sec_hash;
2841 hash_obj_t *cont_hash;
2842 hash_obj_t *prev_obj;
2843 hash_obj_t *seg_hash;
2844 fru_segdesc_t *desc;
2845 format_t format;
2847 /* check the effective uid of the client */
2848 if (cred->dc_euid != 0) {
2849 errno = EPERM;
2850 return (-1); /* not a root */
2853 /* packet hash object */
2854 pkt_hash = lookup_handle_object(packet, PACKET_TYPE);
2855 if (pkt_hash == NULL) {
2856 return (-1);
2859 /* segment hash object */
2860 seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl,
2861 SEGMENT_TYPE);
2862 if (seg_hash == NULL) {
2863 return (-1);
2866 /* check for write perm. */
2867 desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
2868 if (!(desc->field.field_perm & SEGMENT_WRITE)) {
2869 errno = EPERM;
2870 return (-1); /* write not allowed */
2873 /* section hash object */
2874 sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
2875 SECTION_TYPE);
2876 if (sec_hash == NULL) {
2877 return (-1);
2880 if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
2881 errno = EPERM;
2882 return (-1); /* read-only section */
2885 prev_obj = seg_hash->u.seg_obj->pkt_obj_list;
2886 if (prev_obj == NULL) {
2887 return (-1);
2890 /* container hash object */
2891 cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
2892 CONTAINER_TYPE);
2893 if (cont_hash == NULL) {
2894 return (-1);
2897 format = cont_hash->u.cont_obj->format;
2899 fd = open_file();
2900 if (fd < 0) {
2901 return (-1);
2904 if (prev_obj->obj_hdl == packet) { /* first object to be deleted */
2905 adjust_packets(fd, prev_obj, prev_obj->u.pkt_obj->next);
2906 seg_hash->u.seg_obj->trailer_offset -=
2907 (prev_obj->u.pkt_obj->tag_size
2908 + prev_obj->u.pkt_obj->paylen);
2909 free_packet_object(packet, seg_hash);
2910 } else {
2911 for (tmp_obj = prev_obj;
2912 tmp_obj != NULL; tmp_obj = tmp_obj->u.pkt_obj->next) {
2913 /* found the object */
2914 if (tmp_obj->obj_hdl == packet) {
2915 adjust_packets(fd, tmp_obj,
2916 tmp_obj->u.pkt_obj->next);
2917 seg_hash->u.seg_obj->trailer_offset -=
2918 (tmp_obj->u.pkt_obj->tag_size
2919 + tmp_obj->u.pkt_obj->paylen);
2920 free_packet_object(packet, seg_hash);
2925 seg_hash->u.seg_obj->num_of_packets -= 1;
2927 /* calculate checksum */
2928 crc = get_checksum_crc(seg_hash, (seg_hash->u.seg_obj->trailer_offset
2929 - seg_hash->u.seg_obj->segment.offset));
2930 /* write trailer at new offset */
2931 retval = pwrite_new(fd, &trailer, sizeof (trailer),
2932 seg_hash->u.seg_obj->trailer_offset, &format);
2933 if (retval != sizeof (trailer)) {
2934 (void) close(fd);
2935 return (-1);
2938 /* write the checksum value */
2939 retval = pwrite_new(fd, &crc, sizeof (crc),
2940 seg_hash->u.seg_obj->trailer_offset + 1, &format);
2941 (void) close(fd);
2942 if (retval != sizeof (crc)) {
2943 return (-1);
2946 *newsegment = seg_hash->obj_hdl; /* return new segment handle */
2947 return (0);
2951 * Description :
2952 * sun_fru_close_container() removes the association between a
2953 * container and its handle. this routines free's up all the
2954 * hash object contained under container.
2956 * Arguments :
2957 * container_hdl_t holds the file descriptor of the fru.
2959 * Return :
2960 * int
2961 * return 0.
2964 /* ARGSUSED */
2965 static int
2966 sun_fru_close_container(container_hdl_t container)
2968 hash_obj_t *hash_obj;
2969 hash_obj_t *prev_hash;
2970 hash_obj_t *sec_hash_obj;
2971 handle_t obj_hdl;
2973 /* lookup for container hash object */
2974 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
2975 if (hash_obj == NULL) {
2976 return (0);
2979 /* points to section object list */
2980 sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list;
2982 /* traverse section object list */
2983 while (sec_hash_obj != NULL) {
2985 /* traverse segment hash object in the section */
2986 while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) {
2987 /* object handle of the segment hash object */
2988 obj_hdl =
2989 sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl;
2990 free_segment_hash(obj_hdl, sec_hash_obj);
2993 /* going to free section hash object, relink the hash object */
2994 if (sec_hash_obj->prev == NULL) {
2995 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)]
2996 = sec_hash_obj->next;
2997 if (sec_hash_obj->next != NULL) {
2998 sec_hash_obj->next->prev = NULL;
3000 } else {
3001 sec_hash_obj->prev->next = sec_hash_obj->next;
3002 if (sec_hash_obj->next != NULL) {
3003 sec_hash_obj->next->prev = sec_hash_obj->prev;
3007 free(sec_hash_obj->u.sec_obj); /* free section hash object */
3009 prev_hash = sec_hash_obj;
3011 sec_hash_obj = sec_hash_obj->u.sec_obj->next;
3013 free(prev_hash); /* free section hash */
3016 /* free container hash object */
3017 if (hash_obj->prev == NULL) {
3018 hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] =
3019 hash_obj->next;
3020 if (hash_obj->next != NULL) {
3021 hash_obj->next->prev = NULL;
3023 } else {
3024 hash_obj->prev->next = hash_obj->next;
3025 if (hash_obj->next != NULL) {
3026 hash_obj->next->prev = hash_obj->prev;
3030 free(hash_obj->u.cont_obj);
3031 free(hash_obj);
3032 return (0);
3036 * FRU ACCESS API
3040 * Description :
3041 * fru_is_data_available checks if the fruid information
3042 * is available or not on a give fru
3044 * Arguments :
3045 * picl_nodehdl_t hold picl node handle of the fru.
3047 * Return :
3048 * int
3049 * return 0 - if fruid is not present.
3050 * return 1 - if fruid is present.
3053 fru_is_data_available(picl_nodehdl_t fruh)
3055 int retval, ret;
3056 uint8_t slot_no;
3057 picl_nodehdl_t parenth;
3058 format_t fru_format;
3059 hash_obj_t *cont_hash_obj;
3061 if (is_valid_chassis == -1) {
3062 if (fruaccess_platmod_check_chassis() == 0) {
3063 is_valid_chassis = 1;
3064 } else {
3065 is_valid_chassis = 0;
3069 if (!is_valid_chassis) {
3070 return (0);
3073 retval = ptree_get_propval_by_name(fruh, PICL_PROP_PARENT,
3074 &parenth, sizeof (picl_nodehdl_t));
3075 if (retval != PICL_SUCCESS) {
3076 return (0);
3079 if (fruaccess_platmod_check_fru(parenth) != 0) {
3080 return (0);
3083 retval = ptree_get_propval_by_name(parenth, PICL_PROP_GEO_ADDR,
3084 &slot_no, sizeof (uint8_t));
3085 if (retval != PICL_SUCCESS) {
3086 return (0);
3089 if (fruaccess_platmod_init_format(slot_no, &fru_format) !=
3090 PICL_SUCCESS) {
3091 return (0);
3094 ret = is_fru_data_available(precedence, slot_no, &fru_format);
3095 if (ret && (fru_format.format != NO_FRUDATA)) {
3096 goto create;
3097 } else {
3098 return (0);
3100 create:
3102 cont_hash_obj = create_container_hash_object();
3103 if (cont_hash_obj == NULL) {
3104 return (0);
3107 cont_hash_obj->obj_hdl = fruh;
3108 cont_hash_obj->u.cont_obj->format = fru_format;
3110 /* if both formats are present follow the precedence */
3111 if (fru_format.format == 0x3) {
3112 if (precedence == IPMI_FORMAT) {
3113 cont_hash_obj->u.cont_obj->format.format = IPMI_FORMAT;
3114 } else {
3115 cont_hash_obj->u.cont_obj->format.format = SUN_FORMAT;
3118 add_hashobject_to_hashtable(cont_hash_obj, CONTAINER_TYPE);
3119 return (1);
3123 * FRU ACCESS API
3127 * All the routines check the fruid format and redirects the call to
3128 * to appropriate routines depending on fruid format.
3129 * All SUN format routines start with sun_ prefix.
3130 * All IPMI format routines start with ipmi_ prefix.
3132 container_hdl_t
3133 fru_open_container(picl_nodehdl_t fru)
3135 hash_obj_t *hash_obj;
3136 format_t fru_format;
3138 hash_obj = lookup_handle_object((handle_t)fru, CONTAINER_TYPE);
3139 if (hash_obj == NULL) {
3140 return (-1);
3142 fru_format = hash_obj->u.cont_obj->format;
3143 return (fruaccess_func[fru_format.format - 1].open_container(fru));
3147 fru_close_container(container_hdl_t container)
3149 int ret;
3150 format_t fru_format;
3151 hash_obj_t *hash_obj;
3153 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
3154 if (hash_obj == NULL) {
3155 return (-1);
3158 fru_format = hash_obj->u.cont_obj->format;
3159 ret = fruaccess_func[fru_format.format - 1].close_container(container);
3160 return (ret);
3164 fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
3166 int ret;
3167 format_t fru_format;
3168 hash_obj_t *hash_obj;
3170 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
3171 if (hash_obj == NULL) {
3172 return (-1);
3174 fru_format = hash_obj->u.cont_obj->format;
3175 ret = fruaccess_func[fru_format.format - 1].get_num_sections(container,
3176 cred);
3177 return (ret);
3181 fru_get_sections(container_hdl_t container, section_t *section,
3182 int max_sections, door_cred_t *cred)
3184 int ret;
3185 format_t fru_format;
3186 hash_obj_t *hash_obj;
3188 hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
3189 if (hash_obj == NULL) {
3190 return (-1);
3192 fru_format = hash_obj->u.cont_obj->format;
3194 ret = fruaccess_func[fru_format.format - 1].get_sections(container,
3195 section, max_sections, cred);
3196 return (ret);
3200 fru_get_num_segments(section_hdl_t section, door_cred_t *rarg)
3202 int ret;
3203 format_t fru_format;
3204 hash_obj_t *hash_obj;
3206 hash_obj = get_container_hash_object(SEGMENT_TYPE, section);
3207 if (hash_obj == NULL) {
3208 return (-1);
3210 fru_format = hash_obj->u.cont_obj->format;
3212 ret = fruaccess_func[fru_format.format - 1].get_num_segments(section,
3213 rarg);
3214 return (ret);
3218 fru_get_segments(section_hdl_t section, segment_t *segment,
3219 int max_segments, door_cred_t *rarg)
3221 int ret;
3222 format_t fru_format;
3223 hash_obj_t *hash_obj;
3225 hash_obj = get_container_hash_object(SEGMENT_TYPE, section);
3226 if (hash_obj == NULL) {
3227 return (-1);
3229 fru_format = hash_obj->u.cont_obj->format;
3230 ret = fruaccess_func[fru_format.format - 1].get_segments(section,
3231 segment, max_segments, rarg);
3232 return (ret);
3236 fru_add_segment(section_hdl_t section, segment_t *segment,
3237 section_hdl_t *newsection, door_cred_t *cred)
3239 int ret;
3240 format_t fru_format;
3241 hash_obj_t *hash_obj;
3243 hash_obj = get_container_hash_object(SEGMENT_TYPE, section);
3244 if (hash_obj == NULL) {
3245 return (-1);
3247 fru_format = hash_obj->u.cont_obj->format;
3249 ret = fruaccess_func[fru_format.format - 1].add_segment(section,
3250 segment, newsection, cred);
3251 return (ret);
3255 fru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection,
3256 door_cred_t *cred)
3258 int ret;
3259 format_t fru_format;
3260 hash_obj_t *hash_obj;
3262 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3263 if (hash_obj == NULL) {
3264 return (-1);
3266 fru_format = hash_obj->u.cont_obj->format;
3267 ret = fruaccess_func[fru_format.format - 1].delete_segment(segment,
3268 newsection, cred);
3269 return (ret);
3272 ssize_t
3273 fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes,
3274 door_cred_t *cred)
3276 ssize_t ret;
3277 format_t fru_format;
3278 hash_obj_t *hash_obj;
3280 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3281 if (hash_obj == NULL) {
3282 return (-1);
3284 fru_format = hash_obj->u.cont_obj->format;
3285 ret = fruaccess_func[fru_format.format - 1].read_segment(segment,
3286 buffer, nbytes, cred);
3287 return (ret);
3291 fru_write_segment(segment_hdl_t segment, const void *data, size_t nbytes,
3292 segment_hdl_t *newsegment, door_cred_t *cred)
3294 int ret;
3295 format_t fru_format;
3296 hash_obj_t *hash_obj;
3298 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3299 if (hash_obj == NULL) {
3300 return (-1);
3302 fru_format = hash_obj->u.cont_obj->format;
3304 ret = fruaccess_func[fru_format.format - 1].write_segment(segment,
3305 data, nbytes, newsegment, cred);
3306 return (ret);
3310 fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
3312 int ret;
3313 format_t fru_format;
3314 hash_obj_t *hash_obj;
3316 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3317 if (hash_obj == NULL) {
3318 return (-1);
3320 fru_format = hash_obj->u.cont_obj->format;
3322 ret = fruaccess_func[fru_format.format - 1].get_num_packets(segment,
3323 cred);
3324 return (ret);
3328 fru_get_packets(segment_hdl_t segment, packet_t *packet,
3329 int max_packets, door_cred_t *cred)
3331 int ret;
3332 format_t fru_format;
3333 hash_obj_t *hash_obj;
3335 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3336 if (hash_obj == NULL) {
3337 return (-1);
3339 fru_format = hash_obj->u.cont_obj->format;
3341 ret = fruaccess_func[fru_format.format - 1].get_packets(segment,
3342 packet, max_packets, cred);
3343 return (ret);
3346 ssize_t
3347 fru_get_payload(packet_hdl_t packet, void *buffer,
3348 size_t nbytes, door_cred_t *cred)
3350 ssize_t ret;
3351 format_t fru_format;
3352 hash_obj_t *hash_obj;
3354 hash_obj = lookup_handle_object(packet, PACKET_TYPE);
3355 if (hash_obj == NULL) {
3356 return (-1);
3359 hash_obj = get_container_hash_object(PACKET_TYPE,
3360 hash_obj->u.pkt_obj->segment_hdl);
3361 if (hash_obj == NULL) {
3362 return (-1);
3364 fru_format = hash_obj->u.cont_obj->format;
3366 ret = fruaccess_func[fru_format.format - 1].get_payload(packet, buffer,
3367 nbytes, cred);
3368 return (ret);
3372 fru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes,
3373 packet_hdl_t *newpacket, door_cred_t *cred)
3375 int ret;
3376 format_t fru_format;
3377 hash_obj_t *hash_obj;
3379 hash_obj = lookup_handle_object(packet, PACKET_TYPE);
3380 if (hash_obj == NULL) {
3381 return (-1);
3384 hash_obj = get_container_hash_object(PACKET_TYPE,
3385 hash_obj->u.pkt_obj->segment_hdl);
3386 if (hash_obj == NULL) {
3387 return (-1);
3389 fru_format = hash_obj->u.cont_obj->format;
3390 ret = fruaccess_func[fru_format.format - 1].update_payload(packet, data,
3391 nbytes, newpacket, cred);
3392 return (ret);
3396 fru_append_packet(segment_hdl_t segment, packet_t *packet,
3397 const void *payload, size_t nbytes, segment_hdl_t *newsegment,
3398 door_cred_t *cred)
3400 int ret;
3401 format_t fru_format;
3402 hash_obj_t *hash_obj;
3404 hash_obj = get_container_hash_object(PACKET_TYPE, segment);
3405 if (hash_obj == NULL) {
3406 return (-1);
3408 fru_format = hash_obj->u.cont_obj->format;
3410 ret = fruaccess_func[fru_format.format - 1].append_packet(segment,
3411 packet, payload, nbytes, newsegment, cred);
3412 return (ret);
3416 fru_delete_packet(packet_hdl_t packet, segment_hdl_t *newsegment,
3417 door_cred_t *cred)
3419 int ret;
3420 format_t fru_format;
3421 hash_obj_t *hash_obj;
3423 hash_obj = lookup_handle_object(packet, PACKET_TYPE);
3424 if (hash_obj == NULL) {
3425 return (-1);
3428 hash_obj = get_container_hash_object(PACKET_TYPE,
3429 hash_obj->u.pkt_obj->segment_hdl);
3430 if (hash_obj == NULL) {
3431 return (-1);
3433 fru_format = hash_obj->u.cont_obj->format;
3435 ret = fruaccess_func[fru_format.format - 1].delete_packet(packet,
3436 newsegment, cred);
3437 return (ret);