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
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.
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]
23 * Copyright 2005 Sun Microsystems, Inc. All rights reserved.
24 * Use is subject to license terms.
27 #pragma ident "%Z%%M% %I% %E% SMI"
30 * Stuff for mucking about with properties
32 * XXX: There is no distinction between intefer and non-integer properties
33 * XXX: and no functions included for decoding properties. As is, this
34 * XXX: file is suitable for a big-endian machine, since properties are
35 * XXX: encoded using an XDR-like property encoding mechanism, which is
36 * XXX: big-endian native ordering. To fix this, you need to add type-
37 * XXX: sensitive decoding mechanisms and have the consumer of the data
38 * XXX: decode the data, since only the consumer can claim to know the
39 * XXX: the type of the data. (It can't be done automatically.)
42 #include <sys/promif.h>
43 #include <sys/promimpl.h>
44 #include <sys/platform_module.h>
46 static void prom_setprop_null(void);
50 * prom_setprop_{enter,exit} are set to plat_setprop_{enter,exit} on
51 * platforms which require access to the seeproms to be serialized.
52 * Otherwise these default to null functions. These functions must be
53 * called before promif_preprom, since it can sleep and change CPU's,
54 * thereby failing the assert in promif_postprom().
56 void (*prom_setprop_enter
)(void) = prom_setprop_null
;
57 void (*prom_setprop_exit
)(void) = prom_setprop_null
;
64 ci
[0] = p1275_ptr2cell("SUNW,asr-export-len"); /* Service name */
65 ci
[1] = (cell_t
)0; /* #argument cells */
66 ci
[2] = (cell_t
)1; /* #return cells */
67 ci
[3] = (cell_t
)-1; /* Res1: Prime result */
70 (void) p1275_cif_handler(&ci
);
73 return (p1275_cell2int(ci
[3])); /* Res1: buf length */
77 prom_asr_list_keys_len()
81 ci
[0] = p1275_ptr2cell("SUNW,asr-list-keys-len");
82 ci
[1] = (cell_t
)0; /* #argument cells */
83 ci
[2] = (cell_t
)1; /* #return cells */
84 ci
[3] = (cell_t
)-1; /* Res1: Prime result */
87 (void) p1275_cif_handler(&ci
);
90 return (p1275_cell2int(ci
[3])); /* Res1: buf length */
94 prom_asr_export(caddr_t value
)
99 ci
[0] = p1275_ptr2cell("SUNW,asr-export"); /* Service name */
100 ci
[1] = (cell_t
)1; /* #argument cells */
101 ci
[2] = (cell_t
)1; /* #return cells */
102 ci
[3] = p1275_ptr2cell(value
); /* Arg1: buffer address */
103 ci
[4] = -1; /* Res1: buf len */
106 rv
= p1275_cif_handler(&ci
);
111 return (p1275_cell2int(ci
[4])); /* Res1: buf length */
115 prom_asr_list_keys(caddr_t value
)
120 ci
[0] = p1275_ptr2cell("SUNW,asr-list-keys"); /* Service name */
121 ci
[1] = (cell_t
)1; /* #argument cells */
122 ci
[2] = (cell_t
)1; /* #return cells */
123 ci
[3] = p1275_ptr2cell(value
); /* Arg1: buffer address */
124 ci
[4] = -1; /* Res1: buf len */
127 rv
= p1275_cif_handler(&ci
);
132 return (p1275_cell2int(ci
[4])); /* Res1: buf length */
136 prom_asr_disable(char *keystr
, int keystr_len
,
137 char *reason
, int reason_len
)
142 ci
[0] = p1275_ptr2cell("SUNW,asr-disable"); /* Service name */
143 ci
[1] = (cell_t
)4; /* #argument cells */
144 ci
[2] = (cell_t
)0; /* #return cells */
145 ci
[3] = p1275_ptr2cell(keystr
); /* Arg1: key address */
146 ci
[3] = p1275_int2cell(keystr_len
); /* Arg2: key len */
147 ci
[3] = p1275_ptr2cell(reason
); /* Arg1: reason address */
148 ci
[3] = p1275_int2cell(reason_len
); /* Arg2: reason len */
151 rv
= p1275_cif_handler(&ci
);
158 prom_asr_enable(char *keystr
, int keystr_len
)
163 ci
[0] = p1275_ptr2cell("SUNW,asr-enable"); /* Service name */
164 ci
[1] = (cell_t
)2; /* #argument cells */
165 ci
[2] = (cell_t
)0; /* #return cells */
166 ci
[3] = p1275_ptr2cell(keystr
); /* Arg1: key address */
167 ci
[3] = p1275_int2cell(keystr_len
); /* Arg2: key len */
170 rv
= p1275_cif_handler(&ci
);
177 prom_setprop_null(void)
182 prom_getproplen(pnode_t nodeid
, caddr_t name
)
186 ci
[0] = p1275_ptr2cell("getproplen"); /* Service name */
187 ci
[1] = (cell_t
)2; /* #argument cells */
188 ci
[2] = (cell_t
)1; /* #return cells */
189 ci
[3] = p1275_phandle2cell((phandle_t
)nodeid
); /* Arg1: package */
190 ci
[4] = p1275_ptr2cell(name
); /* Arg2: Property name */
191 ci
[5] = (cell_t
)-1; /* Res1: Prime result */
194 (void) p1275_cif_handler(&ci
);
197 return (p1275_cell2int(ci
[5])); /* Res1: Property length */
202 prom_getprop(pnode_t nodeid
, caddr_t name
, caddr_t value
)
208 * This function assumes the buffer is large enough to
209 * hold the result, so in 1275 mode, we pass in the length
210 * of the property as the length of the buffer, since we
211 * have no way of knowing the size of the buffer. Pre-1275
212 * OpenBoot(tm) PROMs did not have a bounded getprop.
214 * Note that we ignore the "length" result of the service.
217 if ((len
= prom_getproplen(nodeid
, name
)) <= 0)
220 ci
[0] = p1275_ptr2cell("getprop"); /* Service name */
221 ci
[1] = (cell_t
)4; /* #argument cells */
222 ci
[2] = (cell_t
)0; /* #result cells */
223 ci
[3] = p1275_phandle2cell((phandle_t
)nodeid
); /* Arg1: package */
224 ci
[4] = p1275_ptr2cell(name
); /* Arg2: property name */
225 ci
[5] = p1275_ptr2cell(value
); /* Arg3: buffer address */
226 ci
[6] = len
; /* Arg4: buf len (assumed) */
229 rv
= p1275_cif_handler(&ci
);
234 return (len
); /* Return known length */
238 prom_bounded_getprop(pnode_t nodeid
, caddr_t name
, caddr_t value
, int len
)
242 ci
[0] = p1275_ptr2cell("getprop"); /* Service name */
243 ci
[1] = (cell_t
)4; /* #argument cells */
244 ci
[2] = (cell_t
)1; /* #result cells */
245 ci
[3] = p1275_phandle2cell((phandle_t
)nodeid
); /* Arg1: package */
246 ci
[4] = p1275_ptr2cell(name
); /* Arg2: property name */
247 ci
[5] = p1275_ptr2cell(value
); /* Arg3: buffer address */
248 ci
[6] = p1275_int2cell(len
); /* Arg4: buffer length */
249 ci
[7] = (cell_t
)-1; /* Res1: Prime result */
252 (void) p1275_cif_handler(&ci
);
255 return (p1275_cell2int(ci
[7])); /* Res1: Returned length */
259 prom_nextprop(pnode_t nodeid
, caddr_t previous
, caddr_t next
)
263 (void) prom_strcpy(next
, ""); /* Prime result, in case call fails */
265 ci
[0] = p1275_ptr2cell("nextprop"); /* Service name */
266 ci
[1] = (cell_t
)3; /* #argument cells */
267 ci
[2] = (cell_t
)0; /* #result cells */
268 ci
[3] = p1275_phandle2cell((phandle_t
)nodeid
); /* Arg1: phandle */
269 ci
[4] = p1275_ptr2cell(previous
); /* Arg2: addr of prev name */
270 ci
[5] = p1275_ptr2cell(next
); /* Arg3: addr of 32 byte buf */
273 (void) p1275_cif_handler(&ci
);
280 prom_setprop(pnode_t nodeid
, caddr_t name
, caddr_t value
, int len
)
283 #ifdef PROM_32BIT_ADDRS
284 caddr_t ovalue
= NULL
;
286 if ((uintptr_t)value
> (uint32_t)-1) {
288 value
= promplat_alloc(len
);
292 promplat_bcopy(ovalue
, value
, len
);
296 prom_setprop_enter();
300 ci
[0] = p1275_ptr2cell("setprop"); /* Service name */
301 ci
[1] = (cell_t
)4; /* #argument cells */
302 ci
[2] = (cell_t
)1; /* #result cells */
303 ci
[3] = p1275_phandle2cell((phandle_t
)nodeid
); /* Arg1: phandle */
304 ci
[4] = p1275_ptr2cell(name
); /* Arg2: property name */
305 ci
[5] = p1275_ptr2cell(value
); /* Arg3: New value ptr */
306 ci
[6] = p1275_int2cell(len
); /* Arg4: New value len */
307 ci
[7] = (cell_t
)-1; /* Res1: Prime result */
309 (void) p1275_cif_handler(&ci
);
315 #ifdef PROM_32BIT_ADDRS
317 promplat_free(value
, len
);
320 return (p1275_cell2int(ci
[7])); /* Res1: Actual new size */
324 * prom_decode_composite_string:
326 * Returns successive strings in a composite string property.
327 * A composite string property is a buffer containing one or more
328 * NULL terminated strings contained within the length of the buffer.
330 * Always call with the base address and length of the property buffer.
331 * On the first call, call with prev == 0, call successively
332 * with prev == to the last value returned from this function
333 * until the routine returns zero which means no more string values.
336 prom_decode_composite_string(void *buf
, size_t buflen
, char *prev
)
338 if ((buf
== 0) || (buflen
== 0) || ((int)buflen
== -1))
342 return ((char *)buf
);
344 prev
+= prom_strlen(prev
) + 1;
345 if (prev
>= ((char *)buf
+ buflen
))