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