4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
27 * This file contains kernel property decode routines adopted from
28 * sunddi.c and ddi_impl.c. The following changes have been applied.
30 * (1) Replace kmem_alloc by malloc. Remove negative indexing
31 * (2) Decoding applies only to prom properties.
32 * (3) For strings, the return value is a composite string, not a string array.
33 * (4) impl_ddi_prop_int_from_prom() uses _LITTLE_ENDIAN from isa_defs.h
35 * XXX This file should be kept in sync with kernel property encoding.
42 #include <sys/types.h>
43 #include <sys/dditypes.h>
44 #include <sys/ddipropdefs.h>
45 #include <sys/isa_defs.h>
47 #include "libdevinfo.h"
50 * Return an integer in native machine format from an OBP 1275 integer
51 * representation, which is big-endian, with no particular alignment
52 * guarantees. intp points to the OBP data, and n the number of bytes.
54 * Byte-swapping may be needed on some implementations.
57 impl_di_prop_int_from_prom(uchar_t
*intp
, int n
)
61 #if defined(_LITTLE_ENDIAN)
64 i
= (i
<< 8) | *(--intp
);
68 i
= (i
<< 8) | *intp
++;
70 #endif /* defined(_LITTLE_ENDIAN) */
76 * Reset the current location pointer in the property handle to the
77 * beginning of the data.
80 di_prop_reset_pos(prop_handle_t
*ph
)
82 ph
->ph_cur_pos
= ph
->ph_data
;
83 ph
->ph_save_pos
= ph
->ph_data
;
87 * Restore the current location pointer in the property handle to the
91 di_prop_save_pos(prop_handle_t
*ph
)
93 ph
->ph_save_pos
= ph
->ph_cur_pos
;
97 * Save the location that the current location poiner is pointing to..
100 di_prop_restore_pos(prop_handle_t
*ph
)
102 ph
->ph_cur_pos
= ph
->ph_save_pos
;
106 * Property encode/decode functions
110 * Decode an array of integers property
113 di_prop_fm_decode_ints(prop_handle_t
*ph
, void *data
, uint_t
*nelements
)
122 * Figure out how many array elements there are by going through the
123 * data without decoding it first and counting.
126 i
= DDI_PROP_INT(ph
, DDI_PROP_CMD_SKIP
, NULL
);
133 * If there are no elements return an error
136 return (DDI_PROP_END_OF_DATA
);
139 * If we cannot skip through the data, we cannot decode it
141 if (i
== DDI_PROP_RESULT_ERROR
)
142 return (DDI_PROP_CANNOT_DECODE
);
145 * Reset the data pointer to the beginning of the encoded data
147 di_prop_reset_pos(ph
);
150 * Allocated memory to store the decoded value in.
152 if ((intp
= malloc(cnt
* sizeof (int))) == NULL
) {
153 return (DDI_PROP_CANNOT_DECODE
);
158 * Decode each elemente and place it in the space we just allocated
161 for (n
= 0; n
< cnt
; n
++, tmp
++) {
162 i
= DDI_PROP_INT(ph
, DDI_PROP_CMD_DECODE
, tmp
);
163 if (i
< DDI_PROP_RESULT_OK
) {
165 * Free the space we just allocated
166 * and return an error.
170 case DDI_PROP_RESULT_EOF
:
171 return (DDI_PROP_END_OF_DATA
);
173 case DDI_PROP_RESULT_ERROR
:
174 return (DDI_PROP_CANNOT_DECODE
);
180 *(int **)data
= intp
;
182 return (DDI_PROP_SUCCESS
);
186 * Decode an array of strings.
189 di_prop_fm_decode_strings(prop_handle_t
*ph
, void *data
, uint_t
*nelements
)
200 * Figure out how much memory we need for the sum total
206 * Get the decoded size of the current encoded string.
208 size
= DDI_PROP_STR(ph
, DDI_PROP_CMD_GET_DSIZE
, NULL
);
217 * If there are no elements return an error
220 return (DDI_PROP_END_OF_DATA
);
223 * If we cannot skip through the data, we cannot decode it
225 if (size
== DDI_PROP_RESULT_ERROR
)
226 return (DDI_PROP_CANNOT_DECODE
);
229 * Allocate memory in which to store the decoded strings.
231 if ((strs
= malloc(nbytes
)) == NULL
) {
232 return (DDI_PROP_CANNOT_DECODE
);
236 * Finally, we can decode each string
238 di_prop_reset_pos(ph
);
240 for (n
= 0; n
< cnt
; n
++) {
241 i
= DDI_PROP_STR(ph
, DDI_PROP_CMD_DECODE
, tmp
);
242 if (i
< DDI_PROP_RESULT_OK
) {
244 * Free the space we just allocated
245 * and return an error
249 case DDI_PROP_RESULT_EOF
:
250 return (DDI_PROP_END_OF_DATA
);
252 case DDI_PROP_RESULT_ERROR
:
253 return (DDI_PROP_CANNOT_DECODE
);
256 tmp
+= strlen(tmp
) + 1;
259 *(char **)data
= strs
;
262 return (DDI_PROP_SUCCESS
);
266 * Decode an array of bytes.
269 di_prop_fm_decode_bytes(prop_handle_t
*ph
, void *data
, uint_t
*nelements
)
276 * If there are no elements return an error
278 if (ph
->ph_size
== 0)
279 return (DDI_PROP_END_OF_DATA
);
282 * Get the size of the encoded array of bytes.
284 nbytes
= DDI_PROP_BYTES(ph
, DDI_PROP_CMD_GET_DSIZE
,
286 if (nbytes
< DDI_PROP_RESULT_OK
) {
288 case DDI_PROP_RESULT_EOF
:
289 return (DDI_PROP_END_OF_DATA
);
291 case DDI_PROP_RESULT_ERROR
:
292 return (DDI_PROP_CANNOT_DECODE
);
297 * Allocated memory to store the decoded value in.
299 if ((tmp
= malloc(nbytes
)) == NULL
) {
300 return (DDI_PROP_CANNOT_DECODE
);
304 * Decode each element and place it in the space we just allocated
306 i
= DDI_PROP_BYTES(ph
, DDI_PROP_CMD_DECODE
, tmp
, nbytes
);
307 if (i
< DDI_PROP_RESULT_OK
) {
309 * Free the space we just allocated
310 * and return an error
314 case DDI_PROP_RESULT_EOF
:
315 return (DDI_PROP_END_OF_DATA
);
317 case DDI_PROP_RESULT_ERROR
:
318 return (DDI_PROP_CANNOT_DECODE
);
322 *(uchar_t
**)data
= tmp
;
325 return (DDI_PROP_SUCCESS
);
329 * OBP 1275 integer, string and byte operators.
331 * DDI_PROP_CMD_DECODE:
333 * DDI_PROP_RESULT_ERROR: cannot decode the data
334 * DDI_PROP_RESULT_EOF: end of data
335 * DDI_PROP_OK: data was decoded
337 * DDI_PROP_CMD_ENCODE:
339 * DDI_PROP_RESULT_ERROR: cannot encode the data
340 * DDI_PROP_RESULT_EOF: end of data
341 * DDI_PROP_OK: data was encoded
345 * DDI_PROP_RESULT_ERROR: cannot skip the data
346 * DDI_PROP_RESULT_EOF: end of data
347 * DDI_PROP_OK: data was skipped
349 * DDI_PROP_CMD_GET_ESIZE:
351 * DDI_PROP_RESULT_ERROR: cannot get encoded size
352 * DDI_PROP_RESULT_EOF: end of data
353 * > 0: the encoded size
355 * DDI_PROP_CMD_GET_DSIZE:
357 * DDI_PROP_RESULT_ERROR: cannot get decoded size
358 * DDI_PROP_RESULT_EOF: end of data
359 * > 0: the decoded size
363 * OBP 1275 integer operator
365 * OBP properties are a byte stream of data, so integers may not be
366 * properly aligned. Therefore we need to copy them one byte at a time.
369 di_prop_1275_int(prop_handle_t
*ph
, uint_t cmd
, int *data
)
374 case DDI_PROP_CMD_DECODE
:
376 * Check that there is encoded data
378 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0)
379 return (DDI_PROP_RESULT_ERROR
);
380 if (ph
->ph_flags
& PH_FROM_PROM
) {
381 i
= ph
->ph_size
< PROP_1275_INT_SIZE
?
382 ph
->ph_size
: PROP_1275_INT_SIZE
;
383 if ((int *)ph
->ph_cur_pos
> ((int *)ph
->ph_data
+
385 return (DDI_PROP_RESULT_ERROR
);
386 } else if (ph
->ph_size
< sizeof (int) ||
387 ((int *)ph
->ph_cur_pos
> ((int *)ph
->ph_data
+
388 ph
->ph_size
- sizeof (int)))) {
389 return (DDI_PROP_RESULT_ERROR
);
393 * Copy the integer, using the implementation-specific
394 * copy function if the property is coming from the PROM.
396 if (ph
->ph_flags
& PH_FROM_PROM
) {
397 *data
= impl_di_prop_int_from_prom(
398 (uchar_t
*)ph
->ph_cur_pos
,
399 (ph
->ph_size
< PROP_1275_INT_SIZE
) ?
400 ph
->ph_size
: PROP_1275_INT_SIZE
);
402 bcopy(ph
->ph_cur_pos
, (caddr_t
)data
, sizeof (int));
406 * Move the current location to the start of the next
407 * bit of undecoded data.
409 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+ PROP_1275_INT_SIZE
;
410 return (DDI_PROP_RESULT_OK
);
412 case DDI_PROP_CMD_ENCODE
:
414 * Check that there is room to encoded the data
416 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
417 ph
->ph_size
< PROP_1275_INT_SIZE
||
418 ((int *)ph
->ph_cur_pos
> ((int *)ph
->ph_data
+
419 ph
->ph_size
- sizeof (int))))
420 return (DDI_PROP_RESULT_ERROR
);
423 * Encode the integer into the byte stream one byte at a
426 bcopy((caddr_t
)data
, ph
->ph_cur_pos
, sizeof (int));
429 * Move the current location to the start of the next bit of
430 * space where we can store encoded data.
432 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+ PROP_1275_INT_SIZE
;
433 return (DDI_PROP_RESULT_OK
);
435 case DDI_PROP_CMD_SKIP
:
437 * Check that there is encoded data
439 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
440 ph
->ph_size
< PROP_1275_INT_SIZE
)
441 return (DDI_PROP_RESULT_ERROR
);
444 if ((caddr_t
)ph
->ph_cur_pos
==
445 (caddr_t
)ph
->ph_data
+ ph
->ph_size
) {
446 return (DDI_PROP_RESULT_EOF
);
447 } else if ((caddr_t
)ph
->ph_cur_pos
>
448 (caddr_t
)ph
->ph_data
+ ph
->ph_size
) {
449 return (DDI_PROP_RESULT_EOF
);
453 * Move the current location to the start of the next bit of
456 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+ PROP_1275_INT_SIZE
;
457 return (DDI_PROP_RESULT_OK
);
459 case DDI_PROP_CMD_GET_ESIZE
:
461 * Return the size of an encoded integer on OBP
463 return (PROP_1275_INT_SIZE
);
465 case DDI_PROP_CMD_GET_DSIZE
:
467 * Return the size of a decoded integer on the system.
469 return (sizeof (int));
473 return (0); /* keep gcc happy */
477 * 64 bit integer operator
479 * This is an extension, defined by Sun, to the 1275 integer
480 * operator. This routine handles the encoding/decoding of
481 * 64 bit integer properties.
484 di_prop_int64_op(prop_handle_t
*ph
, uint_t cmd
, int64_t *data
)
487 case DDI_PROP_CMD_DECODE
:
489 * Check that there is encoded data
491 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0)
492 return (DDI_PROP_RESULT_ERROR
);
493 if (ph
->ph_flags
& PH_FROM_PROM
) {
494 return (DDI_PROP_RESULT_ERROR
);
495 } else if (ph
->ph_size
< sizeof (int64_t) ||
496 ((int64_t *)ph
->ph_cur_pos
> ((int64_t *)ph
->ph_data
+
497 ph
->ph_size
- sizeof (int64_t)))) {
498 return (DDI_PROP_RESULT_ERROR
);
502 * Copy the integer, using the implementation-specific
503 * copy function if the property is coming from the PROM.
505 bcopy(ph
->ph_cur_pos
, (caddr_t
)data
, sizeof (int64_t));
508 * Move the current location to the start of the next
509 * bit of undecoded data.
511 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+
513 return (DDI_PROP_RESULT_OK
);
515 case DDI_PROP_CMD_ENCODE
:
517 * Check that there is room to encoded the data
519 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
520 ph
->ph_size
< sizeof (int64_t) ||
521 ((int64_t *)ph
->ph_cur_pos
> ((int64_t *)ph
->ph_data
+
522 ph
->ph_size
- sizeof (int64_t))))
523 return (DDI_PROP_RESULT_ERROR
);
526 * Encode the integer into the byte stream one byte at a
529 bcopy((caddr_t
)data
, ph
->ph_cur_pos
, sizeof (int64_t));
532 * Move the current location to the start of the next bit of
533 * space where we can store encoded data.
535 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+
537 return (DDI_PROP_RESULT_OK
);
539 case DDI_PROP_CMD_SKIP
:
541 * Check that there is encoded data
543 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
544 ph
->ph_size
< sizeof (int64_t))
545 return (DDI_PROP_RESULT_ERROR
);
548 if ((caddr_t
)ph
->ph_cur_pos
==
549 (caddr_t
)ph
->ph_data
+ ph
->ph_size
) {
550 return (DDI_PROP_RESULT_EOF
);
551 } else if ((caddr_t
)ph
->ph_cur_pos
>
552 (caddr_t
)ph
->ph_data
+ ph
->ph_size
) {
553 return (DDI_PROP_RESULT_EOF
);
557 * Move the current location to the start of the next bit of
560 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+
562 return (DDI_PROP_RESULT_OK
);
564 case DDI_PROP_CMD_GET_ESIZE
:
566 * Return the size of an encoded integer on OBP
568 return (sizeof (int64_t));
570 case DDI_PROP_CMD_GET_DSIZE
:
572 * Return the size of a decoded integer on the system.
574 return (sizeof (int64_t));
578 return (0); /* keep gcc happy */
582 * OBP 1275 string operator.
584 * OBP strings are NULL terminated.
587 di_prop_1275_string(prop_handle_t
*ph
, uint_t cmd
, char *data
)
594 case DDI_PROP_CMD_DECODE
:
596 * Check that there is encoded data
598 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0) {
599 return (DDI_PROP_RESULT_ERROR
);
602 n
= strlen((char *)ph
->ph_cur_pos
) + 1;
603 if ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
605 return (DDI_PROP_RESULT_ERROR
);
609 * Copy the NULL terminated string
611 bcopy((char *)ph
->ph_cur_pos
, data
, n
);
614 * Move the current location to the start of the next bit of
617 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ n
;
618 return (DDI_PROP_RESULT_OK
);
620 case DDI_PROP_CMD_ENCODE
:
622 * Check that there is room to encoded the data
624 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0) {
625 return (DDI_PROP_RESULT_ERROR
);
628 n
= strlen(data
) + 1;
629 if ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
631 return (DDI_PROP_RESULT_ERROR
);
635 * Copy the NULL terminated string
637 bcopy(data
, (char *)ph
->ph_cur_pos
, n
);
640 * Move the current location to the start of the next bit of
641 * space where we can store encoded data.
643 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ n
;
644 return (DDI_PROP_RESULT_OK
);
646 case DDI_PROP_CMD_SKIP
:
648 * Check that there is encoded data
650 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0) {
651 return (DDI_PROP_RESULT_ERROR
);
655 * Return the string length plus one for the NULL
656 * We know the size of the property, we need to
657 * ensure that the string is properly formatted,
658 * since we may be looking up random OBP data.
660 p
= (char *)ph
->ph_cur_pos
;
661 end
= (char *)ph
->ph_data
+ ph
->ph_size
;
664 return (DDI_PROP_RESULT_EOF
);
668 * Make sure each char is printable
670 for (n
= 0; p
< end
&& isascii(*p
) && !iscntrl(*p
); n
++, p
++)
673 /* Check termination and non-zero length */
674 if ((*p
== 0) && (n
!= 0)) {
675 ph
->ph_cur_pos
= p
+ 1;
676 return (DDI_PROP_RESULT_OK
);
679 return (DDI_PROP_RESULT_ERROR
);
681 case DDI_PROP_CMD_GET_ESIZE
:
683 * Return the size of the encoded string on OBP.
685 return (strlen(data
) + 1);
687 case DDI_PROP_CMD_GET_DSIZE
:
689 * Return the string length plus one for the NULL
690 * We know the size of the property, we need to
691 * ensure that the string is properly formatted,
692 * since we may be looking up random OBP data.
694 p
= (char *)ph
->ph_cur_pos
;
695 end
= (char *)ph
->ph_data
+ ph
->ph_size
;
696 for (n
= 0; p
< end
; n
++) {
704 * Add check here to separate EOF and ERROR.
707 return (DDI_PROP_RESULT_EOF
);
709 return (DDI_PROP_RESULT_ERROR
);
714 return (0); /* keep gcc happy */
718 * OBP 1275 byte operator
720 * Caller must specify the number of bytes to get. OBP encodes bytes
721 * as a byte so there is a 1-to-1 translation.
724 di_prop_1275_bytes(prop_handle_t
*ph
, uint_t cmd
, uchar_t
*data
,
728 case DDI_PROP_CMD_DECODE
:
730 * Check that there is encoded data
732 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
733 ph
->ph_size
< nelements
||
734 ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
735 ph
->ph_size
- nelements
)))
736 return (DDI_PROP_RESULT_ERROR
);
741 bcopy((char *)ph
->ph_cur_pos
, (char *)data
, nelements
);
744 * Move the current location
746 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ nelements
;
747 return (DDI_PROP_RESULT_OK
);
749 case DDI_PROP_CMD_ENCODE
:
751 * Check that there is room to encode the data
753 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
754 ph
->ph_size
< nelements
||
755 ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
756 ph
->ph_size
- nelements
)))
757 return (DDI_PROP_RESULT_ERROR
);
762 bcopy((char *)data
, (char *)ph
->ph_cur_pos
, nelements
);
765 * Move the current location to the start of the next bit of
766 * space where we can store encoded data.
768 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ nelements
;
769 return (DDI_PROP_RESULT_OK
);
771 case DDI_PROP_CMD_SKIP
:
773 * Check that there is encoded data
775 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
776 ph
->ph_size
< nelements
)
777 return (DDI_PROP_RESULT_ERROR
);
779 if ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
780 ph
->ph_size
- nelements
))
781 return (DDI_PROP_RESULT_EOF
);
784 * Move the current location
786 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ nelements
;
787 return (DDI_PROP_RESULT_OK
);
789 case DDI_PROP_CMD_GET_ESIZE
:
791 * The size in bytes of the encoded size is the
792 * same as the decoded size provided by the caller.
796 case DDI_PROP_CMD_GET_DSIZE
:
798 * Just return the number of bytes specified by the caller.
805 return (0); /* keep gcc happy */
809 * Used for properties that come from the OBP, hardware configuration files,
810 * or that are created by calls to ddi_prop_update(9F).
812 static struct prop_handle_ops prop_1275_ops
= {
820 * Now the real thing:
821 * Extract type-specific values of an property
824 di_prop_decode_common(void *data
, int size
, int prop_type
, int prom
)
830 int (*prop_decoder
)(prop_handle_t
*, void *, uint_t
*);
833 * If the encoded data came from software, no decoding needed
837 case DI_PROP_TYPE_INT
:
838 if (size
% sizeof (int))
841 nelements
= size
/ sizeof (int);
844 case DI_PROP_TYPE_INT64
:
845 if (size
% sizeof (int64_t))
848 nelements
= size
/ sizeof (int64_t);
851 case DI_PROP_TYPE_STRING
:
856 * Don't trust the data passed in by the caller.
857 * Check every char to make sure it is indeed a
861 /* skip to next non-printable char */
862 for (n
= 0; cp
< end
&&
863 isascii(*cp
) && !iscntrl(*cp
); n
++, cp
++)
867 * Fail if reached end (i.e. last char != 0),
868 * or has a non-printable char. A zero length
869 * string is acceptable.
871 if (cp
== end
|| *cp
!= 0) {
876 * Increment # strings and keep going
884 case DI_PROP_TYPE_BYTE
:
892 * Get the encoded data
894 bzero((caddr_t
)&ph
, sizeof (prop_handle_t
));
895 ph
.ph_data
= *(uchar_t
**)data
;
899 * The data came from prom, use the 1275 OBP decode/encode routines.
901 ph
.ph_cur_pos
= ph
.ph_data
;
902 ph
.ph_save_pos
= ph
.ph_data
;
903 ph
.ph_ops
= &prop_1275_ops
;
904 ph
.ph_flags
= PH_FROM_PROM
;
907 case DI_PROP_TYPE_INT
:
908 prop_decoder
= di_prop_fm_decode_ints
;
910 case DI_PROP_TYPE_STRING
:
911 prop_decoder
= di_prop_fm_decode_strings
;
913 case DI_PROP_TYPE_BYTE
:
915 prop_decoder
= di_prop_fm_decode_bytes
;
919 if ((*prop_decoder
)(&ph
, data
, (uint_t
*)&nelements
)
924 * Free the encoded data
933 di_slot_names_free(int count
, di_slot_name_t
*slot_names
)
935 if (slot_names
== NULL
)
938 while (--count
>= 0) {
939 free(slot_names
[count
].name
);
945 * 1275 "slot-names" format: [int][string1][string2]...[stringN]
946 * - [int] is a 1275 encoded integer
947 * - [string1]...[stringN] are concatenated null-terminated strings
948 * - each bit position in [int] represents a pci device number
949 * - each bit which is set in [int] represents a slot with a device
950 * number of that bit position
951 * - each string in [string1]...[stringN] identifies a slot name only
952 * for the bits which are set in [int]
953 * - the ordering of strings follow the ordering of bits set in [int]
955 * an allocated array of di_slot_name_t is returned through prop_data if
956 * [int] is non-zero and the number of entries as the return value;
957 * use di_slot_names_free() to free the array
960 di_slot_names_decode(uchar_t
*rawdata
, int rawlen
,
961 di_slot_name_t
**prop_data
)
969 di_slot_name_t
*slot_names
= NULL
;
971 if (rawlen
< sizeof (slots
))
974 slots
= impl_di_prop_int_from_prom(rawdata
, sizeof (slots
));
980 maxslots
= sizeof (slots
) * 8;
982 for (i
= 0; i
< maxslots
; i
++) {
983 if (slots
& (1 << i
))
988 slot_names
= malloc(sizeof (*slot_names
) * maxcount
);
989 bzero(slot_names
, sizeof (*slot_names
) * maxcount
);
991 /* also handle unterminated strings */
992 sp
= (char *)(rawdata
+ sizeof (slots
));
993 maxsp
= sp
+ (rawlen
- sizeof (slots
));
995 for (i
= 0; i
< maxslots
; i
++) {
996 if (slots
& (1 << i
)) {
999 len
= strnlen(sp
, (maxsp
- sp
) + 1);
1003 slot_names
[count
].name
=
1004 malloc(sizeof (char) * (len
+ 1));
1005 (void) strlcpy(slot_names
[count
].name
, sp
, len
+ 1);
1007 slot_names
[count
].num
= i
;
1015 * check if the number of strings match with the number of slots;
1016 * we can also get a lesser string count even when there appears to be
1017 * the correct number of strings if one or more pair of strings are
1018 * seperated by more than one NULL byte
1020 if (count
!= maxcount
)
1023 *prop_data
= slot_names
;
1027 di_slot_names_free(maxcount
, slot_names
);