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, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 #pragma ident "%Z%%M% %I% %E% SMI" 28 29 /* 30 * This file contains kernel property decode routines adopted from 31 * sunddi.c and ddi_impl.c. The following changes have been applied. 32 * 33 * (1) Replace kmem_alloc by malloc. Remove negative indexing 34 * (2) Decoding applies only to prom properties. 35 * (3) For strings, the return value is a composite string, not a string array. 36 * (4) impl_ddi_prop_int_from_prom() uses _LITTLE_ENDIAN from isa_defs.h 37 * 38 * XXX This file should be kept in sync with kernel property encoding. 39 */ 40 41 #include <stdlib.h> 42 #include <strings.h> 43 #include <synch.h> 44 #include <ctype.h> 45 #include <sys/types.h> 46 #include <sys/dditypes.h> 47 #include <sys/ddipropdefs.h> 48 #include <sys/isa_defs.h> 49 50 #include "libdevinfo.h" 51 52 /* 53 * Return an integer in native machine format from an OBP 1275 integer 54 * representation, which is big-endian, with no particular alignment 55 * guarantees. intp points to the OBP data, and n the number of bytes. 56 * 57 * Byte-swapping may be needed on some implementations. 58 */ 59 int 60 impl_di_prop_int_from_prom(uchar_t *intp, int n) 61 { 62 int i = 0; 63 64 #if defined(_LITTLE_ENDIAN) 65 intp += n; 66 while (n-- > 0) { 67 i = (i << 8) | *(--intp); 68 } 69 #else 70 while (n-- > 0) { 71 i = (i << 8) | *intp++; 72 } 73 #endif /* defined(_LITTLE_ENDIAN) */ 74 75 return (i); 76 } 77 78 /* 79 * Reset the current location pointer in the property handle to the 80 * beginning of the data. 81 */ 82 void 83 di_prop_reset_pos(prop_handle_t *ph) 84 { 85 ph->ph_cur_pos = ph->ph_data; 86 ph->ph_save_pos = ph->ph_data; 87 } 88 89 /* 90 * Restore the current location pointer in the property handle to the 91 * saved position. 92 */ 93 void 94 di_prop_save_pos(prop_handle_t *ph) 95 { 96 ph->ph_save_pos = ph->ph_cur_pos; 97 } 98 99 /* 100 * Save the location that the current location poiner is pointing to.. 101 */ 102 void 103 di_prop_restore_pos(prop_handle_t *ph) 104 { 105 ph->ph_cur_pos = ph->ph_save_pos; 106 } 107 108 /* 109 * Property encode/decode functions 110 */ 111 112 /* 113 * Decode an array of integers property 114 */ 115 static int 116 di_prop_fm_decode_ints(prop_handle_t *ph, void *data, uint_t *nelements) 117 { 118 int i; 119 int cnt = 0; 120 int *tmp; 121 int *intp; 122 int n; 123 124 /* 125 * Figure out how many array elements there are by going through the 126 * data without decoding it first and counting. 127 */ 128 for (;;) { 129 i = DDI_PROP_INT(ph, DDI_PROP_CMD_SKIP, NULL); 130 if (i < 0) 131 break; 132 cnt++; 133 } 134 135 /* 136 * If there are no elements return an error 137 */ 138 if (cnt == 0) 139 return (DDI_PROP_END_OF_DATA); 140 141 /* 142 * If we cannot skip through the data, we cannot decode it 143 */ 144 if (i == DDI_PROP_RESULT_ERROR) 145 return (DDI_PROP_CANNOT_DECODE); 146 147 /* 148 * Reset the data pointer to the beginning of the encoded data 149 */ 150 di_prop_reset_pos(ph); 151 152 /* 153 * Allocated memory to store the decoded value in. 154 */ 155 if ((intp = malloc(cnt * sizeof (int))) == NULL) { 156 return (DDI_PROP_CANNOT_DECODE); 157 } 158 159 160 /* 161 * Decode each elemente and place it in the space we just allocated 162 */ 163 tmp = intp; 164 for (n = 0; n < cnt; n++, tmp++) { 165 i = DDI_PROP_INT(ph, DDI_PROP_CMD_DECODE, tmp); 166 if (i < DDI_PROP_RESULT_OK) { 167 /* 168 * Free the space we just allocated 169 * and return an error. 170 */ 171 free(intp); 172 switch (i) { 173 case DDI_PROP_RESULT_EOF: 174 return (DDI_PROP_END_OF_DATA); 175 176 case DDI_PROP_RESULT_ERROR: 177 return (DDI_PROP_CANNOT_DECODE); 178 } 179 } 180 } 181 182 *nelements = cnt; 183 *(int **)data = intp; 184 185 return (DDI_PROP_SUCCESS); 186 } 187 188 /* 189 * Decode an array of strings. 190 */ 191 static int 192 di_prop_fm_decode_strings(prop_handle_t *ph, void *data, uint_t *nelements) 193 { 194 int cnt = 0; 195 char *strs; 196 char *tmp; 197 int size; 198 int i; 199 int n; 200 int nbytes; 201 202 /* 203 * Figure out how much memory we need for the sum total 204 */ 205 nbytes = 0; 206 207 for (;;) { 208 /* 209 * Get the decoded size of the current encoded string. 210 */ 211 size = DDI_PROP_STR(ph, DDI_PROP_CMD_GET_DSIZE, NULL); 212 if (size < 0) 213 break; 214 215 cnt++; 216 nbytes += size; 217 } 218 219 /* 220 * If there are no elements return an error 221 */ 222 if (cnt == 0) 223 return (DDI_PROP_END_OF_DATA); 224 225 /* 226 * If we cannot skip through the data, we cannot decode it 227 */ 228 if (size == DDI_PROP_RESULT_ERROR) 229 return (DDI_PROP_CANNOT_DECODE); 230 231 /* 232 * Allocate memory in which to store the decoded strings. 233 */ 234 if ((strs = malloc(nbytes)) == NULL) { 235 return (DDI_PROP_CANNOT_DECODE); 236 } 237 238 /* 239 * Finally, we can decode each string 240 */ 241 di_prop_reset_pos(ph); 242 tmp = strs; 243 for (n = 0; n < cnt; n++) { 244 i = DDI_PROP_STR(ph, DDI_PROP_CMD_DECODE, tmp); 245 if (i < DDI_PROP_RESULT_OK) { 246 /* 247 * Free the space we just allocated 248 * and return an error 249 */ 250 free(strs); 251 switch (i) { 252 case DDI_PROP_RESULT_EOF: 253 return (DDI_PROP_END_OF_DATA); 254 255 case DDI_PROP_RESULT_ERROR: 256 return (DDI_PROP_CANNOT_DECODE); 257 } 258 } 259 tmp += strlen(tmp) + 1; 260 } 261 262 *(char **)data = strs; 263 *nelements = cnt; 264 265 return (DDI_PROP_SUCCESS); 266 } 267 268 /* 269 * Decode an array of bytes. 270 */ 271 static int 272 di_prop_fm_decode_bytes(prop_handle_t *ph, void *data, uint_t *nelements) 273 { 274 uchar_t *tmp; 275 int nbytes; 276 int i; 277 278 /* 279 * If there are no elements return an error 280 */ 281 if (ph->ph_size == 0) 282 return (DDI_PROP_END_OF_DATA); 283 284 /* 285 * Get the size of the encoded array of bytes. 286 */ 287 nbytes = DDI_PROP_BYTES(ph, DDI_PROP_CMD_GET_DSIZE, 288 data, ph->ph_size); 289 if (nbytes < DDI_PROP_RESULT_OK) { 290 switch (nbytes) { 291 case DDI_PROP_RESULT_EOF: 292 return (DDI_PROP_END_OF_DATA); 293 294 case DDI_PROP_RESULT_ERROR: 295 return (DDI_PROP_CANNOT_DECODE); 296 } 297 } 298 299 /* 300 * Allocated memory to store the decoded value in. 301 */ 302 if ((tmp = malloc(nbytes)) == NULL) { 303 return (DDI_PROP_CANNOT_DECODE); 304 } 305 306 /* 307 * Decode each element and place it in the space we just allocated 308 */ 309 i = DDI_PROP_BYTES(ph, DDI_PROP_CMD_DECODE, tmp, nbytes); 310 if (i < DDI_PROP_RESULT_OK) { 311 /* 312 * Free the space we just allocated 313 * and return an error 314 */ 315 free(tmp); 316 switch (i) { 317 case DDI_PROP_RESULT_EOF: 318 return (DDI_PROP_END_OF_DATA); 319 320 case DDI_PROP_RESULT_ERROR: 321 return (DDI_PROP_CANNOT_DECODE); 322 } 323 } 324 325 *(uchar_t **)data = tmp; 326 *nelements = nbytes; 327 328 return (DDI_PROP_SUCCESS); 329 } 330 331 /* 332 * OBP 1275 integer, string and byte operators. 333 * 334 * DDI_PROP_CMD_DECODE: 335 * 336 * DDI_PROP_RESULT_ERROR: cannot decode the data 337 * DDI_PROP_RESULT_EOF: end of data 338 * DDI_PROP_OK: data was decoded 339 * 340 * DDI_PROP_CMD_ENCODE: 341 * 342 * DDI_PROP_RESULT_ERROR: cannot encode the data 343 * DDI_PROP_RESULT_EOF: end of data 344 * DDI_PROP_OK: data was encoded 345 * 346 * DDI_PROP_CMD_SKIP: 347 * 348 * DDI_PROP_RESULT_ERROR: cannot skip the data 349 * DDI_PROP_RESULT_EOF: end of data 350 * DDI_PROP_OK: data was skipped 351 * 352 * DDI_PROP_CMD_GET_ESIZE: 353 * 354 * DDI_PROP_RESULT_ERROR: cannot get encoded size 355 * DDI_PROP_RESULT_EOF: end of data 356 * > 0: the encoded size 357 * 358 * DDI_PROP_CMD_GET_DSIZE: 359 * 360 * DDI_PROP_RESULT_ERROR: cannot get decoded size 361 * DDI_PROP_RESULT_EOF: end of data 362 * > 0: the decoded size 363 */ 364 365 /* 366 * OBP 1275 integer operator 367 * 368 * OBP properties are a byte stream of data, so integers may not be 369 * properly aligned. Therefore we need to copy them one byte at a time. 370 */ 371 int 372 di_prop_1275_int(prop_handle_t *ph, uint_t cmd, int *data) 373 { 374 int i; 375 376 switch (cmd) { 377 case DDI_PROP_CMD_DECODE: 378 /* 379 * Check that there is encoded data 380 */ 381 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 382 return (DDI_PROP_RESULT_ERROR); 383 if (ph->ph_flags & PH_FROM_PROM) { 384 i = ph->ph_size < PROP_1275_INT_SIZE ? 385 ph->ph_size : PROP_1275_INT_SIZE; 386 if ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 387 ph->ph_size - i)) 388 return (DDI_PROP_RESULT_ERROR); 389 } else if (ph->ph_size < sizeof (int) || 390 ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 391 ph->ph_size - sizeof (int)))) { 392 return (DDI_PROP_RESULT_ERROR); 393 } 394 395 /* 396 * Copy the integer, using the implementation-specific 397 * copy function if the property is coming from the PROM. 398 */ 399 if (ph->ph_flags & PH_FROM_PROM) { 400 *data = impl_di_prop_int_from_prom( 401 (uchar_t *)ph->ph_cur_pos, 402 (ph->ph_size < PROP_1275_INT_SIZE) ? 403 ph->ph_size : PROP_1275_INT_SIZE); 404 } else { 405 bcopy(ph->ph_cur_pos, (caddr_t)data, sizeof (int)); 406 } 407 408 /* 409 * Move the current location to the start of the next 410 * bit of undecoded data. 411 */ 412 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 413 return (DDI_PROP_RESULT_OK); 414 415 case DDI_PROP_CMD_ENCODE: 416 /* 417 * Check that there is room to encoded the data 418 */ 419 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 420 ph->ph_size < PROP_1275_INT_SIZE || 421 ((int *)ph->ph_cur_pos > ((int *)ph->ph_data + 422 ph->ph_size - sizeof (int)))) 423 return (DDI_PROP_RESULT_ERROR); 424 425 /* 426 * Encode the integer into the byte stream one byte at a 427 * time. 428 */ 429 bcopy((caddr_t)data, ph->ph_cur_pos, sizeof (int)); 430 431 /* 432 * Move the current location to the start of the next bit of 433 * space where we can store encoded data. 434 */ 435 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 436 return (DDI_PROP_RESULT_OK); 437 438 case DDI_PROP_CMD_SKIP: 439 /* 440 * Check that there is encoded data 441 */ 442 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 443 ph->ph_size < PROP_1275_INT_SIZE) 444 return (DDI_PROP_RESULT_ERROR); 445 446 447 if ((caddr_t)ph->ph_cur_pos == 448 (caddr_t)ph->ph_data + ph->ph_size) { 449 return (DDI_PROP_RESULT_EOF); 450 } else if ((caddr_t)ph->ph_cur_pos > 451 (caddr_t)ph->ph_data + ph->ph_size) { 452 return (DDI_PROP_RESULT_EOF); 453 } 454 455 /* 456 * Move the current location to the start of the next bit of 457 * undecoded data. 458 */ 459 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + PROP_1275_INT_SIZE; 460 return (DDI_PROP_RESULT_OK); 461 462 case DDI_PROP_CMD_GET_ESIZE: 463 /* 464 * Return the size of an encoded integer on OBP 465 */ 466 return (PROP_1275_INT_SIZE); 467 468 case DDI_PROP_CMD_GET_DSIZE: 469 /* 470 * Return the size of a decoded integer on the system. 471 */ 472 return (sizeof (int)); 473 } 474 475 /*NOTREACHED*/ 476 return (0); /* keep gcc happy */ 477 } 478 479 /* 480 * 64 bit integer operator 481 * 482 * This is an extension, defined by Sun, to the 1275 integer 483 * operator. This routine handles the encoding/decoding of 484 * 64 bit integer properties. 485 */ 486 int 487 di_prop_int64_op(prop_handle_t *ph, uint_t cmd, int64_t *data) 488 { 489 switch (cmd) { 490 case DDI_PROP_CMD_DECODE: 491 /* 492 * Check that there is encoded data 493 */ 494 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) 495 return (DDI_PROP_RESULT_ERROR); 496 if (ph->ph_flags & PH_FROM_PROM) { 497 return (DDI_PROP_RESULT_ERROR); 498 } else if (ph->ph_size < sizeof (int64_t) || 499 ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data + 500 ph->ph_size - sizeof (int64_t)))) { 501 return (DDI_PROP_RESULT_ERROR); 502 } 503 504 /* 505 * Copy the integer, using the implementation-specific 506 * copy function if the property is coming from the PROM. 507 */ 508 bcopy(ph->ph_cur_pos, (caddr_t)data, sizeof (int64_t)); 509 510 /* 511 * Move the current location to the start of the next 512 * bit of undecoded data. 513 */ 514 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 515 sizeof (int64_t); 516 return (DDI_PROP_RESULT_OK); 517 518 case DDI_PROP_CMD_ENCODE: 519 /* 520 * Check that there is room to encoded the data 521 */ 522 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 523 ph->ph_size < sizeof (int64_t) || 524 ((int64_t *)ph->ph_cur_pos > ((int64_t *)ph->ph_data + 525 ph->ph_size - sizeof (int64_t)))) 526 return (DDI_PROP_RESULT_ERROR); 527 528 /* 529 * Encode the integer into the byte stream one byte at a 530 * time. 531 */ 532 bcopy((caddr_t)data, ph->ph_cur_pos, sizeof (int64_t)); 533 534 /* 535 * Move the current location to the start of the next bit of 536 * space where we can store encoded data. 537 */ 538 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 539 sizeof (int64_t); 540 return (DDI_PROP_RESULT_OK); 541 542 case DDI_PROP_CMD_SKIP: 543 /* 544 * Check that there is encoded data 545 */ 546 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 547 ph->ph_size < sizeof (int64_t)) 548 return (DDI_PROP_RESULT_ERROR); 549 550 551 if ((caddr_t)ph->ph_cur_pos == 552 (caddr_t)ph->ph_data + ph->ph_size) { 553 return (DDI_PROP_RESULT_EOF); 554 } else if ((caddr_t)ph->ph_cur_pos > 555 (caddr_t)ph->ph_data + ph->ph_size) { 556 return (DDI_PROP_RESULT_EOF); 557 } 558 559 /* 560 * Move the current location to the start of the next bit of 561 * undecoded data. 562 */ 563 ph->ph_cur_pos = (uchar_t *)ph->ph_cur_pos + 564 sizeof (int64_t); 565 return (DDI_PROP_RESULT_OK); 566 567 case DDI_PROP_CMD_GET_ESIZE: 568 /* 569 * Return the size of an encoded integer on OBP 570 */ 571 return (sizeof (int64_t)); 572 573 case DDI_PROP_CMD_GET_DSIZE: 574 /* 575 * Return the size of a decoded integer on the system. 576 */ 577 return (sizeof (int64_t)); 578 } 579 580 /*NOTREACHED*/ 581 return (0); /* keep gcc happy */ 582 } 583 584 /* 585 * OBP 1275 string operator. 586 * 587 * OBP strings are NULL terminated. 588 */ 589 int 590 di_prop_1275_string(prop_handle_t *ph, uint_t cmd, char *data) 591 { 592 int n; 593 char *p; 594 char *end; 595 596 switch (cmd) { 597 case DDI_PROP_CMD_DECODE: 598 /* 599 * Check that there is encoded data 600 */ 601 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 602 return (DDI_PROP_RESULT_ERROR); 603 } 604 605 n = strlen((char *)ph->ph_cur_pos) + 1; 606 if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 607 ph->ph_size - n)) { 608 return (DDI_PROP_RESULT_ERROR); 609 } 610 611 /* 612 * Copy the NULL terminated string 613 */ 614 bcopy((char *)ph->ph_cur_pos, data, n); 615 616 /* 617 * Move the current location to the start of the next bit of 618 * undecoded data. 619 */ 620 ph->ph_cur_pos = (char *)ph->ph_cur_pos + n; 621 return (DDI_PROP_RESULT_OK); 622 623 case DDI_PROP_CMD_ENCODE: 624 /* 625 * Check that there is room to encoded the data 626 */ 627 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 628 return (DDI_PROP_RESULT_ERROR); 629 } 630 631 n = strlen(data) + 1; 632 if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 633 ph->ph_size - n)) { 634 return (DDI_PROP_RESULT_ERROR); 635 } 636 637 /* 638 * Copy the NULL terminated string 639 */ 640 bcopy(data, (char *)ph->ph_cur_pos, n); 641 642 /* 643 * Move the current location to the start of the next bit of 644 * space where we can store encoded data. 645 */ 646 ph->ph_cur_pos = (char *)ph->ph_cur_pos + n; 647 return (DDI_PROP_RESULT_OK); 648 649 case DDI_PROP_CMD_SKIP: 650 /* 651 * Check that there is encoded data 652 */ 653 if (ph->ph_cur_pos == NULL || ph->ph_size == 0) { 654 return (DDI_PROP_RESULT_ERROR); 655 } 656 657 /* 658 * Return the string length plus one for the NULL 659 * We know the size of the property, we need to 660 * ensure that the string is properly formatted, 661 * since we may be looking up random OBP data. 662 */ 663 p = (char *)ph->ph_cur_pos; 664 end = (char *)ph->ph_data + ph->ph_size; 665 666 if (p == end) { 667 return (DDI_PROP_RESULT_EOF); 668 } 669 670 /* 671 * Make sure each char is printable 672 */ 673 for (n = 0; p < end && isascii(*p) && !iscntrl(*p); n++, p++) 674 ; 675 676 /* Check termination and non-zero length */ 677 if ((*p == 0) && (n != 0)) { 678 ph->ph_cur_pos = p + 1; 679 return (DDI_PROP_RESULT_OK); 680 } 681 682 return (DDI_PROP_RESULT_ERROR); 683 684 case DDI_PROP_CMD_GET_ESIZE: 685 /* 686 * Return the size of the encoded string on OBP. 687 */ 688 return (strlen(data) + 1); 689 690 case DDI_PROP_CMD_GET_DSIZE: 691 /* 692 * Return the string length plus one for the NULL 693 * We know the size of the property, we need to 694 * ensure that the string is properly formatted, 695 * since we may be looking up random OBP data. 696 */ 697 p = (char *)ph->ph_cur_pos; 698 end = (char *)ph->ph_data + ph->ph_size; 699 for (n = 0; p < end; n++) { 700 if (*p++ == '\0') { 701 ph->ph_cur_pos = p; 702 return (n+1); 703 } 704 } 705 706 /* 707 * Add check here to separate EOF and ERROR. 708 */ 709 if (p == end) 710 return (DDI_PROP_RESULT_EOF); 711 712 return (DDI_PROP_RESULT_ERROR); 713 714 } 715 716 /*NOTREACHED*/ 717 return (0); /* keep gcc happy */ 718 } 719 720 /* 721 * OBP 1275 byte operator 722 * 723 * Caller must specify the number of bytes to get. OBP encodes bytes 724 * as a byte so there is a 1-to-1 translation. 725 */ 726 int 727 di_prop_1275_bytes(prop_handle_t *ph, uint_t cmd, uchar_t *data, 728 uint_t nelements) 729 { 730 switch (cmd) { 731 case DDI_PROP_CMD_DECODE: 732 /* 733 * Check that there is encoded data 734 */ 735 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 736 ph->ph_size < nelements || 737 ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 738 ph->ph_size - nelements))) 739 return (DDI_PROP_RESULT_ERROR); 740 741 /* 742 * Copy out the bytes 743 */ 744 bcopy((char *)ph->ph_cur_pos, (char *)data, nelements); 745 746 /* 747 * Move the current location 748 */ 749 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 750 return (DDI_PROP_RESULT_OK); 751 752 case DDI_PROP_CMD_ENCODE: 753 /* 754 * Check that there is room to encode the data 755 */ 756 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 757 ph->ph_size < nelements || 758 ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 759 ph->ph_size - nelements))) 760 return (DDI_PROP_RESULT_ERROR); 761 762 /* 763 * Copy in the bytes 764 */ 765 bcopy((char *)data, (char *)ph->ph_cur_pos, nelements); 766 767 /* 768 * Move the current location to the start of the next bit of 769 * space where we can store encoded data. 770 */ 771 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 772 return (DDI_PROP_RESULT_OK); 773 774 case DDI_PROP_CMD_SKIP: 775 /* 776 * Check that there is encoded data 777 */ 778 if (ph->ph_cur_pos == NULL || ph->ph_size == 0 || 779 ph->ph_size < nelements) 780 return (DDI_PROP_RESULT_ERROR); 781 782 if ((char *)ph->ph_cur_pos > ((char *)ph->ph_data + 783 ph->ph_size - nelements)) 784 return (DDI_PROP_RESULT_EOF); 785 786 /* 787 * Move the current location 788 */ 789 ph->ph_cur_pos = (char *)ph->ph_cur_pos + nelements; 790 return (DDI_PROP_RESULT_OK); 791 792 case DDI_PROP_CMD_GET_ESIZE: 793 /* 794 * The size in bytes of the encoded size is the 795 * same as the decoded size provided by the caller. 796 */ 797 return (nelements); 798 799 case DDI_PROP_CMD_GET_DSIZE: 800 /* 801 * Just return the number of bytes specified by the caller. 802 */ 803 return (nelements); 804 805 } 806 807 /*NOTREACHED*/ 808 return (0); /* keep gcc happy */ 809 } 810 811 /* 812 * Used for properties that come from the OBP, hardware configuration files, 813 * or that are created by calls to ddi_prop_update(9F). 814 */ 815 static struct prop_handle_ops prop_1275_ops = { 816 di_prop_1275_int, 817 di_prop_1275_string, 818 di_prop_1275_bytes, 819 di_prop_int64_op 820 }; 821 822 /* 823 * Now the real thing: 824 * Extract type-specific values of an property 825 */ 826 int 827 di_prop_decode_common(void *data, int size, int prop_type, int prom) 828 { 829 int n; 830 int nelements; 831 char *cp, *end; 832 prop_handle_t ph; 833 int (*prop_decoder)(prop_handle_t *, void *, uint_t *); 834 835 /* 836 * If the encoded data came from software, no decoding needed 837 */ 838 if (!prom) { 839 switch (prop_type) { 840 case DI_PROP_TYPE_INT: 841 if (size % sizeof (int)) 842 nelements = -1; 843 else 844 nelements = size / sizeof (int); 845 break; 846 847 case DI_PROP_TYPE_INT64: 848 if (size % sizeof (int64_t)) 849 nelements = -1; 850 else 851 nelements = size / sizeof (int64_t); 852 break; 853 854 case DI_PROP_TYPE_STRING: 855 nelements = 0; 856 cp = *(char **)data; 857 end = cp + size; 858 /* 859 * Don't trust the data passed in by the caller. 860 * Check every char to make sure it is indeed a 861 * string property. 862 */ 863 while (cp < end) { 864 /* skip to next non-printable char */ 865 for (n = 0; cp < end && 866 isascii(*cp) && !iscntrl(*cp); n++, cp++) 867 ; 868 869 /* 870 * Fail if reached end (i.e. last char != 0), 871 * or has a non-printable char. A zero length 872 * string is acceptable. 873 */ 874 if (cp == end || *cp != 0) { 875 nelements = -1; 876 break; 877 } 878 /* 879 * Increment # strings and keep going 880 */ 881 nelements++; 882 cp++; 883 } 884 885 break; 886 887 case DI_PROP_TYPE_BYTE: 888 nelements = size; 889 } 890 891 return (nelements); 892 } 893 894 /* 895 * Get the encoded data 896 */ 897 bzero((caddr_t)&ph, sizeof (prop_handle_t)); 898 ph.ph_data = *(uchar_t **)data; 899 ph.ph_size = size; 900 901 /* 902 * The data came from prom, use the 1275 OBP decode/encode routines. 903 */ 904 ph.ph_cur_pos = ph.ph_data; 905 ph.ph_save_pos = ph.ph_data; 906 ph.ph_ops = &prop_1275_ops; 907 ph.ph_flags = PH_FROM_PROM; 908 909 switch (prop_type) { 910 case DI_PROP_TYPE_INT: 911 prop_decoder = di_prop_fm_decode_ints; 912 break; 913 case DI_PROP_TYPE_STRING: 914 prop_decoder = di_prop_fm_decode_strings; 915 break; 916 case DI_PROP_TYPE_BYTE: 917 default: 918 prop_decoder = di_prop_fm_decode_bytes; 919 break; 920 } 921 922 if ((*prop_decoder)(&ph, data, (uint_t *)&nelements) 923 != DDI_PROP_SUCCESS) 924 return (-1); 925 926 /* 927 * Free the encoded data 928 */ 929 if (size != 0) 930 free(ph.ph_data); 931 932 return (nelements); 933 } 934 935 /* end of devinfo_prop_decode.c */ 936