diff options
author | Bob Moore <robert.moore@intel.com> | 2008-04-10 11:06:41 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2008-04-22 14:29:28 -0400 |
commit | 9aa6169f471771324b476a90d9392daa06d63a2d (patch) | |
tree | 56b435edcccebf6c2803799b91350c50598d8fe9 /drivers/acpi/executer/exfldio.c | |
parent | 549f46044e1e207a2cbfdfb3f9a0d3fd5fd4105e (diff) |
ACPICA: Fixed a problem with Index Fields where the Index register was incorrectly limited to a maximum of 32 bits
Now any size may be used.
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Alexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/executer/exfldio.c')
-rw-r--r-- | drivers/acpi/executer/exfldio.c | 41 |
1 files changed, 34 insertions, 7 deletions
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 1ece1c3fc375..ae402949c357 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c | |||
@@ -806,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
806 | u32 datum_count; | 806 | u32 datum_count; |
807 | u32 field_datum_count; | 807 | u32 field_datum_count; |
808 | u32 i; | 808 | u32 i; |
809 | u32 required_length; | ||
810 | void *new_buffer; | ||
809 | 811 | ||
810 | ACPI_FUNCTION_TRACE(ex_insert_into_field); | 812 | ACPI_FUNCTION_TRACE(ex_insert_into_field); |
811 | 813 | ||
812 | /* Validate input buffer */ | 814 | /* Validate input buffer */ |
813 | 815 | ||
814 | if (buffer_length < | 816 | new_buffer = NULL; |
815 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { | 817 | required_length = |
816 | ACPI_ERROR((AE_INFO, | 818 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); |
817 | "Field size %X (bits) is too large for buffer (%X)", | 819 | /* |
818 | obj_desc->common_field.bit_length, buffer_length)); | 820 | * We must have a buffer that is at least as long as the field |
821 | * we are writing to. This is because individual fields are | ||
822 | * indivisible and partial writes are not supported -- as per | ||
823 | * the ACPI specification. | ||
824 | */ | ||
825 | if (buffer_length < required_length) { | ||
819 | 826 | ||
820 | return_ACPI_STATUS(AE_BUFFER_OVERFLOW); | 827 | /* We need to create a new buffer */ |
828 | |||
829 | new_buffer = ACPI_ALLOCATE_ZEROED(required_length); | ||
830 | if (!new_buffer) { | ||
831 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
832 | } | ||
833 | |||
834 | /* | ||
835 | * Copy the original data to the new buffer, starting | ||
836 | * at Byte zero. All unused (upper) bytes of the | ||
837 | * buffer will be 0. | ||
838 | */ | ||
839 | ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); | ||
840 | buffer = new_buffer; | ||
841 | buffer_length = required_length; | ||
821 | } | 842 | } |
822 | 843 | ||
823 | /* | 844 | /* |
@@ -867,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
867 | merged_datum, | 888 | merged_datum, |
868 | field_offset); | 889 | field_offset); |
869 | if (ACPI_FAILURE(status)) { | 890 | if (ACPI_FAILURE(status)) { |
870 | return_ACPI_STATUS(status); | 891 | goto exit; |
871 | } | 892 | } |
872 | 893 | ||
873 | field_offset += obj_desc->common_field.access_byte_width; | 894 | field_offset += obj_desc->common_field.access_byte_width; |
@@ -925,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
925 | mask, merged_datum, | 946 | mask, merged_datum, |
926 | field_offset); | 947 | field_offset); |
927 | 948 | ||
949 | exit: | ||
950 | /* Free temporary buffer if we used one */ | ||
951 | |||
952 | if (new_buffer) { | ||
953 | ACPI_FREE(new_buffer); | ||
954 | } | ||
928 | return_ACPI_STATUS(status); | 955 | return_ACPI_STATUS(status); |
929 | } | 956 | } |