1 /* 2 * CDDL HEADER START 3 * 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. 7 * 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. 12 * 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] 18 * 19 * CDDL HEADER END 20 */ 21 /* 22 * Copyright 2007 Sun Microsystems, Inc. All rights reserved. 23 * Use is subject to license terms. 24 */ 25 26 /* 27 * This file contains kernel property decode routines adopted from 28 * sunddi.c and ddi_impl.c. The following changes have been applied. 29 * 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 34 * 35 * XXX This file should be kept in sync with kernel property encoding. 36 */ 37 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> 46 47 #include "libdevinfo.h" 48 49 /* 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. 53 * 54 * Byte-swapping may be needed on some implementations. 55 */ 56 int 57 impl_di_prop_int_from_prom(uchar_t *intp, int n) 58 { 59 int i = 0; 60 61 #if defined(_LITTLE_ENDIAN) 62 intp += n; 63 while (n-- > 0) { 64 i = (i << 8) | *(--intp); 65 } 66 #else 67 while (n-- > 0) { 68 i = (i << 8) | *intp++; 69 } 70 #endif /* defined(_LITTLE_ENDIAN) */ 71 72 return (i); 73 } 74 75 /* 76 * Reset the current location pointer in the property handle to the 77 * beginning of the data. 78 */ 79 void 80 di_prop_reset_pos(prop_handle_t *ph) 81 { 82 ph->ph_cur_pos = ph->ph_data; 83 ph->ph_save_pos = ph->ph_data; 84 } 85 86 /* 87 * Restore the current location pointer in the property handle to the 88 * saved position. 89 */ 90 void 91 di_prop_save_pos(prop_handle_t *ph) 92 { 93 ph->ph_save_pos = ph->ph_cur_pos; 94 } 95 96 /* 97 * Save the location that the current location poiner is pointing to.. 98 */ 99 void 100 di_prop_restore_pos(prop_handle_t *ph) 101 { 102 ph->ph_cur_pos = ph->ph_save_pos; 103 } 104 105 /* 106 * Property encode/decode functions 107 */ 108 109 /* 110 * Decode an array of integers property 111 */ 112 static int 113 di_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements) 114 { 115 int i; 116 int cnt = 0; 117 int *tmp; 118 int *intp; 119 int n; 120 121 /* 122 * Figure out how many array elements there are by going through the 123 * data without decoding it first and counting. 124 */ 125 for (;;) { 126 i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL); 127 if (i < 0) 128 break; 129 cnt++; 130 } 131 132 /* 133 * If there are no elements return an error 134 */ 135 if (cnt == 0) 136 return (DDI_PROP_END_OF_DATA); 137 138 /* 139 * If we cannot skip through the data, we cannot decode it 140 */ 141 if (i == DDI_PROP_RESULT_ERROR) 142 return (DDI_PROP_CANNOT_DECODE); 143 144 /* 145 * Reset the data pointer to the beginning of the encoded data 146 */ 147 di_prop_reset_pos(ph); 148 149 /* 150 * Allocated memory to store the decoded value in. 151 */ 152 if ((intp = malloc(cnt * sizeof (int))) == NULL) { 153 return (DDI_PROP_CANNOT_DECODE); 154 } 155 156 157 /* 158 * Decode each elemente and place it in the space we just allocated 159 */ 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) { 164 /* 165 * Free the space we just allocated 166 * and return an error. 167 */ 168 free(intp); 169 switch (i) { 170 case DDI_PROP_RESULT_EOF: 171 return (DDI_PROP_END_OF_DATA); 172 173 case DDI_PROP_RESULT_ERROR: 174 return (DDI_PROP_CANNOT_DECODE); 175 } 176 } 177 } 178 179 *nelements = cnt; 180 *(int **)data = intp; 181 182 return (DDI_PROP_SUCCESS); 183 } 184 185 /* 186 * Decode an array of strings. 187 */ 188 static int 189 di_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements) 190 { 191 int cnt = 0; 192 char *strs; 193 char *tmp; 194 int size; 195 int i; 196 int n; 197 int nbytes; 198 199 /* 200 * Figure out how much memory we need for the sum total 201 */ 202 nbytes = 0; 203 204 for (;;) { 205 /* 206 * Get the decoded size of the current encoded string. 207 */ 208 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 209 if (size < 0) 210 break; 211 212 cnt++; 213 nbytes += size; 214 } 215 216 /* 217 * If there are no elements return an error 218 */ 219 if (cnt == 0) 220 return (DDI_PROP_END_OF_DATA); 221 222 /* 223 * If we cannot skip through the data, we cannot decode it 224 */ 225 if (size == DDI_PROP_RESULT_ERROR) 226 return (DDI_PROP_CANNOT_DECODE); 227 228 /* 229 * Allocate memory in which to store the decoded strings. 230 */ 231 if ((strs = malloc(nbytes)) == NULL) { 232 return (DDI_PROP_CANNOT_DECODE); 233 } 234 235 /* 236 * Finally, we can decode each string 237 */ 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) { 243 /* 244 * Free the space we just allocated 245 * and return an error 246 */ 247 free(strs); 248 switch (i) { 249 case DDI_PROP_RESULT_EOF: 250 return (DDI_PROP_END_OF_DATA); 251 252 case DDI_PROP_RESULT_ERROR: 253 return (DDI_PROP_CANNOT_DECODE); 254 } 255 } 256 tmp += strlen(tmp) + 1; 257 } 258 259 *(char **)data = strs; 260 *nelements = cnt; 261 262 return (DDI_PROP_SUCCESS); 263 } 264 265 /* 266 * Decode an array of bytes. 267 */ 268 static int 269 di_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements) 270 { 271 uchar_t *tmp; 272 int nbytes; 273 int i; 274 275 /* 276 * If there are no elements return an error 277 */ 278 if (ph->ph_size == 0) 279 return (DDI_PROP_END_OF_DATA); 280 281 /* 282 * Get the size of the encoded array of bytes. 283 */ 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); 290 291 case DDI_PROP_RESULT_ERROR: 292 return (DDI_PROP_CANNOT_DECODE); 293 } 294 } 295 296 /* 297 * Allocated memory to store the decoded value in. 298 */ 299 if ((tmp = malloc(nbytes)) == NULL) { 300 return (DDI_PROP_CANNOT_DECODE); 301 } 302 303 /* 304 * Decode each element and place it in the space we just allocated 305 */ 306 i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes); 307 if (i < DDI_PROP_RESULT_OK) { 308 /* 309 * Free the space we just allocated 310 * and return an error 311 */ 312 free(tmp); 313 switch (i) { 314 case DDI_PROP_RESULT_EOF: 315 return (DDI_PROP_END_OF_DATA); 316 317 case DDI_PROP_RESULT_ERROR: 318 return (DDI_PROP_CANNOT_DECODE); 319 } 320 } 321 322 *(uchar_t **)data = tmp; 323 *nelements = nbytes; 324 325 return (DDI_PROP_SUCCESS); 326 } 327 328 /* 329 * OBP 1275 integer, string and byte operators. 330 * 331 * DDI_PROP_CMD_DECODE: 332 * 333 * DDI_PROP_RESULT_ERROR: cannot decode the data 334 * DDI_PROP_RESULT_EOF: end of data 335 * DDI_PROP_OK: data was decoded 336 * 337 * DDI_PROP_CMD_ENCODE: 338 * 339 * DDI_PROP_RESULT_ERROR: cannot encode the data 340 * DDI_PROP_RESULT_EOF: end of data 341 * DDI_PROP_OK: data was encoded 342 * 343 * DDI_PROP_CMD_SKIP: 344 * 345 * DDI_PROP_RESULT_ERROR: cannot skip the data 346 * DDI_PROP_RESULT_EOF: end of data 347 * DDI_PROP_OK: data was skipped 348 * 349 * DDI_PROP_CMD_GET_ESIZE: 350 * 351 * DDI_PROP_RESULT_ERROR: cannot get encoded size 352 * DDI_PROP_RESULT_EOF: end of data 353 * > 0: the encoded size 354 * 355 * DDI_PROP_CMD_GET_DSIZE: 356 * 357 * DDI_PROP_RESULT_ERROR: cannot get decoded size 358 * DDI_PROP_RESULT_EOF: end of data 359 * > 0: the decoded size 360 */ 361 362 /* 363 * OBP 1275 integer operator 364 * 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. 367 */ 368 int 369 di_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data) 370 { 371 int i; 372 373 switch (cmd) { 374 case DDI_PROP_CMD_DECODE: 375 /* 376 * Check that there is encoded data 377 */ 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); 390 } 391 392 /* 393 * Copy the integer, using the implementation-specific 394 * copy function if the property is coming from the PROM. 395 */ 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)); 403 } 404 405 /* 406 * Move the current location to the start of the next 407 * bit of undecoded data. 408 */ 409 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 410 return (DDI_PROP_RESULT_OK); 411 412 case DDI_PROP_CMD_ENCODE: 413 /* 414 * Check that there is room to encoded the data 415 */ 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); 421 422 /* 423 * Encode the integer into the byte stream one byte at a 424 * time. 425 */ 426 bcopy((caddr_t)data, ph->ph_cur_pos, sizeof (int)); 427 428 /* 429 * Move the current location to the start of the next bit of 430 * space where we can store encoded data. 431 */ 432 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 433 return (DDI_PROP_RESULT_OK); 434 435 case DDI_PROP_CMD_SKIP: 436 /* 437 * Check that there is encoded data 438 */ 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); 442 443 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); 450 } 451 452 /* 453 * Move the current location to the start of the next bit of 454 * undecoded data. 455 */ 456 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 457 return (DDI_PROP_RESULT_OK); 458 459 case DDI_PROP_CMD_GET_ESIZE: 460 /* 461 * Return the size of an encoded integer on OBP 462 */ 463 return (PROP_1275_INT_SIZE); 464 465 case DDI_PROP_CMD_GET_DSIZE: 466 /* 467 * Return the size of a decoded integer on the system. 468 */ 469 return (sizeof (int)); 470 } 471 472 /*NOTREACHED*/ 473 return (0); /* keep gcc happy */ 474 } 475 476 /* 477 * 64 bit integer operator 478 * 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. 482 */ 483 int 484 di_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data) 485 { 486 switch (cmd) { 487 case DDI_PROP_CMD_DECODE: 488 /* 489 * Check that there is encoded data 490 */ 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); 499 } 500 501 /* 502 * Copy the integer, using the implementation-specific 503 * copy function if the property is coming from the PROM. 504 */ 505 bcopy(ph->ph_cur_pos, (caddr_t)data, sizeof (int64_t)); 506 507 /* 508 * Move the current location to the start of the next 509 * bit of undecoded data. 510 */ 511 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 512 sizeof (int64_t); 513 return (DDI_PROP_RESULT_OK); 514 515 case DDI_PROP_CMD_ENCODE: 516 /* 517 * Check that there is room to encoded the data 518 */ 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); 524 525 /* 526 * Encode the integer into the byte stream one byte at a 527 * time. 528 */ 529 bcopy((caddr_t)data, ph->ph_cur_pos, sizeof (int64_t)); 530 531 /* 532 * Move the current location to the start of the next bit of 533 * space where we can store encoded data. 534 */ 535 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 536 sizeof (int64_t); 537 return (DDI_PROP_RESULT_OK); 538 539 case DDI_PROP_CMD_SKIP: 540 /* 541 * Check that there is encoded data 542 */ 543 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 544 ph->ph_size < sizeof (int64_t)) 545 return (DDI_PROP_RESULT_ERROR); 546 547 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); 554 } 555 556 /* 557 * Move the current location to the start of the next bit of 558 * undecoded data. 559 */ 560 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 561 sizeof (int64_t); 562 return (DDI_PROP_RESULT_OK); 563 564 case DDI_PROP_CMD_GET_ESIZE: 565 /* 566 * Return the size of an encoded integer on OBP 567 */ 568 return (sizeof (int64_t)); 569 570 case DDI_PROP_CMD_GET_DSIZE: 571 /* 572 * Return the size of a decoded integer on the system. 573 */ 574 return (sizeof (int64_t)); 575 } 576 577 /*NOTREACHED*/ 578 return (0); /* keep gcc happy */ 579 } 580 581 /* 582 * OBP 1275 string operator. 583 * 584 * OBP strings are NULL terminated. 585 */ 586 int 587 di_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data) 588 { 589 int n; 590 char *p; 591 char *end; 592 593 switch (cmd) { 594 case DDI_PROP_CMD_DECODE: 595 /* 596 * Check that there is encoded data 597 */ 598 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 599 return (DDI_PROP_RESULT_ERROR); 600 } 601 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); 606 } 607 608 /* 609 * Copy the NULL terminated string 610 */ 611 bcopy((char *)ph->ph_cur_pos, data, n); 612 613 /* 614 * Move the current location to the start of the next bit of 615 * undecoded data. 616 */ 617 ph->ph_cur_pos = (char *)ph->ph_cur_pos + n; 618 return (DDI_PROP_RESULT_OK); 619 620 case DDI_PROP_CMD_ENCODE: 621 /* 622 * Check that there is room to encoded the data 623 */ 624 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 625 return (DDI_PROP_RESULT_ERROR); 626 } 627 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); 632 } 633 634 /* 635 * Copy the NULL terminated string 636 */ 637 bcopy(data, (char *)ph->ph_cur_pos, n); 638 639 /* 640 * Move the current location to the start of the next bit of 641 * space where we can store encoded data. 642 */ 643 ph->ph_cur_pos = (char *)ph->ph_cur_pos + n; 644 return (DDI_PROP_RESULT_OK); 645 646 case DDI_PROP_CMD_SKIP: 647 /* 648 * Check that there is encoded data 649 */ 650 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 651 return (DDI_PROP_RESULT_ERROR); 652 } 653 654 /* 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. 659 */ 660 p = (char *)ph->ph_cur_pos; 661 end = (char *)ph->ph_data + ph->ph_size; 662 663 if (p == end) { 664 return (DDI_PROP_RESULT_EOF); 665 } 666 667 /* 668 * Make sure each char is printable 669 */ 670 for (n = 0; p < end && isascii(*p) && !iscntrl(*p); n++, p++) 671 ; 672 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); 677 } 678 679 return (DDI_PROP_RESULT_ERROR); 680 681 case DDI_PROP_CMD_GET_ESIZE: 682 /* 683 * Return the size of the encoded string on OBP. 684 */ 685 return (strlen(data) + 1); 686 687 case DDI_PROP_CMD_GET_DSIZE: 688 /* 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. 693 */ 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); 700 } 701 } 702 703 /* 704 * Add check here to separate EOF and ERROR. 705 */ 706 if (p == end) 707 return (DDI_PROP_RESULT_EOF); 708 709 return (DDI_PROP_RESULT_ERROR); 710 711 } 712 713 /*NOTREACHED*/ 714 return (0); /* keep gcc happy */ 715 } 716 717 /* 718 * OBP 1275 byte operator 719 * 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. 722 */ 723 int 724 di_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data, 725 uint_t nelements) 726 { 727 switch (cmd) { 728 case DDI_PROP_CMD_DECODE: 729 /* 730 * Check that there is encoded data 731 */ 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); 737 738 /* 739 * Copy out the bytes 740 */ 741 bcopy((char *)ph->ph_cur_pos, (char *)data, nelements); 742 743 /* 744 * Move the current location 745 */ 746 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 747 return (DDI_PROP_RESULT_OK); 748 749 case DDI_PROP_CMD_ENCODE: 750 /* 751 * Check that there is room to encode the data 752 */ 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); 758 759 /* 760 * Copy in the bytes 761 */ 762 bcopy((char *)data, (char *)ph->ph_cur_pos, nelements); 763 764 /* 765 * Move the current location to the start of the next bit of 766 * space where we can store encoded data. 767 */ 768 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 769 return (DDI_PROP_RESULT_OK); 770 771 case DDI_PROP_CMD_SKIP: 772 /* 773 * Check that there is encoded data 774 */ 775 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 776 ph->ph_size < nelements) 777 return (DDI_PROP_RESULT_ERROR); 778 779 if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 780 ph->ph_size - nelements)) 781 return (DDI_PROP_RESULT_EOF); 782 783 /* 784 * Move the current location 785 */ 786 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 787 return (DDI_PROP_RESULT_OK); 788 789 case DDI_PROP_CMD_GET_ESIZE: 790 /* 791 * The size in bytes of the encoded size is the 792 * same as the decoded size provided by the caller. 793 */ 794 return (nelements); 795 796 case DDI_PROP_CMD_GET_DSIZE: 797 /* 798 * Just return the number of bytes specified by the caller. 799 */ 800 return (nelements); 801 802 } 803 804 /*NOTREACHED*/ 805 return (0); /* keep gcc happy */ 806 } 807 808 /* 809 * Used for properties that come from the OBP, hardware configuration files, 810 * or that are created by calls to ddi_prop_update(9F). 811 */ 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 817 }; 818 819 /* 820 * Now the real thing: 821 * Extract type-specific values of an property 822 */ 823 int 824 di_prop_decode_common(void *data, int size, int prop_type, int prom) 825 { 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 *); 831 832 /* 833 * If the encoded data came from software, no decoding needed 834 */ 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; 843 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; 850 851 case DI_PROP_TYPE_STRING: 852 nelements = 0; 853 cp = *(char **)data; 854 end = cp + size; 855 /* 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. 859 */ 860 while (cp < end) { 861 /* skip to next non-printable char */ 862 for (n = 0; cp < end && 863 isascii(*cp) && !iscntrl(*cp); n++, cp++) 864 ; 865 866 /* 867 * Fail if reached end (i.e. last char != 0), 868 * or has a non-printable char. A zero length 869 * string is acceptable. 870 */ 871 if (cp == end || *cp != 0) { 872 nelements = -1; 873 break; 874 } 875 /* 876 * Increment # strings and keep going 877 */ 878 nelements++; 879 cp++; 880 } 881 882 break; 883 884 case DI_PROP_TYPE_BYTE: 885 nelements = size; 886 } 887 888 return (nelements); 889 } 890 891 /* 892 * Get the encoded data 893 */ 894 bzero((caddr_t)&ph, sizeof (prop_handle_t)); 895 ph.ph_data = *(uchar_t **)data; 896 ph.ph_size = size; 897 898 /* 899 * The data came from prom, use the 1275 OBP decode/encode routines. 900 */ 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; 905 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; 917 } 918 919 if ((*prop_decoder)(&ph, data, (uint_t *)&nelements) 920 != DDI_PROP_SUCCESS) 921 return (-1); 922 923 /* 924 * Free the encoded data 925 */ 926 if (size != 0) 927 free(ph.ph_data); 928 929 return (nelements); 930 } 931 932 void 933 di_slot_names_free(int count, di_slot_name_t *slot_names) 934 { 935 if (slot_names == NULL) 936 return; 937 938 while (--count >= 0) { 939 if (slot_names[count].name != NULL) 940 free(slot_names[count].name); 941 } 942 free(slot_names); 943 } 944 945 /* 946 * 1275 "slot-names" format: [int][string1][string2]...[stringN] 947 * - [int] is a 1275 encoded integer 948 * - [string1]...[stringN] are concatenated null-terminated strings 949 * - each bit position in [int] represents a pci device number 950 * - each bit which is set in [int] represents a slot with a device 951 * number of that bit position 952 * - each string in [string1]...[stringN] identifies a slot name only 953 * for the bits which are set in [int] 954 * - the ordering of strings follow the ordering of bits set in [int] 955 * 956 * an allocated array of di_slot_name_t is returned through prop_data if 957 * [int] is non-zero and the number of entries as the return value; 958 * use di_slot_names_free() to free the array 959 */ 960 int 961 di_slot_names_decode(uchar_t *rawdata, int rawlen, 962 di_slot_name_t **prop_data) 963 { 964 char *sp, *maxsp; 965 int count, i; 966 size_t len; 967 int slots; 968 int maxcount = 0; 969 int maxslots = 0; 970 di_slot_name_t *slot_names = NULL; 971 972 if (rawlen < sizeof (slots)) 973 goto ERROUT; 974 975 slots = impl_di_prop_int_from_prom(rawdata, sizeof (slots)); 976 if (slots == 0) { 977 *prop_data = NULL; 978 return (0); 979 } 980 981 maxslots = sizeof (slots) * 8; 982 count = 0; 983 for (i = 0; i < maxslots; i++) { 984 if (slots & (1 << i)) 985 count++; 986 } 987 maxslots = i; 988 maxcount = count; 989 slot_names = malloc(sizeof (*slot_names) * maxcount); 990 bzero(slot_names, sizeof (*slot_names) * maxcount); 991 992 /* also handle unterminated strings */ 993 sp = (char *)(rawdata + sizeof (slots)); 994 maxsp = sp + (rawlen - sizeof (slots)); 995 count = 0; 996 for (i = 0; i < maxslots; i++) { 997 if (slots & (1 << i)) { 998 if (sp > maxsp) 999 break; 1000 len = strnlen(sp, (maxsp - sp) + 1); 1001 if (len == 0) 1002 break; 1003 1004 slot_names[count].name = 1005 malloc(sizeof (char) * (len + 1)); 1006 (void) strlcpy(slot_names[count].name, sp, len + 1); 1007 1008 slot_names[count].num = i; 1009 1010 sp += len + 1; 1011 count++; 1012 } 1013 } 1014 1015 /* 1016 * check if the number of strings match with the number of slots; 1017 * we can also get a lesser string count even when there appears to be 1018 * the correct number of strings if one or more pair of strings are 1019 * seperated by more than one NULL byte 1020 */ 1021 if (count != maxcount) 1022 goto ERROUT; 1023 1024 *prop_data = slot_names; 1025 return (maxcount); 1026 /*NOTREACHED*/ 1027 ERROUT: 1028 di_slot_names_free(maxcount, slot_names); 1029 *prop_data = NULL; 1030 return (-1); 1031 } 1032