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