xref: /onnv-gate/usr/src/lib/libfru/libfruraw/raw_access.c (revision 12126:60364f3f65c7)
111015SSundeep.Panicker@Sun.COM /*
211015SSundeep.Panicker@Sun.COM  * CDDL HEADER START
311015SSundeep.Panicker@Sun.COM  *
411015SSundeep.Panicker@Sun.COM  * The contents of this file are subject to the terms of the
511015SSundeep.Panicker@Sun.COM  * Common Development and Distribution License (the "License").
611015SSundeep.Panicker@Sun.COM  * You may not use this file except in compliance with the License.
711015SSundeep.Panicker@Sun.COM  *
811015SSundeep.Panicker@Sun.COM  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911015SSundeep.Panicker@Sun.COM  * or http://www.opensolaris.org/os/licensing.
1011015SSundeep.Panicker@Sun.COM  * See the License for the specific language governing permissions
1111015SSundeep.Panicker@Sun.COM  * and limitations under the License.
1211015SSundeep.Panicker@Sun.COM  *
1311015SSundeep.Panicker@Sun.COM  * When distributing Covered Code, include this CDDL HEADER in each
1411015SSundeep.Panicker@Sun.COM  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
1511015SSundeep.Panicker@Sun.COM  * If applicable, add the following below this CDDL HEADER, with the
1611015SSundeep.Panicker@Sun.COM  * fields enclosed by brackets "[]" replaced with your own identifying
1711015SSundeep.Panicker@Sun.COM  * information: Portions Copyright [yyyy] [name of copyright owner]
1811015SSundeep.Panicker@Sun.COM  *
1911015SSundeep.Panicker@Sun.COM  * CDDL HEADER END
2011015SSundeep.Panicker@Sun.COM  */
2111015SSundeep.Panicker@Sun.COM 
2211015SSundeep.Panicker@Sun.COM /*
23*12126SHyon.Kim@Sun.COM  * Copyright (c) 2009, 2010, Oracle and/or its affiliates. All rights reserved.
2411015SSundeep.Panicker@Sun.COM  */
2511015SSundeep.Panicker@Sun.COM 
2611015SSundeep.Panicker@Sun.COM #include <stdio.h>
2711015SSundeep.Panicker@Sun.COM #include <stdlib.h>
2811015SSundeep.Panicker@Sun.COM #include <alloca.h>
2911015SSundeep.Panicker@Sun.COM #include <sys/byteorder.h>
3011015SSundeep.Panicker@Sun.COM #include "fru_access_impl.h"
3111015SSundeep.Panicker@Sun.COM #include "fruraw.h"
3211015SSundeep.Panicker@Sun.COM 
3311015SSundeep.Panicker@Sun.COM #pragma init(initialize_raw_access)
3411015SSundeep.Panicker@Sun.COM 
3511015SSundeep.Panicker@Sun.COM static hash_obj_t	*hash_table[TABLE_SIZE];
3611015SSundeep.Panicker@Sun.COM extern raw_list_t 	*g_raw;
3711015SSundeep.Panicker@Sun.COM 
3811015SSundeep.Panicker@Sun.COM static void
initialize_raw_access(void)3911015SSundeep.Panicker@Sun.COM initialize_raw_access(void)
4011015SSundeep.Panicker@Sun.COM {
4111015SSundeep.Panicker@Sun.COM 	int	count;
4211015SSundeep.Panicker@Sun.COM 
4311015SSundeep.Panicker@Sun.COM 	for (count = 0; count < TABLE_SIZE; count++) {
4411015SSundeep.Panicker@Sun.COM 		hash_table[count] = NULL;
4511015SSundeep.Panicker@Sun.COM 	}
4611015SSundeep.Panicker@Sun.COM }
4711015SSundeep.Panicker@Sun.COM 
4811015SSundeep.Panicker@Sun.COM 
4911015SSundeep.Panicker@Sun.COM static hash_obj_t *
lookup_handle_object(handle_t handle,int object_type)5011015SSundeep.Panicker@Sun.COM lookup_handle_object(handle_t	handle, int object_type)
5111015SSundeep.Panicker@Sun.COM {
5211015SSundeep.Panicker@Sun.COM 	handle_t index_to_hash;
5311015SSundeep.Panicker@Sun.COM 	hash_obj_t *first_hash_obj;
5411015SSundeep.Panicker@Sun.COM 	hash_obj_t *next_hash_obj;
5511015SSundeep.Panicker@Sun.COM 
5611015SSundeep.Panicker@Sun.COM 	index_to_hash = (handle % TABLE_SIZE);
5711015SSundeep.Panicker@Sun.COM 
5811015SSundeep.Panicker@Sun.COM 	first_hash_obj = hash_table[index_to_hash];
5911015SSundeep.Panicker@Sun.COM 	for (next_hash_obj = first_hash_obj; next_hash_obj != NULL;
6011015SSundeep.Panicker@Sun.COM 	    next_hash_obj = next_hash_obj->next) {
6111015SSundeep.Panicker@Sun.COM 		if ((handle == next_hash_obj->obj_hdl) &&
6211015SSundeep.Panicker@Sun.COM 		    (object_type == next_hash_obj->object_type)) {
6311015SSundeep.Panicker@Sun.COM 			return (next_hash_obj);
6411015SSundeep.Panicker@Sun.COM 		}
6511015SSundeep.Panicker@Sun.COM 	}
6611015SSundeep.Panicker@Sun.COM 	return (NULL);
6711015SSundeep.Panicker@Sun.COM }
6811015SSundeep.Panicker@Sun.COM 
6911015SSundeep.Panicker@Sun.COM 
7011015SSundeep.Panicker@Sun.COM static void
add_hashobject_to_hashtable(hash_obj_t * hash_obj)7111015SSundeep.Panicker@Sun.COM add_hashobject_to_hashtable(hash_obj_t *hash_obj)
7211015SSundeep.Panicker@Sun.COM {
7311015SSundeep.Panicker@Sun.COM 	handle_t index_to_hash;
7411015SSundeep.Panicker@Sun.COM 	static	uint64_t handle_count = 0;
7511015SSundeep.Panicker@Sun.COM 
7611015SSundeep.Panicker@Sun.COM 	hash_obj->obj_hdl = ++handle_count;	/* store the handle */
7711015SSundeep.Panicker@Sun.COM 
7811015SSundeep.Panicker@Sun.COM 	/* where to add ? */
7911015SSundeep.Panicker@Sun.COM 	index_to_hash = ((hash_obj->obj_hdl) % TABLE_SIZE);
8011015SSundeep.Panicker@Sun.COM 
8111015SSundeep.Panicker@Sun.COM 	hash_obj->next = hash_table[index_to_hash];
8211015SSundeep.Panicker@Sun.COM 	hash_table[index_to_hash] = hash_obj;	/* hash obj. added */
8311015SSundeep.Panicker@Sun.COM 
8411015SSundeep.Panicker@Sun.COM 	if (hash_obj->next != NULL) {
8511015SSundeep.Panicker@Sun.COM 		hash_obj->next->prev = hash_obj;
8611015SSundeep.Panicker@Sun.COM 	}
8711015SSundeep.Panicker@Sun.COM }
8811015SSundeep.Panicker@Sun.COM 
8911015SSundeep.Panicker@Sun.COM 
9011015SSundeep.Panicker@Sun.COM static hash_obj_t *
create_container_hash_object(void)9111015SSundeep.Panicker@Sun.COM create_container_hash_object(void)
9211015SSundeep.Panicker@Sun.COM {
9311015SSundeep.Panicker@Sun.COM 	hash_obj_t *hash_obj;
9411015SSundeep.Panicker@Sun.COM 	container_obj_t *cont_obj;
9511015SSundeep.Panicker@Sun.COM 
9611015SSundeep.Panicker@Sun.COM 	cont_obj = malloc(sizeof (container_obj_t));
9711015SSundeep.Panicker@Sun.COM 	if (cont_obj == NULL) {
9811015SSundeep.Panicker@Sun.COM 		return (NULL);
9911015SSundeep.Panicker@Sun.COM 	}
10011015SSundeep.Panicker@Sun.COM 
10111015SSundeep.Panicker@Sun.COM 	hash_obj = malloc(sizeof (hash_obj_t));
10211015SSundeep.Panicker@Sun.COM 	if (hash_obj == NULL) {
10311015SSundeep.Panicker@Sun.COM 		free(cont_obj);
10411015SSundeep.Panicker@Sun.COM 		return (NULL);
10511015SSundeep.Panicker@Sun.COM 	}
10611015SSundeep.Panicker@Sun.COM 
10711015SSundeep.Panicker@Sun.COM 	cont_obj->sec_obj_list = NULL;
10811015SSundeep.Panicker@Sun.COM 
10911015SSundeep.Panicker@Sun.COM 	hash_obj->object_type = CONTAINER_TYPE;
11011015SSundeep.Panicker@Sun.COM 	hash_obj->u.cont_obj = cont_obj;
11111015SSundeep.Panicker@Sun.COM 	hash_obj->next = NULL;
11211015SSundeep.Panicker@Sun.COM 	hash_obj->prev = NULL;
11311015SSundeep.Panicker@Sun.COM 
11411015SSundeep.Panicker@Sun.COM 	return (hash_obj);
11511015SSundeep.Panicker@Sun.COM }
11611015SSundeep.Panicker@Sun.COM 
11711015SSundeep.Panicker@Sun.COM 
11811015SSundeep.Panicker@Sun.COM static hash_obj_t *
create_section_hash_object(void)11911015SSundeep.Panicker@Sun.COM create_section_hash_object(void)
12011015SSundeep.Panicker@Sun.COM {
12111015SSundeep.Panicker@Sun.COM 	hash_obj_t *hash_obj;
12211015SSundeep.Panicker@Sun.COM 	section_obj_t *sec_obj;
12311015SSundeep.Panicker@Sun.COM 
12411015SSundeep.Panicker@Sun.COM 	sec_obj	= malloc(sizeof (section_obj_t));
12511015SSundeep.Panicker@Sun.COM 	if (sec_obj == NULL) {
12611015SSundeep.Panicker@Sun.COM 		return (NULL);
12711015SSundeep.Panicker@Sun.COM 	}
12811015SSundeep.Panicker@Sun.COM 
12911015SSundeep.Panicker@Sun.COM 	hash_obj = malloc(sizeof (hash_obj_t));
13011015SSundeep.Panicker@Sun.COM 	if (hash_obj == NULL) {
13111015SSundeep.Panicker@Sun.COM 		free(sec_obj);
13211015SSundeep.Panicker@Sun.COM 		return (NULL);
13311015SSundeep.Panicker@Sun.COM 	}
13411015SSundeep.Panicker@Sun.COM 
13511015SSundeep.Panicker@Sun.COM 	sec_obj->next = NULL;
13611015SSundeep.Panicker@Sun.COM 	sec_obj->seg_obj_list = NULL;
13711015SSundeep.Panicker@Sun.COM 
13811015SSundeep.Panicker@Sun.COM 	hash_obj->u.sec_obj = sec_obj;
13911015SSundeep.Panicker@Sun.COM 	hash_obj->object_type = SECTION_TYPE;
14011015SSundeep.Panicker@Sun.COM 	hash_obj->next = NULL;
14111015SSundeep.Panicker@Sun.COM 	hash_obj->prev = NULL;
14211015SSundeep.Panicker@Sun.COM 
14311015SSundeep.Panicker@Sun.COM 	return (hash_obj);
14411015SSundeep.Panicker@Sun.COM }
14511015SSundeep.Panicker@Sun.COM 
14611015SSundeep.Panicker@Sun.COM 
14711015SSundeep.Panicker@Sun.COM static hash_obj_t *
create_segment_hash_object(void)14811015SSundeep.Panicker@Sun.COM create_segment_hash_object(void)
14911015SSundeep.Panicker@Sun.COM {
15011015SSundeep.Panicker@Sun.COM 	hash_obj_t *hash_obj;
15111015SSundeep.Panicker@Sun.COM 	segment_obj_t *seg_obj;
15211015SSundeep.Panicker@Sun.COM 
15311015SSundeep.Panicker@Sun.COM 	seg_obj	= malloc(sizeof (segment_obj_t));
15411015SSundeep.Panicker@Sun.COM 	if (seg_obj == NULL) {
15511015SSundeep.Panicker@Sun.COM 		return (NULL);
15611015SSundeep.Panicker@Sun.COM 	}
15711015SSundeep.Panicker@Sun.COM 
15811015SSundeep.Panicker@Sun.COM 	hash_obj = malloc(sizeof (hash_obj_t));
15911015SSundeep.Panicker@Sun.COM 	if (hash_obj == NULL) {
16011015SSundeep.Panicker@Sun.COM 		free(seg_obj);
16111015SSundeep.Panicker@Sun.COM 		return (NULL);
16211015SSundeep.Panicker@Sun.COM 	}
16311015SSundeep.Panicker@Sun.COM 
16411015SSundeep.Panicker@Sun.COM 	seg_obj->next = NULL;
16511015SSundeep.Panicker@Sun.COM 	seg_obj->pkt_obj_list = NULL;
16611015SSundeep.Panicker@Sun.COM 
16711015SSundeep.Panicker@Sun.COM 	hash_obj->object_type = SEGMENT_TYPE;
16811015SSundeep.Panicker@Sun.COM 	hash_obj->u.seg_obj = seg_obj;
16911015SSundeep.Panicker@Sun.COM 	hash_obj->next = NULL;
17011015SSundeep.Panicker@Sun.COM 	hash_obj->prev = NULL;
17111015SSundeep.Panicker@Sun.COM 
17211015SSundeep.Panicker@Sun.COM 	return (hash_obj);
17311015SSundeep.Panicker@Sun.COM }
17411015SSundeep.Panicker@Sun.COM 
17511015SSundeep.Panicker@Sun.COM 
17611015SSundeep.Panicker@Sun.COM static hash_obj_t *
create_packet_hash_object(void)17711015SSundeep.Panicker@Sun.COM create_packet_hash_object(void)
17811015SSundeep.Panicker@Sun.COM {
17911015SSundeep.Panicker@Sun.COM 	hash_obj_t *hash_obj;
18011015SSundeep.Panicker@Sun.COM 	packet_obj_t *pkt_obj;
18111015SSundeep.Panicker@Sun.COM 
18211015SSundeep.Panicker@Sun.COM 	pkt_obj	= malloc(sizeof (packet_obj_t));
18311015SSundeep.Panicker@Sun.COM 	if (pkt_obj == NULL) {
18411015SSundeep.Panicker@Sun.COM 		return (NULL);
18511015SSundeep.Panicker@Sun.COM 	}
18611015SSundeep.Panicker@Sun.COM 
18711015SSundeep.Panicker@Sun.COM 	hash_obj = malloc(sizeof (hash_obj_t));
18811015SSundeep.Panicker@Sun.COM 	if (hash_obj == NULL) {
18911015SSundeep.Panicker@Sun.COM 		free(pkt_obj);
19011015SSundeep.Panicker@Sun.COM 		return (NULL);
19111015SSundeep.Panicker@Sun.COM 	}
19211015SSundeep.Panicker@Sun.COM 
19311015SSundeep.Panicker@Sun.COM 	pkt_obj->next = NULL;
19411015SSundeep.Panicker@Sun.COM 
19511015SSundeep.Panicker@Sun.COM 	hash_obj->object_type = PACKET_TYPE;
19611015SSundeep.Panicker@Sun.COM 	hash_obj->u.pkt_obj = pkt_obj;
19711015SSundeep.Panicker@Sun.COM 	hash_obj->next = NULL;
19811015SSundeep.Panicker@Sun.COM 	hash_obj->prev = NULL;
19911015SSundeep.Panicker@Sun.COM 
20011015SSundeep.Panicker@Sun.COM 	return (hash_obj);
20111015SSundeep.Panicker@Sun.COM }
20211015SSundeep.Panicker@Sun.COM 
20311015SSundeep.Panicker@Sun.COM 
20411015SSundeep.Panicker@Sun.COM 
20511015SSundeep.Panicker@Sun.COM static hash_obj_t *
get_container_hash_object(int object_type,handle_t handle)20611015SSundeep.Panicker@Sun.COM get_container_hash_object(int	object_type, handle_t	handle)
20711015SSundeep.Panicker@Sun.COM {
20811015SSundeep.Panicker@Sun.COM 	hash_obj_t	*hash_obj;
20911015SSundeep.Panicker@Sun.COM 
21011015SSundeep.Panicker@Sun.COM 	switch (object_type) {
21111015SSundeep.Panicker@Sun.COM 	case CONTAINER_TYPE:
21211015SSundeep.Panicker@Sun.COM 		break;
21311015SSundeep.Panicker@Sun.COM 	case SECTION_TYPE:
21411015SSundeep.Panicker@Sun.COM 		hash_obj = lookup_handle_object(handle, CONTAINER_TYPE);
21511015SSundeep.Panicker@Sun.COM 		if (hash_obj == NULL) {
21611015SSundeep.Panicker@Sun.COM 			return (NULL);
21711015SSundeep.Panicker@Sun.COM 		}
21811015SSundeep.Panicker@Sun.COM 		break;
21911015SSundeep.Panicker@Sun.COM 	case SEGMENT_TYPE:
22011015SSundeep.Panicker@Sun.COM 		hash_obj = lookup_handle_object(handle, SECTION_TYPE);
22111015SSundeep.Panicker@Sun.COM 		if (hash_obj == NULL) {
22211015SSundeep.Panicker@Sun.COM 			return (NULL);
22311015SSundeep.Panicker@Sun.COM 		}
22411015SSundeep.Panicker@Sun.COM 		hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl,
22511015SSundeep.Panicker@Sun.COM 		    CONTAINER_TYPE);
22611015SSundeep.Panicker@Sun.COM 		break;
22711015SSundeep.Panicker@Sun.COM 	case PACKET_TYPE:
22811015SSundeep.Panicker@Sun.COM 		break;
22911015SSundeep.Panicker@Sun.COM 	default:
23011015SSundeep.Panicker@Sun.COM 		return (NULL);
23111015SSundeep.Panicker@Sun.COM 	}
23211015SSundeep.Panicker@Sun.COM 
23311015SSundeep.Panicker@Sun.COM 	return (hash_obj);
23411015SSundeep.Panicker@Sun.COM }
23511015SSundeep.Panicker@Sun.COM 
23611015SSundeep.Panicker@Sun.COM 
23711015SSundeep.Panicker@Sun.COM static void
add_to_pkt_object_list(hash_obj_t * parent_obj,hash_obj_t * child_obj)23811015SSundeep.Panicker@Sun.COM add_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
23911015SSundeep.Panicker@Sun.COM {
24011015SSundeep.Panicker@Sun.COM 	hash_obj_t *next_hash;
24111015SSundeep.Panicker@Sun.COM 
24211015SSundeep.Panicker@Sun.COM 	/* add the packet object in the end of list */
24311015SSundeep.Panicker@Sun.COM 	child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl;
24411015SSundeep.Panicker@Sun.COM 
24511015SSundeep.Panicker@Sun.COM 	if (parent_obj->u.seg_obj->pkt_obj_list == NULL) {
24611015SSundeep.Panicker@Sun.COM 		parent_obj->u.seg_obj->pkt_obj_list = child_obj;
24711015SSundeep.Panicker@Sun.COM 		return;
24811015SSundeep.Panicker@Sun.COM 	}
24911015SSundeep.Panicker@Sun.COM 
25011015SSundeep.Panicker@Sun.COM 	for (next_hash = parent_obj->u.seg_obj->pkt_obj_list;
25111015SSundeep.Panicker@Sun.COM 	    next_hash->u.pkt_obj->next != NULL;
25211015SSundeep.Panicker@Sun.COM 	    next_hash = next_hash->u.pkt_obj->next) {
25311015SSundeep.Panicker@Sun.COM 		;
25411015SSundeep.Panicker@Sun.COM 	}
25511015SSundeep.Panicker@Sun.COM 
25611015SSundeep.Panicker@Sun.COM 	next_hash->u.pkt_obj->next = child_obj;
25711015SSundeep.Panicker@Sun.COM }
25811015SSundeep.Panicker@Sun.COM 
25911015SSundeep.Panicker@Sun.COM 
26011015SSundeep.Panicker@Sun.COM static void
free_pkt_object_list(hash_obj_t * hash_obj)26111015SSundeep.Panicker@Sun.COM free_pkt_object_list(hash_obj_t	*hash_obj)
26211015SSundeep.Panicker@Sun.COM {
26311015SSundeep.Panicker@Sun.COM 	hash_obj_t *next_obj;
26411015SSundeep.Panicker@Sun.COM 	hash_obj_t *free_obj;
26511015SSundeep.Panicker@Sun.COM 
26611015SSundeep.Panicker@Sun.COM 	next_obj = hash_obj->u.seg_obj->pkt_obj_list;
26711015SSundeep.Panicker@Sun.COM 	while (next_obj != NULL) {
26811015SSundeep.Panicker@Sun.COM 		free_obj = next_obj;
26911015SSundeep.Panicker@Sun.COM 		next_obj = next_obj->u.pkt_obj->next;
27011015SSundeep.Panicker@Sun.COM 		/* if prev is NULL it's the first object in the list */
27111015SSundeep.Panicker@Sun.COM 		if (free_obj->prev == NULL) {
27211015SSundeep.Panicker@Sun.COM 			hash_table[(free_obj->obj_hdl % TABLE_SIZE)] =
27311015SSundeep.Panicker@Sun.COM 			    free_obj->next;
27411015SSundeep.Panicker@Sun.COM 			if (free_obj->next != NULL) {
27511015SSundeep.Panicker@Sun.COM 				free_obj->next->prev = free_obj->prev;
27611015SSundeep.Panicker@Sun.COM 			}
27711015SSundeep.Panicker@Sun.COM 		} else {
27811015SSundeep.Panicker@Sun.COM 			free_obj->prev->next = free_obj->next;
27911015SSundeep.Panicker@Sun.COM 			if (free_obj->next != NULL) {
28011015SSundeep.Panicker@Sun.COM 				free_obj->next->prev = free_obj->prev;
28111015SSundeep.Panicker@Sun.COM 			}
28211015SSundeep.Panicker@Sun.COM 		}
28311015SSundeep.Panicker@Sun.COM 
28411015SSundeep.Panicker@Sun.COM 		free(free_obj->u.pkt_obj->payload);
28511015SSundeep.Panicker@Sun.COM 		free(free_obj->u.pkt_obj);
28611015SSundeep.Panicker@Sun.COM 		free(free_obj);
28711015SSundeep.Panicker@Sun.COM 	}
28811015SSundeep.Panicker@Sun.COM 
28911015SSundeep.Panicker@Sun.COM 	hash_obj->u.seg_obj->pkt_obj_list = NULL;
29011015SSundeep.Panicker@Sun.COM }
29111015SSundeep.Panicker@Sun.COM 
29211015SSundeep.Panicker@Sun.COM 
29311015SSundeep.Panicker@Sun.COM static void
free_segment_hash(handle_t handle,hash_obj_t * sec_hash)29411015SSundeep.Panicker@Sun.COM free_segment_hash(handle_t handle, hash_obj_t *sec_hash)
29511015SSundeep.Panicker@Sun.COM {
29611015SSundeep.Panicker@Sun.COM 	hash_obj_t *seg_hash;
29711015SSundeep.Panicker@Sun.COM 	hash_obj_t *next_hash;
29811015SSundeep.Panicker@Sun.COM 
29911015SSundeep.Panicker@Sun.COM 	seg_hash = sec_hash->u.sec_obj->seg_obj_list;
30011015SSundeep.Panicker@Sun.COM 	if (seg_hash == NULL) {
30111015SSundeep.Panicker@Sun.COM 		return;
30211015SSundeep.Panicker@Sun.COM 	}
30311015SSundeep.Panicker@Sun.COM 
30411015SSundeep.Panicker@Sun.COM 	if (seg_hash->obj_hdl == handle) {
30511015SSundeep.Panicker@Sun.COM 		sec_hash->u.sec_obj->seg_obj_list = seg_hash->u.seg_obj->next;
30611015SSundeep.Panicker@Sun.COM 	} else {
30711015SSundeep.Panicker@Sun.COM 		while (seg_hash->obj_hdl != handle) {
30811015SSundeep.Panicker@Sun.COM 			next_hash = seg_hash;
30911015SSundeep.Panicker@Sun.COM 			seg_hash = seg_hash->u.seg_obj->next;
31011015SSundeep.Panicker@Sun.COM 			if (seg_hash == NULL) {
31111015SSundeep.Panicker@Sun.COM 				return;
31211015SSundeep.Panicker@Sun.COM 			}
31311015SSundeep.Panicker@Sun.COM 		}
31411015SSundeep.Panicker@Sun.COM 		next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next;
31511015SSundeep.Panicker@Sun.COM 	}
31611015SSundeep.Panicker@Sun.COM 
31711015SSundeep.Panicker@Sun.COM 	if (seg_hash->prev == NULL) {
31811015SSundeep.Panicker@Sun.COM 		hash_table[(seg_hash->obj_hdl % TABLE_SIZE)] = seg_hash->next;
31911015SSundeep.Panicker@Sun.COM 		if (seg_hash->next != NULL) {
32011015SSundeep.Panicker@Sun.COM 			seg_hash->next->prev = NULL;
32111015SSundeep.Panicker@Sun.COM 		}
32211015SSundeep.Panicker@Sun.COM 	} else {
32311015SSundeep.Panicker@Sun.COM 		seg_hash->prev->next = seg_hash->next;
32411015SSundeep.Panicker@Sun.COM 		if (seg_hash->next != NULL) {
32511015SSundeep.Panicker@Sun.COM 			seg_hash->next->prev = seg_hash->prev;
32611015SSundeep.Panicker@Sun.COM 		}
32711015SSundeep.Panicker@Sun.COM 	}
32811015SSundeep.Panicker@Sun.COM 
32911015SSundeep.Panicker@Sun.COM 	free_pkt_object_list(seg_hash);
33011015SSundeep.Panicker@Sun.COM 	free(seg_hash->u.seg_obj);
33111015SSundeep.Panicker@Sun.COM 	free(seg_hash);
33211015SSundeep.Panicker@Sun.COM }
33311015SSundeep.Panicker@Sun.COM 
33411015SSundeep.Panicker@Sun.COM 
33511015SSundeep.Panicker@Sun.COM 
33611015SSundeep.Panicker@Sun.COM static void
add_to_sec_object_list(hash_obj_t * parent_obj,hash_obj_t * child_obj)33711015SSundeep.Panicker@Sun.COM add_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
33811015SSundeep.Panicker@Sun.COM {
33911015SSundeep.Panicker@Sun.COM 	hash_obj_t *next_hash;
34011015SSundeep.Panicker@Sun.COM 
34111015SSundeep.Panicker@Sun.COM 	child_obj->u.sec_obj->cont_hdl = parent_obj->obj_hdl;
34211015SSundeep.Panicker@Sun.COM 	if (parent_obj->u.cont_obj->sec_obj_list == NULL) {
34311015SSundeep.Panicker@Sun.COM 		parent_obj->u.cont_obj->sec_obj_list = child_obj;
34411015SSundeep.Panicker@Sun.COM 		return;
34511015SSundeep.Panicker@Sun.COM 	}
34611015SSundeep.Panicker@Sun.COM 
34711015SSundeep.Panicker@Sun.COM 	for (next_hash = parent_obj->u.cont_obj->sec_obj_list;
34811015SSundeep.Panicker@Sun.COM 	    next_hash->u.sec_obj->next != NULL;
34911015SSundeep.Panicker@Sun.COM 	    next_hash = next_hash->u.sec_obj->next) {
35011015SSundeep.Panicker@Sun.COM 		;
35111015SSundeep.Panicker@Sun.COM 	}
35211015SSundeep.Panicker@Sun.COM 
35311015SSundeep.Panicker@Sun.COM 	next_hash->u.sec_obj->next = child_obj;
35411015SSundeep.Panicker@Sun.COM }
35511015SSundeep.Panicker@Sun.COM 
35611015SSundeep.Panicker@Sun.COM 
35711015SSundeep.Panicker@Sun.COM static void
add_to_seg_object_list(hash_obj_t * parent_obj,hash_obj_t * child_obj)35811015SSundeep.Panicker@Sun.COM add_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj)
35911015SSundeep.Panicker@Sun.COM {
36011015SSundeep.Panicker@Sun.COM 	hash_obj_t *next_hash;
36111015SSundeep.Panicker@Sun.COM 
36211015SSundeep.Panicker@Sun.COM 	child_obj->u.seg_obj->section_hdl = parent_obj->obj_hdl;
36311015SSundeep.Panicker@Sun.COM 	if (parent_obj->u.sec_obj->seg_obj_list == NULL) {
36411015SSundeep.Panicker@Sun.COM 		parent_obj->u.sec_obj->seg_obj_list = child_obj;
36511015SSundeep.Panicker@Sun.COM 		return;
36611015SSundeep.Panicker@Sun.COM 	}
36711015SSundeep.Panicker@Sun.COM 
36811015SSundeep.Panicker@Sun.COM 	for (next_hash = parent_obj->u.sec_obj->seg_obj_list;
36911015SSundeep.Panicker@Sun.COM 	    next_hash->u.seg_obj->next != NULL;
37011015SSundeep.Panicker@Sun.COM 	    next_hash = next_hash->u.seg_obj->next) {
37111015SSundeep.Panicker@Sun.COM 		;
37211015SSundeep.Panicker@Sun.COM 	}
37311015SSundeep.Panicker@Sun.COM 
37411015SSundeep.Panicker@Sun.COM 	next_hash->u.seg_obj->next = child_obj;
37511015SSundeep.Panicker@Sun.COM }
37611015SSundeep.Panicker@Sun.COM 
37711015SSundeep.Panicker@Sun.COM 
37811015SSundeep.Panicker@Sun.COM static char *
tokenizer(char * buf,char * separator,char ** nextBuf,char * matched)37911015SSundeep.Panicker@Sun.COM tokenizer(char *buf, char *separator, char **nextBuf, char *matched)
38011015SSundeep.Panicker@Sun.COM {
38111015SSundeep.Panicker@Sun.COM 	int i = 0;
38211015SSundeep.Panicker@Sun.COM 	int j = 0;
38311015SSundeep.Panicker@Sun.COM 
38411015SSundeep.Panicker@Sun.COM 	for (i = 0; buf[i] != '\0'; i++) {
38511015SSundeep.Panicker@Sun.COM 		for (j = 0; j < strlen(separator); j++) {
38611015SSundeep.Panicker@Sun.COM 			if (buf[i] == separator[j]) {
38711015SSundeep.Panicker@Sun.COM 				buf[i] = '\0';
38811015SSundeep.Panicker@Sun.COM 				*nextBuf = &(buf[i+1]);
38911015SSundeep.Panicker@Sun.COM 				*matched = separator[j];
39011015SSundeep.Panicker@Sun.COM 				return (buf);
39111015SSundeep.Panicker@Sun.COM 			}
39211015SSundeep.Panicker@Sun.COM 		}
39311015SSundeep.Panicker@Sun.COM 	}
39411015SSundeep.Panicker@Sun.COM 
39511015SSundeep.Panicker@Sun.COM 	*nextBuf = buf;
39611015SSundeep.Panicker@Sun.COM 	*matched = '\0';
39711015SSundeep.Panicker@Sun.COM 	return (NULL);
39811015SSundeep.Panicker@Sun.COM }
39911015SSundeep.Panicker@Sun.COM 
40011015SSundeep.Panicker@Sun.COM 
40111015SSundeep.Panicker@Sun.COM static void
copy_segment_layout(segment_t * seghdr,void * layout)40211015SSundeep.Panicker@Sun.COM copy_segment_layout(segment_t *seghdr, void *layout)
40311015SSundeep.Panicker@Sun.COM {
40411015SSundeep.Panicker@Sun.COM 	segment_layout_t *seg_layout;
40511015SSundeep.Panicker@Sun.COM 
40611015SSundeep.Panicker@Sun.COM 	seg_layout = (segment_layout_t *)layout;
40711015SSundeep.Panicker@Sun.COM 	(void) memcpy(seghdr->name, &seg_layout->name, SEG_NAME_LEN);
40811015SSundeep.Panicker@Sun.COM 	seghdr->descriptor = GET_SEGMENT_DESCRIPTOR;
40911015SSundeep.Panicker@Sun.COM 	seghdr->offset = BE_16(seg_layout->offset);
41011015SSundeep.Panicker@Sun.COM 	seghdr->length = BE_16(seg_layout->length);
41111015SSundeep.Panicker@Sun.COM }
41211015SSundeep.Panicker@Sun.COM 
41311015SSundeep.Panicker@Sun.COM 
41411015SSundeep.Panicker@Sun.COM static int
get_container_info(const char * def_file,const char * cont_desc_str,container_info_t * cont_info)41511015SSundeep.Panicker@Sun.COM get_container_info(const char *def_file, const char *cont_desc_str,
41611015SSundeep.Panicker@Sun.COM     container_info_t *cont_info)
41711015SSundeep.Panicker@Sun.COM {
41811015SSundeep.Panicker@Sun.COM 	char *item;
41911015SSundeep.Panicker@Sun.COM 	char *token;
42011015SSundeep.Panicker@Sun.COM 	char *field;
42111015SSundeep.Panicker@Sun.COM 	char matched;
42211015SSundeep.Panicker@Sun.COM 	char buf[1024];
42311015SSundeep.Panicker@Sun.COM 	int foundIt = 0;
42411015SSundeep.Panicker@Sun.COM 	FILE *file = fopen(def_file, "r");
42511015SSundeep.Panicker@Sun.COM 
42611015SSundeep.Panicker@Sun.COM 	if (file == NULL)
42711015SSundeep.Panicker@Sun.COM 		return (-1);
42811015SSundeep.Panicker@Sun.COM 
42911015SSundeep.Panicker@Sun.COM 	cont_info->num_sections = 0;
43011015SSundeep.Panicker@Sun.COM 
43111015SSundeep.Panicker@Sun.COM 	while (fgets(buf, sizeof (buf), file) != NULL) {
43211015SSundeep.Panicker@Sun.COM 		/* ignore all comments */
43311015SSundeep.Panicker@Sun.COM 		token = tokenizer(buf, "#", &field, &matched);
43411015SSundeep.Panicker@Sun.COM 		/* find the names */
43511015SSundeep.Panicker@Sun.COM 		token = tokenizer(buf, ":", &field, &matched);
43611015SSundeep.Panicker@Sun.COM 		if (token != 0x00) {
43711015SSundeep.Panicker@Sun.COM 			token = tokenizer(token, "|", &item, &matched);
43811015SSundeep.Panicker@Sun.COM 			while (token != 0x00) {
43911015SSundeep.Panicker@Sun.COM 				if (strcmp(token, cont_desc_str) == 0) {
44011015SSundeep.Panicker@Sun.COM 					foundIt = 1;
44111015SSundeep.Panicker@Sun.COM 					goto found;
44211015SSundeep.Panicker@Sun.COM 				}
44311015SSundeep.Panicker@Sun.COM 				token = tokenizer(item, "|", &item, &matched);
44411015SSundeep.Panicker@Sun.COM 			}
44511015SSundeep.Panicker@Sun.COM 			/* check the last remaining item */
44611015SSundeep.Panicker@Sun.COM 			if ((item != 0x00) &&
44711015SSundeep.Panicker@Sun.COM 			    (strcmp(item, cont_desc_str) == 0)) {
44811015SSundeep.Panicker@Sun.COM 				foundIt = 1;
44911015SSundeep.Panicker@Sun.COM 				goto found;
45011015SSundeep.Panicker@Sun.COM 			}
45111015SSundeep.Panicker@Sun.COM 		}
45211015SSundeep.Panicker@Sun.COM 	}
45311015SSundeep.Panicker@Sun.COM 
45411015SSundeep.Panicker@Sun.COM found :
45511015SSundeep.Panicker@Sun.COM 	if (foundIt == 1) {
45611015SSundeep.Panicker@Sun.COM 		token = tokenizer(field, ":", &field, &matched);
45711015SSundeep.Panicker@Sun.COM 		if (token == 0x00) {
45811015SSundeep.Panicker@Sun.COM 			(void) fclose(file);
45911015SSundeep.Panicker@Sun.COM 			return (-1);
46011015SSundeep.Panicker@Sun.COM 		}
46111015SSundeep.Panicker@Sun.COM 		cont_info->header_ver = (headerrev_t)atoi(token);
46211015SSundeep.Panicker@Sun.COM 
46311015SSundeep.Panicker@Sun.COM 		token = tokenizer(field, ":\n", &field, &matched);
46411015SSundeep.Panicker@Sun.COM 		while (token != 0x00) {
46511015SSundeep.Panicker@Sun.COM 			token = tokenizer(token, ",", &item, &matched);
46611015SSundeep.Panicker@Sun.COM 			if (token == 0x00) {
46711015SSundeep.Panicker@Sun.COM 				(void) fclose(file);
46811015SSundeep.Panicker@Sun.COM 				return (-1);
46911015SSundeep.Panicker@Sun.COM 			}
47011015SSundeep.Panicker@Sun.COM 			if (atoi(token) == 1) {
47111015SSundeep.Panicker@Sun.COM 				cont_info->section_info[cont_info->
47211015SSundeep.Panicker@Sun.COM 				    num_sections].description.field.read_only
47311015SSundeep.Panicker@Sun.COM 				    = 1;
47411015SSundeep.Panicker@Sun.COM 			} else if (atoi(token) == 0) {
47511015SSundeep.Panicker@Sun.COM 				cont_info->section_info[cont_info->
47611015SSundeep.Panicker@Sun.COM 				    num_sections].description.field.read_only
47711015SSundeep.Panicker@Sun.COM 				    = 0;
47811015SSundeep.Panicker@Sun.COM 			} else {
47911015SSundeep.Panicker@Sun.COM 				(void) fclose(file);
48011015SSundeep.Panicker@Sun.COM 				return (-1);
48111015SSundeep.Panicker@Sun.COM 			}
48211015SSundeep.Panicker@Sun.COM 
48311015SSundeep.Panicker@Sun.COM 			token = tokenizer(item, ",", &item, &matched);
48411015SSundeep.Panicker@Sun.COM 			if (token == 0x00) {
48511015SSundeep.Panicker@Sun.COM 				(void) fclose(file);
48611015SSundeep.Panicker@Sun.COM 				return (-1);
48711015SSundeep.Panicker@Sun.COM 			}
48811015SSundeep.Panicker@Sun.COM 
48911015SSundeep.Panicker@Sun.COM 			cont_info->section_info[cont_info->
49011015SSundeep.Panicker@Sun.COM 			    num_sections].address = atoi(token);
49111015SSundeep.Panicker@Sun.COM 			if (item == '\0') {
49211015SSundeep.Panicker@Sun.COM 				(void) fclose(file);
49311015SSundeep.Panicker@Sun.COM 				return (-1);
49411015SSundeep.Panicker@Sun.COM 			}
49511015SSundeep.Panicker@Sun.COM 			cont_info->section_info[cont_info->num_sections].size =
49611015SSundeep.Panicker@Sun.COM 			    atoi(item);
49711015SSundeep.Panicker@Sun.COM 			(cont_info->num_sections)++;
49811015SSundeep.Panicker@Sun.COM 
49911015SSundeep.Panicker@Sun.COM 			token = tokenizer(field, ":\n ", &field, &matched);
50011015SSundeep.Panicker@Sun.COM 		}
50111015SSundeep.Panicker@Sun.COM 	}
50211015SSundeep.Panicker@Sun.COM 	(void) fclose(file);
50311015SSundeep.Panicker@Sun.COM 
50411015SSundeep.Panicker@Sun.COM 	return (0);
50511015SSundeep.Panicker@Sun.COM }
50611015SSundeep.Panicker@Sun.COM 
50711015SSundeep.Panicker@Sun.COM 
50811015SSundeep.Panicker@Sun.COM /* ARGSUSED */
50911015SSundeep.Panicker@Sun.COM int
fru_get_segments(section_hdl_t section,segment_t * segment,int maxseg,door_cred_t * cred)51011015SSundeep.Panicker@Sun.COM fru_get_segments(section_hdl_t section, segment_t *segment, int maxseg,
51111015SSundeep.Panicker@Sun.COM     door_cred_t *cred)
51211015SSundeep.Panicker@Sun.COM {
51311015SSundeep.Panicker@Sun.COM 	int count;
51411015SSundeep.Panicker@Sun.COM 	hash_obj_t *sec_object;
51511015SSundeep.Panicker@Sun.COM 	hash_obj_t *seg_object;
51611015SSundeep.Panicker@Sun.COM 	section_obj_t *sec_obj;
51711015SSundeep.Panicker@Sun.COM 
51811015SSundeep.Panicker@Sun.COM 	sec_object = lookup_handle_object(section, SECTION_TYPE);
51911015SSundeep.Panicker@Sun.COM 	if (sec_object == NULL) {
52011015SSundeep.Panicker@Sun.COM 		return (-1);
52111015SSundeep.Panicker@Sun.COM 	}
52211015SSundeep.Panicker@Sun.COM 
52311015SSundeep.Panicker@Sun.COM 	sec_obj	= sec_object->u.sec_obj;
52411015SSundeep.Panicker@Sun.COM 	if (sec_obj == NULL) {
52511015SSundeep.Panicker@Sun.COM 		return (-1);
52611015SSundeep.Panicker@Sun.COM 	}
52711015SSundeep.Panicker@Sun.COM 
52811015SSundeep.Panicker@Sun.COM 	if (sec_obj->num_of_segment > maxseg) {
52911015SSundeep.Panicker@Sun.COM 		return (-1);
53011015SSundeep.Panicker@Sun.COM 	}
53111015SSundeep.Panicker@Sun.COM 
53211015SSundeep.Panicker@Sun.COM 	seg_object = sec_object->u.sec_obj->seg_obj_list;
53311015SSundeep.Panicker@Sun.COM 	if (seg_object == NULL) {
53411015SSundeep.Panicker@Sun.COM 		return (-1);
53511015SSundeep.Panicker@Sun.COM 	}
53611015SSundeep.Panicker@Sun.COM 
53711015SSundeep.Panicker@Sun.COM 	for (count = 0; count < sec_obj->num_of_segment; count++) {
53811015SSundeep.Panicker@Sun.COM 
53911015SSundeep.Panicker@Sun.COM 		/* populate segment_t */
54011015SSundeep.Panicker@Sun.COM 		segment->handle = seg_object->obj_hdl;
54111015SSundeep.Panicker@Sun.COM 		(void) memcpy(segment->name,
54211015SSundeep.Panicker@Sun.COM 		    seg_object->u.seg_obj->segment.name, SEG_NAME_LEN);
54311015SSundeep.Panicker@Sun.COM 		segment->descriptor = seg_object->u.seg_obj->segment.descriptor;
54411015SSundeep.Panicker@Sun.COM 
54511015SSundeep.Panicker@Sun.COM 		segment->offset	= seg_object->u.seg_obj->segment.offset;
54611015SSundeep.Panicker@Sun.COM 		segment->length	= seg_object->u.seg_obj->segment.length;
54711015SSundeep.Panicker@Sun.COM 		seg_object = seg_object->u.seg_obj->next;
54811015SSundeep.Panicker@Sun.COM 		segment++;
54911015SSundeep.Panicker@Sun.COM 	}
55011015SSundeep.Panicker@Sun.COM 	return (0);
55111015SSundeep.Panicker@Sun.COM }
55211015SSundeep.Panicker@Sun.COM 
55311015SSundeep.Panicker@Sun.COM 
55411015SSundeep.Panicker@Sun.COM static int
raw_memcpy(void * buffer,raw_list_t * rawlist,int offset,int size)55511015SSundeep.Panicker@Sun.COM raw_memcpy(void *buffer, raw_list_t *rawlist, int offset, int size)
55611015SSundeep.Panicker@Sun.COM {
55711015SSundeep.Panicker@Sun.COM 	if (offset + size > rawlist->size) {
55811015SSundeep.Panicker@Sun.COM 		size = rawlist->size - offset;
55911015SSundeep.Panicker@Sun.COM 	}
56011015SSundeep.Panicker@Sun.COM 
56111015SSundeep.Panicker@Sun.COM 	(void) memcpy(buffer, &rawlist->raw[offset], size);
56211015SSundeep.Panicker@Sun.COM 
56311015SSundeep.Panicker@Sun.COM 	return (size);
56411015SSundeep.Panicker@Sun.COM }
56511015SSundeep.Panicker@Sun.COM 
56611015SSundeep.Panicker@Sun.COM 
56711015SSundeep.Panicker@Sun.COM static int
verify_header_crc8(headerrev_t head_ver,unsigned char * bytes,int length)56811015SSundeep.Panicker@Sun.COM verify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length)
56911015SSundeep.Panicker@Sun.COM {
57011015SSundeep.Panicker@Sun.COM 	int crc_offset = 0;
57111015SSundeep.Panicker@Sun.COM 	unsigned char orig_crc8 = 0;
57211015SSundeep.Panicker@Sun.COM 	unsigned char calc_crc8 = 0;
57311015SSundeep.Panicker@Sun.COM 
57411015SSundeep.Panicker@Sun.COM 	switch (head_ver) {
57511015SSundeep.Panicker@Sun.COM 		case SECTION_HDR_VER:
57611015SSundeep.Panicker@Sun.COM 			crc_offset = 4;
57711015SSundeep.Panicker@Sun.COM 			break;
57811015SSundeep.Panicker@Sun.COM 		default:
57911015SSundeep.Panicker@Sun.COM 			errno = EINVAL;
58011015SSundeep.Panicker@Sun.COM 			return (0);
58111015SSundeep.Panicker@Sun.COM 	}
58211015SSundeep.Panicker@Sun.COM 
58311015SSundeep.Panicker@Sun.COM 	orig_crc8 = bytes[crc_offset];
58411015SSundeep.Panicker@Sun.COM 	bytes[crc_offset] = 0x00; /* clear for calc */
58511015SSundeep.Panicker@Sun.COM 	calc_crc8 = compute_crc8(bytes, length);
58611015SSundeep.Panicker@Sun.COM 	bytes[crc_offset] = orig_crc8; /* restore */
58711015SSundeep.Panicker@Sun.COM 
58811015SSundeep.Panicker@Sun.COM 	return (orig_crc8 == calc_crc8);
58911015SSundeep.Panicker@Sun.COM }
59011015SSundeep.Panicker@Sun.COM 
59111015SSundeep.Panicker@Sun.COM 
59211015SSundeep.Panicker@Sun.COM static int
get_section(raw_list_t * rawlist,hash_obj_t * sec_hash,section_t * section)59311015SSundeep.Panicker@Sun.COM get_section(raw_list_t *rawlist, hash_obj_t *sec_hash, section_t *section)
59411015SSundeep.Panicker@Sun.COM {
59511015SSundeep.Panicker@Sun.COM 	int retval;
59611015SSundeep.Panicker@Sun.COM 	int size;
59711015SSundeep.Panicker@Sun.COM 	int count;
59811015SSundeep.Panicker@Sun.COM 	uint16_t hdrver;
59911015SSundeep.Panicker@Sun.COM 	hash_obj_t *seg_hash;
60011015SSundeep.Panicker@Sun.COM 	unsigned char *buffer;
60111015SSundeep.Panicker@Sun.COM 	section_obj_t *sec_obj;
60211015SSundeep.Panicker@Sun.COM 	section_layout_t sec_hdr;
60311015SSundeep.Panicker@Sun.COM 	segment_layout_t *seg_hdr;
60411015SSundeep.Panicker@Sun.COM 	segment_layout_t *seg_buf;
60511015SSundeep.Panicker@Sun.COM 
60611015SSundeep.Panicker@Sun.COM 	sec_obj	= sec_hash->u.sec_obj;
60711015SSundeep.Panicker@Sun.COM 	if (sec_obj == NULL) {
60811015SSundeep.Panicker@Sun.COM 		return (-1);
60911015SSundeep.Panicker@Sun.COM 	}
61011015SSundeep.Panicker@Sun.COM 
61111015SSundeep.Panicker@Sun.COM 	/* populate section_t */
61211015SSundeep.Panicker@Sun.COM 	section->handle = sec_hash->obj_hdl;
61311015SSundeep.Panicker@Sun.COM 	section->offset = sec_obj->section.offset;
61411015SSundeep.Panicker@Sun.COM 	section->length = sec_obj->section.length;
61511015SSundeep.Panicker@Sun.COM 	section->protection = sec_obj->section.protection;
61611015SSundeep.Panicker@Sun.COM 	section->version = sec_obj->section.version;
61711015SSundeep.Panicker@Sun.COM 
61811015SSundeep.Panicker@Sun.COM 	/* read section header layout */
61911015SSundeep.Panicker@Sun.COM 	retval = raw_memcpy(&sec_hdr, rawlist, sec_obj->section.offset,
62011015SSundeep.Panicker@Sun.COM 	    sizeof (sec_hdr));
62111015SSundeep.Panicker@Sun.COM 
62211015SSundeep.Panicker@Sun.COM 	if (retval != sizeof (sec_hdr)) {
62311015SSundeep.Panicker@Sun.COM 		return (-1);
62411015SSundeep.Panicker@Sun.COM 	}
62511015SSundeep.Panicker@Sun.COM 
62611015SSundeep.Panicker@Sun.COM 
62711015SSundeep.Panicker@Sun.COM 	hdrver = GET_SECTION_HDR_VERSION;
62811015SSundeep.Panicker@Sun.COM 
62911015SSundeep.Panicker@Sun.COM 	if ((sec_hdr.headertag != SECTION_HDR_TAG) &&
63011015SSundeep.Panicker@Sun.COM 	    (hdrver != section->version)) {
63111015SSundeep.Panicker@Sun.COM 		return (-1);
63211015SSundeep.Panicker@Sun.COM 	}
63311015SSundeep.Panicker@Sun.COM 
63411015SSundeep.Panicker@Sun.COM 	/* size = section layout + total sizeof segment header */
63511015SSundeep.Panicker@Sun.COM 	size = sizeof (sec_hdr) + ((sec_hdr.segmentcount)
63611015SSundeep.Panicker@Sun.COM 	    * sizeof (segment_layout_t));
63711015SSundeep.Panicker@Sun.COM 
63811015SSundeep.Panicker@Sun.COM 	buffer = alloca(size);
63911015SSundeep.Panicker@Sun.COM 	if (buffer == NULL) {
64011015SSundeep.Panicker@Sun.COM 		return (-1);
64111015SSundeep.Panicker@Sun.COM 	}
64211015SSundeep.Panicker@Sun.COM 
64311015SSundeep.Panicker@Sun.COM 	/* segment header buffer */
64411015SSundeep.Panicker@Sun.COM 	seg_buf = alloca(size - sizeof (sec_hdr));
64511015SSundeep.Panicker@Sun.COM 	if (seg_buf == NULL) {
64611015SSundeep.Panicker@Sun.COM 		return (-1);
64711015SSundeep.Panicker@Sun.COM 	}
64811015SSundeep.Panicker@Sun.COM 
64911015SSundeep.Panicker@Sun.COM 	/* read segment header */
65011015SSundeep.Panicker@Sun.COM 	retval = raw_memcpy(seg_buf, rawlist,
65111015SSundeep.Panicker@Sun.COM 	    sec_obj->section.offset + sizeof (sec_hdr),
65211015SSundeep.Panicker@Sun.COM 	    size - sizeof (sec_hdr));
65311015SSundeep.Panicker@Sun.COM 
65411015SSundeep.Panicker@Sun.COM 	if (retval != (size - sizeof (sec_hdr))) {
65511015SSundeep.Panicker@Sun.COM 		return (-1);
65611015SSundeep.Panicker@Sun.COM 	}
65711015SSundeep.Panicker@Sun.COM 
65811015SSundeep.Panicker@Sun.COM 	/* copy section header layout */
65911015SSundeep.Panicker@Sun.COM 	(void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr));
66011015SSundeep.Panicker@Sun.COM 
66111015SSundeep.Panicker@Sun.COM 	/* copy segment header layout */
66211015SSundeep.Panicker@Sun.COM 	(void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size -
66311015SSundeep.Panicker@Sun.COM 	    sizeof (sec_hdr));
66411015SSundeep.Panicker@Sun.COM 
66511015SSundeep.Panicker@Sun.COM 	/* verify crc8 */
66611015SSundeep.Panicker@Sun.COM 	retval = verify_header_crc8(hdrver, buffer, size);
66711015SSundeep.Panicker@Sun.COM 	if (retval != TRUE) {
66811015SSundeep.Panicker@Sun.COM 		return (-1);
66911015SSundeep.Panicker@Sun.COM 	}
67011015SSundeep.Panicker@Sun.COM 
67111015SSundeep.Panicker@Sun.COM 	section->version = hdrver;
67211015SSundeep.Panicker@Sun.COM 	sec_obj->section.version = hdrver;
67311015SSundeep.Panicker@Sun.COM 
67411015SSundeep.Panicker@Sun.COM 	seg_hdr	= (segment_layout_t *)seg_buf;
67511015SSundeep.Panicker@Sun.COM 
67611015SSundeep.Panicker@Sun.COM 	/* bug fix for frutool */
67711015SSundeep.Panicker@Sun.COM 	if (sec_hash->u.sec_obj->seg_obj_list != NULL) {
67811015SSundeep.Panicker@Sun.COM 		return (0);
67911015SSundeep.Panicker@Sun.COM 	} else {
68011015SSundeep.Panicker@Sun.COM 		sec_obj->num_of_segment = 0;
68111015SSundeep.Panicker@Sun.COM 	}
68211015SSundeep.Panicker@Sun.COM 	for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) {
68311015SSundeep.Panicker@Sun.COM 
68411015SSundeep.Panicker@Sun.COM 		seg_hash = create_segment_hash_object();
68511015SSundeep.Panicker@Sun.COM 		if (seg_hash == NULL) {
68611015SSundeep.Panicker@Sun.COM 			return (-1);
68711015SSundeep.Panicker@Sun.COM 		}
68811015SSundeep.Panicker@Sun.COM 		add_hashobject_to_hashtable(seg_hash);
68911015SSundeep.Panicker@Sun.COM 		copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_hdr);
69011015SSundeep.Panicker@Sun.COM 		add_to_seg_object_list(sec_hash, seg_hash);
69111015SSundeep.Panicker@Sun.COM 		sec_obj->num_of_segment++;
69211015SSundeep.Panicker@Sun.COM 	}
69311015SSundeep.Panicker@Sun.COM 	return (0);
69411015SSundeep.Panicker@Sun.COM }
69511015SSundeep.Panicker@Sun.COM 
69611015SSundeep.Panicker@Sun.COM /* ARGSUSED */
69711015SSundeep.Panicker@Sun.COM int
fru_get_sections(container_hdl_t container,section_t * section,int maxsec,door_cred_t * cred)69811015SSundeep.Panicker@Sun.COM fru_get_sections(container_hdl_t container, section_t *section, int maxsec,
69911015SSundeep.Panicker@Sun.COM     door_cred_t *cred)
70011015SSundeep.Panicker@Sun.COM {
70111015SSundeep.Panicker@Sun.COM 	int count;
70211015SSundeep.Panicker@Sun.COM 	int num_sec = 0;
70311015SSundeep.Panicker@Sun.COM 	hash_obj_t *cont_object;
70411015SSundeep.Panicker@Sun.COM 	hash_obj_t *sec_hash;
70511015SSundeep.Panicker@Sun.COM 
70611015SSundeep.Panicker@Sun.COM 	cont_object = lookup_handle_object(container, CONTAINER_TYPE);
70711015SSundeep.Panicker@Sun.COM 	if (cont_object == NULL) {
70811015SSundeep.Panicker@Sun.COM 		return (-1);
70911015SSundeep.Panicker@Sun.COM 	}
71011015SSundeep.Panicker@Sun.COM 
71111015SSundeep.Panicker@Sun.COM 	if (cont_object->u.cont_obj->num_of_section > maxsec) {
71211015SSundeep.Panicker@Sun.COM 		return (-1);
71311015SSundeep.Panicker@Sun.COM 	}
71411015SSundeep.Panicker@Sun.COM 
71511015SSundeep.Panicker@Sun.COM 	sec_hash = cont_object->u.cont_obj->sec_obj_list;
71611015SSundeep.Panicker@Sun.COM 	if (sec_hash == NULL) {
71711015SSundeep.Panicker@Sun.COM 		return (-1);
71811015SSundeep.Panicker@Sun.COM 	}
71911015SSundeep.Panicker@Sun.COM 
72011015SSundeep.Panicker@Sun.COM 	for (count = 0; count < cont_object->u.cont_obj->num_of_section;
72111015SSundeep.Panicker@Sun.COM 	    count++) {
72211015SSundeep.Panicker@Sun.COM 		section->version = -1;
72311015SSundeep.Panicker@Sun.COM 		/* populate section_t */
72411015SSundeep.Panicker@Sun.COM 		if (get_section(g_raw, sec_hash, section) == 0) {
72511015SSundeep.Panicker@Sun.COM 			section++;
72611015SSundeep.Panicker@Sun.COM 			num_sec++;
72711015SSundeep.Panicker@Sun.COM 		}
72811015SSundeep.Panicker@Sun.COM 		sec_hash = sec_hash->u.sec_obj->next;
72911015SSundeep.Panicker@Sun.COM 	}
73011015SSundeep.Panicker@Sun.COM 	return (num_sec);
73111015SSundeep.Panicker@Sun.COM }
73211015SSundeep.Panicker@Sun.COM 
73311015SSundeep.Panicker@Sun.COM 
73411015SSundeep.Panicker@Sun.COM static uint32_t
get_checksum_crc(hash_obj_t * seg_hash,int data_size)73511015SSundeep.Panicker@Sun.COM get_checksum_crc(hash_obj_t *seg_hash, int data_size)
73611015SSundeep.Panicker@Sun.COM {
73711015SSundeep.Panicker@Sun.COM 	int protection;
73811015SSundeep.Panicker@Sun.COM 	int offset = 0;
73911015SSundeep.Panicker@Sun.COM 	uint32_t crc;
74011015SSundeep.Panicker@Sun.COM 	hash_obj_t *sec_hash;
74111015SSundeep.Panicker@Sun.COM 	hash_obj_t *pkt_hash;
74211015SSundeep.Panicker@Sun.COM 	unsigned char *buffer;
74311015SSundeep.Panicker@Sun.COM 
74411015SSundeep.Panicker@Sun.COM 	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
74511015SSundeep.Panicker@Sun.COM 	    SECTION_TYPE);
74611015SSundeep.Panicker@Sun.COM 	if (sec_hash == NULL) {
74711015SSundeep.Panicker@Sun.COM 		return ((uint32_t)-1);
74811015SSundeep.Panicker@Sun.COM 	}
74911015SSundeep.Panicker@Sun.COM 
75011015SSundeep.Panicker@Sun.COM 	buffer = alloca(data_size);
75111015SSundeep.Panicker@Sun.COM 	if (buffer == NULL) {
75211015SSundeep.Panicker@Sun.COM 		return ((uint32_t)-1);
75311015SSundeep.Panicker@Sun.COM 	}
75411015SSundeep.Panicker@Sun.COM 
75511015SSundeep.Panicker@Sun.COM 	/* traverse the packet object list for all the tags and payload */
75611015SSundeep.Panicker@Sun.COM 	for (pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; pkt_hash != NULL;
75711015SSundeep.Panicker@Sun.COM 	    pkt_hash = pkt_hash->u.pkt_obj->next) {
75811015SSundeep.Panicker@Sun.COM 		(void) memcpy(buffer + offset, &pkt_hash->u.pkt_obj->tag,
75911015SSundeep.Panicker@Sun.COM 		    pkt_hash->u.pkt_obj->tag_size);
76011015SSundeep.Panicker@Sun.COM 		offset += pkt_hash->u.pkt_obj->tag_size;
76111015SSundeep.Panicker@Sun.COM 		(void) memcpy(buffer + offset, pkt_hash->u.pkt_obj->payload,
76211015SSundeep.Panicker@Sun.COM 		    pkt_hash->u.pkt_obj->paylen);
76311015SSundeep.Panicker@Sun.COM 		offset += pkt_hash->u.pkt_obj->paylen;
76411015SSundeep.Panicker@Sun.COM 	}
76511015SSundeep.Panicker@Sun.COM 
76611015SSundeep.Panicker@Sun.COM 	protection = sec_hash->u.sec_obj->section.protection;
76711015SSundeep.Panicker@Sun.COM 
76811015SSundeep.Panicker@Sun.COM 	if (protection == READ_ONLY_SECTION) { /* read-only section */
76911015SSundeep.Panicker@Sun.COM 		crc = compute_crc32(buffer, data_size);
77011015SSundeep.Panicker@Sun.COM 	} else {		/* read/write section */
77111015SSundeep.Panicker@Sun.COM 		crc = compute_checksum32(buffer, data_size);
77211015SSundeep.Panicker@Sun.COM 	}
77311015SSundeep.Panicker@Sun.COM 	return (crc);	/* computed crc */
77411015SSundeep.Panicker@Sun.COM }
77511015SSundeep.Panicker@Sun.COM 
77611015SSundeep.Panicker@Sun.COM 
77711015SSundeep.Panicker@Sun.COM static int
get_packet(raw_list_t * rawlist,void * buffer,int size,int offset)77811015SSundeep.Panicker@Sun.COM get_packet(raw_list_t *rawlist, void *buffer, int size, int offset)
77911015SSundeep.Panicker@Sun.COM {
78011015SSundeep.Panicker@Sun.COM 	int retval;
78111015SSundeep.Panicker@Sun.COM 
78211015SSundeep.Panicker@Sun.COM 	retval = raw_memcpy(buffer, rawlist, offset, size);
78311015SSundeep.Panicker@Sun.COM 
78411015SSundeep.Panicker@Sun.COM 	if (retval != -1) {
78511015SSundeep.Panicker@Sun.COM 		return (0);
78611015SSundeep.Panicker@Sun.COM 	}
78711015SSundeep.Panicker@Sun.COM 	return (-1);
78811015SSundeep.Panicker@Sun.COM }
78911015SSundeep.Panicker@Sun.COM 
79011015SSundeep.Panicker@Sun.COM 
79111015SSundeep.Panicker@Sun.COM static int
get_packets(hash_obj_t * seg_hash,raw_list_t * rawlist,int offset,int length)79211015SSundeep.Panicker@Sun.COM get_packets(hash_obj_t *seg_hash, raw_list_t *rawlist, int offset, int length)
79311015SSundeep.Panicker@Sun.COM {
79411015SSundeep.Panicker@Sun.COM 	int tag_size;
79511015SSundeep.Panicker@Sun.COM 	int paylen;
79611015SSundeep.Panicker@Sun.COM 	int retval;
79711015SSundeep.Panicker@Sun.COM 	int seg_limit = 0;
79811015SSundeep.Panicker@Sun.COM 	int pktcnt = 0;
79911015SSundeep.Panicker@Sun.COM 	char *data;
80011015SSundeep.Panicker@Sun.COM 	uint32_t crc;
80111015SSundeep.Panicker@Sun.COM 	uint32_t origcrc;
80211015SSundeep.Panicker@Sun.COM 	fru_tag_t tag;
80311015SSundeep.Panicker@Sun.COM 	hash_obj_t *pkt_hash_obj;
80411015SSundeep.Panicker@Sun.COM 	hash_obj_t *sec_hash;
80511015SSundeep.Panicker@Sun.COM 	fru_segdesc_t *segdesc;
80611015SSundeep.Panicker@Sun.COM 	fru_tagtype_t tagtype;
80711015SSundeep.Panicker@Sun.COM 	char *ignore_flag;
80811015SSundeep.Panicker@Sun.COM 
80911015SSundeep.Panicker@Sun.COM 	retval = get_packet(rawlist, &tag, sizeof (fru_tag_t), offset);
81011015SSundeep.Panicker@Sun.COM 	if (retval == -1) {
81111015SSundeep.Panicker@Sun.COM 		return (-1);
81211015SSundeep.Panicker@Sun.COM 	}
81311015SSundeep.Panicker@Sun.COM 
81411015SSundeep.Panicker@Sun.COM 	/* section hash object */
81511015SSundeep.Panicker@Sun.COM 	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
81611015SSundeep.Panicker@Sun.COM 	    SECTION_TYPE);
81711015SSundeep.Panicker@Sun.COM 
81811015SSundeep.Panicker@Sun.COM 	if (sec_hash == NULL) {
81911015SSundeep.Panicker@Sun.COM 		return (-1);
82011015SSundeep.Panicker@Sun.COM 	}
82111015SSundeep.Panicker@Sun.COM 
82211015SSundeep.Panicker@Sun.COM 	seg_hash->u.seg_obj->trailer_offset = offset;
82311015SSundeep.Panicker@Sun.COM 
82411015SSundeep.Panicker@Sun.COM 	data = (char *)&tag;
82511015SSundeep.Panicker@Sun.COM 	while (data[0] != SEG_TRAILER_TAG) {
82611015SSundeep.Panicker@Sun.COM 		tagtype	= get_tag_type(&tag); /* verify tag type */
82711015SSundeep.Panicker@Sun.COM 		if (tagtype == -1) {
82811015SSundeep.Panicker@Sun.COM 			return (-1);
82911015SSundeep.Panicker@Sun.COM 		}
83011015SSundeep.Panicker@Sun.COM 
83111015SSundeep.Panicker@Sun.COM 		tag_size = get_tag_size(tagtype);
83211015SSundeep.Panicker@Sun.COM 		if (tag_size == -1) {
83311015SSundeep.Panicker@Sun.COM 			return (-1);
83411015SSundeep.Panicker@Sun.COM 		}
83511015SSundeep.Panicker@Sun.COM 
83611015SSundeep.Panicker@Sun.COM 		seg_limit += tag_size;
83711015SSundeep.Panicker@Sun.COM 		if (seg_limit > length) {
83811015SSundeep.Panicker@Sun.COM 			return (-1);
83911015SSundeep.Panicker@Sun.COM 		}
84011015SSundeep.Panicker@Sun.COM 
84111015SSundeep.Panicker@Sun.COM 		paylen = get_payload_length((void *)&tag);
84211015SSundeep.Panicker@Sun.COM 		if (paylen == -1) {
84311015SSundeep.Panicker@Sun.COM 			return (-1);
84411015SSundeep.Panicker@Sun.COM 		}
84511015SSundeep.Panicker@Sun.COM 
84611015SSundeep.Panicker@Sun.COM 		seg_limit += paylen;
84711015SSundeep.Panicker@Sun.COM 		if (seg_limit > length) {
84811015SSundeep.Panicker@Sun.COM 			return (-1);
84911015SSundeep.Panicker@Sun.COM 		}
85011015SSundeep.Panicker@Sun.COM 		if ((offset + tag_size + paylen) >
85111015SSundeep.Panicker@Sun.COM 		    (sec_hash->u.sec_obj->section.offset +
85211015SSundeep.Panicker@Sun.COM 		    sec_hash->u.sec_obj->section.length)) {
85311015SSundeep.Panicker@Sun.COM 			return (-1);
85411015SSundeep.Panicker@Sun.COM 		}
85511015SSundeep.Panicker@Sun.COM 
85611015SSundeep.Panicker@Sun.COM 		pkt_hash_obj = create_packet_hash_object();
85711015SSundeep.Panicker@Sun.COM 		if (pkt_hash_obj == NULL) {
85811015SSundeep.Panicker@Sun.COM 			return (-1);
85911015SSundeep.Panicker@Sun.COM 		}
86011015SSundeep.Panicker@Sun.COM 
86111015SSundeep.Panicker@Sun.COM 		pkt_hash_obj->u.pkt_obj->payload = malloc(paylen);
86211015SSundeep.Panicker@Sun.COM 		if (pkt_hash_obj->u.pkt_obj->payload == NULL) {
86311015SSundeep.Panicker@Sun.COM 			free(pkt_hash_obj);
86411015SSundeep.Panicker@Sun.COM 			return (-1);
86511015SSundeep.Panicker@Sun.COM 		}
86611015SSundeep.Panicker@Sun.COM 
86711015SSundeep.Panicker@Sun.COM 		offset += tag_size;
86811015SSundeep.Panicker@Sun.COM 
86911015SSundeep.Panicker@Sun.COM 		retval = raw_memcpy(pkt_hash_obj->u.pkt_obj->payload, rawlist,
87011015SSundeep.Panicker@Sun.COM 		    offset, paylen);
87111015SSundeep.Panicker@Sun.COM 
87211015SSundeep.Panicker@Sun.COM 		if (retval != paylen) {
87311015SSundeep.Panicker@Sun.COM 			free(pkt_hash_obj->u.pkt_obj->payload);
87411015SSundeep.Panicker@Sun.COM 			free(pkt_hash_obj);
87511015SSundeep.Panicker@Sun.COM 			return (-1);
87611015SSundeep.Panicker@Sun.COM 		}
87711015SSundeep.Panicker@Sun.COM 
87811015SSundeep.Panicker@Sun.COM 		/* don't change this */
87911015SSundeep.Panicker@Sun.COM 		pkt_hash_obj->u.pkt_obj->tag.raw_data = 0;
88011015SSundeep.Panicker@Sun.COM 		(void) memcpy(&pkt_hash_obj->u.pkt_obj->tag, &tag, tag_size);
88111015SSundeep.Panicker@Sun.COM 		pkt_hash_obj->u.pkt_obj->paylen = paylen;
88211015SSundeep.Panicker@Sun.COM 		pkt_hash_obj->u.pkt_obj->tag_size = tag_size;
88311015SSundeep.Panicker@Sun.COM 		pkt_hash_obj->u.pkt_obj->payload_offset = offset;
88411015SSundeep.Panicker@Sun.COM 
88511015SSundeep.Panicker@Sun.COM 		offset += paylen;
88611015SSundeep.Panicker@Sun.COM 
88711015SSundeep.Panicker@Sun.COM 		add_hashobject_to_hashtable(pkt_hash_obj);
88811015SSundeep.Panicker@Sun.COM 		add_to_pkt_object_list(seg_hash, pkt_hash_obj);
88911015SSundeep.Panicker@Sun.COM 
89011015SSundeep.Panicker@Sun.COM 		pktcnt++;
89111015SSundeep.Panicker@Sun.COM 
89211015SSundeep.Panicker@Sun.COM 		retval = get_packet(rawlist, &tag, sizeof (fru_tag_t),
89311015SSundeep.Panicker@Sun.COM 		    offset);
89411015SSundeep.Panicker@Sun.COM 		if (retval == -1) {
89511015SSundeep.Panicker@Sun.COM 			return (retval);
89611015SSundeep.Panicker@Sun.COM 		}
89711015SSundeep.Panicker@Sun.COM 
89811015SSundeep.Panicker@Sun.COM 		data = (char *)&tag;
89911015SSundeep.Panicker@Sun.COM 	}
90011015SSundeep.Panicker@Sun.COM 
90111015SSundeep.Panicker@Sun.COM 	segdesc	= (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor;
90211015SSundeep.Panicker@Sun.COM 
90311015SSundeep.Panicker@Sun.COM 	seg_hash->u.seg_obj->trailer_offset = offset;
90411015SSundeep.Panicker@Sun.COM 
90511015SSundeep.Panicker@Sun.COM 	if (!segdesc->field.ignore_checksum)  {
90611015SSundeep.Panicker@Sun.COM 		crc = get_checksum_crc(seg_hash, seg_limit);
90711015SSundeep.Panicker@Sun.COM 		offset = seg_hash->u.seg_obj->segment.offset;
90811015SSundeep.Panicker@Sun.COM 
90911015SSundeep.Panicker@Sun.COM 		retval = raw_memcpy(&origcrc, rawlist, offset + seg_limit + 1,
91011015SSundeep.Panicker@Sun.COM 		    sizeof (origcrc));
91111015SSundeep.Panicker@Sun.COM 
91211015SSundeep.Panicker@Sun.COM 		ignore_flag = getenv(IGNORE_CHECK);
91311015SSundeep.Panicker@Sun.COM 		if (ignore_flag != NULL) {
91411015SSundeep.Panicker@Sun.COM 			return (pktcnt);
91511015SSundeep.Panicker@Sun.COM 		}
91611015SSundeep.Panicker@Sun.COM 
91711015SSundeep.Panicker@Sun.COM 		if (retval != sizeof (origcrc)) {
91811015SSundeep.Panicker@Sun.COM 			return (-1);
91911015SSundeep.Panicker@Sun.COM 		}
92011015SSundeep.Panicker@Sun.COM 
92111015SSundeep.Panicker@Sun.COM 		origcrc = BE_32(origcrc);
92211015SSundeep.Panicker@Sun.COM 		if (origcrc != crc) {
92311015SSundeep.Panicker@Sun.COM 			seg_hash->u.seg_obj->trailer_offset = offset;
92411015SSundeep.Panicker@Sun.COM 			return (-1);
92511015SSundeep.Panicker@Sun.COM 		}
92611015SSundeep.Panicker@Sun.COM 	}
92711015SSundeep.Panicker@Sun.COM 
92811015SSundeep.Panicker@Sun.COM 	return (pktcnt);
92911015SSundeep.Panicker@Sun.COM }
93011015SSundeep.Panicker@Sun.COM 
93111015SSundeep.Panicker@Sun.COM /* ARGSUSED */
93211015SSundeep.Panicker@Sun.COM int
fru_get_num_sections(container_hdl_t container,door_cred_t * cred)93311015SSundeep.Panicker@Sun.COM fru_get_num_sections(container_hdl_t container, door_cred_t *cred)
93411015SSundeep.Panicker@Sun.COM {
93511015SSundeep.Panicker@Sun.COM 	hash_obj_t *hash_object;
93611015SSundeep.Panicker@Sun.COM 
93711015SSundeep.Panicker@Sun.COM 	hash_object = lookup_handle_object(container, CONTAINER_TYPE);
93811015SSundeep.Panicker@Sun.COM 	if (hash_object == NULL) {
93911015SSundeep.Panicker@Sun.COM 		return (-1);
94011015SSundeep.Panicker@Sun.COM 	}
94111015SSundeep.Panicker@Sun.COM 
94211015SSundeep.Panicker@Sun.COM 	return (hash_object->u.cont_obj->num_of_section);
94311015SSundeep.Panicker@Sun.COM }
94411015SSundeep.Panicker@Sun.COM 
94511015SSundeep.Panicker@Sun.COM /* ARGSUSED */
94611015SSundeep.Panicker@Sun.COM int
fru_get_num_segments(section_hdl_t section,door_cred_t * cred)94711015SSundeep.Panicker@Sun.COM fru_get_num_segments(section_hdl_t section, door_cred_t *cred)
94811015SSundeep.Panicker@Sun.COM {
94911015SSundeep.Panicker@Sun.COM 	hash_obj_t *sec_object;
95011015SSundeep.Panicker@Sun.COM 	section_obj_t *sec_obj;
95111015SSundeep.Panicker@Sun.COM 
95211015SSundeep.Panicker@Sun.COM 	sec_object = lookup_handle_object(section, SECTION_TYPE);
95311015SSundeep.Panicker@Sun.COM 	if (sec_object == NULL) {
95411015SSundeep.Panicker@Sun.COM 		return (-1);
95511015SSundeep.Panicker@Sun.COM 	}
95611015SSundeep.Panicker@Sun.COM 
95711015SSundeep.Panicker@Sun.COM 	sec_obj	= sec_object->u.sec_obj;
95811015SSundeep.Panicker@Sun.COM 	if (sec_obj == NULL) {
95911015SSundeep.Panicker@Sun.COM 		return (-1);
96011015SSundeep.Panicker@Sun.COM 	}
96111015SSundeep.Panicker@Sun.COM 
96211015SSundeep.Panicker@Sun.COM 	return (sec_obj->num_of_segment);
96311015SSundeep.Panicker@Sun.COM }
96411015SSundeep.Panicker@Sun.COM 
96511015SSundeep.Panicker@Sun.COM /* ARGSUSED */
96611015SSundeep.Panicker@Sun.COM int
fru_get_num_packets(segment_hdl_t segment,door_cred_t * cred)96711015SSundeep.Panicker@Sun.COM fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred)
96811015SSundeep.Panicker@Sun.COM {
96911015SSundeep.Panicker@Sun.COM 	int pktcnt;
97011015SSundeep.Panicker@Sun.COM 	int length;
97111015SSundeep.Panicker@Sun.COM 	uint16_t offset;
97211015SSundeep.Panicker@Sun.COM 	hash_obj_t *cont_hash_obj;
97311015SSundeep.Panicker@Sun.COM 	hash_obj_t *seg_hash;
97411015SSundeep.Panicker@Sun.COM 	hash_obj_t *sec_hash;
97511015SSundeep.Panicker@Sun.COM 	fru_segdesc_t *segdesc;
97611015SSundeep.Panicker@Sun.COM 	segment_obj_t *segment_object;
97711015SSundeep.Panicker@Sun.COM 
97811015SSundeep.Panicker@Sun.COM 	seg_hash = lookup_handle_object(segment, SEGMENT_TYPE);
97911015SSundeep.Panicker@Sun.COM 	if (seg_hash == NULL) {
98011015SSundeep.Panicker@Sun.COM 		return (-1);
98111015SSundeep.Panicker@Sun.COM 	}
98211015SSundeep.Panicker@Sun.COM 
98311015SSundeep.Panicker@Sun.COM 	segment_object = seg_hash->u.seg_obj;
98411015SSundeep.Panicker@Sun.COM 	if (segment_object == NULL) {
98511015SSundeep.Panicker@Sun.COM 		return (-1);
98611015SSundeep.Panicker@Sun.COM 	}
98711015SSundeep.Panicker@Sun.COM 
98811015SSundeep.Panicker@Sun.COM 	segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor;
98911015SSundeep.Panicker@Sun.COM 	if (segdesc->field.opaque) {
99011015SSundeep.Panicker@Sun.COM 		return (0);
99111015SSundeep.Panicker@Sun.COM 	}
99211015SSundeep.Panicker@Sun.COM 
99311015SSundeep.Panicker@Sun.COM 	offset = segment_object->segment.offset;
99411015SSundeep.Panicker@Sun.COM 	length = segment_object->segment.length;
99511015SSundeep.Panicker@Sun.COM 
99611015SSundeep.Panicker@Sun.COM 	cont_hash_obj = get_container_hash_object(SEGMENT_TYPE,
99711015SSundeep.Panicker@Sun.COM 	    segment_object->section_hdl);
99811015SSundeep.Panicker@Sun.COM 
99911015SSundeep.Panicker@Sun.COM 	if (cont_hash_obj == NULL) {
100011015SSundeep.Panicker@Sun.COM 		return (-1);
100111015SSundeep.Panicker@Sun.COM 	}
100211015SSundeep.Panicker@Sun.COM 
100311015SSundeep.Panicker@Sun.COM 	if (seg_hash->u.seg_obj->pkt_obj_list != NULL) {
100411015SSundeep.Panicker@Sun.COM 		return (segment_object->num_of_packets);
100511015SSundeep.Panicker@Sun.COM 	}
100611015SSundeep.Panicker@Sun.COM 	/* section hash object */
100711015SSundeep.Panicker@Sun.COM 	sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl,
100811015SSundeep.Panicker@Sun.COM 	    SECTION_TYPE);
100911015SSundeep.Panicker@Sun.COM 	if (sec_hash == NULL) {
101011015SSundeep.Panicker@Sun.COM 		return (-1);
101111015SSundeep.Panicker@Sun.COM 	}
101211015SSundeep.Panicker@Sun.COM 
101311015SSundeep.Panicker@Sun.COM 	/* valid segment header b'cos crc8 already validated */
101411015SSundeep.Panicker@Sun.COM 	if (offset < sec_hash->u.sec_obj->section.offset) {
101511015SSundeep.Panicker@Sun.COM 		return (-1);
101611015SSundeep.Panicker@Sun.COM 	}
101711015SSundeep.Panicker@Sun.COM 
101811015SSundeep.Panicker@Sun.COM 	segment_object->num_of_packets = 0;
101911015SSundeep.Panicker@Sun.COM 
102011015SSundeep.Panicker@Sun.COM 	pktcnt = get_packets(seg_hash, g_raw, offset, length);
102111015SSundeep.Panicker@Sun.COM 	if (pktcnt == -1) {
102211015SSundeep.Panicker@Sun.COM 		free_pkt_object_list(seg_hash);
102311015SSundeep.Panicker@Sun.COM 		seg_hash->u.seg_obj->pkt_obj_list = NULL;
102411015SSundeep.Panicker@Sun.COM 	}
102511015SSundeep.Panicker@Sun.COM 
102611015SSundeep.Panicker@Sun.COM 	segment_object->num_of_packets = pktcnt;
102711015SSundeep.Panicker@Sun.COM 
102811015SSundeep.Panicker@Sun.COM 	return (segment_object->num_of_packets);
102911015SSundeep.Panicker@Sun.COM }
103011015SSundeep.Panicker@Sun.COM 
103111015SSundeep.Panicker@Sun.COM /* ARGSUSED */
103211015SSundeep.Panicker@Sun.COM int
fru_get_packets(segment_hdl_t segment,packet_t * packet,int maxpackets,door_cred_t * cred)103311015SSundeep.Panicker@Sun.COM fru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets,
103411015SSundeep.Panicker@Sun.COM     door_cred_t *cred)
103511015SSundeep.Panicker@Sun.COM {
103611015SSundeep.Panicker@Sun.COM 	int count;
103711015SSundeep.Panicker@Sun.COM 	hash_obj_t *seg_hash_obj;
103811015SSundeep.Panicker@Sun.COM 	hash_obj_t *pkt_hash_obj;
103911015SSundeep.Panicker@Sun.COM 
104011015SSundeep.Panicker@Sun.COM 	/* segment hash object */
104111015SSundeep.Panicker@Sun.COM 	seg_hash_obj = lookup_handle_object(segment, SEGMENT_TYPE);
104211015SSundeep.Panicker@Sun.COM 	if (seg_hash_obj == NULL) {
104311015SSundeep.Panicker@Sun.COM 		return (-1);
104411015SSundeep.Panicker@Sun.COM 	}
104511015SSundeep.Panicker@Sun.COM 
104611015SSundeep.Panicker@Sun.COM 	if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) {
104711015SSundeep.Panicker@Sun.COM 		return (-1);
104811015SSundeep.Panicker@Sun.COM 	}
104911015SSundeep.Panicker@Sun.COM 
105011015SSundeep.Panicker@Sun.COM 	pkt_hash_obj = seg_hash_obj->u.seg_obj->pkt_obj_list;
105111015SSundeep.Panicker@Sun.COM 	if (pkt_hash_obj == NULL) {
105211015SSundeep.Panicker@Sun.COM 		return (-1);
105311015SSundeep.Panicker@Sun.COM 	}
105411015SSundeep.Panicker@Sun.COM 
105511015SSundeep.Panicker@Sun.COM 	for (count = 0; count < maxpackets; count++, packet++) {
105611015SSundeep.Panicker@Sun.COM 		packet->handle	= pkt_hash_obj->obj_hdl;
105711015SSundeep.Panicker@Sun.COM 		packet->tag = 0;
105811015SSundeep.Panicker@Sun.COM 		(void) memcpy(&packet->tag, &pkt_hash_obj->u.pkt_obj->tag,
105911015SSundeep.Panicker@Sun.COM 		    pkt_hash_obj->u.pkt_obj->tag_size);
106011015SSundeep.Panicker@Sun.COM 		pkt_hash_obj = pkt_hash_obj->u.pkt_obj->next;
106111015SSundeep.Panicker@Sun.COM 	}
106211015SSundeep.Panicker@Sun.COM 
106311015SSundeep.Panicker@Sun.COM 	return (0);
106411015SSundeep.Panicker@Sun.COM }
106511015SSundeep.Panicker@Sun.COM 
106611015SSundeep.Panicker@Sun.COM /* ARGSUSED */
106711015SSundeep.Panicker@Sun.COM ssize_t
fru_get_payload(packet_hdl_t packet,void * buffer,size_t nbytes,door_cred_t * cred)106811015SSundeep.Panicker@Sun.COM fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes,
106911015SSundeep.Panicker@Sun.COM     door_cred_t *cred)
107011015SSundeep.Panicker@Sun.COM {
107111015SSundeep.Panicker@Sun.COM 	hash_obj_t *packet_hash_obj;
107211015SSundeep.Panicker@Sun.COM 
107311015SSundeep.Panicker@Sun.COM 	/* packet hash object */
107411015SSundeep.Panicker@Sun.COM 	packet_hash_obj	= lookup_handle_object(packet, PACKET_TYPE);
107511015SSundeep.Panicker@Sun.COM 	if (packet_hash_obj == NULL) {
107611015SSundeep.Panicker@Sun.COM 		return (-1);
107711015SSundeep.Panicker@Sun.COM 	}
107811015SSundeep.Panicker@Sun.COM 
107911015SSundeep.Panicker@Sun.COM 	/* verify payload length */
108011015SSundeep.Panicker@Sun.COM 	if (nbytes != packet_hash_obj->u.pkt_obj->paylen) {
108111015SSundeep.Panicker@Sun.COM 		return (-1);
108211015SSundeep.Panicker@Sun.COM 	}
108311015SSundeep.Panicker@Sun.COM 
108411015SSundeep.Panicker@Sun.COM 	(void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes);
108511015SSundeep.Panicker@Sun.COM 	return (nbytes);
108611015SSundeep.Panicker@Sun.COM }
108711015SSundeep.Panicker@Sun.COM 
108811015SSundeep.Panicker@Sun.COM 
108911015SSundeep.Panicker@Sun.COM container_hdl_t
open_raw_data(raw_list_t * node)109011015SSundeep.Panicker@Sun.COM open_raw_data(raw_list_t *node)
109111015SSundeep.Panicker@Sun.COM {
109211015SSundeep.Panicker@Sun.COM 	char *cont_conf_file = NULL;
109311015SSundeep.Panicker@Sun.COM 	hash_obj_t *cont_hash_obj;
109411015SSundeep.Panicker@Sun.COM 	hash_obj_t *sec_hash_obj;
109511015SSundeep.Panicker@Sun.COM 	container_info_t cont_info;
109611015SSundeep.Panicker@Sun.COM 	int retval;
109711015SSundeep.Panicker@Sun.COM 	int count;
109811015SSundeep.Panicker@Sun.COM 
109911015SSundeep.Panicker@Sun.COM 	cont_hash_obj = create_container_hash_object();
110011015SSundeep.Panicker@Sun.COM 	if (cont_hash_obj == NULL) {
110111015SSundeep.Panicker@Sun.COM 		return (NULL);
110211015SSundeep.Panicker@Sun.COM 	}
110311015SSundeep.Panicker@Sun.COM 
110411015SSundeep.Panicker@Sun.COM 	add_hashobject_to_hashtable(cont_hash_obj);
110511015SSundeep.Panicker@Sun.COM 
110611015SSundeep.Panicker@Sun.COM 	(void) strncpy(cont_hash_obj->u.cont_obj->device_pathname, "unknown",
110711015SSundeep.Panicker@Sun.COM 	    sizeof (cont_hash_obj->u.cont_obj->device_pathname));
110811015SSundeep.Panicker@Sun.COM 
110911015SSundeep.Panicker@Sun.COM 	cont_conf_file = getenv(FRU_CONT_CONF_ENV_VAR);
111011015SSundeep.Panicker@Sun.COM 	if (cont_conf_file == NULL) {
111111015SSundeep.Panicker@Sun.COM 		cont_conf_file = FRU_CONT_CONF_SPARC;
111211015SSundeep.Panicker@Sun.COM 		retval = get_container_info(cont_conf_file, node->cont_type,
111311015SSundeep.Panicker@Sun.COM 		    &cont_info);
111411015SSundeep.Panicker@Sun.COM 		if (retval < 0) {
111511015SSundeep.Panicker@Sun.COM 			cont_conf_file = FRU_CONT_CONF_X86;
111611015SSundeep.Panicker@Sun.COM 			retval = get_container_info(cont_conf_file,
111711015SSundeep.Panicker@Sun.COM 			    node->cont_type, &cont_info);
111811015SSundeep.Panicker@Sun.COM 		}
111911015SSundeep.Panicker@Sun.COM 	} else {
112011015SSundeep.Panicker@Sun.COM 		retval = get_container_info(cont_conf_file, node->cont_type,
112111015SSundeep.Panicker@Sun.COM 		    &cont_info);
112211015SSundeep.Panicker@Sun.COM 	}
112311015SSundeep.Panicker@Sun.COM 
112411015SSundeep.Panicker@Sun.COM 	if (retval < 0) {
112511015SSundeep.Panicker@Sun.COM 		return (NULL);
112611015SSundeep.Panicker@Sun.COM 	}
112711015SSundeep.Panicker@Sun.COM 
112811015SSundeep.Panicker@Sun.COM 	cont_hash_obj->u.cont_obj->num_of_section = cont_info.num_sections;
112911015SSundeep.Panicker@Sun.COM 	cont_hash_obj->u.cont_obj->sec_obj_list = NULL;
113011015SSundeep.Panicker@Sun.COM 
113111015SSundeep.Panicker@Sun.COM 	for (count = 0; count < cont_info.num_sections; count++) {
113211015SSundeep.Panicker@Sun.COM 		sec_hash_obj = create_section_hash_object();
113311015SSundeep.Panicker@Sun.COM 		if (sec_hash_obj == NULL) {
113411015SSundeep.Panicker@Sun.COM 			return (NULL);
113511015SSundeep.Panicker@Sun.COM 		}
113611015SSundeep.Panicker@Sun.COM 
113711015SSundeep.Panicker@Sun.COM 		add_hashobject_to_hashtable(sec_hash_obj);
113811015SSundeep.Panicker@Sun.COM 
113911015SSundeep.Panicker@Sun.COM 		sec_hash_obj->u.sec_obj->section.offset =
114011015SSundeep.Panicker@Sun.COM 		    cont_info.section_info[count].address;
114111015SSundeep.Panicker@Sun.COM 
114211015SSundeep.Panicker@Sun.COM 		sec_hash_obj->u.sec_obj->section.protection =
114311015SSundeep.Panicker@Sun.COM 		    cont_info.section_info[count].description.field.read_only;
114411015SSundeep.Panicker@Sun.COM 
114511015SSundeep.Panicker@Sun.COM 		sec_hash_obj->u.sec_obj->section.length =
114611015SSundeep.Panicker@Sun.COM 		    cont_info.section_info[count].size;
114711015SSundeep.Panicker@Sun.COM 		sec_hash_obj->u.sec_obj->section.version =
114811015SSundeep.Panicker@Sun.COM 		    cont_info.header_ver;
114911015SSundeep.Panicker@Sun.COM 
115011015SSundeep.Panicker@Sun.COM 		add_to_sec_object_list(cont_hash_obj, sec_hash_obj);
115111015SSundeep.Panicker@Sun.COM 	}
115211015SSundeep.Panicker@Sun.COM 
115311015SSundeep.Panicker@Sun.COM 	return (cont_hash_obj->obj_hdl);
115411015SSundeep.Panicker@Sun.COM }
115511015SSundeep.Panicker@Sun.COM 
115611015SSundeep.Panicker@Sun.COM 
115711015SSundeep.Panicker@Sun.COM int
fru_close_container(container_hdl_t container)115811015SSundeep.Panicker@Sun.COM fru_close_container(container_hdl_t container)
115911015SSundeep.Panicker@Sun.COM {
116011015SSundeep.Panicker@Sun.COM 	hash_obj_t *hash_obj;
116111015SSundeep.Panicker@Sun.COM 	hash_obj_t *prev_hash;
116211015SSundeep.Panicker@Sun.COM 	hash_obj_t *sec_hash_obj;
116311015SSundeep.Panicker@Sun.COM 	handle_t obj_hdl;
116411015SSundeep.Panicker@Sun.COM 
116511015SSundeep.Panicker@Sun.COM 	/* lookup for container hash object */
116611015SSundeep.Panicker@Sun.COM 	hash_obj = lookup_handle_object(container, CONTAINER_TYPE);
116711015SSundeep.Panicker@Sun.COM 	if (hash_obj == NULL) {
116811015SSundeep.Panicker@Sun.COM 		return (0);
116911015SSundeep.Panicker@Sun.COM 	}
117011015SSundeep.Panicker@Sun.COM 
117111015SSundeep.Panicker@Sun.COM 	/* points to section object list */
117211015SSundeep.Panicker@Sun.COM 	sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list;
117311015SSundeep.Panicker@Sun.COM 
117411015SSundeep.Panicker@Sun.COM 	/* traverse section object list */
117511015SSundeep.Panicker@Sun.COM 	while (sec_hash_obj != NULL) {
117611015SSundeep.Panicker@Sun.COM 
117711015SSundeep.Panicker@Sun.COM 		/* traverse segment hash object in the section */
117811015SSundeep.Panicker@Sun.COM 		while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) {
117911015SSundeep.Panicker@Sun.COM 			/* object handle of the segment hash object */
118011015SSundeep.Panicker@Sun.COM 			obj_hdl	=
118111015SSundeep.Panicker@Sun.COM 			    sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl;
118211015SSundeep.Panicker@Sun.COM 			free_segment_hash(obj_hdl, sec_hash_obj);
118311015SSundeep.Panicker@Sun.COM 		}
118411015SSundeep.Panicker@Sun.COM 
118511015SSundeep.Panicker@Sun.COM 		/* going to free section hash object, relink the hash object */
118611015SSundeep.Panicker@Sun.COM 		if (sec_hash_obj->prev == NULL) {
118711015SSundeep.Panicker@Sun.COM 			hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] =
118811015SSundeep.Panicker@Sun.COM 			    sec_hash_obj->next;
118911015SSundeep.Panicker@Sun.COM 			if (sec_hash_obj->next != NULL) {
119011015SSundeep.Panicker@Sun.COM 				sec_hash_obj->next->prev = NULL;
119111015SSundeep.Panicker@Sun.COM 			}
119211015SSundeep.Panicker@Sun.COM 		} else {
119311015SSundeep.Panicker@Sun.COM 			sec_hash_obj->prev->next = sec_hash_obj->next;
119411015SSundeep.Panicker@Sun.COM 			if (sec_hash_obj->next != NULL) {
119511015SSundeep.Panicker@Sun.COM 				sec_hash_obj->next->prev = sec_hash_obj->prev;
119611015SSundeep.Panicker@Sun.COM 			}
119711015SSundeep.Panicker@Sun.COM 		}
119811015SSundeep.Panicker@Sun.COM 
119911015SSundeep.Panicker@Sun.COM 		prev_hash = sec_hash_obj;
120011015SSundeep.Panicker@Sun.COM 		sec_hash_obj = sec_hash_obj->u.sec_obj->next;
120111015SSundeep.Panicker@Sun.COM 
1202*12126SHyon.Kim@Sun.COM 		free(prev_hash->u.sec_obj); /* free section hash object */
120311015SSundeep.Panicker@Sun.COM 		free(prev_hash); /* free section hash */
120411015SSundeep.Panicker@Sun.COM 	}
120511015SSundeep.Panicker@Sun.COM 
120611015SSundeep.Panicker@Sun.COM 	/* free container hash object */
120711015SSundeep.Panicker@Sun.COM 	if (hash_obj->prev == NULL) {
120811015SSundeep.Panicker@Sun.COM 		hash_table[(hash_obj->obj_hdl % TABLE_SIZE)] =
120911015SSundeep.Panicker@Sun.COM 		    hash_obj->next;
121011015SSundeep.Panicker@Sun.COM 		if (hash_obj->next != NULL) {
121111015SSundeep.Panicker@Sun.COM 			hash_obj->next->prev = NULL;
121211015SSundeep.Panicker@Sun.COM 		}
121311015SSundeep.Panicker@Sun.COM 	} else {
121411015SSundeep.Panicker@Sun.COM 		hash_obj->prev->next = hash_obj->next;
121511015SSundeep.Panicker@Sun.COM 		if (hash_obj->next != NULL) {
121611015SSundeep.Panicker@Sun.COM 			hash_obj->next->prev = hash_obj->prev;
121711015SSundeep.Panicker@Sun.COM 		}
121811015SSundeep.Panicker@Sun.COM 	}
121911015SSundeep.Panicker@Sun.COM 
122011015SSundeep.Panicker@Sun.COM 	free(hash_obj->u.cont_obj);
122111015SSundeep.Panicker@Sun.COM 	free(hash_obj);
122211015SSundeep.Panicker@Sun.COM 
122311015SSundeep.Panicker@Sun.COM 	return (0);
122411015SSundeep.Panicker@Sun.COM }
1225