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