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