xref: /onnv-gate/usr/src/cmd/eeprom/i386/benv_kvm.c (revision 11906:6743277598ac)
13446Smrj /*
23446Smrj  * CDDL HEADER START
33446Smrj  *
43446Smrj  * The contents of this file are subject to the terms of the
5*11906SGangadhar.M@Sun.COM  * Common Development and Distribution License (the "License").
6*11906SGangadhar.M@Sun.COM  * You may not use this file except in compliance with the License.
73446Smrj  *
83446Smrj  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
93446Smrj  * or http://www.opensolaris.org/os/licensing.
103446Smrj  * See the License for the specific language governing permissions
113446Smrj  * and limitations under the License.
123446Smrj  *
133446Smrj  * When distributing Covered Code, include this CDDL HEADER in each
143446Smrj  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
153446Smrj  * If applicable, add the following below this CDDL HEADER, with the
163446Smrj  * fields enclosed by brackets "[]" replaced with your own identifying
173446Smrj  * information: Portions Copyright [yyyy] [name of copyright owner]
183446Smrj  *
193446Smrj  * CDDL HEADER END
203446Smrj  */
213446Smrj /*
22*11906SGangadhar.M@Sun.COM  * Copyright 2010 Sun Microsystems, Inc.  All rights reserved.
233446Smrj  * Use is subject to license terms.
243446Smrj  */
253446Smrj 
263446Smrj 
273446Smrj #include "benv.h"
283446Smrj #include <sys/sunddi.h>
293446Smrj #include <sys/ddi_impldefs.h>
303446Smrj #include <sys/openpromio.h>
313446Smrj #include <stdio.h>
323446Smrj 
333446Smrj static int getpropval(struct openpromio *opp, char *prop);
343446Smrj 
353446Smrj static char *promdev = "/dev/openprom";
363446Smrj static int prom_fd;
373446Smrj static char *mfail = "malloc";
383446Smrj 
393446Smrj /*
403446Smrj  * 128 is the size of the largest (currently) property name
413446Smrj  * 16384 - MAXPROPSIZE - sizeof (int) is the size of the largest
423446Smrj  * (currently) property value that is allowed.
433446Smrj  * the sizeof (u_int) is from struct openpromio
443446Smrj  */
453446Smrj 
463446Smrj #define	MAXPROPSIZE	128
473446Smrj #define	MAXVALSIZE	(16384 - MAXPROPSIZE - sizeof (u_int))
483446Smrj #define	BUFSIZE		(MAXPROPSIZE + MAXVALSIZE + sizeof (u_int))
493446Smrj #define	MINVALSIZE	(4 * sizeof (u_long))
503446Smrj #define	MINBUFSIZE	(MINVALSIZE + sizeof (u_long))
513446Smrj 
523446Smrj typedef union {
533446Smrj 	char buf[BUFSIZE];
543446Smrj 	struct openpromio opp;
553446Smrj } Oppbuf;
563446Smrj 
573446Smrj typedef union {
583446Smrj 	char buf[MINVALSIZE + sizeof (u_int)];
593446Smrj 	struct openpromio opp;
603446Smrj } Oppbuf_small;
613446Smrj 
623446Smrj static Oppbuf	oppbuf;
633446Smrj 
643446Smrj static unsigned long
next(unsigned long id)653446Smrj next(unsigned long id)
663446Smrj {
673446Smrj 	Oppbuf_small	oppbuf;
683446Smrj 	struct openpromio *opp = &(oppbuf.opp);
693446Smrj 	unsigned long *ip = (unsigned long *)(opp->oprom_array);
703446Smrj 
713446Smrj 	memset(oppbuf.buf, 0, MINBUFSIZE);
723446Smrj 	opp->oprom_size = MINVALSIZE;
733446Smrj 	*ip = id;
743446Smrj 	if (ioctl(prom_fd, OPROMNEXT, opp) < 0)
753446Smrj 		return (0);
763446Smrj 	return (*(unsigned long *)opp->oprom_array);
773446Smrj }
783446Smrj 
793446Smrj static unsigned long
child(unsigned long id)803446Smrj child(unsigned long id)
813446Smrj {
823446Smrj 	Oppbuf_small	oppbuf;
833446Smrj 	struct openpromio *opp = &(oppbuf.opp);
843446Smrj 	unsigned long *ip = (unsigned long *)(opp->oprom_array);
853446Smrj 
863446Smrj 	memset(oppbuf.buf, 0, MINBUFSIZE);
873446Smrj 	opp->oprom_size = MINVALSIZE;
883446Smrj 	*ip = id;
893446Smrj 	if (ioctl(prom_fd, OPROMCHILD, opp) < 0)
903446Smrj 		return (0);
913446Smrj 	return (*(unsigned long *)opp->oprom_array);
923446Smrj }
933446Smrj 
943446Smrj /*
953446Smrj  * Find a node by name from the prom device tree.
963446Smrj  * Return the id or 0 if it is not found.
973446Smrj  */
983446Smrj static unsigned long
prom_findnode_byname(unsigned long id,char * name)993446Smrj prom_findnode_byname(unsigned long id, char *name)
1003446Smrj {
1013446Smrj 	struct openpromio *opp = &(oppbuf.opp);
1023446Smrj 	unsigned long nid;
1033446Smrj 
1043446Smrj 	if (id == 0)
1053446Smrj 		return (0);
1063446Smrj 	if (!getpropval(opp, "name"))
1073446Smrj 		return (0);
1083446Smrj 	if (strcmp(opp->oprom_array, name) == 0)
1093446Smrj 		return (id);
1103446Smrj 	if (nid = prom_findnode_byname(child(id), name))
1113446Smrj 		return (nid);
1123446Smrj 	if (nid = prom_findnode_byname(next(id), name))
1133446Smrj 		return (nid);
1143446Smrj 	return (0);
1153446Smrj }
1163446Smrj 
1173446Smrj /*
1183446Smrj  * Make the current prom node be the rootnode and return its id.
1193446Smrj  */
1203446Smrj static unsigned long
prom_rootnode()1213446Smrj prom_rootnode()
1223446Smrj {
1233446Smrj 	return (next(0));
1243446Smrj }
1253446Smrj 
1263446Smrj static int
getpropval(struct openpromio * opp,char * prop)1273446Smrj getpropval(struct openpromio *opp, char *prop)
1283446Smrj {
1293446Smrj 	opp->oprom_size = MAXVALSIZE;
1303446Smrj 
1313446Smrj 	(void) strlcpy(opp->oprom_array, prop, MAXPROPSIZE);
1323446Smrj 	if (ioctl(prom_fd, OPROMGETPROP, opp) < 0)
1333446Smrj 		return (0);
1343446Smrj 	if (opp->oprom_size == 0)
1353446Smrj 		return (0);
1363446Smrj 	return (1);
1373446Smrj }
1383446Smrj 
1393446Smrj static int
getnextprop(struct openpromio * opp,char * prop)1403446Smrj getnextprop(struct openpromio *opp, char *prop)
1413446Smrj {
1423446Smrj 	opp->oprom_size = MAXVALSIZE;
1433446Smrj 
1443446Smrj 	(void) strlcpy(opp->oprom_array, prop, MAXPROPSIZE);
1453446Smrj 	if (ioctl(prom_fd, OPROMNXTPROP, opp) < 0)
1463446Smrj 		return (0);
1473446Smrj 	if (opp->oprom_size == 0)
1483446Smrj 		return (0);
1493446Smrj 	return (1);
1503446Smrj }
1513446Smrj 
152*11906SGangadhar.M@Sun.COM char *
getbootcmd(void)153*11906SGangadhar.M@Sun.COM getbootcmd(void)
154*11906SGangadhar.M@Sun.COM {
155*11906SGangadhar.M@Sun.COM 	struct openpromio *opp = &(oppbuf.opp);
156*11906SGangadhar.M@Sun.COM 	opp->oprom_size = MAXVALSIZE;
157*11906SGangadhar.M@Sun.COM 	if (ioctl(prom_fd, OPROMGETBOOTPATH, opp) < 0)
158*11906SGangadhar.M@Sun.COM 		return (NULL);
159*11906SGangadhar.M@Sun.COM 	return (opp->oprom_array);
160*11906SGangadhar.M@Sun.COM }
161*11906SGangadhar.M@Sun.COM 
1623446Smrj /*
1633446Smrj  * Get a pointer to the requested property from the current node.
1643446Smrj  * The property is stored in static storage and the returned pointer
1653446Smrj  * points into the static storage.  The property length is placed in
1663446Smrj  * the location pointed to by the third argument.
1673446Smrj  */
1683446Smrj static unsigned char *
prom_getprop(char * prop,int * lenp)1693446Smrj prom_getprop(char *prop, int *lenp)
1703446Smrj {
1713446Smrj 	struct openpromio *opp = &(oppbuf.opp);
1723446Smrj 
1733446Smrj 	if (!getpropval(opp, prop))
1743446Smrj 		return (NULL);
1753446Smrj 	*lenp = opp->oprom_size;
1763446Smrj 	return ((unsigned char *)opp->oprom_array);
1773446Smrj }
1783446Smrj 
1793446Smrj static unsigned char *
prom_nextprop(char * prop)1803446Smrj prom_nextprop(char *prop)
1813446Smrj {
1823446Smrj 	struct openpromio *opp = &(oppbuf.opp);
1833446Smrj 
1843446Smrj 	if (!getnextprop(opp, prop))
1853446Smrj 		return ((unsigned char *)0);
1863446Smrj 	return ((unsigned char *)opp->oprom_array);
1873446Smrj }
1883446Smrj 
1893446Smrj ddi_prop_t *
get_proplist(char * name)1903446Smrj get_proplist(char *name)
1913446Smrj {
1923446Smrj 	ddi_prop_t *plist, *npp, *plast;
1933446Smrj 	char *curprop, *newprop;
1943446Smrj 	unsigned char *propval;
1953446Smrj 	unsigned long id;
1963446Smrj 
1973446Smrj 	plist = NULL;
1983446Smrj 	plast = NULL;
1993446Smrj 	id = prom_findnode_byname(prom_rootnode(), name);
2003446Smrj 	if (id == 0)
2013446Smrj 		return (plist);
2023446Smrj 	curprop = "";
2033446Smrj 	while (newprop = (char *)prom_nextprop(curprop)) {
2043446Smrj 		curprop = strdup(newprop);
2053446Smrj 		npp = (ddi_prop_t *)malloc(sizeof (ddi_prop_t));
2063446Smrj 		if (npp == 0)
2073446Smrj 			exit(_error(PERROR, mfail));
2083446Smrj 		propval = prom_getprop(curprop, &npp->prop_len);
2093446Smrj 		npp->prop_name = curprop;
2103446Smrj 		if (propval != NULL) {
2113446Smrj 			npp->prop_val = (char *)malloc(npp->prop_len);
2123446Smrj 			if (npp->prop_val == 0)
2133446Smrj 				exit(_error(PERROR, mfail));
2143446Smrj 			memcpy(npp->prop_val, propval, npp->prop_len);
2153446Smrj 		} else
2163446Smrj 			npp->prop_val = NULL;
2173446Smrj 		npp->prop_next = NULL;
2183446Smrj 		if (plast == NULL) {
2193446Smrj 			plist = npp;
2203446Smrj 		} else {
2213446Smrj 			plast->prop_next = npp;
2223446Smrj 		}
2233446Smrj 		plast = npp;
2243446Smrj 	}
2253446Smrj 	return (plist);
2263446Smrj }
2273446Smrj 
2283446Smrj caddr_t
get_propval(char * name,char * node)2293446Smrj get_propval(char *name, char *node)
2303446Smrj {
2313446Smrj 	ddi_prop_t *prop, *plist;
2323446Smrj 
2333446Smrj 	if ((plist = get_proplist(node)) == NULL)
2343446Smrj 		return (NULL);
2353446Smrj 
2363446Smrj 	for (prop = plist; prop != NULL; prop = prop->prop_next)
2373446Smrj 		if (strcmp(prop->prop_name, name) == 0)
2383446Smrj 			return (prop->prop_val);
2393446Smrj 
2403446Smrj 	return (NULL);
2413446Smrj }
2423446Smrj 
2433446Smrj void
get_kbenv(void)2443446Smrj get_kbenv(void)
2453446Smrj {
2463446Smrj 	if ((prom_fd = open(promdev, O_RDONLY)) < 0) {
2473446Smrj 		exit(_error(PERROR, "prom open failed"));
2483446Smrj 	}
2493446Smrj }
2503446Smrj 
2513446Smrj void
close_kbenv(void)2523446Smrj close_kbenv(void)
2533446Smrj {
2543446Smrj 	(void) close(prom_fd);
2553446Smrj }
256