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.
26 #pragma ident "%Z%%M% %I% %E% SMI"
29 * This file contains kernel property decode routines adopted from
30 * sunddi.c and ddi_impl.c. The following changes have been applied.
32 * (1) Replace kmem_alloc by malloc. Remove negative indexing
33 * (2) Decoding applies only to prom properties.
34 * (3) For strings, the return value is a composite string, not a string array.
35 * (4) impl_ddi_prop_int_from_prom() uses _LITTLE_ENDIAN from isa_defs.h
37 * XXX This file should be kept in sync with kernel property encoding.
44 #include <sys/types.h>
45 #include <sys/dditypes.h>
46 #include <sys/ddipropdefs.h>
47 #include <sys/isa_defs.h>
49 #include "libdevinfo.h"
52 * Return an integer in native machine format from an OBP 1275 integer
53 * representation, which is big-endian, with no particular alignment
54 * guarantees. intp points to the OBP data, and n the number of bytes.
56 * Byte-swapping may be needed on some implementations.
59 impl_di_prop_int_from_prom(uchar_t
*intp
, int n
)
63 #if defined(_LITTLE_ENDIAN)
66 i
= (i
<< 8) | *(--intp
);
70 i
= (i
<< 8) | *intp
++;
72 #endif /* defined(_LITTLE_ENDIAN) */
78 * Reset the current location pointer in the property handle to the
79 * beginning of the data.
82 di_prop_reset_pos(prop_handle_t
*ph
)
84 ph
->ph_cur_pos
= ph
->ph_data
;
85 ph
->ph_save_pos
= ph
->ph_data
;
89 * Restore the current location pointer in the property handle to the
93 di_prop_save_pos(prop_handle_t
*ph
)
95 ph
->ph_save_pos
= ph
->ph_cur_pos
;
99 * Save the location that the current location poiner is pointing to..
102 di_prop_restore_pos(prop_handle_t
*ph
)
104 ph
->ph_cur_pos
= ph
->ph_save_pos
;
108 * Property encode/decode functions
112 * Decode an array of integers property
115 di_prop_fm_decode_ints(prop_handle_t
*ph
, void *data
, uint_t
*nelements
)
124 * Figure out how many array elements there are by going through the
125 * data without decoding it first and counting.
128 i
= DDI_PROP_INT(ph
, DDI_PROP_CMD_SKIP
, NULL
);
135 * If there are no elements return an error
138 return (DDI_PROP_END_OF_DATA
);
141 * If we cannot skip through the data, we cannot decode it
143 if (i
== DDI_PROP_RESULT_ERROR
)
144 return (DDI_PROP_CANNOT_DECODE
);
147 * Reset the data pointer to the beginning of the encoded data
149 di_prop_reset_pos(ph
);
152 * Allocated memory to store the decoded value in.
154 if ((intp
= malloc(cnt
* sizeof (int))) == NULL
) {
155 return (DDI_PROP_CANNOT_DECODE
);
160 * Decode each elemente and place it in the space we just allocated
163 for (n
= 0; n
< cnt
; n
++, tmp
++) {
164 i
= DDI_PROP_INT(ph
, DDI_PROP_CMD_DECODE
, tmp
);
165 if (i
< DDI_PROP_RESULT_OK
) {
167 * Free the space we just allocated
168 * and return an error.
172 case DDI_PROP_RESULT_EOF
:
173 return (DDI_PROP_END_OF_DATA
);
175 case DDI_PROP_RESULT_ERROR
:
176 return (DDI_PROP_CANNOT_DECODE
);
182 *(int **)data
= intp
;
184 return (DDI_PROP_SUCCESS
);
188 * Decode an array of strings.
191 di_prop_fm_decode_strings(prop_handle_t
*ph
, void *data
, uint_t
*nelements
)
202 * Figure out how much memory we need for the sum total
208 * Get the decoded size of the current encoded string.
210 size
= DDI_PROP_STR(ph
, DDI_PROP_CMD_GET_DSIZE
, NULL
);
219 * If there are no elements return an error
222 return (DDI_PROP_END_OF_DATA
);
225 * If we cannot skip through the data, we cannot decode it
227 if (size
== DDI_PROP_RESULT_ERROR
)
228 return (DDI_PROP_CANNOT_DECODE
);
231 * Allocate memory in which to store the decoded strings.
233 if ((strs
= malloc(nbytes
)) == NULL
) {
234 return (DDI_PROP_CANNOT_DECODE
);
238 * Finally, we can decode each string
240 di_prop_reset_pos(ph
);
242 for (n
= 0; n
< cnt
; n
++) {
243 i
= DDI_PROP_STR(ph
, DDI_PROP_CMD_DECODE
, tmp
);
244 if (i
< DDI_PROP_RESULT_OK
) {
246 * Free the space we just allocated
247 * and return an error
251 case DDI_PROP_RESULT_EOF
:
252 return (DDI_PROP_END_OF_DATA
);
254 case DDI_PROP_RESULT_ERROR
:
255 return (DDI_PROP_CANNOT_DECODE
);
258 tmp
+= strlen(tmp
) + 1;
261 *(char **)data
= strs
;
264 return (DDI_PROP_SUCCESS
);
268 * Decode an array of bytes.
271 di_prop_fm_decode_bytes(prop_handle_t
*ph
, void *data
, uint_t
*nelements
)
278 * If there are no elements return an error
280 if (ph
->ph_size
== 0)
281 return (DDI_PROP_END_OF_DATA
);
284 * Get the size of the encoded array of bytes.
286 nbytes
= DDI_PROP_BYTES(ph
, DDI_PROP_CMD_GET_DSIZE
,
288 if (nbytes
< DDI_PROP_RESULT_OK
) {
290 case DDI_PROP_RESULT_EOF
:
291 return (DDI_PROP_END_OF_DATA
);
293 case DDI_PROP_RESULT_ERROR
:
294 return (DDI_PROP_CANNOT_DECODE
);
299 * Allocated memory to store the decoded value in.
301 if ((tmp
= malloc(nbytes
)) == NULL
) {
302 return (DDI_PROP_CANNOT_DECODE
);
306 * Decode each element and place it in the space we just allocated
308 i
= DDI_PROP_BYTES(ph
, DDI_PROP_CMD_DECODE
, tmp
, nbytes
);
309 if (i
< DDI_PROP_RESULT_OK
) {
311 * Free the space we just allocated
312 * and return an error
316 case DDI_PROP_RESULT_EOF
:
317 return (DDI_PROP_END_OF_DATA
);
319 case DDI_PROP_RESULT_ERROR
:
320 return (DDI_PROP_CANNOT_DECODE
);
324 *(uchar_t
**)data
= tmp
;
327 return (DDI_PROP_SUCCESS
);
331 * OBP 1275 integer, string and byte operators.
333 * DDI_PROP_CMD_DECODE:
335 * DDI_PROP_RESULT_ERROR: cannot decode the data
336 * DDI_PROP_RESULT_EOF: end of data
337 * DDI_PROP_OK: data was decoded
339 * DDI_PROP_CMD_ENCODE:
341 * DDI_PROP_RESULT_ERROR: cannot encode the data
342 * DDI_PROP_RESULT_EOF: end of data
343 * DDI_PROP_OK: data was encoded
347 * DDI_PROP_RESULT_ERROR: cannot skip the data
348 * DDI_PROP_RESULT_EOF: end of data
349 * DDI_PROP_OK: data was skipped
351 * DDI_PROP_CMD_GET_ESIZE:
353 * DDI_PROP_RESULT_ERROR: cannot get encoded size
354 * DDI_PROP_RESULT_EOF: end of data
355 * > 0: the encoded size
357 * DDI_PROP_CMD_GET_DSIZE:
359 * DDI_PROP_RESULT_ERROR: cannot get decoded size
360 * DDI_PROP_RESULT_EOF: end of data
361 * > 0: the decoded size
365 * OBP 1275 integer operator
367 * OBP properties are a byte stream of data, so integers may not be
368 * properly aligned. Therefore we need to copy them one byte at a time.
371 di_prop_1275_int(prop_handle_t
*ph
, uint_t cmd
, int *data
)
376 case DDI_PROP_CMD_DECODE
:
378 * Check that there is encoded data
380 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0)
381 return (DDI_PROP_RESULT_ERROR
);
382 if (ph
->ph_flags
& PH_FROM_PROM
) {
383 i
= ph
->ph_size
< PROP_1275_INT_SIZE
?
384 ph
->ph_size
: PROP_1275_INT_SIZE
;
385 if ((int *)ph
->ph_cur_pos
> ((int *)ph
->ph_data
+
387 return (DDI_PROP_RESULT_ERROR
);
388 } else if (ph
->ph_size
< sizeof (int) ||
389 ((int *)ph
->ph_cur_pos
> ((int *)ph
->ph_data
+
390 ph
->ph_size
- sizeof (int)))) {
391 return (DDI_PROP_RESULT_ERROR
);
395 * Copy the integer, using the implementation-specific
396 * copy function if the property is coming from the PROM.
398 if (ph
->ph_flags
& PH_FROM_PROM
) {
399 *data
= impl_di_prop_int_from_prom(
400 (uchar_t
*)ph
->ph_cur_pos
,
401 (ph
->ph_size
< PROP_1275_INT_SIZE
) ?
402 ph
->ph_size
: PROP_1275_INT_SIZE
);
404 bcopy(ph
->ph_cur_pos
, (caddr_t
)data
, sizeof (int));
408 * Move the current location to the start of the next
409 * bit of undecoded data.
411 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+ PROP_1275_INT_SIZE
;
412 return (DDI_PROP_RESULT_OK
);
414 case DDI_PROP_CMD_ENCODE
:
416 * Check that there is room to encoded the data
418 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
419 ph
->ph_size
< PROP_1275_INT_SIZE
||
420 ((int *)ph
->ph_cur_pos
> ((int *)ph
->ph_data
+
421 ph
->ph_size
- sizeof (int))))
422 return (DDI_PROP_RESULT_ERROR
);
425 * Encode the integer into the byte stream one byte at a
428 bcopy((caddr_t
)data
, ph
->ph_cur_pos
, sizeof (int));
431 * Move the current location to the start of the next bit of
432 * space where we can store encoded data.
434 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+ PROP_1275_INT_SIZE
;
435 return (DDI_PROP_RESULT_OK
);
437 case DDI_PROP_CMD_SKIP
:
439 * Check that there is encoded data
441 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
442 ph
->ph_size
< PROP_1275_INT_SIZE
)
443 return (DDI_PROP_RESULT_ERROR
);
446 if ((caddr_t
)ph
->ph_cur_pos
==
447 (caddr_t
)ph
->ph_data
+ ph
->ph_size
) {
448 return (DDI_PROP_RESULT_EOF
);
449 } else if ((caddr_t
)ph
->ph_cur_pos
>
450 (caddr_t
)ph
->ph_data
+ ph
->ph_size
) {
451 return (DDI_PROP_RESULT_EOF
);
455 * Move the current location to the start of the next bit of
458 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+ PROP_1275_INT_SIZE
;
459 return (DDI_PROP_RESULT_OK
);
461 case DDI_PROP_CMD_GET_ESIZE
:
463 * Return the size of an encoded integer on OBP
465 return (PROP_1275_INT_SIZE
);
467 case DDI_PROP_CMD_GET_DSIZE
:
469 * Return the size of a decoded integer on the system.
471 return (sizeof (int));
475 return (0); /* keep gcc happy */
479 * 64 bit integer operator
481 * This is an extension, defined by Sun, to the 1275 integer
482 * operator. This routine handles the encoding/decoding of
483 * 64 bit integer properties.
486 di_prop_int64_op(prop_handle_t
*ph
, uint_t cmd
, int64_t *data
)
489 case DDI_PROP_CMD_DECODE
:
491 * Check that there is encoded data
493 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0)
494 return (DDI_PROP_RESULT_ERROR
);
495 if (ph
->ph_flags
& PH_FROM_PROM
) {
496 return (DDI_PROP_RESULT_ERROR
);
497 } else if (ph
->ph_size
< sizeof (int64_t) ||
498 ((int64_t *)ph
->ph_cur_pos
> ((int64_t *)ph
->ph_data
+
499 ph
->ph_size
- sizeof (int64_t)))) {
500 return (DDI_PROP_RESULT_ERROR
);
504 * Copy the integer, using the implementation-specific
505 * copy function if the property is coming from the PROM.
507 bcopy(ph
->ph_cur_pos
, (caddr_t
)data
, sizeof (int64_t));
510 * Move the current location to the start of the next
511 * bit of undecoded data.
513 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+
515 return (DDI_PROP_RESULT_OK
);
517 case DDI_PROP_CMD_ENCODE
:
519 * Check that there is room to encoded the data
521 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
522 ph
->ph_size
< sizeof (int64_t) ||
523 ((int64_t *)ph
->ph_cur_pos
> ((int64_t *)ph
->ph_data
+
524 ph
->ph_size
- sizeof (int64_t))))
525 return (DDI_PROP_RESULT_ERROR
);
528 * Encode the integer into the byte stream one byte at a
531 bcopy((caddr_t
)data
, ph
->ph_cur_pos
, sizeof (int64_t));
534 * Move the current location to the start of the next bit of
535 * space where we can store encoded data.
537 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+
539 return (DDI_PROP_RESULT_OK
);
541 case DDI_PROP_CMD_SKIP
:
543 * Check that there is encoded data
545 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
546 ph
->ph_size
< sizeof (int64_t))
547 return (DDI_PROP_RESULT_ERROR
);
550 if ((caddr_t
)ph
->ph_cur_pos
==
551 (caddr_t
)ph
->ph_data
+ ph
->ph_size
) {
552 return (DDI_PROP_RESULT_EOF
);
553 } else if ((caddr_t
)ph
->ph_cur_pos
>
554 (caddr_t
)ph
->ph_data
+ ph
->ph_size
) {
555 return (DDI_PROP_RESULT_EOF
);
559 * Move the current location to the start of the next bit of
562 ph
->ph_cur_pos
= (uchar_t
*)ph
->ph_cur_pos
+
564 return (DDI_PROP_RESULT_OK
);
566 case DDI_PROP_CMD_GET_ESIZE
:
568 * Return the size of an encoded integer on OBP
570 return (sizeof (int64_t));
572 case DDI_PROP_CMD_GET_DSIZE
:
574 * Return the size of a decoded integer on the system.
576 return (sizeof (int64_t));
580 return (0); /* keep gcc happy */
584 * OBP 1275 string operator.
586 * OBP strings are NULL terminated.
589 di_prop_1275_string(prop_handle_t
*ph
, uint_t cmd
, char *data
)
596 case DDI_PROP_CMD_DECODE
:
598 * Check that there is encoded data
600 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0) {
601 return (DDI_PROP_RESULT_ERROR
);
604 n
= strlen((char *)ph
->ph_cur_pos
) + 1;
605 if ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
607 return (DDI_PROP_RESULT_ERROR
);
611 * Copy the NULL terminated string
613 bcopy((char *)ph
->ph_cur_pos
, data
, n
);
616 * Move the current location to the start of the next bit of
619 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ n
;
620 return (DDI_PROP_RESULT_OK
);
622 case DDI_PROP_CMD_ENCODE
:
624 * Check that there is room to encoded the data
626 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0) {
627 return (DDI_PROP_RESULT_ERROR
);
630 n
= strlen(data
) + 1;
631 if ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
633 return (DDI_PROP_RESULT_ERROR
);
637 * Copy the NULL terminated string
639 bcopy(data
, (char *)ph
->ph_cur_pos
, n
);
642 * Move the current location to the start of the next bit of
643 * space where we can store encoded data.
645 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ n
;
646 return (DDI_PROP_RESULT_OK
);
648 case DDI_PROP_CMD_SKIP
:
650 * Check that there is encoded data
652 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0) {
653 return (DDI_PROP_RESULT_ERROR
);
657 * Return the string length plus one for the NULL
658 * We know the size of the property, we need to
659 * ensure that the string is properly formatted,
660 * since we may be looking up random OBP data.
662 p
= (char *)ph
->ph_cur_pos
;
663 end
= (char *)ph
->ph_data
+ ph
->ph_size
;
666 return (DDI_PROP_RESULT_EOF
);
670 * Make sure each char is printable
672 for (n
= 0; p
< end
&& isascii(*p
) && !iscntrl(*p
); n
++, p
++)
675 /* Check termination and non-zero length */
676 if ((*p
== 0) && (n
!= 0)) {
677 ph
->ph_cur_pos
= p
+ 1;
678 return (DDI_PROP_RESULT_OK
);
681 return (DDI_PROP_RESULT_ERROR
);
683 case DDI_PROP_CMD_GET_ESIZE
:
685 * Return the size of the encoded string on OBP.
687 return (strlen(data
) + 1);
689 case DDI_PROP_CMD_GET_DSIZE
:
691 * Return the string length plus one for the NULL
692 * We know the size of the property, we need to
693 * ensure that the string is properly formatted,
694 * since we may be looking up random OBP data.
696 p
= (char *)ph
->ph_cur_pos
;
697 end
= (char *)ph
->ph_data
+ ph
->ph_size
;
698 for (n
= 0; p
< end
; n
++) {
706 * Add check here to separate EOF and ERROR.
709 return (DDI_PROP_RESULT_EOF
);
711 return (DDI_PROP_RESULT_ERROR
);
716 return (0); /* keep gcc happy */
720 * OBP 1275 byte operator
722 * Caller must specify the number of bytes to get. OBP encodes bytes
723 * as a byte so there is a 1-to-1 translation.
726 di_prop_1275_bytes(prop_handle_t
*ph
, uint_t cmd
, uchar_t
*data
,
730 case DDI_PROP_CMD_DECODE
:
732 * Check that there is encoded data
734 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
735 ph
->ph_size
< nelements
||
736 ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
737 ph
->ph_size
- nelements
)))
738 return (DDI_PROP_RESULT_ERROR
);
743 bcopy((char *)ph
->ph_cur_pos
, (char *)data
, nelements
);
746 * Move the current location
748 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ nelements
;
749 return (DDI_PROP_RESULT_OK
);
751 case DDI_PROP_CMD_ENCODE
:
753 * Check that there is room to encode the data
755 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
756 ph
->ph_size
< nelements
||
757 ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
758 ph
->ph_size
- nelements
)))
759 return (DDI_PROP_RESULT_ERROR
);
764 bcopy((char *)data
, (char *)ph
->ph_cur_pos
, nelements
);
767 * Move the current location to the start of the next bit of
768 * space where we can store encoded data.
770 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ nelements
;
771 return (DDI_PROP_RESULT_OK
);
773 case DDI_PROP_CMD_SKIP
:
775 * Check that there is encoded data
777 if (ph
->ph_cur_pos
== NULL
|| ph
->ph_size
== 0 ||
778 ph
->ph_size
< nelements
)
779 return (DDI_PROP_RESULT_ERROR
);
781 if ((char *)ph
->ph_cur_pos
> ((char *)ph
->ph_data
+
782 ph
->ph_size
- nelements
))
783 return (DDI_PROP_RESULT_EOF
);
786 * Move the current location
788 ph
->ph_cur_pos
= (char *)ph
->ph_cur_pos
+ nelements
;
789 return (DDI_PROP_RESULT_OK
);
791 case DDI_PROP_CMD_GET_ESIZE
:
793 * The size in bytes of the encoded size is the
794 * same as the decoded size provided by the caller.
798 case DDI_PROP_CMD_GET_DSIZE
:
800 * Just return the number of bytes specified by the caller.
807 return (0); /* keep gcc happy */
811 * Used for properties that come from the OBP, hardware configuration files,
812 * or that are created by calls to ddi_prop_update(9F).
814 static struct prop_handle_ops prop_1275_ops
= {
822 * Now the real thing:
823 * Extract type-specific values of an property
826 di_prop_decode_common(void *data
, int size
, int prop_type
, int prom
)
832 int (*prop_decoder
)(prop_handle_t
*, void *, uint_t
*);
835 * If the encoded data came from software, no decoding needed
839 case DI_PROP_TYPE_INT
:
840 if (size
% sizeof (int))
843 nelements
= size
/ sizeof (int);
846 case DI_PROP_TYPE_INT64
:
847 if (size
% sizeof (int64_t))
850 nelements
= size
/ sizeof (int64_t);
853 case DI_PROP_TYPE_STRING
:
858 * Don't trust the data passed in by the caller.
859 * Check every char to make sure it is indeed a
863 /* skip to next non-printable char */
864 for (n
= 0; cp
< end
&&
865 isascii(*cp
) && !iscntrl(*cp
); n
++, cp
++)
869 * Fail if reached end (i.e. last char != 0),
870 * or has a non-printable char. A zero length
871 * string is acceptable.
873 if (cp
== end
|| *cp
!= 0) {
878 * Increment # strings and keep going
886 case DI_PROP_TYPE_BYTE
:
894 * Get the encoded data
896 bzero((caddr_t
)&ph
, sizeof (prop_handle_t
));
897 ph
.ph_data
= *(uchar_t
**)data
;
901 * The data came from prom, use the 1275 OBP decode/encode routines.
903 ph
.ph_cur_pos
= ph
.ph_data
;
904 ph
.ph_save_pos
= ph
.ph_data
;
905 ph
.ph_ops
= &prop_1275_ops
;
906 ph
.ph_flags
= PH_FROM_PROM
;
909 case DI_PROP_TYPE_INT
:
910 prop_decoder
= di_prop_fm_decode_ints
;
912 case DI_PROP_TYPE_STRING
:
913 prop_decoder
= di_prop_fm_decode_strings
;
915 case DI_PROP_TYPE_BYTE
:
917 prop_decoder
= di_prop_fm_decode_bytes
;
921 if ((*prop_decoder
)(&ph
, data
, (uint_t
*)&nelements
)
926 * Free the encoded data
935 di_slot_names_free(int count
, di_slot_name_t
*slot_names
)
937 if (slot_names
== NULL
)
940 while (--count
>= 0) {
941 if (slot_names
[count
].name
!= NULL
)
942 free(slot_names
[count
].name
);
948 * 1275 "slot-names" format: [int][string1][string2]...[stringN]
949 * - [int] is a 1275 encoded integer
950 * - [string1]...[stringN] are concatenated null-terminated strings
951 * - each bit position in [int] represents a pci device number
952 * - each bit which is set in [int] represents a slot with a device
953 * number of that bit position
954 * - each string in [string1]...[stringN] identifies a slot name only
955 * for the bits which are set in [int]
956 * - the ordering of strings follow the ordering of bits set in [int]
958 * an allocated array of di_slot_name_t is returned through prop_data if
959 * [int] is non-zero and the number of entries as the return value;
960 * use di_slot_names_free() to free the array
963 di_slot_names_decode(uchar_t
*rawdata
, int rawlen
,
964 di_slot_name_t
**prop_data
)
972 di_slot_name_t
*slot_names
= NULL
;
974 if (rawlen
< sizeof (slots
))
977 slots
= impl_di_prop_int_from_prom(rawdata
, sizeof (slots
));
983 maxslots
= sizeof (slots
) * 8;
985 for (i
= 0; i
< maxslots
; i
++) {
986 if (slots
& (1 << i
))
991 slot_names
= malloc(sizeof (*slot_names
) * maxcount
);
992 bzero(slot_names
, sizeof (*slot_names
) * maxcount
);
994 /* also handle unterminated strings */
995 sp
= (char *)(rawdata
+ sizeof (slots
));
996 maxsp
= sp
+ (rawlen
- sizeof (slots
));
998 for (i
= 0; i
< maxslots
; i
++) {
999 if (slots
& (1 << i
)) {
1002 len
= strnlen(sp
, (maxsp
- sp
) + 1);
1006 slot_names
[count
].name
=
1007 malloc(sizeof (char) * (len
+ 1));
1008 (void) strlcpy(slot_names
[count
].name
, sp
, len
+ 1);
1010 slot_names
[count
].num
= i
;
1018 * check if the number of strings match with the number of slots;
1019 * we can also get a lesser string count even when there appears to be
1020 * the correct number of strings if one or more pair of strings are
1021 * seperated by more than one NULL byte
1023 if (count
!= maxcount
)
1026 *prop_data
= slot_names
;
1030 di_slot_names_free(maxcount
, slot_names
);