1*7c478bd9Sstevel@tonic-gate /* 2*7c478bd9Sstevel@tonic-gate * CDDL HEADER START 3*7c478bd9Sstevel@tonic-gate * 4*7c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*7c478bd9Sstevel@tonic-gate * Common Development and Distribution License, Version 1.0 only 6*7c478bd9Sstevel@tonic-gate * (the "License"). You may not use this file except in compliance 7*7c478bd9Sstevel@tonic-gate * with the License. 8*7c478bd9Sstevel@tonic-gate * 9*7c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*7c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 11*7c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 12*7c478bd9Sstevel@tonic-gate * and limitations under the License. 13*7c478bd9Sstevel@tonic-gate * 14*7c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 15*7c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*7c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 17*7c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 18*7c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 19*7c478bd9Sstevel@tonic-gate * 20*7c478bd9Sstevel@tonic-gate * CDDL HEADER END 21*7c478bd9Sstevel@tonic-gate */ 22*7c478bd9Sstevel@tonic-gate /* 23*7c478bd9Sstevel@tonic-gate * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24*7c478bd9Sstevel@tonic-gate * Use is subject to license terms. 25*7c478bd9Sstevel@tonic-gate */ 26*7c478bd9Sstevel@tonic-gate 27*7c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 28*7c478bd9Sstevel@tonic-gate 29*7c478bd9Sstevel@tonic-gate #include <limits.h> 30*7c478bd9Sstevel@tonic-gate #include <alloca.h> 31*7c478bd9Sstevel@tonic-gate #include "fru_access_impl.h" 32*7c478bd9Sstevel@tonic-gate 33*7c478bd9Sstevel@tonic-gate #pragma init(initialize_fruaccess) /* .init section */ 34*7c478bd9Sstevel@tonic-gate 35*7c478bd9Sstevel@tonic-gate static hash_obj_t *hash_table[TABLE_SIZE]; 36*7c478bd9Sstevel@tonic-gate 37*7c478bd9Sstevel@tonic-gate /* 38*7c478bd9Sstevel@tonic-gate * seeprom is the driver_name for the SEEPROM device drivers in excalibur 39*7c478bd9Sstevel@tonic-gate * Define the devfsadm command to load the seeprom drivers if open fails. 40*7c478bd9Sstevel@tonic-gate */ 41*7c478bd9Sstevel@tonic-gate 42*7c478bd9Sstevel@tonic-gate static char devfsadm_cmd[] = "/usr/sbin/devfsadm -i seeprom"; 43*7c478bd9Sstevel@tonic-gate 44*7c478bd9Sstevel@tonic-gate /* this routine initialize the hash table. */ 45*7c478bd9Sstevel@tonic-gate 46*7c478bd9Sstevel@tonic-gate static void 47*7c478bd9Sstevel@tonic-gate initialize_fruaccess(void) 48*7c478bd9Sstevel@tonic-gate { 49*7c478bd9Sstevel@tonic-gate int count; 50*7c478bd9Sstevel@tonic-gate for (count = 0; count < TABLE_SIZE; count++) { 51*7c478bd9Sstevel@tonic-gate hash_table[count] = NULL; 52*7c478bd9Sstevel@tonic-gate } 53*7c478bd9Sstevel@tonic-gate } 54*7c478bd9Sstevel@tonic-gate 55*7c478bd9Sstevel@tonic-gate /* 56*7c478bd9Sstevel@tonic-gate * called to lookup hash object for specified handle in the hash table. 57*7c478bd9Sstevel@tonic-gate * 58*7c478bd9Sstevel@tonic-gate */ 59*7c478bd9Sstevel@tonic-gate 60*7c478bd9Sstevel@tonic-gate static hash_obj_t * 61*7c478bd9Sstevel@tonic-gate lookup_handle_object(handle_t handle, int object_type) 62*7c478bd9Sstevel@tonic-gate { 63*7c478bd9Sstevel@tonic-gate handle_t index_to_hash; 64*7c478bd9Sstevel@tonic-gate hash_obj_t *first_hash_obj; 65*7c478bd9Sstevel@tonic-gate hash_obj_t *next_hash_obj; 66*7c478bd9Sstevel@tonic-gate 67*7c478bd9Sstevel@tonic-gate index_to_hash = (handle % TABLE_SIZE); 68*7c478bd9Sstevel@tonic-gate 69*7c478bd9Sstevel@tonic-gate first_hash_obj = hash_table[index_to_hash]; 70*7c478bd9Sstevel@tonic-gate for (next_hash_obj = first_hash_obj; next_hash_obj != NULL; 71*7c478bd9Sstevel@tonic-gate next_hash_obj = next_hash_obj->next) { 72*7c478bd9Sstevel@tonic-gate if ((handle == next_hash_obj->obj_hdl) && 73*7c478bd9Sstevel@tonic-gate (object_type == next_hash_obj->object_type)) { 74*7c478bd9Sstevel@tonic-gate return (next_hash_obj); 75*7c478bd9Sstevel@tonic-gate } 76*7c478bd9Sstevel@tonic-gate } 77*7c478bd9Sstevel@tonic-gate return (NULL); 78*7c478bd9Sstevel@tonic-gate } 79*7c478bd9Sstevel@tonic-gate 80*7c478bd9Sstevel@tonic-gate /* called to allocate container hash object */ 81*7c478bd9Sstevel@tonic-gate 82*7c478bd9Sstevel@tonic-gate static hash_obj_t * 83*7c478bd9Sstevel@tonic-gate create_container_hash_object(void) 84*7c478bd9Sstevel@tonic-gate { 85*7c478bd9Sstevel@tonic-gate hash_obj_t *hash_obj; 86*7c478bd9Sstevel@tonic-gate container_obj_t *cont_obj; 87*7c478bd9Sstevel@tonic-gate 88*7c478bd9Sstevel@tonic-gate cont_obj = malloc(sizeof (container_obj_t)); 89*7c478bd9Sstevel@tonic-gate if (cont_obj == NULL) { 90*7c478bd9Sstevel@tonic-gate return (NULL); 91*7c478bd9Sstevel@tonic-gate } 92*7c478bd9Sstevel@tonic-gate 93*7c478bd9Sstevel@tonic-gate hash_obj = malloc(sizeof (hash_obj_t)); 94*7c478bd9Sstevel@tonic-gate if (hash_obj == NULL) { 95*7c478bd9Sstevel@tonic-gate free(cont_obj); 96*7c478bd9Sstevel@tonic-gate return (NULL); 97*7c478bd9Sstevel@tonic-gate } 98*7c478bd9Sstevel@tonic-gate 99*7c478bd9Sstevel@tonic-gate cont_obj->sec_obj_list = NULL; 100*7c478bd9Sstevel@tonic-gate 101*7c478bd9Sstevel@tonic-gate hash_obj->object_type = CONTAINER_TYPE; 102*7c478bd9Sstevel@tonic-gate hash_obj->u.cont_obj = cont_obj; 103*7c478bd9Sstevel@tonic-gate hash_obj->next = NULL; 104*7c478bd9Sstevel@tonic-gate hash_obj->prev = NULL; 105*7c478bd9Sstevel@tonic-gate 106*7c478bd9Sstevel@tonic-gate return (hash_obj); 107*7c478bd9Sstevel@tonic-gate } 108*7c478bd9Sstevel@tonic-gate 109*7c478bd9Sstevel@tonic-gate /* called to allocate section hash object */ 110*7c478bd9Sstevel@tonic-gate 111*7c478bd9Sstevel@tonic-gate static hash_obj_t * 112*7c478bd9Sstevel@tonic-gate create_section_hash_object(void) 113*7c478bd9Sstevel@tonic-gate { 114*7c478bd9Sstevel@tonic-gate hash_obj_t *hash_obj; 115*7c478bd9Sstevel@tonic-gate section_obj_t *sec_obj; 116*7c478bd9Sstevel@tonic-gate 117*7c478bd9Sstevel@tonic-gate sec_obj = malloc(sizeof (section_obj_t)); 118*7c478bd9Sstevel@tonic-gate if (sec_obj == NULL) { 119*7c478bd9Sstevel@tonic-gate return (NULL); 120*7c478bd9Sstevel@tonic-gate } 121*7c478bd9Sstevel@tonic-gate 122*7c478bd9Sstevel@tonic-gate hash_obj = malloc(sizeof (hash_obj_t)); 123*7c478bd9Sstevel@tonic-gate if (hash_obj == NULL) { 124*7c478bd9Sstevel@tonic-gate free(sec_obj); 125*7c478bd9Sstevel@tonic-gate return (NULL); 126*7c478bd9Sstevel@tonic-gate } 127*7c478bd9Sstevel@tonic-gate 128*7c478bd9Sstevel@tonic-gate sec_obj->next = NULL; 129*7c478bd9Sstevel@tonic-gate sec_obj->seg_obj_list = NULL; 130*7c478bd9Sstevel@tonic-gate 131*7c478bd9Sstevel@tonic-gate hash_obj->u.sec_obj = sec_obj; 132*7c478bd9Sstevel@tonic-gate hash_obj->object_type = SECTION_TYPE; 133*7c478bd9Sstevel@tonic-gate hash_obj->next = NULL; 134*7c478bd9Sstevel@tonic-gate hash_obj->prev = NULL; 135*7c478bd9Sstevel@tonic-gate 136*7c478bd9Sstevel@tonic-gate return (hash_obj); 137*7c478bd9Sstevel@tonic-gate } 138*7c478bd9Sstevel@tonic-gate 139*7c478bd9Sstevel@tonic-gate /* called to allocate segment hash object */ 140*7c478bd9Sstevel@tonic-gate 141*7c478bd9Sstevel@tonic-gate static hash_obj_t * 142*7c478bd9Sstevel@tonic-gate create_segment_hash_object(void) 143*7c478bd9Sstevel@tonic-gate { 144*7c478bd9Sstevel@tonic-gate hash_obj_t *hash_obj; 145*7c478bd9Sstevel@tonic-gate segment_obj_t *seg_obj; 146*7c478bd9Sstevel@tonic-gate 147*7c478bd9Sstevel@tonic-gate seg_obj = malloc(sizeof (segment_obj_t)); 148*7c478bd9Sstevel@tonic-gate if (seg_obj == NULL) { 149*7c478bd9Sstevel@tonic-gate return (NULL); 150*7c478bd9Sstevel@tonic-gate } 151*7c478bd9Sstevel@tonic-gate 152*7c478bd9Sstevel@tonic-gate hash_obj = malloc(sizeof (hash_obj_t)); 153*7c478bd9Sstevel@tonic-gate if (hash_obj == NULL) { 154*7c478bd9Sstevel@tonic-gate free(seg_obj); 155*7c478bd9Sstevel@tonic-gate return (NULL); 156*7c478bd9Sstevel@tonic-gate } 157*7c478bd9Sstevel@tonic-gate 158*7c478bd9Sstevel@tonic-gate seg_obj->next = NULL; 159*7c478bd9Sstevel@tonic-gate seg_obj->pkt_obj_list = NULL; 160*7c478bd9Sstevel@tonic-gate 161*7c478bd9Sstevel@tonic-gate hash_obj->object_type = SEGMENT_TYPE; 162*7c478bd9Sstevel@tonic-gate hash_obj->u.seg_obj = seg_obj; 163*7c478bd9Sstevel@tonic-gate hash_obj->next = NULL; 164*7c478bd9Sstevel@tonic-gate hash_obj->prev = NULL; 165*7c478bd9Sstevel@tonic-gate 166*7c478bd9Sstevel@tonic-gate return (hash_obj); 167*7c478bd9Sstevel@tonic-gate } 168*7c478bd9Sstevel@tonic-gate 169*7c478bd9Sstevel@tonic-gate /* called to allocate packet hash object */ 170*7c478bd9Sstevel@tonic-gate 171*7c478bd9Sstevel@tonic-gate static hash_obj_t * 172*7c478bd9Sstevel@tonic-gate create_packet_hash_object(void) 173*7c478bd9Sstevel@tonic-gate { 174*7c478bd9Sstevel@tonic-gate hash_obj_t *hash_obj; 175*7c478bd9Sstevel@tonic-gate packet_obj_t *pkt_obj; 176*7c478bd9Sstevel@tonic-gate 177*7c478bd9Sstevel@tonic-gate pkt_obj = malloc(sizeof (packet_obj_t)); 178*7c478bd9Sstevel@tonic-gate if (pkt_obj == NULL) { 179*7c478bd9Sstevel@tonic-gate return (NULL); 180*7c478bd9Sstevel@tonic-gate } 181*7c478bd9Sstevel@tonic-gate 182*7c478bd9Sstevel@tonic-gate hash_obj = malloc(sizeof (hash_obj_t)); 183*7c478bd9Sstevel@tonic-gate if (hash_obj == NULL) { 184*7c478bd9Sstevel@tonic-gate free(pkt_obj); 185*7c478bd9Sstevel@tonic-gate return (NULL); 186*7c478bd9Sstevel@tonic-gate } 187*7c478bd9Sstevel@tonic-gate 188*7c478bd9Sstevel@tonic-gate pkt_obj->next = NULL; 189*7c478bd9Sstevel@tonic-gate 190*7c478bd9Sstevel@tonic-gate hash_obj->object_type = PACKET_TYPE; 191*7c478bd9Sstevel@tonic-gate hash_obj->u.pkt_obj = pkt_obj; 192*7c478bd9Sstevel@tonic-gate hash_obj->next = NULL; 193*7c478bd9Sstevel@tonic-gate hash_obj->prev = NULL; 194*7c478bd9Sstevel@tonic-gate 195*7c478bd9Sstevel@tonic-gate return (hash_obj); 196*7c478bd9Sstevel@tonic-gate } 197*7c478bd9Sstevel@tonic-gate 198*7c478bd9Sstevel@tonic-gate /* called to add allocated hash object into the hash table */ 199*7c478bd9Sstevel@tonic-gate 200*7c478bd9Sstevel@tonic-gate static void 201*7c478bd9Sstevel@tonic-gate add_hashobject_to_hashtable(hash_obj_t *hash_obj) 202*7c478bd9Sstevel@tonic-gate { 203*7c478bd9Sstevel@tonic-gate handle_t index_to_hash; 204*7c478bd9Sstevel@tonic-gate static uint64_t handle_count = 0; 205*7c478bd9Sstevel@tonic-gate 206*7c478bd9Sstevel@tonic-gate hash_obj->obj_hdl = ++handle_count; /* store the handle */ 207*7c478bd9Sstevel@tonic-gate 208*7c478bd9Sstevel@tonic-gate /* where to add ? */ 209*7c478bd9Sstevel@tonic-gate index_to_hash = ((hash_obj->obj_hdl) % TABLE_SIZE); 210*7c478bd9Sstevel@tonic-gate 211*7c478bd9Sstevel@tonic-gate hash_obj->next = hash_table[index_to_hash]; 212*7c478bd9Sstevel@tonic-gate hash_table[index_to_hash] = hash_obj; /* hash obj. added */ 213*7c478bd9Sstevel@tonic-gate 214*7c478bd9Sstevel@tonic-gate if (hash_obj->next != NULL) { 215*7c478bd9Sstevel@tonic-gate hash_obj->next->prev = hash_obj; 216*7c478bd9Sstevel@tonic-gate } 217*7c478bd9Sstevel@tonic-gate } 218*7c478bd9Sstevel@tonic-gate 219*7c478bd9Sstevel@tonic-gate /* called to add section object list into the section list */ 220*7c478bd9Sstevel@tonic-gate 221*7c478bd9Sstevel@tonic-gate static void 222*7c478bd9Sstevel@tonic-gate add_to_sec_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 223*7c478bd9Sstevel@tonic-gate { 224*7c478bd9Sstevel@tonic-gate hash_obj_t *next_hash; 225*7c478bd9Sstevel@tonic-gate 226*7c478bd9Sstevel@tonic-gate child_obj->u.sec_obj->cont_hdl = parent_obj->obj_hdl; 227*7c478bd9Sstevel@tonic-gate if (parent_obj->u.cont_obj->sec_obj_list == NULL) { 228*7c478bd9Sstevel@tonic-gate parent_obj->u.cont_obj->sec_obj_list = child_obj; 229*7c478bd9Sstevel@tonic-gate return; 230*7c478bd9Sstevel@tonic-gate } 231*7c478bd9Sstevel@tonic-gate 232*7c478bd9Sstevel@tonic-gate for (next_hash = parent_obj->u.cont_obj->sec_obj_list; 233*7c478bd9Sstevel@tonic-gate next_hash->u.sec_obj->next != NULL; 234*7c478bd9Sstevel@tonic-gate next_hash = next_hash->u.sec_obj->next) { 235*7c478bd9Sstevel@tonic-gate ; 236*7c478bd9Sstevel@tonic-gate } 237*7c478bd9Sstevel@tonic-gate 238*7c478bd9Sstevel@tonic-gate next_hash->u.sec_obj->next = child_obj; 239*7c478bd9Sstevel@tonic-gate } 240*7c478bd9Sstevel@tonic-gate 241*7c478bd9Sstevel@tonic-gate /* called to add segment object list into segment list */ 242*7c478bd9Sstevel@tonic-gate 243*7c478bd9Sstevel@tonic-gate static void 244*7c478bd9Sstevel@tonic-gate add_to_seg_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 245*7c478bd9Sstevel@tonic-gate { 246*7c478bd9Sstevel@tonic-gate hash_obj_t *next_hash; 247*7c478bd9Sstevel@tonic-gate 248*7c478bd9Sstevel@tonic-gate child_obj->u.seg_obj->section_hdl = parent_obj->obj_hdl; 249*7c478bd9Sstevel@tonic-gate if (parent_obj->u.sec_obj->seg_obj_list == NULL) { 250*7c478bd9Sstevel@tonic-gate parent_obj->u.sec_obj->seg_obj_list = child_obj; 251*7c478bd9Sstevel@tonic-gate return; 252*7c478bd9Sstevel@tonic-gate } 253*7c478bd9Sstevel@tonic-gate 254*7c478bd9Sstevel@tonic-gate for (next_hash = parent_obj->u.sec_obj->seg_obj_list; 255*7c478bd9Sstevel@tonic-gate next_hash->u.seg_obj->next != NULL; 256*7c478bd9Sstevel@tonic-gate next_hash = next_hash->u.seg_obj->next) { 257*7c478bd9Sstevel@tonic-gate ; 258*7c478bd9Sstevel@tonic-gate } 259*7c478bd9Sstevel@tonic-gate 260*7c478bd9Sstevel@tonic-gate next_hash->u.seg_obj->next = child_obj; 261*7c478bd9Sstevel@tonic-gate } 262*7c478bd9Sstevel@tonic-gate 263*7c478bd9Sstevel@tonic-gate /* called to add packet object list into packet list */ 264*7c478bd9Sstevel@tonic-gate 265*7c478bd9Sstevel@tonic-gate static void 266*7c478bd9Sstevel@tonic-gate add_to_pkt_object_list(hash_obj_t *parent_obj, hash_obj_t *child_obj) 267*7c478bd9Sstevel@tonic-gate { 268*7c478bd9Sstevel@tonic-gate hash_obj_t *next_hash; 269*7c478bd9Sstevel@tonic-gate 270*7c478bd9Sstevel@tonic-gate /* add the packet object in the end of list */ 271*7c478bd9Sstevel@tonic-gate child_obj->u.pkt_obj->segment_hdl = parent_obj->obj_hdl; 272*7c478bd9Sstevel@tonic-gate 273*7c478bd9Sstevel@tonic-gate if (parent_obj->u.seg_obj->pkt_obj_list == NULL) { 274*7c478bd9Sstevel@tonic-gate parent_obj->u.seg_obj->pkt_obj_list = child_obj; 275*7c478bd9Sstevel@tonic-gate return; 276*7c478bd9Sstevel@tonic-gate } 277*7c478bd9Sstevel@tonic-gate 278*7c478bd9Sstevel@tonic-gate for (next_hash = parent_obj->u.seg_obj->pkt_obj_list; 279*7c478bd9Sstevel@tonic-gate next_hash->u.pkt_obj->next != NULL; 280*7c478bd9Sstevel@tonic-gate next_hash = next_hash->u.pkt_obj->next) { 281*7c478bd9Sstevel@tonic-gate ; 282*7c478bd9Sstevel@tonic-gate } 283*7c478bd9Sstevel@tonic-gate 284*7c478bd9Sstevel@tonic-gate next_hash->u.pkt_obj->next = child_obj; 285*7c478bd9Sstevel@tonic-gate } 286*7c478bd9Sstevel@tonic-gate 287*7c478bd9Sstevel@tonic-gate static void 288*7c478bd9Sstevel@tonic-gate copy_segment_layout(segment_t *seghdr, void *layout) 289*7c478bd9Sstevel@tonic-gate { 290*7c478bd9Sstevel@tonic-gate segment_layout_t *seg_layout; 291*7c478bd9Sstevel@tonic-gate 292*7c478bd9Sstevel@tonic-gate seg_layout = (segment_layout_t *)layout; 293*7c478bd9Sstevel@tonic-gate (void) memcpy(seghdr->name, &seg_layout->name, SEG_NAME_LEN); 294*7c478bd9Sstevel@tonic-gate seghdr->descriptor = GET_SEGMENT_DESCRIPTOR; 295*7c478bd9Sstevel@tonic-gate seghdr->offset = seg_layout->offset; 296*7c478bd9Sstevel@tonic-gate seghdr->length = seg_layout->length; 297*7c478bd9Sstevel@tonic-gate } 298*7c478bd9Sstevel@tonic-gate 299*7c478bd9Sstevel@tonic-gate static hash_obj_t * 300*7c478bd9Sstevel@tonic-gate get_container_hash_object(int object_type, handle_t handle) 301*7c478bd9Sstevel@tonic-gate { 302*7c478bd9Sstevel@tonic-gate hash_obj_t *hash_obj; 303*7c478bd9Sstevel@tonic-gate 304*7c478bd9Sstevel@tonic-gate switch (object_type) { 305*7c478bd9Sstevel@tonic-gate case CONTAINER_TYPE : 306*7c478bd9Sstevel@tonic-gate break; 307*7c478bd9Sstevel@tonic-gate case SECTION_TYPE : 308*7c478bd9Sstevel@tonic-gate hash_obj = lookup_handle_object(handle, CONTAINER_TYPE); 309*7c478bd9Sstevel@tonic-gate if (hash_obj == NULL) { 310*7c478bd9Sstevel@tonic-gate return (NULL); 311*7c478bd9Sstevel@tonic-gate } 312*7c478bd9Sstevel@tonic-gate break; 313*7c478bd9Sstevel@tonic-gate case SEGMENT_TYPE : 314*7c478bd9Sstevel@tonic-gate hash_obj = lookup_handle_object(handle, SECTION_TYPE); 315*7c478bd9Sstevel@tonic-gate if (hash_obj == NULL) { 316*7c478bd9Sstevel@tonic-gate return (NULL); 317*7c478bd9Sstevel@tonic-gate } 318*7c478bd9Sstevel@tonic-gate hash_obj = lookup_handle_object(hash_obj->u.sec_obj->cont_hdl, 319*7c478bd9Sstevel@tonic-gate CONTAINER_TYPE); 320*7c478bd9Sstevel@tonic-gate break; 321*7c478bd9Sstevel@tonic-gate case PACKET_TYPE : 322*7c478bd9Sstevel@tonic-gate break; 323*7c478bd9Sstevel@tonic-gate default : 324*7c478bd9Sstevel@tonic-gate return (NULL); 325*7c478bd9Sstevel@tonic-gate } 326*7c478bd9Sstevel@tonic-gate return (hash_obj); 327*7c478bd9Sstevel@tonic-gate } 328*7c478bd9Sstevel@tonic-gate 329*7c478bd9Sstevel@tonic-gate 330*7c478bd9Sstevel@tonic-gate static void 331*7c478bd9Sstevel@tonic-gate sort_offsettbl(int segcnt, seg_info_t *offset_tbl) 332*7c478bd9Sstevel@tonic-gate { 333*7c478bd9Sstevel@tonic-gate int cntx; 334*7c478bd9Sstevel@tonic-gate int cnty; 335*7c478bd9Sstevel@tonic-gate seg_info_t tmp; 336*7c478bd9Sstevel@tonic-gate 337*7c478bd9Sstevel@tonic-gate for (cntx = 0; cntx < segcnt+2; cntx++) { 338*7c478bd9Sstevel@tonic-gate for (cnty = cntx+1; cnty < segcnt + 2; cnty++) { 339*7c478bd9Sstevel@tonic-gate if (offset_tbl[cntx].offset > 340*7c478bd9Sstevel@tonic-gate offset_tbl[cnty].offset) { 341*7c478bd9Sstevel@tonic-gate (void) memcpy(&tmp, &offset_tbl[cnty], 342*7c478bd9Sstevel@tonic-gate sizeof (seg_info_t)); 343*7c478bd9Sstevel@tonic-gate (void) memcpy(&offset_tbl[cnty], 344*7c478bd9Sstevel@tonic-gate &offset_tbl[cntx], sizeof (seg_info_t)); 345*7c478bd9Sstevel@tonic-gate 346*7c478bd9Sstevel@tonic-gate (void) memcpy(&offset_tbl[cntx], &tmp, 347*7c478bd9Sstevel@tonic-gate sizeof (seg_info_t)); 348*7c478bd9Sstevel@tonic-gate } 349*7c478bd9Sstevel@tonic-gate } 350*7c478bd9Sstevel@tonic-gate } 351*7c478bd9Sstevel@tonic-gate } 352*7c478bd9Sstevel@tonic-gate 353*7c478bd9Sstevel@tonic-gate /* 354*7c478bd9Sstevel@tonic-gate * Description : move_segment_data() reads the segment data and writes it 355*7c478bd9Sstevel@tonic-gate * back to the new segment offset. 356*7c478bd9Sstevel@tonic-gate */ 357*7c478bd9Sstevel@tonic-gate 358*7c478bd9Sstevel@tonic-gate static void 359*7c478bd9Sstevel@tonic-gate move_segment_data(void *seghdr, int newoffset, container_hdl_t contfd) 360*7c478bd9Sstevel@tonic-gate { 361*7c478bd9Sstevel@tonic-gate int ret; 362*7c478bd9Sstevel@tonic-gate char *buffer; 363*7c478bd9Sstevel@tonic-gate segment_layout_t *segment; 364*7c478bd9Sstevel@tonic-gate 365*7c478bd9Sstevel@tonic-gate segment = (segment_layout_t *)seghdr; 366*7c478bd9Sstevel@tonic-gate 367*7c478bd9Sstevel@tonic-gate buffer = alloca(segment->length); 368*7c478bd9Sstevel@tonic-gate if (buffer == NULL) { 369*7c478bd9Sstevel@tonic-gate return; 370*7c478bd9Sstevel@tonic-gate } 371*7c478bd9Sstevel@tonic-gate 372*7c478bd9Sstevel@tonic-gate ret = pread(contfd, buffer, segment->length, segment->offset); 373*7c478bd9Sstevel@tonic-gate if (ret != segment->length) { 374*7c478bd9Sstevel@tonic-gate return; 375*7c478bd9Sstevel@tonic-gate } 376*7c478bd9Sstevel@tonic-gate 377*7c478bd9Sstevel@tonic-gate segment->offset = newoffset; 378*7c478bd9Sstevel@tonic-gate 379*7c478bd9Sstevel@tonic-gate ret = pwrite(contfd, buffer, segment->length, segment->offset); 380*7c478bd9Sstevel@tonic-gate if (ret != segment->length) { 381*7c478bd9Sstevel@tonic-gate return; 382*7c478bd9Sstevel@tonic-gate } 383*7c478bd9Sstevel@tonic-gate } 384*7c478bd9Sstevel@tonic-gate 385*7c478bd9Sstevel@tonic-gate /* 386*7c478bd9Sstevel@tonic-gate * Description : pack_segment_data() moves the segment data if there is 387*7c478bd9Sstevel@tonic-gate * a hole between two segments. 388*7c478bd9Sstevel@tonic-gate */ 389*7c478bd9Sstevel@tonic-gate 390*7c478bd9Sstevel@tonic-gate static void 391*7c478bd9Sstevel@tonic-gate pack_segment_data(char *seghdr, int segcnt, container_hdl_t contfd, 392*7c478bd9Sstevel@tonic-gate seg_info_t *offset_tbl) 393*7c478bd9Sstevel@tonic-gate { 394*7c478bd9Sstevel@tonic-gate int cnt; 395*7c478bd9Sstevel@tonic-gate int diff; 396*7c478bd9Sstevel@tonic-gate int newoffset; 397*7c478bd9Sstevel@tonic-gate 398*7c478bd9Sstevel@tonic-gate for (cnt = segcnt + 1; cnt > 0; cnt--) { 399*7c478bd9Sstevel@tonic-gate if (!offset_tbl[cnt - 1].fixed) { 400*7c478bd9Sstevel@tonic-gate if (offset_tbl[cnt].offset - 401*7c478bd9Sstevel@tonic-gate (offset_tbl[cnt -1 ].offset + 402*7c478bd9Sstevel@tonic-gate offset_tbl[cnt - 1].length) > 0) { 403*7c478bd9Sstevel@tonic-gate 404*7c478bd9Sstevel@tonic-gate diff = offset_tbl[cnt].offset - 405*7c478bd9Sstevel@tonic-gate (offset_tbl[cnt - 1].offset + 406*7c478bd9Sstevel@tonic-gate offset_tbl[cnt - 1].length); 407*7c478bd9Sstevel@tonic-gate newoffset = offset_tbl[cnt - 1].offset + diff; 408*7c478bd9Sstevel@tonic-gate 409*7c478bd9Sstevel@tonic-gate move_segment_data(seghdr, newoffset, contfd); 410*7c478bd9Sstevel@tonic-gate 411*7c478bd9Sstevel@tonic-gate offset_tbl[cnt - 1].offset = newoffset; 412*7c478bd9Sstevel@tonic-gate 413*7c478bd9Sstevel@tonic-gate sort_offsettbl(segcnt, offset_tbl); 414*7c478bd9Sstevel@tonic-gate } 415*7c478bd9Sstevel@tonic-gate } 416*7c478bd9Sstevel@tonic-gate } 417*7c478bd9Sstevel@tonic-gate } 418*7c478bd9Sstevel@tonic-gate 419*7c478bd9Sstevel@tonic-gate /* 420*7c478bd9Sstevel@tonic-gate * Description : build_offset_tbl() builds the offset table by reading all the 421*7c478bd9Sstevel@tonic-gate * segment header. it makes two more entry into the table one for 422*7c478bd9Sstevel@tonic-gate * section size and another with start of the section after the 423*7c478bd9Sstevel@tonic-gate * segment header. 424*7c478bd9Sstevel@tonic-gate */ 425*7c478bd9Sstevel@tonic-gate 426*7c478bd9Sstevel@tonic-gate static int 427*7c478bd9Sstevel@tonic-gate build_offset_tbl(void *seghdr, int segcnt, int secsize, 428*7c478bd9Sstevel@tonic-gate seg_info_t *offset_tbl) 429*7c478bd9Sstevel@tonic-gate { 430*7c478bd9Sstevel@tonic-gate int cnt; 431*7c478bd9Sstevel@tonic-gate fru_segdesc_t segdesc; 432*7c478bd9Sstevel@tonic-gate segment_layout_t *segment; 433*7c478bd9Sstevel@tonic-gate 434*7c478bd9Sstevel@tonic-gate for (cnt = 0; cnt < segcnt; cnt++) { 435*7c478bd9Sstevel@tonic-gate segment = (segment_layout_t *)(seghdr) + cnt; 436*7c478bd9Sstevel@tonic-gate 437*7c478bd9Sstevel@tonic-gate (void) memcpy(&segdesc, &segment->descriptor, 438*7c478bd9Sstevel@tonic-gate sizeof (uint32_t)); 439*7c478bd9Sstevel@tonic-gate offset_tbl[cnt].segnum = cnt; 440*7c478bd9Sstevel@tonic-gate offset_tbl[cnt].offset = segment->offset; 441*7c478bd9Sstevel@tonic-gate offset_tbl[cnt].length = segment->length; 442*7c478bd9Sstevel@tonic-gate offset_tbl[cnt].fixed = segdesc.field.fixed; 443*7c478bd9Sstevel@tonic-gate } 444*7c478bd9Sstevel@tonic-gate 445*7c478bd9Sstevel@tonic-gate /* upper boundary of segment area (lower address bytes) */ 446*7c478bd9Sstevel@tonic-gate offset_tbl[cnt].segnum = -1; 447*7c478bd9Sstevel@tonic-gate offset_tbl[cnt].offset = sizeof (section_layout_t) + 448*7c478bd9Sstevel@tonic-gate ((cnt + 1) * sizeof (segment_layout_t)); 449*7c478bd9Sstevel@tonic-gate 450*7c478bd9Sstevel@tonic-gate offset_tbl[cnt].length = 0; 451*7c478bd9Sstevel@tonic-gate offset_tbl[cnt].fixed = 1; 452*7c478bd9Sstevel@tonic-gate /* lower boundary of segment area (higher address bytes) */ 453*7c478bd9Sstevel@tonic-gate 454*7c478bd9Sstevel@tonic-gate offset_tbl[cnt+1].segnum = -1; 455*7c478bd9Sstevel@tonic-gate offset_tbl[cnt+1].offset = secsize; 456*7c478bd9Sstevel@tonic-gate offset_tbl[cnt+1].length = 0; 457*7c478bd9Sstevel@tonic-gate offset_tbl[cnt+1].fixed = 1; 458*7c478bd9Sstevel@tonic-gate return (0); 459*7c478bd9Sstevel@tonic-gate } 460*7c478bd9Sstevel@tonic-gate 461*7c478bd9Sstevel@tonic-gate static int 462*7c478bd9Sstevel@tonic-gate hole_discovery(int bytes, int segcnt, int *totsize, seg_info_t *offset_tbl) 463*7c478bd9Sstevel@tonic-gate { 464*7c478bd9Sstevel@tonic-gate int cnt = 0; 465*7c478bd9Sstevel@tonic-gate 466*7c478bd9Sstevel@tonic-gate *totsize = 0; 467*7c478bd9Sstevel@tonic-gate for (cnt = segcnt + 1; cnt > 0; cnt--) { 468*7c478bd9Sstevel@tonic-gate if (bytes <= offset_tbl[cnt].offset - 469*7c478bd9Sstevel@tonic-gate (offset_tbl[cnt - 1].offset + 470*7c478bd9Sstevel@tonic-gate offset_tbl[cnt - 1].length)) { 471*7c478bd9Sstevel@tonic-gate return (offset_tbl[cnt].offset - bytes); 472*7c478bd9Sstevel@tonic-gate } 473*7c478bd9Sstevel@tonic-gate 474*7c478bd9Sstevel@tonic-gate *totsize += offset_tbl[cnt].offset - 475*7c478bd9Sstevel@tonic-gate (offset_tbl[cnt - 1].offset + offset_tbl[cnt - 1].length); 476*7c478bd9Sstevel@tonic-gate } 477*7c478bd9Sstevel@tonic-gate return (0); 478*7c478bd9Sstevel@tonic-gate } 479*7c478bd9Sstevel@tonic-gate 480*7c478bd9Sstevel@tonic-gate 481*7c478bd9Sstevel@tonic-gate /* 482*7c478bd9Sstevel@tonic-gate * Description : segment_hdr_present() verify space for new segment header to 483*7c478bd9Sstevel@tonic-gate * be added. 484*7c478bd9Sstevel@tonic-gate */ 485*7c478bd9Sstevel@tonic-gate 486*7c478bd9Sstevel@tonic-gate static int 487*7c478bd9Sstevel@tonic-gate segment_hdr_present(int segoffset, int size, seg_info_t *offset_tbl) 488*7c478bd9Sstevel@tonic-gate { 489*7c478bd9Sstevel@tonic-gate if ((segoffset + size) <= offset_tbl[0].offset) 490*7c478bd9Sstevel@tonic-gate return (0); 491*7c478bd9Sstevel@tonic-gate else 492*7c478bd9Sstevel@tonic-gate return (-1); 493*7c478bd9Sstevel@tonic-gate } 494*7c478bd9Sstevel@tonic-gate 495*7c478bd9Sstevel@tonic-gate /* 496*7c478bd9Sstevel@tonic-gate * Description : find_offset() is called from fru_add_segment routine to find 497*7c478bd9Sstevel@tonic-gate * a valid offset. 498*7c478bd9Sstevel@tonic-gate */ 499*7c478bd9Sstevel@tonic-gate 500*7c478bd9Sstevel@tonic-gate static int 501*7c478bd9Sstevel@tonic-gate find_offset(char *seghdr, int segcnt, int secsize, int *sectionoffset, 502*7c478bd9Sstevel@tonic-gate int segsize, int fix, container_hdl_t contfd) 503*7c478bd9Sstevel@tonic-gate { 504*7c478bd9Sstevel@tonic-gate int ret; 505*7c478bd9Sstevel@tonic-gate int newoffset; 506*7c478bd9Sstevel@tonic-gate int totsize = 0; 507*7c478bd9Sstevel@tonic-gate seg_info_t *offset_tbl; 508*7c478bd9Sstevel@tonic-gate 509*7c478bd9Sstevel@tonic-gate if (segcnt == 0) { 510*7c478bd9Sstevel@tonic-gate if (!fix) { /* if not fixed segment */ 511*7c478bd9Sstevel@tonic-gate *sectionoffset = secsize - segsize; 512*7c478bd9Sstevel@tonic-gate } 513*7c478bd9Sstevel@tonic-gate return (0); 514*7c478bd9Sstevel@tonic-gate } 515*7c478bd9Sstevel@tonic-gate 516*7c478bd9Sstevel@tonic-gate /* 517*7c478bd9Sstevel@tonic-gate * two extra segment info structure are allocated for start of segment 518*7c478bd9Sstevel@tonic-gate * and other end of segment. first segment offset is first available 519*7c478bd9Sstevel@tonic-gate * space and length is 0. second segment offset is is segment length and 520*7c478bd9Sstevel@tonic-gate * offset is 0. build_offset_tbl() explains how upper boundary and lower 521*7c478bd9Sstevel@tonic-gate * boudary segment area are initialized in seg_info_t table. 522*7c478bd9Sstevel@tonic-gate */ 523*7c478bd9Sstevel@tonic-gate 524*7c478bd9Sstevel@tonic-gate offset_tbl = malloc((segcnt + 2) * sizeof (seg_info_t)); 525*7c478bd9Sstevel@tonic-gate if (offset_tbl == NULL) { 526*7c478bd9Sstevel@tonic-gate return (-1); 527*7c478bd9Sstevel@tonic-gate } 528*7c478bd9Sstevel@tonic-gate 529*7c478bd9Sstevel@tonic-gate /* read all the segment header to make offset table */ 530*7c478bd9Sstevel@tonic-gate ret = build_offset_tbl(seghdr, segcnt, secsize, offset_tbl); 531*7c478bd9Sstevel@tonic-gate if (ret != 0) { 532*7c478bd9Sstevel@tonic-gate free(offset_tbl); 533*7c478bd9Sstevel@tonic-gate return (-1); 534*7c478bd9Sstevel@tonic-gate } 535*7c478bd9Sstevel@tonic-gate 536*7c478bd9Sstevel@tonic-gate /* sort the table */ 537*7c478bd9Sstevel@tonic-gate sort_offsettbl(segcnt, offset_tbl); 538*7c478bd9Sstevel@tonic-gate 539*7c478bd9Sstevel@tonic-gate /* new segment header offset */ 540*7c478bd9Sstevel@tonic-gate newoffset = sizeof (section_layout_t) + segcnt * 541*7c478bd9Sstevel@tonic-gate sizeof (segment_layout_t); 542*7c478bd9Sstevel@tonic-gate 543*7c478bd9Sstevel@tonic-gate /* do? new segment header overlap any existing data */ 544*7c478bd9Sstevel@tonic-gate ret = segment_hdr_present(newoffset, sizeof (segment_layout_t), 545*7c478bd9Sstevel@tonic-gate offset_tbl); 546*7c478bd9Sstevel@tonic-gate if (ret != 0) { /* make room for new segment if possible */ 547*7c478bd9Sstevel@tonic-gate 548*7c478bd9Sstevel@tonic-gate /* look for hole in order to move segment data */ 549*7c478bd9Sstevel@tonic-gate if (offset_tbl[0].fixed == SEGMENT_FIXED) { /* fixed segment */ 550*7c478bd9Sstevel@tonic-gate free(offset_tbl); 551*7c478bd9Sstevel@tonic-gate return (-1); 552*7c478bd9Sstevel@tonic-gate } 553*7c478bd9Sstevel@tonic-gate 554*7c478bd9Sstevel@tonic-gate newoffset = hole_discovery(offset_tbl[0].length, segcnt, 555*7c478bd9Sstevel@tonic-gate &totsize, offset_tbl); 556*7c478bd9Sstevel@tonic-gate if (newoffset != 0) { /* found new offset */ 557*7c478bd9Sstevel@tonic-gate /* now new offset */ 558*7c478bd9Sstevel@tonic-gate offset_tbl[0].offset = newoffset; 559*7c478bd9Sstevel@tonic-gate 560*7c478bd9Sstevel@tonic-gate /* move the segment data */ 561*7c478bd9Sstevel@tonic-gate move_segment_data(seghdr, newoffset, contfd); 562*7c478bd9Sstevel@tonic-gate /* again sort the offset table */ 563*7c478bd9Sstevel@tonic-gate sort_offsettbl(segcnt, offset_tbl); 564*7c478bd9Sstevel@tonic-gate } else { 565*7c478bd9Sstevel@tonic-gate /* pack the existing hole */ 566*7c478bd9Sstevel@tonic-gate if (totsize > offset_tbl[0].length) { 567*7c478bd9Sstevel@tonic-gate pack_segment_data(seghdr, segcnt, contfd, 568*7c478bd9Sstevel@tonic-gate offset_tbl); 569*7c478bd9Sstevel@tonic-gate } else { 570*7c478bd9Sstevel@tonic-gate free(offset_tbl); 571*7c478bd9Sstevel@tonic-gate return (-1); 572*7c478bd9Sstevel@tonic-gate } 573*7c478bd9Sstevel@tonic-gate } 574*7c478bd9Sstevel@tonic-gate } 575*7c478bd9Sstevel@tonic-gate 576*7c478bd9Sstevel@tonic-gate totsize = 0; 577*7c478bd9Sstevel@tonic-gate newoffset = hole_discovery(segsize, segcnt, &totsize, offset_tbl); 578*7c478bd9Sstevel@tonic-gate 579*7c478bd9Sstevel@tonic-gate if (newoffset == 0) { /* No hole found */ 580*7c478bd9Sstevel@tonic-gate if (totsize >= segsize) { 581*7c478bd9Sstevel@tonic-gate pack_segment_data(seghdr, segcnt, contfd, offset_tbl); 582*7c478bd9Sstevel@tonic-gate newoffset = hole_discovery(segsize, segcnt, &totsize, 583*7c478bd9Sstevel@tonic-gate offset_tbl); 584*7c478bd9Sstevel@tonic-gate if (newoffset != 0) { 585*7c478bd9Sstevel@tonic-gate *sectionoffset = newoffset; 586*7c478bd9Sstevel@tonic-gate free(offset_tbl); 587*7c478bd9Sstevel@tonic-gate return (0); 588*7c478bd9Sstevel@tonic-gate } 589*7c478bd9Sstevel@tonic-gate } 590*7c478bd9Sstevel@tonic-gate } else { 591*7c478bd9Sstevel@tonic-gate *sectionoffset = newoffset; 592*7c478bd9Sstevel@tonic-gate free(offset_tbl); 593*7c478bd9Sstevel@tonic-gate return (0); 594*7c478bd9Sstevel@tonic-gate } 595*7c478bd9Sstevel@tonic-gate free(offset_tbl); 596*7c478bd9Sstevel@tonic-gate return (-1); 597*7c478bd9Sstevel@tonic-gate } 598*7c478bd9Sstevel@tonic-gate 599*7c478bd9Sstevel@tonic-gate static char * 600*7c478bd9Sstevel@tonic-gate tokenizer(char *buf, char *separator, char **nextBuf, char *matched) 601*7c478bd9Sstevel@tonic-gate { 602*7c478bd9Sstevel@tonic-gate int i = 0; 603*7c478bd9Sstevel@tonic-gate int j = 0; 604*7c478bd9Sstevel@tonic-gate 605*7c478bd9Sstevel@tonic-gate for (i = 0; buf[i] != '\0'; i++) { 606*7c478bd9Sstevel@tonic-gate for (j = 0; j < strlen(separator); j++) { 607*7c478bd9Sstevel@tonic-gate if (buf[i] == separator[j]) { 608*7c478bd9Sstevel@tonic-gate buf[i] = '\0'; 609*7c478bd9Sstevel@tonic-gate *nextBuf = &(buf[i+1]); 610*7c478bd9Sstevel@tonic-gate *matched = separator[j]; 611*7c478bd9Sstevel@tonic-gate return (buf); 612*7c478bd9Sstevel@tonic-gate } 613*7c478bd9Sstevel@tonic-gate } 614*7c478bd9Sstevel@tonic-gate } 615*7c478bd9Sstevel@tonic-gate 616*7c478bd9Sstevel@tonic-gate *nextBuf = buf; 617*7c478bd9Sstevel@tonic-gate *matched = '\0'; 618*7c478bd9Sstevel@tonic-gate return (NULL); 619*7c478bd9Sstevel@tonic-gate } 620*7c478bd9Sstevel@tonic-gate 621*7c478bd9Sstevel@tonic-gate static int 622*7c478bd9Sstevel@tonic-gate get_container_info(const char *def_file, const char *cont_desc_str, 623*7c478bd9Sstevel@tonic-gate container_info_t *cont_info) 624*7c478bd9Sstevel@tonic-gate { 625*7c478bd9Sstevel@tonic-gate char *item; 626*7c478bd9Sstevel@tonic-gate char *token; 627*7c478bd9Sstevel@tonic-gate char *field; 628*7c478bd9Sstevel@tonic-gate char matched; 629*7c478bd9Sstevel@tonic-gate char buf[1024]; 630*7c478bd9Sstevel@tonic-gate int foundIt = 0; 631*7c478bd9Sstevel@tonic-gate int ro_tok; 632*7c478bd9Sstevel@tonic-gate int index; 633*7c478bd9Sstevel@tonic-gate FILE *file = fopen(def_file, "r"); 634*7c478bd9Sstevel@tonic-gate 635*7c478bd9Sstevel@tonic-gate if (file == NULL) 636*7c478bd9Sstevel@tonic-gate return (-1); 637*7c478bd9Sstevel@tonic-gate 638*7c478bd9Sstevel@tonic-gate cont_info->num_sections = 0; 639*7c478bd9Sstevel@tonic-gate 640*7c478bd9Sstevel@tonic-gate while (fgets(buf, sizeof (buf), file) != NULL) { 641*7c478bd9Sstevel@tonic-gate /* ignore all comments */ 642*7c478bd9Sstevel@tonic-gate token = tokenizer(buf, "#", &field, &matched); 643*7c478bd9Sstevel@tonic-gate /* find the names */ 644*7c478bd9Sstevel@tonic-gate token = tokenizer(buf, ":", &field, &matched); 645*7c478bd9Sstevel@tonic-gate if (token != 0x00) { 646*7c478bd9Sstevel@tonic-gate token = tokenizer(token, "|", &item, &matched); 647*7c478bd9Sstevel@tonic-gate while (token != 0x00) { 648*7c478bd9Sstevel@tonic-gate if (strcmp(token, cont_desc_str) == 0) { 649*7c478bd9Sstevel@tonic-gate foundIt = 1; 650*7c478bd9Sstevel@tonic-gate goto found; 651*7c478bd9Sstevel@tonic-gate } 652*7c478bd9Sstevel@tonic-gate token = tokenizer(item, "|", &item, &matched); 653*7c478bd9Sstevel@tonic-gate } 654*7c478bd9Sstevel@tonic-gate /* check the last remaining item */ 655*7c478bd9Sstevel@tonic-gate if ((item != 0x00) && 656*7c478bd9Sstevel@tonic-gate (strcmp(item, cont_desc_str) == 0)) { 657*7c478bd9Sstevel@tonic-gate foundIt = 1; 658*7c478bd9Sstevel@tonic-gate goto found; 659*7c478bd9Sstevel@tonic-gate } 660*7c478bd9Sstevel@tonic-gate } 661*7c478bd9Sstevel@tonic-gate } 662*7c478bd9Sstevel@tonic-gate 663*7c478bd9Sstevel@tonic-gate found : 664*7c478bd9Sstevel@tonic-gate if (foundIt == 1) { 665*7c478bd9Sstevel@tonic-gate token = tokenizer(field, ":", &field, &matched); 666*7c478bd9Sstevel@tonic-gate if (token == 0x00) { 667*7c478bd9Sstevel@tonic-gate (void) fclose(file); 668*7c478bd9Sstevel@tonic-gate return (-1); 669*7c478bd9Sstevel@tonic-gate } 670*7c478bd9Sstevel@tonic-gate cont_info->header_ver = (headerrev_t)atoi(token); 671*7c478bd9Sstevel@tonic-gate 672*7c478bd9Sstevel@tonic-gate token = tokenizer(field, ":\n", &field, &matched); 673*7c478bd9Sstevel@tonic-gate while (token != 0x00) { 674*7c478bd9Sstevel@tonic-gate token = tokenizer(token, ",", &item, &matched); 675*7c478bd9Sstevel@tonic-gate if (token == 0x00) { 676*7c478bd9Sstevel@tonic-gate (void) fclose(file); 677*7c478bd9Sstevel@tonic-gate return (-1); 678*7c478bd9Sstevel@tonic-gate } 679*7c478bd9Sstevel@tonic-gate ro_tok = atoi(token); 680*7c478bd9Sstevel@tonic-gate index = cont_info->num_sections; 681*7c478bd9Sstevel@tonic-gate cont_info->section_info[index].encoding = ENC_STANDARD; 682*7c478bd9Sstevel@tonic-gate if (ro_tok == 1) { 683*7c478bd9Sstevel@tonic-gate cont_info->section_info[index].description. 684*7c478bd9Sstevel@tonic-gate field.read_only = 1; 685*7c478bd9Sstevel@tonic-gate } else if (ro_tok == 0) { 686*7c478bd9Sstevel@tonic-gate cont_info->section_info[index].description. 687*7c478bd9Sstevel@tonic-gate field.read_only = 0; 688*7c478bd9Sstevel@tonic-gate } else if (ro_tok == 2) { 689*7c478bd9Sstevel@tonic-gate /* 690*7c478bd9Sstevel@tonic-gate * a value of 2 in the read-only token means 691*7c478bd9Sstevel@tonic-gate * that the data in this section needs 692*7c478bd9Sstevel@tonic-gate * re-interpreting 693*7c478bd9Sstevel@tonic-gate */ 694*7c478bd9Sstevel@tonic-gate cont_info->section_info[index].description. 695*7c478bd9Sstevel@tonic-gate field.read_only = 1; 696*7c478bd9Sstevel@tonic-gate } else { 697*7c478bd9Sstevel@tonic-gate (void) fclose(file); 698*7c478bd9Sstevel@tonic-gate return (-1); 699*7c478bd9Sstevel@tonic-gate } 700*7c478bd9Sstevel@tonic-gate 701*7c478bd9Sstevel@tonic-gate token = tokenizer(item, ",", &item, &matched); 702*7c478bd9Sstevel@tonic-gate if (token == 0x00) { 703*7c478bd9Sstevel@tonic-gate (void) fclose(file); 704*7c478bd9Sstevel@tonic-gate return (-1); 705*7c478bd9Sstevel@tonic-gate } 706*7c478bd9Sstevel@tonic-gate 707*7c478bd9Sstevel@tonic-gate cont_info->section_info[index].address = atoi(token); 708*7c478bd9Sstevel@tonic-gate if (ro_tok == 2) { 709*7c478bd9Sstevel@tonic-gate /* 710*7c478bd9Sstevel@tonic-gate * expect an extra parameter to define the 711*7c478bd9Sstevel@tonic-gate * data interpreter 712*7c478bd9Sstevel@tonic-gate */ 713*7c478bd9Sstevel@tonic-gate token = tokenizer(item, ",", &item, &matched); 714*7c478bd9Sstevel@tonic-gate if (token == 0x00) { 715*7c478bd9Sstevel@tonic-gate (void) fclose(file); 716*7c478bd9Sstevel@tonic-gate return (-1); 717*7c478bd9Sstevel@tonic-gate } 718*7c478bd9Sstevel@tonic-gate } 719*7c478bd9Sstevel@tonic-gate if (item == '\0') { 720*7c478bd9Sstevel@tonic-gate (void) fclose(file); 721*7c478bd9Sstevel@tonic-gate return (-1); 722*7c478bd9Sstevel@tonic-gate } 723*7c478bd9Sstevel@tonic-gate cont_info->section_info[index].size = 724*7c478bd9Sstevel@tonic-gate ro_tok == 2 ? atoi(token) : atoi(item); 725*7c478bd9Sstevel@tonic-gate if (ro_tok == 2) { 726*7c478bd9Sstevel@tonic-gate if (strcmp(item, "SPD") == 0) 727*7c478bd9Sstevel@tonic-gate cont_info->section_info[index]. 728*7c478bd9Sstevel@tonic-gate encoding = ENC_SPD; 729*7c478bd9Sstevel@tonic-gate else { 730*7c478bd9Sstevel@tonic-gate (void) fclose(file); 731*7c478bd9Sstevel@tonic-gate return (-1); 732*7c478bd9Sstevel@tonic-gate } 733*7c478bd9Sstevel@tonic-gate } 734*7c478bd9Sstevel@tonic-gate (cont_info->num_sections)++; 735*7c478bd9Sstevel@tonic-gate 736*7c478bd9Sstevel@tonic-gate token = tokenizer(field, ":\n ", &field, &matched); 737*7c478bd9Sstevel@tonic-gate } 738*7c478bd9Sstevel@tonic-gate } 739*7c478bd9Sstevel@tonic-gate (void) fclose(file); 740*7c478bd9Sstevel@tonic-gate return (0); 741*7c478bd9Sstevel@tonic-gate } 742*7c478bd9Sstevel@tonic-gate 743*7c478bd9Sstevel@tonic-gate /* 744*7c478bd9Sstevel@tonic-gate * Description :fru_open_container() opens the container associated with a fru. 745*7c478bd9Sstevel@tonic-gate * it's called by data plugin module before creating container 746*7c478bd9Sstevel@tonic-gate * property. it calls picltree library routine to get the 747*7c478bd9Sstevel@tonic-gate * device path and driver binding name for the fru to get the 748*7c478bd9Sstevel@tonic-gate * corresponding fru name that describe the fru layout. 749*7c478bd9Sstevel@tonic-gate * 750*7c478bd9Sstevel@tonic-gate * Arguments :picl_hdl_t fru 751*7c478bd9Sstevel@tonic-gate * A handle for PICL tree node of class "fru" representing the 752*7c478bd9Sstevel@tonic-gate * FRU with the container to open. 753*7c478bd9Sstevel@tonic-gate * 754*7c478bd9Sstevel@tonic-gate * Return : 755*7c478bd9Sstevel@tonic-gate * On Success, a Positive integer container handle. is returned 756*7c478bd9Sstevel@tonic-gate * for use in subsequent fru operations;on error, 0 is returned 757*7c478bd9Sstevel@tonic-gate * and "errno" is set appropriately. 758*7c478bd9Sstevel@tonic-gate */ 759*7c478bd9Sstevel@tonic-gate 760*7c478bd9Sstevel@tonic-gate container_hdl_t 761*7c478bd9Sstevel@tonic-gate fru_open_container(picl_nodehdl_t fruhdl) 762*7c478bd9Sstevel@tonic-gate { 763*7c478bd9Sstevel@tonic-gate int retval; 764*7c478bd9Sstevel@tonic-gate int count; 765*7c478bd9Sstevel@tonic-gate char *bname; 766*7c478bd9Sstevel@tonic-gate char devpath[PATH_MAX]; 767*7c478bd9Sstevel@tonic-gate char nmbuf[SYS_NMLN]; 768*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_hash_obj; 769*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash_obj; 770*7c478bd9Sstevel@tonic-gate picl_nodehdl_t tmphdl; 771*7c478bd9Sstevel@tonic-gate picl_prophdl_t prophdl; 772*7c478bd9Sstevel@tonic-gate ptree_propinfo_t propinfo; 773*7c478bd9Sstevel@tonic-gate container_info_t cont_info; 774*7c478bd9Sstevel@tonic-gate 775*7c478bd9Sstevel@tonic-gate /* Get property handle of _seeprom_source under fru node */ 776*7c478bd9Sstevel@tonic-gate retval = ptree_get_propval_by_name(fruhdl, PICL_REFPROP_SEEPROM_SRC, 777*7c478bd9Sstevel@tonic-gate &tmphdl, sizeof (tmphdl)); 778*7c478bd9Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 779*7c478bd9Sstevel@tonic-gate return (NULL); 780*7c478bd9Sstevel@tonic-gate } 781*7c478bd9Sstevel@tonic-gate 782*7c478bd9Sstevel@tonic-gate /* Get the device path of the fru */ 783*7c478bd9Sstevel@tonic-gate retval = ptree_get_propval_by_name(tmphdl, PICL_PROP_DEVICEPATH, 784*7c478bd9Sstevel@tonic-gate devpath, PATH_MAX); 785*7c478bd9Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 786*7c478bd9Sstevel@tonic-gate return (NULL); 787*7c478bd9Sstevel@tonic-gate } 788*7c478bd9Sstevel@tonic-gate 789*7c478bd9Sstevel@tonic-gate retval = ptree_get_prop_by_name(tmphdl, PICL_PROP_BINDING_NAME, 790*7c478bd9Sstevel@tonic-gate &prophdl); 791*7c478bd9Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 792*7c478bd9Sstevel@tonic-gate return (NULL); 793*7c478bd9Sstevel@tonic-gate } 794*7c478bd9Sstevel@tonic-gate 795*7c478bd9Sstevel@tonic-gate retval = ptree_get_propinfo(prophdl, &propinfo); 796*7c478bd9Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 797*7c478bd9Sstevel@tonic-gate return (NULL); 798*7c478bd9Sstevel@tonic-gate } 799*7c478bd9Sstevel@tonic-gate 800*7c478bd9Sstevel@tonic-gate bname = alloca(propinfo.piclinfo.size); 801*7c478bd9Sstevel@tonic-gate if (bname == NULL) { 802*7c478bd9Sstevel@tonic-gate return (NULL); 803*7c478bd9Sstevel@tonic-gate } 804*7c478bd9Sstevel@tonic-gate 805*7c478bd9Sstevel@tonic-gate /* get the driver binding name */ 806*7c478bd9Sstevel@tonic-gate retval = ptree_get_propval(prophdl, bname, propinfo.piclinfo.size); 807*7c478bd9Sstevel@tonic-gate if (retval != PICL_SUCCESS) { 808*7c478bd9Sstevel@tonic-gate return (NULL); 809*7c478bd9Sstevel@tonic-gate } 810*7c478bd9Sstevel@tonic-gate 811*7c478bd9Sstevel@tonic-gate cont_hash_obj = create_container_hash_object(); 812*7c478bd9Sstevel@tonic-gate if (cont_hash_obj == NULL) { 813*7c478bd9Sstevel@tonic-gate return (NULL); 814*7c478bd9Sstevel@tonic-gate } 815*7c478bd9Sstevel@tonic-gate 816*7c478bd9Sstevel@tonic-gate add_hashobject_to_hashtable(cont_hash_obj); 817*7c478bd9Sstevel@tonic-gate 818*7c478bd9Sstevel@tonic-gate (void) strlcpy(cont_hash_obj->u.cont_obj->device_pathname, devpath, 819*7c478bd9Sstevel@tonic-gate sizeof (devpath)); 820*7c478bd9Sstevel@tonic-gate 821*7c478bd9Sstevel@tonic-gate /* if there's a platform-specific conf file, use that */ 822*7c478bd9Sstevel@tonic-gate retval = -1; 823*7c478bd9Sstevel@tonic-gate if (sysinfo(SI_PLATFORM, nmbuf, sizeof (nmbuf)) != -1) { 824*7c478bd9Sstevel@tonic-gate (void) snprintf(devpath, PATH_MAX, PICLD_PLAT_PLUGIN_DIRF, 825*7c478bd9Sstevel@tonic-gate nmbuf); 826*7c478bd9Sstevel@tonic-gate (void) strlcat(devpath, FRU_CONTAINER_CONF, PATH_MAX); 827*7c478bd9Sstevel@tonic-gate retval = access(devpath, R_OK); 828*7c478bd9Sstevel@tonic-gate } 829*7c478bd9Sstevel@tonic-gate if (retval != 0) { 830*7c478bd9Sstevel@tonic-gate /* nothing for the platform, try the base name */ 831*7c478bd9Sstevel@tonic-gate (void) snprintf(devpath, PATH_MAX, "%s/%s", 832*7c478bd9Sstevel@tonic-gate CONTAINER_DIR, FRU_CONTAINER_CONF); 833*7c478bd9Sstevel@tonic-gate retval = access(devpath, R_OK); 834*7c478bd9Sstevel@tonic-gate } 835*7c478bd9Sstevel@tonic-gate /* matches driver binding name to get container information */ 836*7c478bd9Sstevel@tonic-gate if (retval == 0) { 837*7c478bd9Sstevel@tonic-gate retval = get_container_info(devpath, bname, &cont_info); 838*7c478bd9Sstevel@tonic-gate } 839*7c478bd9Sstevel@tonic-gate if (retval < 0) { 840*7c478bd9Sstevel@tonic-gate return (NULL); 841*7c478bd9Sstevel@tonic-gate } 842*7c478bd9Sstevel@tonic-gate 843*7c478bd9Sstevel@tonic-gate cont_hash_obj->u.cont_obj->num_of_section = cont_info.num_sections; 844*7c478bd9Sstevel@tonic-gate cont_hash_obj->u.cont_obj->sec_obj_list = NULL; 845*7c478bd9Sstevel@tonic-gate 846*7c478bd9Sstevel@tonic-gate for (count = 0; count < cont_info.num_sections; count++) { 847*7c478bd9Sstevel@tonic-gate sec_hash_obj = create_section_hash_object(); 848*7c478bd9Sstevel@tonic-gate if (sec_hash_obj == NULL) { 849*7c478bd9Sstevel@tonic-gate return (NULL); 850*7c478bd9Sstevel@tonic-gate } 851*7c478bd9Sstevel@tonic-gate 852*7c478bd9Sstevel@tonic-gate add_hashobject_to_hashtable(sec_hash_obj); 853*7c478bd9Sstevel@tonic-gate 854*7c478bd9Sstevel@tonic-gate sec_hash_obj->u.sec_obj->section.offset = 855*7c478bd9Sstevel@tonic-gate cont_info.section_info[count].address; 856*7c478bd9Sstevel@tonic-gate 857*7c478bd9Sstevel@tonic-gate sec_hash_obj->u.sec_obj->section.protection = 858*7c478bd9Sstevel@tonic-gate cont_info.section_info[count].description.field.read_only; 859*7c478bd9Sstevel@tonic-gate 860*7c478bd9Sstevel@tonic-gate sec_hash_obj->u.sec_obj->section.length = 861*7c478bd9Sstevel@tonic-gate cont_info.section_info[count].size; 862*7c478bd9Sstevel@tonic-gate 863*7c478bd9Sstevel@tonic-gate sec_hash_obj->u.sec_obj->section.version = cont_info.header_ver; 864*7c478bd9Sstevel@tonic-gate sec_hash_obj->u.sec_obj->encoding = 865*7c478bd9Sstevel@tonic-gate cont_info.section_info[count].encoding; 866*7c478bd9Sstevel@tonic-gate 867*7c478bd9Sstevel@tonic-gate add_to_sec_object_list(cont_hash_obj, sec_hash_obj); 868*7c478bd9Sstevel@tonic-gate } 869*7c478bd9Sstevel@tonic-gate return (cont_hash_obj->obj_hdl); 870*7c478bd9Sstevel@tonic-gate } 871*7c478bd9Sstevel@tonic-gate 872*7c478bd9Sstevel@tonic-gate static int 873*7c478bd9Sstevel@tonic-gate verify_header_crc8(headerrev_t head_ver, unsigned char *bytes, int length) 874*7c478bd9Sstevel@tonic-gate { 875*7c478bd9Sstevel@tonic-gate int crc_offset = 0; 876*7c478bd9Sstevel@tonic-gate unsigned char orig_crc8 = 0; 877*7c478bd9Sstevel@tonic-gate unsigned char calc_crc8 = 0; 878*7c478bd9Sstevel@tonic-gate 879*7c478bd9Sstevel@tonic-gate switch (head_ver) { 880*7c478bd9Sstevel@tonic-gate case SECTION_HDR_VER: 881*7c478bd9Sstevel@tonic-gate crc_offset = 4; 882*7c478bd9Sstevel@tonic-gate break; 883*7c478bd9Sstevel@tonic-gate default: 884*7c478bd9Sstevel@tonic-gate errno = EINVAL; 885*7c478bd9Sstevel@tonic-gate return (0); 886*7c478bd9Sstevel@tonic-gate } 887*7c478bd9Sstevel@tonic-gate 888*7c478bd9Sstevel@tonic-gate orig_crc8 = bytes[crc_offset]; 889*7c478bd9Sstevel@tonic-gate bytes[crc_offset] = 0x00; /* clear for calc */ 890*7c478bd9Sstevel@tonic-gate calc_crc8 = compute_crc8(bytes, length); 891*7c478bd9Sstevel@tonic-gate bytes[crc_offset] = orig_crc8; /* restore */ 892*7c478bd9Sstevel@tonic-gate return (orig_crc8 == calc_crc8); 893*7c478bd9Sstevel@tonic-gate } 894*7c478bd9Sstevel@tonic-gate 895*7c478bd9Sstevel@tonic-gate /* 896*7c478bd9Sstevel@tonic-gate * Description : 897*7c478bd9Sstevel@tonic-gate * fru_get_num_sections() returns number of sections in a 898*7c478bd9Sstevel@tonic-gate * container. it calls get_container_index() to get the container 899*7c478bd9Sstevel@tonic-gate * index number in the container list. 900*7c478bd9Sstevel@tonic-gate * 901*7c478bd9Sstevel@tonic-gate * Arguments : 902*7c478bd9Sstevel@tonic-gate * container_hdl_t : container handle. 903*7c478bd9Sstevel@tonic-gate * 904*7c478bd9Sstevel@tonic-gate * Return : 905*7c478bd9Sstevel@tonic-gate * int 906*7c478bd9Sstevel@tonic-gate * On success, returns number of sections in a container. 907*7c478bd9Sstevel@tonic-gate * 908*7c478bd9Sstevel@tonic-gate */ 909*7c478bd9Sstevel@tonic-gate 910*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 911*7c478bd9Sstevel@tonic-gate int 912*7c478bd9Sstevel@tonic-gate fru_get_num_sections(container_hdl_t container, door_cred_t *cred) 913*7c478bd9Sstevel@tonic-gate { 914*7c478bd9Sstevel@tonic-gate hash_obj_t *hash_object; 915*7c478bd9Sstevel@tonic-gate 916*7c478bd9Sstevel@tonic-gate hash_object = lookup_handle_object(container, CONTAINER_TYPE); 917*7c478bd9Sstevel@tonic-gate if (hash_object == NULL) { 918*7c478bd9Sstevel@tonic-gate return (-1); 919*7c478bd9Sstevel@tonic-gate } 920*7c478bd9Sstevel@tonic-gate 921*7c478bd9Sstevel@tonic-gate return (hash_object->u.cont_obj->num_of_section); 922*7c478bd9Sstevel@tonic-gate } 923*7c478bd9Sstevel@tonic-gate 924*7c478bd9Sstevel@tonic-gate /* 925*7c478bd9Sstevel@tonic-gate * called from fru_get_sections() 926*7c478bd9Sstevel@tonic-gate */ 927*7c478bd9Sstevel@tonic-gate 928*7c478bd9Sstevel@tonic-gate static void 929*7c478bd9Sstevel@tonic-gate get_section(int fd, hash_obj_t *sec_hash, section_t *section) 930*7c478bd9Sstevel@tonic-gate { 931*7c478bd9Sstevel@tonic-gate int retval; 932*7c478bd9Sstevel@tonic-gate int size; 933*7c478bd9Sstevel@tonic-gate int count; 934*7c478bd9Sstevel@tonic-gate uint16_t hdrver; 935*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 936*7c478bd9Sstevel@tonic-gate unsigned char *buffer; 937*7c478bd9Sstevel@tonic-gate section_obj_t *sec_obj; 938*7c478bd9Sstevel@tonic-gate section_layout_t sec_hdr; 939*7c478bd9Sstevel@tonic-gate segment_layout_t *seg_hdr; 940*7c478bd9Sstevel@tonic-gate segment_layout_t *seg_buf; 941*7c478bd9Sstevel@tonic-gate 942*7c478bd9Sstevel@tonic-gate sec_obj = sec_hash->u.sec_obj; 943*7c478bd9Sstevel@tonic-gate if (sec_obj == NULL) { 944*7c478bd9Sstevel@tonic-gate return; 945*7c478bd9Sstevel@tonic-gate } 946*7c478bd9Sstevel@tonic-gate 947*7c478bd9Sstevel@tonic-gate /* populate section_t */ 948*7c478bd9Sstevel@tonic-gate section->handle = sec_hash->obj_hdl; 949*7c478bd9Sstevel@tonic-gate section->offset = sec_obj->section.offset; 950*7c478bd9Sstevel@tonic-gate section->length = sec_obj->section.length; 951*7c478bd9Sstevel@tonic-gate section->protection = sec_obj->section.protection; 952*7c478bd9Sstevel@tonic-gate section->version = sec_obj->section.version; 953*7c478bd9Sstevel@tonic-gate sec_obj->num_of_segment = 0; 954*7c478bd9Sstevel@tonic-gate 955*7c478bd9Sstevel@tonic-gate switch (sec_obj->encoding) { 956*7c478bd9Sstevel@tonic-gate case ENC_STANDARD: 957*7c478bd9Sstevel@tonic-gate /* read section header layout */ 958*7c478bd9Sstevel@tonic-gate retval = pread(fd, &sec_hdr, sizeof (sec_hdr), 959*7c478bd9Sstevel@tonic-gate sec_obj->section.offset); 960*7c478bd9Sstevel@tonic-gate break; 961*7c478bd9Sstevel@tonic-gate 962*7c478bd9Sstevel@tonic-gate case ENC_SPD: 963*7c478bd9Sstevel@tonic-gate retval = get_sp_sec_hdr(&sec_hdr, sizeof (sec_hdr)); 964*7c478bd9Sstevel@tonic-gate break; 965*7c478bd9Sstevel@tonic-gate 966*7c478bd9Sstevel@tonic-gate default: 967*7c478bd9Sstevel@tonic-gate return; 968*7c478bd9Sstevel@tonic-gate } 969*7c478bd9Sstevel@tonic-gate 970*7c478bd9Sstevel@tonic-gate if (retval != sizeof (sec_hdr)) { 971*7c478bd9Sstevel@tonic-gate return; 972*7c478bd9Sstevel@tonic-gate } 973*7c478bd9Sstevel@tonic-gate 974*7c478bd9Sstevel@tonic-gate hdrver = GET_SECTION_HDR_VERSION; 975*7c478bd9Sstevel@tonic-gate 976*7c478bd9Sstevel@tonic-gate if ((sec_hdr.headertag != SECTION_HDR_TAG) && 977*7c478bd9Sstevel@tonic-gate (hdrver != section->version)) { 978*7c478bd9Sstevel@tonic-gate return; 979*7c478bd9Sstevel@tonic-gate } 980*7c478bd9Sstevel@tonic-gate 981*7c478bd9Sstevel@tonic-gate /* size = section layout + total sizeof segment header */ 982*7c478bd9Sstevel@tonic-gate size = sizeof (sec_hdr) + ((sec_hdr.segmentcount) * 983*7c478bd9Sstevel@tonic-gate sizeof (segment_layout_t)); 984*7c478bd9Sstevel@tonic-gate 985*7c478bd9Sstevel@tonic-gate buffer = alloca(size); 986*7c478bd9Sstevel@tonic-gate if (buffer == NULL) { 987*7c478bd9Sstevel@tonic-gate return; 988*7c478bd9Sstevel@tonic-gate } 989*7c478bd9Sstevel@tonic-gate 990*7c478bd9Sstevel@tonic-gate /* segment header buffer */ 991*7c478bd9Sstevel@tonic-gate seg_buf = alloca(size - sizeof (sec_hdr)); 992*7c478bd9Sstevel@tonic-gate if (seg_buf == NULL) { 993*7c478bd9Sstevel@tonic-gate return; 994*7c478bd9Sstevel@tonic-gate } 995*7c478bd9Sstevel@tonic-gate 996*7c478bd9Sstevel@tonic-gate switch (sec_obj->encoding) { 997*7c478bd9Sstevel@tonic-gate case ENC_STANDARD: 998*7c478bd9Sstevel@tonic-gate /* read segment header */ 999*7c478bd9Sstevel@tonic-gate retval = pread(fd, seg_buf, size - sizeof (sec_hdr), 1000*7c478bd9Sstevel@tonic-gate sec_obj->section.offset + sizeof (sec_hdr)); 1001*7c478bd9Sstevel@tonic-gate break; 1002*7c478bd9Sstevel@tonic-gate 1003*7c478bd9Sstevel@tonic-gate case ENC_SPD: 1004*7c478bd9Sstevel@tonic-gate retval = 1005*7c478bd9Sstevel@tonic-gate get_sp_seg_hdr(seg_buf, size - sizeof (sec_hdr)); 1006*7c478bd9Sstevel@tonic-gate break; 1007*7c478bd9Sstevel@tonic-gate 1008*7c478bd9Sstevel@tonic-gate default: 1009*7c478bd9Sstevel@tonic-gate return; 1010*7c478bd9Sstevel@tonic-gate } 1011*7c478bd9Sstevel@tonic-gate 1012*7c478bd9Sstevel@tonic-gate if (retval != (size - sizeof (sec_hdr))) { 1013*7c478bd9Sstevel@tonic-gate return; 1014*7c478bd9Sstevel@tonic-gate } 1015*7c478bd9Sstevel@tonic-gate 1016*7c478bd9Sstevel@tonic-gate /* copy section header layout */ 1017*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, &sec_hdr, sizeof (sec_hdr)); 1018*7c478bd9Sstevel@tonic-gate 1019*7c478bd9Sstevel@tonic-gate /* copy segment header layout */ 1020*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer + sizeof (sec_hdr), seg_buf, size - 1021*7c478bd9Sstevel@tonic-gate sizeof (sec_hdr)); 1022*7c478bd9Sstevel@tonic-gate 1023*7c478bd9Sstevel@tonic-gate /* verify crc8 */ 1024*7c478bd9Sstevel@tonic-gate retval = verify_header_crc8(hdrver, buffer, size); 1025*7c478bd9Sstevel@tonic-gate if (retval != TRUE) { 1026*7c478bd9Sstevel@tonic-gate return; 1027*7c478bd9Sstevel@tonic-gate } 1028*7c478bd9Sstevel@tonic-gate 1029*7c478bd9Sstevel@tonic-gate section->version = hdrver; 1030*7c478bd9Sstevel@tonic-gate sec_obj->section.version = hdrver; 1031*7c478bd9Sstevel@tonic-gate 1032*7c478bd9Sstevel@tonic-gate seg_hdr = (segment_layout_t *)seg_buf; 1033*7c478bd9Sstevel@tonic-gate 1034*7c478bd9Sstevel@tonic-gate for (count = 0; count < sec_hdr.segmentcount; count++, seg_hdr++) { 1035*7c478bd9Sstevel@tonic-gate seg_hash = create_segment_hash_object(); 1036*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 1037*7c478bd9Sstevel@tonic-gate return; 1038*7c478bd9Sstevel@tonic-gate } 1039*7c478bd9Sstevel@tonic-gate 1040*7c478bd9Sstevel@tonic-gate add_hashobject_to_hashtable(seg_hash); 1041*7c478bd9Sstevel@tonic-gate 1042*7c478bd9Sstevel@tonic-gate copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_hdr); 1043*7c478bd9Sstevel@tonic-gate 1044*7c478bd9Sstevel@tonic-gate add_to_seg_object_list(sec_hash, seg_hash); 1045*7c478bd9Sstevel@tonic-gate 1046*7c478bd9Sstevel@tonic-gate sec_obj->num_of_segment++; 1047*7c478bd9Sstevel@tonic-gate } 1048*7c478bd9Sstevel@tonic-gate } 1049*7c478bd9Sstevel@tonic-gate 1050*7c478bd9Sstevel@tonic-gate 1051*7c478bd9Sstevel@tonic-gate static int 1052*7c478bd9Sstevel@tonic-gate call_devfsadm(void) 1053*7c478bd9Sstevel@tonic-gate { 1054*7c478bd9Sstevel@tonic-gate char *phys_path; 1055*7c478bd9Sstevel@tonic-gate di_node_t root_node; 1056*7c478bd9Sstevel@tonic-gate di_node_t prom_node; 1057*7c478bd9Sstevel@tonic-gate di_node_t f_node; 1058*7c478bd9Sstevel@tonic-gate 1059*7c478bd9Sstevel@tonic-gate if ((root_node = di_init("/", DINFOCPYALL)) == DI_NODE_NIL) { 1060*7c478bd9Sstevel@tonic-gate return (-1); 1061*7c478bd9Sstevel@tonic-gate } 1062*7c478bd9Sstevel@tonic-gate 1063*7c478bd9Sstevel@tonic-gate f_node = di_drv_first_node(PICL_CLASS_SEEPROM, root_node); 1064*7c478bd9Sstevel@tonic-gate if (f_node != DI_NODE_NIL) { 1065*7c478bd9Sstevel@tonic-gate phys_path = di_devfs_path(f_node); 1066*7c478bd9Sstevel@tonic-gate if ((prom_node = di_init(phys_path, DINFOMINOR)) != 1067*7c478bd9Sstevel@tonic-gate DI_NODE_NIL) { 1068*7c478bd9Sstevel@tonic-gate di_fini(prom_node); 1069*7c478bd9Sstevel@tonic-gate di_fini(root_node); 1070*7c478bd9Sstevel@tonic-gate (void) pclose(popen(devfsadm_cmd, "r")); 1071*7c478bd9Sstevel@tonic-gate return (0); 1072*7c478bd9Sstevel@tonic-gate } 1073*7c478bd9Sstevel@tonic-gate } 1074*7c478bd9Sstevel@tonic-gate di_fini(root_node); 1075*7c478bd9Sstevel@tonic-gate return (-1); 1076*7c478bd9Sstevel@tonic-gate } 1077*7c478bd9Sstevel@tonic-gate 1078*7c478bd9Sstevel@tonic-gate /* 1079*7c478bd9Sstevel@tonic-gate * Description : 1080*7c478bd9Sstevel@tonic-gate * fru_get_sections() fills an array of section structures passed 1081*7c478bd9Sstevel@tonic-gate * as an argument. 1082*7c478bd9Sstevel@tonic-gate * 1083*7c478bd9Sstevel@tonic-gate * Arguments : 1084*7c478bd9Sstevel@tonic-gate * container_hdl_t : container handle(device descriptor). 1085*7c478bd9Sstevel@tonic-gate * section_t : array of section structure. 1086*7c478bd9Sstevel@tonic-gate * int : maximum number of section in a container. 1087*7c478bd9Sstevel@tonic-gate * 1088*7c478bd9Sstevel@tonic-gate * Returns : 1089*7c478bd9Sstevel@tonic-gate * int 1090*7c478bd9Sstevel@tonic-gate * On success,the number of section structures written is returned; 1091*7c478bd9Sstevel@tonic-gate * on error, -1 is returned and "errno" is set appropriately. 1092*7c478bd9Sstevel@tonic-gate * 1093*7c478bd9Sstevel@tonic-gate */ 1094*7c478bd9Sstevel@tonic-gate 1095*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1096*7c478bd9Sstevel@tonic-gate int 1097*7c478bd9Sstevel@tonic-gate fru_get_sections(container_hdl_t container, section_t *section, int maxsec, 1098*7c478bd9Sstevel@tonic-gate door_cred_t *cred) 1099*7c478bd9Sstevel@tonic-gate { 1100*7c478bd9Sstevel@tonic-gate int device_fd; 1101*7c478bd9Sstevel@tonic-gate int retrys = 1; 1102*7c478bd9Sstevel@tonic-gate int count; 1103*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_object; 1104*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 1105*7c478bd9Sstevel@tonic-gate 1106*7c478bd9Sstevel@tonic-gate cont_object = lookup_handle_object(container, CONTAINER_TYPE); 1107*7c478bd9Sstevel@tonic-gate 1108*7c478bd9Sstevel@tonic-gate if (cont_object == NULL) { 1109*7c478bd9Sstevel@tonic-gate return (-1); 1110*7c478bd9Sstevel@tonic-gate } 1111*7c478bd9Sstevel@tonic-gate 1112*7c478bd9Sstevel@tonic-gate if (cont_object->u.cont_obj->num_of_section > maxsec) { 1113*7c478bd9Sstevel@tonic-gate return (-1); 1114*7c478bd9Sstevel@tonic-gate } 1115*7c478bd9Sstevel@tonic-gate 1116*7c478bd9Sstevel@tonic-gate sec_hash = cont_object->u.cont_obj->sec_obj_list; 1117*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 1118*7c478bd9Sstevel@tonic-gate return (-1); 1119*7c478bd9Sstevel@tonic-gate } 1120*7c478bd9Sstevel@tonic-gate 1121*7c478bd9Sstevel@tonic-gate do { 1122*7c478bd9Sstevel@tonic-gate device_fd = 1123*7c478bd9Sstevel@tonic-gate open(cont_object->u.cont_obj->device_pathname, O_RDONLY); 1124*7c478bd9Sstevel@tonic-gate if (device_fd >= 0) { 1125*7c478bd9Sstevel@tonic-gate break; 1126*7c478bd9Sstevel@tonic-gate } 1127*7c478bd9Sstevel@tonic-gate } while ((retrys-- > 0) && (call_devfsadm() == 0)); 1128*7c478bd9Sstevel@tonic-gate 1129*7c478bd9Sstevel@tonic-gate if (device_fd < 0) { 1130*7c478bd9Sstevel@tonic-gate return (-1); 1131*7c478bd9Sstevel@tonic-gate } 1132*7c478bd9Sstevel@tonic-gate 1133*7c478bd9Sstevel@tonic-gate for (count = 0; count < cont_object->u.cont_obj->num_of_section; 1134*7c478bd9Sstevel@tonic-gate count++, section++) { 1135*7c478bd9Sstevel@tonic-gate section->version = -1; 1136*7c478bd9Sstevel@tonic-gate /* populate section_t */ 1137*7c478bd9Sstevel@tonic-gate get_section(device_fd, sec_hash, section); 1138*7c478bd9Sstevel@tonic-gate sec_hash = sec_hash->u.sec_obj->next; 1139*7c478bd9Sstevel@tonic-gate } 1140*7c478bd9Sstevel@tonic-gate 1141*7c478bd9Sstevel@tonic-gate (void) close(device_fd); 1142*7c478bd9Sstevel@tonic-gate return (count); 1143*7c478bd9Sstevel@tonic-gate } 1144*7c478bd9Sstevel@tonic-gate 1145*7c478bd9Sstevel@tonic-gate /* 1146*7c478bd9Sstevel@tonic-gate * Description : 1147*7c478bd9Sstevel@tonic-gate * fru_get_num_segments() returns the current number of segments 1148*7c478bd9Sstevel@tonic-gate * in a section. 1149*7c478bd9Sstevel@tonic-gate * 1150*7c478bd9Sstevel@tonic-gate * Arguments : 1151*7c478bd9Sstevel@tonic-gate * section_hdl_t : section header holding section information. 1152*7c478bd9Sstevel@tonic-gate * 1153*7c478bd9Sstevel@tonic-gate * Return : 1154*7c478bd9Sstevel@tonic-gate * int 1155*7c478bd9Sstevel@tonic-gate * On success, the number of segments in the argument section is 1156*7c478bd9Sstevel@tonic-gate * returned; on error -1 is returned. 1157*7c478bd9Sstevel@tonic-gate */ 1158*7c478bd9Sstevel@tonic-gate 1159*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1160*7c478bd9Sstevel@tonic-gate int 1161*7c478bd9Sstevel@tonic-gate fru_get_num_segments(section_hdl_t section, door_cred_t *cred) 1162*7c478bd9Sstevel@tonic-gate { 1163*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_object; 1164*7c478bd9Sstevel@tonic-gate section_obj_t *sec_obj; 1165*7c478bd9Sstevel@tonic-gate 1166*7c478bd9Sstevel@tonic-gate sec_object = lookup_handle_object(section, SECTION_TYPE); 1167*7c478bd9Sstevel@tonic-gate if (sec_object == NULL) { 1168*7c478bd9Sstevel@tonic-gate return (-1); 1169*7c478bd9Sstevel@tonic-gate } 1170*7c478bd9Sstevel@tonic-gate 1171*7c478bd9Sstevel@tonic-gate sec_obj = sec_object->u.sec_obj; 1172*7c478bd9Sstevel@tonic-gate if (sec_obj == NULL) { 1173*7c478bd9Sstevel@tonic-gate return (-1); 1174*7c478bd9Sstevel@tonic-gate } 1175*7c478bd9Sstevel@tonic-gate 1176*7c478bd9Sstevel@tonic-gate return (sec_obj->num_of_segment); 1177*7c478bd9Sstevel@tonic-gate } 1178*7c478bd9Sstevel@tonic-gate 1179*7c478bd9Sstevel@tonic-gate /* 1180*7c478bd9Sstevel@tonic-gate * Description : 1181*7c478bd9Sstevel@tonic-gate * fru_get_segments() fills an array of structures representing the 1182*7c478bd9Sstevel@tonic-gate * segments in a section. 1183*7c478bd9Sstevel@tonic-gate * 1184*7c478bd9Sstevel@tonic-gate * Arguments : 1185*7c478bd9Sstevel@tonic-gate * section_hdl_t : holds section number. 1186*7c478bd9Sstevel@tonic-gate * segment_t : on success will hold segment information. 1187*7c478bd9Sstevel@tonic-gate * int : maximum number of segment. 1188*7c478bd9Sstevel@tonic-gate * 1189*7c478bd9Sstevel@tonic-gate * Return : 1190*7c478bd9Sstevel@tonic-gate * int 1191*7c478bd9Sstevel@tonic-gate * On success, the number of segment structures written is 1192*7c478bd9Sstevel@tonic-gate * returned; on errno -1 is returned. 1193*7c478bd9Sstevel@tonic-gate */ 1194*7c478bd9Sstevel@tonic-gate 1195*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1196*7c478bd9Sstevel@tonic-gate int 1197*7c478bd9Sstevel@tonic-gate fru_get_segments(section_hdl_t section, segment_t *segment, int maxseg, 1198*7c478bd9Sstevel@tonic-gate door_cred_t *cred) 1199*7c478bd9Sstevel@tonic-gate { 1200*7c478bd9Sstevel@tonic-gate int count; 1201*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_object; 1202*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_object; 1203*7c478bd9Sstevel@tonic-gate section_obj_t *sec_obj; 1204*7c478bd9Sstevel@tonic-gate 1205*7c478bd9Sstevel@tonic-gate sec_object = lookup_handle_object(section, SECTION_TYPE); 1206*7c478bd9Sstevel@tonic-gate if (sec_object == NULL) { 1207*7c478bd9Sstevel@tonic-gate return (-1); 1208*7c478bd9Sstevel@tonic-gate } 1209*7c478bd9Sstevel@tonic-gate 1210*7c478bd9Sstevel@tonic-gate sec_obj = sec_object->u.sec_obj; 1211*7c478bd9Sstevel@tonic-gate if (sec_obj == NULL) { 1212*7c478bd9Sstevel@tonic-gate return (-1); 1213*7c478bd9Sstevel@tonic-gate } 1214*7c478bd9Sstevel@tonic-gate 1215*7c478bd9Sstevel@tonic-gate if (sec_obj->num_of_segment > maxseg) { 1216*7c478bd9Sstevel@tonic-gate return (-1); 1217*7c478bd9Sstevel@tonic-gate } 1218*7c478bd9Sstevel@tonic-gate 1219*7c478bd9Sstevel@tonic-gate seg_object = sec_object->u.sec_obj->seg_obj_list; 1220*7c478bd9Sstevel@tonic-gate if (seg_object == NULL) { 1221*7c478bd9Sstevel@tonic-gate return (-1); 1222*7c478bd9Sstevel@tonic-gate } 1223*7c478bd9Sstevel@tonic-gate 1224*7c478bd9Sstevel@tonic-gate for (count = 0; count < sec_obj->num_of_segment; count++) { 1225*7c478bd9Sstevel@tonic-gate 1226*7c478bd9Sstevel@tonic-gate /* populate segment_t */ 1227*7c478bd9Sstevel@tonic-gate segment->handle = seg_object->obj_hdl; 1228*7c478bd9Sstevel@tonic-gate (void) memcpy(segment->name, 1229*7c478bd9Sstevel@tonic-gate seg_object->u.seg_obj->segment.name, SEG_NAME_LEN); 1230*7c478bd9Sstevel@tonic-gate segment->descriptor = seg_object->u.seg_obj->segment.descriptor; 1231*7c478bd9Sstevel@tonic-gate 1232*7c478bd9Sstevel@tonic-gate segment->offset = seg_object->u.seg_obj->segment.offset; 1233*7c478bd9Sstevel@tonic-gate segment->length = seg_object->u.seg_obj->segment.length; 1234*7c478bd9Sstevel@tonic-gate seg_object = seg_object->u.seg_obj->next; 1235*7c478bd9Sstevel@tonic-gate segment++; 1236*7c478bd9Sstevel@tonic-gate } 1237*7c478bd9Sstevel@tonic-gate return (0); 1238*7c478bd9Sstevel@tonic-gate } 1239*7c478bd9Sstevel@tonic-gate 1240*7c478bd9Sstevel@tonic-gate /* 1241*7c478bd9Sstevel@tonic-gate * Description : 1242*7c478bd9Sstevel@tonic-gate * fru_add_segment() adds a segment to a section. 1243*7c478bd9Sstevel@tonic-gate * 1244*7c478bd9Sstevel@tonic-gate * Arguments : 1245*7c478bd9Sstevel@tonic-gate * section_hdl_t section 1246*7c478bd9Sstevel@tonic-gate * A handle for the section in which to add the segment. 1247*7c478bd9Sstevel@tonic-gate * 1248*7c478bd9Sstevel@tonic-gate * segment_t *segment 1249*7c478bd9Sstevel@tonic-gate * On entry, the "handle" component of "segment" is ignored and the 1250*7c478bd9Sstevel@tonic-gate * remaining components specify the parameters of the segment to be 1251*7c478bd9Sstevel@tonic-gate * added. On return, the "handle" component is set to the handle 1252*7c478bd9Sstevel@tonic-gate * for the added segment. The segment offset is mandatory for FIXED 1253*7c478bd9Sstevel@tonic-gate * segments; otherwise, the offset is advisory. 1254*7c478bd9Sstevel@tonic-gate * 1255*7c478bd9Sstevel@tonic-gate * Return : 1256*7c478bd9Sstevel@tonic-gate * int 1257*7c478bd9Sstevel@tonic-gate * On success, 0 is returned; on error -1 is returned. 1258*7c478bd9Sstevel@tonic-gate * 1259*7c478bd9Sstevel@tonic-gate */ 1260*7c478bd9Sstevel@tonic-gate 1261*7c478bd9Sstevel@tonic-gate int 1262*7c478bd9Sstevel@tonic-gate fru_add_segment(section_hdl_t section, segment_t *segment, 1263*7c478bd9Sstevel@tonic-gate section_hdl_t *newsection, door_cred_t *cred) 1264*7c478bd9Sstevel@tonic-gate { 1265*7c478bd9Sstevel@tonic-gate int fd; 1266*7c478bd9Sstevel@tonic-gate int retval; 1267*7c478bd9Sstevel@tonic-gate int offset; 1268*7c478bd9Sstevel@tonic-gate int sec_size; 1269*7c478bd9Sstevel@tonic-gate int seg_cnt; 1270*7c478bd9Sstevel@tonic-gate int bufsize; 1271*7c478bd9Sstevel@tonic-gate int new_seg_offset; 1272*7c478bd9Sstevel@tonic-gate int new_seg_length; 1273*7c478bd9Sstevel@tonic-gate int fixed_segment; 1274*7c478bd9Sstevel@tonic-gate char trailer[] = { 0x0c, 0x00, 0x00, 0x00, 0x00 }; 1275*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_hash; 1276*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 1277*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 1278*7c478bd9Sstevel@tonic-gate fru_segdesc_t *new_seg_desc; 1279*7c478bd9Sstevel@tonic-gate unsigned char *crcbuf; 1280*7c478bd9Sstevel@tonic-gate section_layout_t sec_layout; 1281*7c478bd9Sstevel@tonic-gate segment_layout_t *seg_layout; 1282*7c478bd9Sstevel@tonic-gate segment_layout_t *segment_buf; 1283*7c478bd9Sstevel@tonic-gate 1284*7c478bd9Sstevel@tonic-gate /* check the effective uid of the client */ 1285*7c478bd9Sstevel@tonic-gate if (cred->dc_euid != 0) { 1286*7c478bd9Sstevel@tonic-gate errno = EPERM; 1287*7c478bd9Sstevel@tonic-gate return (-1); /* not a root */ 1288*7c478bd9Sstevel@tonic-gate } 1289*7c478bd9Sstevel@tonic-gate 1290*7c478bd9Sstevel@tonic-gate /* section hash */ 1291*7c478bd9Sstevel@tonic-gate sec_hash = lookup_handle_object(section, SECTION_TYPE); 1292*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 1293*7c478bd9Sstevel@tonic-gate return (-1); 1294*7c478bd9Sstevel@tonic-gate } 1295*7c478bd9Sstevel@tonic-gate 1296*7c478bd9Sstevel@tonic-gate /* check for read-only section */ 1297*7c478bd9Sstevel@tonic-gate if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { 1298*7c478bd9Sstevel@tonic-gate errno = EPERM; 1299*7c478bd9Sstevel@tonic-gate return (-1); 1300*7c478bd9Sstevel@tonic-gate } 1301*7c478bd9Sstevel@tonic-gate 1302*7c478bd9Sstevel@tonic-gate /* look for duplicate segment */ 1303*7c478bd9Sstevel@tonic-gate seg_hash = sec_hash->u.sec_obj->seg_obj_list; 1304*7c478bd9Sstevel@tonic-gate while (seg_hash != NULL) { 1305*7c478bd9Sstevel@tonic-gate if (strncmp(segment->name, seg_hash->u.seg_obj->segment.name, 1306*7c478bd9Sstevel@tonic-gate SEG_NAME_LEN) == 0) { 1307*7c478bd9Sstevel@tonic-gate errno = EEXIST; 1308*7c478bd9Sstevel@tonic-gate return (-1); /* can't add duplicate segment */ 1309*7c478bd9Sstevel@tonic-gate } 1310*7c478bd9Sstevel@tonic-gate seg_hash = seg_hash->u.seg_obj->next; 1311*7c478bd9Sstevel@tonic-gate } 1312*7c478bd9Sstevel@tonic-gate 1313*7c478bd9Sstevel@tonic-gate /* get the container hash */ 1314*7c478bd9Sstevel@tonic-gate cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, 1315*7c478bd9Sstevel@tonic-gate CONTAINER_TYPE); 1316*7c478bd9Sstevel@tonic-gate if (cont_hash == NULL) { 1317*7c478bd9Sstevel@tonic-gate return (-1); 1318*7c478bd9Sstevel@tonic-gate } 1319*7c478bd9Sstevel@tonic-gate 1320*7c478bd9Sstevel@tonic-gate /* open the container */ 1321*7c478bd9Sstevel@tonic-gate fd = open(cont_hash->u.cont_obj->device_pathname, O_RDWR); 1322*7c478bd9Sstevel@tonic-gate if (fd < 0) { 1323*7c478bd9Sstevel@tonic-gate return (-1); 1324*7c478bd9Sstevel@tonic-gate } 1325*7c478bd9Sstevel@tonic-gate 1326*7c478bd9Sstevel@tonic-gate /* section start here */ 1327*7c478bd9Sstevel@tonic-gate offset = sec_hash->u.sec_obj->section.offset; 1328*7c478bd9Sstevel@tonic-gate 1329*7c478bd9Sstevel@tonic-gate /* read section header layout */ 1330*7c478bd9Sstevel@tonic-gate retval = pread(fd, &sec_layout, sizeof (sec_layout), offset); 1331*7c478bd9Sstevel@tonic-gate if (retval != sizeof (sec_layout)) { 1332*7c478bd9Sstevel@tonic-gate (void) close(fd); 1333*7c478bd9Sstevel@tonic-gate return (-1); 1334*7c478bd9Sstevel@tonic-gate } 1335*7c478bd9Sstevel@tonic-gate 1336*7c478bd9Sstevel@tonic-gate /* check for valid section header */ 1337*7c478bd9Sstevel@tonic-gate if (sec_layout.headertag != SECTION_HDR_TAG) { 1338*7c478bd9Sstevel@tonic-gate /* write a new one */ 1339*7c478bd9Sstevel@tonic-gate sec_layout.headertag = SECTION_HDR_TAG; 1340*7c478bd9Sstevel@tonic-gate sec_layout.headerversion[0] = SECTION_HDR_VER_BIT0; 1341*7c478bd9Sstevel@tonic-gate sec_layout.headerversion[1] = SECTION_HDR_VER_BIT1; 1342*7c478bd9Sstevel@tonic-gate sec_layout.headerlength = sizeof (sec_layout); 1343*7c478bd9Sstevel@tonic-gate sec_layout.segmentcount = 0; 1344*7c478bd9Sstevel@tonic-gate } 1345*7c478bd9Sstevel@tonic-gate 1346*7c478bd9Sstevel@tonic-gate /* section size */ 1347*7c478bd9Sstevel@tonic-gate sec_size = sec_hash->u.sec_obj->section.length; 1348*7c478bd9Sstevel@tonic-gate 1349*7c478bd9Sstevel@tonic-gate /* number of segment in the section */ 1350*7c478bd9Sstevel@tonic-gate seg_cnt = sec_layout.segmentcount; 1351*7c478bd9Sstevel@tonic-gate 1352*7c478bd9Sstevel@tonic-gate /* total sizeof segment + new segment */ 1353*7c478bd9Sstevel@tonic-gate bufsize = sizeof (segment_layout_t) * (seg_cnt + 1); 1354*7c478bd9Sstevel@tonic-gate segment_buf = alloca(bufsize); 1355*7c478bd9Sstevel@tonic-gate if (segment_buf == NULL) { 1356*7c478bd9Sstevel@tonic-gate return (-1); 1357*7c478bd9Sstevel@tonic-gate } 1358*7c478bd9Sstevel@tonic-gate 1359*7c478bd9Sstevel@tonic-gate /* read entire segment header */ 1360*7c478bd9Sstevel@tonic-gate retval = pread(fd, segment_buf, (bufsize - sizeof (segment_layout_t)), 1361*7c478bd9Sstevel@tonic-gate offset + sizeof (section_layout_t)); 1362*7c478bd9Sstevel@tonic-gate if (retval != (bufsize - sizeof (segment_layout_t))) { 1363*7c478bd9Sstevel@tonic-gate (void) close(fd); 1364*7c478bd9Sstevel@tonic-gate return (-1); 1365*7c478bd9Sstevel@tonic-gate } 1366*7c478bd9Sstevel@tonic-gate 1367*7c478bd9Sstevel@tonic-gate new_seg_offset = segment->offset; /* new segment offset */ 1368*7c478bd9Sstevel@tonic-gate new_seg_length = segment->length; /* new segment length */ 1369*7c478bd9Sstevel@tonic-gate 1370*7c478bd9Sstevel@tonic-gate new_seg_desc = (fru_segdesc_t *)&segment->descriptor; 1371*7c478bd9Sstevel@tonic-gate 1372*7c478bd9Sstevel@tonic-gate fixed_segment = new_seg_desc->field.fixed; 1373*7c478bd9Sstevel@tonic-gate 1374*7c478bd9Sstevel@tonic-gate /* get new offset for new segment to be addedd */ 1375*7c478bd9Sstevel@tonic-gate retval = find_offset((char *)segment_buf, seg_cnt, sec_size, 1376*7c478bd9Sstevel@tonic-gate &new_seg_offset, new_seg_length, fixed_segment, fd); 1377*7c478bd9Sstevel@tonic-gate 1378*7c478bd9Sstevel@tonic-gate if (retval != 0) { 1379*7c478bd9Sstevel@tonic-gate (void) close(fd); 1380*7c478bd9Sstevel@tonic-gate errno = EAGAIN; 1381*7c478bd9Sstevel@tonic-gate return (-1); 1382*7c478bd9Sstevel@tonic-gate } 1383*7c478bd9Sstevel@tonic-gate 1384*7c478bd9Sstevel@tonic-gate /* copy new segment data in segment layout */ 1385*7c478bd9Sstevel@tonic-gate seg_layout = (segment_layout_t *)(segment_buf + seg_cnt); 1386*7c478bd9Sstevel@tonic-gate (void) memcpy(&seg_layout->name, segment->name, SEG_NAME_LEN); 1387*7c478bd9Sstevel@tonic-gate (void) memcpy(seg_layout->descriptor, &segment->descriptor, 1388*7c478bd9Sstevel@tonic-gate sizeof (uint32_t)); 1389*7c478bd9Sstevel@tonic-gate seg_layout->length = segment->length; 1390*7c478bd9Sstevel@tonic-gate seg_layout->offset = new_seg_offset; /* new segment offset */ 1391*7c478bd9Sstevel@tonic-gate 1392*7c478bd9Sstevel@tonic-gate sec_layout.segmentcount += 1; 1393*7c478bd9Sstevel@tonic-gate 1394*7c478bd9Sstevel@tonic-gate crcbuf = alloca(sizeof (section_layout_t) + bufsize); 1395*7c478bd9Sstevel@tonic-gate if (crcbuf == NULL) { 1396*7c478bd9Sstevel@tonic-gate (void) close(fd); 1397*7c478bd9Sstevel@tonic-gate return (-1); 1398*7c478bd9Sstevel@tonic-gate } 1399*7c478bd9Sstevel@tonic-gate 1400*7c478bd9Sstevel@tonic-gate sec_layout.headercrc8 = 0; 1401*7c478bd9Sstevel@tonic-gate sec_layout.headerlength += sizeof (segment_layout_t); 1402*7c478bd9Sstevel@tonic-gate 1403*7c478bd9Sstevel@tonic-gate (void) memcpy(crcbuf, (char *)&sec_layout, sizeof (section_layout_t)); 1404*7c478bd9Sstevel@tonic-gate (void) memcpy(crcbuf + sizeof (section_layout_t), segment_buf, bufsize); 1405*7c478bd9Sstevel@tonic-gate 1406*7c478bd9Sstevel@tonic-gate sec_layout.headercrc8 = compute_crc8(crcbuf, bufsize + 1407*7c478bd9Sstevel@tonic-gate sizeof (section_layout_t)); 1408*7c478bd9Sstevel@tonic-gate 1409*7c478bd9Sstevel@tonic-gate /* write section header */ 1410*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, &sec_layout, sizeof (section_layout_t), offset); 1411*7c478bd9Sstevel@tonic-gate if (retval != sizeof (section_layout_t)) { 1412*7c478bd9Sstevel@tonic-gate (void) close(fd); 1413*7c478bd9Sstevel@tonic-gate return (-1); 1414*7c478bd9Sstevel@tonic-gate } 1415*7c478bd9Sstevel@tonic-gate 1416*7c478bd9Sstevel@tonic-gate /* write segment header */ 1417*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, segment_buf, bufsize, offset + 1418*7c478bd9Sstevel@tonic-gate sizeof (section_layout_t)); 1419*7c478bd9Sstevel@tonic-gate if (retval != bufsize) { 1420*7c478bd9Sstevel@tonic-gate (void) close(fd); 1421*7c478bd9Sstevel@tonic-gate return (-1); 1422*7c478bd9Sstevel@tonic-gate } 1423*7c478bd9Sstevel@tonic-gate 1424*7c478bd9Sstevel@tonic-gate /* write segment trailer */ 1425*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, &trailer, sizeof (trailer), new_seg_offset); 1426*7c478bd9Sstevel@tonic-gate if (retval != sizeof (trailer)) { 1427*7c478bd9Sstevel@tonic-gate (void) close(fd); 1428*7c478bd9Sstevel@tonic-gate return (-1); 1429*7c478bd9Sstevel@tonic-gate } 1430*7c478bd9Sstevel@tonic-gate 1431*7c478bd9Sstevel@tonic-gate (void) close(fd); 1432*7c478bd9Sstevel@tonic-gate 1433*7c478bd9Sstevel@tonic-gate /* create new segment hash object */ 1434*7c478bd9Sstevel@tonic-gate seg_hash = create_segment_hash_object(); 1435*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 1436*7c478bd9Sstevel@tonic-gate return (-1); 1437*7c478bd9Sstevel@tonic-gate } 1438*7c478bd9Sstevel@tonic-gate 1439*7c478bd9Sstevel@tonic-gate add_hashobject_to_hashtable(seg_hash); 1440*7c478bd9Sstevel@tonic-gate 1441*7c478bd9Sstevel@tonic-gate copy_segment_layout(&seg_hash->u.seg_obj->segment, seg_layout); 1442*7c478bd9Sstevel@tonic-gate 1443*7c478bd9Sstevel@tonic-gate add_to_seg_object_list(sec_hash, seg_hash); 1444*7c478bd9Sstevel@tonic-gate 1445*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->num_of_segment += 1; 1446*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset = new_seg_offset; 1447*7c478bd9Sstevel@tonic-gate *newsection = section; /* return the new section handle */ 1448*7c478bd9Sstevel@tonic-gate return (0); 1449*7c478bd9Sstevel@tonic-gate } 1450*7c478bd9Sstevel@tonic-gate 1451*7c478bd9Sstevel@tonic-gate static void 1452*7c478bd9Sstevel@tonic-gate free_pkt_object_list(hash_obj_t *hash_obj) 1453*7c478bd9Sstevel@tonic-gate { 1454*7c478bd9Sstevel@tonic-gate hash_obj_t *next_obj; 1455*7c478bd9Sstevel@tonic-gate hash_obj_t *free_obj; 1456*7c478bd9Sstevel@tonic-gate 1457*7c478bd9Sstevel@tonic-gate next_obj = hash_obj->u.seg_obj->pkt_obj_list; 1458*7c478bd9Sstevel@tonic-gate while (next_obj != NULL) { 1459*7c478bd9Sstevel@tonic-gate free_obj = next_obj; 1460*7c478bd9Sstevel@tonic-gate next_obj = next_obj->u.pkt_obj->next; 1461*7c478bd9Sstevel@tonic-gate /* if prev is NULL it's the first object in the list */ 1462*7c478bd9Sstevel@tonic-gate if (free_obj->prev == NULL) { 1463*7c478bd9Sstevel@tonic-gate hash_table[(free_obj->obj_hdl % TABLE_SIZE)] = 1464*7c478bd9Sstevel@tonic-gate free_obj->next; 1465*7c478bd9Sstevel@tonic-gate if (free_obj->next != NULL) { 1466*7c478bd9Sstevel@tonic-gate free_obj->next->prev = free_obj->prev; 1467*7c478bd9Sstevel@tonic-gate } 1468*7c478bd9Sstevel@tonic-gate } else { 1469*7c478bd9Sstevel@tonic-gate free_obj->prev->next = free_obj->next; 1470*7c478bd9Sstevel@tonic-gate if (free_obj->next != NULL) { 1471*7c478bd9Sstevel@tonic-gate free_obj->next->prev = free_obj->prev; 1472*7c478bd9Sstevel@tonic-gate } 1473*7c478bd9Sstevel@tonic-gate } 1474*7c478bd9Sstevel@tonic-gate 1475*7c478bd9Sstevel@tonic-gate free(free_obj->u.pkt_obj->payload); 1476*7c478bd9Sstevel@tonic-gate free(free_obj->u.pkt_obj); 1477*7c478bd9Sstevel@tonic-gate free(free_obj); 1478*7c478bd9Sstevel@tonic-gate } 1479*7c478bd9Sstevel@tonic-gate 1480*7c478bd9Sstevel@tonic-gate hash_obj->u.seg_obj->pkt_obj_list = NULL; 1481*7c478bd9Sstevel@tonic-gate } 1482*7c478bd9Sstevel@tonic-gate 1483*7c478bd9Sstevel@tonic-gate static void 1484*7c478bd9Sstevel@tonic-gate free_segment_hash(handle_t handle, hash_obj_t *sec_hash) 1485*7c478bd9Sstevel@tonic-gate { 1486*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 1487*7c478bd9Sstevel@tonic-gate hash_obj_t *next_hash; 1488*7c478bd9Sstevel@tonic-gate 1489*7c478bd9Sstevel@tonic-gate seg_hash = sec_hash->u.sec_obj->seg_obj_list; 1490*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 1491*7c478bd9Sstevel@tonic-gate return; 1492*7c478bd9Sstevel@tonic-gate } 1493*7c478bd9Sstevel@tonic-gate 1494*7c478bd9Sstevel@tonic-gate if (seg_hash->obj_hdl == handle) { 1495*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->seg_obj_list = seg_hash->u.seg_obj->next; 1496*7c478bd9Sstevel@tonic-gate } else { 1497*7c478bd9Sstevel@tonic-gate while (seg_hash->obj_hdl != handle) { 1498*7c478bd9Sstevel@tonic-gate next_hash = seg_hash; 1499*7c478bd9Sstevel@tonic-gate seg_hash = seg_hash->u.seg_obj->next; 1500*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 1501*7c478bd9Sstevel@tonic-gate return; 1502*7c478bd9Sstevel@tonic-gate } 1503*7c478bd9Sstevel@tonic-gate } 1504*7c478bd9Sstevel@tonic-gate next_hash->u.seg_obj->next = seg_hash->u.seg_obj->next; 1505*7c478bd9Sstevel@tonic-gate } 1506*7c478bd9Sstevel@tonic-gate 1507*7c478bd9Sstevel@tonic-gate if (seg_hash->prev == NULL) { 1508*7c478bd9Sstevel@tonic-gate hash_table[(seg_hash->obj_hdl % TABLE_SIZE)] = seg_hash->next; 1509*7c478bd9Sstevel@tonic-gate if (seg_hash->next != NULL) { 1510*7c478bd9Sstevel@tonic-gate seg_hash->next->prev = NULL; 1511*7c478bd9Sstevel@tonic-gate } 1512*7c478bd9Sstevel@tonic-gate } else { 1513*7c478bd9Sstevel@tonic-gate seg_hash->prev->next = seg_hash->next; 1514*7c478bd9Sstevel@tonic-gate if (seg_hash->next != NULL) { 1515*7c478bd9Sstevel@tonic-gate seg_hash->next->prev = seg_hash->prev; 1516*7c478bd9Sstevel@tonic-gate } 1517*7c478bd9Sstevel@tonic-gate } 1518*7c478bd9Sstevel@tonic-gate 1519*7c478bd9Sstevel@tonic-gate free_pkt_object_list(seg_hash); 1520*7c478bd9Sstevel@tonic-gate free(seg_hash->u.seg_obj); 1521*7c478bd9Sstevel@tonic-gate free(seg_hash); 1522*7c478bd9Sstevel@tonic-gate } 1523*7c478bd9Sstevel@tonic-gate 1524*7c478bd9Sstevel@tonic-gate /* 1525*7c478bd9Sstevel@tonic-gate * Description : 1526*7c478bd9Sstevel@tonic-gate * fru_delete_segment() deletes a segment from a section; the 1527*7c478bd9Sstevel@tonic-gate * associated container data is not altered. 1528*7c478bd9Sstevel@tonic-gate * 1529*7c478bd9Sstevel@tonic-gate * Arguments : segment_hdl_t segment handle. 1530*7c478bd9Sstevel@tonic-gate * section_hdl_t new section handle. 1531*7c478bd9Sstevel@tonic-gate * 1532*7c478bd9Sstevel@tonic-gate * Return : 1533*7c478bd9Sstevel@tonic-gate * int 1534*7c478bd9Sstevel@tonic-gate * On success, 0 returned; On error -1 is returned. 1535*7c478bd9Sstevel@tonic-gate */ 1536*7c478bd9Sstevel@tonic-gate 1537*7c478bd9Sstevel@tonic-gate int 1538*7c478bd9Sstevel@tonic-gate fru_delete_segment(segment_hdl_t segment, section_hdl_t *newsection, 1539*7c478bd9Sstevel@tonic-gate door_cred_t *cred) 1540*7c478bd9Sstevel@tonic-gate { 1541*7c478bd9Sstevel@tonic-gate int num_of_seg; 1542*7c478bd9Sstevel@tonic-gate int bufsize; 1543*7c478bd9Sstevel@tonic-gate int count; 1544*7c478bd9Sstevel@tonic-gate int retval; 1545*7c478bd9Sstevel@tonic-gate int fd; 1546*7c478bd9Sstevel@tonic-gate int segnum; 1547*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 1548*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 1549*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_hash; 1550*7c478bd9Sstevel@tonic-gate hash_obj_t *tmp_hash; 1551*7c478bd9Sstevel@tonic-gate unsigned char *buffer; 1552*7c478bd9Sstevel@tonic-gate fru_segdesc_t *desc; 1553*7c478bd9Sstevel@tonic-gate segment_layout_t *seg_buf; 1554*7c478bd9Sstevel@tonic-gate section_layout_t *sec_layout; 1555*7c478bd9Sstevel@tonic-gate segment_layout_t *seg_layout; 1556*7c478bd9Sstevel@tonic-gate segment_layout_t *next_layout; 1557*7c478bd9Sstevel@tonic-gate 1558*7c478bd9Sstevel@tonic-gate /* check the effective uid of the client */ 1559*7c478bd9Sstevel@tonic-gate if (cred->dc_euid != 0) { 1560*7c478bd9Sstevel@tonic-gate errno = EPERM; 1561*7c478bd9Sstevel@tonic-gate return (-1); /* not a root */ 1562*7c478bd9Sstevel@tonic-gate } 1563*7c478bd9Sstevel@tonic-gate 1564*7c478bd9Sstevel@tonic-gate seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); 1565*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 1566*7c478bd9Sstevel@tonic-gate return (-1); 1567*7c478bd9Sstevel@tonic-gate } 1568*7c478bd9Sstevel@tonic-gate 1569*7c478bd9Sstevel@tonic-gate desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; 1570*7c478bd9Sstevel@tonic-gate if (!(desc->field.field_perm & SEGMENT_DELETE)) { 1571*7c478bd9Sstevel@tonic-gate errno = EPERM; 1572*7c478bd9Sstevel@tonic-gate return (-1); /* can't delete this segment */ 1573*7c478bd9Sstevel@tonic-gate } 1574*7c478bd9Sstevel@tonic-gate 1575*7c478bd9Sstevel@tonic-gate sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 1576*7c478bd9Sstevel@tonic-gate SECTION_TYPE); 1577*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 1578*7c478bd9Sstevel@tonic-gate return (-1); 1579*7c478bd9Sstevel@tonic-gate } 1580*7c478bd9Sstevel@tonic-gate 1581*7c478bd9Sstevel@tonic-gate if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { 1582*7c478bd9Sstevel@tonic-gate errno = EPERM; 1583*7c478bd9Sstevel@tonic-gate return (-1); 1584*7c478bd9Sstevel@tonic-gate } 1585*7c478bd9Sstevel@tonic-gate 1586*7c478bd9Sstevel@tonic-gate num_of_seg = sec_hash->u.sec_obj->num_of_segment; 1587*7c478bd9Sstevel@tonic-gate 1588*7c478bd9Sstevel@tonic-gate bufsize = (sizeof (segment_layout_t) * num_of_seg); 1589*7c478bd9Sstevel@tonic-gate 1590*7c478bd9Sstevel@tonic-gate seg_buf = alloca(bufsize); 1591*7c478bd9Sstevel@tonic-gate if (seg_buf == NULL) { 1592*7c478bd9Sstevel@tonic-gate return (-1); 1593*7c478bd9Sstevel@tonic-gate } 1594*7c478bd9Sstevel@tonic-gate 1595*7c478bd9Sstevel@tonic-gate segnum = 0; 1596*7c478bd9Sstevel@tonic-gate for (tmp_hash = sec_hash->u.sec_obj->seg_obj_list; tmp_hash != NULL; 1597*7c478bd9Sstevel@tonic-gate tmp_hash = tmp_hash->u.seg_obj->next) { 1598*7c478bd9Sstevel@tonic-gate if (tmp_hash->obj_hdl == segment) { 1599*7c478bd9Sstevel@tonic-gate break; 1600*7c478bd9Sstevel@tonic-gate } 1601*7c478bd9Sstevel@tonic-gate segnum++; 1602*7c478bd9Sstevel@tonic-gate } 1603*7c478bd9Sstevel@tonic-gate 1604*7c478bd9Sstevel@tonic-gate cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, 1605*7c478bd9Sstevel@tonic-gate CONTAINER_TYPE); 1606*7c478bd9Sstevel@tonic-gate if (cont_hash == NULL) { 1607*7c478bd9Sstevel@tonic-gate return (-1); 1608*7c478bd9Sstevel@tonic-gate } 1609*7c478bd9Sstevel@tonic-gate 1610*7c478bd9Sstevel@tonic-gate fd = open(cont_hash->u.cont_obj->device_pathname, O_RDWR); 1611*7c478bd9Sstevel@tonic-gate if (fd < 0) { 1612*7c478bd9Sstevel@tonic-gate return (-1); 1613*7c478bd9Sstevel@tonic-gate } 1614*7c478bd9Sstevel@tonic-gate 1615*7c478bd9Sstevel@tonic-gate sec_layout = alloca(sizeof (section_layout_t)); 1616*7c478bd9Sstevel@tonic-gate if (sec_layout == NULL) { 1617*7c478bd9Sstevel@tonic-gate (void) close(fd); 1618*7c478bd9Sstevel@tonic-gate return (-1); 1619*7c478bd9Sstevel@tonic-gate } 1620*7c478bd9Sstevel@tonic-gate 1621*7c478bd9Sstevel@tonic-gate /* read section layout header */ 1622*7c478bd9Sstevel@tonic-gate retval = pread(fd, sec_layout, sizeof (section_layout_t), 1623*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->section.offset); 1624*7c478bd9Sstevel@tonic-gate if (retval != sizeof (section_layout_t)) { 1625*7c478bd9Sstevel@tonic-gate (void) close(fd); 1626*7c478bd9Sstevel@tonic-gate return (-1); 1627*7c478bd9Sstevel@tonic-gate } 1628*7c478bd9Sstevel@tonic-gate 1629*7c478bd9Sstevel@tonic-gate /* read segment header layout */ 1630*7c478bd9Sstevel@tonic-gate retval = pread(fd, seg_buf, bufsize, 1631*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->section.offset + sizeof (section_layout_t)); 1632*7c478bd9Sstevel@tonic-gate if (retval != bufsize) { 1633*7c478bd9Sstevel@tonic-gate (void) close(fd); 1634*7c478bd9Sstevel@tonic-gate return (-1); 1635*7c478bd9Sstevel@tonic-gate } 1636*7c478bd9Sstevel@tonic-gate 1637*7c478bd9Sstevel@tonic-gate seg_layout = (segment_layout_t *)(seg_buf + segnum); 1638*7c478bd9Sstevel@tonic-gate next_layout = seg_layout; 1639*7c478bd9Sstevel@tonic-gate for (count = segnum; 1640*7c478bd9Sstevel@tonic-gate count < sec_hash->u.sec_obj->num_of_segment - 1; count++) { 1641*7c478bd9Sstevel@tonic-gate next_layout++; 1642*7c478bd9Sstevel@tonic-gate (void) memcpy(seg_layout, next_layout, 1643*7c478bd9Sstevel@tonic-gate sizeof (segment_layout_t)); 1644*7c478bd9Sstevel@tonic-gate seg_layout++; 1645*7c478bd9Sstevel@tonic-gate } 1646*7c478bd9Sstevel@tonic-gate 1647*7c478bd9Sstevel@tonic-gate (void) memset(seg_layout, '\0', sizeof (segment_layout_t)); 1648*7c478bd9Sstevel@tonic-gate 1649*7c478bd9Sstevel@tonic-gate sec_layout->headercrc8 = 0; 1650*7c478bd9Sstevel@tonic-gate 1651*7c478bd9Sstevel@tonic-gate sec_layout->headerlength -= sizeof (segment_layout_t); 1652*7c478bd9Sstevel@tonic-gate sec_layout->segmentcount -= 1; 1653*7c478bd9Sstevel@tonic-gate 1654*7c478bd9Sstevel@tonic-gate buffer = alloca(sec_layout->headerlength); 1655*7c478bd9Sstevel@tonic-gate if (buffer == NULL) { 1656*7c478bd9Sstevel@tonic-gate (void) close(fd); 1657*7c478bd9Sstevel@tonic-gate return (-1); 1658*7c478bd9Sstevel@tonic-gate } 1659*7c478bd9Sstevel@tonic-gate 1660*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, sec_layout, sizeof (section_layout_t)); 1661*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer + sizeof (section_layout_t), seg_buf, bufsize - 1662*7c478bd9Sstevel@tonic-gate sizeof (segment_layout_t)); 1663*7c478bd9Sstevel@tonic-gate sec_layout->headercrc8 = compute_crc8(buffer, sec_layout->headerlength); 1664*7c478bd9Sstevel@tonic-gate 1665*7c478bd9Sstevel@tonic-gate /* write section header with update crc8 and header length */ 1666*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, sec_layout, sizeof (section_layout_t), 1667*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->section.offset); 1668*7c478bd9Sstevel@tonic-gate if (retval != sizeof (section_layout_t)) { 1669*7c478bd9Sstevel@tonic-gate (void) close(fd); 1670*7c478bd9Sstevel@tonic-gate return (-1); 1671*7c478bd9Sstevel@tonic-gate } 1672*7c478bd9Sstevel@tonic-gate 1673*7c478bd9Sstevel@tonic-gate /* write the update segment header */ 1674*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, seg_buf, bufsize, 1675*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->section.offset + sizeof (section_layout_t)); 1676*7c478bd9Sstevel@tonic-gate (void) close(fd); 1677*7c478bd9Sstevel@tonic-gate if (retval != bufsize) { 1678*7c478bd9Sstevel@tonic-gate return (-1); 1679*7c478bd9Sstevel@tonic-gate } 1680*7c478bd9Sstevel@tonic-gate 1681*7c478bd9Sstevel@tonic-gate free_segment_hash(segment, sec_hash); 1682*7c478bd9Sstevel@tonic-gate 1683*7c478bd9Sstevel@tonic-gate *newsection = sec_hash->obj_hdl; 1684*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->num_of_segment = sec_layout->segmentcount; 1685*7c478bd9Sstevel@tonic-gate 1686*7c478bd9Sstevel@tonic-gate return (0); 1687*7c478bd9Sstevel@tonic-gate } 1688*7c478bd9Sstevel@tonic-gate 1689*7c478bd9Sstevel@tonic-gate /* 1690*7c478bd9Sstevel@tonic-gate * Description : 1691*7c478bd9Sstevel@tonic-gate * fru_read_segment() reads the raw contents of a segment. 1692*7c478bd9Sstevel@tonic-gate * 1693*7c478bd9Sstevel@tonic-gate * Arguments : segment_hdl_t : segment handle. 1694*7c478bd9Sstevel@tonic-gate * void * : buffer containing segment data when function returns. 1695*7c478bd9Sstevel@tonic-gate * size_t :number of bytes. 1696*7c478bd9Sstevel@tonic-gate * 1697*7c478bd9Sstevel@tonic-gate * Return : 1698*7c478bd9Sstevel@tonic-gate * int 1699*7c478bd9Sstevel@tonic-gate * On success, the number of bytes read is returned; 1700*7c478bd9Sstevel@tonic-gate * 1701*7c478bd9Sstevel@tonic-gate * Notes : 1702*7c478bd9Sstevel@tonic-gate * Segments containing packets can be read in structured fashion 1703*7c478bd9Sstevel@tonic-gate * using the fru_get_packets() and fru_get_payload() primitives;the 1704*7c478bd9Sstevel@tonic-gate * entire byte range of a segment can be read using 1705*7c478bd9Sstevel@tonic-gate * fru_read_segment(). 1706*7c478bd9Sstevel@tonic-gate */ 1707*7c478bd9Sstevel@tonic-gate 1708*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 1709*7c478bd9Sstevel@tonic-gate ssize_t 1710*7c478bd9Sstevel@tonic-gate fru_read_segment(segment_hdl_t segment, void *buffer, size_t nbytes, 1711*7c478bd9Sstevel@tonic-gate door_cred_t *cred) 1712*7c478bd9Sstevel@tonic-gate { 1713*7c478bd9Sstevel@tonic-gate int fd; 1714*7c478bd9Sstevel@tonic-gate int retval; 1715*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 1716*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 1717*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_hash; 1718*7c478bd9Sstevel@tonic-gate 1719*7c478bd9Sstevel@tonic-gate /* segment hash object */ 1720*7c478bd9Sstevel@tonic-gate seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); 1721*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 1722*7c478bd9Sstevel@tonic-gate return (-1); 1723*7c478bd9Sstevel@tonic-gate } 1724*7c478bd9Sstevel@tonic-gate 1725*7c478bd9Sstevel@tonic-gate /* section hash object */ 1726*7c478bd9Sstevel@tonic-gate sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 1727*7c478bd9Sstevel@tonic-gate SECTION_TYPE); 1728*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 1729*7c478bd9Sstevel@tonic-gate return (-1); 1730*7c478bd9Sstevel@tonic-gate } 1731*7c478bd9Sstevel@tonic-gate 1732*7c478bd9Sstevel@tonic-gate /* container hash object */ 1733*7c478bd9Sstevel@tonic-gate cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, 1734*7c478bd9Sstevel@tonic-gate CONTAINER_TYPE); 1735*7c478bd9Sstevel@tonic-gate if (cont_hash == NULL) { 1736*7c478bd9Sstevel@tonic-gate return (-1); 1737*7c478bd9Sstevel@tonic-gate } 1738*7c478bd9Sstevel@tonic-gate 1739*7c478bd9Sstevel@tonic-gate if (seg_hash->u.seg_obj->segment.length < nbytes) { 1740*7c478bd9Sstevel@tonic-gate return (-1); 1741*7c478bd9Sstevel@tonic-gate } 1742*7c478bd9Sstevel@tonic-gate 1743*7c478bd9Sstevel@tonic-gate fd = open(cont_hash->u.cont_obj->device_pathname, O_RDONLY); 1744*7c478bd9Sstevel@tonic-gate if (fd < 0) { 1745*7c478bd9Sstevel@tonic-gate return (-1); 1746*7c478bd9Sstevel@tonic-gate } 1747*7c478bd9Sstevel@tonic-gate 1748*7c478bd9Sstevel@tonic-gate switch (sec_hash->u.sec_obj->encoding) { 1749*7c478bd9Sstevel@tonic-gate case ENC_STANDARD: 1750*7c478bd9Sstevel@tonic-gate retval = pread(fd, buffer, nbytes, 1751*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->segment.offset); 1752*7c478bd9Sstevel@tonic-gate (void) close(fd); 1753*7c478bd9Sstevel@tonic-gate if (retval != nbytes) { 1754*7c478bd9Sstevel@tonic-gate return (-1); 1755*7c478bd9Sstevel@tonic-gate } 1756*7c478bd9Sstevel@tonic-gate break; 1757*7c478bd9Sstevel@tonic-gate 1758*7c478bd9Sstevel@tonic-gate case ENC_SPD: { 1759*7c478bd9Sstevel@tonic-gate char *spd_buf; 1760*7c478bd9Sstevel@tonic-gate uchar_t *ptr; 1761*7c478bd9Sstevel@tonic-gate size_t len; 1762*7c478bd9Sstevel@tonic-gate 1763*7c478bd9Sstevel@tonic-gate spd_buf = alloca(sec_hash->u.sec_obj->section.length); 1764*7c478bd9Sstevel@tonic-gate if (spd_buf == NULL) 1765*7c478bd9Sstevel@tonic-gate retval = -1; 1766*7c478bd9Sstevel@tonic-gate else { 1767*7c478bd9Sstevel@tonic-gate retval = get_spd_data(fd, spd_buf, 1768*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->section.length, 1769*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->segment.offset); 1770*7c478bd9Sstevel@tonic-gate } 1771*7c478bd9Sstevel@tonic-gate (void) close(fd); 1772*7c478bd9Sstevel@tonic-gate if (retval != 0) { 1773*7c478bd9Sstevel@tonic-gate return (-1); 1774*7c478bd9Sstevel@tonic-gate } 1775*7c478bd9Sstevel@tonic-gate retval = cvrt_dim_data(spd_buf, 1776*7c478bd9Sstevel@tonic-gate sec_hash->u.sec_obj->section.length, &ptr, &len); 1777*7c478bd9Sstevel@tonic-gate if (retval != 0) { 1778*7c478bd9Sstevel@tonic-gate return (-1); 1779*7c478bd9Sstevel@tonic-gate } 1780*7c478bd9Sstevel@tonic-gate if (nbytes > len) 1781*7c478bd9Sstevel@tonic-gate nbytes = len; 1782*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, ptr, nbytes); 1783*7c478bd9Sstevel@tonic-gate free(ptr); 1784*7c478bd9Sstevel@tonic-gate break; 1785*7c478bd9Sstevel@tonic-gate } 1786*7c478bd9Sstevel@tonic-gate 1787*7c478bd9Sstevel@tonic-gate default: 1788*7c478bd9Sstevel@tonic-gate return (-1); 1789*7c478bd9Sstevel@tonic-gate } 1790*7c478bd9Sstevel@tonic-gate 1791*7c478bd9Sstevel@tonic-gate return (nbytes); 1792*7c478bd9Sstevel@tonic-gate } 1793*7c478bd9Sstevel@tonic-gate 1794*7c478bd9Sstevel@tonic-gate /* 1795*7c478bd9Sstevel@tonic-gate * Description : 1796*7c478bd9Sstevel@tonic-gate * fru_write_segment() writes a raw segment. 1797*7c478bd9Sstevel@tonic-gate * 1798*7c478bd9Sstevel@tonic-gate * Arguments : segment_hdl_t :segment handle. 1799*7c478bd9Sstevel@tonic-gate * const void * : data buffer. 1800*7c478bd9Sstevel@tonic-gate * size_t : number of bytes. 1801*7c478bd9Sstevel@tonic-gate * segment_hdl_t : new segment handle. 1802*7c478bd9Sstevel@tonic-gate * 1803*7c478bd9Sstevel@tonic-gate * Returns : 1804*7c478bd9Sstevel@tonic-gate * int 1805*7c478bd9Sstevel@tonic-gate * On success, the number of bytes written is returned 1806*7c478bd9Sstevel@tonic-gate * 1807*7c478bd9Sstevel@tonic-gate */ 1808*7c478bd9Sstevel@tonic-gate /*ARGSUSED*/ 1809*7c478bd9Sstevel@tonic-gate int 1810*7c478bd9Sstevel@tonic-gate fru_write_segment(segment_hdl_t segment, const void *data, size_t nbytes, 1811*7c478bd9Sstevel@tonic-gate segment_hdl_t *newsegment, door_cred_t *cred) 1812*7c478bd9Sstevel@tonic-gate { 1813*7c478bd9Sstevel@tonic-gate return (ENOTSUP); 1814*7c478bd9Sstevel@tonic-gate } 1815*7c478bd9Sstevel@tonic-gate 1816*7c478bd9Sstevel@tonic-gate 1817*7c478bd9Sstevel@tonic-gate static int 1818*7c478bd9Sstevel@tonic-gate get_packet(int device_fd, void *buffer, int size, int offset) 1819*7c478bd9Sstevel@tonic-gate { 1820*7c478bd9Sstevel@tonic-gate int retval; 1821*7c478bd9Sstevel@tonic-gate 1822*7c478bd9Sstevel@tonic-gate retval = pread(device_fd, (char *)buffer, size, offset); 1823*7c478bd9Sstevel@tonic-gate if (retval != -1) { 1824*7c478bd9Sstevel@tonic-gate return (0); 1825*7c478bd9Sstevel@tonic-gate } 1826*7c478bd9Sstevel@tonic-gate return (-1); 1827*7c478bd9Sstevel@tonic-gate } 1828*7c478bd9Sstevel@tonic-gate 1829*7c478bd9Sstevel@tonic-gate static uint32_t 1830*7c478bd9Sstevel@tonic-gate get_checksum_crc(hash_obj_t *seg_hash, int data_size) 1831*7c478bd9Sstevel@tonic-gate { 1832*7c478bd9Sstevel@tonic-gate int protection; 1833*7c478bd9Sstevel@tonic-gate int offset = 0; 1834*7c478bd9Sstevel@tonic-gate uint32_t crc; 1835*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 1836*7c478bd9Sstevel@tonic-gate hash_obj_t *pkt_hash; 1837*7c478bd9Sstevel@tonic-gate unsigned char *buffer; 1838*7c478bd9Sstevel@tonic-gate 1839*7c478bd9Sstevel@tonic-gate sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 1840*7c478bd9Sstevel@tonic-gate SECTION_TYPE); 1841*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 1842*7c478bd9Sstevel@tonic-gate return ((uint32_t)-1); 1843*7c478bd9Sstevel@tonic-gate } 1844*7c478bd9Sstevel@tonic-gate 1845*7c478bd9Sstevel@tonic-gate buffer = alloca(data_size); 1846*7c478bd9Sstevel@tonic-gate if (buffer == NULL) { 1847*7c478bd9Sstevel@tonic-gate return ((uint32_t)-1); 1848*7c478bd9Sstevel@tonic-gate } 1849*7c478bd9Sstevel@tonic-gate 1850*7c478bd9Sstevel@tonic-gate /* traverse the packet object list for all the tags and payload */ 1851*7c478bd9Sstevel@tonic-gate for (pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; 1852*7c478bd9Sstevel@tonic-gate pkt_hash != NULL; pkt_hash = pkt_hash->u.pkt_obj->next) { 1853*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer + offset, &pkt_hash->u.pkt_obj->tag, 1854*7c478bd9Sstevel@tonic-gate pkt_hash->u.pkt_obj->tag_size); 1855*7c478bd9Sstevel@tonic-gate offset += pkt_hash->u.pkt_obj->tag_size; 1856*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer + offset, pkt_hash->u.pkt_obj->payload, 1857*7c478bd9Sstevel@tonic-gate pkt_hash->u.pkt_obj->paylen); 1858*7c478bd9Sstevel@tonic-gate offset += pkt_hash->u.pkt_obj->paylen; 1859*7c478bd9Sstevel@tonic-gate } 1860*7c478bd9Sstevel@tonic-gate 1861*7c478bd9Sstevel@tonic-gate protection = sec_hash->u.sec_obj->section.protection; 1862*7c478bd9Sstevel@tonic-gate 1863*7c478bd9Sstevel@tonic-gate if (protection == READ_ONLY_SECTION) { /* read-only section */ 1864*7c478bd9Sstevel@tonic-gate crc = compute_crc32(buffer, data_size); 1865*7c478bd9Sstevel@tonic-gate } else { /* read/write section */ 1866*7c478bd9Sstevel@tonic-gate crc = compute_checksum32(buffer, data_size); 1867*7c478bd9Sstevel@tonic-gate } 1868*7c478bd9Sstevel@tonic-gate return (crc); /* computed crc */ 1869*7c478bd9Sstevel@tonic-gate } 1870*7c478bd9Sstevel@tonic-gate 1871*7c478bd9Sstevel@tonic-gate static int 1872*7c478bd9Sstevel@tonic-gate get_dev_or_buffered_packets(hash_obj_t *seg_hash, int device_fd, int offset, 1873*7c478bd9Sstevel@tonic-gate int length, const char *buf) 1874*7c478bd9Sstevel@tonic-gate { 1875*7c478bd9Sstevel@tonic-gate int tag_size; 1876*7c478bd9Sstevel@tonic-gate int paylen; 1877*7c478bd9Sstevel@tonic-gate int retval; 1878*7c478bd9Sstevel@tonic-gate int seg_limit = 0; 1879*7c478bd9Sstevel@tonic-gate int pktcnt = 0; 1880*7c478bd9Sstevel@tonic-gate char *data; 1881*7c478bd9Sstevel@tonic-gate uint32_t crc; 1882*7c478bd9Sstevel@tonic-gate uint32_t origcrc; 1883*7c478bd9Sstevel@tonic-gate fru_tag_t tag; 1884*7c478bd9Sstevel@tonic-gate hash_obj_t *pkt_hash_obj; 1885*7c478bd9Sstevel@tonic-gate fru_segdesc_t *segdesc; 1886*7c478bd9Sstevel@tonic-gate fru_tagtype_t tagtype; 1887*7c478bd9Sstevel@tonic-gate 1888*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 1889*7c478bd9Sstevel@tonic-gate retval = get_packet(device_fd, &tag, sizeof (fru_tag_t), 1890*7c478bd9Sstevel@tonic-gate offset); 1891*7c478bd9Sstevel@tonic-gate if (retval == -1) { 1892*7c478bd9Sstevel@tonic-gate return (-1); 1893*7c478bd9Sstevel@tonic-gate } 1894*7c478bd9Sstevel@tonic-gate } else if (length - offset < sizeof (fru_tag_t)) { 1895*7c478bd9Sstevel@tonic-gate return (-1); 1896*7c478bd9Sstevel@tonic-gate } else { 1897*7c478bd9Sstevel@tonic-gate (void) memcpy(&tag, buf + offset, sizeof (fru_tag_t)); 1898*7c478bd9Sstevel@tonic-gate } 1899*7c478bd9Sstevel@tonic-gate 1900*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset = offset; 1901*7c478bd9Sstevel@tonic-gate 1902*7c478bd9Sstevel@tonic-gate data = (char *)&tag; 1903*7c478bd9Sstevel@tonic-gate while (data[0] != SEG_TRAILER_TAG) { 1904*7c478bd9Sstevel@tonic-gate tagtype = get_tag_type(&tag); /* verify tag type */ 1905*7c478bd9Sstevel@tonic-gate if (tagtype == -1) { 1906*7c478bd9Sstevel@tonic-gate return (-1); 1907*7c478bd9Sstevel@tonic-gate } 1908*7c478bd9Sstevel@tonic-gate 1909*7c478bd9Sstevel@tonic-gate tag_size = get_tag_size(tagtype); 1910*7c478bd9Sstevel@tonic-gate if (tag_size == -1) { 1911*7c478bd9Sstevel@tonic-gate return (-1); 1912*7c478bd9Sstevel@tonic-gate } 1913*7c478bd9Sstevel@tonic-gate 1914*7c478bd9Sstevel@tonic-gate seg_limit += tag_size; 1915*7c478bd9Sstevel@tonic-gate if (seg_limit > length) { 1916*7c478bd9Sstevel@tonic-gate return (-1); 1917*7c478bd9Sstevel@tonic-gate } 1918*7c478bd9Sstevel@tonic-gate 1919*7c478bd9Sstevel@tonic-gate paylen = get_payload_length((void *)&tag); 1920*7c478bd9Sstevel@tonic-gate if (paylen == -1) { 1921*7c478bd9Sstevel@tonic-gate return (-1); 1922*7c478bd9Sstevel@tonic-gate } 1923*7c478bd9Sstevel@tonic-gate 1924*7c478bd9Sstevel@tonic-gate seg_limit += paylen; 1925*7c478bd9Sstevel@tonic-gate if (seg_limit > length) { 1926*7c478bd9Sstevel@tonic-gate return (-1); 1927*7c478bd9Sstevel@tonic-gate } 1928*7c478bd9Sstevel@tonic-gate 1929*7c478bd9Sstevel@tonic-gate pkt_hash_obj = create_packet_hash_object(); 1930*7c478bd9Sstevel@tonic-gate if (pkt_hash_obj == NULL) { 1931*7c478bd9Sstevel@tonic-gate return (-1); 1932*7c478bd9Sstevel@tonic-gate } 1933*7c478bd9Sstevel@tonic-gate 1934*7c478bd9Sstevel@tonic-gate pkt_hash_obj->u.pkt_obj->payload = malloc(paylen); 1935*7c478bd9Sstevel@tonic-gate if (pkt_hash_obj->u.pkt_obj->payload == NULL) { 1936*7c478bd9Sstevel@tonic-gate free(pkt_hash_obj); 1937*7c478bd9Sstevel@tonic-gate return (-1); 1938*7c478bd9Sstevel@tonic-gate } 1939*7c478bd9Sstevel@tonic-gate 1940*7c478bd9Sstevel@tonic-gate offset += tag_size; 1941*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 1942*7c478bd9Sstevel@tonic-gate retval = pread(device_fd, 1943*7c478bd9Sstevel@tonic-gate pkt_hash_obj->u.pkt_obj->payload, paylen, offset); 1944*7c478bd9Sstevel@tonic-gate } else if (paylen + offset > length) { 1945*7c478bd9Sstevel@tonic-gate retval = 0; 1946*7c478bd9Sstevel@tonic-gate } else { 1947*7c478bd9Sstevel@tonic-gate (void) memcpy(pkt_hash_obj->u.pkt_obj->payload, 1948*7c478bd9Sstevel@tonic-gate buf + offset, paylen); 1949*7c478bd9Sstevel@tonic-gate retval = paylen; 1950*7c478bd9Sstevel@tonic-gate } 1951*7c478bd9Sstevel@tonic-gate if (retval != paylen) { 1952*7c478bd9Sstevel@tonic-gate free(pkt_hash_obj->u.pkt_obj->payload); 1953*7c478bd9Sstevel@tonic-gate free(pkt_hash_obj); 1954*7c478bd9Sstevel@tonic-gate return (-1); 1955*7c478bd9Sstevel@tonic-gate } 1956*7c478bd9Sstevel@tonic-gate 1957*7c478bd9Sstevel@tonic-gate /* don't change this */ 1958*7c478bd9Sstevel@tonic-gate pkt_hash_obj->u.pkt_obj->tag.raw_data = 0; 1959*7c478bd9Sstevel@tonic-gate (void) memcpy(&pkt_hash_obj->u.pkt_obj->tag, &tag, tag_size); 1960*7c478bd9Sstevel@tonic-gate pkt_hash_obj->u.pkt_obj->paylen = paylen; 1961*7c478bd9Sstevel@tonic-gate pkt_hash_obj->u.pkt_obj->tag_size = tag_size; 1962*7c478bd9Sstevel@tonic-gate pkt_hash_obj->u.pkt_obj->payload_offset = offset; 1963*7c478bd9Sstevel@tonic-gate 1964*7c478bd9Sstevel@tonic-gate offset += paylen; 1965*7c478bd9Sstevel@tonic-gate 1966*7c478bd9Sstevel@tonic-gate add_hashobject_to_hashtable(pkt_hash_obj); 1967*7c478bd9Sstevel@tonic-gate add_to_pkt_object_list(seg_hash, pkt_hash_obj); 1968*7c478bd9Sstevel@tonic-gate 1969*7c478bd9Sstevel@tonic-gate pktcnt++; 1970*7c478bd9Sstevel@tonic-gate 1971*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 1972*7c478bd9Sstevel@tonic-gate retval = get_packet(device_fd, &tag, sizeof (fru_tag_t), 1973*7c478bd9Sstevel@tonic-gate offset); 1974*7c478bd9Sstevel@tonic-gate if (retval == -1) { 1975*7c478bd9Sstevel@tonic-gate return (-1); 1976*7c478bd9Sstevel@tonic-gate } 1977*7c478bd9Sstevel@tonic-gate } else if (length - offset < sizeof (fru_tag_t)) { 1978*7c478bd9Sstevel@tonic-gate if (length - offset > 0) { 1979*7c478bd9Sstevel@tonic-gate /* 1980*7c478bd9Sstevel@tonic-gate * not enough data for a full fru_tag_t 1981*7c478bd9Sstevel@tonic-gate * just return what there is 1982*7c478bd9Sstevel@tonic-gate */ 1983*7c478bd9Sstevel@tonic-gate (void) memset(&tag, 0, sizeof (fru_tag_t)); 1984*7c478bd9Sstevel@tonic-gate (void) memcpy(&tag, buf + offset, 1985*7c478bd9Sstevel@tonic-gate length - offset); 1986*7c478bd9Sstevel@tonic-gate } 1987*7c478bd9Sstevel@tonic-gate } else { 1988*7c478bd9Sstevel@tonic-gate (void) memcpy(&tag, buf + offset, sizeof (fru_tag_t)); 1989*7c478bd9Sstevel@tonic-gate } 1990*7c478bd9Sstevel@tonic-gate 1991*7c478bd9Sstevel@tonic-gate data = (char *)&tag; 1992*7c478bd9Sstevel@tonic-gate } 1993*7c478bd9Sstevel@tonic-gate 1994*7c478bd9Sstevel@tonic-gate segdesc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; 1995*7c478bd9Sstevel@tonic-gate 1996*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset = offset; 1997*7c478bd9Sstevel@tonic-gate 1998*7c478bd9Sstevel@tonic-gate if (!segdesc->field.ignore_checksum) { 1999*7c478bd9Sstevel@tonic-gate crc = get_checksum_crc(seg_hash, seg_limit); 2000*7c478bd9Sstevel@tonic-gate offset = seg_hash->u.seg_obj->segment.offset; 2001*7c478bd9Sstevel@tonic-gate 2002*7c478bd9Sstevel@tonic-gate if (buf == NULL) { 2003*7c478bd9Sstevel@tonic-gate retval = pread(device_fd, &origcrc, sizeof (origcrc), 2004*7c478bd9Sstevel@tonic-gate offset + seg_limit + 1); 2005*7c478bd9Sstevel@tonic-gate if (retval != sizeof (origcrc)) { 2006*7c478bd9Sstevel@tonic-gate return (-1); 2007*7c478bd9Sstevel@tonic-gate } 2008*7c478bd9Sstevel@tonic-gate } else if (length - offset < sizeof (origcrc)) { 2009*7c478bd9Sstevel@tonic-gate return (-1); 2010*7c478bd9Sstevel@tonic-gate } else { 2011*7c478bd9Sstevel@tonic-gate (void) memcpy(&origcrc, buf + seg_limit + 1, 2012*7c478bd9Sstevel@tonic-gate sizeof (origcrc)); 2013*7c478bd9Sstevel@tonic-gate } 2014*7c478bd9Sstevel@tonic-gate 2015*7c478bd9Sstevel@tonic-gate if (origcrc != crc) { 2016*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset = offset; 2017*7c478bd9Sstevel@tonic-gate } 2018*7c478bd9Sstevel@tonic-gate } 2019*7c478bd9Sstevel@tonic-gate 2020*7c478bd9Sstevel@tonic-gate return (pktcnt); 2021*7c478bd9Sstevel@tonic-gate } 2022*7c478bd9Sstevel@tonic-gate 2023*7c478bd9Sstevel@tonic-gate static int 2024*7c478bd9Sstevel@tonic-gate get_packets(hash_obj_t *seg_hash, int device_fd, int offset, int length) 2025*7c478bd9Sstevel@tonic-gate { 2026*7c478bd9Sstevel@tonic-gate return (get_dev_or_buffered_packets(seg_hash, device_fd, offset, 2027*7c478bd9Sstevel@tonic-gate length, NULL)); 2028*7c478bd9Sstevel@tonic-gate } 2029*7c478bd9Sstevel@tonic-gate 2030*7c478bd9Sstevel@tonic-gate static int 2031*7c478bd9Sstevel@tonic-gate get_buffered_packets(hash_obj_t *seg_hash, const char *seg_buf, size_t seg_len) 2032*7c478bd9Sstevel@tonic-gate { 2033*7c478bd9Sstevel@tonic-gate return (get_dev_or_buffered_packets(seg_hash, -1, 0, seg_len, seg_buf)); 2034*7c478bd9Sstevel@tonic-gate } 2035*7c478bd9Sstevel@tonic-gate 2036*7c478bd9Sstevel@tonic-gate /* 2037*7c478bd9Sstevel@tonic-gate * Description : 2038*7c478bd9Sstevel@tonic-gate * fru_get_num_packets() returns the current number of packets 2039*7c478bd9Sstevel@tonic-gate * in a segment. 2040*7c478bd9Sstevel@tonic-gate * 2041*7c478bd9Sstevel@tonic-gate * Arguments : segment_hdl_t : segment handle. 2042*7c478bd9Sstevel@tonic-gate * 2043*7c478bd9Sstevel@tonic-gate * Return : 2044*7c478bd9Sstevel@tonic-gate * int 2045*7c478bd9Sstevel@tonic-gate * On success, the number of packets is returned; 2046*7c478bd9Sstevel@tonic-gate * -1 on failure. 2047*7c478bd9Sstevel@tonic-gate */ 2048*7c478bd9Sstevel@tonic-gate int 2049*7c478bd9Sstevel@tonic-gate fru_get_num_packets(segment_hdl_t segment, door_cred_t *cred) 2050*7c478bd9Sstevel@tonic-gate { 2051*7c478bd9Sstevel@tonic-gate int device_fd; 2052*7c478bd9Sstevel@tonic-gate int pktcnt; 2053*7c478bd9Sstevel@tonic-gate int length; 2054*7c478bd9Sstevel@tonic-gate uint16_t offset; 2055*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_hash_obj; 2056*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 2057*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 2058*7c478bd9Sstevel@tonic-gate fru_segdesc_t *segdesc; 2059*7c478bd9Sstevel@tonic-gate segment_obj_t *segment_object; 2060*7c478bd9Sstevel@tonic-gate 2061*7c478bd9Sstevel@tonic-gate seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); 2062*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 2063*7c478bd9Sstevel@tonic-gate return (-1); 2064*7c478bd9Sstevel@tonic-gate } 2065*7c478bd9Sstevel@tonic-gate 2066*7c478bd9Sstevel@tonic-gate segment_object = seg_hash->u.seg_obj; 2067*7c478bd9Sstevel@tonic-gate if (segment_object == NULL) { 2068*7c478bd9Sstevel@tonic-gate return (-1); 2069*7c478bd9Sstevel@tonic-gate } 2070*7c478bd9Sstevel@tonic-gate 2071*7c478bd9Sstevel@tonic-gate segdesc = (fru_segdesc_t *)&segment_object->segment.descriptor; 2072*7c478bd9Sstevel@tonic-gate if (segdesc->field.opaque) { 2073*7c478bd9Sstevel@tonic-gate return (0); 2074*7c478bd9Sstevel@tonic-gate } 2075*7c478bd9Sstevel@tonic-gate 2076*7c478bd9Sstevel@tonic-gate if (seg_hash->u.seg_obj->pkt_obj_list != NULL) { 2077*7c478bd9Sstevel@tonic-gate return (segment_object->num_of_packets); 2078*7c478bd9Sstevel@tonic-gate } 2079*7c478bd9Sstevel@tonic-gate 2080*7c478bd9Sstevel@tonic-gate offset = segment_object->segment.offset; 2081*7c478bd9Sstevel@tonic-gate length = segment_object->segment.length; 2082*7c478bd9Sstevel@tonic-gate 2083*7c478bd9Sstevel@tonic-gate /* section hash object */ 2084*7c478bd9Sstevel@tonic-gate sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 2085*7c478bd9Sstevel@tonic-gate SECTION_TYPE); 2086*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 2087*7c478bd9Sstevel@tonic-gate return (-1); 2088*7c478bd9Sstevel@tonic-gate } 2089*7c478bd9Sstevel@tonic-gate 2090*7c478bd9Sstevel@tonic-gate segment_object->num_of_packets = 0; 2091*7c478bd9Sstevel@tonic-gate 2092*7c478bd9Sstevel@tonic-gate switch (sec_hash->u.sec_obj->encoding) { 2093*7c478bd9Sstevel@tonic-gate case ENC_STANDARD: 2094*7c478bd9Sstevel@tonic-gate cont_hash_obj = get_container_hash_object(SEGMENT_TYPE, 2095*7c478bd9Sstevel@tonic-gate segment_object->section_hdl); 2096*7c478bd9Sstevel@tonic-gate if (cont_hash_obj == NULL) { 2097*7c478bd9Sstevel@tonic-gate return (-1); 2098*7c478bd9Sstevel@tonic-gate } 2099*7c478bd9Sstevel@tonic-gate device_fd = open(cont_hash_obj->u.cont_obj->device_pathname, 2100*7c478bd9Sstevel@tonic-gate O_RDWR); 2101*7c478bd9Sstevel@tonic-gate if (device_fd < 0) { 2102*7c478bd9Sstevel@tonic-gate return (-1); 2103*7c478bd9Sstevel@tonic-gate } 2104*7c478bd9Sstevel@tonic-gate 2105*7c478bd9Sstevel@tonic-gate pktcnt = get_packets(seg_hash, device_fd, offset, length); 2106*7c478bd9Sstevel@tonic-gate (void) close(device_fd); 2107*7c478bd9Sstevel@tonic-gate break; 2108*7c478bd9Sstevel@tonic-gate 2109*7c478bd9Sstevel@tonic-gate case ENC_SPD: { 2110*7c478bd9Sstevel@tonic-gate ssize_t spd_seg_len; 2111*7c478bd9Sstevel@tonic-gate size_t nbytes; 2112*7c478bd9Sstevel@tonic-gate char *seg_buf; 2113*7c478bd9Sstevel@tonic-gate 2114*7c478bd9Sstevel@tonic-gate nbytes = segment_object->segment.length; 2115*7c478bd9Sstevel@tonic-gate seg_buf = alloca(nbytes); 2116*7c478bd9Sstevel@tonic-gate if (seg_buf == NULL) 2117*7c478bd9Sstevel@tonic-gate return (-1); 2118*7c478bd9Sstevel@tonic-gate spd_seg_len = 2119*7c478bd9Sstevel@tonic-gate fru_read_segment(segment, seg_buf, nbytes, cred); 2120*7c478bd9Sstevel@tonic-gate if (spd_seg_len < 0) 2121*7c478bd9Sstevel@tonic-gate return (-1); 2122*7c478bd9Sstevel@tonic-gate pktcnt = get_buffered_packets(seg_hash, seg_buf, 2123*7c478bd9Sstevel@tonic-gate spd_seg_len); 2124*7c478bd9Sstevel@tonic-gate break; 2125*7c478bd9Sstevel@tonic-gate } 2126*7c478bd9Sstevel@tonic-gate 2127*7c478bd9Sstevel@tonic-gate default: 2128*7c478bd9Sstevel@tonic-gate return (-1); 2129*7c478bd9Sstevel@tonic-gate } 2130*7c478bd9Sstevel@tonic-gate 2131*7c478bd9Sstevel@tonic-gate if (pktcnt == -1) { 2132*7c478bd9Sstevel@tonic-gate free_pkt_object_list(seg_hash); 2133*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->pkt_obj_list = NULL; 2134*7c478bd9Sstevel@tonic-gate } 2135*7c478bd9Sstevel@tonic-gate 2136*7c478bd9Sstevel@tonic-gate segment_object->num_of_packets = pktcnt; 2137*7c478bd9Sstevel@tonic-gate 2138*7c478bd9Sstevel@tonic-gate return (segment_object->num_of_packets); 2139*7c478bd9Sstevel@tonic-gate } 2140*7c478bd9Sstevel@tonic-gate 2141*7c478bd9Sstevel@tonic-gate 2142*7c478bd9Sstevel@tonic-gate /* 2143*7c478bd9Sstevel@tonic-gate * Description : 2144*7c478bd9Sstevel@tonic-gate * fru_get_packets() fills an array of structures representing the 2145*7c478bd9Sstevel@tonic-gate * packets in a segment. 2146*7c478bd9Sstevel@tonic-gate * 2147*7c478bd9Sstevel@tonic-gate * Arguments : segment_hdl_t : segment handle. 2148*7c478bd9Sstevel@tonic-gate * packet_t : packet buffer. 2149*7c478bd9Sstevel@tonic-gate * int : maximum number of packets. 2150*7c478bd9Sstevel@tonic-gate * 2151*7c478bd9Sstevel@tonic-gate * Return : 2152*7c478bd9Sstevel@tonic-gate * int 2153*7c478bd9Sstevel@tonic-gate * On success, the number of packet structures written is returned; 2154*7c478bd9Sstevel@tonic-gate * On failure -1 is returned; 2155*7c478bd9Sstevel@tonic-gate * 2156*7c478bd9Sstevel@tonic-gate */ 2157*7c478bd9Sstevel@tonic-gate 2158*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2159*7c478bd9Sstevel@tonic-gate int 2160*7c478bd9Sstevel@tonic-gate fru_get_packets(segment_hdl_t segment, packet_t *packet, int maxpackets, 2161*7c478bd9Sstevel@tonic-gate door_cred_t *cred) 2162*7c478bd9Sstevel@tonic-gate { 2163*7c478bd9Sstevel@tonic-gate int count; 2164*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash_obj; 2165*7c478bd9Sstevel@tonic-gate hash_obj_t *pkt_hash_obj; 2166*7c478bd9Sstevel@tonic-gate 2167*7c478bd9Sstevel@tonic-gate /* segment hash object */ 2168*7c478bd9Sstevel@tonic-gate seg_hash_obj = lookup_handle_object(segment, SEGMENT_TYPE); 2169*7c478bd9Sstevel@tonic-gate if (seg_hash_obj == NULL) { 2170*7c478bd9Sstevel@tonic-gate return (-1); 2171*7c478bd9Sstevel@tonic-gate } 2172*7c478bd9Sstevel@tonic-gate 2173*7c478bd9Sstevel@tonic-gate if (seg_hash_obj->u.seg_obj->num_of_packets != maxpackets) { 2174*7c478bd9Sstevel@tonic-gate return (-1); 2175*7c478bd9Sstevel@tonic-gate } 2176*7c478bd9Sstevel@tonic-gate 2177*7c478bd9Sstevel@tonic-gate pkt_hash_obj = seg_hash_obj->u.seg_obj->pkt_obj_list; 2178*7c478bd9Sstevel@tonic-gate if (pkt_hash_obj == NULL) { 2179*7c478bd9Sstevel@tonic-gate return (-1); 2180*7c478bd9Sstevel@tonic-gate } 2181*7c478bd9Sstevel@tonic-gate 2182*7c478bd9Sstevel@tonic-gate for (count = 0; count < maxpackets; count++, packet++) { 2183*7c478bd9Sstevel@tonic-gate packet->handle = pkt_hash_obj->obj_hdl; 2184*7c478bd9Sstevel@tonic-gate packet->tag = 0; 2185*7c478bd9Sstevel@tonic-gate (void) memcpy(&packet->tag, &pkt_hash_obj->u.pkt_obj->tag, 2186*7c478bd9Sstevel@tonic-gate pkt_hash_obj->u.pkt_obj->tag_size); 2187*7c478bd9Sstevel@tonic-gate pkt_hash_obj = pkt_hash_obj->u.pkt_obj->next; 2188*7c478bd9Sstevel@tonic-gate } 2189*7c478bd9Sstevel@tonic-gate 2190*7c478bd9Sstevel@tonic-gate return (0); 2191*7c478bd9Sstevel@tonic-gate } 2192*7c478bd9Sstevel@tonic-gate 2193*7c478bd9Sstevel@tonic-gate /* 2194*7c478bd9Sstevel@tonic-gate * Description : 2195*7c478bd9Sstevel@tonic-gate * fru_get_payload() copies the contents of a packet's payload. 2196*7c478bd9Sstevel@tonic-gate * 2197*7c478bd9Sstevel@tonic-gate * Arguments : packet_hdl_t : packet handle. 2198*7c478bd9Sstevel@tonic-gate * void * : payload buffer. 2199*7c478bd9Sstevel@tonic-gate * size_t : sizeof the buffer. 2200*7c478bd9Sstevel@tonic-gate * 2201*7c478bd9Sstevel@tonic-gate * Return : 2202*7c478bd9Sstevel@tonic-gate * int 2203*7c478bd9Sstevel@tonic-gate * On success, the number of bytes copied is returned; On error 2204*7c478bd9Sstevel@tonic-gate * -1 returned. 2205*7c478bd9Sstevel@tonic-gate */ 2206*7c478bd9Sstevel@tonic-gate 2207*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2208*7c478bd9Sstevel@tonic-gate ssize_t 2209*7c478bd9Sstevel@tonic-gate fru_get_payload(packet_hdl_t packet, void *buffer, size_t nbytes, 2210*7c478bd9Sstevel@tonic-gate door_cred_t *cred) 2211*7c478bd9Sstevel@tonic-gate { 2212*7c478bd9Sstevel@tonic-gate hash_obj_t *packet_hash_obj; 2213*7c478bd9Sstevel@tonic-gate 2214*7c478bd9Sstevel@tonic-gate /* packet hash object */ 2215*7c478bd9Sstevel@tonic-gate packet_hash_obj = lookup_handle_object(packet, PACKET_TYPE); 2216*7c478bd9Sstevel@tonic-gate if (packet_hash_obj == NULL) { 2217*7c478bd9Sstevel@tonic-gate return (-1); 2218*7c478bd9Sstevel@tonic-gate } 2219*7c478bd9Sstevel@tonic-gate 2220*7c478bd9Sstevel@tonic-gate /* verify payload length */ 2221*7c478bd9Sstevel@tonic-gate if (nbytes != packet_hash_obj->u.pkt_obj->paylen) { 2222*7c478bd9Sstevel@tonic-gate return (-1); 2223*7c478bd9Sstevel@tonic-gate } 2224*7c478bd9Sstevel@tonic-gate 2225*7c478bd9Sstevel@tonic-gate (void) memcpy(buffer, packet_hash_obj->u.pkt_obj->payload, nbytes); 2226*7c478bd9Sstevel@tonic-gate return (nbytes); 2227*7c478bd9Sstevel@tonic-gate } 2228*7c478bd9Sstevel@tonic-gate 2229*7c478bd9Sstevel@tonic-gate /* 2230*7c478bd9Sstevel@tonic-gate * Description : 2231*7c478bd9Sstevel@tonic-gate * fru_update_payload() writes the contents of a packet's payload. 2232*7c478bd9Sstevel@tonic-gate * 2233*7c478bd9Sstevel@tonic-gate * Arguments : packet_hdl_t : packet handle. 2234*7c478bd9Sstevel@tonic-gate * const void * : data buffer. 2235*7c478bd9Sstevel@tonic-gate * size_t : buffer size. 2236*7c478bd9Sstevel@tonic-gate * packet_hdl_t : new packet handle. 2237*7c478bd9Sstevel@tonic-gate * 2238*7c478bd9Sstevel@tonic-gate * Return : 2239*7c478bd9Sstevel@tonic-gate * int 2240*7c478bd9Sstevel@tonic-gate * On success, 0 is returned; on failure 2241*7c478bd9Sstevel@tonic-gate * -1 is returned. 2242*7c478bd9Sstevel@tonic-gate */ 2243*7c478bd9Sstevel@tonic-gate 2244*7c478bd9Sstevel@tonic-gate int 2245*7c478bd9Sstevel@tonic-gate fru_update_payload(packet_hdl_t packet, const void *data, size_t nbytes, 2246*7c478bd9Sstevel@tonic-gate packet_hdl_t *newpacket, door_cred_t *cred) 2247*7c478bd9Sstevel@tonic-gate { 2248*7c478bd9Sstevel@tonic-gate int fd; 2249*7c478bd9Sstevel@tonic-gate int segment_offset; 2250*7c478bd9Sstevel@tonic-gate int trailer_offset; 2251*7c478bd9Sstevel@tonic-gate int retval; 2252*7c478bd9Sstevel@tonic-gate uint32_t crc; 2253*7c478bd9Sstevel@tonic-gate hash_obj_t *pkt_hash; 2254*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 2255*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 2256*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_hash; 2257*7c478bd9Sstevel@tonic-gate fru_segdesc_t *desc; 2258*7c478bd9Sstevel@tonic-gate 2259*7c478bd9Sstevel@tonic-gate /* check the effective uid of the client */ 2260*7c478bd9Sstevel@tonic-gate if (cred->dc_euid != 0) { 2261*7c478bd9Sstevel@tonic-gate errno = EPERM; 2262*7c478bd9Sstevel@tonic-gate return (-1); /* not a root */ 2263*7c478bd9Sstevel@tonic-gate } 2264*7c478bd9Sstevel@tonic-gate 2265*7c478bd9Sstevel@tonic-gate /* packet hash object */ 2266*7c478bd9Sstevel@tonic-gate pkt_hash = lookup_handle_object(packet, PACKET_TYPE); 2267*7c478bd9Sstevel@tonic-gate if (pkt_hash == NULL) { 2268*7c478bd9Sstevel@tonic-gate return (-1); 2269*7c478bd9Sstevel@tonic-gate } 2270*7c478bd9Sstevel@tonic-gate 2271*7c478bd9Sstevel@tonic-gate /* segment hash object */ 2272*7c478bd9Sstevel@tonic-gate seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl, 2273*7c478bd9Sstevel@tonic-gate SEGMENT_TYPE); 2274*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 2275*7c478bd9Sstevel@tonic-gate return (-1); 2276*7c478bd9Sstevel@tonic-gate } 2277*7c478bd9Sstevel@tonic-gate 2278*7c478bd9Sstevel@tonic-gate /* check for write perm. */ 2279*7c478bd9Sstevel@tonic-gate desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; 2280*7c478bd9Sstevel@tonic-gate if (!(desc->field.field_perm & SEGMENT_WRITE)) { 2281*7c478bd9Sstevel@tonic-gate errno = EPERM; 2282*7c478bd9Sstevel@tonic-gate return (-1); /* write not allowed */ 2283*7c478bd9Sstevel@tonic-gate } 2284*7c478bd9Sstevel@tonic-gate 2285*7c478bd9Sstevel@tonic-gate sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 2286*7c478bd9Sstevel@tonic-gate SECTION_TYPE); 2287*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 2288*7c478bd9Sstevel@tonic-gate return (-1); 2289*7c478bd9Sstevel@tonic-gate } 2290*7c478bd9Sstevel@tonic-gate 2291*7c478bd9Sstevel@tonic-gate if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { 2292*7c478bd9Sstevel@tonic-gate errno = EPERM; 2293*7c478bd9Sstevel@tonic-gate return (-1); /* read-only section */ 2294*7c478bd9Sstevel@tonic-gate } 2295*7c478bd9Sstevel@tonic-gate 2296*7c478bd9Sstevel@tonic-gate cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, 2297*7c478bd9Sstevel@tonic-gate CONTAINER_TYPE); 2298*7c478bd9Sstevel@tonic-gate if (cont_hash == NULL) { 2299*7c478bd9Sstevel@tonic-gate return (-1); 2300*7c478bd9Sstevel@tonic-gate } 2301*7c478bd9Sstevel@tonic-gate 2302*7c478bd9Sstevel@tonic-gate if (pkt_hash->u.pkt_obj->paylen != nbytes) { 2303*7c478bd9Sstevel@tonic-gate return (-1); 2304*7c478bd9Sstevel@tonic-gate } 2305*7c478bd9Sstevel@tonic-gate 2306*7c478bd9Sstevel@tonic-gate (void) memcpy(pkt_hash->u.pkt_obj->payload, (char *)data, nbytes); 2307*7c478bd9Sstevel@tonic-gate fd = open(cont_hash->u.cont_obj->device_pathname, O_RDWR); 2308*7c478bd9Sstevel@tonic-gate if (fd < 0) { 2309*7c478bd9Sstevel@tonic-gate return (-1); 2310*7c478bd9Sstevel@tonic-gate } 2311*7c478bd9Sstevel@tonic-gate 2312*7c478bd9Sstevel@tonic-gate trailer_offset = seg_hash->u.seg_obj->trailer_offset; 2313*7c478bd9Sstevel@tonic-gate segment_offset = seg_hash->u.seg_obj->segment.offset; 2314*7c478bd9Sstevel@tonic-gate 2315*7c478bd9Sstevel@tonic-gate crc = get_checksum_crc(seg_hash, (trailer_offset - segment_offset)); 2316*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, data, nbytes, pkt_hash->u.pkt_obj->payload_offset); 2317*7c478bd9Sstevel@tonic-gate if (retval != nbytes) { 2318*7c478bd9Sstevel@tonic-gate (void) close(fd); 2319*7c478bd9Sstevel@tonic-gate return (-1); 2320*7c478bd9Sstevel@tonic-gate } 2321*7c478bd9Sstevel@tonic-gate 2322*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, &crc, sizeof (crc), trailer_offset + 1); 2323*7c478bd9Sstevel@tonic-gate (void) close(fd); 2324*7c478bd9Sstevel@tonic-gate if (retval != sizeof (crc)) { 2325*7c478bd9Sstevel@tonic-gate return (-1); 2326*7c478bd9Sstevel@tonic-gate } 2327*7c478bd9Sstevel@tonic-gate *newpacket = packet; 2328*7c478bd9Sstevel@tonic-gate return (0); 2329*7c478bd9Sstevel@tonic-gate } 2330*7c478bd9Sstevel@tonic-gate 2331*7c478bd9Sstevel@tonic-gate /* 2332*7c478bd9Sstevel@tonic-gate * Description : 2333*7c478bd9Sstevel@tonic-gate * fru_append_packet() appends a packet to a segment. 2334*7c478bd9Sstevel@tonic-gate * 2335*7c478bd9Sstevel@tonic-gate * Arguments : 2336*7c478bd9Sstevel@tonic-gate * segment_hdl_t segment 2337*7c478bd9Sstevel@tonic-gate * A handle for the segment to which the packet will be appended. 2338*7c478bd9Sstevel@tonic-gate * 2339*7c478bd9Sstevel@tonic-gate * packet_t *packet 2340*7c478bd9Sstevel@tonic-gate * On entry, the "tag" component of "packet" specifies the tag 2341*7c478bd9Sstevel@tonic-gate * value for the added packet; the "handle" component is ignored. 2342*7c478bd9Sstevel@tonic-gate * On return, the "handle" component is set to the handle of the 2343*7c478bd9Sstevel@tonic-gate * appended packet. 2344*7c478bd9Sstevel@tonic-gate * 2345*7c478bd9Sstevel@tonic-gate * const void *payload 2346*7c478bd9Sstevel@tonic-gate * A pointer to the caller's buffer containing the payload data for 2347*7c478bd9Sstevel@tonic-gate * the appended packet. 2348*7c478bd9Sstevel@tonic-gate * 2349*7c478bd9Sstevel@tonic-gate * size_t nbytes 2350*7c478bd9Sstevel@tonic-gate * The size of the caller buffer. 2351*7c478bd9Sstevel@tonic-gate * 2352*7c478bd9Sstevel@tonic-gate * Return : 2353*7c478bd9Sstevel@tonic-gate * int 2354*7c478bd9Sstevel@tonic-gate * On success, 0 is returned; on error -1 is returned; 2355*7c478bd9Sstevel@tonic-gate */ 2356*7c478bd9Sstevel@tonic-gate 2357*7c478bd9Sstevel@tonic-gate int 2358*7c478bd9Sstevel@tonic-gate fru_append_packet(segment_hdl_t segment, packet_t *packet, const void *payload, 2359*7c478bd9Sstevel@tonic-gate size_t nbytes, segment_hdl_t *newsegment, door_cred_t *cred) 2360*7c478bd9Sstevel@tonic-gate { 2361*7c478bd9Sstevel@tonic-gate int trailer_offset; 2362*7c478bd9Sstevel@tonic-gate int tag_size; 2363*7c478bd9Sstevel@tonic-gate int fd; 2364*7c478bd9Sstevel@tonic-gate int retval; 2365*7c478bd9Sstevel@tonic-gate char trailer[] = {0x0c, 0x00, 0x00, 0x00, 0x00}; 2366*7c478bd9Sstevel@tonic-gate uint32_t crc; 2367*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 2368*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 2369*7c478bd9Sstevel@tonic-gate hash_obj_t *pkt_hash; 2370*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_hash; 2371*7c478bd9Sstevel@tonic-gate fru_tagtype_t tagtype; 2372*7c478bd9Sstevel@tonic-gate fru_segdesc_t *desc; 2373*7c478bd9Sstevel@tonic-gate 2374*7c478bd9Sstevel@tonic-gate /* check the effective uid of the client */ 2375*7c478bd9Sstevel@tonic-gate if (cred->dc_euid != 0) { 2376*7c478bd9Sstevel@tonic-gate errno = EPERM; 2377*7c478bd9Sstevel@tonic-gate return (-1); /* not a root */ 2378*7c478bd9Sstevel@tonic-gate } 2379*7c478bd9Sstevel@tonic-gate 2380*7c478bd9Sstevel@tonic-gate seg_hash = lookup_handle_object(segment, SEGMENT_TYPE); 2381*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 2382*7c478bd9Sstevel@tonic-gate return (-1); 2383*7c478bd9Sstevel@tonic-gate } 2384*7c478bd9Sstevel@tonic-gate 2385*7c478bd9Sstevel@tonic-gate /* check for write perm. */ 2386*7c478bd9Sstevel@tonic-gate desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; 2387*7c478bd9Sstevel@tonic-gate if (!(desc->field.field_perm & SEGMENT_WRITE)) { 2388*7c478bd9Sstevel@tonic-gate errno = EPERM; 2389*7c478bd9Sstevel@tonic-gate return (-1); /* write not allowed */ 2390*7c478bd9Sstevel@tonic-gate } 2391*7c478bd9Sstevel@tonic-gate 2392*7c478bd9Sstevel@tonic-gate sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 2393*7c478bd9Sstevel@tonic-gate SECTION_TYPE); 2394*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 2395*7c478bd9Sstevel@tonic-gate return (-1); 2396*7c478bd9Sstevel@tonic-gate } 2397*7c478bd9Sstevel@tonic-gate 2398*7c478bd9Sstevel@tonic-gate if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { 2399*7c478bd9Sstevel@tonic-gate errno = EPERM; 2400*7c478bd9Sstevel@tonic-gate return (-1); /* read-only section */ 2401*7c478bd9Sstevel@tonic-gate } 2402*7c478bd9Sstevel@tonic-gate 2403*7c478bd9Sstevel@tonic-gate trailer_offset = seg_hash->u.seg_obj->trailer_offset; 2404*7c478bd9Sstevel@tonic-gate 2405*7c478bd9Sstevel@tonic-gate /* 2406*7c478bd9Sstevel@tonic-gate * if trailer offset is 0 than parse the segment data to get the trailer 2407*7c478bd9Sstevel@tonic-gate * offset to compute the remaining space left in the segment area for 2408*7c478bd9Sstevel@tonic-gate * new packet to be added. 2409*7c478bd9Sstevel@tonic-gate */ 2410*7c478bd9Sstevel@tonic-gate if (trailer_offset == 0) { 2411*7c478bd9Sstevel@tonic-gate (void) fru_get_num_packets(segment, cred); 2412*7c478bd9Sstevel@tonic-gate trailer_offset = seg_hash->u.seg_obj->trailer_offset; 2413*7c478bd9Sstevel@tonic-gate } 2414*7c478bd9Sstevel@tonic-gate 2415*7c478bd9Sstevel@tonic-gate tagtype = get_tag_type((void *)&packet->tag); 2416*7c478bd9Sstevel@tonic-gate if (tagtype == -1) { 2417*7c478bd9Sstevel@tonic-gate return (-1); 2418*7c478bd9Sstevel@tonic-gate } 2419*7c478bd9Sstevel@tonic-gate 2420*7c478bd9Sstevel@tonic-gate tag_size = get_tag_size(tagtype); 2421*7c478bd9Sstevel@tonic-gate if (tag_size == -1) { 2422*7c478bd9Sstevel@tonic-gate return (-1); 2423*7c478bd9Sstevel@tonic-gate } 2424*7c478bd9Sstevel@tonic-gate 2425*7c478bd9Sstevel@tonic-gate if (seg_hash->u.seg_obj->segment.length > 2426*7c478bd9Sstevel@tonic-gate ((trailer_offset - seg_hash->u.seg_obj->segment.offset) + 2427*7c478bd9Sstevel@tonic-gate tag_size + nbytes + sizeof (char) + sizeof (uint32_t))) { 2428*7c478bd9Sstevel@tonic-gate /* create new packet hash */ 2429*7c478bd9Sstevel@tonic-gate pkt_hash = create_packet_hash_object(); 2430*7c478bd9Sstevel@tonic-gate if (pkt_hash == NULL) { 2431*7c478bd9Sstevel@tonic-gate return (-1); 2432*7c478bd9Sstevel@tonic-gate } 2433*7c478bd9Sstevel@tonic-gate 2434*7c478bd9Sstevel@tonic-gate /* tag initialization */ 2435*7c478bd9Sstevel@tonic-gate (void) memcpy(&pkt_hash->u.pkt_obj->tag, &packet->tag, 2436*7c478bd9Sstevel@tonic-gate tag_size); 2437*7c478bd9Sstevel@tonic-gate pkt_hash->u.pkt_obj->tag_size = tag_size; 2438*7c478bd9Sstevel@tonic-gate 2439*7c478bd9Sstevel@tonic-gate /* payload inititalization */ 2440*7c478bd9Sstevel@tonic-gate pkt_hash->u.pkt_obj->payload = malloc(nbytes); 2441*7c478bd9Sstevel@tonic-gate if (pkt_hash->u.pkt_obj->payload == NULL) { 2442*7c478bd9Sstevel@tonic-gate free(pkt_hash); 2443*7c478bd9Sstevel@tonic-gate return (-1); 2444*7c478bd9Sstevel@tonic-gate } 2445*7c478bd9Sstevel@tonic-gate 2446*7c478bd9Sstevel@tonic-gate (void) memcpy(pkt_hash->u.pkt_obj->payload, payload, nbytes); 2447*7c478bd9Sstevel@tonic-gate pkt_hash->u.pkt_obj->paylen = nbytes; 2448*7c478bd9Sstevel@tonic-gate pkt_hash->u.pkt_obj->payload_offset = trailer_offset + tag_size; 2449*7c478bd9Sstevel@tonic-gate 2450*7c478bd9Sstevel@tonic-gate /* add to hash table */ 2451*7c478bd9Sstevel@tonic-gate add_hashobject_to_hashtable(pkt_hash); 2452*7c478bd9Sstevel@tonic-gate 2453*7c478bd9Sstevel@tonic-gate add_to_pkt_object_list(seg_hash, pkt_hash); 2454*7c478bd9Sstevel@tonic-gate 2455*7c478bd9Sstevel@tonic-gate cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, 2456*7c478bd9Sstevel@tonic-gate CONTAINER_TYPE); 2457*7c478bd9Sstevel@tonic-gate if (cont_hash == NULL) { 2458*7c478bd9Sstevel@tonic-gate return (-1); 2459*7c478bd9Sstevel@tonic-gate } 2460*7c478bd9Sstevel@tonic-gate 2461*7c478bd9Sstevel@tonic-gate fd = open(cont_hash->u.cont_obj->device_pathname, O_RDWR); 2462*7c478bd9Sstevel@tonic-gate if (fd < 0) { 2463*7c478bd9Sstevel@tonic-gate return (-1); 2464*7c478bd9Sstevel@tonic-gate } 2465*7c478bd9Sstevel@tonic-gate 2466*7c478bd9Sstevel@tonic-gate /* update the trailer offset */ 2467*7c478bd9Sstevel@tonic-gate trailer_offset += tag_size + nbytes; 2468*7c478bd9Sstevel@tonic-gate 2469*7c478bd9Sstevel@tonic-gate /* calculate new checksum */ 2470*7c478bd9Sstevel@tonic-gate crc = get_checksum_crc(seg_hash, (trailer_offset - 2471*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->segment.offset)); 2472*7c478bd9Sstevel@tonic-gate 2473*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, &packet->tag, tag_size, 2474*7c478bd9Sstevel@tonic-gate trailer_offset - (tag_size + nbytes)); 2475*7c478bd9Sstevel@tonic-gate if (retval != tag_size) { 2476*7c478bd9Sstevel@tonic-gate (void) close(fd); 2477*7c478bd9Sstevel@tonic-gate return (-1); 2478*7c478bd9Sstevel@tonic-gate } 2479*7c478bd9Sstevel@tonic-gate 2480*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, payload, nbytes, trailer_offset - nbytes); 2481*7c478bd9Sstevel@tonic-gate if (retval != nbytes) { 2482*7c478bd9Sstevel@tonic-gate (void) close(fd); 2483*7c478bd9Sstevel@tonic-gate return (-1); 2484*7c478bd9Sstevel@tonic-gate } 2485*7c478bd9Sstevel@tonic-gate 2486*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, trailer, sizeof (trailer), trailer_offset); 2487*7c478bd9Sstevel@tonic-gate if (retval != sizeof (trailer)) { 2488*7c478bd9Sstevel@tonic-gate (void) close(fd); 2489*7c478bd9Sstevel@tonic-gate return (-1); 2490*7c478bd9Sstevel@tonic-gate } 2491*7c478bd9Sstevel@tonic-gate 2492*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, &crc, sizeof (crc), trailer_offset + 1); 2493*7c478bd9Sstevel@tonic-gate (void) close(fd); 2494*7c478bd9Sstevel@tonic-gate if (retval != sizeof (crc)) { 2495*7c478bd9Sstevel@tonic-gate return (-1); 2496*7c478bd9Sstevel@tonic-gate } 2497*7c478bd9Sstevel@tonic-gate 2498*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset = trailer_offset; 2499*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->num_of_packets += 1; 2500*7c478bd9Sstevel@tonic-gate 2501*7c478bd9Sstevel@tonic-gate *newsegment = segment; /* return new segment handle */ 2502*7c478bd9Sstevel@tonic-gate return (0); 2503*7c478bd9Sstevel@tonic-gate } else { 2504*7c478bd9Sstevel@tonic-gate errno = EAGAIN; 2505*7c478bd9Sstevel@tonic-gate } 2506*7c478bd9Sstevel@tonic-gate 2507*7c478bd9Sstevel@tonic-gate return (-1); 2508*7c478bd9Sstevel@tonic-gate } 2509*7c478bd9Sstevel@tonic-gate 2510*7c478bd9Sstevel@tonic-gate static void 2511*7c478bd9Sstevel@tonic-gate adjust_packets(int fd, hash_obj_t *free_obj, hash_obj_t *object_list) 2512*7c478bd9Sstevel@tonic-gate { 2513*7c478bd9Sstevel@tonic-gate int retval; 2514*7c478bd9Sstevel@tonic-gate uint32_t new_offset; 2515*7c478bd9Sstevel@tonic-gate hash_obj_t *hash_ptr; 2516*7c478bd9Sstevel@tonic-gate 2517*7c478bd9Sstevel@tonic-gate new_offset = free_obj->u.pkt_obj->payload_offset - 2518*7c478bd9Sstevel@tonic-gate free_obj->u.pkt_obj->tag_size; 2519*7c478bd9Sstevel@tonic-gate for (hash_ptr = object_list; 2520*7c478bd9Sstevel@tonic-gate hash_ptr != NULL; hash_ptr = hash_ptr->u.pkt_obj->next) { 2521*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, &hash_ptr->u.pkt_obj->tag, 2522*7c478bd9Sstevel@tonic-gate hash_ptr->u.pkt_obj->tag_size, new_offset); 2523*7c478bd9Sstevel@tonic-gate if (retval != hash_ptr->u.pkt_obj->tag_size) { 2524*7c478bd9Sstevel@tonic-gate return; 2525*7c478bd9Sstevel@tonic-gate } 2526*7c478bd9Sstevel@tonic-gate new_offset += hash_ptr->u.pkt_obj->tag_size; 2527*7c478bd9Sstevel@tonic-gate hash_ptr->u.pkt_obj->payload_offset = new_offset; 2528*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, hash_ptr->u.pkt_obj->payload, 2529*7c478bd9Sstevel@tonic-gate hash_ptr->u.pkt_obj->paylen, new_offset); 2530*7c478bd9Sstevel@tonic-gate if (retval != hash_ptr->u.pkt_obj->paylen) { 2531*7c478bd9Sstevel@tonic-gate return; 2532*7c478bd9Sstevel@tonic-gate } 2533*7c478bd9Sstevel@tonic-gate new_offset += hash_ptr->u.pkt_obj->paylen; 2534*7c478bd9Sstevel@tonic-gate } 2535*7c478bd9Sstevel@tonic-gate } 2536*7c478bd9Sstevel@tonic-gate 2537*7c478bd9Sstevel@tonic-gate static void 2538*7c478bd9Sstevel@tonic-gate free_packet_object(handle_t handle, hash_obj_t *seg_hash) 2539*7c478bd9Sstevel@tonic-gate { 2540*7c478bd9Sstevel@tonic-gate hash_obj_t *pkt_hash; 2541*7c478bd9Sstevel@tonic-gate hash_obj_t *next_hash; 2542*7c478bd9Sstevel@tonic-gate 2543*7c478bd9Sstevel@tonic-gate pkt_hash = seg_hash->u.seg_obj->pkt_obj_list; 2544*7c478bd9Sstevel@tonic-gate if (pkt_hash == NULL) { 2545*7c478bd9Sstevel@tonic-gate return; 2546*7c478bd9Sstevel@tonic-gate } 2547*7c478bd9Sstevel@tonic-gate 2548*7c478bd9Sstevel@tonic-gate if (pkt_hash->obj_hdl == handle) { 2549*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->pkt_obj_list = pkt_hash->u.pkt_obj->next; 2550*7c478bd9Sstevel@tonic-gate } else { 2551*7c478bd9Sstevel@tonic-gate while (pkt_hash->obj_hdl != handle) { 2552*7c478bd9Sstevel@tonic-gate next_hash = pkt_hash; 2553*7c478bd9Sstevel@tonic-gate pkt_hash = pkt_hash->u.pkt_obj->next; 2554*7c478bd9Sstevel@tonic-gate if (pkt_hash == NULL) { 2555*7c478bd9Sstevel@tonic-gate return; 2556*7c478bd9Sstevel@tonic-gate } 2557*7c478bd9Sstevel@tonic-gate } 2558*7c478bd9Sstevel@tonic-gate next_hash->u.pkt_obj->next = pkt_hash->u.pkt_obj->next; 2559*7c478bd9Sstevel@tonic-gate } 2560*7c478bd9Sstevel@tonic-gate 2561*7c478bd9Sstevel@tonic-gate if (pkt_hash->prev == NULL) { 2562*7c478bd9Sstevel@tonic-gate hash_table[(pkt_hash->obj_hdl % TABLE_SIZE)] = pkt_hash->next; 2563*7c478bd9Sstevel@tonic-gate if (pkt_hash->next != NULL) { 2564*7c478bd9Sstevel@tonic-gate pkt_hash->next->prev = NULL; 2565*7c478bd9Sstevel@tonic-gate } 2566*7c478bd9Sstevel@tonic-gate } else { 2567*7c478bd9Sstevel@tonic-gate pkt_hash->prev->next = pkt_hash->next; 2568*7c478bd9Sstevel@tonic-gate if (pkt_hash->next != NULL) { 2569*7c478bd9Sstevel@tonic-gate pkt_hash->next->prev = pkt_hash->prev; 2570*7c478bd9Sstevel@tonic-gate } 2571*7c478bd9Sstevel@tonic-gate } 2572*7c478bd9Sstevel@tonic-gate 2573*7c478bd9Sstevel@tonic-gate free(pkt_hash->u.pkt_obj->payload); 2574*7c478bd9Sstevel@tonic-gate free(pkt_hash->u.pkt_obj); 2575*7c478bd9Sstevel@tonic-gate free(pkt_hash); 2576*7c478bd9Sstevel@tonic-gate } 2577*7c478bd9Sstevel@tonic-gate 2578*7c478bd9Sstevel@tonic-gate /* 2579*7c478bd9Sstevel@tonic-gate * Description : 2580*7c478bd9Sstevel@tonic-gate * fru_delete_packet() deletes a packet from a segment. 2581*7c478bd9Sstevel@tonic-gate * 2582*7c478bd9Sstevel@tonic-gate * Arguments : packet_hdl_t : packet number to be deleted. 2583*7c478bd9Sstevel@tonic-gate * segment_hdl_t : new segment handler. 2584*7c478bd9Sstevel@tonic-gate * 2585*7c478bd9Sstevel@tonic-gate * Return : 2586*7c478bd9Sstevel@tonic-gate * int 2587*7c478bd9Sstevel@tonic-gate * On success, 0 is returned; on error, -1. 2588*7c478bd9Sstevel@tonic-gate * 2589*7c478bd9Sstevel@tonic-gate * NOTES 2590*7c478bd9Sstevel@tonic-gate * Packets are adjacent; thus, deleting a packet requires moving 2591*7c478bd9Sstevel@tonic-gate * succeeding packets to compact the resulting hole. 2592*7c478bd9Sstevel@tonic-gate */ 2593*7c478bd9Sstevel@tonic-gate 2594*7c478bd9Sstevel@tonic-gate int 2595*7c478bd9Sstevel@tonic-gate fru_delete_packet(packet_hdl_t packet, segment_hdl_t *newsegment, 2596*7c478bd9Sstevel@tonic-gate door_cred_t *cred) 2597*7c478bd9Sstevel@tonic-gate { 2598*7c478bd9Sstevel@tonic-gate int retval; 2599*7c478bd9Sstevel@tonic-gate int fd; 2600*7c478bd9Sstevel@tonic-gate char trailer[] = { 0x0c, 0x00, 0x00, 0x00, 0x00}; 2601*7c478bd9Sstevel@tonic-gate uint32_t crc; 2602*7c478bd9Sstevel@tonic-gate hash_obj_t *tmp_obj; 2603*7c478bd9Sstevel@tonic-gate hash_obj_t *pkt_hash; 2604*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash; 2605*7c478bd9Sstevel@tonic-gate hash_obj_t *cont_hash; 2606*7c478bd9Sstevel@tonic-gate hash_obj_t *prev_obj; 2607*7c478bd9Sstevel@tonic-gate hash_obj_t *seg_hash; 2608*7c478bd9Sstevel@tonic-gate fru_segdesc_t *desc; 2609*7c478bd9Sstevel@tonic-gate 2610*7c478bd9Sstevel@tonic-gate /* check the effective uid of the client */ 2611*7c478bd9Sstevel@tonic-gate if (cred->dc_euid != 0) { 2612*7c478bd9Sstevel@tonic-gate errno = EPERM; 2613*7c478bd9Sstevel@tonic-gate return (-1); /* not a root */ 2614*7c478bd9Sstevel@tonic-gate } 2615*7c478bd9Sstevel@tonic-gate 2616*7c478bd9Sstevel@tonic-gate /* packet hash object */ 2617*7c478bd9Sstevel@tonic-gate pkt_hash = lookup_handle_object(packet, PACKET_TYPE); 2618*7c478bd9Sstevel@tonic-gate if (pkt_hash == NULL) { 2619*7c478bd9Sstevel@tonic-gate return (-1); 2620*7c478bd9Sstevel@tonic-gate } 2621*7c478bd9Sstevel@tonic-gate 2622*7c478bd9Sstevel@tonic-gate /* segment hash object */ 2623*7c478bd9Sstevel@tonic-gate seg_hash = lookup_handle_object(pkt_hash->u.pkt_obj->segment_hdl, 2624*7c478bd9Sstevel@tonic-gate SEGMENT_TYPE); 2625*7c478bd9Sstevel@tonic-gate if (seg_hash == NULL) { 2626*7c478bd9Sstevel@tonic-gate return (-1); 2627*7c478bd9Sstevel@tonic-gate } 2628*7c478bd9Sstevel@tonic-gate 2629*7c478bd9Sstevel@tonic-gate /* check for write perm. */ 2630*7c478bd9Sstevel@tonic-gate desc = (fru_segdesc_t *)&seg_hash->u.seg_obj->segment.descriptor; 2631*7c478bd9Sstevel@tonic-gate if (!(desc->field.field_perm & SEGMENT_WRITE)) { 2632*7c478bd9Sstevel@tonic-gate errno = EPERM; 2633*7c478bd9Sstevel@tonic-gate return (-1); /* write not allowed */ 2634*7c478bd9Sstevel@tonic-gate } 2635*7c478bd9Sstevel@tonic-gate 2636*7c478bd9Sstevel@tonic-gate /* section hash object */ 2637*7c478bd9Sstevel@tonic-gate sec_hash = lookup_handle_object(seg_hash->u.seg_obj->section_hdl, 2638*7c478bd9Sstevel@tonic-gate SECTION_TYPE); 2639*7c478bd9Sstevel@tonic-gate if (sec_hash == NULL) { 2640*7c478bd9Sstevel@tonic-gate return (-1); 2641*7c478bd9Sstevel@tonic-gate } 2642*7c478bd9Sstevel@tonic-gate 2643*7c478bd9Sstevel@tonic-gate if (sec_hash->u.sec_obj->section.protection == READ_ONLY_SECTION) { 2644*7c478bd9Sstevel@tonic-gate errno = EPERM; 2645*7c478bd9Sstevel@tonic-gate return (-1); /* read-only section */ 2646*7c478bd9Sstevel@tonic-gate } 2647*7c478bd9Sstevel@tonic-gate 2648*7c478bd9Sstevel@tonic-gate prev_obj = seg_hash->u.seg_obj->pkt_obj_list; 2649*7c478bd9Sstevel@tonic-gate if (prev_obj == NULL) { 2650*7c478bd9Sstevel@tonic-gate return (-1); 2651*7c478bd9Sstevel@tonic-gate } 2652*7c478bd9Sstevel@tonic-gate 2653*7c478bd9Sstevel@tonic-gate /* container hash object */ 2654*7c478bd9Sstevel@tonic-gate cont_hash = lookup_handle_object(sec_hash->u.sec_obj->cont_hdl, 2655*7c478bd9Sstevel@tonic-gate CONTAINER_TYPE); 2656*7c478bd9Sstevel@tonic-gate if (cont_hash == NULL) { 2657*7c478bd9Sstevel@tonic-gate return (-1); 2658*7c478bd9Sstevel@tonic-gate } 2659*7c478bd9Sstevel@tonic-gate 2660*7c478bd9Sstevel@tonic-gate fd = open(cont_hash->u.cont_obj->device_pathname, O_RDWR); 2661*7c478bd9Sstevel@tonic-gate if (fd < 0) { 2662*7c478bd9Sstevel@tonic-gate return (-1); 2663*7c478bd9Sstevel@tonic-gate } 2664*7c478bd9Sstevel@tonic-gate 2665*7c478bd9Sstevel@tonic-gate if (prev_obj->obj_hdl == packet) { /* first object to be deleted */ 2666*7c478bd9Sstevel@tonic-gate adjust_packets(fd, prev_obj, prev_obj->u.pkt_obj->next); 2667*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset -= 2668*7c478bd9Sstevel@tonic-gate (prev_obj->u.pkt_obj->tag_size + 2669*7c478bd9Sstevel@tonic-gate prev_obj->u.pkt_obj->paylen); 2670*7c478bd9Sstevel@tonic-gate free_packet_object(packet, seg_hash); 2671*7c478bd9Sstevel@tonic-gate } else { 2672*7c478bd9Sstevel@tonic-gate for (tmp_obj = prev_obj; 2673*7c478bd9Sstevel@tonic-gate tmp_obj != NULL; tmp_obj = tmp_obj->u.pkt_obj->next) { 2674*7c478bd9Sstevel@tonic-gate /* found the object */ 2675*7c478bd9Sstevel@tonic-gate if (tmp_obj->obj_hdl == packet) { 2676*7c478bd9Sstevel@tonic-gate adjust_packets(fd, tmp_obj, 2677*7c478bd9Sstevel@tonic-gate tmp_obj->u.pkt_obj->next); 2678*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset -= 2679*7c478bd9Sstevel@tonic-gate (tmp_obj->u.pkt_obj->tag_size + 2680*7c478bd9Sstevel@tonic-gate tmp_obj->u.pkt_obj->paylen); 2681*7c478bd9Sstevel@tonic-gate free_packet_object(packet, seg_hash); 2682*7c478bd9Sstevel@tonic-gate } 2683*7c478bd9Sstevel@tonic-gate } 2684*7c478bd9Sstevel@tonic-gate } 2685*7c478bd9Sstevel@tonic-gate 2686*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->num_of_packets -= 1; 2687*7c478bd9Sstevel@tonic-gate 2688*7c478bd9Sstevel@tonic-gate /* calculate checksum */ 2689*7c478bd9Sstevel@tonic-gate crc = get_checksum_crc(seg_hash, (seg_hash->u.seg_obj->trailer_offset - 2690*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->segment.offset)); 2691*7c478bd9Sstevel@tonic-gate /* write trailer at new offset */ 2692*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, &trailer, sizeof (trailer), 2693*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset); 2694*7c478bd9Sstevel@tonic-gate if (retval != sizeof (trailer)) { 2695*7c478bd9Sstevel@tonic-gate (void) close(fd); 2696*7c478bd9Sstevel@tonic-gate return (-1); 2697*7c478bd9Sstevel@tonic-gate } 2698*7c478bd9Sstevel@tonic-gate 2699*7c478bd9Sstevel@tonic-gate /* write the checksum value */ 2700*7c478bd9Sstevel@tonic-gate retval = pwrite(fd, &crc, sizeof (crc), 2701*7c478bd9Sstevel@tonic-gate seg_hash->u.seg_obj->trailer_offset + 1); 2702*7c478bd9Sstevel@tonic-gate (void) close(fd); 2703*7c478bd9Sstevel@tonic-gate if (retval != sizeof (crc)) { 2704*7c478bd9Sstevel@tonic-gate return (-1); 2705*7c478bd9Sstevel@tonic-gate } 2706*7c478bd9Sstevel@tonic-gate 2707*7c478bd9Sstevel@tonic-gate *newsegment = seg_hash->obj_hdl; /* return new segment handle */ 2708*7c478bd9Sstevel@tonic-gate return (0); 2709*7c478bd9Sstevel@tonic-gate } 2710*7c478bd9Sstevel@tonic-gate 2711*7c478bd9Sstevel@tonic-gate /* 2712*7c478bd9Sstevel@tonic-gate * Description : 2713*7c478bd9Sstevel@tonic-gate * fru_close_container() removes the association between a 2714*7c478bd9Sstevel@tonic-gate * container and its handle. this routines free's up all the 2715*7c478bd9Sstevel@tonic-gate * hash object contained under container. 2716*7c478bd9Sstevel@tonic-gate * 2717*7c478bd9Sstevel@tonic-gate * Arguments : 2718*7c478bd9Sstevel@tonic-gate * container_hdl_t holds the file descriptor of the fru. 2719*7c478bd9Sstevel@tonic-gate * 2720*7c478bd9Sstevel@tonic-gate * Return : 2721*7c478bd9Sstevel@tonic-gate * int 2722*7c478bd9Sstevel@tonic-gate * return 0. 2723*7c478bd9Sstevel@tonic-gate * 2724*7c478bd9Sstevel@tonic-gate */ 2725*7c478bd9Sstevel@tonic-gate 2726*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2727*7c478bd9Sstevel@tonic-gate int 2728*7c478bd9Sstevel@tonic-gate fru_close_container(container_hdl_t container) 2729*7c478bd9Sstevel@tonic-gate { 2730*7c478bd9Sstevel@tonic-gate hash_obj_t *hash_obj; 2731*7c478bd9Sstevel@tonic-gate hash_obj_t *prev_hash; 2732*7c478bd9Sstevel@tonic-gate hash_obj_t *sec_hash_obj; 2733*7c478bd9Sstevel@tonic-gate handle_t obj_hdl; 2734*7c478bd9Sstevel@tonic-gate 2735*7c478bd9Sstevel@tonic-gate /* lookup for container hash object */ 2736*7c478bd9Sstevel@tonic-gate hash_obj = lookup_handle_object(container, CONTAINER_TYPE); 2737*7c478bd9Sstevel@tonic-gate if (hash_obj == NULL) { 2738*7c478bd9Sstevel@tonic-gate return (0); 2739*7c478bd9Sstevel@tonic-gate } 2740*7c478bd9Sstevel@tonic-gate 2741*7c478bd9Sstevel@tonic-gate /* points to section object list */ 2742*7c478bd9Sstevel@tonic-gate sec_hash_obj = hash_obj->u.cont_obj->sec_obj_list; 2743*7c478bd9Sstevel@tonic-gate 2744*7c478bd9Sstevel@tonic-gate /* traverse section object list */ 2745*7c478bd9Sstevel@tonic-gate while (sec_hash_obj != NULL) { 2746*7c478bd9Sstevel@tonic-gate 2747*7c478bd9Sstevel@tonic-gate /* traverse segment hash object in the section */ 2748*7c478bd9Sstevel@tonic-gate while (sec_hash_obj->u.sec_obj->seg_obj_list != NULL) { 2749*7c478bd9Sstevel@tonic-gate /* object handle of the segment hash object */ 2750*7c478bd9Sstevel@tonic-gate obj_hdl = 2751*7c478bd9Sstevel@tonic-gate sec_hash_obj->u.sec_obj->seg_obj_list->obj_hdl; 2752*7c478bd9Sstevel@tonic-gate free_segment_hash(obj_hdl, sec_hash_obj); 2753*7c478bd9Sstevel@tonic-gate } 2754*7c478bd9Sstevel@tonic-gate 2755*7c478bd9Sstevel@tonic-gate /* going to free section hash object, relink the hash object */ 2756*7c478bd9Sstevel@tonic-gate if (sec_hash_obj->prev == NULL) { 2757*7c478bd9Sstevel@tonic-gate hash_table[(sec_hash_obj->obj_hdl % TABLE_SIZE)] = 2758*7c478bd9Sstevel@tonic-gate sec_hash_obj->next; 2759*7c478bd9Sstevel@tonic-gate if (sec_hash_obj->next != NULL) { 2760*7c478bd9Sstevel@tonic-gate sec_hash_obj->next->prev = NULL; 2761*7c478bd9Sstevel@tonic-gate } 2762*7c478bd9Sstevel@tonic-gate } else { 2763*7c478bd9Sstevel@tonic-gate sec_hash_obj->prev->next = sec_hash_obj->next; 2764*7c478bd9Sstevel@tonic-gate if (sec_hash_obj->next != NULL) { 2765*7c478bd9Sstevel@tonic-gate sec_hash_obj->next->prev = sec_hash_obj->prev; 2766*7c478bd9Sstevel@tonic-gate } 2767*7c478bd9Sstevel@tonic-gate } 2768*7c478bd9Sstevel@tonic-gate 2769*7c478bd9Sstevel@tonic-gate prev_hash = sec_hash_obj; 2770*7c478bd9Sstevel@tonic-gate 2771*7c478bd9Sstevel@tonic-gate sec_hash_obj = sec_hash_obj->u.sec_obj->next; 2772*7c478bd9Sstevel@tonic-gate 2773*7c478bd9Sstevel@tonic-gate free(prev_hash->u.sec_obj); /* free section hash object */ 2774*7c478bd9Sstevel@tonic-gate free(prev_hash); /* free section hash */ 2775*7c478bd9Sstevel@tonic-gate } 2776*7c478bd9Sstevel@tonic-gate 2777*7c478bd9Sstevel@tonic-gate /* free container hash object */ 2778*7c478bd9Sstevel@tonic-gate if (hash_obj->prev == NULL) { 2779*7c478bd9Sstevel@tonic-gate hash_table[(hash_obj->obj_hdl % TABLE_SIZE)] = hash_obj->next; 2780*7c478bd9Sstevel@tonic-gate if (hash_obj->next != NULL) { 2781*7c478bd9Sstevel@tonic-gate hash_obj->next->prev = NULL; 2782*7c478bd9Sstevel@tonic-gate } 2783*7c478bd9Sstevel@tonic-gate } else { 2784*7c478bd9Sstevel@tonic-gate hash_obj->prev->next = hash_obj->next; 2785*7c478bd9Sstevel@tonic-gate if (hash_obj->next != NULL) { 2786*7c478bd9Sstevel@tonic-gate hash_obj->next->prev = hash_obj->prev; 2787*7c478bd9Sstevel@tonic-gate } 2788*7c478bd9Sstevel@tonic-gate } 2789*7c478bd9Sstevel@tonic-gate 2790*7c478bd9Sstevel@tonic-gate free(hash_obj->u.cont_obj); 2791*7c478bd9Sstevel@tonic-gate free(hash_obj); 2792*7c478bd9Sstevel@tonic-gate return (0); 2793*7c478bd9Sstevel@tonic-gate } 2794*7c478bd9Sstevel@tonic-gate 2795*7c478bd9Sstevel@tonic-gate /* 2796*7c478bd9Sstevel@tonic-gate * Description : 2797*7c478bd9Sstevel@tonic-gate * fru_is_data_available() checks to see if the frudata 2798*7c478bd9Sstevel@tonic-gate * is available on a fru. 2799*7c478bd9Sstevel@tonic-gate * 2800*7c478bd9Sstevel@tonic-gate * Arguments : 2801*7c478bd9Sstevel@tonic-gate * picl_nodehdl_t holds the picl node handle of the fru. 2802*7c478bd9Sstevel@tonic-gate * 2803*7c478bd9Sstevel@tonic-gate * Return : 2804*7c478bd9Sstevel@tonic-gate * int 2805*7c478bd9Sstevel@tonic-gate * return 1: if FRUID information is available 2806*7c478bd9Sstevel@tonic-gate * return 0: if FRUID information is not present 2807*7c478bd9Sstevel@tonic-gate * 2808*7c478bd9Sstevel@tonic-gate */ 2809*7c478bd9Sstevel@tonic-gate 2810*7c478bd9Sstevel@tonic-gate /* ARGSUSED */ 2811*7c478bd9Sstevel@tonic-gate int 2812*7c478bd9Sstevel@tonic-gate fru_is_data_available(picl_nodehdl_t fru) 2813*7c478bd9Sstevel@tonic-gate { 2814*7c478bd9Sstevel@tonic-gate return (0); 2815*7c478bd9Sstevel@tonic-gate } 2816