remove pyzfs
[unleashed.git] / usr / src / lib / libdevinfo / devinfo_prop_decode.c
blobaf104d933ce551de4c92896e4ce2f23457e88f86
1 /*
2 * CDDL HEADER START
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]
19 * CDDL HEADER END
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.
38 #include <stdlib.h>
39 #include <strings.h>
40 #include <synch.h>
41 #include <ctype.h>
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.
56 int
57 impl_di_prop_int_from_prom(uchar_t *intp, int n)
59 int i = 0;
61 #if defined(_LITTLE_ENDIAN)
62 intp += n;
63 while (n-- > 0) {
64 i = (i << 8) | *(--intp);
66 #else
67 while (n-- > 0) {
68 i = (i << 8) | *intp++;
70 #endif /* defined(_LITTLE_ENDIAN) */
72 return (i);
76 * Reset the current location pointer in the property handle to the
77 * beginning of the data.
79 void
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
88 * saved position.
90 void
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..
99 void
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
112 static int
113 di_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements)
115 int i;
116 int cnt = 0;
117 int *tmp;
118 int *intp;
119 int n;
122 * Figure out how many array elements there are by going through the
123 * data without decoding it first and counting.
125 for (;;) {
126 i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL);
127 if (i < 0)
128 break;
129 cnt++;
133 * If there are no elements return an error
135 if (cnt == 0)
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
160 tmp = intp;
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.
168 free(intp);
169 switch (i) {
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);
179 *nelements = cnt;
180 *(int **)data = intp;
182 return (DDI_PROP_SUCCESS);
186 * Decode an array of strings.
188 static int
189 di_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements)
191 int cnt = 0;
192 char *strs;
193 char *tmp;
194 int size;
195 int i;
196 int n;
197 int nbytes;
200 * Figure out how much memory we need for the sum total
202 nbytes = 0;
204 for (;;) {
206 * Get the decoded size of the current encoded string.
208 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL);
209 if (size < 0)
210 break;
212 cnt++;
213 nbytes += size;
217 * If there are no elements return an error
219 if (cnt == 0)
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);
239 tmp = strs;
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
247 free(strs);
248 switch (i) {
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;
260 *nelements = cnt;
262 return (DDI_PROP_SUCCESS);
266 * Decode an array of bytes.
268 static int
269 di_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements)
271 uchar_t *tmp;
272 int nbytes;
273 int i;
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,
285 data, ph->ph_size);
286 if (nbytes < DDI_PROP_RESULT_OK) {
287 switch (nbytes) {
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
312 free(tmp);
313 switch (i) {
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;
323 *nelements = nbytes;
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
343 * DDI_PROP_CMD_SKIP:
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)
371 int i;
373 switch (cmd) {
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 +
384 ph->ph_size - i))
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);
401 } else {
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
424 * time.
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
454 * undecoded data.
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));
472 /*NOTREACHED*/
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)
486 switch (cmd) {
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 +
512 sizeof (int64_t);
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
527 * time.
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 +
536 sizeof (int64_t);
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
558 * undecoded data.
560 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos +
561 sizeof (int64_t);
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));
577 /*NOTREACHED*/
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)
589 int n;
590 char *p;
591 char *end;
593 switch (cmd) {
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 +
604 ph->ph_size - n)) {
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
615 * undecoded data.
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 +
630 ph->ph_size - n)) {
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;
663 if (p == end) {
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++) {
697 if (*p++ == '\0') {
698 ph->ph_cur_pos = p;
699 return (n+1);
704 * Add check here to separate EOF and ERROR.
706 if (p == end)
707 return (DDI_PROP_RESULT_EOF);
709 return (DDI_PROP_RESULT_ERROR);
713 /*NOTREACHED*/
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,
725 uint_t nelements)
727 switch (cmd) {
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);
739 * Copy out the bytes
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);
760 * Copy in the bytes
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.
794 return (nelements);
796 case DDI_PROP_CMD_GET_DSIZE:
798 * Just return the number of bytes specified by the caller.
800 return (nelements);
804 /*NOTREACHED*/
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 = {
813 di_prop_1275_int,
814 di_prop_1275_string,
815 di_prop_1275_bytes,
816 di_prop_int64_op
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)
826 int n;
827 int nelements;
828 char *cp, *end;
829 prop_handle_t ph;
830 int (*prop_decoder)(prop_handle_t *, void *, uint_t *);
833 * If the encoded data came from software, no decoding needed
835 if (!prom) {
836 switch (prop_type) {
837 case DI_PROP_TYPE_INT:
838 if (size % sizeof (int))
839 nelements = -1;
840 else
841 nelements = size / sizeof (int);
842 break;
844 case DI_PROP_TYPE_INT64:
845 if (size % sizeof (int64_t))
846 nelements = -1;
847 else
848 nelements = size / sizeof (int64_t);
849 break;
851 case DI_PROP_TYPE_STRING:
852 nelements = 0;
853 cp = *(char **)data;
854 end = cp + size;
856 * Don't trust the data passed in by the caller.
857 * Check every char to make sure it is indeed a
858 * string property.
860 while (cp < end) {
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) {
872 nelements = -1;
873 break;
876 * Increment # strings and keep going
878 nelements++;
879 cp++;
882 break;
884 case DI_PROP_TYPE_BYTE:
885 nelements = size;
888 return (nelements);
892 * Get the encoded data
894 bzero((caddr_t)&ph, sizeof (prop_handle_t));
895 ph.ph_data = *(uchar_t **)data;
896 ph.ph_size = size;
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;
906 switch (prop_type) {
907 case DI_PROP_TYPE_INT:
908 prop_decoder = di_prop_fm_decode_ints;
909 break;
910 case DI_PROP_TYPE_STRING:
911 prop_decoder = di_prop_fm_decode_strings;
912 break;
913 case DI_PROP_TYPE_BYTE:
914 default:
915 prop_decoder = di_prop_fm_decode_bytes;
916 break;
919 if ((*prop_decoder)(&ph, data, (uint_t *)&nelements)
920 != DDI_PROP_SUCCESS)
921 return (-1);
924 * Free the encoded data
926 if (size != 0)
927 free(ph.ph_data);
929 return (nelements);
932 void
933 di_slot_names_free(int count, di_slot_name_t *slot_names)
935 if (slot_names == NULL)
936 return;
938 while (--count >= 0) {
939 free(slot_names[count].name);
941 free(slot_names);
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)
963 char *sp, *maxsp;
964 int count, i;
965 size_t len;
966 int slots;
967 int maxcount = 0;
968 int maxslots = 0;
969 di_slot_name_t *slot_names = NULL;
971 if (rawlen < sizeof (slots))
972 goto ERROUT;
974 slots = impl_di_prop_int_from_prom(rawdata, sizeof (slots));
975 if (slots == 0) {
976 *prop_data = NULL;
977 return (0);
980 maxslots = sizeof (slots) * 8;
981 count = 0;
982 for (i = 0; i < maxslots; i++) {
983 if (slots & (1 << i))
984 count++;
986 maxslots = i;
987 maxcount = count;
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));
994 count = 0;
995 for (i = 0; i < maxslots; i++) {
996 if (slots & (1 << i)) {
997 if (sp > maxsp)
998 break;
999 len = strnlen(sp, (maxsp - sp) + 1);
1000 if (len == 0)
1001 break;
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;
1009 sp += len + 1;
1010 count++;
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)
1021 goto ERROUT;
1023 *prop_data = slot_names;
1024 return (maxcount);
1025 /*NOTREACHED*/
1026 ERROUT:
1027 di_slot_names_free(maxcount, slot_names);
1028 *prop_data = NULL;
1029 return (-1);