1*3446Smrj /* 2*3446Smrj * CDDL HEADER START 3*3446Smrj * 4*3446Smrj * The contents of this file are subject to the terms of the 5*3446Smrj * Common Development and Distribution License, Version 1.0 only 6*3446Smrj * (the "License"). You may not use this file except in compliance 7*3446Smrj * with the License. 8*3446Smrj * 9*3446Smrj * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10*3446Smrj * or http://www.opensolaris.org/os/licensing. 11*3446Smrj * See the License for the specific language governing permissions 12*3446Smrj * and limitations under the License. 13*3446Smrj * 14*3446Smrj * When distributing Covered Code, include this CDDL HEADER in each 15*3446Smrj * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16*3446Smrj * If applicable, add the following below this CDDL HEADER, with the 17*3446Smrj * fields enclosed by brackets "[]" replaced with your own identifying 18*3446Smrj * information: Portions Copyright [yyyy] [name of copyright owner] 19*3446Smrj * 20*3446Smrj * CDDL HEADER END 21*3446Smrj */ 22*3446Smrj /* 23*3446Smrj * Copyright 1996-2002 Sun Microsystems, Inc. All rights reserved. 24*3446Smrj * Use is subject to license terms. 25*3446Smrj */ 26*3446Smrj 27*3446Smrj #pragma ident "%Z%%M% %I% %E% SMI" 28*3446Smrj 29*3446Smrj #include "benv.h" 30*3446Smrj #include <sys/sunddi.h> 31*3446Smrj #include <sys/ddi_impldefs.h> 32*3446Smrj #include <sys/openpromio.h> 33*3446Smrj #include <stdio.h> 34*3446Smrj 35*3446Smrj static int getpropval(struct openpromio *opp, char *prop); 36*3446Smrj 37*3446Smrj static char *promdev = "/dev/openprom"; 38*3446Smrj static int prom_fd; 39*3446Smrj static char *mfail = "malloc"; 40*3446Smrj 41*3446Smrj /* 42*3446Smrj * 128 is the size of the largest (currently) property name 43*3446Smrj * 16384 - MAXPROPSIZE - sizeof (int) is the size of the largest 44*3446Smrj * (currently) property value that is allowed. 45*3446Smrj * the sizeof (u_int) is from struct openpromio 46*3446Smrj */ 47*3446Smrj 48*3446Smrj #define MAXPROPSIZE 128 49*3446Smrj #define MAXVALSIZE (16384 - MAXPROPSIZE - sizeof (u_int)) 50*3446Smrj #define BUFSIZE (MAXPROPSIZE + MAXVALSIZE + sizeof (u_int)) 51*3446Smrj #define MINVALSIZE (4 * sizeof (u_long)) 52*3446Smrj #define MINBUFSIZE (MINVALSIZE + sizeof (u_long)) 53*3446Smrj 54*3446Smrj typedef union { 55*3446Smrj char buf[BUFSIZE]; 56*3446Smrj struct openpromio opp; 57*3446Smrj } Oppbuf; 58*3446Smrj 59*3446Smrj typedef union { 60*3446Smrj char buf[MINVALSIZE + sizeof (u_int)]; 61*3446Smrj struct openpromio opp; 62*3446Smrj } Oppbuf_small; 63*3446Smrj 64*3446Smrj static Oppbuf oppbuf; 65*3446Smrj 66*3446Smrj static unsigned long 67*3446Smrj next(unsigned long id) 68*3446Smrj { 69*3446Smrj Oppbuf_small oppbuf; 70*3446Smrj struct openpromio *opp = &(oppbuf.opp); 71*3446Smrj unsigned long *ip = (unsigned long *)(opp->oprom_array); 72*3446Smrj 73*3446Smrj memset(oppbuf.buf, 0, MINBUFSIZE); 74*3446Smrj opp->oprom_size = MINVALSIZE; 75*3446Smrj *ip = id; 76*3446Smrj if (ioctl(prom_fd, OPROMNEXT, opp) < 0) 77*3446Smrj return (0); 78*3446Smrj return (*(unsigned long *)opp->oprom_array); 79*3446Smrj } 80*3446Smrj 81*3446Smrj static unsigned long 82*3446Smrj child(unsigned long id) 83*3446Smrj { 84*3446Smrj Oppbuf_small oppbuf; 85*3446Smrj struct openpromio *opp = &(oppbuf.opp); 86*3446Smrj unsigned long *ip = (unsigned long *)(opp->oprom_array); 87*3446Smrj 88*3446Smrj memset(oppbuf.buf, 0, MINBUFSIZE); 89*3446Smrj opp->oprom_size = MINVALSIZE; 90*3446Smrj *ip = id; 91*3446Smrj if (ioctl(prom_fd, OPROMCHILD, opp) < 0) 92*3446Smrj return (0); 93*3446Smrj return (*(unsigned long *)opp->oprom_array); 94*3446Smrj } 95*3446Smrj 96*3446Smrj /* 97*3446Smrj * Find a node by name from the prom device tree. 98*3446Smrj * Return the id or 0 if it is not found. 99*3446Smrj */ 100*3446Smrj static unsigned long 101*3446Smrj prom_findnode_byname(unsigned long id, char *name) 102*3446Smrj { 103*3446Smrj struct openpromio *opp = &(oppbuf.opp); 104*3446Smrj unsigned long nid; 105*3446Smrj 106*3446Smrj if (id == 0) 107*3446Smrj return (0); 108*3446Smrj if (!getpropval(opp, "name")) 109*3446Smrj return (0); 110*3446Smrj if (strcmp(opp->oprom_array, name) == 0) 111*3446Smrj return (id); 112*3446Smrj if (nid = prom_findnode_byname(child(id), name)) 113*3446Smrj return (nid); 114*3446Smrj if (nid = prom_findnode_byname(next(id), name)) 115*3446Smrj return (nid); 116*3446Smrj return (0); 117*3446Smrj } 118*3446Smrj 119*3446Smrj /* 120*3446Smrj * Make the current prom node be the rootnode and return its id. 121*3446Smrj */ 122*3446Smrj static unsigned long 123*3446Smrj prom_rootnode() 124*3446Smrj { 125*3446Smrj return (next(0)); 126*3446Smrj } 127*3446Smrj 128*3446Smrj static int 129*3446Smrj getpropval(struct openpromio *opp, char *prop) 130*3446Smrj { 131*3446Smrj opp->oprom_size = MAXVALSIZE; 132*3446Smrj 133*3446Smrj (void) strlcpy(opp->oprom_array, prop, MAXPROPSIZE); 134*3446Smrj if (ioctl(prom_fd, OPROMGETPROP, opp) < 0) 135*3446Smrj return (0); 136*3446Smrj if (opp->oprom_size == 0) 137*3446Smrj return (0); 138*3446Smrj return (1); 139*3446Smrj } 140*3446Smrj 141*3446Smrj static int 142*3446Smrj getnextprop(struct openpromio *opp, char *prop) 143*3446Smrj { 144*3446Smrj opp->oprom_size = MAXVALSIZE; 145*3446Smrj 146*3446Smrj (void) strlcpy(opp->oprom_array, prop, MAXPROPSIZE); 147*3446Smrj if (ioctl(prom_fd, OPROMNXTPROP, opp) < 0) 148*3446Smrj return (0); 149*3446Smrj if (opp->oprom_size == 0) 150*3446Smrj return (0); 151*3446Smrj return (1); 152*3446Smrj } 153*3446Smrj 154*3446Smrj /* 155*3446Smrj * Get a pointer to the requested property from the current node. 156*3446Smrj * The property is stored in static storage and the returned pointer 157*3446Smrj * points into the static storage. The property length is placed in 158*3446Smrj * the location pointed to by the third argument. 159*3446Smrj */ 160*3446Smrj static unsigned char * 161*3446Smrj prom_getprop(char *prop, int *lenp) 162*3446Smrj { 163*3446Smrj struct openpromio *opp = &(oppbuf.opp); 164*3446Smrj 165*3446Smrj if (!getpropval(opp, prop)) 166*3446Smrj return (NULL); 167*3446Smrj *lenp = opp->oprom_size; 168*3446Smrj return ((unsigned char *)opp->oprom_array); 169*3446Smrj } 170*3446Smrj 171*3446Smrj static unsigned char * 172*3446Smrj prom_nextprop(char *prop) 173*3446Smrj { 174*3446Smrj struct openpromio *opp = &(oppbuf.opp); 175*3446Smrj 176*3446Smrj if (!getnextprop(opp, prop)) 177*3446Smrj return ((unsigned char *)0); 178*3446Smrj return ((unsigned char *)opp->oprom_array); 179*3446Smrj } 180*3446Smrj 181*3446Smrj ddi_prop_t * 182*3446Smrj get_proplist(char *name) 183*3446Smrj { 184*3446Smrj ddi_prop_t *plist, *npp, *plast; 185*3446Smrj char *curprop, *newprop; 186*3446Smrj unsigned char *propval; 187*3446Smrj unsigned long id; 188*3446Smrj 189*3446Smrj plist = NULL; 190*3446Smrj plast = NULL; 191*3446Smrj id = prom_findnode_byname(prom_rootnode(), name); 192*3446Smrj if (id == 0) 193*3446Smrj return (plist); 194*3446Smrj curprop = ""; 195*3446Smrj while (newprop = (char *)prom_nextprop(curprop)) { 196*3446Smrj curprop = strdup(newprop); 197*3446Smrj npp = (ddi_prop_t *)malloc(sizeof (ddi_prop_t)); 198*3446Smrj if (npp == 0) 199*3446Smrj exit(_error(PERROR, mfail)); 200*3446Smrj propval = prom_getprop(curprop, &npp->prop_len); 201*3446Smrj npp->prop_name = curprop; 202*3446Smrj if (propval != NULL) { 203*3446Smrj npp->prop_val = (char *)malloc(npp->prop_len); 204*3446Smrj if (npp->prop_val == 0) 205*3446Smrj exit(_error(PERROR, mfail)); 206*3446Smrj memcpy(npp->prop_val, propval, npp->prop_len); 207*3446Smrj } else 208*3446Smrj npp->prop_val = NULL; 209*3446Smrj npp->prop_next = NULL; 210*3446Smrj if (plast == NULL) { 211*3446Smrj plist = npp; 212*3446Smrj } else { 213*3446Smrj plast->prop_next = npp; 214*3446Smrj } 215*3446Smrj plast = npp; 216*3446Smrj } 217*3446Smrj return (plist); 218*3446Smrj } 219*3446Smrj 220*3446Smrj caddr_t 221*3446Smrj get_propval(char *name, char *node) 222*3446Smrj { 223*3446Smrj ddi_prop_t *prop, *plist; 224*3446Smrj 225*3446Smrj if ((plist = get_proplist(node)) == NULL) 226*3446Smrj return (NULL); 227*3446Smrj 228*3446Smrj for (prop = plist; prop != NULL; prop = prop->prop_next) 229*3446Smrj if (strcmp(prop->prop_name, name) == 0) 230*3446Smrj return (prop->prop_val); 231*3446Smrj 232*3446Smrj return (NULL); 233*3446Smrj } 234*3446Smrj 235*3446Smrj void 236*3446Smrj get_kbenv(void) 237*3446Smrj { 238*3446Smrj if ((prom_fd = open(promdev, O_RDONLY)) < 0) { 239*3446Smrj exit(_error(PERROR, "prom open failed")); 240*3446Smrj } 241*3446Smrj } 242*3446Smrj 243*3446Smrj void 244*3446Smrj close_kbenv(void) 245*3446Smrj { 246*3446Smrj (void) close(prom_fd); 247*3446Smrj } 248