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