diff options
Diffstat (limited to 'drivers/acpi/utilities/utmisc.c')
-rw-r--r-- | drivers/acpi/utilities/utmisc.c | 109 |
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, "ient, NULL); |
708 | "ient, 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 | ||