xref: /onnv-gate/usr/src/lib/libdevinfo/devinfo_prop_decode.c (revision 3814:125bd6a8c9c0)
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
5*3814Sjveta  * Common Development and Distribution License (the "License").
6*3814Sjveta  * You may not use this file except in compliance with the License.
70Sstevel@tonic-gate  *
80Sstevel@tonic-gate  * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
90Sstevel@tonic-gate  * or http://www.opensolaris.org/os/licensing.
100Sstevel@tonic-gate  * See the License for the specific language governing permissions
110Sstevel@tonic-gate  * and limitations under the License.
120Sstevel@tonic-gate  *
130Sstevel@tonic-gate  * When distributing Covered Code, include this CDDL HEADER in each
140Sstevel@tonic-gate  * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
150Sstevel@tonic-gate  * If applicable, add the following below this CDDL HEADER, with the
160Sstevel@tonic-gate  * fields enclosed by brackets "[]" replaced with your own identifying
170Sstevel@tonic-gate  * information: Portions Copyright [yyyy] [name of copyright owner]
180Sstevel@tonic-gate  *
190Sstevel@tonic-gate  * CDDL HEADER END
200Sstevel@tonic-gate  */
210Sstevel@tonic-gate /*
22*3814Sjveta  * Copyright 2007 Sun Microsystems, Inc.  All rights reserved.
230Sstevel@tonic-gate  * Use is subject to license terms.
240Sstevel@tonic-gate  */
250Sstevel@tonic-gate 
260Sstevel@tonic-gate #pragma ident	"%Z%%M%	%I%	%E% SMI"
270Sstevel@tonic-gate 
280Sstevel@tonic-gate /*
290Sstevel@tonic-gate  * This file contains kernel property decode routines adopted from
300Sstevel@tonic-gate  * sunddi.c and ddi_impl.c. The following changes have been applied.
310Sstevel@tonic-gate  *
320Sstevel@tonic-gate  * (1) Replace kmem_alloc by malloc. Remove negative indexing
330Sstevel@tonic-gate  * (2) Decoding applies only to prom properties.
340Sstevel@tonic-gate  * (3) For strings, the return value is a composite string, not a string array.
350Sstevel@tonic-gate  * (4) impl_ddi_prop_int_from_prom() uses _LITTLE_ENDIAN from isa_defs.h
360Sstevel@tonic-gate  *
370Sstevel@tonic-gate  * XXX This file should be kept in sync with kernel property encoding.
380Sstevel@tonic-gate  */
390Sstevel@tonic-gate 
400Sstevel@tonic-gate #include <stdlib.h>
410Sstevel@tonic-gate #include <strings.h>
420Sstevel@tonic-gate #include <synch.h>
430Sstevel@tonic-gate #include <ctype.h>
440Sstevel@tonic-gate #include <sys/types.h>
450Sstevel@tonic-gate #include <sys/dditypes.h>
460Sstevel@tonic-gate #include <sys/ddipropdefs.h>
470Sstevel@tonic-gate #include <sys/isa_defs.h>
480Sstevel@tonic-gate 
490Sstevel@tonic-gate #include "libdevinfo.h"
500Sstevel@tonic-gate 
510Sstevel@tonic-gate /*
520Sstevel@tonic-gate  * Return an integer in native machine format from an OBP 1275 integer
530Sstevel@tonic-gate  * representation, which is big-endian, with no particular alignment
540Sstevel@tonic-gate  * guarantees. intp points to the OBP data, and n the number of bytes.
550Sstevel@tonic-gate  *
560Sstevel@tonic-gate  * Byte-swapping may be needed on some implementations.
570Sstevel@tonic-gate  */
580Sstevel@tonic-gate int
impl_di_prop_int_from_prom(uchar_t * intp,int n)590Sstevel@tonic-gate impl_di_prop_int_from_prom(uchar_t *intp, int n)
600Sstevel@tonic-gate {
610Sstevel@tonic-gate 	int i = 0;
620Sstevel@tonic-gate 
630Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN)
640Sstevel@tonic-gate 	intp += n;
650Sstevel@tonic-gate 	while (n-- > 0) {
660Sstevel@tonic-gate 		i = (i << 8) | *(--intp);
670Sstevel@tonic-gate 	}
680Sstevel@tonic-gate #else
690Sstevel@tonic-gate 	while (n-- > 0) {
700Sstevel@tonic-gate 		i = (i << 8) | *intp++;
710Sstevel@tonic-gate 	}
720Sstevel@tonic-gate #endif	/* defined(_LITTLE_ENDIAN) */
730Sstevel@tonic-gate 
740Sstevel@tonic-gate 	return (i);
750Sstevel@tonic-gate }
760Sstevel@tonic-gate 
770Sstevel@tonic-gate /*
780Sstevel@tonic-gate  * Reset the current location pointer in the property handle to the
790Sstevel@tonic-gate  * beginning of the data.
800Sstevel@tonic-gate  */
810Sstevel@tonic-gate void
di_prop_reset_pos(prop_handle_t * ph)820Sstevel@tonic-gate di_prop_reset_pos(prop_handle_t *ph)
830Sstevel@tonic-gate {
840Sstevel@tonic-gate 	ph->ph_cur_pos = ph->ph_data;
850Sstevel@tonic-gate 	ph->ph_save_pos = ph->ph_data;
860Sstevel@tonic-gate }
870Sstevel@tonic-gate 
880Sstevel@tonic-gate /*
890Sstevel@tonic-gate  * Restore the current location pointer in the property handle to the
900Sstevel@tonic-gate  * saved position.
910Sstevel@tonic-gate  */
920Sstevel@tonic-gate void
di_prop_save_pos(prop_handle_t * ph)930Sstevel@tonic-gate di_prop_save_pos(prop_handle_t *ph)
940Sstevel@tonic-gate {
950Sstevel@tonic-gate 	ph->ph_save_pos = ph->ph_cur_pos;
960Sstevel@tonic-gate }
970Sstevel@tonic-gate 
980Sstevel@tonic-gate /*
990Sstevel@tonic-gate  * Save the location that the current location poiner is pointing to..
1000Sstevel@tonic-gate  */
1010Sstevel@tonic-gate void
di_prop_restore_pos(prop_handle_t * ph)1020Sstevel@tonic-gate di_prop_restore_pos(prop_handle_t *ph)
1030Sstevel@tonic-gate {
1040Sstevel@tonic-gate 	ph->ph_cur_pos = ph->ph_save_pos;
1050Sstevel@tonic-gate }
1060Sstevel@tonic-gate 
1070Sstevel@tonic-gate /*
1080Sstevel@tonic-gate  * Property encode/decode functions
1090Sstevel@tonic-gate  */
1100Sstevel@tonic-gate 
1110Sstevel@tonic-gate /*
1120Sstevel@tonic-gate  * Decode an array of integers property
1130Sstevel@tonic-gate  */
1140Sstevel@tonic-gate static int
di_prop_fm_decode_ints(prop_handle_t * ph,void * data,uint_t * nelements)1150Sstevel@tonic-gate di_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements)
1160Sstevel@tonic-gate {
1170Sstevel@tonic-gate 	int	i;
1180Sstevel@tonic-gate 	int	cnt = 0;
1190Sstevel@tonic-gate 	int	*tmp;
1200Sstevel@tonic-gate 	int	*intp;
1210Sstevel@tonic-gate 	int	n;
1220Sstevel@tonic-gate 
1230Sstevel@tonic-gate 	/*
1240Sstevel@tonic-gate 	 * Figure out how many array elements there are by going through the
1250Sstevel@tonic-gate 	 * data without decoding it first and counting.
1260Sstevel@tonic-gate 	 */
1270Sstevel@tonic-gate 	for (;;) {
1280Sstevel@tonic-gate 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL);
1290Sstevel@tonic-gate 		if (i < 0)
1300Sstevel@tonic-gate 			break;
1310Sstevel@tonic-gate 		cnt++;
1320Sstevel@tonic-gate 	}
1330Sstevel@tonic-gate 
1340Sstevel@tonic-gate 	/*
1350Sstevel@tonic-gate 	 * If there are no elements return an error
1360Sstevel@tonic-gate 	 */
1370Sstevel@tonic-gate 	if (cnt == 0)
1380Sstevel@tonic-gate 		return (DDI_PROP_END_OF_DATA);
1390Sstevel@tonic-gate 
1400Sstevel@tonic-gate 	/*
1410Sstevel@tonic-gate 	 * If we cannot skip through the data, we cannot decode it
1420Sstevel@tonic-gate 	 */
1430Sstevel@tonic-gate 	if (i == DDI_PROP_RESULT_ERROR)
1440Sstevel@tonic-gate 		return (DDI_PROP_CANNOT_DECODE);
1450Sstevel@tonic-gate 
1460Sstevel@tonic-gate 	/*
1470Sstevel@tonic-gate 	 * Reset the data pointer to the beginning of the encoded data
1480Sstevel@tonic-gate 	 */
1490Sstevel@tonic-gate 	di_prop_reset_pos(ph);
1500Sstevel@tonic-gate 
1510Sstevel@tonic-gate 	/*
1520Sstevel@tonic-gate 	 * Allocated memory to store the decoded value in.
1530Sstevel@tonic-gate 	 */
1540Sstevel@tonic-gate 	if ((intp = malloc(cnt * sizeof (int))) == NULL) {
1550Sstevel@tonic-gate 		return (DDI_PROP_CANNOT_DECODE);
1560Sstevel@tonic-gate 	}
1570Sstevel@tonic-gate 
1580Sstevel@tonic-gate 
1590Sstevel@tonic-gate 	/*
1600Sstevel@tonic-gate 	 * Decode each elemente and place it in the space we just allocated
1610Sstevel@tonic-gate 	 */
1620Sstevel@tonic-gate 	tmp = intp;
1630Sstevel@tonic-gate 	for (n = 0; n < cnt; n++, tmp++) {
1640Sstevel@tonic-gate 		i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp);
1650Sstevel@tonic-gate 		if (i < DDI_PROP_RESULT_OK) {
1660Sstevel@tonic-gate 			/*
1670Sstevel@tonic-gate 			 * Free the space we just allocated
1680Sstevel@tonic-gate 			 * and return an error.
1690Sstevel@tonic-gate 			 */
1700Sstevel@tonic-gate 			free(intp);
1710Sstevel@tonic-gate 			switch (i) {
1720Sstevel@tonic-gate 			case DDI_PROP_RESULT_EOF:
1730Sstevel@tonic-gate 				return (DDI_PROP_END_OF_DATA);
1740Sstevel@tonic-gate 
1750Sstevel@tonic-gate 			case DDI_PROP_RESULT_ERROR:
1760Sstevel@tonic-gate 				return (DDI_PROP_CANNOT_DECODE);
1770Sstevel@tonic-gate 			}
1780Sstevel@tonic-gate 		}
1790Sstevel@tonic-gate 	}
1800Sstevel@tonic-gate 
1810Sstevel@tonic-gate 	*nelements = cnt;
1820Sstevel@tonic-gate 	*(int **)data = intp;
1830Sstevel@tonic-gate 
1840Sstevel@tonic-gate 	return (DDI_PROP_SUCCESS);
1850Sstevel@tonic-gate }
1860Sstevel@tonic-gate 
1870Sstevel@tonic-gate /*
1880Sstevel@tonic-gate  * Decode an array of strings.
1890Sstevel@tonic-gate  */
1900Sstevel@tonic-gate static int
di_prop_fm_decode_strings(prop_handle_t * ph,void * data,uint_t * nelements)1910Sstevel@tonic-gate di_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements)
1920Sstevel@tonic-gate {
1930Sstevel@tonic-gate 	int		cnt = 0;
1940Sstevel@tonic-gate 	char		*strs;
1950Sstevel@tonic-gate 	char		*tmp;
1960Sstevel@tonic-gate 	int		size;
1970Sstevel@tonic-gate 	int		i;
1980Sstevel@tonic-gate 	int		n;
1990Sstevel@tonic-gate 	int		nbytes;
2000Sstevel@tonic-gate 
2010Sstevel@tonic-gate 	/*
2020Sstevel@tonic-gate 	 * Figure out how much memory we need for the sum total
2030Sstevel@tonic-gate 	 */
2040Sstevel@tonic-gate 	nbytes = 0;
2050Sstevel@tonic-gate 
2060Sstevel@tonic-gate 	for (;;) {
2070Sstevel@tonic-gate 		/*
2080Sstevel@tonic-gate 		 * Get the decoded size of the current encoded string.
2090Sstevel@tonic-gate 		 */
2100Sstevel@tonic-gate 		size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
2110Sstevel@tonic-gate 		if (size < 0)
2120Sstevel@tonic-gate 			break;
2130Sstevel@tonic-gate 
2140Sstevel@tonic-gate 		cnt++;
2150Sstevel@tonic-gate 		nbytes += size;
2160Sstevel@tonic-gate 	}
2170Sstevel@tonic-gate 
2180Sstevel@tonic-gate 	/*
2190Sstevel@tonic-gate 	 * If there are no elements return an error
2200Sstevel@tonic-gate 	 */
2210Sstevel@tonic-gate 	if (cnt == 0)
2220Sstevel@tonic-gate 		return (DDI_PROP_END_OF_DATA);
2230Sstevel@tonic-gate 
2240Sstevel@tonic-gate 	/*
2250Sstevel@tonic-gate 	 * If we cannot skip through the data, we cannot decode it
2260Sstevel@tonic-gate 	 */
2270Sstevel@tonic-gate 	if (size == DDI_PROP_RESULT_ERROR)
2280Sstevel@tonic-gate 		return (DDI_PROP_CANNOT_DECODE);
2290Sstevel@tonic-gate 
2300Sstevel@tonic-gate 	/*
2310Sstevel@tonic-gate 	 * Allocate memory in which to store the decoded strings.
2320Sstevel@tonic-gate 	 */
2330Sstevel@tonic-gate 	if ((strs = malloc(nbytes)) == NULL) {
2340Sstevel@tonic-gate 		return (DDI_PROP_CANNOT_DECODE);
2350Sstevel@tonic-gate 	}
2360Sstevel@tonic-gate 
2370Sstevel@tonic-gate 	/*
2380Sstevel@tonic-gate 	 * Finally, we can decode each string
2390Sstevel@tonic-gate 	 */
2400Sstevel@tonic-gate 	di_prop_reset_pos(ph);
2410Sstevel@tonic-gate 	tmp = strs;
2420Sstevel@tonic-gate 	for (n = 0; n < cnt; n++) {
2430Sstevel@tonic-gate 		i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp);
2440Sstevel@tonic-gate 		if (i < DDI_PROP_RESULT_OK) {
2450Sstevel@tonic-gate 			/*
2460Sstevel@tonic-gate 			 * Free the space we just allocated
2470Sstevel@tonic-gate 			 * and return an error
2480Sstevel@tonic-gate 			 */
2490Sstevel@tonic-gate 			free(strs);
2500Sstevel@tonic-gate 			switch (i) {
2510Sstevel@tonic-gate 			case DDI_PROP_RESULT_EOF:
2520Sstevel@tonic-gate 				return (DDI_PROP_END_OF_DATA);
2530Sstevel@tonic-gate 
2540Sstevel@tonic-gate 			case DDI_PROP_RESULT_ERROR:
2550Sstevel@tonic-gate 				return (DDI_PROP_CANNOT_DECODE);
2560Sstevel@tonic-gate 			}
2570Sstevel@tonic-gate 		}
2580Sstevel@tonic-gate 		tmp += strlen(tmp) + 1;
2590Sstevel@tonic-gate 	}
2600Sstevel@tonic-gate 
2610Sstevel@tonic-gate 	*(char **)data = strs;
2620Sstevel@tonic-gate 	*nelements = cnt;
2630Sstevel@tonic-gate 
2640Sstevel@tonic-gate 	return (DDI_PROP_SUCCESS);
2650Sstevel@tonic-gate }
2660Sstevel@tonic-gate 
2670Sstevel@tonic-gate /*
2680Sstevel@tonic-gate  * Decode an array of bytes.
2690Sstevel@tonic-gate  */
2700Sstevel@tonic-gate static int
di_prop_fm_decode_bytes(prop_handle_t * ph,void * data,uint_t * nelements)2710Sstevel@tonic-gate di_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements)
2720Sstevel@tonic-gate {
2730Sstevel@tonic-gate 	uchar_t		*tmp;
2740Sstevel@tonic-gate 	int		nbytes;
2750Sstevel@tonic-gate 	int		i;
2760Sstevel@tonic-gate 
2770Sstevel@tonic-gate 	/*
2780Sstevel@tonic-gate 	 * If there are no elements return an error
2790Sstevel@tonic-gate 	 */
2800Sstevel@tonic-gate 	if (ph->ph_size == 0)
2810Sstevel@tonic-gate 		return (DDI_PROP_END_OF_DATA);
2820Sstevel@tonic-gate 
2830Sstevel@tonic-gate 	/*
2840Sstevel@tonic-gate 	 * Get the size of the encoded array of bytes.
2850Sstevel@tonic-gate 	 */
2860Sstevel@tonic-gate 	nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE,
2870Sstevel@tonic-gate 		data, ph->ph_size);
2880Sstevel@tonic-gate 	if (nbytes < DDI_PROP_RESULT_OK) {
2890Sstevel@tonic-gate 		switch (nbytes) {
2900Sstevel@tonic-gate 		case DDI_PROP_RESULT_EOF:
2910Sstevel@tonic-gate 			return (DDI_PROP_END_OF_DATA);
2920Sstevel@tonic-gate 
2930Sstevel@tonic-gate 		case DDI_PROP_RESULT_ERROR:
2940Sstevel@tonic-gate 			return (DDI_PROP_CANNOT_DECODE);
2950Sstevel@tonic-gate 		}
2960Sstevel@tonic-gate 	}
2970Sstevel@tonic-gate 
2980Sstevel@tonic-gate 	/*
2990Sstevel@tonic-gate 	 * Allocated memory to store the decoded value in.
3000Sstevel@tonic-gate 	 */
3010Sstevel@tonic-gate 	if ((tmp = malloc(nbytes)) == NULL) {
3020Sstevel@tonic-gate 		return (DDI_PROP_CANNOT_DECODE);
3030Sstevel@tonic-gate 	}
3040Sstevel@tonic-gate 
3050Sstevel@tonic-gate 	/*
3060Sstevel@tonic-gate 	 * Decode each element and place it in the space we just allocated
3070Sstevel@tonic-gate 	 */
3080Sstevel@tonic-gate 	i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes);
3090Sstevel@tonic-gate 	if (i < DDI_PROP_RESULT_OK) {
3100Sstevel@tonic-gate 		/*
3110Sstevel@tonic-gate 		 * Free the space we just allocated
3120Sstevel@tonic-gate 		 * and return an error
3130Sstevel@tonic-gate 		 */
3140Sstevel@tonic-gate 		free(tmp);
3150Sstevel@tonic-gate 		switch (i) {
3160Sstevel@tonic-gate 		case DDI_PROP_RESULT_EOF:
3170Sstevel@tonic-gate 			return (DDI_PROP_END_OF_DATA);
3180Sstevel@tonic-gate 
3190Sstevel@tonic-gate 		case DDI_PROP_RESULT_ERROR:
3200Sstevel@tonic-gate 			return (DDI_PROP_CANNOT_DECODE);
3210Sstevel@tonic-gate 		}
3220Sstevel@tonic-gate 	}
3230Sstevel@tonic-gate 
3240Sstevel@tonic-gate 	*(uchar_t **)data = tmp;
3250Sstevel@tonic-gate 	*nelements = nbytes;
3260Sstevel@tonic-gate 
3270Sstevel@tonic-gate 	return (DDI_PROP_SUCCESS);
3280Sstevel@tonic-gate }
3290Sstevel@tonic-gate 
3300Sstevel@tonic-gate /*
3310Sstevel@tonic-gate  * OBP 1275 integer, string and byte operators.
3320Sstevel@tonic-gate  *
3330Sstevel@tonic-gate  * DDI_PROP_CMD_DECODE:
3340Sstevel@tonic-gate  *
3350Sstevel@tonic-gate  *	DDI_PROP_RESULT_ERROR:		cannot decode the data
3360Sstevel@tonic-gate  *	DDI_PROP_RESULT_EOF:		end of data
3370Sstevel@tonic-gate  *	DDI_PROP_OK:			data was decoded
3380Sstevel@tonic-gate  *
3390Sstevel@tonic-gate  * DDI_PROP_CMD_ENCODE:
3400Sstevel@tonic-gate  *
3410Sstevel@tonic-gate  *	DDI_PROP_RESULT_ERROR:		cannot encode the data
3420Sstevel@tonic-gate  *	DDI_PROP_RESULT_EOF:		end of data
3430Sstevel@tonic-gate  *	DDI_PROP_OK:			data was encoded
3440Sstevel@tonic-gate  *
3450Sstevel@tonic-gate  * DDI_PROP_CMD_SKIP:
3460Sstevel@tonic-gate  *
3470Sstevel@tonic-gate  *	DDI_PROP_RESULT_ERROR:		cannot skip the data
3480Sstevel@tonic-gate  *	DDI_PROP_RESULT_EOF:		end of data
3490Sstevel@tonic-gate  *	DDI_PROP_OK:			data was skipped
3500Sstevel@tonic-gate  *
3510Sstevel@tonic-gate  * DDI_PROP_CMD_GET_ESIZE:
3520Sstevel@tonic-gate  *
3530Sstevel@tonic-gate  *	DDI_PROP_RESULT_ERROR:		cannot get encoded size
3540Sstevel@tonic-gate  *	DDI_PROP_RESULT_EOF:		end of data
3550Sstevel@tonic-gate  *	> 0:				the encoded size
3560Sstevel@tonic-gate  *
3570Sstevel@tonic-gate  * DDI_PROP_CMD_GET_DSIZE:
3580Sstevel@tonic-gate  *
3590Sstevel@tonic-gate  *	DDI_PROP_RESULT_ERROR:		cannot get decoded size
3600Sstevel@tonic-gate  *	DDI_PROP_RESULT_EOF:		end of data
3610Sstevel@tonic-gate  *	> 0:				the decoded size
3620Sstevel@tonic-gate  */
3630Sstevel@tonic-gate 
3640Sstevel@tonic-gate /*
3650Sstevel@tonic-gate  * OBP 1275 integer operator
3660Sstevel@tonic-gate  *
3670Sstevel@tonic-gate  * OBP properties are a byte stream of data, so integers may not be
3680Sstevel@tonic-gate  * properly aligned. Therefore we need to copy them one byte at a time.
3690Sstevel@tonic-gate  */
3700Sstevel@tonic-gate int
di_prop_1275_int(prop_handle_t * ph,uint_t cmd,int * data)3710Sstevel@tonic-gate di_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data)
3720Sstevel@tonic-gate {
3730Sstevel@tonic-gate 	int	i;
3740Sstevel@tonic-gate 
3750Sstevel@tonic-gate 	switch (cmd) {
3760Sstevel@tonic-gate 	case DDI_PROP_CMD_DECODE:
3770Sstevel@tonic-gate 		/*
3780Sstevel@tonic-gate 		 * Check that there is encoded data
3790Sstevel@tonic-gate 		 */
3800Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
3810Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
3820Sstevel@tonic-gate 		if (ph->ph_flags & PH_FROM_PROM) {
3830Sstevel@tonic-gate 			i = ph->ph_size < PROP_1275_INT_SIZE ?
3840Sstevel@tonic-gate 			    ph->ph_size : PROP_1275_INT_SIZE;
3850Sstevel@tonic-gate 			if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
3860Sstevel@tonic-gate 			    ph->ph_size - i))
3870Sstevel@tonic-gate 				return (DDI_PROP_RESULT_ERROR);
3880Sstevel@tonic-gate 		} else if (ph->ph_size < sizeof (int) ||
3890Sstevel@tonic-gate 		    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
3900Sstevel@tonic-gate 		    ph->ph_size - sizeof (int)))) {
3910Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
3920Sstevel@tonic-gate 		}
3930Sstevel@tonic-gate 
3940Sstevel@tonic-gate 		/*
3950Sstevel@tonic-gate 		 * Copy the integer, using the implementation-specific
3960Sstevel@tonic-gate 		 * copy function if the property is coming from the PROM.
3970Sstevel@tonic-gate 		 */
3980Sstevel@tonic-gate 		if (ph->ph_flags & PH_FROM_PROM) {
3990Sstevel@tonic-gate 			*data = impl_di_prop_int_from_prom(
4000Sstevel@tonic-gate 			    (uchar_t *)ph->ph_cur_pos,
4010Sstevel@tonic-gate 			    (ph->ph_size < PROP_1275_INT_SIZE) ?
4020Sstevel@tonic-gate 			    ph->ph_size : PROP_1275_INT_SIZE);
4030Sstevel@tonic-gate 		} else {
4040Sstevel@tonic-gate 			bcopy(ph->ph_cur_pos, (caddr_t)data, sizeof (int));
4050Sstevel@tonic-gate 		}
4060Sstevel@tonic-gate 
4070Sstevel@tonic-gate 		/*
4080Sstevel@tonic-gate 		 * Move the current location to the start of the next
4090Sstevel@tonic-gate 		 * bit of undecoded data.
4100Sstevel@tonic-gate 		 */
4110Sstevel@tonic-gate 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
4120Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
4130Sstevel@tonic-gate 
4140Sstevel@tonic-gate 	case DDI_PROP_CMD_ENCODE:
4150Sstevel@tonic-gate 		/*
4160Sstevel@tonic-gate 		 * Check that there is room to encoded the data
4170Sstevel@tonic-gate 		 */
4180Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
4190Sstevel@tonic-gate 		    ph->ph_size < PROP_1275_INT_SIZE ||
4200Sstevel@tonic-gate 		    ((int *)ph->ph_cur_pos > ((int *)ph->ph_data +
4210Sstevel@tonic-gate 		    ph->ph_size - sizeof (int))))
4220Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
4230Sstevel@tonic-gate 
4240Sstevel@tonic-gate 		/*
4250Sstevel@tonic-gate 		 * Encode the integer into the byte stream one byte at a
4260Sstevel@tonic-gate 		 * time.
4270Sstevel@tonic-gate 		 */
4280Sstevel@tonic-gate 		bcopy((caddr_t)data, ph->ph_cur_pos, sizeof (int));
4290Sstevel@tonic-gate 
4300Sstevel@tonic-gate 		/*
4310Sstevel@tonic-gate 		 * Move the current location to the start of the next bit of
4320Sstevel@tonic-gate 		 * space where we can store encoded data.
4330Sstevel@tonic-gate 		 */
4340Sstevel@tonic-gate 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
4350Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
4360Sstevel@tonic-gate 
4370Sstevel@tonic-gate 	case DDI_PROP_CMD_SKIP:
4380Sstevel@tonic-gate 		/*
4390Sstevel@tonic-gate 		 * Check that there is encoded data
4400Sstevel@tonic-gate 		 */
4410Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
4420Sstevel@tonic-gate 		    ph->ph_size < PROP_1275_INT_SIZE)
4430Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
4440Sstevel@tonic-gate 
4450Sstevel@tonic-gate 
4460Sstevel@tonic-gate 		if ((caddr_t)ph->ph_cur_pos ==
4470Sstevel@tonic-gate 		    (caddr_t)ph->ph_data + ph->ph_size) {
4480Sstevel@tonic-gate 			return (DDI_PROP_RESULT_EOF);
4490Sstevel@tonic-gate 		} else if ((caddr_t)ph->ph_cur_pos >
4500Sstevel@tonic-gate 		    (caddr_t)ph->ph_data + ph->ph_size) {
4510Sstevel@tonic-gate 			return (DDI_PROP_RESULT_EOF);
4520Sstevel@tonic-gate 		}
4530Sstevel@tonic-gate 
4540Sstevel@tonic-gate 		/*
4550Sstevel@tonic-gate 		 * Move the current location to the start of the next bit of
4560Sstevel@tonic-gate 		 * undecoded data.
4570Sstevel@tonic-gate 		 */
4580Sstevel@tonic-gate 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE;
4590Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
4600Sstevel@tonic-gate 
4610Sstevel@tonic-gate 	case DDI_PROP_CMD_GET_ESIZE:
4620Sstevel@tonic-gate 		/*
4630Sstevel@tonic-gate 		 * Return the size of an encoded integer on OBP
4640Sstevel@tonic-gate 		 */
4650Sstevel@tonic-gate 		return (PROP_1275_INT_SIZE);
4660Sstevel@tonic-gate 
4670Sstevel@tonic-gate 	case DDI_PROP_CMD_GET_DSIZE:
4680Sstevel@tonic-gate 		/*
4690Sstevel@tonic-gate 		 * Return the size of a decoded integer on the system.
4700Sstevel@tonic-gate 		 */
4710Sstevel@tonic-gate 		return (sizeof (int));
4720Sstevel@tonic-gate 	}
4730Sstevel@tonic-gate 
4740Sstevel@tonic-gate 	/*NOTREACHED*/
4750Sstevel@tonic-gate 	return (0);	/* keep gcc happy */
4760Sstevel@tonic-gate }
4770Sstevel@tonic-gate 
4780Sstevel@tonic-gate /*
4790Sstevel@tonic-gate  * 64 bit integer operator
4800Sstevel@tonic-gate  *
4810Sstevel@tonic-gate  * This is an extension, defined by Sun, to the 1275 integer
4820Sstevel@tonic-gate  * operator.  This routine handles the encoding/decoding of
4830Sstevel@tonic-gate  * 64 bit integer properties.
4840Sstevel@tonic-gate  */
4850Sstevel@tonic-gate int
di_prop_int64_op(prop_handle_t * ph,uint_t cmd,int64_t * data)4860Sstevel@tonic-gate di_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data)
4870Sstevel@tonic-gate {
4880Sstevel@tonic-gate 	switch (cmd) {
4890Sstevel@tonic-gate 	case DDI_PROP_CMD_DECODE:
4900Sstevel@tonic-gate 		/*
4910Sstevel@tonic-gate 		 * Check that there is encoded data
4920Sstevel@tonic-gate 		 */
4930Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0)
4940Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
4950Sstevel@tonic-gate 		if (ph->ph_flags & PH_FROM_PROM) {
4960Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
4970Sstevel@tonic-gate 		} else if (ph->ph_size < sizeof (int64_t) ||
4980Sstevel@tonic-gate 		    ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data +
4990Sstevel@tonic-gate 		    ph->ph_size - sizeof (int64_t)))) {
5000Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
5010Sstevel@tonic-gate 		}
5020Sstevel@tonic-gate 
5030Sstevel@tonic-gate 		/*
5040Sstevel@tonic-gate 		 * Copy the integer, using the implementation-specific
5050Sstevel@tonic-gate 		 * copy function if the property is coming from the PROM.
5060Sstevel@tonic-gate 		 */
5070Sstevel@tonic-gate 		bcopy(ph->ph_cur_pos, (caddr_t)data, sizeof (int64_t));
5080Sstevel@tonic-gate 
5090Sstevel@tonic-gate 		/*
5100Sstevel@tonic-gate 		 * Move the current location to the start of the next
5110Sstevel@tonic-gate 		 * bit of undecoded data.
5120Sstevel@tonic-gate 		 */
5130Sstevel@tonic-gate 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
5140Sstevel@tonic-gate 		    sizeof (int64_t);
5150Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
5160Sstevel@tonic-gate 
5170Sstevel@tonic-gate 	case DDI_PROP_CMD_ENCODE:
5180Sstevel@tonic-gate 		/*
5190Sstevel@tonic-gate 		 * Check that there is room to encoded the data
5200Sstevel@tonic-gate 		 */
5210Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
5220Sstevel@tonic-gate 		    ph->ph_size < sizeof (int64_t) ||
5230Sstevel@tonic-gate 		    ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data +
5240Sstevel@tonic-gate 		    ph->ph_size - sizeof (int64_t))))
5250Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
5260Sstevel@tonic-gate 
5270Sstevel@tonic-gate 		/*
5280Sstevel@tonic-gate 		 * Encode the integer into the byte stream one byte at a
5290Sstevel@tonic-gate 		 * time.
5300Sstevel@tonic-gate 		 */
5310Sstevel@tonic-gate 		bcopy((caddr_t)data, ph->ph_cur_pos, sizeof (int64_t));
5320Sstevel@tonic-gate 
5330Sstevel@tonic-gate 		/*
5340Sstevel@tonic-gate 		 * Move the current location to the start of the next bit of
5350Sstevel@tonic-gate 		 * space where we can store encoded data.
5360Sstevel@tonic-gate 		 */
5370Sstevel@tonic-gate 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
5380Sstevel@tonic-gate 		    sizeof (int64_t);
5390Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
5400Sstevel@tonic-gate 
5410Sstevel@tonic-gate 	case DDI_PROP_CMD_SKIP:
5420Sstevel@tonic-gate 		/*
5430Sstevel@tonic-gate 		 * Check that there is encoded data
5440Sstevel@tonic-gate 		 */
5450Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
5460Sstevel@tonic-gate 		    ph->ph_size < sizeof (int64_t))
5470Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
5480Sstevel@tonic-gate 
5490Sstevel@tonic-gate 
5500Sstevel@tonic-gate 		if ((caddr_t)ph->ph_cur_pos ==
5510Sstevel@tonic-gate 		    (caddr_t)ph->ph_data + ph->ph_size) {
5520Sstevel@tonic-gate 			return (DDI_PROP_RESULT_EOF);
5530Sstevel@tonic-gate 		} else if ((caddr_t)ph->ph_cur_pos >
5540Sstevel@tonic-gate 		    (caddr_t)ph->ph_data + ph->ph_size) {
5550Sstevel@tonic-gate 			return (DDI_PROP_RESULT_EOF);
5560Sstevel@tonic-gate 		}
5570Sstevel@tonic-gate 
5580Sstevel@tonic-gate 		/*
5590Sstevel@tonic-gate 		 * Move the current location to the start of the next bit of
5600Sstevel@tonic-gate 		 * undecoded data.
5610Sstevel@tonic-gate 		 */
5620Sstevel@tonic-gate 		ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
5630Sstevel@tonic-gate 		    sizeof (int64_t);
5640Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
5650Sstevel@tonic-gate 
5660Sstevel@tonic-gate 	case DDI_PROP_CMD_GET_ESIZE:
5670Sstevel@tonic-gate 		/*
5680Sstevel@tonic-gate 		 * Return the size of an encoded integer on OBP
5690Sstevel@tonic-gate 		 */
5700Sstevel@tonic-gate 		return (sizeof (int64_t));
5710Sstevel@tonic-gate 
5720Sstevel@tonic-gate 	case DDI_PROP_CMD_GET_DSIZE:
5730Sstevel@tonic-gate 		/*
5740Sstevel@tonic-gate 		 * Return the size of a decoded integer on the system.
5750Sstevel@tonic-gate 		 */
5760Sstevel@tonic-gate 		return (sizeof (int64_t));
5770Sstevel@tonic-gate 	}
5780Sstevel@tonic-gate 
5790Sstevel@tonic-gate 	/*NOTREACHED*/
5800Sstevel@tonic-gate 	return (0);	/* keep gcc happy */
5810Sstevel@tonic-gate }
5820Sstevel@tonic-gate 
5830Sstevel@tonic-gate /*
5840Sstevel@tonic-gate  * OBP 1275 string operator.
5850Sstevel@tonic-gate  *
5860Sstevel@tonic-gate  * OBP strings are NULL terminated.
5870Sstevel@tonic-gate  */
5880Sstevel@tonic-gate int
di_prop_1275_string(prop_handle_t * ph,uint_t cmd,char * data)5890Sstevel@tonic-gate di_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data)
5900Sstevel@tonic-gate {
5910Sstevel@tonic-gate 	int	n;
5920Sstevel@tonic-gate 	char	*p;
5930Sstevel@tonic-gate 	char	*end;
5940Sstevel@tonic-gate 
5950Sstevel@tonic-gate 	switch (cmd) {
5960Sstevel@tonic-gate 	case DDI_PROP_CMD_DECODE:
5970Sstevel@tonic-gate 		/*
5980Sstevel@tonic-gate 		 * Check that there is encoded data
5990Sstevel@tonic-gate 		 */
6000Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
6010Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
6020Sstevel@tonic-gate 		}
6030Sstevel@tonic-gate 
6040Sstevel@tonic-gate 		n = strlen((char *)ph->ph_cur_pos) + 1;
6050Sstevel@tonic-gate 		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
6060Sstevel@tonic-gate 		    ph->ph_size - n)) {
6070Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
6080Sstevel@tonic-gate 		}
6090Sstevel@tonic-gate 
6100Sstevel@tonic-gate 		/*
6110Sstevel@tonic-gate 		 * Copy the NULL terminated string
6120Sstevel@tonic-gate 		 */
6130Sstevel@tonic-gate 		bcopy((char *)ph->ph_cur_pos, data, n);
6140Sstevel@tonic-gate 
6150Sstevel@tonic-gate 		/*
6160Sstevel@tonic-gate 		 * Move the current location to the start of the next bit of
6170Sstevel@tonic-gate 		 * undecoded data.
6180Sstevel@tonic-gate 		 */
6190Sstevel@tonic-gate 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + n;
6200Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
6210Sstevel@tonic-gate 
6220Sstevel@tonic-gate 	case DDI_PROP_CMD_ENCODE:
6230Sstevel@tonic-gate 		/*
6240Sstevel@tonic-gate 		 * Check that there is room to encoded the data
6250Sstevel@tonic-gate 		 */
6260Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
6270Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
6280Sstevel@tonic-gate 		}
6290Sstevel@tonic-gate 
6300Sstevel@tonic-gate 		n = strlen(data) + 1;
6310Sstevel@tonic-gate 		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
6320Sstevel@tonic-gate 		    ph->ph_size - n)) {
6330Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
6340Sstevel@tonic-gate 		}
6350Sstevel@tonic-gate 
6360Sstevel@tonic-gate 		/*
6370Sstevel@tonic-gate 		 * Copy the NULL terminated string
6380Sstevel@tonic-gate 		 */
6390Sstevel@tonic-gate 		bcopy(data, (char *)ph->ph_cur_pos, n);
6400Sstevel@tonic-gate 
6410Sstevel@tonic-gate 		/*
6420Sstevel@tonic-gate 		 * Move the current location to the start of the next bit of
6430Sstevel@tonic-gate 		 * space where we can store encoded data.
6440Sstevel@tonic-gate 		 */
6450Sstevel@tonic-gate 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + n;
6460Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
6470Sstevel@tonic-gate 
6480Sstevel@tonic-gate 	case DDI_PROP_CMD_SKIP:
6490Sstevel@tonic-gate 		/*
6500Sstevel@tonic-gate 		 * Check that there is encoded data
6510Sstevel@tonic-gate 		 */
6520Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0) {
6530Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
6540Sstevel@tonic-gate 		}
6550Sstevel@tonic-gate 
6560Sstevel@tonic-gate 		/*
6570Sstevel@tonic-gate 		 * Return the string length plus one for the NULL
6580Sstevel@tonic-gate 		 * We know the size of the property, we need to
6590Sstevel@tonic-gate 		 * ensure that the string is properly formatted,
6600Sstevel@tonic-gate 		 * since we may be looking up random OBP data.
6610Sstevel@tonic-gate 		 */
6620Sstevel@tonic-gate 		p = (char *)ph->ph_cur_pos;
6630Sstevel@tonic-gate 		end = (char *)ph->ph_data + ph->ph_size;
6640Sstevel@tonic-gate 
6650Sstevel@tonic-gate 		if (p == end) {
6660Sstevel@tonic-gate 			return (DDI_PROP_RESULT_EOF);
6670Sstevel@tonic-gate 		}
6680Sstevel@tonic-gate 
6690Sstevel@tonic-gate 		/*
6700Sstevel@tonic-gate 		 * Make sure each char is printable
6710Sstevel@tonic-gate 		 */
6720Sstevel@tonic-gate 		for (n = 0; p < end && isascii(*p) && !iscntrl(*p); n++, p++)
6730Sstevel@tonic-gate 			;
6740Sstevel@tonic-gate 
6750Sstevel@tonic-gate 		/* Check termination and non-zero length */
6760Sstevel@tonic-gate 		if ((*p == 0) && (n != 0)) {
6770Sstevel@tonic-gate 			ph->ph_cur_pos = p + 1;
6780Sstevel@tonic-gate 			return (DDI_PROP_RESULT_OK);
6790Sstevel@tonic-gate 		}
6800Sstevel@tonic-gate 
6810Sstevel@tonic-gate 		return (DDI_PROP_RESULT_ERROR);
6820Sstevel@tonic-gate 
6830Sstevel@tonic-gate 	case DDI_PROP_CMD_GET_ESIZE:
6840Sstevel@tonic-gate 		/*
6850Sstevel@tonic-gate 		 * Return the size of the encoded string on OBP.
6860Sstevel@tonic-gate 		 */
6870Sstevel@tonic-gate 		return (strlen(data) + 1);
6880Sstevel@tonic-gate 
6890Sstevel@tonic-gate 	case DDI_PROP_CMD_GET_DSIZE:
6900Sstevel@tonic-gate 		/*
6910Sstevel@tonic-gate 		 * Return the string length plus one for the NULL
6920Sstevel@tonic-gate 		 * We know the size of the property, we need to
6930Sstevel@tonic-gate 		 * ensure that the string is properly formatted,
6940Sstevel@tonic-gate 		 * since we may be looking up random OBP data.
6950Sstevel@tonic-gate 		 */
6960Sstevel@tonic-gate 		p = (char *)ph->ph_cur_pos;
6970Sstevel@tonic-gate 		end = (char *)ph->ph_data + ph->ph_size;
6980Sstevel@tonic-gate 		for (n = 0; p < end; n++) {
6990Sstevel@tonic-gate 			if (*p++ == '\0') {
7000Sstevel@tonic-gate 				ph->ph_cur_pos = p;
7010Sstevel@tonic-gate 				return (n+1);
7020Sstevel@tonic-gate 			}
7030Sstevel@tonic-gate 		}
7040Sstevel@tonic-gate 
7050Sstevel@tonic-gate 		/*
7060Sstevel@tonic-gate 		 * Add check here to separate EOF and ERROR.
7070Sstevel@tonic-gate 		 */
7080Sstevel@tonic-gate 		if (p == end)
7090Sstevel@tonic-gate 			return (DDI_PROP_RESULT_EOF);
7100Sstevel@tonic-gate 
7110Sstevel@tonic-gate 		return (DDI_PROP_RESULT_ERROR);
7120Sstevel@tonic-gate 
7130Sstevel@tonic-gate 	}
7140Sstevel@tonic-gate 
7150Sstevel@tonic-gate 	/*NOTREACHED*/
7160Sstevel@tonic-gate 	return (0);	/* keep gcc happy */
7170Sstevel@tonic-gate }
7180Sstevel@tonic-gate 
7190Sstevel@tonic-gate /*
7200Sstevel@tonic-gate  * OBP 1275 byte operator
7210Sstevel@tonic-gate  *
7220Sstevel@tonic-gate  * Caller must specify the number of bytes to get. OBP encodes bytes
7230Sstevel@tonic-gate  * as a byte so there is a 1-to-1 translation.
7240Sstevel@tonic-gate  */
7250Sstevel@tonic-gate int
di_prop_1275_bytes(prop_handle_t * ph,uint_t cmd,uchar_t * data,uint_t nelements)7260Sstevel@tonic-gate di_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data,
7270Sstevel@tonic-gate     uint_t nelements)
7280Sstevel@tonic-gate {
7290Sstevel@tonic-gate 	switch (cmd) {
7300Sstevel@tonic-gate 	case DDI_PROP_CMD_DECODE:
7310Sstevel@tonic-gate 		/*
7320Sstevel@tonic-gate 		 * Check that there is encoded data
7330Sstevel@tonic-gate 		 */
7340Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
7350Sstevel@tonic-gate 		    ph->ph_size < nelements ||
7360Sstevel@tonic-gate 		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
7370Sstevel@tonic-gate 		    ph->ph_size - nelements)))
7380Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
7390Sstevel@tonic-gate 
7400Sstevel@tonic-gate 		/*
7410Sstevel@tonic-gate 		 * Copy out the bytes
7420Sstevel@tonic-gate 		 */
7430Sstevel@tonic-gate 		bcopy((char *)ph->ph_cur_pos, (char *)data, nelements);
7440Sstevel@tonic-gate 
7450Sstevel@tonic-gate 		/*
7460Sstevel@tonic-gate 		 * Move the current location
7470Sstevel@tonic-gate 		 */
7480Sstevel@tonic-gate 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
7490Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
7500Sstevel@tonic-gate 
7510Sstevel@tonic-gate 	case DDI_PROP_CMD_ENCODE:
7520Sstevel@tonic-gate 		/*
7530Sstevel@tonic-gate 		 * Check that there is room to encode the data
7540Sstevel@tonic-gate 		 */
7550Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
7560Sstevel@tonic-gate 		    ph->ph_size < nelements ||
7570Sstevel@tonic-gate 		    ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
7580Sstevel@tonic-gate 		    ph->ph_size - nelements)))
7590Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
7600Sstevel@tonic-gate 
7610Sstevel@tonic-gate 		/*
7620Sstevel@tonic-gate 		 * Copy in the bytes
7630Sstevel@tonic-gate 		 */
7640Sstevel@tonic-gate 		bcopy((char *)data, (char *)ph->ph_cur_pos, nelements);
7650Sstevel@tonic-gate 
7660Sstevel@tonic-gate 		/*
7670Sstevel@tonic-gate 		 * Move the current location to the start of the next bit of
7680Sstevel@tonic-gate 		 * space where we can store encoded data.
7690Sstevel@tonic-gate 		 */
7700Sstevel@tonic-gate 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
7710Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
7720Sstevel@tonic-gate 
7730Sstevel@tonic-gate 	case DDI_PROP_CMD_SKIP:
7740Sstevel@tonic-gate 		/*
7750Sstevel@tonic-gate 		 * Check that there is encoded data
7760Sstevel@tonic-gate 		 */
7770Sstevel@tonic-gate 		if (ph->ph_cur_pos == NULL || ph->ph_size == 0 ||
7780Sstevel@tonic-gate 		    ph->ph_size < nelements)
7790Sstevel@tonic-gate 			return (DDI_PROP_RESULT_ERROR);
7800Sstevel@tonic-gate 
7810Sstevel@tonic-gate 		if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data +
7820Sstevel@tonic-gate 		    ph->ph_size - nelements))
7830Sstevel@tonic-gate 			return (DDI_PROP_RESULT_EOF);
7840Sstevel@tonic-gate 
7850Sstevel@tonic-gate 		/*
7860Sstevel@tonic-gate 		 * Move the current location
7870Sstevel@tonic-gate 		 */
7880Sstevel@tonic-gate 		ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements;
7890Sstevel@tonic-gate 		return (DDI_PROP_RESULT_OK);
7900Sstevel@tonic-gate 
7910Sstevel@tonic-gate 	case DDI_PROP_CMD_GET_ESIZE:
7920Sstevel@tonic-gate 		/*
7930Sstevel@tonic-gate 		 * The size in bytes of the encoded size is the
7940Sstevel@tonic-gate 		 * same as the decoded size provided by the caller.
7950Sstevel@tonic-gate 		 */
7960Sstevel@tonic-gate 		return (nelements);
7970Sstevel@tonic-gate 
7980Sstevel@tonic-gate 	case DDI_PROP_CMD_GET_DSIZE:
7990Sstevel@tonic-gate 		/*
8000Sstevel@tonic-gate 		 * Just return the number of bytes specified by the caller.
8010Sstevel@tonic-gate 		 */
8020Sstevel@tonic-gate 		return (nelements);
8030Sstevel@tonic-gate 
8040Sstevel@tonic-gate 	}
8050Sstevel@tonic-gate 
8060Sstevel@tonic-gate 	/*NOTREACHED*/
8070Sstevel@tonic-gate 	return (0);	/* keep gcc happy */
8080Sstevel@tonic-gate }
8090Sstevel@tonic-gate 
8100Sstevel@tonic-gate /*
8110Sstevel@tonic-gate  * Used for properties that come from the OBP, hardware configuration files,
8120Sstevel@tonic-gate  * or that are created by calls to ddi_prop_update(9F).
8130Sstevel@tonic-gate  */
8140Sstevel@tonic-gate static struct prop_handle_ops prop_1275_ops = {
8150Sstevel@tonic-gate 	di_prop_1275_int,
8160Sstevel@tonic-gate 	di_prop_1275_string,
8170Sstevel@tonic-gate 	di_prop_1275_bytes,
8180Sstevel@tonic-gate 	di_prop_int64_op
8190Sstevel@tonic-gate };
8200Sstevel@tonic-gate 
8210Sstevel@tonic-gate /*
8220Sstevel@tonic-gate  * Now the real thing:
8230Sstevel@tonic-gate  * Extract type-specific values of an property
8240Sstevel@tonic-gate  */
8250Sstevel@tonic-gate int
di_prop_decode_common(void * data,int size,int prop_type,int prom)8260Sstevel@tonic-gate di_prop_decode_common(void *data, int size, int prop_type, int prom)
8270Sstevel@tonic-gate {
8280Sstevel@tonic-gate 	int n;
8290Sstevel@tonic-gate 	int nelements;
8300Sstevel@tonic-gate 	char *cp, *end;
8310Sstevel@tonic-gate 	prop_handle_t ph;
8320Sstevel@tonic-gate 	int (*prop_decoder)(prop_handle_t *, void *, uint_t *);
8330Sstevel@tonic-gate 
8340Sstevel@tonic-gate 	/*
8350Sstevel@tonic-gate 	 * If the encoded data came from software, no decoding needed
8360Sstevel@tonic-gate 	 */
8370Sstevel@tonic-gate 	if (!prom) {
8380Sstevel@tonic-gate 		switch (prop_type) {
8390Sstevel@tonic-gate 		case DI_PROP_TYPE_INT:
8400Sstevel@tonic-gate 			if (size % sizeof (int))
8410Sstevel@tonic-gate 				nelements = -1;
8420Sstevel@tonic-gate 			else
8430Sstevel@tonic-gate 				nelements = size / sizeof (int);
8440Sstevel@tonic-gate 			break;
8450Sstevel@tonic-gate 
8460Sstevel@tonic-gate 		case DI_PROP_TYPE_INT64:
8470Sstevel@tonic-gate 			if (size % sizeof (int64_t))
8480Sstevel@tonic-gate 				nelements = -1;
8490Sstevel@tonic-gate 			else
8500Sstevel@tonic-gate 				nelements = size / sizeof (int64_t);
8510Sstevel@tonic-gate 			break;
8520Sstevel@tonic-gate 
8530Sstevel@tonic-gate 		case DI_PROP_TYPE_STRING:
8540Sstevel@tonic-gate 			nelements = 0;
8550Sstevel@tonic-gate 			cp = *(char **)data;
8560Sstevel@tonic-gate 			end = cp + size;
8570Sstevel@tonic-gate 			/*
8580Sstevel@tonic-gate 			 * Don't trust the data passed in by the caller.
8590Sstevel@tonic-gate 			 * Check every char to make sure it is indeed a
8600Sstevel@tonic-gate 			 * string property.
8610Sstevel@tonic-gate 			 */
8620Sstevel@tonic-gate 			while (cp < end) {
8630Sstevel@tonic-gate 				/* skip to next non-printable char */
8640Sstevel@tonic-gate 				for (n = 0; cp < end &&
8650Sstevel@tonic-gate 				    isascii(*cp) && !iscntrl(*cp); n++, cp++)
8660Sstevel@tonic-gate 					;
8670Sstevel@tonic-gate 
8680Sstevel@tonic-gate 				/*
8690Sstevel@tonic-gate 				 * Fail if reached end (i.e. last char != 0),
8700Sstevel@tonic-gate 				 * or has a non-printable char. A zero length
8710Sstevel@tonic-gate 				 * string is acceptable.
8720Sstevel@tonic-gate 				 */
8730Sstevel@tonic-gate 				if (cp == end || *cp != 0) {
8740Sstevel@tonic-gate 					nelements = -1;
8750Sstevel@tonic-gate 					break;
8760Sstevel@tonic-gate 				}
8770Sstevel@tonic-gate 				/*
8780Sstevel@tonic-gate 				 * Increment # strings and keep going
8790Sstevel@tonic-gate 				 */
8800Sstevel@tonic-gate 				nelements++;
8810Sstevel@tonic-gate 				cp++;
8820Sstevel@tonic-gate 			}
8830Sstevel@tonic-gate 
8840Sstevel@tonic-gate 			break;
8850Sstevel@tonic-gate 
8860Sstevel@tonic-gate 		case DI_PROP_TYPE_BYTE:
8870Sstevel@tonic-gate 			nelements = size;
8880Sstevel@tonic-gate 		}
8890Sstevel@tonic-gate 
8900Sstevel@tonic-gate 		return (nelements);
8910Sstevel@tonic-gate 	}
8920Sstevel@tonic-gate 
8930Sstevel@tonic-gate 	/*
8940Sstevel@tonic-gate 	 * Get the encoded data
8950Sstevel@tonic-gate 	 */
8960Sstevel@tonic-gate 	bzero((caddr_t)&ph, sizeof (prop_handle_t));
8970Sstevel@tonic-gate 	ph.ph_data = *(uchar_t **)data;
8980Sstevel@tonic-gate 	ph.ph_size = size;
8990Sstevel@tonic-gate 
9000Sstevel@tonic-gate 	/*
9010Sstevel@tonic-gate 	 * The data came from prom, use the 1275 OBP decode/encode routines.
9020Sstevel@tonic-gate 	 */
9030Sstevel@tonic-gate 	ph.ph_cur_pos = ph.ph_data;
9040Sstevel@tonic-gate 	ph.ph_save_pos = ph.ph_data;
9050Sstevel@tonic-gate 	ph.ph_ops = &prop_1275_ops;
9060Sstevel@tonic-gate 	ph.ph_flags = PH_FROM_PROM;
9070Sstevel@tonic-gate 
9080Sstevel@tonic-gate 	switch (prop_type) {
9090Sstevel@tonic-gate 	case DI_PROP_TYPE_INT:
9100Sstevel@tonic-gate 		prop_decoder = di_prop_fm_decode_ints;
9110Sstevel@tonic-gate 		break;
9120Sstevel@tonic-gate 	case DI_PROP_TYPE_STRING:
9130Sstevel@tonic-gate 		prop_decoder = di_prop_fm_decode_strings;
9140Sstevel@tonic-gate 		break;
9150Sstevel@tonic-gate 	case DI_PROP_TYPE_BYTE:
9160Sstevel@tonic-gate 	default:
9170Sstevel@tonic-gate 		prop_decoder = di_prop_fm_decode_bytes;
9180Sstevel@tonic-gate 		break;
9190Sstevel@tonic-gate 	}
9200Sstevel@tonic-gate 
9210Sstevel@tonic-gate 	if ((*prop_decoder)(&ph, data, (uint_t *)&nelements)
9220Sstevel@tonic-gate 	    != DDI_PROP_SUCCESS)
9230Sstevel@tonic-gate 		return (-1);
9240Sstevel@tonic-gate 
9250Sstevel@tonic-gate 	/*
9260Sstevel@tonic-gate 	 * Free the encoded data
9270Sstevel@tonic-gate 	 */
9280Sstevel@tonic-gate 	if (size != 0)
9290Sstevel@tonic-gate 		free(ph.ph_data);
9300Sstevel@tonic-gate 
9310Sstevel@tonic-gate 	return (nelements);
9320Sstevel@tonic-gate }
9330Sstevel@tonic-gate 
934*3814Sjveta void
di_slot_names_free(int count,di_slot_name_t * slot_names)935*3814Sjveta di_slot_names_free(int count, di_slot_name_t *slot_names)
936*3814Sjveta {
937*3814Sjveta 	if (slot_names == NULL)
938*3814Sjveta 		return;
939*3814Sjveta 
940*3814Sjveta 	while (--count >= 0) {
941*3814Sjveta 		if (slot_names[count].name != NULL)
942*3814Sjveta 			free(slot_names[count].name);
943*3814Sjveta 	}
944*3814Sjveta 	free(slot_names);
945*3814Sjveta }
946*3814Sjveta 
947*3814Sjveta /*
948*3814Sjveta  * 1275 "slot-names" format: [int][string1][string2]...[stringN]
949*3814Sjveta  *	- [int] is a 1275 encoded integer
950*3814Sjveta  *      - [string1]...[stringN] are concatenated null-terminated strings
951*3814Sjveta  *      - each bit position in [int] represents a pci device number
952*3814Sjveta  *	- each bit which is set in [int] represents a slot with a device
953*3814Sjveta  *	  number of that bit position
954*3814Sjveta  *      - each string in [string1]...[stringN] identifies a slot name only
955*3814Sjveta  *	  for the bits which are set in [int]
956*3814Sjveta  *	- the ordering of strings follow the ordering of bits set in [int]
957*3814Sjveta  *
958*3814Sjveta  * an allocated array of di_slot_name_t is returned through prop_data if
959*3814Sjveta  * [int] is non-zero and the number of entries as the return value;
960*3814Sjveta  * use di_slot_names_free() to free the array
961*3814Sjveta  */
962*3814Sjveta int
di_slot_names_decode(uchar_t * rawdata,int rawlen,di_slot_name_t ** prop_data)963*3814Sjveta di_slot_names_decode(uchar_t *rawdata, int rawlen,
964*3814Sjveta     di_slot_name_t **prop_data)
965*3814Sjveta {
966*3814Sjveta 	char *sp, *maxsp;
967*3814Sjveta 	int count, i;
968*3814Sjveta 	size_t len;
969*3814Sjveta 	int slots;
970*3814Sjveta 	int maxcount = 0;
971*3814Sjveta 	int maxslots = 0;
972*3814Sjveta 	di_slot_name_t *slot_names = NULL;
973*3814Sjveta 
974*3814Sjveta 	if (rawlen < sizeof (slots))
975*3814Sjveta 		goto ERROUT;
976*3814Sjveta 
977*3814Sjveta 	slots = impl_di_prop_int_from_prom(rawdata, sizeof (slots));
978*3814Sjveta 	if (slots == 0) {
979*3814Sjveta 		*prop_data = NULL;
980*3814Sjveta 		return (0);
981*3814Sjveta 	}
982*3814Sjveta 
983*3814Sjveta 	maxslots = sizeof (slots) * 8;
984*3814Sjveta 	count = 0;
985*3814Sjveta 	for (i = 0; i < maxslots; i++) {
986*3814Sjveta 		if (slots & (1 << i))
987*3814Sjveta 			count++;
988*3814Sjveta 	}
989*3814Sjveta 	maxslots = i;
990*3814Sjveta 	maxcount = count;
991*3814Sjveta 	slot_names = malloc(sizeof (*slot_names) * maxcount);
992*3814Sjveta 	bzero(slot_names, sizeof (*slot_names) * maxcount);
993*3814Sjveta 
994*3814Sjveta 	/* also handle unterminated strings */
995*3814Sjveta 	sp = (char *)(rawdata + sizeof (slots));
996*3814Sjveta 	maxsp = sp + (rawlen - sizeof (slots));
997*3814Sjveta 	count = 0;
998*3814Sjveta 	for (i = 0; i < maxslots; i++) {
999*3814Sjveta 		if (slots & (1 << i)) {
1000*3814Sjveta 			if (sp > maxsp)
1001*3814Sjveta 				break;
1002*3814Sjveta 			len = strnlen(sp, (maxsp - sp) + 1);
1003*3814Sjveta 			if (len == 0)
1004*3814Sjveta 				break;
1005*3814Sjveta 
1006*3814Sjveta 			slot_names[count].name =
1007*3814Sjveta 			    malloc(sizeof (char) * (len + 1));
1008*3814Sjveta 			(void) strlcpy(slot_names[count].name, sp, len + 1);
1009*3814Sjveta 
1010*3814Sjveta 			slot_names[count].num = i;
1011*3814Sjveta 
1012*3814Sjveta 			sp += len + 1;
1013*3814Sjveta 			count++;
1014*3814Sjveta 		}
1015*3814Sjveta 	}
1016*3814Sjveta 
1017*3814Sjveta 	/*
1018*3814Sjveta 	 * check if the number of strings match with the number of slots;
1019*3814Sjveta 	 * we can also get a lesser string count even when there appears to be
1020*3814Sjveta 	 * the correct number of strings if one or more pair of strings are
1021*3814Sjveta 	 * seperated by more than one NULL byte
1022*3814Sjveta 	 */
1023*3814Sjveta 	if (count != maxcount)
1024*3814Sjveta 		goto ERROUT;
1025*3814Sjveta 
1026*3814Sjveta 	*prop_data = slot_names;
1027*3814Sjveta 	return (maxcount);
1028*3814Sjveta 	/*NOTREACHED*/
1029*3814Sjveta ERROUT:
1030*3814Sjveta 	di_slot_names_free(maxcount, slot_names);
1031*3814Sjveta 	*prop_data = NULL;
1032*3814Sjveta 	return (-1);
1033*3814Sjveta }
1034