17c478bdstevel@tonic-gate/*
27c478bdstevel@tonic-gate * CDDL HEADER START
37c478bdstevel@tonic-gate *
47c478bdstevel@tonic-gate * The contents of this file are subject to the terms of the
5af3025fdt * Common Development and Distribution License (the "License").
6af3025fdt * You may not use this file except in compliance with the License.
77c478bdstevel@tonic-gate *
87c478bdstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
97c478bdstevel@tonic-gate * or http://www.opensolaris.org/os/licensing.
107c478bdstevel@tonic-gate * See the License for the specific language governing permissions
117c478bdstevel@tonic-gate * and limitations under the License.
127c478bdstevel@tonic-gate *
137c478bdstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each
147c478bdstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
157c478bdstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the
167c478bdstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying
177c478bdstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner]
187c478bdstevel@tonic-gate *
197c478bdstevel@tonic-gate * CDDL HEADER END
207c478bdstevel@tonic-gate */
217c478bdstevel@tonic-gate/*
22af3025fdt * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
237c478bdstevel@tonic-gate * Use is subject to license terms.
247c478bdstevel@tonic-gate */
257c478bdstevel@tonic-gate
267c478bdstevel@tonic-gate#pragma ident	"%Z%%M%	%I%	%E% SMI"
277c478bdstevel@tonic-gate
287c478bdstevel@tonic-gate#include <limits.h>
297c478bdstevel@tonic-gate#include <alloca.h>
307c478bdstevel@tonic-gate#include "fru_access_impl.h"
317c478bdstevel@tonic-gate
327c478bdstevel@tonic-gate#pragma init(initialize_fruaccess)	/* .init section */
337c478bdstevel@tonic-gate
347c478bdstevel@tonic-gatestatic	hash_obj_t	*hash_table[TABLE_SIZE];
357c478bdstevel@tonic-gate
367c478bdstevel@tonic-gate/*
377c478bdstevel@tonic-gate * seeprom is the driver_name for the SEEPROM device drivers in excalibur
387c478bdstevel@tonic-gate * Define the devfsadm command to load the seeprom drivers if open fails.
397c478bdstevel@tonic-gate */
407c478bdstevel@tonic-gate
417c478bdstevel@tonic-gatestatic	char	devfsadm_cmd[] = "/usr/sbin/devfsadm -i seeprom";
427c478bdstevel@tonic-gate
437c478bdstevel@tonic-gate/* this routine initialize the hash table. */
447c478bdstevel@tonic-gate
457c478bdstevel@tonic-gatestatic void
467c478bdstevel@tonic-gateinitialize_fruaccess(void)
477c478bdstevel@tonic-gate{
487c478bdstevel@tonic-gate	int	count;
497c478bdstevel@tonic-gate	for (count = 0; count < TABLE_SIZE; count++) {
507c478bdstevel@tonic-gate		hash_table[count] = NULL;
517c478bdstevel@tonic-gate	}
527c478bdstevel@tonic-gate}
537c478bdstevel@tonic-gate
547c478bdstevel@tonic-gate/*
557c478bdstevel@tonic-gate * called to lookup hash object for specified handle in the hash table.
567c478bdstevel@tonic-gate *
577c478bdstevel@tonic-gate */
587c478bdstevel@tonic-gate
597c478bdstevel@tonic-gatestatic hash_obj_t *
607c478bdstevel@tonic-gatelookup_handle_object(handle_t	handle, int object_type)
617c478bdstevel@tonic-gate{
627c478bdstevel@tonic-gate	handle_t	index_to_hash;
637c478bdstevel@tonic-gate	hash_obj_t	*first_hash_obj;
647c478bdstevel@tonic-gate	hash_obj_t	*next_hash_obj;
657c478bdstevel@tonic-gate
667c478bdstevel@tonic-gate	index_to_hash	= (handle % TABLE_SIZE);
677c478bdstevel@tonic-gate
687c478bdstevel@tonic-gate	first_hash_obj = hash_table[index_to_hash];
697c478bdstevel@tonic-gate	for (next_hash_obj = first_hash_obj; next_hash_obj != NULL;
707c478bdstevel@tonic-gate	    next_hash_obj = next_hash_obj->next) {
717c478bdstevel@tonic-gate		if ((handle == next_hash_obj->obj_hdl) &&
727c478bdstevel@tonic-gate		    (object_type == next_hash_obj->object_type)) {
737c478bdstevel@tonic-gate			return (next_hash_obj);
747c478bdstevel@tonic-gate		}
757c478bdstevel@tonic-gate	}
767c478bdstevel@tonic-gate	return (NULL);
777c478bdstevel@tonic-gate}
787c478bdstevel@tonic-gate
797c478bdstevel@tonic-gate/* called to allocate container hash object */
807c478bdstevel@tonic-gate
817c478bdstevel@tonic-gatestatic hash_obj_t *
827c478bdstevel@tonic-gatecreate_container_hash_object(void)
837c478bdstevel@tonic-gate{
847c478bdstevel@tonic-gate	hash_obj_t		*hash_obj;
857c478bdstevel@tonic-gate	container_obj_t		*cont_obj;
867c478bdstevel@tonic-gate
877c478bdstevel@tonic-gate	cont_obj	= malloc(sizeof (container_obj_t));
887c478bdstevel@tonic-gate	if (cont_obj == NULL) {
897c478bdstevel@tonic-gate		return (NULL);
907c478bdstevel@tonic-gate	}
917c478bdstevel@tonic-gate
927c478bdstevel@tonic-gate	hash_obj = malloc(sizeof (hash_obj_t));
937c478bdstevel@tonic-gate	if (hash_obj == NULL) {
947c478bdstevel@tonic-gate		free(cont_obj);
957c478bdstevel@tonic-gate		return (NULL);
967c478bdstevel@tonic-gate	}
977c478bdstevel@tonic-gate
987c478bdstevel@tonic-gate	cont_obj->sec_obj_list	= NULL;
997c478bdstevel@tonic-gate
1007c478bdstevel@tonic-gate	hash_obj->object_type	= CONTAINER_TYPE;
1017c478bdstevel@tonic-gate	hash_obj->u.cont_obj	= cont_obj;
1027c478bdstevel@tonic-gate	hash_obj->next	= NULL;
1037c478bdstevel@tonic-gate	hash_obj->prev	= NULL;
1047c478bdstevel@tonic-gate
1057c478bdstevel@tonic-gate	return (hash_obj);
1067c478bdstevel@tonic-gate}
1077c478bdstevel@tonic-gate
1087c478bdstevel@tonic-gate/* called to allocate section hash object */
1097c478bdstevel@tonic-gate
1107c478bdstevel@tonic-gatestatic hash_obj_t *
1117c478bdstevel@tonic-gatecreate_section_hash_object(void)
1127c478bdstevel@tonic-gate{
1137c478bdstevel@tonic-gate	hash_obj_t		*hash_obj;
1147c478bdstevel@tonic-gate	section_obj_t		*sec_obj;
1157c478bdstevel@tonic-gate
1167c478bdstevel@tonic-gate	sec_obj	= malloc(sizeof (section_obj_t));
1177c478bdstevel@tonic-gate	if (sec_obj == NULL) {
1187c478bdstevel@tonic-gate		return (NULL);
1197c478bdstevel@tonic-gate	}
1207c478bdstevel@tonic-gate
1217c478bdstevel@tonic-gate	hash_obj = malloc(sizeof (hash_obj_t));
1227c478bdstevel@tonic-gate	if (hash_obj == NULL) {
1237c478bdstevel@tonic-gate		free(sec_obj);
1247c478bdstevel@tonic-gate		return (NULL);
1257c478bdstevel@tonic-gate	}
1267c478bdstevel@tonic-gate
1277c478bdstevel@tonic-gate	sec_obj->next		= NULL;
1287c478bdstevel@tonic-gate	sec_obj->seg_obj_list	= NULL;
1297c478bdstevel@tonic-gate
1307c478bdstevel@tonic-gate	hash_obj->u.sec_obj	= sec_obj;
1317c478bdstevel@tonic-gate	hash_obj->object_type	= SECTION_TYPE;
1327c478bdstevel@tonic-gate	hash_obj->next		= NULL;
1337c478bdstevel@tonic-gate	hash_obj->prev		= NULL;
1347c478bdstevel@tonic-gate
1357c478bdstevel@tonic-gate	return (hash_obj);
1367c478bdstevel@tonic-gate}
1377c478bdstevel@tonic-gate
1387c478bdstevel@tonic-gate/* called to allocate segment hash object */
1397c478bdstevel@tonic-gate
1407c478bdstevel@tonic-gatestatic hash_obj_t *
1417c478bdstevel@tonic-gatecreate_segment_hash_object(void)
1427c478bdstevel@tonic-gate{
1437c478bdstevel@tonic-gate	hash_obj_t		*hash_obj;
1447c478bdstevel@tonic-gate	segment_obj_t		*seg_obj;
1457c478bdstevel@tonic-gate
1467c478bdstevel@tonic-gate	seg_obj	= malloc(sizeof (segment_obj_t));
1477c478bdstevel@tonic-gate	if (seg_obj == NULL) {
1487c478bdstevel@tonic-gate		return (NULL);
1497c478bdstevel@tonic-gate	}
1507c478bdstevel@tonic-gate
1517c478bdstevel@tonic-gate	hash_obj = malloc(sizeof (hash_obj_t));
1527c478bdstevel@tonic-gate	if (hash_obj == NULL) {
1537c478bdstevel@tonic-gate		free(seg_obj);
1547c478bdstevel@tonic-gate		return (NULL);
1557c478bdstevel@tonic-gate	}
1567c478bdstevel@tonic-gate
1577c478bdstevel@tonic-gate	seg_obj->next		= NULL;
1587c478bdstevel@tonic-gate	seg_obj->pkt_obj_list	= NULL;
1597c478bdstevel@tonic-gate
1607c478bdstevel@tonic-gate	hash_obj->object_type	= SEGMENT_TYPE;
1617c478bdstevel@tonic-gate	hash_obj->u.seg_obj	= seg_obj;
1627c478bdstevel@tonic-gate	hash_obj->next		= NULL;
1637c478bdstevel@tonic-gate	hash_obj->prev		= NULL;
1647c478bdstevel@tonic-gate
1657c478bdstevel@tonic-gate	return (hash_obj);
1667c478bdstevel@tonic-gate}
1677c478bdstevel@tonic-gate
1687c478bdstevel@tonic-gate/* called to allocate packet hash object */
1697c478bdstevel@tonic-gate
1707c478bdstevel@tonic-gatestatic hash_obj_t *
1717c478bdstevel@tonic-gatecreate_packet_hash_object(void)
1727c478bdstevel@tonic-gate{
1737c478bdstevel@tonic-gate	hash_obj_t		*hash_obj;
1747c478bdstevel@tonic-gate	packet_obj_t		*pkt_obj;
1757c478bdstevel@tonic-gate
1767c478bdstevel@tonic-gate	pkt_obj	= malloc(sizeof (packet_obj_t));
1777c478bdstevel@tonic-gate	if (pkt_obj == NULL) {
1787c478bdstevel@tonic-gate		return (NULL);
1797c478bdstevel@tonic-gate	}
1807c478bdstevel@tonic-gate
1817c478bdstevel@tonic-gate	hash_obj	= malloc(sizeof (hash_obj_t));
1827c478bdstevel@tonic-gate	if (hash_obj == NULL) {
1837c478bdstevel@tonic-gate		free(pkt_obj);
1847c478bdstevel@tonic-gate		return (NULL);
1857c478bdstevel@tonic-gate	}
1867c478bdstevel@tonic-gate
1877c478bdstevel@tonic-gate	pkt_obj->next		= NULL;
1887c478bdstevel@tonic-gate
1897c478bdstevel@tonic-gate	hash_obj->object_type	= PACKET_TYPE;
1907c478bdstevel@tonic-gate	hash_obj->u.pkt_obj	= pkt_obj;
1917c478bdstevel@tonic-gate	hash_obj->next		= NULL;
1927c478bdstevel@tonic-gate	hash_obj->prev		= NULL;
1937c478bdstevel@tonic-gate
1947c478bdstevel@tonic-gate	return (hash_obj);
1957c478bdstevel@tonic-gate}
1967c478bdstevel@tonic-gate
1977c478bdstevel@tonic-gate/* called to add allocated hash object into the hash table */
1987c478bdstevel@tonic-gate
1997c478bdstevel@tonic-gatestatic void
2007c478bdstevel@tonic-gateadd_hashobject_to_hashtable(hash_obj_t *hash_obj)
2017c478bdstevel@tonic-gate{
2027c478bdstevel@tonic-gate	handle_t		index_to_hash;
2037c478bdstevel@tonic-gate	static	uint64_t	handle_count	= 0;
2047c478bdstevel@tonic-gate
2057c478bdstevel@tonic-gate	hash_obj->obj_hdl = ++handle_count;	/* store the handle */
2067c478bdstevel@tonic-gate
2077c478bdstevel@tonic-gate	/* where to add ? */
2087c478bdstevel@tonic-gate	index_to_hash	= ((hash_obj->obj_hdl) % TABLE_SIZE);
2097c478bdstevel@tonic-gate
2107c478bdstevel@tonic-gate	hash_obj->next	= hash_table[index_to_hash];
2117c478bdstevel@tonic-gate	hash_table[index_to_hash] = hash_obj;	/* hash obj. added */
2127c478bdstevel@tonic-gate
2137c478bdstevel@tonic-gate	if (hash_obj->next != NULL) {
2147c478bdstevel@tonic-gate		hash_obj->next->prev = hash_obj;
2157c478bdstevel@tonic-gate	}
2167c478bdstevel@tonic-gate}
2177c478bdstevel@tonic-gate
2187c478bdstevel@tonic-gate/* called to add section object list into the section list */
2197c478bdstevel@tonic-gate
2207c478bdstevel@tonic-gatestatic void
2217c478bdstevel@tonic-gateadd_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
2227c478bdstevel@tonic-gate{
2237c478bdstevel@tonic-gate	hash_obj_t	*next_hash;
2247c478bdstevel@tonic-gate
2257c478bdstevel@tonic-gate	child_obj->u.sec_obj->cont_hdl = parent_obj->obj_hdl;
2267c478bdstevel@tonic-gate	if (parent_obj->u.cont_obj->sec_obj_list == NULL) {
2277c478bdstevel@tonic-gate		parent_obj->u.cont_obj->sec_obj_list = child_obj;
2287c478bdstevel@tonic-gate		return;
2297c478bdstevel@tonic-gate	}
2307c478bdstevel@tonic-gate
2317c478bdstevel@tonic-gate	for (next_hash = parent_obj->u.cont_obj->sec_obj_list;
2327c478bdstevel@tonic-gate	    next_hash->u.sec_obj->next != NULL;
2337c478bdstevel@tonic-gate	    next_hash = next_hash->u.sec_obj->next) {
2347c478bdstevel@tonic-gate		;
2357c478bdstevel@tonic-gate	}
2367c478bdstevel@tonic-gate
2377c478bdstevel@tonic-gate	next_hash->u.sec_obj->next	= child_obj;
2387c478bdstevel@tonic-gate}
2397c478bdstevel@tonic-gate
2407c478bdstevel@tonic-gate/* called to add segment object list into segment list */
2417c478bdstevel@tonic-gate
2427c478bdstevel@tonic-gatestatic void
2437c478bdstevel@tonic-gateadd_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
2447c478bdstevel@tonic-gate{
2457c478bdstevel@tonic-gate	hash_obj_t	*next_hash;
2467c478bdstevel@tonic-gate
2477c478bdstevel@tonic-gate	child_obj->u.seg_obj->section_hdl = parent_obj->obj_hdl;
2487c478bdstevel@tonic-gate	if (parent_obj->u.sec_obj->seg_obj_list == NULL) {
2497c478bdstevel@tonic-gate		parent_obj->u.sec_obj->seg_obj_list = child_obj;
2507c478bdstevel@tonic-gate		return;
2517c478bdstevel@tonic-gate	}
2527c478bdstevel@tonic-gate
2537c478bdstevel@tonic-gate	for (next_hash = parent_obj->u.sec_obj->seg_obj_list;
2547c478bdstevel@tonic-gate	    next_hash->u.seg_obj->next != NULL;
2557c478bdstevel@tonic-gate	    next_hash = next_hash->u.seg_obj->next) {
2567c478bdstevel@tonic-gate		;
2577c478bdstevel@tonic-gate	}
2587c478bdstevel@tonic-gate
2597c478bdstevel@tonic-gate	next_hash->u.seg_obj->next	= child_obj;
2607c478bdstevel@tonic-gate}
2617c478bdstevel@tonic-gate
2627c478bdstevel@tonic-gate/* called to add packet object list into packet list */
2637c478bdstevel@tonic-gate
2647c478bdstevel@tonic-gatestatic void
2657c478bdstevel@tonic-gateadd_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
2667c478bdstevel@tonic-gate{
2677c478bdstevel@tonic-gate	hash_obj_t	*next_hash;
2687c478bdstevel@tonic-gate
2697c478bdstevel@tonic-gate	/* add the packet object in the end of list */
2707c478bdstevel@tonic-gate	child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl;
2717c478bdstevel@tonic-gate
2727c478bdstevel@tonic-gate	if (parent_obj->u.seg_obj->pkt_obj_list == NULL) {
2737c478bdstevel@tonic-gate		parent_obj->u.seg_obj->pkt_obj_list = child_obj;
2747c478bdstevel@tonic-gate		return;
2757c478bdstevel@tonic-gate	}
2767c478bdstevel@tonic-gate
2777c478bdstevel@tonic-gate	for (next_hash = parent_obj->u.seg_obj->pkt_obj_list;
2787c478bdstevel@tonic-gate	    next_hash->u.pkt_obj->next != NULL;
2797c478bdstevel@tonic-gate	    next_hash = next_hash->u.pkt_obj->next) {
2807c478bdstevel@tonic-gate		;
2817c478bdstevel@tonic-gate	}
2827c478bdstevel@tonic-gate
2837c478bdstevel@tonic-gate	next_hash->u.pkt_obj->next = child_obj;
2847c478bdstevel@tonic-gate}
2857c478bdstevel@tonic-gate
2867c478bdstevel@tonic-gatestatic void
2877c478bdstevel@tonic-gatecopy_segment_layout(segment_t	*seghdr, void	*layout)
2887c478bdstevel@tonic-gate{
2897c478bdstevel@tonic-gate	segment_layout_t	*seg_layout;
2907c478bdstevel@tonic-gate
2917c478bdstevel@tonic-gate	seg_layout	= (segment_layout_t *)layout;
2927c478bdstevel@tonic-gate	(void) memcpy(seghdr->name, &seg_layout->name, SEG_NAME_LEN);
2937c478bdstevel@tonic-gate	seghdr->descriptor = GET_SEGMENT_DESCRIPTOR;
2947c478bdstevel@tonic-gate	seghdr->offset	= seg_layout->offset;
2957c478bdstevel@tonic-gate	seghdr->length	= seg_layout->length;
2967c478bdstevel@tonic-gate}
2977c478bdstevel@tonic-gate
2987c478bdstevel@tonic-gatestatic hash_obj_t *
2997c478bdstevel@tonic-gateget_container_hash_object(int	object_type, handle_t	handle)
3007c478bdstevel@tonic-gate{
3017c478bdstevel@tonic-gate	hash_obj_t	*hash_obj;
3027c478bdstevel@tonic-gate
3037c478bdstevel@tonic-gate	switch (object_type) {
3047c478bdstevel@tonic-gate	case	CONTAINER_TYPE	:
3057c478bdstevel@tonic-gate		break;
3067c478bdstevel@tonic-gate	case	SECTION_TYPE	:
3077c478bdstevel@tonic-gate		hash_obj = lookup_handle_object(handle, CONTAINER_TYPE);
3087c478bdstevel@tonic-gate		if (hash_obj == NULL) {
3097c478bdstevel@tonic-gate			return (NULL);
3107c478bdstevel@tonic-gate		}
3117c478bdstevel@tonic-gate		break;
3127c478bdstevel@tonic-gate	case	SEGMENT_TYPE	:
3137c478bdstevel@tonic-gate		hash_obj = lookup_handle_object(handle, SECTION_TYPE);
3147c478bdstevel@tonic-gate		if (hash_obj == NULL) {
3157c478bdstevel@tonic-gate			return (NULL);
3167c478bdstevel@tonic-gate		}
3177c478bdstevel@tonic-gate		hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl,
3187c478bdstevel@tonic-gate		    CONTAINER_TYPE);
3197c478bdstevel@tonic-gate		break;
3207c478bdstevel@tonic-gate	case	PACKET_TYPE	:
3217c478bdstevel@tonic-gate		break;
3227c478bdstevel@tonic-gate	default	:
3237c478bdstevel@tonic-gate		return (NULL);
3247c478bdstevel@tonic-gate	}
3257c478bdstevel@tonic-gate	return (hash_obj);
3267c478bdstevel@tonic-gate}
3277c478bdstevel@tonic-gate
3287c478bdstevel@tonic-gate
3297c478bdstevel@tonic-gatestatic void
3307c478bdstevel@tonic-gatesort_offsettbl(int	segcnt, seg_info_t	*offset_tbl)
3317c478bdstevel@tonic-gate{
3327c478bdstevel@tonic-gate	int		cntx;
3337c478bdstevel@tonic-gate	int		cnty;
3347c478bdstevel@tonic-gate	seg_info_t	tmp;
3357c478bdstevel@tonic-gate
3367c478bdstevel@tonic-gate	for (cntx = 0; cntx < segcnt+2; cntx++) {
3377c478bdstevel@tonic-gate		for (cnty = cntx+1; cnty < segcnt + 2; cnty++) {
3387c478bdstevel@tonic-gate			if (offset_tbl[cntx].offset >
3397c478bdstevel@tonic-gate			    offset_tbl[cnty].offset) {
3407c478bdstevel@tonic-gate				(void) memcpy(&tmp, &offset_tbl[cnty],
3417c478bdstevel@tonic-gate				    sizeof (seg_info_t));
3427c478bdstevel@tonic-gate				(void) memcpy(&offset_tbl[cnty],
3437c478bdstevel@tonic-gate				    &offset_tbl[cntx], sizeof (seg_info_t));
3447c478bdstevel@tonic-gate
3457c478bdstevel@tonic-gate				(void) memcpy(&offset_tbl[cntx], &tmp,
3467c478bdstevel@tonic-gate				    sizeof (seg_info_t));
3477c478bdstevel@tonic-gate			}
3487c478bdstevel@tonic-gate		}
3497c478bdstevel@tonic-gate	}
3507c478bdstevel@tonic-gate}
3517c478bdstevel@tonic-gate
3527c478bdstevel@tonic-gate/*
3537c478bdstevel@tonic-gate * Description : move_segment_data() reads the segment data and writes it
3547c478bdstevel@tonic-gate *      back to the new segment offset.
3557c478bdstevel@tonic-gate */
3567c478bdstevel@tonic-gate
3577c478bdstevel@tonic-gatestatic void
3587c478bdstevel@tonic-gatemove_segment_data(void *seghdr, int newoffset, container_hdl_t contfd)
3597c478bdstevel@tonic-gate{
3607c478bdstevel@tonic-gate	int			ret;
3617c478bdstevel@tonic-gate	char			*buffer;
3627c478bdstevel@tonic-gate	segment_layout_t	*segment;
3637c478bdstevel@tonic-gate
3647c478bdstevel@tonic-gate	segment	= (segment_layout_t *)seghdr;
3657c478bdstevel@tonic-gate
3667c478bdstevel@tonic-gate	buffer = alloca(segment->length);
3677c478bdstevel@tonic-gate	if (buffer == NULL) {
3687c478bdstevel@tonic-gate		return;
3697c478bdstevel@tonic-gate	}
3707c478bdstevel@tonic-gate
3717c478bdstevel@tonic-gate	ret = pread(contfd, buffer, segment->length, segment->offset);
3727c478bdstevel@tonic-gate	if (ret != segment->length) {
3737c478bdstevel@tonic-gate		return;
3747c478bdstevel@tonic-gate	}
3757c478bdstevel@tonic-gate
3767c478bdstevel@tonic-gate	segment->offset = newoffset;
3777c478bdstevel@tonic-gate
3787c478bdstevel@tonic-gate	ret = pwrite(contfd, buffer, segment->length, segment->offset);
3797c478bdstevel@tonic-gate	if (ret != segment->length) {
3807c478bdstevel@tonic-gate		return;
3817c478bdstevel@tonic-gate	}
3827c478bdstevel@tonic-gate}
3837c478bdstevel@tonic-gate
3847c478bdstevel@tonic-gate/*
3857c478bdstevel@tonic-gate * Description : pack_segment_data() moves the segment data if there is
3867c478bdstevel@tonic-gate *              a hole between two segments.
3877c478bdstevel@tonic-gate */
3887c478bdstevel@tonic-gate
3897c478bdstevel@tonic-gatestatic void
3907c478bdstevel@tonic-gatepack_segment_data(char *seghdr, int segcnt, container_hdl_t contfd,
3917c478bdstevel@tonic-gate    seg_info_t *offset_tbl)
3927c478bdstevel@tonic-gate{
3937c478bdstevel@tonic-gate	int	cnt;
3947c478bdstevel@tonic-gate	int	diff;
3957c478bdstevel@tonic-gate	int	newoffset;
3967c478bdstevel@tonic-gate
3977c478bdstevel@tonic-gate	for (cnt = segcnt + 1; cnt > 0; cnt--) {
3987c478bdstevel@tonic-gate		if (!offset_tbl[cnt - 1].fixed) {
3997c478bdstevel@tonic-gate			if (offset_tbl[cnt].offset -
4007c478bdstevel@tonic-gate			    (offset_tbl[cnt -1 ].offset +
4017c478bdstevel@tonic-gate			    offset_tbl[cnt - 1].length) > 0) {
4027c478bdstevel@tonic-gate
4037c478bdstevel@tonic-gate				diff = offset_tbl[cnt].offset -
4047c478bdstevel@tonic-gate				    (offset_tbl[cnt - 1].offset +
4057c478bdstevel@tonic-gate				    offset_tbl[cnt - 1].length);
4067c478bdstevel@tonic-gate				newoffset = offset_tbl[cnt - 1].offset + diff;
4077c478bdstevel@tonic-gate
4087c478bdstevel@tonic-gate				move_segment_data(seghdr, newoffset, contfd);
4097c478bdstevel@tonic-gate
4107c478bdstevel@tonic-gate				offset_tbl[cnt - 1].offset = newoffset;
4117c478bdstevel@tonic-gate
4127c478bdstevel@tonic-gate				sort_offsettbl(segcnt, offset_tbl);
4137c478bdstevel@tonic-gate			}
4147c478bdstevel@tonic-gate		}
4157c478bdstevel@tonic-gate	}
4167c478bdstevel@tonic-gate}
4177c478bdstevel@tonic-gate
4187c478bdstevel@tonic-gate/*
4197c478bdstevel@tonic-gate * Description : build_offset_tbl() builds the offset table by reading all the
4207c478bdstevel@tonic-gate *              segment header. it makes two more entry into the table one for
4217c478bdstevel@tonic-gate *              section size and another with start of the section after the
4227c478bdstevel@tonic-gate *              segment header.
4237c478bdstevel@tonic-gate */
4247c478bdstevel@tonic-gate
4257c478bdstevel@tonic-gatestatic int
4267c478bdstevel@tonic-gatebuild_offset_tbl(void   *seghdr, int segcnt, int secsize,
4277c478bdstevel@tonic-gate    seg_info_t *offset_tbl)
4287c478bdstevel@tonic-gate{
4297c478bdstevel@tonic-gate	int			cnt;
4307c478bdstevel@tonic-gate	fru_segdesc_t		segdesc;
4317c478bdstevel@tonic-gate	segment_layout_t	*segment;
4327c478bdstevel@tonic-gate
4337c478bdstevel@tonic-gate	for (cnt = 0; cnt < segcnt; cnt++) {
4347c478bdstevel@tonic-gate		segment	= (segment_layout_t *)(seghdr) + cnt;
4357c478bdstevel@tonic-gate
4367c478bdstevel@tonic-gate		(void) memcpy(&segdesc, &segment->descriptor,
4377c478bdstevel@tonic-gate		    sizeof (uint32_t));
4387c478bdstevel@tonic-gate		offset_tbl[cnt].segnum = cnt;
4397c478bdstevel@tonic-gate		offset_tbl[cnt].offset = segment->offset;
4407c478bdstevel@tonic-gate		offset_tbl[cnt].length = segment->length;
4417c478bdstevel@tonic-gate		offset_tbl[cnt].fixed = segdesc.field.fixed;
4427c478bdstevel@tonic-gate	}
4437c478bdstevel@tonic-gate
4447c478bdstevel@tonic-gate	/* upper boundary of segment area (lower address bytes) */
4457c478bdstevel@tonic-gate	offset_tbl[cnt].segnum = -1;
4467c478bdstevel@tonic-gate	offset_tbl[cnt].offset = sizeof (section_layout_t) +
4477c478bdstevel@tonic-gate	    ((cnt + 1) * sizeof (segment_layout_t));
4487c478bdstevel@tonic-gate
4497c478bdstevel@tonic-gate	offset_tbl[cnt].length = 0;
4507c478bdstevel@tonic-gate	offset_tbl[cnt].fixed  = 1;
4517c478bdstevel@tonic-gate	/* lower boundary of segment area (higher address bytes) */
4527c478bdstevel@tonic-gate
4537c478bdstevel@tonic-gate	offset_tbl[cnt+1].segnum = -1;
4547c478bdstevel@tonic-gate	offset_tbl[cnt+1].offset = secsize;
4557c478bdstevel@tonic-gate	offset_tbl[cnt+1].length = 0;
4567c478bdstevel@tonic-gate	offset_tbl[cnt+1].fixed = 1;
4577c478bdstevel@tonic-gate	return (0);
4587c478bdstevel@tonic-gate}
4597c478bdstevel@tonic-gate
4607c478bdstevel@tonic-gatestatic int
4617c478bdstevel@tonic-gatehole_discovery(int bytes, int segcnt, int *totsize, seg_info_t *offset_tbl)
4627c478bdstevel@tonic-gate{
4637c478bdstevel@tonic-gate	int cnt = 0;
4647c478bdstevel@tonic-gate
4657c478bdstevel@tonic-gate	*totsize = 0;
4667c478bdstevel@tonic-gate	for (cnt = segcnt + 1; cnt > 0; cnt--) {
4677c478bdstevel@tonic-gate		if (bytes <= offset_tbl[cnt].offset -
4687c478bdstevel@tonic-gate		    (offset_tbl[cnt - 1].offset +
4697c478bdstevel@tonic-gate		    offset_tbl[cnt - 1].length)) {
4707c478bdstevel@tonic-gate			return (offset_tbl[cnt].offset - bytes);
4717c478bdstevel@tonic-gate		}
4727c478bdstevel@tonic-gate
4737c478bdstevel@tonic-gate		*totsize += offset_tbl[cnt].offset -
4747c478bdstevel@tonic-gate		    (offset_tbl[cnt - 1].offset + offset_tbl[cnt - 1].length);
4757c478bdstevel@tonic-gate	}
4767c478bdstevel@tonic-gate	return (0);
4777c478bdstevel@tonic-gate}
4787c478bdstevel@tonic-gate
4797c478bdstevel@tonic-gate
4807c478bdstevel@tonic-gate/*
4817c478bdstevel@tonic-gate * Description : segment_hdr_present() verify space for new segment header to
4827c478bdstevel@tonic-gate *              be added.
4837c478bdstevel@tonic-gate */
4847c478bdstevel@tonic-gate
4857c478bdstevel@tonic-gatestatic int
4867c478bdstevel@tonic-gatesegment_hdr_present(int segoffset, int size, seg_info_t *offset_tbl)
4877c478bdstevel@tonic-gate{
4887c478bdstevel@tonic-gate	if ((segoffset + size) <= offset_tbl[0].offset)
4897c478bdstevel@tonic-gate		return (0);
4907c478bdstevel@tonic-gate	else
4917c478bdstevel@tonic-gate		return (-1);
4927c478bdstevel@tonic-gate}
4937c478bdstevel@tonic-gate
4947c478bdstevel@tonic-gate/*
4957c478bdstevel@tonic-gate * Description : find_offset() is called from fru_add_segment routine to find
4967c478bdstevel@tonic-gate *              a valid offset.
4977c478bdstevel@tonic-gate */
4987c478bdstevel@tonic-gate
4997c478bdstevel@tonic-gatestatic int
5007c478bdstevel@tonic-gatefind_offset(char *seghdr, int segcnt, int secsize, int *sectionoffset,
5017c478bdstevel@tonic-gate    int segsize, int fix, container_hdl_t contfd)
5027c478bdstevel@tonic-gate{
5037c478bdstevel@tonic-gate	int		ret;
5047c478bdstevel@tonic-gate	int		newoffset;
5057c478bdstevel@tonic-gate	int		totsize = 0;
5067c478bdstevel@tonic-gate	seg_info_t	*offset_tbl;
5077c478bdstevel@tonic-gate
5087c478bdstevel@tonic-gate	if (segcnt == 0) {
5097c478bdstevel@tonic-gate		if (!fix) {	/* if not fixed segment */
5107c478bdstevel@tonic-gate			*sectionoffset = secsize - segsize;
5117c478bdstevel@tonic-gate		}
5127c478bdstevel@tonic-gate		return (0);
5137c478bdstevel@tonic-gate	}
5147c478bdstevel@tonic-gate
5157c478bdstevel@tonic-gate	/*
5167c478bdstevel@tonic-gate	 * two extra segment info structure are allocated for start of segment
5177c478bdstevel@tonic-gate	 * and other end of segment. first segment offset is first available
5187c478bdstevel@tonic-gate	 * space and length is 0. second segment offset is is segment length and
5197c478bdstevel@tonic-gate	 * offset is 0. build_offset_tbl() explains how upper boundary and lower
5207c478bdstevel@tonic-gate	 * boudary segment area are initialized in seg_info_t table.
5217c478bdstevel@tonic-gate	 */
5227c478bdstevel@tonic-gate
5237c478bdstevel@tonic-gate	offset_tbl    = malloc((segcnt + 2) * sizeof (seg_info_t));
5247c478bdstevel@tonic-gate	if (offset_tbl == NULL) {
5257c478bdstevel@tonic-gate		return (-1);
5267c478bdstevel@tonic-gate	}
5277c478bdstevel@tonic-gate
5287c478bdstevel@tonic-gate	/* read all the segment header to make offset table */
5297c478bdstevel@tonic-gate	ret = build_offset_tbl(seghdr, segcnt, secsize, offset_tbl);
5307c478bdstevel@tonic-gate	if (ret != 0) {
5317c478bdstevel@tonic-gate		free(offset_tbl);
5327c478bdstevel@tonic-gate		return (-1);
5337c478bdstevel@tonic-gate	}
5347c478bdstevel@tonic-gate
5357c478bdstevel@tonic-gate	/* sort the table */
5367c478bdstevel@tonic-gate	sort_offsettbl(segcnt, offset_tbl);
5377c478bdstevel@tonic-gate
5387c478bdstevel@tonic-gate	/* new segment header offset */
5397c478bdstevel@tonic-gate	newoffset = sizeof (section_layout_t) + segcnt *
5407c478bdstevel@tonic-gate	    sizeof (segment_layout_t);
5417c478bdstevel@tonic-gate
5427c478bdstevel@tonic-gate	/* do? new segment header overlap any existing data */
5437c478bdstevel@tonic-gate	ret = segment_hdr_present(newoffset, sizeof (segment_layout_t),
5447c478bdstevel@tonic-gate	    offset_tbl);
5457c478bdstevel@tonic-gate	if (ret != 0) { /* make room for new segment if possible */
5467c478bdstevel@tonic-gate
5477c478bdstevel@tonic-gate	/* look for hole in order to move segment data */
5487c478bdstevel@tonic-gate		if (offset_tbl[0].fixed == SEGMENT_FIXED) { /* fixed segment */
5497c478bdstevel@tonic-gate			free(offset_tbl);
5507c478bdstevel@tonic-gate			return (-1);
5517c478bdstevel@tonic-gate		}
5527c478bdstevel@tonic-gate
5537c478bdstevel@tonic-gate		newoffset = hole_discovery(offset_tbl[0].length, segcnt,
5547c478bdstevel@tonic-gate		    &totsize, offset_tbl);
5557c478bdstevel@tonic-gate		if (newoffset != 0) { /* found new offset */
5567c478bdstevel@tonic-gate				/* now new offset */
5577c478bdstevel@tonic-gate			offset_tbl[0].offset = newoffset;
5587c478bdstevel@tonic-gate
5597c478bdstevel@tonic-gate			/* move the segment data */
5607c478bdstevel@tonic-gate			move_segment_data(seghdr, newoffset, contfd);
5617c478bdstevel@tonic-gate			/* again sort the offset table */
5627c478bdstevel@tonic-gate			sort_offsettbl(segcnt, offset_tbl);
5637c478bdstevel@tonic-gate		} else {
5647c478bdstevel@tonic-gate			/* pack the existing hole */
5657c478bdstevel@tonic-gate			if (totsize > offset_tbl[0].length) {
5667c478bdstevel@tonic-gate				pack_segment_data(seghdr, segcnt, contfd,
5677c478bdstevel@tonic-gate				    offset_tbl);
5687c478bdstevel@tonic-gate			} else {
5697c478bdstevel@tonic-gate				free(offset_tbl);
5707c478bdstevel@tonic-gate				return (-1);
5717c478bdstevel@tonic-gate			}
5727c478bdstevel@tonic-gate		}
5737c478bdstevel@tonic-gate	}
5747c478bdstevel@tonic-gate
5757c478bdstevel@tonic-gate	totsize = 0;
5767c478bdstevel@tonic-gate	newoffset = hole_discovery(segsize, segcnt, &totsize, offset_tbl);
5777c478bdstevel@tonic-gate
5787c478bdstevel@tonic-gate	if (newoffset == 0) { /* No hole found */
5797c478bdstevel@tonic-gate		if (totsize >= segsize) {
5807c478bdstevel@tonic-gate			pack_segment_data(seghdr, segcnt, contfd, offset_tbl);
5817c478bdstevel@tonic-gate			newoffset = hole_discovery(segsize, segcnt, &totsize,
5827c478bdstevel@tonic-gate			    offset_tbl);
5837c478bdstevel@tonic-gate			if (newoffset != 0) {
5847c478bdstevel@tonic-gate				*sectionoffset = newoffset;
5857c478bdstevel@tonic-gate				free(offset_tbl);
5867c478bdstevel@tonic-gate				return (0);
5877c478bdstevel@tonic-gate			}
5887c478bdstevel@tonic-gate		}
5897c478bdstevel@tonic-gate	} else {
5907c478bdstevel@tonic-gate		*sectionoffset = newoffset;
5917c478bdstevel@tonic-gate		free(offset_tbl);
5927c478bdstevel@tonic-gate		return (0);
5937c478bdstevel@tonic-gate	}
5947c478bdstevel@tonic-gate	free(offset_tbl);
5957c478bdstevel@tonic-gate	return (-1);
5967c478bdstevel@tonic-gate}
5977c478bdstevel@tonic-gate
5987c478bdstevel@tonic-gatestatic char *
5997c478bdstevel@tonic-gatetokenizer(char *buf, char *separator, char **nextBuf, char *matched)
6007c478bdstevel@tonic-gate{
6017c478bdstevel@tonic-gate	int i = 0;
6027c478bdstevel@tonic-gate	int j = 0;
6037c478bdstevel@tonic-gate
6047c478bdstevel@tonic-gate	for (i = 0; buf[i] != '\0'; i++) {
6057c478bdstevel@tonic-gate		for (j = 0; j < strlen(separator); j++) {
6067c478bdstevel@tonic-gate			if (buf[i] == separator[j]) {
6077c478bdstevel@tonic-gate				buf[i] = '\0';
6087c478bdstevel@tonic-gate				*nextBuf = &(buf[i+1]);
6097c478bdstevel@tonic-gate				*matched = separator[j];
6107c478bdstevel@tonic-gate				return (buf);
6117c478bdstevel@tonic-gate			}
6127c478bdstevel@tonic-gate		}
6137c478bdstevel@tonic-gate	}
6147c478bdstevel@tonic-gate
6157c478bdstevel@tonic-gate	*nextBuf = buf;
6167c478bdstevel@tonic-gate	*matched = '\0';
6177c478bdstevel@tonic-gate	return (NULL);
6187c478bdstevel@tonic-gate}
6197c478bdstevel@tonic-gate
6207c478bdstevel@tonic-gatestatic int
6217c478bdstevel@tonic-gateget_container_info(const char *def_file, const char *cont_desc_str,
6227c478bdstevel@tonic-gate    container_info_t *cont_info)
6237c478bdstevel@tonic-gate{
6247c478bdstevel@tonic-gate	char	*item;
6257c478bdstevel@tonic-gate	char	*token;
6267c478bdstevel@tonic-gate	char	*field;
6277c478bdstevel@tonic-gate	char	matched;
6287c478bdstevel@tonic-gate	char	buf[1024];
6297c478bdstevel@tonic-gate	int	foundIt = 0;
6307c478bdstevel@tonic-gate	int	ro_tok;
6317c478bdstevel@tonic-gate	int	index;
6327c478bdstevel@tonic-gate	FILE	*file = fopen(def_file, "r");
6337c478bdstevel@tonic-gate
6347c478bdstevel@tonic-gate	if (file == NULL)
6357c478bdstevel@tonic-gate		return (-1);
6367c478bdstevel@tonic-gate
6377c478bdstevel@tonic-gate	cont_info->num_sections = 0;
6387c478bdstevel@tonic-gate
6397c478bdstevel@tonic-gate	while (fgets(buf, sizeof (buf), file) != NULL) {
6407c478bdstevel@tonic-gate		/* ignore all comments */
6417c478bdstevel@tonic-gate		token = tokenizer(buf, "#", &field, &matched);
6427c478bdstevel@tonic-gate		/* find the names */
6437c478bdstevel@tonic-gate		token = tokenizer(buf, ":", &field, &matched);
6447c478bdstevel@tonic-gate		if (token != 0x00) {
6457c478bdstevel@tonic-gate			token = tokenizer(token, "|", &item, &matched);
6467c478bdstevel@tonic-gate			while (token != 0x00) {
6477c478bdstevel@tonic-gate				if (strcmp(token, cont_desc_str) == 0) {
6487c478bdstevel@tonic-gate					foundIt = 1;
6497c478bdstevel@tonic-gate					goto found;
6507c478bdstevel@tonic-gate				}
6517c478bdstevel@tonic-gate				token = tokenizer(item, "|", &item, &matched);
6527c478bdstevel@tonic-gate			}
6537c478bdstevel@tonic-gate			/* check the last remaining item */
6547c478bdstevel@tonic-gate			if ((item != 0x00) &&
6557c478bdstevel@tonic-gate			    (strcmp(item, cont_desc_str) == 0)) {
6567c478bdstevel@tonic-gate				foundIt = 1;
6577c478bdstevel@tonic-gate				goto found;
6587c478bdstevel@tonic-gate			}
6597c478bdstevel@tonic-gate		}
6607c478bdstevel@tonic-gate	}
6617c478bdstevel@tonic-gate
6627c478bdstevel@tonic-gatefound :
6637c478bdstevel@tonic-gate	if (foundIt == 1) {
6647c478bdstevel@tonic-gate		token = tokenizer(field, ":", &field, &matched);
6657c478bdstevel@tonic-gate		if (token == 0x00) {
6667c478bdstevel@tonic-gate			(void) fclose(file);
6677c478bdstevel@tonic-gate			return (-1);
6687c478bdstevel@tonic-gate		}
6697c478bdstevel@tonic-gate		cont_info->header_ver = (headerrev_t)atoi(token);
6707c478bdstevel@tonic-gate
6717c478bdstevel@tonic-gate		token = tokenizer(field, ":\n", &field, &matched);
6727c478bdstevel@tonic-gate		while (token != 0x00) {
6737c478bdstevel@tonic-gate			token = tokenizer(token, ",", &item, &matched);
6747c478bdstevel@tonic-gate			if (token == 0x00) {
6757c478bdstevel@tonic-gate				(void) fclose(file);
6767c478bdstevel@tonic-gate				return (-1);
6777c478bdstevel@tonic-gate			}
6787c478bdstevel@tonic-gate			ro_tok = atoi(token);
6797c478bdstevel@tonic-gate			index = cont_info->num_sections;
6807c478bdstevel@tonic-gate			cont_info->section_info[index].encoding = ENC_STANDARD;
6817c478bdstevel@tonic-gate			if (ro_tok == 1) {
6827c478bdstevel@tonic-gate				cont_info->section_info[index].description.
6837c478bdstevel@tonic-gate				    field.read_only = 1;
6847c478bdstevel@tonic-gate			} else if (ro_tok == 0) {
6857c478bdstevel@tonic-gate				cont_info->section_info[index].description.
6867c478bdstevel@tonic-gate				    field.read_only = 0;
6877c478bdstevel@tonic-gate			} else if (ro_tok == 2) {
6887c478bdstevel@tonic-gate				/*
6897c478bdstevel@tonic-gate				 * a value of 2 in the read-only token means
6907c478bdstevel@tonic-gate				 * that the data in this section needs
6917c478bdstevel@tonic-gate				 * re-interpreting
6927c478bdstevel@tonic-gate				 */
6937c478bdstevel@tonic-gate				cont_info->section_info[index].description.
6947c478bdstevel@tonic-gate				    field.read_only = 1;
6957c478bdstevel@tonic-gate			} else {
6967c478bdstevel@tonic-gate				(void) fclose(file);
6977c478bdstevel@tonic-gate				return (-1);
6987c478bdstevel@tonic-gate			}
6997c478bdstevel@tonic-gate
7007c478bdstevel@tonic-gate			token = tokenizer(item, ",", &item, &matched);
7017c478bdstevel@tonic-gate			if (token == 0x00) {
7027c478bdstevel@tonic-gate				(void) fclose(file);
7037c478bdstevel@tonic-gate				return (-1);
7047c478bdstevel@tonic-gate			}
7057c478bdstevel@tonic-gate
7067c478bdstevel@tonic-gate			cont_info->section_info[index].address = atoi(token);
7077c478bdstevel@tonic-gate			if (ro_tok == 2) {
7087c478bdstevel@tonic-gate				/*
7097c478bdstevel@tonic-gate				 * expect an extra parameter to define the
7107c478bdstevel@tonic-gate				 * data interpreter
7117c478bdstevel@tonic-gate				 */
7127c478bdstevel@tonic-gate				token = tokenizer(item, ",", &item, &matched);
7137c478bdstevel@tonic-gate				if (token == 0x00) {
7147c478bdstevel@tonic-gate					(void) fclose(file);
7157c478bdstevel@tonic-gate					return (-1);
7167c478bdstevel@tonic-gate				}
7177c478bdstevel@tonic-gate			}
7187c478bdstevel@tonic-gate			if (item == '\0') {
7197c478bdstevel@tonic-gate				(void) fclose(file);
7207c478bdstevel@tonic-gate				return (-1);
7217c478bdstevel@tonic-gate			}
7227c478bdstevel@tonic-gate			cont_info->section_info[index].size =
7237c478bdstevel@tonic-gate			    ro_tok == 2 ? atoi(token) : atoi(item);
7247c478bdstevel@tonic-gate			if (ro_tok == 2) {
7257c478bdstevel@tonic-gate				if (strcmp(item, "SPD") == 0)
7267c478bdstevel@tonic-gate					cont_info->section_info[index].
7277c478bdstevel@tonic-gate					    encoding = ENC_SPD;
7287c478bdstevel@tonic-gate				else {
7297c478bdstevel@tonic-gate					(void) fclose(file);
7307c478bdstevel@tonic-gate					return (-1);
7317c478bdstevel@tonic-gate				}
7327c478bdstevel@tonic-gate			}
7337c478bdstevel@tonic-gate			(cont_info->num_sections)++;
7347c478bdstevel@tonic-gate
7357c478bdstevel@tonic-gate			token = tokenizer(field, ":\n ", &field, &matched);
7367c478bdstevel@tonic-gate		}
7377c478bdstevel@tonic-gate	}
7387c478bdstevel@tonic-gate	(void) fclose(file);
7397c478bdstevel@tonic-gate	return (0);
7407c478bdstevel@tonic-gate}
7417c478bdstevel@tonic-gate
7427c478bdstevel@tonic-gate/*
7437c478bdstevel@tonic-gate * Description :fru_open_container() opens the container associated with a fru.
7447c478bdstevel@tonic-gate *              it's called by data plugin module before creating container
7457c478bdstevel@tonic-gate *              property.  it calls picltree library routine to get the
7467c478bdstevel@tonic-gate *              device path and driver binding name for the fru to get the
7477c478bdstevel@tonic-gate *              corresponding fru name that describe the fru layout.
7487c478bdstevel@tonic-gate *
7497c478bdstevel@tonic-gate * Arguments   :picl_hdl_t      fru
7507c478bdstevel@tonic-gate *              A handle for PICL tree node of class "fru" representing the
7517c478bdstevel@tonic-gate *              FRU with the container to open.
7527c478bdstevel@tonic-gate *
7537c478bdstevel@tonic-gate * Return      :
7547c478bdstevel@tonic-gate *              On Success, a Positive integer container handle. is returned
7557c478bdstevel@tonic-gate *              for use in subsequent fru operations;on error, 0 is returned
7567c478bdstevel@tonic-gate *              and "errno" is set appropriately.
7577c478bdstevel@tonic-gate */
7587c478bdstevel@tonic-gate
7597c478bdstevel@tonic-gatecontainer_hdl_t
7607c478bdstevel@tonic-gatefru_open_container(picl_nodehdl_t fruhdl)
7617c478bdstevel@tonic-gate{
7627c478bdstevel@tonic-gate	int			retval;
7637c478bdstevel@tonic-gate	int			count;
764c5805b0ps	int			device_fd;
765c5805b0ps	uchar_t			first_byte;
7667c478bdstevel@tonic-gate	char			*bname;
7677c478bdstevel@tonic-gate	char			devpath[PATH_MAX];
7687c478bdstevel@tonic-gate	char			nmbuf[SYS_NMLN];
7697c478bdstevel@tonic-gate	hash_obj_t		*cont_hash_obj;
7707c478bdstevel@tonic-gate	hash_obj_t		*sec_hash_obj;
7717c478bdstevel@tonic-gate	picl_nodehdl_t		tmphdl;
7727c478bdstevel@tonic-gate	picl_prophdl_t		prophdl;
7737c478bdstevel@tonic-gate	ptree_propinfo_t	propinfo;
7747c478bdstevel@tonic-gate	container_info_t	cont_info;
7757c478bdstevel@tonic-gate
7767c478bdstevel@tonic-gate	/* Get property handle of _seeprom_source under fru node */
7777c478bdstevel@tonic-gate	retval = ptree_get_propval_by_name(fruhdl, PICL_REFPROP_SEEPROM_SRC,
7787c478bdstevel@tonic-gate	    &tmphdl, sizeof (tmphdl));
7797c478bdstevel@tonic-gate	if (retval != PICL_SUCCESS) {
7807c478bdstevel@tonic-gate		return (NULL);
7817c478bdstevel@tonic-gate	}
7827c478bdstevel@tonic-gate
7837c478bdstevel@tonic-gate	/* Get the device path of the fru */
7847c478bdstevel@tonic-gate	retval = ptree_get_propval_by_name(tmphdl, PICL_PROP_DEVICEPATH,
7857c478bdstevel@tonic-gate	    devpath, PATH_MAX);
7867c478bdstevel@tonic-gate	if (retval != PICL_SUCCESS) {
7877c478bdstevel@tonic-gate		return (NULL);
7887c478bdstevel@tonic-gate	}
7897c478bdstevel@tonic-gate
7907c478bdstevel@tonic-gate	retval = ptree_get_prop_by_name(tmphdl, PICL_PROP_BINDING_NAME,
7917c478bdstevel@tonic-gate	    &prophdl);
7927c478bdstevel@tonic-gate	if (retval != PICL_SUCCESS) {
7937c478bdstevel@tonic-gate		return (NULL);
7947c478bdstevel@tonic-gate	}
7957c478bdstevel@tonic-gate
7967c478bdstevel@tonic-gate	retval = ptree_get_propinfo(prophdl, &propinfo);
7977c478bdstevel@tonic-gate	if (retval != PICL_SUCCESS) {
7987c478bdstevel@tonic-gate		return (NULL);
7997c478bdstevel@tonic-gate	}
8007c478bdstevel@tonic-gate
8017c478bdstevel@tonic-gate	bname = alloca(propinfo.piclinfo.size);
8027c478bdstevel@tonic-gate	if (bname == NULL) {
8037c478bdstevel@tonic-gate		return (NULL);
8047c478bdstevel@tonic-gate	}
8057c478bdstevel@tonic-gate
8067c478bdstevel@tonic-gate	/* get the driver binding name */
8077c478bdstevel@tonic-gate	retval = ptree_get_propval(prophdl, bname, propinfo.piclinfo.size);
8087c478bdstevel@tonic-gate	if (retval != PICL_SUCCESS) {
8097c478bdstevel@tonic-gate		return (NULL);
8107c478bdstevel@tonic-gate	}
8117c478bdstevel@tonic-gate
8127c478bdstevel@tonic-gate	cont_hash_obj	= create_container_hash_object();
8137c478bdstevel@tonic-gate	if (cont_hash_obj == NULL) {
8147c478bdstevel@tonic-gate		return (NULL);
8157c478bdstevel@tonic-gate	}
8167c478bdstevel@tonic-gate
8177c478bdstevel@tonic-gate	add_hashobject_to_hashtable(cont_hash_obj);
8187c478bdstevel@tonic-gate
8197c478bdstevel@tonic-gate	(void) strlcpy(cont_hash_obj->u.cont_obj->device_pathname, devpath,
8207c478bdstevel@tonic-gate	    sizeof (devpath));
8217c478bdstevel@tonic-gate
822c5805b0ps	/* check for sun or non-sun type fru */
823c5805b0ps	if (strcmp(bname, "i2c-at34c02") == 0) {
824c5805b0ps		device_fd = open(devpath, O_RDONLY);
825c5805b0ps		if (device_fd < 0) {
826c5805b0ps			return (NULL);
827c5805b0ps		}
828c5805b0ps		first_byte = 0x00;
829c5805b0ps
830c5805b0ps		retval = pread(device_fd, &first_byte, sizeof (first_byte), 0);
831af3025fdt		(void) close(device_fd);
832af3025fdt		switch (first_byte) {
833af3025fdt			case 0x08:
834af3025fdt				(void) strcpy(bname, "i2c-at34cps");
835af3025fdt				break;
836af3025fdt			case 0x80:
837af3025fdt				(void) strcpy(bname, "i2c-at34c02");
838af3025fdt				break;
839af3025fdt			default:
840af3025fdt				(void) strcpy(bname, "i2c-at34cuk");
841af3025fdt				break;
842af3025fdt		}
843c5805b0ps	}
844c5805b0ps
8457c478bdstevel@tonic-gate	/* if there's a platform-specific conf file, use that */
8467c478bdstevel@tonic-gate	retval = -1;
8477c478bdstevel@tonic-gate	if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) {
8487c478bdstevel@tonic-gate		(void) snprintf(devpath, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF,
8497c478bdstevel@tonic-gate		    nmbuf);
8507c478bdstevel@tonic-gate		(void) strlcat(devpath, FRU_CONTAINER_CONF, PATH_MAX);
8517c478bdstevel@tonic-gate		retval = access(devpath, R_OK);
8527c478bdstevel@tonic-gate	}
8537c478bdstevel@tonic-gate	if (retval != 0) {
8547c478bdstevel@tonic-gate		/* nothing for the platform, try the base name */
8557c478bdstevel@tonic-gate		(void) snprintf(devpath, PATH_MAX, "%s/%s",
8567c478bdstevel@tonic-gate		    CONTAINER_DIR, FRU_CONTAINER_CONF);
8577c478bdstevel@tonic-gate		retval = access(devpath, R_OK);
8587c478bdstevel@tonic-gate	}
8597c478bdstevel@tonic-gate	/* matches driver binding name to get container information */
8607c478bdstevel@tonic-gate	if (retval == 0) {
8617c478bdstevel@tonic-gate		retval = get_container_info(devpath, bname, &cont_info);
8627c478bdstevel@tonic-gate	}
8637c478bdstevel@tonic-gate	if (retval < 0) {
8647c478bdstevel@tonic-gate		return (NULL);
8657c478bdstevel@tonic-gate	}
8667c478bdstevel@tonic-gate
8677c478bdstevel@tonic-gate	cont_hash_obj->u.cont_obj->num_of_section =  cont_info.num_sections;
8687c478bdstevel@tonic-gate	cont_hash_obj->u.cont_obj->sec_obj_list = NULL;
8697c478bdstevel@tonic-gate
8707c478bdstevel@tonic-gate	for (count = 0; count < cont_info.num_sections; count++) {
8717c478bdstevel@tonic-gate		sec_hash_obj = create_section_hash_object();
8727c478bdstevel@tonic-gate		if (sec_hash_obj == NULL) {
8737c478bdstevel@tonic-gate			return (NULL);
8747c478bdstevel@tonic-gate		}
8757c478bdstevel@tonic-gate
8767c478bdstevel@tonic-gate		add_hashobject_to_hashtable(sec_hash_obj);
8777c478bdstevel@tonic-gate
8787c478bdstevel@tonic-gate		sec_hash_obj->u.sec_obj->section.offset =
8797c478bdstevel@tonic-gate		    cont_info.section_info[count].address;
8807c478bdstevel@tonic-gate
8817c478bdstevel@tonic-gate		sec_hash_obj->u.sec_obj->section.protection =
8827c478bdstevel@tonic-gate		    cont_info.section_info[count].description.field.read_only;
8837c478bdstevel@tonic-gate
8847c478bdstevel@tonic-gate		sec_hash_obj->u.sec_obj->section.length =
8857c478bdstevel@tonic-gate		    cont_info.section_info[count].size;
8867c478bdstevel@tonic-gate
8877c478bdstevel@tonic-gate		sec_hash_obj->u.sec_obj->section.version = cont_info.header_ver;
8887c478bdstevel@tonic-gate		sec_hash_obj->u.sec_obj->encoding =
8897c478bdstevel@tonic-gate		    cont_info.section_info[count].encoding;
8907c478bdstevel@tonic-gate
8917c478bdstevel@tonic-gate		add_to_sec_object_list(cont_hash_obj, sec_hash_obj);
8927c478bdstevel@tonic-gate	}
8937c478bdstevel@tonic-gate	return (cont_hash_obj->obj_hdl);
8947c478bdstevel@tonic-gate}
8957c478bdstevel@tonic-gate
8967c478bdstevel@tonic-gatestatic int
8977c478bdstevel@tonic-gateverify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length)
8987c478bdstevel@tonic-gate{
8997c478bdstevel@tonic-gate	int		crc_offset = 0;
9007c478bdstevel@tonic-gate	unsigned char	orig_crc8 = 0;
9017c478bdstevel@tonic-gate	unsigned char	calc_crc8 = 0;
9027c478bdstevel@tonic-gate
9037c478bdstevel@tonic-gate	switch (head_ver) {
9047c478bdstevel@tonic-gate		case SECTION_HDR_VER:
9057c478bdstevel@tonic-gate			crc_offset = 4;
9067c478bdstevel@tonic-gate			break;
9077c478bdstevel@tonic-gate		default:
9087c478bdstevel@tonic-gate			errno = EINVAL;
9097c478bdstevel@tonic-gate			return (0);
9107c478bdstevel@tonic-gate	}
9117c478bdstevel@tonic-gate
9127c478bdstevel@tonic-gate	orig_crc8 = bytes[crc_offset];
9137c478bdstevel@tonic-gate	bytes[crc_offset] = 0x00; /* clear for calc */
9147c478bdstevel@tonic-gate	calc_crc8 = compute_crc8(bytes, length);
9157c478bdstevel@tonic-gate	bytes[crc_offset] = orig_crc8; /* restore */
9167c478bdstevel@tonic-gate	return (orig_crc8 == calc_crc8);
9177c478bdstevel@tonic-gate}
9187c478bdstevel@tonic-gate
9197c478bdstevel@tonic-gate/*
9207c478bdstevel@tonic-gate * Description	:
9217c478bdstevel@tonic-gate *		fru_get_num_sections() returns number of sections in a
9227c478bdstevel@tonic-gate *		container. it calls get_container_index() to get the container
9237c478bdstevel@tonic-gate *		index number in the container list.
9247c478bdstevel@tonic-gate *
9257c478bdstevel@tonic-gate * Arguments	:
9267c478bdstevel@tonic-gate *		container_hdl_t	: container handle.
9277c478bdstevel@tonic-gate *
9287c478bdstevel@tonic-gate * Return	:
9297c478bdstevel@tonic-gate *		int
9307c478bdstevel@tonic-gate *		On success, returns number of sections in a container.
9317c478bdstevel@tonic-gate *
9327c478bdstevel@tonic-gate */
9337c478bdstevel@tonic-gate
9347c478bdstevel@tonic-gate/* ARGSUSED */
9357c478bdstevel@tonic-gateint
9367c478bdstevel@tonic-gatefru_get_num_sections(container_hdl_t container, door_cred_t *cred)
9377c478bdstevel@tonic-gate{
9387c478bdstevel@tonic-gate	hash_obj_t		*hash_object;
9397c478bdstevel@tonic-gate
9407c478bdstevel@tonic-gate	hash_object	= lookup_handle_object(container, CONTAINER_TYPE);
9417c478bdstevel@tonic-gate	if (hash_object == NULL) {
9427c478bdstevel@tonic-gate		return (-1);
9437c478bdstevel@tonic-gate	}
9447c478bdstevel@tonic-gate
9457c478bdstevel@tonic-gate	return (hash_object->u.cont_obj->num_of_section);
9467c478bdstevel@tonic-gate}
9477c478bdstevel@tonic-gate
9487c478bdstevel@tonic-gate/*
9497c478bdstevel@tonic-gate * called from fru_get_sections()
9507c478bdstevel@tonic-gate */
9517c478bdstevel@tonic-gate
9527c478bdstevel@tonic-gatestatic void
9537c478bdstevel@tonic-gateget_section(int fd, hash_obj_t *sec_hash, section_t *section)
9547c478bdstevel@tonic-gate{
9557c478bdstevel@tonic-gate	int			retval;
9567c478bdstevel@tonic-gate	int			size;
9577c478bdstevel@tonic-gate	int			count;
9587c478bdstevel@tonic-gate	uint16_t		hdrver;
9597c478bdstevel@tonic-gate	hash_obj_t		*seg_hash;
9607c478bdstevel@tonic-gate	unsigned char		*buffer;
9617c478bdstevel@tonic-gate	section_obj_t		*sec_obj;
9627c478bdstevel@tonic-gate	section_layout_t	sec_hdr;
9637c478bdstevel@tonic-gate	segment_layout_t	*seg_hdr;
9647c478bdstevel@tonic-gate	segment_layout_t	*seg_buf;
9657c478bdstevel@tonic-gate
9667c478bdstevel@tonic-gate	sec_obj	= sec_hash->u.sec_obj;
9677c478bdstevel@tonic-gate	if (sec_obj == NULL) {
9687c478bdstevel@tonic-gate		return;
9697c478bdstevel@tonic-gate	}
9707c478bdstevel@tonic-gate
9717c478bdstevel@tonic-gate	/* populate section_t */
9727c478bdstevel@tonic-gate	section->handle = sec_hash->obj_hdl;
9737c478bdstevel@tonic-gate	section->offset = sec_obj->section.offset;
9747c478bdstevel@tonic-gate	section->length = sec_obj->section.length;
9757c478bdstevel@tonic-gate	section->protection = sec_obj->section.protection;
9767c478bdstevel@tonic-gate	section->version = sec_obj->section.version;
9777c478bdstevel@tonic-gate	sec_obj->num_of_segment	= 0;
9787c478bdstevel@tonic-gate
9797c478bdstevel@tonic-gate	switch (sec_obj->encoding) {
9807c478bdstevel@tonic-gate	case ENC_STANDARD:
9817c478bdstevel@tonic-gate		/* read section header layout */
9827c478bdstevel@tonic-gate		retval = pread(fd, &sec_hdr, sizeof (sec_hdr),
9837c478bdstevel@tonic-gate		    sec_obj->section.offset);
9847c478bdstevel@tonic-gate		break;
9857c478bdstevel@tonic-gate
9867c478bdstevel@tonic-gate	case ENC_SPD:
9877c478bdstevel@tonic-gate		retval = get_sp_sec_hdr(&sec_hdr, sizeof (sec_hdr));
9887c478bdstevel@tonic-gate		break;
9897c478bdstevel@tonic-gate
9907c478bdstevel@tonic-gate	default:
9917c478bdstevel@tonic-gate		return;
9927c478bdstevel@tonic-gate	}
9937c478bdstevel@tonic-gate
9947c478bdstevel@tonic-gate	if (retval != sizeof (sec_hdr)) {
9957c478bdstevel@tonic-gate		return;
9967c478bdstevel@tonic-gate	}
9977c478bdstevel@tonic-gate
9987c478bdstevel@tonic-gate	hdrver	= GET_SECTION_HDR_VERSION;
9997c478bdstevel@tonic-gate
10007c478bdstevel@tonic-gate	if ((sec_hdr.headertag != SECTION_HDR_TAG) &&
10017c478bdstevel@tonic-gate	    (hdrver != section->version)) {
10027c478bdstevel@tonic-gate		return;
10037c478bdstevel@tonic-gate	}
10047c478bdstevel@tonic-gate
10057c478bdstevel@tonic-gate	/* size = section layout + total sizeof segment header */
10067c478bdstevel@tonic-gate	size	= sizeof (sec_hdr) + ((sec_hdr.segmentcount) *
10077c478bdstevel@tonic-gate	    sizeof (segment_layout_t));
10087c478bdstevel@tonic-gate
10097c478bdstevel@tonic-gate	buffer	= alloca(size);
10107c478bdstevel@tonic-gate	if (buffer == NULL) {
10117c478bdstevel@tonic-gate		return;
10127c478bdstevel@tonic-gate	}
10137c478bdstevel@tonic-gate
10147c478bdstevel@tonic-gate	/* segment header buffer */
10157c478bdstevel@tonic-gate	seg_buf = alloca(size - sizeof (sec_hdr));
10167c478bdstevel@tonic-gate	if (seg_buf == NULL) {
10177c478bdstevel@tonic-gate		return;
10187c478bdstevel@tonic-gate	}
10197c478bdstevel@tonic-gate
10207c478bdstevel@tonic-gate	switch (sec_obj->encoding) {
10217c478bdstevel@tonic-gate	case ENC_STANDARD:
10227c478bdstevel@tonic-gate		/* read segment header */
10237c478bdstevel@tonic-gate		retval = pread(fd, seg_buf, size - sizeof (sec_hdr),
10247c478bdstevel@tonic-gate		    sec_obj->section.offset + sizeof (sec_hdr));
10257c478bdstevel@tonic-gate		break;
10267c478bdstevel@tonic-gate
10277c478bdstevel@tonic-gate	case ENC_SPD:
10287c478bdstevel@tonic-gate		retval =
10297c478bdstevel@tonic-gate		    get_sp_seg_hdr(seg_buf, size - sizeof (sec_hdr));
10307c478bdstevel@tonic-gate		break;
10317c478bdstevel@tonic-gate
10327c478bdstevel@tonic-gate	default:
10337c478bdstevel@tonic-gate		return;
10347c478bdstevel@tonic-gate	}
10357c478bdstevel@tonic-gate
10367c478bdstevel@tonic-gate	if (retval != (size - sizeof (sec_hdr))) {
10377c478bdstevel@tonic-gate		return;
10387c478bdstevel@tonic-gate	}
10397c478bdstevel@tonic-gate
10407c478bdstevel@tonic-gate	/* copy section header layout */
10417c478bdstevel@tonic-gate	(void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr));
10427c478bdstevel@tonic-gate
10437c478bdstevel@tonic-gate	/* copy segment header layout */
10447c478bdstevel@tonic-gate	(void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size -
10457c478bdstevel@tonic-gate	    sizeof (sec_hdr));
10467c478bdstevel@tonic-gate
10477c478bdstevel@tonic-gate	/* verify crc8 */
10487c478bdstevel@tonic-gate	retval = verify_header_crc8(hdrver, buffer, size);
10497c478bdstevel@tonic-gate	if (retval != TRUE) {
10507c478bdstevel@tonic-gate		return;
10517c478bdstevel@tonic-gate	}
10527c478bdstevel@tonic-gate
10537c478bdstevel@tonic-gate	section->version = hdrver;
10547c478bdstevel@tonic-gate	sec_obj->section.version = hdrver;
10557c478bdstevel@tonic-gate
10567c478bdstevel@tonic-gate	seg_hdr	= (segment_layout_t *)seg_buf;
10577c478bdstevel@tonic-gate
10587c478bdstevel@tonic-gate	for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) {
10597c478bdstevel@tonic-gate		seg_hash = create_segment_hash_object();
10607c478bdstevel@tonic-gate		if (seg_hash == NULL) {
10617c478bdstevel@tonic-gate			return;
10627c478bdstevel@tonic-gate		}
10637c478bdstevel@tonic-gate
10647c478bdstevel@tonic-gate		add_hashobject_to_hashtable(seg_hash);
10657c478bdstevel@tonic-gate
10667c478bdstevel@tonic-gate		copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_hdr);
10677c478bdstevel@tonic-gate
10687c478bdstevel@tonic-gate		add_to_seg_object_list(sec_hash, seg_hash);
10697c478bdstevel@tonic-gate
10707c478bdstevel@tonic-gate		sec_obj->num_of_segment++;
10717c478bdstevel@tonic-gate	}
10727c478bdstevel@tonic-gate}
10737c478bdstevel@tonic-gate
10747c478bdstevel@tonic-gate
10757c478bdstevel@tonic-gatestatic int
10767c478bdstevel@tonic-gatecall_devfsadm(void)
10777c478bdstevel@tonic-gate{
10787c478bdstevel@tonic-gate	char		*phys_path;
10797c478bdstevel@tonic-gate	di_node_t	root_node;
10807c478bdstevel@tonic-gate	di_node_t	prom_node;
10817c478bdstevel@tonic-gate	di_node_t	f_node;
10827c478bdstevel@tonic-gate
10837c478bdstevel@tonic-gate	if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) {
10847c478bdstevel@tonic-gate		return (-1);
10857c478bdstevel@tonic-gate	}
10867c478bdstevel@tonic-gate
10877c478bdstevel@tonic-gate	f_node = di_drv_first_node(PICL_CLASS_SEEPROM, root_node);
10887c478bdstevel@tonic-gate	if (f_node != DI_NODE_NIL) {
10897c478bdstevel@tonic-gate		phys_path = di_devfs_path(f_node);
10907c478bdstevel@tonic-gate		if ((prom_node = di_init(phys_path, DINFOMINOR)) !=
10917c478bdstevel@tonic-gate		    DI_NODE_NIL) {
10927c478bdstevel@tonic-gate			di_fini(prom_node);
10937c478bdstevel@tonic-gate			di_fini(root_node);
10947c478bdstevel@tonic-gate			(void) pclose(popen(devfsadm_cmd, "r"));
10957c478bdstevel@tonic-gate			return (0);
10967c478bdstevel@tonic-gate		}
10977c478bdstevel@tonic-gate	}
10987c478bdstevel@tonic-gate	di_fini(root_node);
10997c478bdstevel@tonic-gate	return (-1);
11007c478bdstevel@tonic-gate}
11017c478bdstevel@tonic-gate
11027c478bdstevel@tonic-gate/*
11037c478bdstevel@tonic-gate * Description	:
11047c478bdstevel@tonic-gate *   		fru_get_sections() fills an array of section structures passed
11057c478bdstevel@tonic-gate *		as an argument.
11067c478bdstevel@tonic-gate *
11077c478bdstevel@tonic-gate * Arguments	:
11087c478bdstevel@tonic-gate *		container_hdl_t : container handle(device descriptor).
11097c478bdstevel@tonic-gate *		section_t	: array of section structure.
11107c478bdstevel@tonic-gate *		int		: maximum number of section in a container.
11117c478bdstevel@tonic-gate *
11127c478bdstevel@tonic-gate * Returns	:
11137c478bdstevel@tonic-gate *   		int
11147c478bdstevel@tonic-gate *     		On success,the number of section structures written is returned;
11157c478bdstevel@tonic-gate *     		on error, -1 is returned and "errno" is set appropriately.
11167c478bdstevel@tonic-gate *
11177c478bdstevel@tonic-gate */
11187c478bdstevel@tonic-gate
11197c478bdstevel@tonic-gate/* ARGSUSED */
11207c478bdstevel@tonic-gateint
11217c478bdstevel@tonic-gatefru_get_sections(container_hdl_t container, section_t *section, int maxsec,
11227c478bdstevel@tonic-gate							door_cred_t *cred)
11237c478bdstevel@tonic-gate{
11247c478bdstevel@tonic-gate	int		device_fd;
11257c478bdstevel@tonic-gate	int		retrys = 1;
11267c478bdstevel@tonic-gate	int		count;
11277c478bdstevel@tonic-gate	hash_obj_t	*cont_object;
11287c478bdstevel@tonic-gate	hash_obj_t	*sec_hash;
11297c478bdstevel@tonic-gate
11307c478bdstevel@tonic-gate	cont_object = lookup_handle_object(container, CONTAINER_TYPE);
11317c478bdstevel@tonic-gate
11327c478bdstevel@tonic-gate	if (cont_object == NULL) {
11337c478bdstevel@tonic-gate		return (-1);
11347c478bdstevel@tonic-gate	}
11357c478bdstevel@tonic-gate
11367c478bdstevel@tonic-gate	if (cont_object->u.cont_obj->num_of_section > maxsec) {
11377c478bdstevel@tonic-gate		return (-1);
11387c478bdstevel@tonic-gate	}
11397c478bdstevel@tonic-gate
11407c478bdstevel@tonic-gate	sec_hash = cont_object->u.cont_obj->sec_obj_list;
11417c478bdstevel@tonic-gate	if (sec_hash == NULL) {
11427c478bdstevel@tonic-gate		return (-1);
11437c478bdstevel@tonic-gate	}
11447c478bdstevel@tonic-gate
11457c478bdstevel@tonic-gate	do {
11467c478bdstevel@tonic-gate		device_fd =
11477c478bdstevel@tonic-gate		    open(cont_object->u.cont_obj->device_pathname, O_RDONLY);
11487c478bdstevel@tonic-gate		if (device_fd >= 0) {
11497c478bdstevel@tonic-gate			break;
11507c478bdstevel@tonic-gate		}
11517c478bdstevel@tonic-gate	} while ((retrys-- > 0) && (call_devfsadm() == 0));
11527c478bdstevel@tonic-gate
11537c478bdstevel@tonic-gate	if (device_fd < 0) {
11547c478bdstevel@tonic-gate		return (-1);
11557c478bdstevel@tonic-gate	}
11567c478bdstevel@tonic-gate
11577c478bdstevel@tonic-gate	for (count = 0; count < cont_object->u.cont_obj->num_of_section;
11587c478bdstevel@tonic-gate	    count++, section++) {
11597c478bdstevel@tonic-gate		section->version = -1;
11607c478bdstevel@tonic-gate		/* populate section_t */
11617c478bdstevel@tonic-gate		get_section(device_fd, sec_hash, section);
11627c478bdstevel@tonic-gate		sec_hash = sec_hash->u.sec_obj->next;
11637c478bdstevel@tonic-gate	}
11647c478bdstevel@tonic-gate
11657c478bdstevel@tonic-gate	(void) close(device_fd);
11667c478bdstevel@tonic-gate	return (count);
11677c478bdstevel@tonic-gate}
11687c478bdstevel@tonic-gate
11697c478bdstevel@tonic-gate/*
11707c478bdstevel@tonic-gate * Description	:
11717c478bdstevel@tonic-gate * 		fru_get_num_segments() returns the current number of segments
11727c478bdstevel@tonic-gate *		in a section.
11737c478bdstevel@tonic-gate *
11747c478bdstevel@tonic-gate * Arguments	:
11757c478bdstevel@tonic-gate *		section_hdl_t : section header holding section information.
11767c478bdstevel@tonic-gate *
11777c478bdstevel@tonic-gate * Return	:
11787c478bdstevel@tonic-gate * 		int
11797c478bdstevel@tonic-gate *     		On success, the number of segments in the argument section is
11807c478bdstevel@tonic-gate *     		returned; on error -1 is returned.
11817c478bdstevel@tonic-gate */
11827c478bdstevel@tonic-gate
11837c478bdstevel@tonic-gate/* ARGSUSED */
11847c478bdstevel@tonic-gateint
11857c478bdstevel@tonic-gatefru_get_num_segments(section_hdl_t section, door_cred_t *cred)
11867c478bdstevel@tonic-gate{
11877c478bdstevel@tonic-gate	hash_obj_t	*sec_object;
11887c478bdstevel@tonic-gate	section_obj_t	*sec_obj;
11897c478bdstevel@tonic-gate
11907c478bdstevel@tonic-gate	sec_object	= lookup_handle_object(section, SECTION_TYPE);
11917c478bdstevel@tonic-gate	if (sec_object == NULL) {
11927c478bdstevel@tonic-gate		return (-1);
11937c478bdstevel@tonic-gate	}
11947c478bdstevel@tonic-gate
11957c478bdstevel@tonic-gate	sec_obj	= sec_object->u.sec_obj;
11967c478bdstevel@tonic-gate	if (sec_obj == NULL) {
11977c478bdstevel@tonic-gate		return (-1);
11987c478bdstevel@tonic-gate	}
11997c478bdstevel@tonic-gate
12007c478bdstevel@tonic-gate	return (sec_obj->num_of_segment);
12017c478bdstevel@tonic-gate}
12027c478bdstevel@tonic-gate
12037c478bdstevel@tonic-gate/*
12047c478bdstevel@tonic-gate * Description	:
12057c478bdstevel@tonic-gate *		fru_get_segments() fills an array of structures representing the
12067c478bdstevel@tonic-gate *		segments in a section.
12077c478bdstevel@tonic-gate *
12087c478bdstevel@tonic-gate * Arguments	:
12097c478bdstevel@tonic-gate *		section_hdl_t : holds section number.
12107c478bdstevel@tonic-gate *		segment_t : on success will hold segment information.
12117c478bdstevel@tonic-gate *		int	: maximum number of segment.
12127c478bdstevel@tonic-gate *
12137c478bdstevel@tonic-gate * Return	:
12147c478bdstevel@tonic-gate *		int
12157c478bdstevel@tonic-gate *		On success, the number of segment structures written is
12167c478bdstevel@tonic-gate *		returned; on errno -1 is returned.
12177c478bdstevel@tonic-gate */
12187c478bdstevel@tonic-gate
12197c478bdstevel@tonic-gate/* ARGSUSED */
12207c478bdstevel@tonic-gateint
12217c478bdstevel@tonic-gatefru_get_segments(section_hdl_t section, segment_t *segment, int maxseg,
12227c478bdstevel@tonic-gate    door_cred_t *cred)
12237c478bdstevel@tonic-gate{
12247c478bdstevel@tonic-gate	int		count;
12257c478bdstevel@tonic-gate	hash_obj_t	*sec_object;
12267c478bdstevel@tonic-gate	hash_obj_t	*seg_object;
12277c478bdstevel@tonic-gate	section_obj_t	*sec_obj;
12287c478bdstevel@tonic-gate
12297c478bdstevel@tonic-gate	sec_object = lookup_handle_object(section, SECTION_TYPE);
12307c478bdstevel@tonic-gate	if (sec_object == NULL) {
12317c478bdstevel@tonic-gate		return (-1);
12327c478bdstevel@tonic-gate	}
12337c478bdstevel@tonic-gate
12347c478bdstevel@tonic-gate	sec_obj	= sec_object->u.sec_obj;
12357c478bdstevel@tonic-gate	if (sec_obj == NULL) {
12367c478bdstevel@tonic-gate		return (-1);
12377c478bdstevel@tonic-gate	}
12387c478bdstevel@tonic-gate
12397c478bdstevel@tonic-gate	if (sec_obj->num_of_segment > maxseg) {
12407c478bdstevel@tonic-gate		return (-1);
12417c478bdstevel@tonic-gate	}
12427c478bdstevel@tonic-gate
12437c478bdstevel@tonic-gate	seg_object	= sec_object->u.sec_obj->seg_obj_list;
12447c478bdstevel@tonic-gate	if (seg_object == NULL) {
12457c478bdstevel@tonic-gate		return (-1);
12467c478bdstevel@tonic-gate	}
12477c478bdstevel@tonic-gate
12487c478bdstevel@tonic-gate	for (count = 0; count < sec_obj->num_of_segment; count++) {
12497c478bdstevel@tonic-gate
12507c478bdstevel@tonic-gate		/* populate segment_t */
12517c478bdstevel@tonic-gate		segment->handle = seg_object->obj_hdl;
12527c478bdstevel@tonic-gate		(void) memcpy(segment->name,
12537c478bdstevel@tonic-gate		    seg_object->u.seg_obj->segment.name, SEG_NAME_LEN);
12547c478bdstevel@tonic-gate		segment->descriptor = seg_object->u.seg_obj->segment.descriptor;
12557c478bdstevel@tonic-gate
12567c478bdstevel@tonic-gate		segment->offset	= seg_object->u.seg_obj->segment.offset;
12577c478bdstevel@tonic-gate		segment->length	= seg_object->u.seg_obj->segment.length;
12587c478bdstevel@tonic-gate		seg_object = seg_object->u.seg_obj->next;
12597c478bdstevel@tonic-gate		segment++;
12607c478bdstevel@tonic-gate	}
12617c478bdstevel@tonic-gate	return (0);
12627c478bdstevel@tonic-gate}
12637c478bdstevel@tonic-gate
12647c478bdstevel@tonic-gate/*
12657c478bdstevel@tonic-gate * Description	:
12667c478bdstevel@tonic-gate *		fru_add_segment() adds a segment to a section.
12677c478bdstevel@tonic-gate *
12687c478bdstevel@tonic-gate * Arguments	:
12697c478bdstevel@tonic-gate *		section_hdl_t section
12707c478bdstevel@tonic-gate *		A handle for the section in which to add the segment.
12717c478bdstevel@tonic-gate *
12727c478bdstevel@tonic-gate *		segment_t *segment
12737c478bdstevel@tonic-gate *		On entry, the "handle" component of "segment" is ignored and the
12747c478bdstevel@tonic-gate *		remaining components specify the parameters of the segment to be
12757c478bdstevel@tonic-gate *		added.  On return, the "handle" component is set to the handle
12767c478bdstevel@tonic-gate *		for the added segment. The segment offset is mandatory for FIXED
12777c478bdstevel@tonic-gate *		segments; otherwise, the offset is advisory.
12787c478bdstevel@tonic-gate *
12797c478bdstevel@tonic-gate * Return	:
12807c478bdstevel@tonic-gate *		int
12817c478bdstevel@tonic-gate *		On success, 0 is returned; on error -1 is returned.
12827c478bdstevel@tonic-gate *
12837c478bdstevel@tonic-gate */
12847c478bdstevel@tonic-gate
12857c478bdstevel@tonic-gateint
12867c478bdstevel@tonic-gatefru_add_segment(section_hdl_t section, segment_t *segment,
12877c478bdstevel@tonic-gate				section_hdl_t *newsection, door_cred_t *cred)
12887c478bdstevel@tonic-gate{
12897c478bdstevel@tonic-gate	int		fd;
12907c478bdstevel@tonic-gate	int		retval;
12917c478bdstevel@tonic-gate	int		offset;
12927c478bdstevel@tonic-gate	int		sec_size;
12937c478bdstevel@tonic-gate	int		seg_cnt;
12947c478bdstevel@tonic-gate	int		bufsize;
12957c478bdstevel@tonic-gate	int		new_seg_offset;
12967c478bdstevel@tonic-gate	int		new_seg_length;
12977c478bdstevel@tonic-gate	int		fixed_segment;
12987c478bdstevel@tonic-gate	char		trailer[]	= { 0x0c, 0x00, 0x00, 0x00, 0x00 };
12997c478bdstevel@tonic-gate	hash_obj_t	*cont_hash;
13007c478bdstevel@tonic-gate	hash_obj_t	*sec_hash;
13017c478bdstevel@tonic-gate	hash_obj_t	*seg_hash;
13027c478bdstevel@tonic-gate	fru_segdesc_t	*new_seg_desc;
13037c478bdstevel@tonic-gate	unsigned char 	*crcbuf;
13047c478bdstevel@tonic-gate	section_layout_t sec_layout;
13057c478bdstevel@tonic-gate	segment_layout_t *seg_layout;
13067c478bdstevel@tonic-gate	segment_layout_t *segment_buf;
13077c478bdstevel@tonic-gate
13087c478bdstevel@tonic-gate	/* check the effective uid of the client */
13097c478bdstevel@tonic-gate	if (cred->dc_euid != 0) {
13107c478bdstevel@tonic-gate		errno = EPERM;
13117c478bdstevel@tonic-gate		return (-1);	/* not a root */
13127c478bdstevel@tonic-gate	}
13137c478bdstevel@tonic-gate
13147c478bdstevel@tonic-gate	/* section hash */
13157c478bdstevel@tonic-gate	sec_hash = lookup_handle_object(section, SECTION_TYPE);
13167c478bdstevel@tonic-gate	if (sec_hash == NULL) {
13177c478bdstevel@tonic-gate		return (-1);
13187c478bdstevel@tonic-gate	}
13197c478bdstevel@tonic-gate
13207c478bdstevel@tonic-gate	/* check for read-only section */
13217c478bdstevel@tonic-gate	if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
13227c478bdstevel@tonic-gate		errno = EPERM;
13237c478bdstevel@tonic-gate		return (-1);
13247c478bdstevel@tonic-gate	}
13257c478bdstevel@tonic-gate
13267c478bdstevel@tonic-gate	/* look for duplicate segment */
13277c478bdstevel@tonic-gate	seg_hash = sec_hash->u.sec_obj->seg_obj_list;
13287c478bdstevel@tonic-gate	while (seg_hash != NULL) {
13297c478bdstevel@tonic-gate		if (strncmp(segment->name, seg_hash->u.seg_obj->segment.name,
13307c478bdstevel@tonic-gate		    SEG_NAME_LEN) == 0) {
13317c478bdstevel@tonic-gate			errno = EEXIST;
13327c478bdstevel@tonic-gate			return (-1); /* can't add duplicate segment */
13337c478bdstevel@tonic-gate		}
13347c478bdstevel@tonic-gate		seg_hash = seg_hash->u.seg_obj->next;
13357c478bdstevel@tonic-gate	}
13367c478bdstevel@tonic-gate
13377c478bdstevel@tonic-gate	/* get the container hash */
13387c478bdstevel@tonic-gate	cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
13397c478bdstevel@tonic-gate	    CONTAINER_TYPE);
13407c478bdstevel@tonic-gate	if (cont_hash == NULL) {
13417c478bdstevel@tonic-gate		return (-1);
13427c478bdstevel@tonic-gate	}
13437c478bdstevel@tonic-gate
13447c478bdstevel@tonic-gate	/* open the container */
13457c478bdstevel@tonic-gate	fd = open(cont_hash->u.cont_obj->device_pathname, O_RDWR);
13467c478bdstevel@tonic-gate	if (fd < 0) {
13477c478bdstevel@tonic-gate		return (-1);
13487c478bdstevel@tonic-gate	}
13497c478bdstevel@tonic-gate
13507c478bdstevel@tonic-gate	/* section start here */
13517c478bdstevel@tonic-gate	offset	= sec_hash->u.sec_obj->section.offset;
13527c478bdstevel@tonic-gate
13537c478bdstevel@tonic-gate	/* read section header layout */
13547c478bdstevel@tonic-gate	retval = pread(fd, &sec_layout, sizeof (sec_layout), offset);
13557c478bdstevel@tonic-gate	if (retval != sizeof (sec_layout)) {
13567c478bdstevel@tonic-gate		(void) close(fd);
13577c478bdstevel@tonic-gate		return (-1);
13587c478bdstevel@tonic-gate	}
13597c478bdstevel@tonic-gate
13607c478bdstevel@tonic-gate	/* check for valid section header */
13617c478bdstevel@tonic-gate	if (sec_layout.headertag != SECTION_HDR_TAG) {
13627c478bdstevel@tonic-gate		/* write a new one */
13637c478bdstevel@tonic-gate		sec_layout.headertag		= SECTION_HDR_TAG;
13647c478bdstevel@tonic-gate		sec_layout.headerversion[0]	= SECTION_HDR_VER_BIT0;
13657c478bdstevel@tonic-gate		sec_layout.headerversion[1]	= SECTION_HDR_VER_BIT1;
13667c478bdstevel@tonic-gate		sec_layout.headerlength		= sizeof (sec_layout);
13677c478bdstevel@tonic-gate		sec_layout.segmentcount		= 0;
13687c478bdstevel@tonic-gate	}
13697c478bdstevel@tonic-gate
13707c478bdstevel@tonic-gate	/* section size */
13717c478bdstevel@tonic-gate	sec_size	= sec_hash->u.sec_obj->section.length;
13727c478bdstevel@tonic-gate
13737c478bdstevel@tonic-gate	/* number of segment in the section */
13747c478bdstevel@tonic-gate	seg_cnt	= sec_layout.segmentcount;
13757c478bdstevel@tonic-gate
13767c478bdstevel@tonic-gate	/* total sizeof segment + new segment */
13777c478bdstevel@tonic-gate	bufsize	=	sizeof (segment_layout_t) * (seg_cnt + 1);
13787c478bdstevel@tonic-gate	segment_buf = alloca(bufsize);
13797c478bdstevel@tonic-gate	if (segment_buf == NULL) {
13807c478bdstevel@tonic-gate		return (-1);
13817c478bdstevel@tonic-gate	}
13827c478bdstevel@tonic-gate
13837c478bdstevel@tonic-gate	/* read entire segment header */
13847c478bdstevel@tonic-gate	retval = pread(fd, segment_buf,  (bufsize - sizeof (segment_layout_t)),
13857c478bdstevel@tonic-gate	    offset + sizeof (section_layout_t));
13867c478bdstevel@tonic-gate	if (retval != (bufsize - sizeof (segment_layout_t))) {
13877c478bdstevel@tonic-gate		(void) close(fd);
13887c478bdstevel@tonic-gate		return (-1);
13897c478bdstevel@tonic-gate	}
13907c478bdstevel@tonic-gate
13917c478bdstevel@tonic-gate	new_seg_offset	= segment->offset; /* new segment offset */
13927c478bdstevel@tonic-gate	new_seg_length	= segment->length; /* new segment length */
13937c478bdstevel@tonic-gate
13947c478bdstevel@tonic-gate	new_seg_desc	= (fru_segdesc_t *)&segment->descriptor;
13957c478bdstevel@tonic-gate
13967c478bdstevel@tonic-gate	fixed_segment	= new_seg_desc->field.fixed;
13977c478bdstevel@tonic-gate
13987c478bdstevel@tonic-gate	/* get new offset for new segment to be addedd */
13997c478bdstevel@tonic-gate	retval = find_offset((char *)segment_buf, seg_cnt, sec_size,
14007c478bdstevel@tonic-gate	    &new_seg_offset, new_seg_length, fixed_segment, fd);
14017c478bdstevel@tonic-gate
14027c478bdstevel@tonic-gate	if (retval != 0)	{
14037c478bdstevel@tonic-gate		(void) close(fd);
14047c478bdstevel@tonic-gate		errno = EAGAIN;
14057c478bdstevel@tonic-gate		return (-1);
14067c478bdstevel@tonic-gate	}
14077c478bdstevel@tonic-gate
14087c478bdstevel@tonic-gate	/* copy new segment data in segment layout */
14097c478bdstevel@tonic-gate	seg_layout	= (segment_layout_t *)(segment_buf + seg_cnt);
14107c478bdstevel@tonic-gate	(void) memcpy(&seg_layout->name, segment->name, SEG_NAME_LEN);
14117c478bdstevel@tonic-gate	(void) memcpy(seg_layout->descriptor, &segment->descriptor,
14127c478bdstevel@tonic-gate	    sizeof (uint32_t));
14137c478bdstevel@tonic-gate	seg_layout->length	= segment->length;
14147c478bdstevel@tonic-gate	seg_layout->offset	= new_seg_offset; /* new segment offset */
14157c478bdstevel@tonic-gate
14167c478bdstevel@tonic-gate	sec_layout.segmentcount += 1;
14177c478bdstevel@tonic-gate
14187c478bdstevel@tonic-gate	crcbuf	= alloca(sizeof (section_layout_t) + bufsize);
14197c478bdstevel@tonic-gate	if (crcbuf == NULL) {
14207c478bdstevel@tonic-gate		(void) close(fd);
14217c478bdstevel@tonic-gate		return (-1);
14227c478bdstevel@tonic-gate	}
14237c478bdstevel@tonic-gate
14247c478bdstevel@tonic-gate	sec_layout.headercrc8 = 0;
14257c478bdstevel@tonic-gate	sec_layout.headerlength += sizeof (segment_layout_t);
14267c478bdstevel@tonic-gate
14277c478bdstevel@tonic-gate	(void) memcpy(crcbuf, (char *)&sec_layout, sizeof (section_layout_t));
14287c478bdstevel@tonic-gate	(void) memcpy(crcbuf + sizeof (section_layout_t), segment_buf, bufsize);
14297c478bdstevel@tonic-gate
14307c478bdstevel@tonic-gate	sec_layout.headercrc8 = compute_crc8(crcbuf, bufsize +
14317c478bdstevel@tonic-gate	    sizeof (section_layout_t));
14327c478bdstevel@tonic-gate
14337c478bdstevel@tonic-gate	/* write section header */
14347c478bdstevel@tonic-gate	retval = pwrite(fd, &sec_layout, sizeof (section_layout_t), offset);
14357c478bdstevel@tonic-gate	if (retval != sizeof (section_layout_t)) {
14367c478bdstevel@tonic-gate		(void) close(fd);
14377c478bdstevel@tonic-gate		return (-1);
14387c478bdstevel@tonic-gate	}
14397c478bdstevel@tonic-gate
14407c478bdstevel@tonic-gate	/* write segment header */
14417c478bdstevel@tonic-gate	retval = pwrite(fd, segment_buf, bufsize, offset +
14427c478bdstevel@tonic-gate	    sizeof (section_layout_t));
14437c478bdstevel@tonic-gate	if (retval != bufsize) {
14447c478bdstevel@tonic-gate		(void) close(fd);
14457c478bdstevel@tonic-gate		return (-1);
14467c478bdstevel@tonic-gate	}
14477c478bdstevel@tonic-gate
14487c478bdstevel@tonic-gate	/* write segment trailer */
14497c478bdstevel@tonic-gate	retval = pwrite(fd, &trailer, sizeof (trailer), new_seg_offset);
14507c478bdstevel@tonic-gate	if (retval != sizeof (trailer)) {
14517c478bdstevel@tonic-gate		(void) close(fd);
14527c478bdstevel@tonic-gate		return (-1);
14537c478bdstevel@tonic-gate	}
14547c478bdstevel@tonic-gate
14557c478bdstevel@tonic-gate	(void) close(fd);
14567c478bdstevel@tonic-gate
14577c478bdstevel@tonic-gate	/* create new segment hash object */
14587c478bdstevel@tonic-gate	seg_hash	= create_segment_hash_object();
14597c478bdstevel@tonic-gate	if (seg_hash == NULL) {
14607c478bdstevel@tonic-gate		return (-1);
14617c478bdstevel@tonic-gate	}
14627c478bdstevel@tonic-gate
14637c478bdstevel@tonic-gate	add_hashobject_to_hashtable(seg_hash);
14647c478bdstevel@tonic-gate
14657c478bdstevel@tonic-gate	copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_layout);
14667c478bdstevel@tonic-gate
14677c478bdstevel@tonic-gate	add_to_seg_object_list(sec_hash, seg_hash);
14687c478bdstevel@tonic-gate
14697c478bdstevel@tonic-gate	sec_hash->u.sec_obj->num_of_segment += 1;
14707c478bdstevel@tonic-gate	seg_hash->u.seg_obj->trailer_offset = new_seg_offset;
14717c478bdstevel@tonic-gate	*newsection	= section; /* return the new section handle */
14727c478bdstevel@tonic-gate	return (0);
14737c478bdstevel@tonic-gate}
14747c478bdstevel@tonic-gate
14757c478bdstevel@tonic-gatestatic void
14767c478bdstevel@tonic-gatefree_pkt_object_list(hash_obj_t	*hash_obj)
14777c478bdstevel@tonic-gate{
14787c478bdstevel@tonic-gate	hash_obj_t	*next_obj;
14797c478bdstevel@tonic-gate	hash_obj_t	*free_obj;
14807c478bdstevel@tonic-gate
14817c478bdstevel@tonic-gate	next_obj = hash_obj->u.seg_obj->pkt_obj_list;
14827c478bdstevel@tonic-gate	while (next_obj != NULL) {
14837c478bdstevel@tonic-gate		free_obj = next_obj;
14847c478bdstevel@tonic-gate		next_obj = next_obj->u.pkt_obj->next;
14857c478bdstevel@tonic-gate		/* if prev is NULL it's the first object in the list */
14867c478bdstevel@tonic-gate		if (free_obj->prev == NULL) {
14877c478bdstevel@tonic-gate			hash_table[(free_obj->obj_hdl % TABLE_SIZE)] =
14887c478bdstevel@tonic-gate			    free_obj->next;
14897c478bdstevel@tonic-gate			if (free_obj->next != NULL) {
14907c478bdstevel@tonic-gate				free_obj->next->prev = free_obj->prev;
14917c478bdstevel@tonic-gate			}
14927c478bdstevel@tonic-gate		} else {
14937c478bdstevel@tonic-gate			free_obj->prev->next = free_obj->next;
14947c478bdstevel@tonic-gate			if (free_obj->next != NULL) {
14957c478bdstevel@tonic-gate				free_obj->next->prev = free_obj->prev;
14967c478bdstevel@tonic-gate			}
14977c478bdstevel@tonic-gate		}
14987c478bdstevel@tonic-gate
14997c478bdstevel@tonic-gate		free(free_obj->u.pkt_obj->payload);
15007c478bdstevel@tonic-gate		free(free_obj->u.pkt_obj);
15017c478bdstevel@tonic-gate		free(free_obj);
15027c478bdstevel@tonic-gate	}
15037c478bdstevel@tonic-gate
15047c478bdstevel@tonic-gate	hash_obj->u.seg_obj->pkt_obj_list = NULL;
15057c478bdstevel@tonic-gate}
15067c478bdstevel@tonic-gate
15077c478bdstevel@tonic-gatestatic void
15087c478bdstevel@tonic-gatefree_segment_hash(handle_t	handle, hash_obj_t	*sec_hash)
15097c478bdstevel@tonic-gate{
15107c478bdstevel@tonic-gate	hash_obj_t	*seg_hash;
15117c478bdstevel@tonic-gate	hash_obj_t	*next_hash;
15127c478bdstevel@tonic-gate
15137c478bdstevel@tonic-gate	seg_hash	= sec_hash->u.sec_obj->seg_obj_list;
15147c478bdstevel@tonic-gate	if (seg_hash == NULL) {
15157c478bdstevel@tonic-gate		return;
15167c478bdstevel@tonic-gate	}
15177c478bdstevel@tonic-gate
15187c478bdstevel@tonic-gate	if (seg_hash->obj_hdl == handle) {
15197c478bdstevel@tonic-gate		sec_hash->u.sec_obj->seg_obj_list = seg_hash->u.seg_obj->next;
15207c478bdstevel@tonic-gate	} else {
15217c478bdstevel@tonic-gate		while (seg_hash->obj_hdl != handle) {
15227c478bdstevel@tonic-gate			next_hash	= seg_hash;
15237c478bdstevel@tonic-gate			seg_hash = seg_hash->u.seg_obj->next;
15247c478bdstevel@tonic-gate			if (seg_hash == NULL) {
15257c478bdstevel@tonic-gate				return;
15267c478bdstevel@tonic-gate			}
15277c478bdstevel@tonic-gate		}
15287c478bdstevel@tonic-gate		next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next;
15297c478bdstevel@tonic-gate	}
15307c478bdstevel@tonic-gate
15317c478bdstevel@tonic-gate	if (seg_hash->prev == NULL) {
15327c478bdstevel@tonic-gate		hash_table[(seg_hash->obj_hdl % TABLE_SIZE)] = seg_hash->next;
15337c478bdstevel@tonic-gate		if (seg_hash->next != NULL) {
15347c478bdstevel@tonic-gate			seg_hash->next->prev = NULL;
15357c478bdstevel@tonic-gate		}
15367c478bdstevel@tonic-gate	} else {
15377c478bdstevel@tonic-gate		seg_hash->prev->next = seg_hash->next;
15387c478bdstevel@tonic-gate		if (seg_hash->next != NULL) {
15397c478bdstevel@tonic-gate			seg_hash->next->prev = seg_hash->prev;
15407c478bdstevel@tonic-gate		}
15417c478bdstevel@tonic-gate	}
15427c478bdstevel@tonic-gate
15437c478bdstevel@tonic-gate	free_pkt_object_list(seg_hash);
15447c478bdstevel@tonic-gate	free(seg_hash->u.seg_obj);
15457c478bdstevel@tonic-gate	free(seg_hash);
15467c478bdstevel@tonic-gate}
15477c478bdstevel@tonic-gate
15487c478bdstevel@tonic-gate/*
15497c478bdstevel@tonic-gate * Description	:
15507c478bdstevel@tonic-gate *		fru_delete_segment() deletes a segment from a section; the
15517c478bdstevel@tonic-gate *		associated container data is not altered.
15527c478bdstevel@tonic-gate *
15537c478bdstevel@tonic-gate * Arguments	: segment_hdl_t	segment handle.
15547c478bdstevel@tonic-gate *		  section_hdl_t	new section handle.
15557c478bdstevel@tonic-gate *
15567c478bdstevel@tonic-gate * Return	:
15577c478bdstevel@tonic-gate *		int
15587c478bdstevel@tonic-gate *		On success, 0 returned; On error -1 is returned.
15597c478bdstevel@tonic-gate */
15607c478bdstevel@tonic-gate
15617c478bdstevel@tonic-gateint
15627c478bdstevel@tonic-gatefru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection,
15637c478bdstevel@tonic-gate							door_cred_t *cred)
15647c478bdstevel@tonic-gate{
15657c478bdstevel@tonic-gate	int			num_of_seg;
15667c478bdstevel@tonic-gate	int			bufsize;
15677c478bdstevel@tonic-gate	int			count;
15687c478bdstevel@tonic-gate	int			retval;
15697c478bdstevel@tonic-gate	int			fd;
15707c478bdstevel@tonic-gate	int			segnum;
15717c478bdstevel@tonic-gate	hash_obj_t		*seg_hash;
15727c478bdstevel@tonic-gate	hash_obj_t		*sec_hash;
15737c478bdstevel@tonic-gate	hash_obj_t		*cont_hash;
15747c478bdstevel@tonic-gate	hash_obj_t		*tmp_hash;
15757c478bdstevel@tonic-gate	unsigned char		*buffer;
15767c478bdstevel@tonic-gate	fru_segdesc_t		*desc;
15777c478bdstevel@tonic-gate	segment_layout_t	*seg_buf;
15787c478bdstevel@tonic-gate	section_layout_t	*sec_layout;
15797c478bdstevel@tonic-gate	segment_layout_t	*seg_layout;
15807c478bdstevel@tonic-gate	segment_layout_t	*next_layout;
15817c478bdstevel@tonic-gate
15827c478bdstevel@tonic-gate	/* check the effective uid of the client */
15837c478bdstevel@tonic-gate	if (cred->dc_euid != 0) {
15847c478bdstevel@tonic-gate		errno = EPERM;
15857c478bdstevel@tonic-gate		return (-1);	/* not a root */
15867c478bdstevel@tonic-gate	}
15877c478bdstevel@tonic-gate
15887c478bdstevel@tonic-gate	seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
15897c478bdstevel@tonic-gate	if (seg_hash == NULL) {
15907c478bdstevel@tonic-gate		return (-1);
15917c478bdstevel@tonic-gate	}
15927c478bdstevel@tonic-gate
15937c478bdstevel@tonic-gate	desc    = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
15947c478bdstevel@tonic-gate	if (!(desc->field.field_perm & SEGMENT_DELETE)) {
15957c478bdstevel@tonic-gate		errno = EPERM;
15967c478bdstevel@tonic-gate		return (-1); /* can't delete this segment */
15977c478bdstevel@tonic-gate	}
15987c478bdstevel@tonic-gate
15997c478bdstevel@tonic-gate	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
16007c478bdstevel@tonic-gate	    SECTION_TYPE);
16017c478bdstevel@tonic-gate	if (sec_hash == NULL) {
16027c478bdstevel@tonic-gate		return (-1);
16037c478bdstevel@tonic-gate	}
16047c478bdstevel@tonic-gate
16057c478bdstevel@tonic-gate	if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
16067c478bdstevel@tonic-gate		errno = EPERM;
16077c478bdstevel@tonic-gate		return (-1);
16087c478bdstevel@tonic-gate	}
16097c478bdstevel@tonic-gate
16107c478bdstevel@tonic-gate	num_of_seg	= sec_hash->u.sec_obj->num_of_segment;
16117c478bdstevel@tonic-gate
16127c478bdstevel@tonic-gate	bufsize	= (sizeof (segment_layout_t) * num_of_seg);
16137c478bdstevel@tonic-gate
16147c478bdstevel@tonic-gate	seg_buf	= alloca(bufsize);
16157c478bdstevel@tonic-gate	if (seg_buf == NULL) {
16167c478bdstevel@tonic-gate		return (-1);
16177c478bdstevel@tonic-gate	}
16187c478bdstevel@tonic-gate
16197c478bdstevel@tonic-gate	segnum	= 0;
16207c478bdstevel@tonic-gate	for (tmp_hash = sec_hash->u.sec_obj->seg_obj_list; tmp_hash != NULL;
16217c478bdstevel@tonic-gate	    tmp_hash = tmp_hash->u.seg_obj->next) {
16227c478bdstevel@tonic-gate		if (tmp_hash->obj_hdl == segment) {
16237c478bdstevel@tonic-gate			break;
16247c478bdstevel@tonic-gate		}
16257c478bdstevel@tonic-gate		segnum++;
16267c478bdstevel@tonic-gate	}
16277c478bdstevel@tonic-gate
16287c478bdstevel@tonic-gate	cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
16297c478bdstevel@tonic-gate	    CONTAINER_TYPE);
16307c478bdstevel@tonic-gate	if (cont_hash == NULL) {
16317c478bdstevel@tonic-gate		return (-1);
16327c478bdstevel@tonic-gate	}
16337c478bdstevel@tonic-gate
16347c478bdstevel@tonic-gate	fd  = open(cont_hash->u.cont_obj->device_pathname, O_RDWR);
16357c478bdstevel@tonic-gate	if (fd < 0) {
16367c478bdstevel@tonic-gate		return (-1);
16377c478bdstevel@tonic-gate	}
16387c478bdstevel@tonic-gate
16397c478bdstevel@tonic-gate	sec_layout	= alloca(sizeof (section_layout_t));
16407c478bdstevel@tonic-gate	if (sec_layout == NULL) {
16417c478bdstevel@tonic-gate		(void) close(fd);
16427c478bdstevel@tonic-gate		return (-1);
16437c478bdstevel@tonic-gate	}
16447c478bdstevel@tonic-gate
16457c478bdstevel@tonic-gate	/* read section layout header */
16467c478bdstevel@tonic-gate	retval = pread(fd, sec_layout, sizeof (section_layout_t),
16477c478bdstevel@tonic-gate	    sec_hash->u.sec_obj->section.offset);
16487c478bdstevel@tonic-gate	if (retval != sizeof (section_layout_t)) {
16497c478bdstevel@tonic-gate		(void) close(fd);
16507c478bdstevel@tonic-gate		return (-1);
16517c478bdstevel@tonic-gate	}
16527c478bdstevel@tonic-gate
16537c478bdstevel@tonic-gate	/* read segment header layout */
16547c478bdstevel@tonic-gate	retval = pread(fd, seg_buf, bufsize,
16557c478bdstevel@tonic-gate	    sec_hash->u.sec_obj->section.offset + sizeof (section_layout_t));
16567c478bdstevel@tonic-gate	if (retval != bufsize) {
16577c478bdstevel@tonic-gate		(void) close(fd);
16587c478bdstevel@tonic-gate		return (-1);
16597c478bdstevel@tonic-gate	}
16607c478bdstevel@tonic-gate
16617c478bdstevel@tonic-gate	seg_layout = (segment_layout_t *)(seg_buf + segnum);
16627c478bdstevel@tonic-gate	next_layout	= seg_layout;
16637c478bdstevel@tonic-gate	for (count = segnum;
16647c478bdstevel@tonic-gate	    count < sec_hash->u.sec_obj->num_of_segment - 1; count++) {
16657c478bdstevel@tonic-gate		next_layout++;
16667c478bdstevel@tonic-gate		(void) memcpy(seg_layout, next_layout,
16677c478bdstevel@tonic-gate		    sizeof (segment_layout_t));
16687c478bdstevel@tonic-gate		seg_layout++;
16697c478bdstevel@tonic-gate	}
16707c478bdstevel@tonic-gate
16717c478bdstevel@tonic-gate	(void) memset(seg_layout, '\0', sizeof (segment_layout_t));
16727c478bdstevel@tonic-gate
16737c478bdstevel@tonic-gate	sec_layout->headercrc8 = 0;
16747c478bdstevel@tonic-gate
16757c478bdstevel@tonic-gate	sec_layout->headerlength -= sizeof (segment_layout_t);
16767c478bdstevel@tonic-gate	sec_layout->segmentcount -= 1;
16777c478bdstevel@tonic-gate
16787c478bdstevel@tonic-gate	buffer = alloca(sec_layout->headerlength);
16797c478bdstevel@tonic-gate	if (buffer == NULL) {
16807c478bdstevel@tonic-gate		(void) close(fd);
16817c478bdstevel@tonic-gate		return (-1);
16827c478bdstevel@tonic-gate	}
16837c478bdstevel@tonic-gate
16847c478bdstevel@tonic-gate	(void) memcpy(buffer, sec_layout, sizeof (section_layout_t));
16857c478bdstevel@tonic-gate	(void) memcpy(buffer + sizeof (section_layout_t), seg_buf, bufsize -
16867c478bdstevel@tonic-gate	    sizeof (segment_layout_t));
16877c478bdstevel@tonic-gate	sec_layout->headercrc8 = compute_crc8(buffer, sec_layout->headerlength);
16887c478bdstevel@tonic-gate
16897c478bdstevel@tonic-gate	/* write section header with update crc8 and header length */
16907c478bdstevel@tonic-gate	retval = pwrite(fd, sec_layout, sizeof (section_layout_t),
16917c478bdstevel@tonic-gate	    sec_hash->u.sec_obj->section.offset);
16927c478bdstevel@tonic-gate	if (retval != sizeof (section_layout_t)) {
16937c478bdstevel@tonic-gate		(void) close(fd);
16947c478bdstevel@tonic-gate		return (-1);
16957c478bdstevel@tonic-gate	}
16967c478bdstevel@tonic-gate
16977c478bdstevel@tonic-gate	/* write the update segment header */
16987c478bdstevel@tonic-gate	retval = pwrite(fd, seg_buf, bufsize,
16997c478bdstevel@tonic-gate	    sec_hash->u.sec_obj->section.offset + sizeof (section_layout_t));
17007c478bdstevel@tonic-gate	(void) close(fd);
17017c478bdstevel@tonic-gate	if (retval != bufsize) {
17027c478bdstevel@tonic-gate		return (-1);
17037c478bdstevel@tonic-gate	}
17047c478bdstevel@tonic-gate
17057c478bdstevel@tonic-gate	free_segment_hash(segment, sec_hash);
17067c478bdstevel@tonic-gate
17077c478bdstevel@tonic-gate	*newsection	= sec_hash->obj_hdl;
17087c478bdstevel@tonic-gate	sec_hash->u.sec_obj->num_of_segment = sec_layout->segmentcount;
17097c478bdstevel@tonic-gate
17107c478bdstevel@tonic-gate	return (0);
17117c478bdstevel@tonic-gate}
17127c478bdstevel@tonic-gate
17137c478bdstevel@tonic-gate/*
17147c478bdstevel@tonic-gate * Description	:
17157c478bdstevel@tonic-gate * 		fru_read_segment() reads the raw contents of a segment.
17167c478bdstevel@tonic-gate *
17177c478bdstevel@tonic-gate * Arguments	: segment_hdl_t : segment handle.
17187c478bdstevel@tonic-gate *		 void *	: buffer containing segment data when function returns.
17197c478bdstevel@tonic-gate *		size_t :number of bytes.
17207c478bdstevel@tonic-gate *
17217c478bdstevel@tonic-gate * Return	:
17227c478bdstevel@tonic-gate * 		int
17237c478bdstevel@tonic-gate *		On success, the number of bytes read is returned;
17247c478bdstevel@tonic-gate *
17257c478bdstevel@tonic-gate * Notes	:
17267c478bdstevel@tonic-gate *		Segments containing packets can be read in structured fashion
17277c478bdstevel@tonic-gate *		using the fru_get_packets() and fru_get_payload() primitives;the
17287c478bdstevel@tonic-gate *		entire byte range of a segment can be read using
17297c478bdstevel@tonic-gate *		fru_read_segment().
17307c478bdstevel@tonic-gate */
17317c478bdstevel@tonic-gate
17327c478bdstevel@tonic-gate/* ARGSUSED */
17337c478bdstevel@tonic-gatessize_t
17347c478bdstevel@tonic-gatefru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes,
17357c478bdstevel@tonic-gate    door_cred_t *cred)
17367c478bdstevel@tonic-gate{
17377c478bdstevel@tonic-gate	int		fd;
17387c478bdstevel@tonic-gate	int		retval;
17397c478bdstevel@tonic-gate	hash_obj_t	*seg_hash;
17407c478bdstevel@tonic-gate	hash_obj_t	*sec_hash;
17417c478bdstevel@tonic-gate	hash_obj_t	*cont_hash;
17427c478bdstevel@tonic-gate
17437c478bdstevel@tonic-gate	/* segment hash object */
17447c478bdstevel@tonic-gate	seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
17457c478bdstevel@tonic-gate	if (seg_hash == NULL) {
17467c478bdstevel@tonic-gate		return (-1);
17477c478bdstevel@tonic-gate	}
17487c478bdstevel@tonic-gate
17497c478bdstevel@tonic-gate	/* section hash object */
17507c478bdstevel@tonic-gate	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
17517c478bdstevel@tonic-gate	    SECTION_TYPE);
17527c478bdstevel@tonic-gate	if (sec_hash == NULL) {
17537c478bdstevel@tonic-gate		return (-1);
17547c478bdstevel@tonic-gate	}
17557c478bdstevel@tonic-gate
17567c478bdstevel@tonic-gate	/* container hash object */
17577c478bdstevel@tonic-gate	cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
17587c478bdstevel@tonic-gate	    CONTAINER_TYPE);
17597c478bdstevel@tonic-gate	if (cont_hash == NULL) {
17607c478bdstevel@tonic-gate		return (-1);
17617c478bdstevel@tonic-gate	}
17627c478bdstevel@tonic-gate
17637c478bdstevel@tonic-gate	if (seg_hash->u.seg_obj->segment.length < nbytes) {
17647c478bdstevel@tonic-gate		return (-1);
17657c478bdstevel@tonic-gate	}
17667c478bdstevel@tonic-gate
17677c478bdstevel@tonic-gate	fd = open(cont_hash->u.cont_obj->device_pathname, O_RDONLY);
17687c478bdstevel@tonic-gate	if (fd < 0) {
17697c478bdstevel@tonic-gate		return (-1);
17707c478bdstevel@tonic-gate	}
17717c478bdstevel@tonic-gate
17727c478bdstevel@tonic-gate	switch (sec_hash->u.sec_obj->encoding) {
17737c478bdstevel@tonic-gate	case ENC_STANDARD:
17747c478bdstevel@tonic-gate		retval = pread(fd, buffer, nbytes,
17757c478bdstevel@tonic-gate		    seg_hash->u.seg_obj->segment.offset);
17767c478bdstevel@tonic-gate		(void) close(fd);
17777c478bdstevel@tonic-gate		if (retval != nbytes) {
17787c478bdstevel@tonic-gate			return (-1);
17797c478bdstevel@tonic-gate		}
17807c478bdstevel@tonic-gate		break;
17817c478bdstevel@tonic-gate
17827c478bdstevel@tonic-gate	case ENC_SPD: {
17837c478bdstevel@tonic-gate		char	*spd_buf;
17847c478bdstevel@tonic-gate		uchar_t	*ptr;
17857c478bdstevel@tonic-gate		size_t	len;
17867c478bdstevel@tonic-gate
17877c478bdstevel@tonic-gate		spd_buf = alloca(sec_hash->u.sec_obj->section.length);
17887c478bdstevel@tonic-gate		if (spd_buf == NULL)
17897c478bdstevel@tonic-gate			retval = -1;
17907c478bdstevel@tonic-gate		else {
17917c478bdstevel@tonic-gate			retval = get_spd_data(fd, spd_buf,
17927c478bdstevel@tonic-gate			    sec_hash->u.sec_obj->section.length,
17937c478bdstevel@tonic-gate			    seg_hash->u.seg_obj->segment.offset);
17947c478bdstevel@tonic-gate		}
17957c478bdstevel@tonic-gate		(void) close(fd);
17967c478bdstevel@tonic-gate		if (retval != 0) {
17977c478bdstevel@tonic-gate			return (-1);
17987c478bdstevel@tonic-gate		}
17997c478bdstevel@tonic-gate		retval = cvrt_dim_data(spd_buf,
18007c478bdstevel@tonic-gate		    sec_hash->u.sec_obj->section.length, &ptr, &len);
18017c478bdstevel@tonic-gate		if (retval != 0) {
18027c478bdstevel@tonic-gate			return (-1);
18037c478bdstevel@tonic-gate		}
18047c478bdstevel@tonic-gate		if (nbytes > len)
18057c478bdstevel@tonic-gate			nbytes = len;
18067c478bdstevel@tonic-gate		(void) memcpy(buffer, ptr, nbytes);
18077c478bdstevel@tonic-gate		free(ptr);
18087c478bdstevel@tonic-gate		break;
18097c478bdstevel@tonic-gate	}
18107c478bdstevel@tonic-gate
18117c478bdstevel@tonic-gate	default:
18127c478bdstevel@tonic-gate		return (-1);
18137c478bdstevel@tonic-gate	}
18147c478bdstevel@tonic-gate
18157c478bdstevel@tonic-gate	return (nbytes);
18167c478bdstevel@tonic-gate}
18177c478bdstevel@tonic-gate
18187c478bdstevel@tonic-gate/*
18197c478bdstevel@tonic-gate * Description	:
18207c478bdstevel@tonic-gate *		fru_write_segment() writes a raw segment.
18217c478bdstevel@tonic-gate *
18227c478bdstevel@tonic-gate * Arguments	: segment_hdl_t :segment handle.
18237c478bdstevel@tonic-gate *		 const void * : data buffer.
18247c478bdstevel@tonic-gate *		 size_t	: number of bytes.
18257c478bdstevel@tonic-gate *		 segment_hdl_t : new segment handle.
18267c478bdstevel@tonic-gate *
18277c478bdstevel@tonic-gate * Returns	:
18287c478bdstevel@tonic-gate *		int
18297c478bdstevel@tonic-gate *		On success, the number of bytes written is returned
18307c478bdstevel@tonic-gate *
18317c478bdstevel@tonic-gate */
18327c478bdstevel@tonic-gate/*ARGSUSED*/
18337c478bdstevel@tonic-gateint
18347c478bdstevel@tonic-gatefru_write_segment(segment_hdl_t segment, const void *data, size_t nbytes,
18357c478bdstevel@tonic-gate    segment_hdl_t *newsegment, door_cred_t *cred)
18367c478bdstevel@tonic-gate{
18377c478bdstevel@tonic-gate	return (ENOTSUP);
18387c478bdstevel@tonic-gate}
18397c478bdstevel@tonic-gate
18407c478bdstevel@tonic-gate
18417c478bdstevel@tonic-gatestatic int
18427c478bdstevel@tonic-gateget_packet(int device_fd, void *buffer, int size, int offset)
18437c478bdstevel@tonic-gate{
18447c478bdstevel@tonic-gate	int	retval;
18457c478bdstevel@tonic-gate
18467c478bdstevel@tonic-gate	retval = pread(device_fd, (char *)buffer, size, offset);
18477c478bdstevel@tonic-gate	if (retval != -1) {
18487c478bdstevel@tonic-gate		return (0);
18497c478bdstevel@tonic-gate	}
18507c478bdstevel@tonic-gate	return (-1);
18517c478bdstevel@tonic-gate}
18527c478bdstevel@tonic-gate
18537c478bdstevel@tonic-gatestatic uint32_t
18547c478bdstevel@tonic-gateget_checksum_crc(hash_obj_t	*seg_hash, int data_size)
18557c478bdstevel@tonic-gate{
18567c478bdstevel@tonic-gate	int		protection;
18577c478bdstevel@tonic-gate	int		offset = 0;
18587c478bdstevel@tonic-gate	uint32_t	crc;
18597c478bdstevel@tonic-gate	hash_obj_t	*sec_hash;
18607c478bdstevel@tonic-gate	hash_obj_t	*pkt_hash;
18617c478bdstevel@tonic-gate	unsigned char	*buffer;
18627c478bdstevel@tonic-gate
18637c478bdstevel@tonic-gate	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
18647c478bdstevel@tonic-gate	    SECTION_TYPE);
18657c478bdstevel@tonic-gate	if (sec_hash == NULL) {
18667c478bdstevel@tonic-gate		return ((uint32_t)-1);
18677c478bdstevel@tonic-gate	}
18687c478bdstevel@tonic-gate
18697c478bdstevel@tonic-gate	buffer = alloca(data_size);
18707c478bdstevel@tonic-gate	if (buffer == NULL) {
18717c478bdstevel@tonic-gate		return ((uint32_t)-1);
18727c478bdstevel@tonic-gate	}
18737c478bdstevel@tonic-gate
18747c478bdstevel@tonic-gate	/* traverse the packet object list for all the tags and payload */
18757c478bdstevel@tonic-gate	for (pkt_hash = seg_hash->u.seg_obj->pkt_obj_list;
18767c478bdstevel@tonic-gate	    pkt_hash != NULL; pkt_hash = pkt_hash->u.pkt_obj->next) {
18777c478bdstevel@tonic-gate		(void) memcpy(buffer + offset, &pkt_hash->u.pkt_obj->tag,
18787c478bdstevel@tonic-gate		    pkt_hash->u.pkt_obj->tag_size);
18797c478bdstevel@tonic-gate		offset += pkt_hash->u.pkt_obj->tag_size;
18807c478bdstevel@tonic-gate		(void) memcpy(buffer + offset, pkt_hash->u.pkt_obj->payload,
18817c478bdstevel@tonic-gate		    pkt_hash->u.pkt_obj->paylen);
18827c478bdstevel@tonic-gate		offset += pkt_hash->u.pkt_obj->paylen;
18837c478bdstevel@tonic-gate	}
18847c478bdstevel@tonic-gate
18857c478bdstevel@tonic-gate	protection	= sec_hash->u.sec_obj->section.protection;
18867c478bdstevel@tonic-gate
18877c478bdstevel@tonic-gate	if (protection == READ_ONLY_SECTION) { /* read-only section */
18887c478bdstevel@tonic-gate		crc = compute_crc32(buffer, data_size);
18897c478bdstevel@tonic-gate	} else {		/* read/write section */
18907c478bdstevel@tonic-gate		crc = compute_checksum32(buffer, data_size);
18917c478bdstevel@tonic-gate	}
18927c478bdstevel@tonic-gate	return (crc);	/* computed crc */
18937c478bdstevel@tonic-gate}
18947c478bdstevel@tonic-gate
18957c478bdstevel@tonic-gatestatic int
18967c478bdstevel@tonic-gateget_dev_or_buffered_packets(hash_obj_t *seg_hash, int device_fd, int offset,
18977c478bdstevel@tonic-gate    int length, const char *buf)
18987c478bdstevel@tonic-gate{
18997c478bdstevel@tonic-gate	int		tag_size;
19007c478bdstevel@tonic-gate	int		paylen;
19017c478bdstevel@tonic-gate	int		retval;
19027c478bdstevel@tonic-gate	int		seg_limit = 0;
19037c478bdstevel@tonic-gate	int		pktcnt	= 0;
19047c478bdstevel@tonic-gate	char		*data;
19057c478bdstevel@tonic-gate	uint32_t	crc;
19067c478bdstevel@tonic-gate	uint32_t	origcrc;
19077c478bdstevel@tonic-gate	fru_tag_t	tag;
19087c478bdstevel@tonic-gate	hash_obj_t	*pkt_hash_obj;
19097c478bdstevel@tonic-gate	fru_segdesc_t	*segdesc;
19107c478bdstevel@tonic-gate	fru_tagtype_t	tagtype;
19117c478bdstevel@tonic-gate
19127c478bdstevel@tonic-gate	if (buf == NULL) {
19137c478bdstevel@tonic-gate		retval = get_packet(device_fd, &tag, sizeof (fru_tag_t),
19147c478bdstevel@tonic-gate		    offset);
19157c478bdstevel@tonic-gate		if (retval == -1) {
19167c478bdstevel@tonic-gate			return (-1);
19177c478bdstevel@tonic-gate		}
19187c478bdstevel@tonic-gate	} else if (length - offset < sizeof (fru_tag_t)) {
19197c478bdstevel@tonic-gate		return (-1);
19207c478bdstevel@tonic-gate	} else {
19217c478bdstevel@tonic-gate		(void) memcpy(&tag, buf + offset, sizeof (fru_tag_t));
19227c478bdstevel@tonic-gate	}
19237c478bdstevel@tonic-gate
19247c478bdstevel@tonic-gate	seg_hash->u.seg_obj->trailer_offset = offset;
19257c478bdstevel@tonic-gate
19267c478bdstevel@tonic-gate	data	= (char *)&tag;
19277c478bdstevel@tonic-gate	while (data[0] != SEG_TRAILER_TAG) {
19287c478bdstevel@tonic-gate		tagtype	= get_tag_type(&tag); /* verify tag type */
19297c478bdstevel@tonic-gate		if (tagtype == -1) {
19307c478bdstevel@tonic-gate			return (-1);
19317c478bdstevel@tonic-gate		}
19327c478bdstevel@tonic-gate
19337c478bdstevel@tonic-gate		tag_size = get_tag_size(tagtype);
19347c478bdstevel@tonic-gate		if (tag_size == -1) {
19357c478bdstevel@tonic-gate			return (-1);
19367c478bdstevel@tonic-gate		}
19377c478bdstevel@tonic-gate
19387c478bdstevel@tonic-gate		seg_limit += tag_size;
19397c478bdstevel@tonic-gate		if (seg_limit > length) {
19407c478bdstevel@tonic-gate			return (-1);
19417c478bdstevel@tonic-gate		}
19427c478bdstevel@tonic-gate
19437c478bdstevel@tonic-gate		paylen = get_payload_length((void *)&tag);
19447c478bdstevel@tonic-gate		if (paylen == -1) {
19457c478bdstevel@tonic-gate			return (-1);
19467c478bdstevel@tonic-gate		}
19477c478bdstevel@tonic-gate
19487c478bdstevel@tonic-gate		seg_limit += paylen;
19497c478bdstevel@tonic-gate		if (seg_limit > length) {
19507c478bdstevel@tonic-gate			return (-1);
19517c478bdstevel@tonic-gate		}
19527c478bdstevel@tonic-gate
19537c478bdstevel@tonic-gate		pkt_hash_obj = create_packet_hash_object();
19547c478bdstevel@tonic-gate		if (pkt_hash_obj == NULL) {
19557c478bdstevel@tonic-gate			return (-1);
19567c478bdstevel@tonic-gate		}
19577c478bdstevel@tonic-gate
19587c478bdstevel@tonic-gate		pkt_hash_obj->u.pkt_obj->payload = malloc(paylen);
19597c478bdstevel@tonic-gate		if (pkt_hash_obj->u.pkt_obj->payload == NULL) {
19607c478bdstevel@tonic-gate			free(pkt_hash_obj);
19617c478bdstevel@tonic-gate			return (-1);
19627c478bdstevel@tonic-gate		}
19637c478bdstevel@tonic-gate
19647c478bdstevel@tonic-gate		offset += tag_size;
19657c478bdstevel@tonic-gate		if (buf == NULL) {
19667c478bdstevel@tonic-gate			retval = pread(device_fd,
19677c478bdstevel@tonic-gate			    pkt_hash_obj->u.pkt_obj->payload, paylen, offset);
19687c478bdstevel@tonic-gate		} else if (paylen + offset > length) {
19697c478bdstevel@tonic-gate			retval = 0;
19707c478bdstevel@tonic-gate		} else {
19717c478bdstevel@tonic-gate			(void) memcpy(pkt_hash_obj->u.pkt_obj->payload,
19727c478bdstevel@tonic-gate			    buf + offset, paylen);
19737c478bdstevel@tonic-gate			retval = paylen;
19747c478bdstevel@tonic-gate		}
19757c478bdstevel@tonic-gate		if (retval != paylen) {
19767c478bdstevel@tonic-gate			free(pkt_hash_obj->u.pkt_obj->payload);
19777c478bdstevel@tonic-gate			free(pkt_hash_obj);
19787c478bdstevel@tonic-gate			return (-1);
19797c478bdstevel@tonic-gate		}
19807c478bdstevel@tonic-gate
19817c478bdstevel@tonic-gate		/* don't change this */
19827c478bdstevel@tonic-gate		pkt_hash_obj->u.pkt_obj->tag.raw_data = 0;
19837c478bdstevel@tonic-gate		(void) memcpy(&pkt_hash_obj->u.pkt_obj->tag, &tag, tag_size);
19847c478bdstevel@tonic-gate		pkt_hash_obj->u.pkt_obj->paylen = paylen;
19857c478bdstevel@tonic-gate		pkt_hash_obj->u.pkt_obj->tag_size = tag_size;
19867c478bdstevel@tonic-gate		pkt_hash_obj->u.pkt_obj->payload_offset = offset;
19877c478bdstevel@tonic-gate
19887c478bdstevel@tonic-gate		offset += paylen;
19897c478bdstevel@tonic-gate
19907c478bdstevel@tonic-gate		add_hashobject_to_hashtable(pkt_hash_obj);
19917c478bdstevel@tonic-gate		add_to_pkt_object_list(seg_hash, pkt_hash_obj);
19927c478bdstevel@tonic-gate
19937c478bdstevel@tonic-gate		pktcnt++;
19947c478bdstevel@tonic-gate
19957c478bdstevel@tonic-gate		if (buf == NULL) {
19967c478bdstevel@tonic-gate			retval = get_packet(device_fd, &tag, sizeof (fru_tag_t),
19977c478bdstevel@tonic-gate			    offset);
19987c478bdstevel@tonic-gate			if (retval == -1) {
19997c478bdstevel@tonic-gate				return (-1);
20007c478bdstevel@tonic-gate			}
20017c478bdstevel@tonic-gate		} else if (length - offset < sizeof (fru_tag_t)) {
20027c478bdstevel@tonic-gate			if (length - offset > 0) {
20037c478bdstevel@tonic-gate				/*
20047c478bdstevel@tonic-gate				 * not enough data for a full fru_tag_t
20057c478bdstevel@tonic-gate				 * just return what there is
20067c478bdstevel@tonic-gate				 */
20077c478bdstevel@tonic-gate				(void) memset(&tag, 0, sizeof (fru_tag_t));
20087c478bdstevel@tonic-gate				(void) memcpy(&tag, buf + offset,
20097c478bdstevel@tonic-gate				    length - offset);
20107c478bdstevel@tonic-gate			}
20117c478bdstevel@tonic-gate		} else {
20127c478bdstevel@tonic-gate			(void) memcpy(&tag, buf + offset, sizeof (fru_tag_t));
20137c478bdstevel@tonic-gate		}
20147c478bdstevel@tonic-gate
20157c478bdstevel@tonic-gate		data	= (char *)&tag;
20167c478bdstevel@tonic-gate	}
20177c478bdstevel@tonic-gate
20187c478bdstevel@tonic-gate	segdesc	= (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
20197c478bdstevel@tonic-gate
20207c478bdstevel@tonic-gate	seg_hash->u.seg_obj->trailer_offset = offset;
20217c478bdstevel@tonic-gate
20227c478bdstevel@tonic-gate	if (!segdesc->field.ignore_checksum)  {
20237c478bdstevel@tonic-gate		crc = get_checksum_crc(seg_hash, seg_limit);
20247c478bdstevel@tonic-gate		offset	= seg_hash->u.seg_obj->segment.offset;
20257c478bdstevel@tonic-gate
20267c478bdstevel@tonic-gate		if (buf == NULL) {
20277c478bdstevel@tonic-gate			retval = pread(device_fd, &origcrc, sizeof (origcrc),
20287c478bdstevel@tonic-gate			    offset + seg_limit + 1);
20297c478bdstevel@tonic-gate			if (retval != sizeof (origcrc)) {
20307c478bdstevel@tonic-gate				return (-1);
20317c478bdstevel@tonic-gate			}
20327c478bdstevel@tonic-gate		} else if (length - offset < sizeof (origcrc)) {
20337c478bdstevel@tonic-gate			return (-1);
20347c478bdstevel@tonic-gate		} else {
20357c478bdstevel@tonic-gate			(void) memcpy(&origcrc, buf + seg_limit + 1,
20367c478bdstevel@tonic-gate			    sizeof (origcrc));
20377c478bdstevel@tonic-gate		}
20387c478bdstevel@tonic-gate
20397c478bdstevel@tonic-gate		if (origcrc != crc) {
20407c478bdstevel@tonic-gate			seg_hash->u.seg_obj->trailer_offset = offset;
20417c478bdstevel@tonic-gate		}
20427c478bdstevel@tonic-gate	}
20437c478bdstevel@tonic-gate
20447c478bdstevel@tonic-gate	return (pktcnt);
20457c478bdstevel@tonic-gate}
20467c478bdstevel@tonic-gate
20477c478bdstevel@tonic-gatestatic int
20487c478bdstevel@tonic-gateget_packets(hash_obj_t *seg_hash, int device_fd, int offset, int length)
20497c478bdstevel@tonic-gate{
20507c478bdstevel@tonic-gate	return (get_dev_or_buffered_packets(seg_hash, device_fd, offset,
20517c478bdstevel@tonic-gate	    length, NULL));
20527c478bdstevel@tonic-gate}
20537c478bdstevel@tonic-gate
20547c478bdstevel@tonic-gatestatic int
20557c478bdstevel@tonic-gateget_buffered_packets(hash_obj_t *seg_hash, const char *seg_buf, size_t seg_len)
20567c478bdstevel@tonic-gate{
20577c478bdstevel@tonic-gate	return (get_dev_or_buffered_packets(seg_hash, -1, 0, seg_len, seg_buf));
20587c478bdstevel@tonic-gate}
20597c478bdstevel@tonic-gate
20607c478bdstevel@tonic-gate/*
20617c478bdstevel@tonic-gate * Description	:
20627c478bdstevel@tonic-gate *		fru_get_num_packets() returns the current number of packets
20637c478bdstevel@tonic-gate *		in a segment.
20647c478bdstevel@tonic-gate *
20657c478bdstevel@tonic-gate * Arguments	: segment_hdl_t : segment handle.
20667c478bdstevel@tonic-gate *
20677c478bdstevel@tonic-gate * Return	:
20687c478bdstevel@tonic-gate *		int
20697c478bdstevel@tonic-gate *		On success, the number of packets is returned;
20707c478bdstevel@tonic-gate *		-1 on failure.
20717c478bdstevel@tonic-gate */
20727c478bdstevel@tonic-gateint
20737c478bdstevel@tonic-gatefru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
20747c478bdstevel@tonic-gate{
20757c478bdstevel@tonic-gate	int		device_fd;
20767c478bdstevel@tonic-gate	int		pktcnt;
20777c478bdstevel@tonic-gate	int		length;
20787c478bdstevel@tonic-gate	uint16_t	offset;
20797c478bdstevel@tonic-gate	hash_obj_t	*cont_hash_obj;
20807c478bdstevel@tonic-gate	hash_obj_t	*sec_hash;
20817c478bdstevel@tonic-gate	hash_obj_t	*seg_hash;
20827c478bdstevel@tonic-gate	fru_segdesc_t	*segdesc;
20837c478bdstevel@tonic-gate	segment_obj_t	*segment_object;
20847c478bdstevel@tonic-gate
20857c478bdstevel@tonic-gate	seg_hash	= lookup_handle_object(segment, SEGMENT_TYPE);
20867c478bdstevel@tonic-gate	if (seg_hash == NULL) {
20877c478bdstevel@tonic-gate		return (-1);
20887c478bdstevel@tonic-gate	}
20897c478bdstevel@tonic-gate
20907c478bdstevel@tonic-gate	segment_object	= seg_hash->u.seg_obj;
20917c478bdstevel@tonic-gate	if (segment_object == NULL) {
20927c478bdstevel@tonic-gate		return (-1);
20937c478bdstevel@tonic-gate	}
20947c478bdstevel@tonic-gate
20957c478bdstevel@tonic-gate	segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor;
20967c478bdstevel@tonic-gate	if (segdesc->field.opaque) {
20977c478bdstevel@tonic-gate		return (0);
20987c478bdstevel@tonic-gate	}
20997c478bdstevel@tonic-gate
21007c478bdstevel@tonic-gate	if (seg_hash->u.seg_obj->pkt_obj_list != NULL) {
21017c478bdstevel@tonic-gate		return (segment_object->num_of_packets);
21027c478bdstevel@tonic-gate	}
21037c478bdstevel@tonic-gate
21047c478bdstevel@tonic-gate	offset = segment_object->segment.offset;
21057c478bdstevel@tonic-gate	length = segment_object->segment.length;
21067c478bdstevel@tonic-gate
21077c478bdstevel@tonic-gate	/* section hash object */
21087c478bdstevel@tonic-gate	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
21097c478bdstevel@tonic-gate	    SECTION_TYPE);
21107c478bdstevel@tonic-gate	if (sec_hash == NULL) {
21117c478bdstevel@tonic-gate		return (-1);
21127c478bdstevel@tonic-gate	}
21137c478bdstevel@tonic-gate
21147c478bdstevel@tonic-gate	segment_object->num_of_packets = 0;
21157c478bdstevel@tonic-gate
21167c478bdstevel@tonic-gate	switch (sec_hash->u.sec_obj->encoding) {
21177c478bdstevel@tonic-gate	case ENC_STANDARD:
21187c478bdstevel@tonic-gate		cont_hash_obj = get_container_hash_object(SEGMENT_TYPE,
21197c478bdstevel@tonic-gate		    segment_object->section_hdl);
21207c478bdstevel@tonic-gate		if (cont_hash_obj == NULL) {
21217c478bdstevel@tonic-gate			return (-1);
21227c478bdstevel@tonic-gate		}
21237c478bdstevel@tonic-gate		device_fd = open(cont_hash_obj->u.cont_obj->device_pathname,
21247c478bdstevel@tonic-gate		    O_RDWR);
21257c478bdstevel@tonic-gate		if (device_fd < 0) {
21267c478bdstevel@tonic-gate			return (-1);
21277c478bdstevel@tonic-gate		}
21287c478bdstevel@tonic-gate
21297c478bdstevel@tonic-gate		pktcnt = get_packets(seg_hash, device_fd, offset, length);
21307c478bdstevel@tonic-gate		(void) close(device_fd);
21317c478bdstevel@tonic-gate		break;
21327c478bdstevel@tonic-gate
21337c478bdstevel@tonic-gate	case ENC_SPD: {
21347c478bdstevel@tonic-gate		ssize_t		spd_seg_len;
21357c478bdstevel@tonic-gate		size_t		nbytes;
21367c478bdstevel@tonic-gate		char		*seg_buf;
21377c478bdstevel@tonic-gate
21387c478bdstevel@tonic-gate		nbytes = segment_object->segment.length;
21397c478bdstevel@tonic-gate		seg_buf = alloca(nbytes);
21407c478bdstevel@tonic-gate		if (seg_buf == NULL)
21417c478bdstevel@tonic-gate			return (-1);
21427c478bdstevel@tonic-gate		spd_seg_len =
21437c478bdstevel@tonic-gate		    fru_read_segment(segment, seg_buf, nbytes, cred);
21447c478bdstevel@tonic-gate		if (spd_seg_len < 0)
2145af3025fdt			return (-1);
21467c478bdstevel@tonic-gate		pktcnt = get_buffered_packets(seg_hash, seg_buf,
21477c478bdstevel@tonic-gate		    spd_seg_len);
21487c478bdstevel@tonic-gate		break;
21497c478bdstevel@tonic-gate	}
21507c478bdstevel@tonic-gate
21517c478bdstevel@tonic-gate	default:
21527c478bdstevel@tonic-gate		return (-1);
21537c478bdstevel@tonic-gate	}
21547c478bdstevel@tonic-gate
21557c478bdstevel@tonic-gate	if (pktcnt == -1) {
21567c478bdstevel@tonic-gate		free_pkt_object_list(seg_hash);
21577c478bdstevel@tonic-gate		seg_hash->u.seg_obj->pkt_obj_list = NULL;
21587c478bdstevel@tonic-gate	}
21597c478bdstevel@tonic-gate
21607c478bdstevel@tonic-gate	segment_object->num_of_packets = pktcnt;
21617c478bdstevel@tonic-gate
21627c478bdstevel@tonic-gate	return (segment_object->num_of_packets);
21637c478bdstevel@tonic-gate}
21647c478bdstevel@tonic-gate
21657c478bdstevel@tonic-gate
21667c478bdstevel@tonic-gate/*
21677c478bdstevel@tonic-gate * Description	:
21687c478bdstevel@tonic-gate *		fru_get_packets() fills an array of structures representing the
21697c478bdstevel@tonic-gate *		packets in a segment.
21707c478bdstevel@tonic-gate *
21717c478bdstevel@tonic-gate * Arguments	: segment_hdl_t : segment handle.
21727c478bdstevel@tonic-gate *		packet_t	: packet buffer.
21737c478bdstevel@tonic-gate *		int	: maximum number of packets.
21747c478bdstevel@tonic-gate *
21757c478bdstevel@tonic-gate * Return	:
21767c478bdstevel@tonic-gate *		int
21777c478bdstevel@tonic-gate *		On success, the number of packet structures written is returned;
21787c478bdstevel@tonic-gate *		On failure -1 is returned;
21797c478bdstevel@tonic-gate *
21807c478bdstevel@tonic-gate */
21817c478bdstevel@tonic-gate
21827c478bdstevel@tonic-gate/* ARGSUSED */
21837c478bdstevel@tonic-gateint
21847c478bdstevel@tonic-gatefru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets,
21857c478bdstevel@tonic-gate    door_cred_t *cred)
21867c478bdstevel@tonic-gate{
21877c478bdstevel@tonic-gate	int		count;
21887c478bdstevel@tonic-gate	hash_obj_t	*seg_hash_obj;
21897c478bdstevel@tonic-gate	hash_obj_t	*pkt_hash_obj;
21907c478bdstevel@tonic-gate
21917c478bdstevel@tonic-gate	/* segment hash object */
21927c478bdstevel@tonic-gate	seg_hash_obj	= lookup_handle_object(segment, SEGMENT_TYPE);
21937c478bdstevel@tonic-gate	if (seg_hash_obj == NULL) {
21947c478bdstevel@tonic-gate		return (-1);
21957c478bdstevel@tonic-gate	}
21967c478bdstevel@tonic-gate
21977c478bdstevel@tonic-gate	if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) {
21987c478bdstevel@tonic-gate		return (-1);
21997c478bdstevel@tonic-gate	}
22007c478bdstevel@tonic-gate
22017c478bdstevel@tonic-gate	pkt_hash_obj	= seg_hash_obj->u.seg_obj->pkt_obj_list;
22027c478bdstevel@tonic-gate	if (pkt_hash_obj == NULL) {
22037c478bdstevel@tonic-gate		return (-1);
22047c478bdstevel@tonic-gate	}
22057c478bdstevel@tonic-gate
22067c478bdstevel@tonic-gate	for (count = 0; count < maxpackets; count++, packet++) {
22077c478bdstevel@tonic-gate		packet->handle	= pkt_hash_obj->obj_hdl;
22087c478bdstevel@tonic-gate		packet->tag = 0;
22097c478bdstevel@tonic-gate		(void) memcpy(&packet->tag, &pkt_hash_obj->u.pkt_obj->tag,
22107c478bdstevel@tonic-gate		    pkt_hash_obj->u.pkt_obj->tag_size);
22117c478bdstevel@tonic-gate		pkt_hash_obj = pkt_hash_obj->u.pkt_obj->next;
22127c478bdstevel@tonic-gate	}
22137c478bdstevel@tonic-gate
22147c478bdstevel@tonic-gate	return (0);
22157c478bdstevel@tonic-gate}
22167c478bdstevel@tonic-gate
22177c478bdstevel@tonic-gate/*
22187c478bdstevel@tonic-gate * Description	:
22197c478bdstevel@tonic-gate *		fru_get_payload() copies the contents of a packet's payload.
22207c478bdstevel@tonic-gate *
22217c478bdstevel@tonic-gate * Arguments	: packet_hdl_t : packet handle.
22227c478bdstevel@tonic-gate *		void *	: payload buffer.
22237c478bdstevel@tonic-gate *		size_t	: sizeof the buffer.
22247c478bdstevel@tonic-gate *
22257c478bdstevel@tonic-gate * Return	:
22267c478bdstevel@tonic-gate *    		int
22277c478bdstevel@tonic-gate *     		On success, the number of bytes copied is returned; On error
22287c478bdstevel@tonic-gate *		-1 returned.
22297c478bdstevel@tonic-gate */
22307c478bdstevel@tonic-gate
22317c478bdstevel@tonic-gate/* ARGSUSED */
22327c478bdstevel@tonic-gatessize_t
22337c478bdstevel@tonic-gatefru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes,
22347c478bdstevel@tonic-gate    door_cred_t *cred)
22357c478bdstevel@tonic-gate{
22367c478bdstevel@tonic-gate	hash_obj_t	*packet_hash_obj;
22377c478bdstevel@tonic-gate
22387c478bdstevel@tonic-gate	/* packet hash object */
22397c478bdstevel@tonic-gate	packet_hash_obj	= lookup_handle_object(packet, PACKET_TYPE);
22407c478bdstevel@tonic-gate	if (packet_hash_obj == NULL) {
22417c478bdstevel@tonic-gate		return (-1);
22427c478bdstevel@tonic-gate	}
22437c478bdstevel@tonic-gate
22447c478bdstevel@tonic-gate	/* verify payload length */
22457c478bdstevel@tonic-gate	if (nbytes != packet_hash_obj->u.pkt_obj->paylen) {
22467c478bdstevel@tonic-gate		return (-1);
22477c478bdstevel@tonic-gate	}
22487c478bdstevel@tonic-gate
22497c478bdstevel@tonic-gate	(void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes);
22507c478bdstevel@tonic-gate	return (nbytes);
22517c478bdstevel@tonic-gate}
22527c478bdstevel@tonic-gate
22537c478bdstevel@tonic-gate/*
22547c478bdstevel@tonic-gate * Description	:
22557c478bdstevel@tonic-gate * 		fru_update_payload() writes the contents of a packet's payload.
22567c478bdstevel@tonic-gate *
22577c478bdstevel@tonic-gate * Arguments	: packet_hdl_t : packet handle.
22587c478bdstevel@tonic-gate *		const void * : data buffer.
22597c478bdstevel@tonic-gate *		size_t	: buffer size.
22607c478bdstevel@tonic-gate *		packet_hdl_t	: new packet handle.
22617c478bdstevel@tonic-gate *
22627c478bdstevel@tonic-gate * Return	:
22637c478bdstevel@tonic-gate * 		int
22647c478bdstevel@tonic-gate *		On success, 0 is returned; on failure
22657c478bdstevel@tonic-gate *		-1 is returned.
22667c478bdstevel@tonic-gate */
22677c478bdstevel@tonic-gate
22687c478bdstevel@tonic-gateint
22697c478bdstevel@tonic-gatefru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes,
22707c478bdstevel@tonic-gate    packet_hdl_t *newpacket, door_cred_t *cred)
22717c478bdstevel@tonic-gate{
22727c478bdstevel@tonic-gate	int		fd;
22737c478bdstevel@tonic-gate	int		segment_offset;
22747c478bdstevel@tonic-gate	int		trailer_offset;
22757c478bdstevel@tonic-gate	int		retval;
22767c478bdstevel@tonic-gate	uint32_t	crc;
22777c478bdstevel@tonic-gate	hash_obj_t	*pkt_hash;
22787c478bdstevel@tonic-gate	hash_obj_t	*seg_hash;
22797c478bdstevel@tonic-gate	hash_obj_t	*sec_hash;
22807c478bdstevel@tonic-gate	hash_obj_t	*cont_hash;
22817c478bdstevel@tonic-gate	fru_segdesc_t	*desc;
22827c478bdstevel@tonic-gate
22837c478bdstevel@tonic-gate	/* check the effective uid of the client */
22847c478bdstevel@tonic-gate	if (cred->dc_euid != 0) {
22857c478bdstevel@tonic-gate		errno = EPERM;
22867c478bdstevel@tonic-gate		return (-1);	/* not a root */
22877c478bdstevel@tonic-gate	}
22887c478bdstevel@tonic-gate
22897c478bdstevel@tonic-gate	/* packet hash object */
22907c478bdstevel@tonic-gate	pkt_hash = lookup_handle_object(packet,	PACKET_TYPE);
22917c478bdstevel@tonic-gate	if (pkt_hash == NULL) {
22927c478bdstevel@tonic-gate		return (-1);
22937c478bdstevel@tonic-gate	}
22947c478bdstevel@tonic-gate
22957c478bdstevel@tonic-gate	/* segment hash object */
22967c478bdstevel@tonic-gate	seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl,
22977c478bdstevel@tonic-gate	    SEGMENT_TYPE);
22987c478bdstevel@tonic-gate	if (seg_hash == NULL) {
22997c478bdstevel@tonic-gate		return (-1);
23007c478bdstevel@tonic-gate	}
23017c478bdstevel@tonic-gate
23027c478bdstevel@tonic-gate	/* check for write perm. */
23037c478bdstevel@tonic-gate	desc    = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
23047c478bdstevel@tonic-gate	if (!(desc->field.field_perm & SEGMENT_WRITE)) {
23057c478bdstevel@tonic-gate		errno = EPERM;
23067c478bdstevel@tonic-gate		return (-1); /* write not allowed */
23077c478bdstevel@tonic-gate	}
23087c478bdstevel@tonic-gate
23097c478bdstevel@tonic-gate	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
23107c478bdstevel@tonic-gate	    SECTION_TYPE);
23117c478bdstevel@tonic-gate	if (sec_hash == NULL) {
23127c478bdstevel@tonic-gate		return (-1);
23137c478bdstevel@tonic-gate	}
23147c478bdstevel@tonic-gate
23157c478bdstevel@tonic-gate	if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
23167c478bdstevel@tonic-gate		errno = EPERM;
23177c478bdstevel@tonic-gate		return (-1);		/* read-only section */
23187c478bdstevel@tonic-gate	}
23197c478bdstevel@tonic-gate
23207c478bdstevel@tonic-gate	cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
23217c478bdstevel@tonic-gate	    CONTAINER_TYPE);
23227c478bdstevel@tonic-gate	if (cont_hash == NULL) {
23237c478bdstevel@tonic-gate		return (-1);
23247c478bdstevel@tonic-gate	}
23257c478bdstevel@tonic-gate
23267c478bdstevel@tonic-gate	if (pkt_hash->u.pkt_obj->paylen != nbytes) {
23277c478bdstevel@tonic-gate		return (-1);
23287c478bdstevel@tonic-gate	}
23297c478bdstevel@tonic-gate
23307c478bdstevel@tonic-gate	(void) memcpy(pkt_hash->u.pkt_obj->payload, (char *)data, nbytes);
23317c478bdstevel@tonic-gate	fd	= open(cont_hash->u.cont_obj->device_pathname, O_RDWR);
23327c478bdstevel@tonic-gate	if (fd < 0) {
23337c478bdstevel@tonic-gate		return (-1);
23347c478bdstevel@tonic-gate	}
23357c478bdstevel@tonic-gate
23367c478bdstevel@tonic-gate	trailer_offset	= seg_hash->u.seg_obj->trailer_offset;
23377c478bdstevel@tonic-gate	segment_offset	= seg_hash->u.seg_obj->segment.offset;
23387c478bdstevel@tonic-gate
23397c478bdstevel@tonic-gate	crc = get_checksum_crc(seg_hash, (trailer_offset - segment_offset));
23407c478bdstevel@tonic-gate	retval = pwrite(fd, data, nbytes, pkt_hash->u.pkt_obj->payload_offset);
23417c478bdstevel@tonic-gate	if (retval != nbytes) {
23427c478bdstevel@tonic-gate		(void) close(fd);
23437c478bdstevel@tonic-gate		return (-1);
23447c478bdstevel@tonic-gate	}
23457c478bdstevel@tonic-gate
23467c478bdstevel@tonic-gate	retval = pwrite(fd, &crc, sizeof (crc), trailer_offset + 1);
23477c478bdstevel@tonic-gate	(void) close(fd);
23487c478bdstevel@tonic-gate	if (retval != sizeof (crc)) {
23497c478bdstevel@tonic-gate		return (-1);
23507c478bdstevel@tonic-gate	}
23517c478bdstevel@tonic-gate	*newpacket	= packet;
23527c478bdstevel@tonic-gate	return (0);
23537c478bdstevel@tonic-gate}
23547c478bdstevel@tonic-gate
23557c478bdstevel@tonic-gate/*
23567c478bdstevel@tonic-gate * Description	:
23577c478bdstevel@tonic-gate *		fru_append_packet() appends a packet to a segment.
23587c478bdstevel@tonic-gate *
23597c478bdstevel@tonic-gate * Arguments	:
23607c478bdstevel@tonic-gate *		segment_hdl_t segment
23617c478bdstevel@tonic-gate *		A handle for the segment to which the packet will be appended.
23627c478bdstevel@tonic-gate *
23637c478bdstevel@tonic-gate *   		packet_t *packet
23647c478bdstevel@tonic-gate *     		On entry, the "tag" component of "packet" specifies the tag
23657c478bdstevel@tonic-gate *     		value for the added packet; the "handle" component is ignored.
23667c478bdstevel@tonic-gate *     		On return, the "handle" component is set to the handle of the
23677c478bdstevel@tonic-gate *     		appended packet.
23687c478bdstevel@tonic-gate *
23697c478bdstevel@tonic-gate *   		const void *payload
23707c478bdstevel@tonic-gate *     		A pointer to the caller's buffer containing the payload data for
23717c478bdstevel@tonic-gate *     		the appended packet.
23727c478bdstevel@tonic-gate *
23737c478bdstevel@tonic-gate *   		size_t nbytes
23747c478bdstevel@tonic-gate *     		The size of the caller buffer.
23757c478bdstevel@tonic-gate *
23767c478bdstevel@tonic-gate * Return	:
23777c478bdstevel@tonic-gate *   		int
23787c478bdstevel@tonic-gate *     		On success, 0 is returned; on error -1 is returned;
23797c478bdstevel@tonic-gate */
23807c478bdstevel@tonic-gate
23817c478bdstevel@tonic-gateint
23827c478bdstevel@tonic-gatefru_append_packet(segment_hdl_t segment, packet_t *packet, const void *payload,
23837c478bdstevel@tonic-gate    size_t nbytes, segment_hdl_t *newsegment, door_cred_t *cred)
23847c478bdstevel@tonic-gate{
23857c478bdstevel@tonic-gate	int		trailer_offset;
23867c478bdstevel@tonic-gate	int		tag_size;
23877c478bdstevel@tonic-gate	int		fd;
23887c478bdstevel@tonic-gate	int		retval;
23897c478bdstevel@tonic-gate	char		trailer[] = {0x0c, 0x00, 0x00, 0x00, 0x00};
23907c478bdstevel@tonic-gate	uint32_t	crc;
23917c478bdstevel@tonic-gate	hash_obj_t	*seg_hash;
23927c478bdstevel@tonic-gate	hash_obj_t	*sec_hash;
23937c478bdstevel@tonic-gate	hash_obj_t	*pkt_hash;
23947c478bdstevel@tonic-gate	hash_obj_t	*cont_hash;
23957c478bdstevel@tonic-gate	fru_tagtype_t	tagtype;
23967c478bdstevel@tonic-gate	fru_segdesc_t	*desc;
23977c478bdstevel@tonic-gate
23987c478bdstevel@tonic-gate	/* check the effective uid of the client */
23997c478bdstevel@tonic-gate	if (cred->dc_euid != 0) {
24007c478bdstevel@tonic-gate		errno = EPERM;
24017c478bdstevel@tonic-gate		return (-1);	/* not a root */
24027c478bdstevel@tonic-gate	}
24037c478bdstevel@tonic-gate
24047c478bdstevel@tonic-gate	seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
24057c478bdstevel@tonic-gate	if (seg_hash == NULL) {
24067c478bdstevel@tonic-gate		return (-1);
24077c478bdstevel@tonic-gate	}
24087c478bdstevel@tonic-gate
24097c478bdstevel@tonic-gate	/* check for write perm. */
24107c478bdstevel@tonic-gate	desc    = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
24117c478bdstevel@tonic-gate	if (!(desc->field.field_perm & SEGMENT_WRITE)) {
24127c478bdstevel@tonic-gate		errno = EPERM;
24137c478bdstevel@tonic-gate		return (-1); /* write not allowed */
24147c478bdstevel@tonic-gate	}
24157c478bdstevel@tonic-gate
24167c478bdstevel@tonic-gate	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
24177c478bdstevel@tonic-gate	    SECTION_TYPE);
24187c478bdstevel@tonic-gate	if (sec_hash == NULL) {
24197c478bdstevel@tonic-gate		return (-1);
24207c478bdstevel@tonic-gate	}
24217c478bdstevel@tonic-gate
24227c478bdstevel@tonic-gate	if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) {
24237c478bdstevel@tonic-gate		errno = EPERM;
24247c478bdstevel@tonic-gate		return (-1);		/* read-only section */
24257c478bdstevel@tonic-gate	}
24267c478bdstevel@tonic-gate
24277c478bdstevel@tonic-gate	trailer_offset	= seg_hash->u.seg_obj->trailer_offset;
24287c478bdstevel@tonic-gate
24297c478bdstevel@tonic-gate	/*
24307c478bdstevel@tonic-gate	 * if trailer offset is 0 than parse the segment data to get the trailer
24317c478bdstevel@tonic-gate	 * offset to compute the remaining space left in the segment area for
24327c478bdstevel@tonic-gate	 * new packet to be added.
24337c478bdstevel@tonic-gate	 */
24347c478bdstevel@tonic-gate	if (trailer_offset == 0) {
24357c478bdstevel@tonic-gate		(void) fru_get_num_packets(segment, cred);
24367c478bdstevel@tonic-gate		trailer_offset  = seg_hash->u.seg_obj->trailer_offset;
24377c478bdstevel@tonic-gate	}
24387c478bdstevel@tonic-gate
24397c478bdstevel@tonic-gate	tagtype	= get_tag_type((void *)&packet->tag);
24407c478bdstevel@tonic-gate	if (tagtype == -1) {
24417c478bdstevel@tonic-gate		return (-1);
24427c478bdstevel@tonic-gate	}
24437c478bdstevel@tonic-gate
24447c478bdstevel@tonic-gate	tag_size	= get_tag_size(tagtype);
24457c478bdstevel@tonic-gate	if (tag_size == -1) {
24467c478bdstevel@tonic-gate		return (-1);
24477c478bdstevel@tonic-gate	}
24487c478bdstevel@tonic-gate
24497c478bdstevel@tonic-gate	if (seg_hash->u.seg_obj->segment.length >
24507c478bdstevel@tonic-gate	    ((trailer_offset - seg_hash->u.seg_obj->segment.offset) +
24517c478bdstevel@tonic-gate	    tag_size + nbytes + sizeof (char) + sizeof (uint32_t))) {
24527c478bdstevel@tonic-gate		/* create new packet hash */
24537c478bdstevel@tonic-gate		pkt_hash = create_packet_hash_object();
24547c478bdstevel@tonic-gate		if (pkt_hash == NULL) {
24557c478bdstevel@tonic-gate			return (-1);
24567c478bdstevel@tonic-gate		}
24577c478bdstevel@tonic-gate
24587c478bdstevel@tonic-gate		/* tag initialization */
24597c478bdstevel@tonic-gate		(void) memcpy(&pkt_hash->u.pkt_obj->tag, &packet->tag,
24607c478bdstevel@tonic-gate		    tag_size);
24617c478bdstevel@tonic-gate		pkt_hash->u.pkt_obj->tag_size	= tag_size;
24627c478bdstevel@tonic-gate
24637c478bdstevel@tonic-gate		/* payload inititalization */
24647c478bdstevel@tonic-gate		pkt_hash->u.pkt_obj->payload	= malloc(nbytes);
24657c478bdstevel@tonic-gate		if (pkt_hash->u.pkt_obj->payload == NULL) {
24667c478bdstevel@tonic-gate			free(pkt_hash);
24677c478bdstevel@tonic-gate			return (-1);
24687c478bdstevel@tonic-gate		}
24697c478bdstevel@tonic-gate
24707c478bdstevel@tonic-gate		(void) memcpy(pkt_hash->u.pkt_obj->payload, payload, nbytes);
24717c478bdstevel@tonic-gate		pkt_hash->u.pkt_obj->paylen	= nbytes;
24727c478bdstevel@tonic-gate		pkt_hash->u.pkt_obj->payload_offset = trailer_offset + tag_size;
24737c478bdstevel@tonic-gate
24747c478bdstevel@tonic-gate		/* add to hash table */
24757c478bdstevel@tonic-gate		add_hashobject_to_hashtable(pkt_hash);
24767c478bdstevel@tonic-gate
24777c478bdstevel@tonic-gate		add_to_pkt_object_list(seg_hash, pkt_hash);
24787c478bdstevel@tonic-gate
24797c478bdstevel@tonic-gate		cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl,
24807c478bdstevel@tonic-gate		    CONTAINER_TYPE);
24817c478bdstevel@tonic-gate		if (cont_hash == NULL) {
24827c478bdstevel@tonic-gate			return (-1);
24837c478bdstevel@tonic-gate		}
24847c478bdstevel@tonic-gate
24857c478bdstevel@tonic-gate		fd = open(cont_hash->u.cont_obj->device_pathname, O_RDWR);
24867c478bdstevel@tonic-gate		if (fd < 0) {
24877c478bdstevel@tonic-gate			return (-1);
24887c478bdstevel@tonic-gate		}
24897c478bdstevel@tonic-gate
24907c478bdstevel@tonic-gate		/* update the trailer offset  */
24917c478bdstevel@tonic-gate		trailer_offset += tag_size + nbytes;
24927c478bdstevel@tonic-gate
24937c478bdstevel@tonic-gate		/* calculate new checksum */
24947c478bdstevel@tonic-gate		crc = get_checksum_crc(seg_hash, (trailer_offset -
24957c478bdstevel@tonic-gate		    seg_hash->u.seg_obj->segment.offset));
24967c478bdstevel@tonic-gate
24977c478bdstevel@tonic-gate		retval = pwrite(fd, &packet->tag, tag_size,
24987c478bdstevel@tonic-gate		    trailer_offset - (tag_size + nbytes));
24997c478bdstevel@tonic-gate		if (retval != tag_size) {
25007c478bdstevel@tonic-gate			(void) close(fd);
25017c478bdstevel@tonic-gate			return (-1);
25027c478bdstevel@tonic-gate		}
25037c478bdstevel@tonic-gate
25047c478bdstevel@tonic-gate		retval = pwrite(fd, payload, nbytes, trailer_offset - nbytes);
25057c478bdstevel@tonic-gate		if (retval != nbytes) {
25067c478bdstevel@tonic-gate			(void) close(fd);
25077c478bdstevel@tonic-gate			return (-1);
25087c478bdstevel@tonic-gate		}
25097c478bdstevel@tonic-gate
25107c478bdstevel@tonic-gate		retval = pwrite(fd, trailer, sizeof (trailer), trailer_offset);
25117c478bdstevel@tonic-gate		if (retval != sizeof (trailer)) {
25127c478bdstevel@tonic-gate			(void) close(fd);
25137c478bdstevel@tonic-gate			return (-1);
25147c478bdstevel@tonic-gate		}
25157c478bdstevel@tonic-gate
25167c478bdstevel@tonic-gate		retval = pwrite(fd, &crc, sizeof (crc), trailer_offset + 1);
25177c478bdstevel@tonic-gate		(void) close(fd);
25187c478bdstevel@tonic-gate		if (retval != sizeof (crc)) {
25197c478bdstevel@tonic-gate			return (-1);
25207c478bdstevel@tonic-gate		}
25217c478bdstevel@tonic-gate
25227c478bdstevel@tonic-gate		seg_hash->u.seg_obj->trailer_offset = trailer_offset;
25237c478bdstevel@tonic-gate		seg_hash->u.seg_obj->num_of_packets += 1;
25247c478bdstevel@tonic-gate
25257c478bdstevel@tonic-gate		*newsegment	= segment; 	/* return new segment handle */
25267c478bdstevel@tonic-gate		return (0);
25277c478bdstevel@tonic-gate	} else {
25287c478bdstevel@tonic-gate		errno = EAGAIN;
25297c478bdstevel@tonic-gate	}
25307c478bdstevel@tonic-gate
25317c478bdstevel@tonic-gate	return (-1);
25327c478bdstevel@tonic-gate}
25337c478bdstevel@tonic-gate
25347c478bdstevel@tonic-gatestatic void
25357c478bdstevel@tonic-gateadjust_packets(int	fd, hash_obj_t	*free_obj, hash_obj_t	*object_list)
25367c478bdstevel@tonic-gate{
25377c478bdstevel@tonic-gate	int		retval;
25387c478bdstevel@tonic-gate	uint32_t	new_offset;
25397c478bdstevel@tonic-gate	hash_obj_t	*hash_ptr;
25407c478bdstevel@tonic-gate
25417c478bdstevel@tonic-gate	new_offset = free_obj->u.pkt_obj->payload_offset -
25427c478bdstevel@tonic-gate	    free_obj->u.pkt_obj->tag_size;
25437c478bdstevel@tonic-gate	for (hash_ptr = object_list;
25447c478bdstevel@tonic-gate	    hash_ptr != NULL; hash_ptr = hash_ptr->u.pkt_obj->next) {
25457c478bdstevel@tonic-gate		retval = pwrite(fd, &hash_ptr->u.pkt_obj->tag,
25467c478bdstevel@tonic-gate		    hash_ptr->u.pkt_obj->tag_size, new_offset);
25477c478bdstevel@tonic-gate		if (retval != hash_ptr->u.pkt_obj->tag_size) {
25487c478bdstevel@tonic-gate			return;
25497c478bdstevel@tonic-gate		}
25507c478bdstevel@tonic-gate		new_offset += hash_ptr->u.pkt_obj->tag_size;
25517c478bdstevel@tonic-gate		hash_ptr->u.pkt_obj->payload_offset = new_offset;
25527c478bdstevel@tonic-gate		retval = pwrite(fd, hash_ptr->u.pkt_obj->payload,
25537c478bdstevel@tonic-gate		    hash_ptr->u.pkt_obj->paylen, new_offset);
25547c478bdstevel@tonic-gate		if (retval != hash_ptr->u.pkt_obj->paylen) {
25557c478bdstevel@tonic-gate			return;
25567c478bdstevel@tonic-gate		}
25577c478bdstevel@tonic-gate		new_offset += hash_ptr->u.pkt_obj->paylen;
25587c478bdstevel@tonic-gate	}
25597c478bdstevel@tonic-gate}
25607c478bdstevel@tonic-gate
25617c478bdstevel@tonic-gatestatic void
25627c478bdstevel@tonic-gatefree_packet_object(handle_t	handle, hash_obj_t *seg_hash)
25637c478bdstevel@tonic-gate{
25647c478bdstevel@tonic-gate	hash_obj_t	*pkt_hash;
25657c478bdstevel@tonic-gate	hash_obj_t	*next_hash;
25667c478bdstevel@tonic-gate
25677c478bdstevel@tonic-gate	pkt_hash	= seg_hash->u.seg_obj->pkt_obj_list;
25687c478bdstevel@tonic-gate	if (pkt_hash == NULL) {
25697c478bdstevel@tonic-gate		return;
25707c478bdstevel@tonic-gate	}
25717c478bdstevel@tonic-gate
25727c478bdstevel@tonic-gate	if (pkt_hash->obj_hdl == handle) {
25737c478bdstevel@tonic-gate		seg_hash->u.seg_obj->pkt_obj_list = pkt_hash->u.pkt_obj->next;
25747c478bdstevel@tonic-gate	} else {
25757c478bdstevel@tonic-gate		while (pkt_hash->obj_hdl != handle) {
25767c478bdstevel@tonic-gate			next_hash = pkt_hash;
25777c478bdstevel@tonic-gate			pkt_hash = pkt_hash->u.pkt_obj->next;
25787c478bdstevel@tonic-gate			if (pkt_hash == NULL) {
25797c478bdstevel@tonic-gate				return;
25807c478bdstevel@tonic-gate			}
25817c478bdstevel@tonic-gate		}
25827c478bdstevel@tonic-gate		next_hash->u.pkt_obj->next = pkt_hash->u.pkt_obj->next;
25837c478bdstevel@tonic-gate	}
25847c478bdstevel@tonic-gate
25857c478bdstevel@tonic-gate	if (pkt_hash->prev == NULL) {
25867c478bdstevel@tonic-gate		hash_table[(pkt_hash->obj_hdl % TABLE_SIZE)] = pkt_hash->next;
25877c478bdstevel@tonic-gate		if (pkt_hash->next != NULL) {
25887c478bdstevel@tonic-gate			pkt_hash->next->prev = NULL;
25897c478bdstevel@tonic-gate		}
25907c478bdstevel@tonic-gate	} else {
25917c478bdstevel@tonic-gate		pkt_hash->prev->next = pkt_hash->next;
25927c478bdstevel@tonic-gate		if (pkt_hash->next != NULL) {
25937c478bdstevel@tonic-gate			pkt_hash->next->prev = pkt_hash->prev;
25947c478bdstevel@tonic-gate		}
25957c478bdstevel@tonic-gate	}
25967c478bdstevel@tonic-gate
25977c478bdstevel@tonic-gate	free(pkt_hash->u.pkt_obj->payload);
25987c478bdstevel@tonic-gate	free(pkt_hash->u.pkt_obj);
25997c478bdstevel@tonic-gate	free(pkt_hash);
26007c478bdstevel@tonic-gate}
26017c478bdstevel@tonic-gate
26027c478bdstevel@tonic-gate/*
26037c478bdstevel@tonic-gate * Description	:
26047c478bdstevel@tonic-gate *   		fru_delete_packet() deletes a packet from a segment.
26057c478bdstevel@tonic-gate *
26067c478bdstevel@tonic-gate * Arguments	: packet_hdl_t : packet number to be deleted.
26077c478bdstevel@tonic-gate *		segment_hdl_t : new segment handler.
26087c478bd