aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/utilities/utmisc.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/utilities/utmisc.c')
-rw-r--r--drivers/acpi/utilities/utmisc.c109
1 files changed, 72 insertions, 37 deletions
diff --git a/drivers/acpi/utilities/utmisc.c b/drivers/acpi/utilities/utmisc.c
index 874467117cec..5c75d35ad1cd 100644
--- a/drivers/acpi/utilities/utmisc.c
+++ b/drivers/acpi/utilities/utmisc.c
@@ -601,7 +601,8 @@ acpi_name acpi_ut_repair_name(acpi_name name)
601 * FUNCTION: acpi_ut_strtoul64 601 * FUNCTION: acpi_ut_strtoul64
602 * 602 *
603 * PARAMETERS: String - Null terminated string 603 * PARAMETERS: String - Null terminated string
604 * Base - Radix of the string: 10, 16, or ACPI_ANY_BASE 604 * Base - Radix of the string: 16 or ACPI_ANY_BASE;
605 * ACPI_ANY_BASE means 'in behalf of to_integer'
605 * ret_integer - Where the converted integer is returned 606 * ret_integer - Where the converted integer is returned
606 * 607 *
607 * RETURN: Status and Converted value 608 * RETURN: Status and Converted value
@@ -617,16 +618,17 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
617 u32 this_digit = 0; 618 u32 this_digit = 0;
618 acpi_integer return_value = 0; 619 acpi_integer return_value = 0;
619 acpi_integer quotient; 620 acpi_integer quotient;
621 acpi_integer dividend;
622 u32 to_integer_op = (base == ACPI_ANY_BASE);
623 u32 mode32 = (acpi_gbl_integer_byte_width == 4);
624 u8 valid_digits = 0;
625 u8 sign_of0x = 0;
626 u8 term = 0;
620 627
621 ACPI_FUNCTION_TRACE(ut_stroul64); 628 ACPI_FUNCTION_TRACE(ut_stroul64);
622 629
623 if ((!string) || !(*string)) {
624 goto error_exit;
625 }
626
627 switch (base) { 630 switch (base) {
628 case ACPI_ANY_BASE: 631 case ACPI_ANY_BASE:
629 case 10:
630 case 16: 632 case 16:
631 break; 633 break;
632 634
@@ -635,39 +637,45 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
635 return_ACPI_STATUS(AE_BAD_PARAMETER); 637 return_ACPI_STATUS(AE_BAD_PARAMETER);
636 } 638 }
637 639
640 if (!string) {
641 goto error_exit;
642 }
643
638 /* Skip over any white space in the buffer */ 644 /* Skip over any white space in the buffer */
639 645
640 while (ACPI_IS_SPACE(*string) || *string == '\t') { 646 while ((*string) && (ACPI_IS_SPACE(*string) || *string == '\t')) {
641 string++; 647 string++;
642 } 648 }
643 649
644 /* 650 if (to_integer_op) {
645 * If the input parameter Base is zero, then we need to 651 /*
646 * determine if it is decimal or hexadecimal: 652 * Base equal to ACPI_ANY_BASE means 'to_integer operation case'.
647 */ 653 * We need to determine if it is decimal or hexadecimal.
648 if (base == 0) { 654 */
649 if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { 655 if ((*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) {
656 sign_of0x = 1;
650 base = 16; 657 base = 16;
658
659 /* Skip over the leading '0x' */
651 string += 2; 660 string += 2;
652 } else { 661 } else {
653 base = 10; 662 base = 10;
654 } 663 }
655 } 664 }
656 665
657 /* 666 /* Any string left? Check that '0x' is not followed by white space. */
658 * For hexadecimal base, skip over the leading 667
659 * 0 or 0x, if they are present. 668 if (!(*string) || ACPI_IS_SPACE(*string) || *string == '\t') {
660 */ 669 if (to_integer_op) {
661 if ((base == 16) && 670 goto error_exit;
662 (*string == '0') && (ACPI_TOLOWER(*(string + 1)) == 'x')) { 671 } else {
663 string += 2; 672 goto all_done;
673 }
664 } 674 }
665 675
666 /* Any string left? */ 676 dividend = (mode32) ? ACPI_UINT32_MAX : ACPI_UINT64_MAX;
667 677
668 if (!(*string)) { 678 /* At least one character in the string here */
669 goto error_exit;
670 }
671 679
672 /* Main loop: convert the string to a 64-bit integer */ 680 /* Main loop: convert the string to a 64-bit integer */
673 681
@@ -677,14 +685,12 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
677 /* Convert ASCII 0-9 to Decimal value */ 685 /* Convert ASCII 0-9 to Decimal value */
678 686
679 this_digit = ((u8) * string) - '0'; 687 this_digit = ((u8) * string) - '0';
680 } else { 688 } else if (base == 10) {
681 if (base == 10) {
682 689
683 /* Digit is out of range */ 690 /* Digit is out of range; possible in to_integer case only */
684
685 goto error_exit;
686 }
687 691
692 term = 1;
693 } else {
688 this_digit = (u8) ACPI_TOUPPER(*string); 694 this_digit = (u8) ACPI_TOUPPER(*string);
689 if (ACPI_IS_XDIGIT((char)this_digit)) { 695 if (ACPI_IS_XDIGIT((char)this_digit)) {
690 696
@@ -692,22 +698,49 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
692 698
693 this_digit = this_digit - 'A' + 10; 699 this_digit = this_digit - 'A' + 10;
694 } else { 700 } else {
695 /* 701 term = 1;
696 * We allow non-hex chars, just stop now, same as end-of-string. 702 }
697 * See ACPI spec, string-to-integer conversion. 703 }
698 */ 704
705 if (term) {
706 if (to_integer_op) {
707 goto error_exit;
708 } else {
699 break; 709 break;
700 } 710 }
711 } else if ((valid_digits == 0) && (this_digit == 0)
712 && !sign_of0x) {
713
714 /* Skip zeros */
715 string++;
716 continue;
717 }
718
719 valid_digits++;
720
721 if (sign_of0x
722 && ((valid_digits > 16)
723 || ((valid_digits > 8) && mode32))) {
724 /*
725 * This is to_integer operation case.
726 * No any restrictions for string-to-integer conversion,
727 * see ACPI spec.
728 */
729 goto error_exit;
701 } 730 }
702 731
703 /* Divide the digit into the correct position */ 732 /* Divide the digit into the correct position */
704 733
705 (void) 734 (void)
706 acpi_ut_short_divide((ACPI_INTEGER_MAX - 735 acpi_ut_short_divide((dividend - (acpi_integer) this_digit),
707 (acpi_integer) this_digit), base, 736 base, &quotient, NULL);
708 &quotient, NULL); 737
709 if (return_value > quotient) { 738 if (return_value > quotient) {
710 goto error_exit; 739 if (to_integer_op) {
740 goto error_exit;
741 } else {
742 break;
743 }
711 } 744 }
712 745
713 return_value *= base; 746 return_value *= base;
@@ -717,6 +750,8 @@ acpi_ut_strtoul64(char *string, u32 base, acpi_integer * ret_integer)
717 750
718 /* All done, normal exit */ 751 /* All done, normal exit */
719 752
753 all_done:
754
720 *ret_integer = return_value; 755 *ret_integer = return_value;
721 return_ACPI_STATUS(AE_OK); 756 return_ACPI_STATUS(AE_OK);
722 757