17c478bd9Sstevel@tonic-gate /* 27c478bd9Sstevel@tonic-gate * CDDL HEADER START 37c478bd9Sstevel@tonic-gate * 47c478bd9Sstevel@tonic-gate * The contents of this file are subject to the terms of the 5*3ebafc43Sjveta * Common Development and Distribution License (the "License"). 6*3ebafc43Sjveta * You may not use this file except in compliance with the License. 77c478bd9Sstevel@tonic-gate * 87c478bd9Sstevel@tonic-gate * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 97c478bd9Sstevel@tonic-gate * or http://www.opensolaris.org/os/licensing. 107c478bd9Sstevel@tonic-gate * See the License for the specific language governing permissions 117c478bd9Sstevel@tonic-gate * and limitations under the License. 127c478bd9Sstevel@tonic-gate * 137c478bd9Sstevel@tonic-gate * When distributing Covered Code, include this CDDL HEADER in each 147c478bd9Sstevel@tonic-gate * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 157c478bd9Sstevel@tonic-gate * If applicable, add the following below this CDDL HEADER, with the 167c478bd9Sstevel@tonic-gate * fields enclosed by brackets "[]" replaced with your own identifying 177c478bd9Sstevel@tonic-gate * information: Portions Copyright [yyyy] [name of copyright owner] 187c478bd9Sstevel@tonic-gate * 197c478bd9Sstevel@tonic-gate * CDDL HEADER END 207c478bd9Sstevel@tonic-gate */ 217c478bd9Sstevel@tonic-gate /* 22*3ebafc43Sjveta * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 237c478bd9Sstevel@tonic-gate * Use is subject to license terms. 247c478bd9Sstevel@tonic-gate */ 257c478bd9Sstevel@tonic-gate 267c478bd9Sstevel@tonic-gate #pragma ident "%Z%%M% %I% %E% SMI" 277c478bd9Sstevel@tonic-gate 287c478bd9Sstevel@tonic-gate /* 297c478bd9Sstevel@tonic-gate * This file contains kernel property decode routines adopted from 307c478bd9Sstevel@tonic-gate * sunddi.c and ddi_impl.c. The following changes have been applied. 317c478bd9Sstevel@tonic-gate * 327c478bd9Sstevel@tonic-gate * (1) Replace kmem_alloc by malloc. Remove negative indexing 337c478bd9Sstevel@tonic-gate * (2) Decoding applies only to prom properties. 347c478bd9Sstevel@tonic-gate * (3) For strings, the return value is a composite string, not a string array. 357c478bd9Sstevel@tonic-gate * (4) impl_ddi_prop_int_from_prom() uses _LITTLE_ENDIAN from isa_defs.h 367c478bd9Sstevel@tonic-gate * 377c478bd9Sstevel@tonic-gate * XXX This file should be kept in sync with kernel property encoding. 387c478bd9Sstevel@tonic-gate */ 397c478bd9Sstevel@tonic-gate 407c478bd9Sstevel@tonic-gate #include <stdlib.h> 417c478bd9Sstevel@tonic-gate #include <strings.h> 427c478bd9Sstevel@tonic-gate #include <synch.h> 437c478bd9Sstevel@tonic-gate #include <ctype.h> 447c478bd9Sstevel@tonic-gate #include <sys/types.h> 457c478bd9Sstevel@tonic-gate #include <sys/dditypes.h> 467c478bd9Sstevel@tonic-gate #include <sys/ddipropdefs.h> 477c478bd9Sstevel@tonic-gate #include <sys/isa_defs.h> 487c478bd9Sstevel@tonic-gate 497c478bd9Sstevel@tonic-gate #include "libdevinfo.h" 507c478bd9Sstevel@tonic-gate 517c478bd9Sstevel@tonic-gate /* 527c478bd9Sstevel@tonic-gate * Return an integer in native machine format from an OBP 1275 integer 537c478bd9Sstevel@tonic-gate * representation, which is big-endian, with no particular alignment 547c478bd9Sstevel@tonic-gate * guarantees. intp points to the OBP data, and n the number of bytes. 557c478bd9Sstevel@tonic-gate * 567c478bd9Sstevel@tonic-gate * Byte-swapping may be needed on some implementations. 577c478bd9Sstevel@tonic-gate */ 587c478bd9Sstevel@tonic-gate int 597c478bd9Sstevel@tonic-gate impl_di_prop_int_from_prom(uchar_t *intp, int n) 607c478bd9Sstevel@tonic-gate { 617c478bd9Sstevel@tonic-gate int i = 0; 627c478bd9Sstevel@tonic-gate 637c478bd9Sstevel@tonic-gate #if defined(_LITTLE_ENDIAN) 647c478bd9Sstevel@tonic-gate intp += n; 657c478bd9Sstevel@tonic-gate while (n-- > 0) { 667c478bd9Sstevel@tonic-gate i = (i << 8) | *(--intp); 677c478bd9Sstevel@tonic-gate } 687c478bd9Sstevel@tonic-gate #else 697c478bd9Sstevel@tonic-gate while (n-- > 0) { 707c478bd9Sstevel@tonic-gate i = (i << 8) | *intp++; 717c478bd9Sstevel@tonic-gate } 727c478bd9Sstevel@tonic-gate #endif /* defined(_LITTLE_ENDIAN) */ 737c478bd9Sstevel@tonic-gate 747c478bd9Sstevel@tonic-gate return (i); 757c478bd9Sstevel@tonic-gate } 767c478bd9Sstevel@tonic-gate 777c478bd9Sstevel@tonic-gate /* 787c478bd9Sstevel@tonic-gate * Reset the current location pointer in the property handle to the 797c478bd9Sstevel@tonic-gate * beginning of the data. 807c478bd9Sstevel@tonic-gate */ 817c478bd9Sstevel@tonic-gate void 827c478bd9Sstevel@tonic-gate di_prop_reset_pos(prop_handle_t *ph) 837c478bd9Sstevel@tonic-gate { 847c478bd9Sstevel@tonic-gate ph->ph_cur_pos = ph->ph_data; 857c478bd9Sstevel@tonic-gate ph->ph_save_pos = ph->ph_data; 867c478bd9Sstevel@tonic-gate } 877c478bd9Sstevel@tonic-gate 887c478bd9Sstevel@tonic-gate /* 897c478bd9Sstevel@tonic-gate * Restore the current location pointer in the property handle to the 907c478bd9Sstevel@tonic-gate * saved position. 917c478bd9Sstevel@tonic-gate */ 927c478bd9Sstevel@tonic-gate void 937c478bd9Sstevel@tonic-gate di_prop_save_pos(prop_handle_t *ph) 947c478bd9Sstevel@tonic-gate { 957c478bd9Sstevel@tonic-gate ph->ph_save_pos = ph->ph_cur_pos; 967c478bd9Sstevel@tonic-gate } 977c478bd9Sstevel@tonic-gate 987c478bd9Sstevel@tonic-gate /* 997c478bd9Sstevel@tonic-gate * Save the location that the current location poiner is pointing to.. 1007c478bd9Sstevel@tonic-gate */ 1017c478bd9Sstevel@tonic-gate void 1027c478bd9Sstevel@tonic-gate di_prop_restore_pos(prop_handle_t *ph) 1037c478bd9Sstevel@tonic-gate { 1047c478bd9Sstevel@tonic-gate ph->ph_cur_pos = ph->ph_save_pos; 1057c478bd9Sstevel@tonic-gate } 1067c478bd9Sstevel@tonic-gate 1077c478bd9Sstevel@tonic-gate /* 1087c478bd9Sstevel@tonic-gate * Property encode/decode functions 1097c478bd9Sstevel@tonic-gate */ 1107c478bd9Sstevel@tonic-gate 1117c478bd9Sstevel@tonic-gate /* 1127c478bd9Sstevel@tonic-gate * Decode an array of integers property 1137c478bd9Sstevel@tonic-gate */ 1147c478bd9Sstevel@tonic-gate static int 1157c478bd9Sstevel@tonic-gate di_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements) 1167c478bd9Sstevel@tonic-gate { 1177c478bd9Sstevel@tonic-gate int i; 1187c478bd9Sstevel@tonic-gate int cnt = 0; 1197c478bd9Sstevel@tonic-gate int *tmp; 1207c478bd9Sstevel@tonic-gate int *intp; 1217c478bd9Sstevel@tonic-gate int n; 1227c478bd9Sstevel@tonic-gate 1237c478bd9Sstevel@tonic-gate /* 1247c478bd9Sstevel@tonic-gate * Figure out how many array elements there are by going through the 1257c478bd9Sstevel@tonic-gate * data without decoding it first and counting. 1267c478bd9Sstevel@tonic-gate */ 1277c478bd9Sstevel@tonic-gate for (;;) { 1287c478bd9Sstevel@tonic-gate i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL); 1297c478bd9Sstevel@tonic-gate if (i < 0) 1307c478bd9Sstevel@tonic-gate break; 1317c478bd9Sstevel@tonic-gate cnt++; 1327c478bd9Sstevel@tonic-gate } 1337c478bd9Sstevel@tonic-gate 1347c478bd9Sstevel@tonic-gate /* 1357c478bd9Sstevel@tonic-gate * If there are no elements return an error 1367c478bd9Sstevel@tonic-gate */ 1377c478bd9Sstevel@tonic-gate if (cnt == 0) 1387c478bd9Sstevel@tonic-gate return (DDI_PROP_END_OF_DATA); 1397c478bd9Sstevel@tonic-gate 1407c478bd9Sstevel@tonic-gate /* 1417c478bd9Sstevel@tonic-gate * If we cannot skip through the data, we cannot decode it 1427c478bd9Sstevel@tonic-gate */ 1437c478bd9Sstevel@tonic-gate if (i == DDI_PROP_RESULT_ERROR) 1447c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 1457c478bd9Sstevel@tonic-gate 1467c478bd9Sstevel@tonic-gate /* 1477c478bd9Sstevel@tonic-gate * Reset the data pointer to the beginning of the encoded data 1487c478bd9Sstevel@tonic-gate */ 1497c478bd9Sstevel@tonic-gate di_prop_reset_pos(ph); 1507c478bd9Sstevel@tonic-gate 1517c478bd9Sstevel@tonic-gate /* 1527c478bd9Sstevel@tonic-gate * Allocated memory to store the decoded value in. 1537c478bd9Sstevel@tonic-gate */ 1547c478bd9Sstevel@tonic-gate if ((intp = malloc(cnt * sizeof (int))) == NULL) { 1557c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 1567c478bd9Sstevel@tonic-gate } 1577c478bd9Sstevel@tonic-gate 1587c478bd9Sstevel@tonic-gate 1597c478bd9Sstevel@tonic-gate /* 1607c478bd9Sstevel@tonic-gate * Decode each elemente and place it in the space we just allocated 1617c478bd9Sstevel@tonic-gate */ 1627c478bd9Sstevel@tonic-gate tmp = intp; 1637c478bd9Sstevel@tonic-gate for (n = 0; n < cnt; n++, tmp++) { 1647c478bd9Sstevel@tonic-gate i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp); 1657c478bd9Sstevel@tonic-gate if (i < DDI_PROP_RESULT_OK) { 1667c478bd9Sstevel@tonic-gate /* 1677c478bd9Sstevel@tonic-gate * Free the space we just allocated 1687c478bd9Sstevel@tonic-gate * and return an error. 1697c478bd9Sstevel@tonic-gate */ 1707c478bd9Sstevel@tonic-gate free(intp); 1717c478bd9Sstevel@tonic-gate switch (i) { 1727c478bd9Sstevel@tonic-gate case DDI_PROP_RESULT_EOF: 1737c478bd9Sstevel@tonic-gate return (DDI_PROP_END_OF_DATA); 1747c478bd9Sstevel@tonic-gate 1757c478bd9Sstevel@tonic-gate case DDI_PROP_RESULT_ERROR: 1767c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 1777c478bd9Sstevel@tonic-gate } 1787c478bd9Sstevel@tonic-gate } 1797c478bd9Sstevel@tonic-gate } 1807c478bd9Sstevel@tonic-gate 1817c478bd9Sstevel@tonic-gate *nelements = cnt; 1827c478bd9Sstevel@tonic-gate *(int **)data = intp; 1837c478bd9Sstevel@tonic-gate 1847c478bd9Sstevel@tonic-gate return (DDI_PROP_SUCCESS); 1857c478bd9Sstevel@tonic-gate } 1867c478bd9Sstevel@tonic-gate 1877c478bd9Sstevel@tonic-gate /* 1887c478bd9Sstevel@tonic-gate * Decode an array of strings. 1897c478bd9Sstevel@tonic-gate */ 1907c478bd9Sstevel@tonic-gate static int 1917c478bd9Sstevel@tonic-gate di_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements) 1927c478bd9Sstevel@tonic-gate { 1937c478bd9Sstevel@tonic-gate int cnt = 0; 1947c478bd9Sstevel@tonic-gate char *strs; 1957c478bd9Sstevel@tonic-gate char *tmp; 1967c478bd9Sstevel@tonic-gate int size; 1977c478bd9Sstevel@tonic-gate int i; 1987c478bd9Sstevel@tonic-gate int n; 1997c478bd9Sstevel@tonic-gate int nbytes; 2007c478bd9Sstevel@tonic-gate 2017c478bd9Sstevel@tonic-gate /* 2027c478bd9Sstevel@tonic-gate * Figure out how much memory we need for the sum total 2037c478bd9Sstevel@tonic-gate */ 2047c478bd9Sstevel@tonic-gate nbytes = 0; 2057c478bd9Sstevel@tonic-gate 2067c478bd9Sstevel@tonic-gate for (;;) { 2077c478bd9Sstevel@tonic-gate /* 2087c478bd9Sstevel@tonic-gate * Get the decoded size of the current encoded string. 2097c478bd9Sstevel@tonic-gate */ 2107c478bd9Sstevel@tonic-gate size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 2117c478bd9Sstevel@tonic-gate if (size < 0) 2127c478bd9Sstevel@tonic-gate break; 2137c478bd9Sstevel@tonic-gate 2147c478bd9Sstevel@tonic-gate cnt++; 2157c478bd9Sstevel@tonic-gate nbytes += size; 2167c478bd9Sstevel@tonic-gate } 2177c478bd9Sstevel@tonic-gate 2187c478bd9Sstevel@tonic-gate /* 2197c478bd9Sstevel@tonic-gate * If there are no elements return an error 2207c478bd9Sstevel@tonic-gate */ 2217c478bd9Sstevel@tonic-gate if (cnt == 0) 2227c478bd9Sstevel@tonic-gate return (DDI_PROP_END_OF_DATA); 2237c478bd9Sstevel@tonic-gate 2247c478bd9Sstevel@tonic-gate /* 2257c478bd9Sstevel@tonic-gate * If we cannot skip through the data, we cannot decode it 2267c478bd9Sstevel@tonic-gate */ 2277c478bd9Sstevel@tonic-gate if (size == DDI_PROP_RESULT_ERROR) 2287c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 2297c478bd9Sstevel@tonic-gate 2307c478bd9Sstevel@tonic-gate /* 2317c478bd9Sstevel@tonic-gate * Allocate memory in which to store the decoded strings. 2327c478bd9Sstevel@tonic-gate */ 2337c478bd9Sstevel@tonic-gate if ((strs = malloc(nbytes)) == NULL) { 2347c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 2357c478bd9Sstevel@tonic-gate } 2367c478bd9Sstevel@tonic-gate 2377c478bd9Sstevel@tonic-gate /* 2387c478bd9Sstevel@tonic-gate * Finally, we can decode each string 2397c478bd9Sstevel@tonic-gate */ 2407c478bd9Sstevel@tonic-gate di_prop_reset_pos(ph); 2417c478bd9Sstevel@tonic-gate tmp = strs; 2427c478bd9Sstevel@tonic-gate for (n = 0; n < cnt; n++) { 2437c478bd9Sstevel@tonic-gate i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp); 2447c478bd9Sstevel@tonic-gate if (i < DDI_PROP_RESULT_OK) { 2457c478bd9Sstevel@tonic-gate /* 2467c478bd9Sstevel@tonic-gate * Free the space we just allocated 2477c478bd9Sstevel@tonic-gate * and return an error 2487c478bd9Sstevel@tonic-gate */ 2497c478bd9Sstevel@tonic-gate free(strs); 2507c478bd9Sstevel@tonic-gate switch (i) { 2517c478bd9Sstevel@tonic-gate case DDI_PROP_RESULT_EOF: 2527c478bd9Sstevel@tonic-gate return (DDI_PROP_END_OF_DATA); 2537c478bd9Sstevel@tonic-gate 2547c478bd9Sstevel@tonic-gate case DDI_PROP_RESULT_ERROR: 2557c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 2567c478bd9Sstevel@tonic-gate } 2577c478bd9Sstevel@tonic-gate } 2587c478bd9Sstevel@tonic-gate tmp += strlen(tmp) + 1; 2597c478bd9Sstevel@tonic-gate } 2607c478bd9Sstevel@tonic-gate 2617c478bd9Sstevel@tonic-gate *(char **)data = strs; 2627c478bd9Sstevel@tonic-gate *nelements = cnt; 2637c478bd9Sstevel@tonic-gate 2647c478bd9Sstevel@tonic-gate return (DDI_PROP_SUCCESS); 2657c478bd9Sstevel@tonic-gate } 2667c478bd9Sstevel@tonic-gate 2677c478bd9Sstevel@tonic-gate /* 2687c478bd9Sstevel@tonic-gate * Decode an array of bytes. 2697c478bd9Sstevel@tonic-gate */ 2707c478bd9Sstevel@tonic-gate static int 2717c478bd9Sstevel@tonic-gate di_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements) 2727c478bd9Sstevel@tonic-gate { 2737c478bd9Sstevel@tonic-gate uchar_t *tmp; 2747c478bd9Sstevel@tonic-gate int nbytes; 2757c478bd9Sstevel@tonic-gate int i; 2767c478bd9Sstevel@tonic-gate 2777c478bd9Sstevel@tonic-gate /* 2787c478bd9Sstevel@tonic-gate * If there are no elements return an error 2797c478bd9Sstevel@tonic-gate */ 2807c478bd9Sstevel@tonic-gate if (ph->ph_size == 0) 2817c478bd9Sstevel@tonic-gate return (DDI_PROP_END_OF_DATA); 2827c478bd9Sstevel@tonic-gate 2837c478bd9Sstevel@tonic-gate /* 2847c478bd9Sstevel@tonic-gate * Get the size of the encoded array of bytes. 2857c478bd9Sstevel@tonic-gate */ 2867c478bd9Sstevel@tonic-gate nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE, 2877c478bd9Sstevel@tonic-gate data, ph->ph_size); 2887c478bd9Sstevel@tonic-gate if (nbytes < DDI_PROP_RESULT_OK) { 2897c478bd9Sstevel@tonic-gate switch (nbytes) { 2907c478bd9Sstevel@tonic-gate case DDI_PROP_RESULT_EOF: 2917c478bd9Sstevel@tonic-gate return (DDI_PROP_END_OF_DATA); 2927c478bd9Sstevel@tonic-gate 2937c478bd9Sstevel@tonic-gate case DDI_PROP_RESULT_ERROR: 2947c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 2957c478bd9Sstevel@tonic-gate } 2967c478bd9Sstevel@tonic-gate } 2977c478bd9Sstevel@tonic-gate 2987c478bd9Sstevel@tonic-gate /* 2997c478bd9Sstevel@tonic-gate * Allocated memory to store the decoded value in. 3007c478bd9Sstevel@tonic-gate */ 3017c478bd9Sstevel@tonic-gate if ((tmp = malloc(nbytes)) == NULL) { 3027c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 3037c478bd9Sstevel@tonic-gate } 3047c478bd9Sstevel@tonic-gate 3057c478bd9Sstevel@tonic-gate /* 3067c478bd9Sstevel@tonic-gate * Decode each element and place it in the space we just allocated 3077c478bd9Sstevel@tonic-gate */ 3087c478bd9Sstevel@tonic-gate i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes); 3097c478bd9Sstevel@tonic-gate if (i < DDI_PROP_RESULT_OK) { 3107c478bd9Sstevel@tonic-gate /* 3117c478bd9Sstevel@tonic-gate * Free the space we just allocated 3127c478bd9Sstevel@tonic-gate * and return an error 3137c478bd9Sstevel@tonic-gate */ 3147c478bd9Sstevel@tonic-gate free(tmp); 3157c478bd9Sstevel@tonic-gate switch (i) { 3167c478bd9Sstevel@tonic-gate case DDI_PROP_RESULT_EOF: 3177c478bd9Sstevel@tonic-gate return (DDI_PROP_END_OF_DATA); 3187c478bd9Sstevel@tonic-gate 3197c478bd9Sstevel@tonic-gate case DDI_PROP_RESULT_ERROR: 3207c478bd9Sstevel@tonic-gate return (DDI_PROP_CANNOT_DECODE); 3217c478bd9Sstevel@tonic-gate } 3227c478bd9Sstevel@tonic-gate } 3237c478bd9Sstevel@tonic-gate 3247c478bd9Sstevel@tonic-gate *(uchar_t **)data = tmp; 3257c478bd9Sstevel@tonic-gate *nelements = nbytes; 3267c478bd9Sstevel@tonic-gate 3277c478bd9Sstevel@tonic-gate return (DDI_PROP_SUCCESS); 3287c478bd9Sstevel@tonic-gate } 3297c478bd9Sstevel@tonic-gate 3307c478bd9Sstevel@tonic-gate /* 3317c478bd9Sstevel@tonic-gate * OBP 1275 integer, string and byte operators. 3327c478bd9Sstevel@tonic-gate * 3337c478bd9Sstevel@tonic-gate * DDI_PROP_CMD_DECODE: 3347c478bd9Sstevel@tonic-gate * 3357c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_ERROR: cannot decode the data 3367c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_EOF: end of data 3377c478bd9Sstevel@tonic-gate * DDI_PROP_OK: data was decoded 3387c478bd9Sstevel@tonic-gate * 3397c478bd9Sstevel@tonic-gate * DDI_PROP_CMD_ENCODE: 3407c478bd9Sstevel@tonic-gate * 3417c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_ERROR: cannot encode the data 3427c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_EOF: end of data 3437c478bd9Sstevel@tonic-gate * DDI_PROP_OK: data was encoded 3447c478bd9Sstevel@tonic-gate * 3457c478bd9Sstevel@tonic-gate * DDI_PROP_CMD_SKIP: 3467c478bd9Sstevel@tonic-gate * 3477c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_ERROR: cannot skip the data 3487c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_EOF: end of data 3497c478bd9Sstevel@tonic-gate * DDI_PROP_OK: data was skipped 3507c478bd9Sstevel@tonic-gate * 3517c478bd9Sstevel@tonic-gate * DDI_PROP_CMD_GET_ESIZE: 3527c478bd9Sstevel@tonic-gate * 3537c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_ERROR: cannot get encoded size 3547c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_EOF: end of data 3557c478bd9Sstevel@tonic-gate * > 0: the encoded size 3567c478bd9Sstevel@tonic-gate * 3577c478bd9Sstevel@tonic-gate * DDI_PROP_CMD_GET_DSIZE: 3587c478bd9Sstevel@tonic-gate * 3597c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_ERROR: cannot get decoded size 3607c478bd9Sstevel@tonic-gate * DDI_PROP_RESULT_EOF: end of data 3617c478bd9Sstevel@tonic-gate * > 0: the decoded size 3627c478bd9Sstevel@tonic-gate */ 3637c478bd9Sstevel@tonic-gate 3647c478bd9Sstevel@tonic-gate /* 3657c478bd9Sstevel@tonic-gate * OBP 1275 integer operator 3667c478bd9Sstevel@tonic-gate * 3677c478bd9Sstevel@tonic-gate * OBP properties are a byte stream of data, so integers may not be 3687c478bd9Sstevel@tonic-gate * properly aligned. Therefore we need to copy them one byte at a time. 3697c478bd9Sstevel@tonic-gate */ 3707c478bd9Sstevel@tonic-gate int 3717c478bd9Sstevel@tonic-gate di_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data) 3727c478bd9Sstevel@tonic-gate { 3737c478bd9Sstevel@tonic-gate int i; 3747c478bd9Sstevel@tonic-gate 3757c478bd9Sstevel@tonic-gate switch (cmd) { 3767c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_DECODE: 3777c478bd9Sstevel@tonic-gate /* 3787c478bd9Sstevel@tonic-gate * Check that there is encoded data 3797c478bd9Sstevel@tonic-gate */ 3807c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 3817c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 3827c478bd9Sstevel@tonic-gate if (ph->ph_flags & PH_FROM_PROM) { 3837c478bd9Sstevel@tonic-gate i = ph->ph_size < PROP_1275_INT_SIZE ? 3847c478bd9Sstevel@tonic-gate ph->ph_size : PROP_1275_INT_SIZE; 3857c478bd9Sstevel@tonic-gate if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3867c478bd9Sstevel@tonic-gate ph->ph_size - i)) 3877c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 3887c478bd9Sstevel@tonic-gate } else if (ph->ph_size < sizeof (int) || 3897c478bd9Sstevel@tonic-gate ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 3907c478bd9Sstevel@tonic-gate ph->ph_size - sizeof (int)))) { 3917c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 3927c478bd9Sstevel@tonic-gate } 3937c478bd9Sstevel@tonic-gate 3947c478bd9Sstevel@tonic-gate /* 3957c478bd9Sstevel@tonic-gate * Copy the integer, using the implementation-specific 3967c478bd9Sstevel@tonic-gate * copy function if the property is coming from the PROM. 3977c478bd9Sstevel@tonic-gate */ 3987c478bd9Sstevel@tonic-gate if (ph->ph_flags & PH_FROM_PROM) { 3997c478bd9Sstevel@tonic-gate *data = impl_di_prop_int_from_prom( 4007c478bd9Sstevel@tonic-gate (uchar_t *)ph->ph_cur_pos, 4017c478bd9Sstevel@tonic-gate (ph->ph_size < PROP_1275_INT_SIZE) ? 4027c478bd9Sstevel@tonic-gate ph->ph_size : PROP_1275_INT_SIZE); 4037c478bd9Sstevel@tonic-gate } else { 4047c478bd9Sstevel@tonic-gate bcopy(ph->ph_cur_pos, (caddr_t)data, sizeof (int)); 4057c478bd9Sstevel@tonic-gate } 4067c478bd9Sstevel@tonic-gate 4077c478bd9Sstevel@tonic-gate /* 4087c478bd9Sstevel@tonic-gate * Move the current location to the start of the next 4097c478bd9Sstevel@tonic-gate * bit of undecoded data. 4107c478bd9Sstevel@tonic-gate */ 4117c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 4127c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 4137c478bd9Sstevel@tonic-gate 4147c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_ENCODE: 4157c478bd9Sstevel@tonic-gate /* 4167c478bd9Sstevel@tonic-gate * Check that there is room to encoded the data 4177c478bd9Sstevel@tonic-gate */ 4187c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 4197c478bd9Sstevel@tonic-gate ph->ph_size < PROP_1275_INT_SIZE || 4207c478bd9Sstevel@tonic-gate ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 4217c478bd9Sstevel@tonic-gate ph->ph_size - sizeof (int)))) 4227c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 4237c478bd9Sstevel@tonic-gate 4247c478bd9Sstevel@tonic-gate /* 4257c478bd9Sstevel@tonic-gate * Encode the integer into the byte stream one byte at a 4267c478bd9Sstevel@tonic-gate * time. 4277c478bd9Sstevel@tonic-gate */ 4287c478bd9Sstevel@tonic-gate bcopy((caddr_t)data, ph->ph_cur_pos, sizeof (int)); 4297c478bd9Sstevel@tonic-gate 4307c478bd9Sstevel@tonic-gate /* 4317c478bd9Sstevel@tonic-gate * Move the current location to the start of the next bit of 4327c478bd9Sstevel@tonic-gate * space where we can store encoded data. 4337c478bd9Sstevel@tonic-gate */ 4347c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 4357c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 4367c478bd9Sstevel@tonic-gate 4377c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_SKIP: 4387c478bd9Sstevel@tonic-gate /* 4397c478bd9Sstevel@tonic-gate * Check that there is encoded data 4407c478bd9Sstevel@tonic-gate */ 4417c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 4427c478bd9Sstevel@tonic-gate ph->ph_size < PROP_1275_INT_SIZE) 4437c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 4447c478bd9Sstevel@tonic-gate 4457c478bd9Sstevel@tonic-gate 4467c478bd9Sstevel@tonic-gate if ((caddr_t)ph->ph_cur_pos == 4477c478bd9Sstevel@tonic-gate (caddr_t)ph->ph_data + ph->ph_size) { 4487c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_EOF); 4497c478bd9Sstevel@tonic-gate } else if ((caddr_t)ph->ph_cur_pos > 4507c478bd9Sstevel@tonic-gate (caddr_t)ph->ph_data + ph->ph_size) { 4517c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_EOF); 4527c478bd9Sstevel@tonic-gate } 4537c478bd9Sstevel@tonic-gate 4547c478bd9Sstevel@tonic-gate /* 4557c478bd9Sstevel@tonic-gate * Move the current location to the start of the next bit of 4567c478bd9Sstevel@tonic-gate * undecoded data. 4577c478bd9Sstevel@tonic-gate */ 4587c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 4597c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 4607c478bd9Sstevel@tonic-gate 4617c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_GET_ESIZE: 4627c478bd9Sstevel@tonic-gate /* 4637c478bd9Sstevel@tonic-gate * Return the size of an encoded integer on OBP 4647c478bd9Sstevel@tonic-gate */ 4657c478bd9Sstevel@tonic-gate return (PROP_1275_INT_SIZE); 4667c478bd9Sstevel@tonic-gate 4677c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_GET_DSIZE: 4687c478bd9Sstevel@tonic-gate /* 4697c478bd9Sstevel@tonic-gate * Return the size of a decoded integer on the system. 4707c478bd9Sstevel@tonic-gate */ 4717c478bd9Sstevel@tonic-gate return (sizeof (int)); 4727c478bd9Sstevel@tonic-gate } 4737c478bd9Sstevel@tonic-gate 4747c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 4757c478bd9Sstevel@tonic-gate return (0); /* keep gcc happy */ 4767c478bd9Sstevel@tonic-gate } 4777c478bd9Sstevel@tonic-gate 4787c478bd9Sstevel@tonic-gate /* 4797c478bd9Sstevel@tonic-gate * 64 bit integer operator 4807c478bd9Sstevel@tonic-gate * 4817c478bd9Sstevel@tonic-gate * This is an extension, defined by Sun, to the 1275 integer 4827c478bd9Sstevel@tonic-gate * operator. This routine handles the encoding/decoding of 4837c478bd9Sstevel@tonic-gate * 64 bit integer properties. 4847c478bd9Sstevel@tonic-gate */ 4857c478bd9Sstevel@tonic-gate int 4867c478bd9Sstevel@tonic-gate di_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data) 4877c478bd9Sstevel@tonic-gate { 4887c478bd9Sstevel@tonic-gate switch (cmd) { 4897c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_DECODE: 4907c478bd9Sstevel@tonic-gate /* 4917c478bd9Sstevel@tonic-gate * Check that there is encoded data 4927c478bd9Sstevel@tonic-gate */ 4937c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 4947c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 4957c478bd9Sstevel@tonic-gate if (ph->ph_flags & PH_FROM_PROM) { 4967c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 4977c478bd9Sstevel@tonic-gate } else if (ph->ph_size < sizeof (int64_t) || 4987c478bd9Sstevel@tonic-gate ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data + 4997c478bd9Sstevel@tonic-gate ph->ph_size - sizeof (int64_t)))) { 5007c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 5017c478bd9Sstevel@tonic-gate } 5027c478bd9Sstevel@tonic-gate 5037c478bd9Sstevel@tonic-gate /* 5047c478bd9Sstevel@tonic-gate * Copy the integer, using the implementation-specific 5057c478bd9Sstevel@tonic-gate * copy function if the property is coming from the PROM. 5067c478bd9Sstevel@tonic-gate */ 5077c478bd9Sstevel@tonic-gate bcopy(ph->ph_cur_pos, (caddr_t)data, sizeof (int64_t)); 5087c478bd9Sstevel@tonic-gate 5097c478bd9Sstevel@tonic-gate /* 5107c478bd9Sstevel@tonic-gate * Move the current location to the start of the next 5117c478bd9Sstevel@tonic-gate * bit of undecoded data. 5127c478bd9Sstevel@tonic-gate */ 5137c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 5147c478bd9Sstevel@tonic-gate sizeof (int64_t); 5157c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 5167c478bd9Sstevel@tonic-gate 5177c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_ENCODE: 5187c478bd9Sstevel@tonic-gate /* 5197c478bd9Sstevel@tonic-gate * Check that there is room to encoded the data 5207c478bd9Sstevel@tonic-gate */ 5217c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 5227c478bd9Sstevel@tonic-gate ph->ph_size < sizeof (int64_t) || 5237c478bd9Sstevel@tonic-gate ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data + 5247c478bd9Sstevel@tonic-gate ph->ph_size - sizeof (int64_t)))) 5257c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 5267c478bd9Sstevel@tonic-gate 5277c478bd9Sstevel@tonic-gate /* 5287c478bd9Sstevel@tonic-gate * Encode the integer into the byte stream one byte at a 5297c478bd9Sstevel@tonic-gate * time. 5307c478bd9Sstevel@tonic-gate */ 5317c478bd9Sstevel@tonic-gate bcopy((caddr_t)data, ph->ph_cur_pos, sizeof (int64_t)); 5327c478bd9Sstevel@tonic-gate 5337c478bd9Sstevel@tonic-gate /* 5347c478bd9Sstevel@tonic-gate * Move the current location to the start of the next bit of 5357c478bd9Sstevel@tonic-gate * space where we can store encoded data. 5367c478bd9Sstevel@tonic-gate */ 5377c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 5387c478bd9Sstevel@tonic-gate sizeof (int64_t); 5397c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 5407c478bd9Sstevel@tonic-gate 5417c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_SKIP: 5427c478bd9Sstevel@tonic-gate /* 5437c478bd9Sstevel@tonic-gate * Check that there is encoded data 5447c478bd9Sstevel@tonic-gate */ 5457c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 5467c478bd9Sstevel@tonic-gate ph->ph_size < sizeof (int64_t)) 5477c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 5487c478bd9Sstevel@tonic-gate 5497c478bd9Sstevel@tonic-gate 5507c478bd9Sstevel@tonic-gate if ((caddr_t)ph->ph_cur_pos == 5517c478bd9Sstevel@tonic-gate (caddr_t)ph->ph_data + ph->ph_size) { 5527c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_EOF); 5537c478bd9Sstevel@tonic-gate } else if ((caddr_t)ph->ph_cur_pos > 5547c478bd9Sstevel@tonic-gate (caddr_t)ph->ph_data + ph->ph_size) { 5557c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_EOF); 5567c478bd9Sstevel@tonic-gate } 5577c478bd9Sstevel@tonic-gate 5587c478bd9Sstevel@tonic-gate /* 5597c478bd9Sstevel@tonic-gate * Move the current location to the start of the next bit of 5607c478bd9Sstevel@tonic-gate * undecoded data. 5617c478bd9Sstevel@tonic-gate */ 5627c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 5637c478bd9Sstevel@tonic-gate sizeof (int64_t); 5647c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 5657c478bd9Sstevel@tonic-gate 5667c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_GET_ESIZE: 5677c478bd9Sstevel@tonic-gate /* 5687c478bd9Sstevel@tonic-gate * Return the size of an encoded integer on OBP 5697c478bd9Sstevel@tonic-gate */ 5707c478bd9Sstevel@tonic-gate return (sizeof (int64_t)); 5717c478bd9Sstevel@tonic-gate 5727c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_GET_DSIZE: 5737c478bd9Sstevel@tonic-gate /* 5747c478bd9Sstevel@tonic-gate * Return the size of a decoded integer on the system. 5757c478bd9Sstevel@tonic-gate */ 5767c478bd9Sstevel@tonic-gate return (sizeof (int64_t)); 5777c478bd9Sstevel@tonic-gate } 5787c478bd9Sstevel@tonic-gate 5797c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 5807c478bd9Sstevel@tonic-gate return (0); /* keep gcc happy */ 5817c478bd9Sstevel@tonic-gate } 5827c478bd9Sstevel@tonic-gate 5837c478bd9Sstevel@tonic-gate /* 5847c478bd9Sstevel@tonic-gate * OBP 1275 string operator. 5857c478bd9Sstevel@tonic-gate * 5867c478bd9Sstevel@tonic-gate * OBP strings are NULL terminated. 5877c478bd9Sstevel@tonic-gate */ 5887c478bd9Sstevel@tonic-gate int 5897c478bd9Sstevel@tonic-gate di_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data) 5907c478bd9Sstevel@tonic-gate { 5917c478bd9Sstevel@tonic-gate int n; 5927c478bd9Sstevel@tonic-gate char *p; 5937c478bd9Sstevel@tonic-gate char *end; 5947c478bd9Sstevel@tonic-gate 5957c478bd9Sstevel@tonic-gate switch (cmd) { 5967c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_DECODE: 5977c478bd9Sstevel@tonic-gate /* 5987c478bd9Sstevel@tonic-gate * Check that there is encoded data 5997c478bd9Sstevel@tonic-gate */ 6007c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 6017c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 6027c478bd9Sstevel@tonic-gate } 6037c478bd9Sstevel@tonic-gate 6047c478bd9Sstevel@tonic-gate n = strlen((char *)ph->ph_cur_pos) + 1; 6057c478bd9Sstevel@tonic-gate if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 6067c478bd9Sstevel@tonic-gate ph->ph_size - n)) { 6077c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 6087c478bd9Sstevel@tonic-gate } 6097c478bd9Sstevel@tonic-gate 6107c478bd9Sstevel@tonic-gate /* 6117c478bd9Sstevel@tonic-gate * Copy the NULL terminated string 6127c478bd9Sstevel@tonic-gate */ 6137c478bd9Sstevel@tonic-gate bcopy((char *)ph->ph_cur_pos, data, n); 6147c478bd9Sstevel@tonic-gate 6157c478bd9Sstevel@tonic-gate /* 6167c478bd9Sstevel@tonic-gate * Move the current location to the start of the next bit of 6177c478bd9Sstevel@tonic-gate * undecoded data. 6187c478bd9Sstevel@tonic-gate */ 6197c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (char *)ph->ph_cur_pos + n; 6207c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 6217c478bd9Sstevel@tonic-gate 6227c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_ENCODE: 6237c478bd9Sstevel@tonic-gate /* 6247c478bd9Sstevel@tonic-gate * Check that there is room to encoded the data 6257c478bd9Sstevel@tonic-gate */ 6267c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 6277c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 6287c478bd9Sstevel@tonic-gate } 6297c478bd9Sstevel@tonic-gate 6307c478bd9Sstevel@tonic-gate n = strlen(data) + 1; 6317c478bd9Sstevel@tonic-gate if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 6327c478bd9Sstevel@tonic-gate ph->ph_size - n)) { 6337c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 6347c478bd9Sstevel@tonic-gate } 6357c478bd9Sstevel@tonic-gate 6367c478bd9Sstevel@tonic-gate /* 6377c478bd9Sstevel@tonic-gate * Copy the NULL terminated string 6387c478bd9Sstevel@tonic-gate */ 6397c478bd9Sstevel@tonic-gate bcopy(data, (char *)ph->ph_cur_pos, n); 6407c478bd9Sstevel@tonic-gate 6417c478bd9Sstevel@tonic-gate /* 6427c478bd9Sstevel@tonic-gate * Move the current location to the start of the next bit of 6437c478bd9Sstevel@tonic-gate * space where we can store encoded data. 6447c478bd9Sstevel@tonic-gate */ 6457c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (char *)ph->ph_cur_pos + n; 6467c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 6477c478bd9Sstevel@tonic-gate 6487c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_SKIP: 6497c478bd9Sstevel@tonic-gate /* 6507c478bd9Sstevel@tonic-gate * Check that there is encoded data 6517c478bd9Sstevel@tonic-gate */ 6527c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 6537c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 6547c478bd9Sstevel@tonic-gate } 6557c478bd9Sstevel@tonic-gate 6567c478bd9Sstevel@tonic-gate /* 6577c478bd9Sstevel@tonic-gate * Return the string length plus one for the NULL 6587c478bd9Sstevel@tonic-gate * We know the size of the property, we need to 6597c478bd9Sstevel@tonic-gate * ensure that the string is properly formatted, 6607c478bd9Sstevel@tonic-gate * since we may be looking up random OBP data. 6617c478bd9Sstevel@tonic-gate */ 6627c478bd9Sstevel@tonic-gate p = (char *)ph->ph_cur_pos; 6637c478bd9Sstevel@tonic-gate end = (char *)ph->ph_data + ph->ph_size; 6647c478bd9Sstevel@tonic-gate 6657c478bd9Sstevel@tonic-gate if (p == end) { 6667c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_EOF); 6677c478bd9Sstevel@tonic-gate } 6687c478bd9Sstevel@tonic-gate 6697c478bd9Sstevel@tonic-gate /* 6707c478bd9Sstevel@tonic-gate * Make sure each char is printable 6717c478bd9Sstevel@tonic-gate */ 6727c478bd9Sstevel@tonic-gate for (n = 0; p < end && isascii(*p) && !iscntrl(*p); n++, p++) 6737c478bd9Sstevel@tonic-gate ; 6747c478bd9Sstevel@tonic-gate 6757c478bd9Sstevel@tonic-gate /* Check termination and non-zero length */ 6767c478bd9Sstevel@tonic-gate if ((*p == 0) && (n != 0)) { 6777c478bd9Sstevel@tonic-gate ph->ph_cur_pos = p + 1; 6787c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 6797c478bd9Sstevel@tonic-gate } 6807c478bd9Sstevel@tonic-gate 6817c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 6827c478bd9Sstevel@tonic-gate 6837c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_GET_ESIZE: 6847c478bd9Sstevel@tonic-gate /* 6857c478bd9Sstevel@tonic-gate * Return the size of the encoded string on OBP. 6867c478bd9Sstevel@tonic-gate */ 6877c478bd9Sstevel@tonic-gate return (strlen(data) + 1); 6887c478bd9Sstevel@tonic-gate 6897c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_GET_DSIZE: 6907c478bd9Sstevel@tonic-gate /* 6917c478bd9Sstevel@tonic-gate * Return the string length plus one for the NULL 6927c478bd9Sstevel@tonic-gate * We know the size of the property, we need to 6937c478bd9Sstevel@tonic-gate * ensure that the string is properly formatted, 6947c478bd9Sstevel@tonic-gate * since we may be looking up random OBP data. 6957c478bd9Sstevel@tonic-gate */ 6967c478bd9Sstevel@tonic-gate p = (char *)ph->ph_cur_pos; 6977c478bd9Sstevel@tonic-gate end = (char *)ph->ph_data + ph->ph_size; 6987c478bd9Sstevel@tonic-gate for (n = 0; p < end; n++) { 6997c478bd9Sstevel@tonic-gate if (*p++ == '\0') { 7007c478bd9Sstevel@tonic-gate ph->ph_cur_pos = p; 7017c478bd9Sstevel@tonic-gate return (n+1); 7027c478bd9Sstevel@tonic-gate } 7037c478bd9Sstevel@tonic-gate } 7047c478bd9Sstevel@tonic-gate 7057c478bd9Sstevel@tonic-gate /* 7067c478bd9Sstevel@tonic-gate * Add check here to separate EOF and ERROR. 7077c478bd9Sstevel@tonic-gate */ 7087c478bd9Sstevel@tonic-gate if (p == end) 7097c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_EOF); 7107c478bd9Sstevel@tonic-gate 7117c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 7127c478bd9Sstevel@tonic-gate 7137c478bd9Sstevel@tonic-gate } 7147c478bd9Sstevel@tonic-gate 7157c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 7167c478bd9Sstevel@tonic-gate return (0); /* keep gcc happy */ 7177c478bd9Sstevel@tonic-gate } 7187c478bd9Sstevel@tonic-gate 7197c478bd9Sstevel@tonic-gate /* 7207c478bd9Sstevel@tonic-gate * OBP 1275 byte operator 7217c478bd9Sstevel@tonic-gate * 7227c478bd9Sstevel@tonic-gate * Caller must specify the number of bytes to get. OBP encodes bytes 7237c478bd9Sstevel@tonic-gate * as a byte so there is a 1-to-1 translation. 7247c478bd9Sstevel@tonic-gate */ 7257c478bd9Sstevel@tonic-gate int 7267c478bd9Sstevel@tonic-gate di_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data, 7277c478bd9Sstevel@tonic-gate uint_t nelements) 7287c478bd9Sstevel@tonic-gate { 7297c478bd9Sstevel@tonic-gate switch (cmd) { 7307c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_DECODE: 7317c478bd9Sstevel@tonic-gate /* 7327c478bd9Sstevel@tonic-gate * Check that there is encoded data 7337c478bd9Sstevel@tonic-gate */ 7347c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 7357c478bd9Sstevel@tonic-gate ph->ph_size < nelements || 7367c478bd9Sstevel@tonic-gate ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 7377c478bd9Sstevel@tonic-gate ph->ph_size - nelements))) 7387c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 7397c478bd9Sstevel@tonic-gate 7407c478bd9Sstevel@tonic-gate /* 7417c478bd9Sstevel@tonic-gate * Copy out the bytes 7427c478bd9Sstevel@tonic-gate */ 7437c478bd9Sstevel@tonic-gate bcopy((char *)ph->ph_cur_pos, (char *)data, nelements); 7447c478bd9Sstevel@tonic-gate 7457c478bd9Sstevel@tonic-gate /* 7467c478bd9Sstevel@tonic-gate * Move the current location 7477c478bd9Sstevel@tonic-gate */ 7487c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 7497c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 7507c478bd9Sstevel@tonic-gate 7517c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_ENCODE: 7527c478bd9Sstevel@tonic-gate /* 7537c478bd9Sstevel@tonic-gate * Check that there is room to encode the data 7547c478bd9Sstevel@tonic-gate */ 7557c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 7567c478bd9Sstevel@tonic-gate ph->ph_size < nelements || 7577c478bd9Sstevel@tonic-gate ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 7587c478bd9Sstevel@tonic-gate ph->ph_size - nelements))) 7597c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 7607c478bd9Sstevel@tonic-gate 7617c478bd9Sstevel@tonic-gate /* 7627c478bd9Sstevel@tonic-gate * Copy in the bytes 7637c478bd9Sstevel@tonic-gate */ 7647c478bd9Sstevel@tonic-gate bcopy((char *)data, (char *)ph->ph_cur_pos, nelements); 7657c478bd9Sstevel@tonic-gate 7667c478bd9Sstevel@tonic-gate /* 7677c478bd9Sstevel@tonic-gate * Move the current location to the start of the next bit of 7687c478bd9Sstevel@tonic-gate * space where we can store encoded data. 7697c478bd9Sstevel@tonic-gate */ 7707c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 7717c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 7727c478bd9Sstevel@tonic-gate 7737c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_SKIP: 7747c478bd9Sstevel@tonic-gate /* 7757c478bd9Sstevel@tonic-gate * Check that there is encoded data 7767c478bd9Sstevel@tonic-gate */ 7777c478bd9Sstevel@tonic-gate if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 7787c478bd9Sstevel@tonic-gate ph->ph_size < nelements) 7797c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_ERROR); 7807c478bd9Sstevel@tonic-gate 7817c478bd9Sstevel@tonic-gate if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 7827c478bd9Sstevel@tonic-gate ph->ph_size - nelements)) 7837c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_EOF); 7847c478bd9Sstevel@tonic-gate 7857c478bd9Sstevel@tonic-gate /* 7867c478bd9Sstevel@tonic-gate * Move the current location 7877c478bd9Sstevel@tonic-gate */ 7887c478bd9Sstevel@tonic-gate ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 7897c478bd9Sstevel@tonic-gate return (DDI_PROP_RESULT_OK); 7907c478bd9Sstevel@tonic-gate 7917c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_GET_ESIZE: 7927c478bd9Sstevel@tonic-gate /* 7937c478bd9Sstevel@tonic-gate * The size in bytes of the encoded size is the 7947c478bd9Sstevel@tonic-gate * same as the decoded size provided by the caller. 7957c478bd9Sstevel@tonic-gate */ 7967c478bd9Sstevel@tonic-gate return (nelements); 7977c478bd9Sstevel@tonic-gate 7987c478bd9Sstevel@tonic-gate case DDI_PROP_CMD_GET_DSIZE: 7997c478bd9Sstevel@tonic-gate /* 8007c478bd9Sstevel@tonic-gate * Just return the number of bytes specified by the caller. 8017c478bd9Sstevel@tonic-gate */ 8027c478bd9Sstevel@tonic-gate return (nelements); 8037c478bd9Sstevel@tonic-gate 8047c478bd9Sstevel@tonic-gate } 8057c478bd9Sstevel@tonic-gate 8067c478bd9Sstevel@tonic-gate /*NOTREACHED*/ 8077c478bd9Sstevel@tonic-gate return (0); /* keep gcc happy */ 8087c478bd9Sstevel@tonic-gate } 8097c478bd9Sstevel@tonic-gate 8107c478bd9Sstevel@tonic-gate /* 8117c478bd9Sstevel@tonic-gate * Used for properties that come from the OBP, hardware configuration files, 8127c478bd9Sstevel@tonic-gate * or that are created by calls to ddi_prop_update(9F). 8137c478bd9Sstevel@tonic-gate */ 8147c478bd9Sstevel@tonic-gate static struct prop_handle_ops prop_1275_ops = { 8157c478bd9Sstevel@tonic-gate di_prop_1275_int, 8167c478bd9Sstevel@tonic-gate di_prop_1275_string, 8177c478bd9Sstevel@tonic-gate di_prop_1275_bytes, 8187c478bd9Sstevel@tonic-gate di_prop_int64_op 8197c478bd9Sstevel@tonic-gate }; 8207c478bd9Sstevel@tonic-gate 8217c478bd9Sstevel@tonic-gate /* 8227c478bd9Sstevel@tonic-gate * Now the real thing: 8237c478bd9Sstevel@tonic-gate * Extract type-specific values of an property 8247c478bd9Sstevel@tonic-gate */ 8257c478bd9Sstevel@tonic-gate int 8267c478bd9Sstevel@tonic-gate di_prop_decode_common(void *data, int size, int prop_type, int prom) 8277c478bd9Sstevel@tonic-gate { 8287c478bd9Sstevel@tonic-gate int n; 8297c478bd9Sstevel@tonic-gate int nelements; 8307c478bd9Sstevel@tonic-gate char *cp, *end; 8317c478bd9Sstevel@tonic-gate prop_handle_t ph; 8327c478bd9Sstevel@tonic-gate int (*prop_decoder)(prop_handle_t *, void *, uint_t *); 8337c478bd9Sstevel@tonic-gate 8347c478bd9Sstevel@tonic-gate /* 8357c478bd9Sstevel@tonic-gate * If the encoded data came from software, no decoding needed 8367c478bd9Sstevel@tonic-gate */ 8377c478bd9Sstevel@tonic-gate if (!prom) { 8387c478bd9Sstevel@tonic-gate switch (prop_type) { 8397c478bd9Sstevel@tonic-gate case DI_PROP_TYPE_INT: 8407c478bd9Sstevel@tonic-gate if (size % sizeof (int)) 8417c478bd9Sstevel@tonic-gate nelements = -1; 8427c478bd9Sstevel@tonic-gate else 8437c478bd9Sstevel@tonic-gate nelements = size / sizeof (int); 8447c478bd9Sstevel@tonic-gate break; 8457c478bd9Sstevel@tonic-gate 8467c478bd9Sstevel@tonic-gate case DI_PROP_TYPE_INT64: 8477c478bd9Sstevel@tonic-gate if (size % sizeof (int64_t)) 8487c478bd9Sstevel@tonic-gate nelements = -1; 8497c478bd9Sstevel@tonic-gate else 8507c478bd9Sstevel@tonic-gate nelements = size / sizeof (int64_t); 8517c478bd9Sstevel@tonic-gate break; 8527c478bd9Sstevel@tonic-gate 8537c478bd9Sstevel@tonic-gate case DI_PROP_TYPE_STRING: 8547c478bd9Sstevel@tonic-gate nelements = 0; 8557c478bd9Sstevel@tonic-gate cp = *(char **)data; 8567c478bd9Sstevel@tonic-gate end = cp + size; 8577c478bd9Sstevel@tonic-gate /* 8587c478bd9Sstevel@tonic-gate * Don't trust the data passed in by the caller. 8597c478bd9Sstevel@tonic-gate * Check every char to make sure it is indeed a 8607c478bd9Sstevel@tonic-gate * string property. 8617c478bd9Sstevel@tonic-gate */ 8627c478bd9Sstevel@tonic-gate while (cp < end) { 8637c478bd9Sstevel@tonic-gate /* skip to next non-printable char */ 8647c478bd9Sstevel@tonic-gate for (n = 0; cp < end && 8657c478bd9Sstevel@tonic-gate isascii(*cp) && !iscntrl(*cp); n++, cp++) 8667c478bd9Sstevel@tonic-gate ; 8677c478bd9Sstevel@tonic-gate 8687c478bd9Sstevel@tonic-gate /* 8697c478bd9Sstevel@tonic-gate * Fail if reached end (i.e. last char != 0), 8707c478bd9Sstevel@tonic-gate * or has a non-printable char. A zero length 8717c478bd9Sstevel@tonic-gate * string is acceptable. 8727c478bd9Sstevel@tonic-gate */ 8737c478bd9Sstevel@tonic-gate if (cp == end || *cp != 0) { 8747c478bd9Sstevel@tonic-gate nelements = -1; 8757c478bd9Sstevel@tonic-gate break; 8767c478bd9Sstevel@tonic-gate } 8777c478bd9Sstevel@tonic-gate /* 8787c478bd9Sstevel@tonic-gate * Increment # strings and keep going 8797c478bd9Sstevel@tonic-gate */ 8807c478bd9Sstevel@tonic-gate nelements++; 8817c478bd9Sstevel@tonic-gate cp++; 8827c478bd9Sstevel@tonic-gate } 8837c478bd9Sstevel@tonic-gate 8847c478bd9Sstevel@tonic-gate break; 8857c478bd9Sstevel@tonic-gate 8867c478bd9Sstevel@tonic-gate case DI_PROP_TYPE_BYTE: 8877c478bd9Sstevel@tonic-gate nelements = size; 8887c478bd9Sstevel@tonic-gate } 8897c478bd9Sstevel@tonic-gate 8907c478bd9Sstevel@tonic-gate return (nelements); 8917c478bd9Sstevel@tonic-gate } 8927c478bd9Sstevel@tonic-gate 8937c478bd9Sstevel@tonic-gate /* 8947c478bd9Sstevel@tonic-gate * Get the encoded data 8957c478bd9Sstevel@tonic-gate */ 8967c478bd9Sstevel@tonic-gate bzero((caddr_t)&ph, sizeof (prop_handle_t)); 8977c478bd9Sstevel@tonic-gate ph.ph_data = *(uchar_t **)data; 8987c478bd9Sstevel@tonic-gate ph.ph_size = size; 8997c478bd9Sstevel@tonic-gate 9007c478bd9Sstevel@tonic-gate /* 9017c478bd9Sstevel@tonic-gate * The data came from prom, use the 1275 OBP decode/encode routines. 9027c478bd9Sstevel@tonic-gate */ 9037c478bd9Sstevel@tonic-gate ph.ph_cur_pos = ph.ph_data; 9047c478bd9Sstevel@tonic-gate ph.ph_save_pos = ph.ph_data; 9057c478bd9Sstevel@tonic-gate ph.ph_ops = &prop_1275_ops; 9067c478bd9Sstevel@tonic-gate ph.ph_flags = PH_FROM_PROM; 9077c478bd9Sstevel@tonic-gate 9087c478bd9Sstevel@tonic-gate switch (prop_type) { 9097c478bd9Sstevel@tonic-gate case DI_PROP_TYPE_INT: 9107c478bd9Sstevel@tonic-gate prop_decoder = di_prop_fm_decode_ints; 9117c478bd9Sstevel@tonic-gate break; 9127c478bd9Sstevel@tonic-gate case DI_PROP_TYPE_STRING: 9137c478bd9Sstevel@tonic-gate prop_decoder = di_prop_fm_decode_strings; 9147c478bd9Sstevel@tonic-gate break; 9157c478bd9Sstevel@tonic-gate case DI_PROP_TYPE_BYTE: 9167c478bd9Sstevel@tonic-gate default: 9177c478bd9Sstevel@tonic-gate prop_decoder = di_prop_fm_decode_bytes; 9187c478bd9Sstevel@tonic-gate break; 9197c478bd9Sstevel@tonic-gate } 9207c478bd9Sstevel@tonic-gate 9217c478bd9Sstevel@tonic-gate if ((*prop_decoder)(&ph, data, (uint_t *)&nelements) 9227c478bd9Sstevel@tonic-gate != DDI_PROP_SUCCESS) 9237c478bd9Sstevel@tonic-gate return (-1); 9247c478bd9Sstevel@tonic-gate 9257c478bd9Sstevel@tonic-gate /* 9267c478bd9Sstevel@tonic-gate * Free the encoded data 9277c478bd9Sstevel@tonic-gate */ 9287c478bd9Sstevel@tonic-gate if (size != 0) 9297c478bd9Sstevel@tonic-gate free(ph.ph_data); 9307c478bd9Sstevel@tonic-gate 9317c478bd9Sstevel@tonic-gate return (nelements); 9327c478bd9Sstevel@tonic-gate } 9337c478bd9Sstevel@tonic-gate 934*3ebafc43Sjveta void 935*3ebafc43Sjveta di_slot_names_free(int count, di_slot_name_t *slot_names) 936*3ebafc43Sjveta { 937*3ebafc43Sjveta if (slot_names == NULL) 938*3ebafc43Sjveta return; 939*3ebafc43Sjveta 940*3ebafc43Sjveta while (--count >= 0) { 941*3ebafc43Sjveta if (slot_names[count].name != NULL) 942*3ebafc43Sjveta free(slot_names[count].name); 943*3ebafc43Sjveta } 944*3ebafc43Sjveta free(slot_names); 945*3ebafc43Sjveta } 946*3ebafc43Sjveta 947*3ebafc43Sjveta /* 948*3ebafc43Sjveta * 1275 "slot-names" format: [int][string1][string2]...[stringN] 949*3ebafc43Sjveta * - [int] is a 1275 encoded integer 950*3ebafc43Sjveta * - [string1]...[stringN] are concatenated null-terminated strings 951*3ebafc43Sjveta * - each bit position in [int] represents a pci device number 952*3ebafc43Sjveta * - each bit which is set in [int] represents a slot with a device 953*3ebafc43Sjveta * number of that bit position 954*3ebafc43Sjveta * - each string in [string1]...[stringN] identifies a slot name only 955*3ebafc43Sjveta * for the bits which are set in [int] 956*3ebafc43Sjveta * - the ordering of strings follow the ordering of bits set in [int] 957*3ebafc43Sjveta * 958*3ebafc43Sjveta * an allocated array of di_slot_name_t is returned through prop_data if 959*3ebafc43Sjveta * [int] is non-zero and the number of entries as the return value; 960*3ebafc43Sjveta * use di_slot_names_free() to free the array 961*3ebafc43Sjveta */ 962*3ebafc43Sjveta int 963*3ebafc43Sjveta di_slot_names_decode(uchar_t *rawdata, int rawlen, 964*3ebafc43Sjveta di_slot_name_t **prop_data) 965*3ebafc43Sjveta { 966*3ebafc43Sjveta char *sp, *maxsp; 967*3ebafc43Sjveta int count, i; 968*3ebafc43Sjveta size_t len; 969*3ebafc43Sjveta int slots; 970*3ebafc43Sjveta int maxcount = 0; 971*3ebafc43Sjveta int maxslots = 0; 972*3ebafc43Sjveta di_slot_name_t *slot_names = NULL; 973*3ebafc43Sjveta 974*3ebafc43Sjveta if (rawlen < sizeof (slots)) 975*3ebafc43Sjveta goto ERROUT; 976*3ebafc43Sjveta 977*3ebafc43Sjveta slots = impl_di_prop_int_from_prom(rawdata, sizeof (slots)); 978*3ebafc43Sjveta if (slots == 0) { 979*3ebafc43Sjveta *prop_data = NULL; 980*3ebafc43Sjveta return (0); 981*3ebafc43Sjveta } 982*3ebafc43Sjveta 983*3ebafc43Sjveta maxslots = sizeof (slots) * 8; 984*3ebafc43Sjveta count = 0; 985*3ebafc43Sjveta for (i = 0; i < maxslots; i++) { 986*3ebafc43Sjveta if (slots & (1 << i)) 987*3ebafc43Sjveta count++; 988*3ebafc43Sjveta } 989*3ebafc43Sjveta maxslots = i; 990*3ebafc43Sjveta maxcount = count; 991*3ebafc43Sjveta slot_names = malloc(sizeof (*slot_names) * maxcount); 992*3ebafc43Sjveta bzero(slot_names, sizeof (*slot_names) * maxcount); 993*3ebafc43Sjveta 994*3ebafc43Sjveta /* also handle unterminated strings */ 995*3ebafc43Sjveta sp = (char *)(rawdata + sizeof (slots)); 996*3ebafc43Sjveta maxsp = sp + (rawlen - sizeof (slots)); 997*3ebafc43Sjveta count = 0; 998*3ebafc43Sjveta for (i = 0; i < maxslots; i++) { 999*3ebafc43Sjveta if (slots & (1 << i)) { 1000*3ebafc43Sjveta if (sp > maxsp) 1001*3ebafc43Sjveta break; 1002*3ebafc43Sjveta len = strnlen(sp, (maxsp - sp) + 1); 1003*3ebafc43Sjveta if (len == 0) 1004*3ebafc43Sjveta break; 1005*3ebafc43Sjveta 1006*3ebafc43Sjveta slot_names[count].name = 1007*3ebafc43Sjveta malloc(sizeof (char) * (len + 1)); 1008*3ebafc43Sjveta (void) strlcpy(slot_names[count].name, sp, len + 1); 1009*3ebafc43Sjveta 1010*3ebafc43Sjveta slot_names[count].num = i; 1011*3ebafc43Sjveta 1012*3ebafc43Sjveta sp += len + 1; 1013*3ebafc43Sjveta count++; 1014*3ebafc43Sjveta } 1015*3ebafc43Sjveta } 1016*3ebafc43Sjveta 1017*3ebafc43Sjveta /* 1018*3ebafc43Sjveta * check if the number of strings match with the number of slots; 1019*3ebafc43Sjveta * we can also get a lesser string count even when there appears to be 1020*3ebafc43Sjveta * the correct number of strings if one or more pair of strings are 1021*3ebafc43Sjveta * seperated by more than one NULL byte 1022*3ebafc43Sjveta */ 1023*3ebafc43Sjveta if (count != maxcount) 1024*3ebafc43Sjveta goto ERROUT; 1025*3ebafc43Sjveta 1026*3ebafc43Sjveta *prop_data = slot_names; 1027*3ebafc43Sjveta return (maxcount); 1028*3ebafc43Sjveta /*NOTREACHED*/ 1029*3ebafc43Sjveta ERROUT: 1030*3ebafc43Sjveta di_slot_names_free(maxcount, slot_names); 1031*3ebafc43Sjveta *prop_data = NULL; 1032*3ebafc43Sjveta return (-1); 1033*3ebafc43Sjveta } 1034