xref: /onnv-gate/usr/src/psm/promif/ieee1275/common/prom_prop.c (revision 789:b348f31ed315)
10Sstevel@tonic-gate /*
20Sstevel@tonic-gate  * CDDL HEADER START
30Sstevel@tonic-gate  *
40Sstevel@tonic-gate  * The contents of this file are subject to the terms of the
50Sstevel@tonic-gate  * Common Development and Distribution License, Version 1.0 only
60Sstevel@tonic-gate  * (the "License").  You may not use this file except in compliance
70Sstevel@tonic-gate  * with the License.
80Sstevel@tonic-gate  *
90Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
100Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
110Sstevel@tonic-gate  * See the License for the specific language governing permissions
120Sstevel@tonic-gate  * and limitations under the License.
130Sstevel@tonic-gate  *
140Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
150Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
160Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
170Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
180Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
190Sstevel@tonic-gate  *
200Sstevel@tonic-gate  * CDDL HEADER END
210Sstevel@tonic-gate  */
220Sstevel@tonic-gate /*
23*789Sahrens  * Copyright 2005 Sun Microsystems, Inc.  All rights reserved.
240Sstevel@tonic-gate  * Use is subject to license terms.
250Sstevel@tonic-gate  */
260Sstevel@tonic-gate 
270Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
280Sstevel@tonic-gate 
290Sstevel@tonic-gate /*
300Sstevel@tonic-gate  * Stuff for mucking about with properties
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  * XXX: There is no distinction between intefer and non-integer properties
330Sstevel@tonic-gate  * XXX: and no functions included for decoding properties.  As is, this
340Sstevel@tonic-gate  * XXX: file is suitable for a big-endian machine, since properties are
350Sstevel@tonic-gate  * XXX: encoded using an XDR-like property encoding mechanism, which is
360Sstevel@tonic-gate  * XXX: big-endian native ordering.  To fix this, you need to add type-
370Sstevel@tonic-gate  * XXX: sensitive decoding mechanisms and have the consumer of the data
380Sstevel@tonic-gate  * XXX: decode the data, since only the consumer can claim to know the
390Sstevel@tonic-gate  * XXX: the type of the data. (It can't be done automatically.)
400Sstevel@tonic-gate  */
410Sstevel@tonic-gate 
420Sstevel@tonic-gate #include <sys/promif.h>
430Sstevel@tonic-gate #include <sys/promimpl.h>
440Sstevel@tonic-gate #include <sys/platform_module.h>
450Sstevel@tonic-gate 
460Sstevel@tonic-gate static void prom_setprop_null(void);
470Sstevel@tonic-gate 
480Sstevel@tonic-gate 
490Sstevel@tonic-gate /*
500Sstevel@tonic-gate  * prom_setprop_{enter,exit} are set to plat_setprop_{enter,exit} on
510Sstevel@tonic-gate  * platforms which require access to the seeproms to be serialized.
520Sstevel@tonic-gate  * Otherwise these default to null functions.  These functions must be
530Sstevel@tonic-gate  * called before promif_preprom, since it can sleep and change CPU's,
540Sstevel@tonic-gate  * thereby failing the assert in promif_postprom().
550Sstevel@tonic-gate  */
560Sstevel@tonic-gate void (*prom_setprop_enter)(void) = prom_setprop_null;
570Sstevel@tonic-gate void (*prom_setprop_exit)(void) = prom_setprop_null;
580Sstevel@tonic-gate 
590Sstevel@tonic-gate int
prom_asr_export_len()600Sstevel@tonic-gate prom_asr_export_len()
610Sstevel@tonic-gate {
620Sstevel@tonic-gate 	cell_t ci[4];
630Sstevel@tonic-gate 
640Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("SUNW,asr-export-len");	/* Service name */
650Sstevel@tonic-gate 	ci[1] = (cell_t)0;			/* #argument cells */
660Sstevel@tonic-gate 	ci[2] = (cell_t)1;			/* #return cells */
670Sstevel@tonic-gate 	ci[3] = (cell_t)-1;			/* Res1: Prime result */
680Sstevel@tonic-gate 
690Sstevel@tonic-gate 	promif_preprom();
700Sstevel@tonic-gate 	(void) p1275_cif_handler(&ci);
710Sstevel@tonic-gate 	promif_postprom();
720Sstevel@tonic-gate 
730Sstevel@tonic-gate 	return (p1275_cell2int(ci[3]));		/* Res1: buf length */
740Sstevel@tonic-gate }
750Sstevel@tonic-gate 
760Sstevel@tonic-gate int
prom_asr_list_keys_len()770Sstevel@tonic-gate prom_asr_list_keys_len()
780Sstevel@tonic-gate {
790Sstevel@tonic-gate 	cell_t ci[4];
800Sstevel@tonic-gate 
810Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("SUNW,asr-list-keys-len");
820Sstevel@tonic-gate 	ci[1] = (cell_t)0;			/* #argument cells */
830Sstevel@tonic-gate 	ci[2] = (cell_t)1;			/* #return cells */
840Sstevel@tonic-gate 	ci[3] = (cell_t)-1;			/* Res1: Prime result */
850Sstevel@tonic-gate 
860Sstevel@tonic-gate 	promif_preprom();
870Sstevel@tonic-gate 	(void) p1275_cif_handler(&ci);
880Sstevel@tonic-gate 	promif_postprom();
890Sstevel@tonic-gate 
900Sstevel@tonic-gate 	return (p1275_cell2int(ci[3]));		/* Res1: buf length */
910Sstevel@tonic-gate }
920Sstevel@tonic-gate 
930Sstevel@tonic-gate int
prom_asr_export(caddr_t value)940Sstevel@tonic-gate prom_asr_export(caddr_t value)
950Sstevel@tonic-gate {
960Sstevel@tonic-gate 	int rv;
970Sstevel@tonic-gate 	cell_t ci[5];
980Sstevel@tonic-gate 
990Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("SUNW,asr-export");	/* Service name */
1000Sstevel@tonic-gate 	ci[1] = (cell_t)1;			/* #argument cells */
1010Sstevel@tonic-gate 	ci[2] = (cell_t)1;			/* #return cells */
1020Sstevel@tonic-gate 	ci[3] = p1275_ptr2cell(value);		/* Arg1: buffer address */
1030Sstevel@tonic-gate 	ci[4] = -1;				/* Res1: buf len */
1040Sstevel@tonic-gate 
1050Sstevel@tonic-gate 	promif_preprom();
1060Sstevel@tonic-gate 	rv = p1275_cif_handler(&ci);
1070Sstevel@tonic-gate 	promif_postprom();
1080Sstevel@tonic-gate 
1090Sstevel@tonic-gate 	if (rv != 0)
1100Sstevel@tonic-gate 		return (-1);
1110Sstevel@tonic-gate 	return (p1275_cell2int(ci[4]));		/* Res1: buf length */
1120Sstevel@tonic-gate }
1130Sstevel@tonic-gate 
1140Sstevel@tonic-gate int
prom_asr_list_keys(caddr_t value)1150Sstevel@tonic-gate prom_asr_list_keys(caddr_t value)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	int rv;
1180Sstevel@tonic-gate 	cell_t ci[5];
1190Sstevel@tonic-gate 
1200Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("SUNW,asr-list-keys");	/* Service name */
1210Sstevel@tonic-gate 	ci[1] = (cell_t)1;			/* #argument cells */
1220Sstevel@tonic-gate 	ci[2] = (cell_t)1;			/* #return cells */
1230Sstevel@tonic-gate 	ci[3] = p1275_ptr2cell(value);		/* Arg1: buffer address */
1240Sstevel@tonic-gate 	ci[4] = -1;				/* Res1: buf len */
1250Sstevel@tonic-gate 
1260Sstevel@tonic-gate 	promif_preprom();
1270Sstevel@tonic-gate 	rv = p1275_cif_handler(&ci);
1280Sstevel@tonic-gate 	promif_postprom();
1290Sstevel@tonic-gate 
1300Sstevel@tonic-gate 	if (rv != 0)
1310Sstevel@tonic-gate 		return (-1);
1320Sstevel@tonic-gate 	return (p1275_cell2int(ci[4]));		/* Res1: buf length */
1330Sstevel@tonic-gate }
1340Sstevel@tonic-gate 
1350Sstevel@tonic-gate int
prom_asr_disable(char * keystr,int keystr_len,char * reason,int reason_len)1360Sstevel@tonic-gate prom_asr_disable(char *keystr, int keystr_len,
1370Sstevel@tonic-gate     char *reason, int reason_len)
1380Sstevel@tonic-gate {
1390Sstevel@tonic-gate 	int rv;
1400Sstevel@tonic-gate 	cell_t ci[5];
1410Sstevel@tonic-gate 
1420Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("SUNW,asr-disable");	/* Service name */
1430Sstevel@tonic-gate 	ci[1] = (cell_t)4;			/* #argument cells */
1440Sstevel@tonic-gate 	ci[2] = (cell_t)0;			/* #return cells */
1450Sstevel@tonic-gate 	ci[3] = p1275_ptr2cell(keystr);		/* Arg1: key address */
1460Sstevel@tonic-gate 	ci[3] = p1275_int2cell(keystr_len);	/* Arg2: key len */
1470Sstevel@tonic-gate 	ci[3] = p1275_ptr2cell(reason);		/* Arg1: reason address */
1480Sstevel@tonic-gate 	ci[3] = p1275_int2cell(reason_len);	/* Arg2: reason len */
1490Sstevel@tonic-gate 
1500Sstevel@tonic-gate 	promif_preprom();
1510Sstevel@tonic-gate 	rv = p1275_cif_handler(&ci);
1520Sstevel@tonic-gate 	promif_postprom();
1530Sstevel@tonic-gate 
1540Sstevel@tonic-gate 	return (rv);
1550Sstevel@tonic-gate }
1560Sstevel@tonic-gate 
1570Sstevel@tonic-gate int
prom_asr_enable(char * keystr,int keystr_len)1580Sstevel@tonic-gate prom_asr_enable(char *keystr, int keystr_len)
1590Sstevel@tonic-gate {
1600Sstevel@tonic-gate 	int rv;
1610Sstevel@tonic-gate 	cell_t ci[5];
1620Sstevel@tonic-gate 
1630Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("SUNW,asr-enable");	/* Service name */
1640Sstevel@tonic-gate 	ci[1] = (cell_t)2;			/* #argument cells */
1650Sstevel@tonic-gate 	ci[2] = (cell_t)0;			/* #return cells */
1660Sstevel@tonic-gate 	ci[3] = p1275_ptr2cell(keystr);		/* Arg1: key address */
1670Sstevel@tonic-gate 	ci[3] = p1275_int2cell(keystr_len);	/* Arg2: key len */
1680Sstevel@tonic-gate 
1690Sstevel@tonic-gate 	promif_preprom();
1700Sstevel@tonic-gate 	rv = p1275_cif_handler(&ci);
1710Sstevel@tonic-gate 	promif_postprom();
1720Sstevel@tonic-gate 
1730Sstevel@tonic-gate 	return (rv);
1740Sstevel@tonic-gate }
1750Sstevel@tonic-gate 
1760Sstevel@tonic-gate static void
prom_setprop_null(void)1770Sstevel@tonic-gate prom_setprop_null(void)
1780Sstevel@tonic-gate {
1790Sstevel@tonic-gate }
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate int
prom_getproplen(pnode_t nodeid,caddr_t name)182*789Sahrens prom_getproplen(pnode_t nodeid, caddr_t name)
1830Sstevel@tonic-gate {
1840Sstevel@tonic-gate 	cell_t ci[6];
1850Sstevel@tonic-gate 
1860Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("getproplen");	/* Service name */
1870Sstevel@tonic-gate 	ci[1] = (cell_t)2;			/* #argument cells */
1880Sstevel@tonic-gate 	ci[2] = (cell_t)1;			/* #return cells */
1890Sstevel@tonic-gate 	ci[3] = p1275_phandle2cell((phandle_t)nodeid);	/* Arg1: package */
1900Sstevel@tonic-gate 	ci[4] = p1275_ptr2cell(name);		/* Arg2: Property name */
1910Sstevel@tonic-gate 	ci[5] = (cell_t)-1;			/* Res1: Prime result */
1920Sstevel@tonic-gate 
1930Sstevel@tonic-gate 	promif_preprom();
1940Sstevel@tonic-gate 	(void) p1275_cif_handler(&ci);
1950Sstevel@tonic-gate 	promif_postprom();
1960Sstevel@tonic-gate 
1970Sstevel@tonic-gate 	return (p1275_cell2int(ci[5]));		/* Res1: Property length */
1980Sstevel@tonic-gate }
1990Sstevel@tonic-gate 
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate int
prom_getprop(pnode_t nodeid,caddr_t name,caddr_t value)202*789Sahrens prom_getprop(pnode_t nodeid, caddr_t name, caddr_t value)
2030Sstevel@tonic-gate {
2040Sstevel@tonic-gate 	int len, rv;
2050Sstevel@tonic-gate 	cell_t ci[8];
2060Sstevel@tonic-gate 
2070Sstevel@tonic-gate 	/*
2080Sstevel@tonic-gate 	 * This function assumes the buffer is large enough to
2090Sstevel@tonic-gate 	 * hold the result, so in 1275 mode, we pass in the length
2100Sstevel@tonic-gate 	 * of the property as the length of the buffer, since we
2110Sstevel@tonic-gate 	 * have no way of knowing the size of the buffer. Pre-1275
2120Sstevel@tonic-gate 	 * OpenBoot(tm) PROMs did not have a bounded getprop.
2130Sstevel@tonic-gate 	 *
2140Sstevel@tonic-gate 	 * Note that we ignore the "length" result of the service.
2150Sstevel@tonic-gate 	 */
2160Sstevel@tonic-gate 
2170Sstevel@tonic-gate 	if ((len = prom_getproplen(nodeid, name)) <= 0)
2180Sstevel@tonic-gate 		return (len);
2190Sstevel@tonic-gate 
2200Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("getprop");	/* Service name */
2210Sstevel@tonic-gate 	ci[1] = (cell_t)4;			/* #argument cells */
2220Sstevel@tonic-gate 	ci[2] = (cell_t)0;			/* #result cells */
2230Sstevel@tonic-gate 	ci[3] = p1275_phandle2cell((phandle_t)nodeid);	/* Arg1: package */
2240Sstevel@tonic-gate 	ci[4] = p1275_ptr2cell(name);		/* Arg2: property name */
2250Sstevel@tonic-gate 	ci[5] = p1275_ptr2cell(value);		/* Arg3: buffer address */
2260Sstevel@tonic-gate 	ci[6] = len;				/* Arg4: buf len (assumed) */
2270Sstevel@tonic-gate 
2280Sstevel@tonic-gate 	promif_preprom();
2290Sstevel@tonic-gate 	rv = p1275_cif_handler(&ci);
2300Sstevel@tonic-gate 	promif_postprom();
2310Sstevel@tonic-gate 
2320Sstevel@tonic-gate 	if (rv != 0)
2330Sstevel@tonic-gate 		return (-1);
2340Sstevel@tonic-gate 	return (len);				/* Return known length */
2350Sstevel@tonic-gate }
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate int
prom_bounded_getprop(pnode_t nodeid,caddr_t name,caddr_t value,int len)238*789Sahrens prom_bounded_getprop(pnode_t nodeid, caddr_t name, caddr_t value, int len)
2390Sstevel@tonic-gate {
2400Sstevel@tonic-gate 	cell_t ci[8];
2410Sstevel@tonic-gate 
2420Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("getprop");	/* Service name */
2430Sstevel@tonic-gate 	ci[1] = (cell_t)4;			/* #argument cells */
2440Sstevel@tonic-gate 	ci[2] = (cell_t)1;			/* #result cells */
2450Sstevel@tonic-gate 	ci[3] = p1275_phandle2cell((phandle_t)nodeid); /* Arg1: package */
2460Sstevel@tonic-gate 	ci[4] = p1275_ptr2cell(name);		/* Arg2: property name */
2470Sstevel@tonic-gate 	ci[5] = p1275_ptr2cell(value);		/* Arg3: buffer address */
2480Sstevel@tonic-gate 	ci[6] = p1275_int2cell(len);		/* Arg4: buffer length */
2490Sstevel@tonic-gate 	ci[7] = (cell_t)-1;			/* Res1: Prime result */
2500Sstevel@tonic-gate 
2510Sstevel@tonic-gate 	promif_preprom();
2520Sstevel@tonic-gate 	(void) p1275_cif_handler(&ci);
2530Sstevel@tonic-gate 	promif_postprom();
2540Sstevel@tonic-gate 
2550Sstevel@tonic-gate 	return (p1275_cell2int(ci[7]));		/* Res1: Returned length */
2560Sstevel@tonic-gate }
2570Sstevel@tonic-gate 
2580Sstevel@tonic-gate caddr_t
prom_nextprop(pnode_t nodeid,caddr_t previous,caddr_t next)259*789Sahrens prom_nextprop(pnode_t nodeid, caddr_t previous, caddr_t next)
2600Sstevel@tonic-gate {
2610Sstevel@tonic-gate 	cell_t ci[7];
2620Sstevel@tonic-gate 
2630Sstevel@tonic-gate 	(void) prom_strcpy(next, "");	/* Prime result, in case call fails */
2640Sstevel@tonic-gate 
2650Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("nextprop");	/* Service name */
2660Sstevel@tonic-gate 	ci[1] = (cell_t)3;			/* #argument cells */
2670Sstevel@tonic-gate 	ci[2] = (cell_t)0;			/* #result cells */
2680Sstevel@tonic-gate 	ci[3] = p1275_phandle2cell((phandle_t)nodeid); /* Arg1: phandle */
2690Sstevel@tonic-gate 	ci[4] = p1275_ptr2cell(previous);	/* Arg2: addr of prev name */
2700Sstevel@tonic-gate 	ci[5] = p1275_ptr2cell(next);		/* Arg3: addr of 32 byte buf */
2710Sstevel@tonic-gate 
2720Sstevel@tonic-gate 	promif_preprom();
2730Sstevel@tonic-gate 	(void) p1275_cif_handler(&ci);
2740Sstevel@tonic-gate 	promif_postprom();
2750Sstevel@tonic-gate 
2760Sstevel@tonic-gate 	return (next);
2770Sstevel@tonic-gate }
2780Sstevel@tonic-gate 
2790Sstevel@tonic-gate int
prom_setprop(pnode_t nodeid,caddr_t name,caddr_t value,int len)280*789Sahrens prom_setprop(pnode_t nodeid, caddr_t name, caddr_t value, int len)
2810Sstevel@tonic-gate {
2820Sstevel@tonic-gate 	cell_t ci[8];
2830Sstevel@tonic-gate #ifdef PROM_32BIT_ADDRS
2840Sstevel@tonic-gate 	caddr_t ovalue = NULL;
2850Sstevel@tonic-gate 
2860Sstevel@tonic-gate 	if ((uintptr_t)value > (uint32_t)-1) {
2870Sstevel@tonic-gate 		ovalue = value;
2880Sstevel@tonic-gate 		value = promplat_alloc(len);
2890Sstevel@tonic-gate 		if (value == NULL) {
2900Sstevel@tonic-gate 			return (-1);
2910Sstevel@tonic-gate 		}
2920Sstevel@tonic-gate 		promplat_bcopy(ovalue, value, len);
2930Sstevel@tonic-gate 	}
2940Sstevel@tonic-gate #endif
2950Sstevel@tonic-gate 
2960Sstevel@tonic-gate 	prom_setprop_enter();
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	promif_preprom();
2990Sstevel@tonic-gate 
3000Sstevel@tonic-gate 	ci[0] = p1275_ptr2cell("setprop");	/* Service name */
3010Sstevel@tonic-gate 	ci[1] = (cell_t)4;			/* #argument cells */
3020Sstevel@tonic-gate 	ci[2] = (cell_t)1;			/* #result cells */
3030Sstevel@tonic-gate 	ci[3] = p1275_phandle2cell((phandle_t)nodeid);	/* Arg1: phandle */
3040Sstevel@tonic-gate 	ci[4] = p1275_ptr2cell(name);		/* Arg2: property name */
3050Sstevel@tonic-gate 	ci[5] = p1275_ptr2cell(value);		/* Arg3: New value ptr */
3060Sstevel@tonic-gate 	ci[6] = p1275_int2cell(len);		/* Arg4: New value len */
3070Sstevel@tonic-gate 	ci[7] = (cell_t)-1;			/* Res1: Prime result */
3080Sstevel@tonic-gate 
3090Sstevel@tonic-gate 	(void) p1275_cif_handler(&ci);
3100Sstevel@tonic-gate 
3110Sstevel@tonic-gate 	promif_postprom();
3120Sstevel@tonic-gate 
3130Sstevel@tonic-gate 	prom_setprop_exit();
3140Sstevel@tonic-gate 
3150Sstevel@tonic-gate #ifdef PROM_32BIT_ADDRS
3160Sstevel@tonic-gate 	if (ovalue != NULL)
3170Sstevel@tonic-gate 		promplat_free(value, len);
3180Sstevel@tonic-gate #endif
3190Sstevel@tonic-gate 
3200Sstevel@tonic-gate 	return (p1275_cell2int(ci[7]));		/* Res1: Actual new size */
3210Sstevel@tonic-gate }
3220Sstevel@tonic-gate 
3230Sstevel@tonic-gate /*
3240Sstevel@tonic-gate  * prom_decode_composite_string:
3250Sstevel@tonic-gate  *
3260Sstevel@tonic-gate  * Returns successive strings in a composite string property.
3270Sstevel@tonic-gate  * A composite string property is a buffer containing one or more
3280Sstevel@tonic-gate  * NULL terminated strings contained within the length of the buffer.
3290Sstevel@tonic-gate  *
3300Sstevel@tonic-gate  * Always call with the base address and length of the property buffer.
3310Sstevel@tonic-gate  * On the first call, call with prev == 0, call successively
3320Sstevel@tonic-gate  * with prev == to the last value returned from this function
3330Sstevel@tonic-gate  * until the routine returns zero which means no more string values.
3340Sstevel@tonic-gate  */
3350Sstevel@tonic-gate char *
prom_decode_composite_string(void * buf,size_t buflen,char * prev)3360Sstevel@tonic-gate prom_decode_composite_string(void *buf, size_t buflen, char *prev)
3370Sstevel@tonic-gate {
3380Sstevel@tonic-gate 	if ((buf == 0) || (buflen == 0) || ((int)buflen == -1))
3390Sstevel@tonic-gate 		return ((char *)0);
3400Sstevel@tonic-gate 
3410Sstevel@tonic-gate 	if (prev == 0)
3420Sstevel@tonic-gate 		return ((char *)buf);
3430Sstevel@tonic-gate 
3440Sstevel@tonic-gate 	prev += prom_strlen(prev) + 1;
3450Sstevel@tonic-gate 	if (prev >= ((char *)buf + buflen))
3460Sstevel@tonic-gate 		return ((char *)0);
3470Sstevel@tonic-gate 	return (prev);
3480Sstevel@tonic-gate }
349