xref: /onnv-gate/usr/src/cmd/eeprom/i386/benv_kvm.c (revision 3446:5903aece022d)
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