diff options
Diffstat (limited to 'drivers/acpi/executer/exfldio.c')
-rw-r--r-- | drivers/acpi/executer/exfldio.c | 46 |
1 files changed, 37 insertions, 9 deletions
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 65a48b6170ee..e336b5dc7a50 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c | |||
@@ -5,7 +5,7 @@ | |||
5 | *****************************************************************************/ | 5 | *****************************************************************************/ |
6 | 6 | ||
7 | /* | 7 | /* |
8 | * Copyright (C) 2000 - 2007, R. Byron Moore | 8 | * Copyright (C) 2000 - 2008, Intel Corp. |
9 | * All rights reserved. | 9 | * All rights reserved. |
10 | * | 10 | * |
11 | * Redistribution and use in source and binary forms, with or without | 11 | * Redistribution and use in source and binary forms, with or without |
@@ -263,7 +263,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, | |||
263 | rgn_desc->region.space_id, | 263 | rgn_desc->region.space_id, |
264 | obj_desc->common_field.access_byte_width, | 264 | obj_desc->common_field.access_byte_width, |
265 | obj_desc->common_field.base_byte_offset, | 265 | obj_desc->common_field.base_byte_offset, |
266 | field_datum_byte_offset, (void *)address)); | 266 | field_datum_byte_offset, ACPI_CAST_PTR(void, |
267 | address))); | ||
267 | 268 | ||
268 | /* Invoke the appropriate address_space/op_region handler */ | 269 | /* Invoke the appropriate address_space/op_region handler */ |
269 | 270 | ||
@@ -805,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
805 | u32 datum_count; | 806 | u32 datum_count; |
806 | u32 field_datum_count; | 807 | u32 field_datum_count; |
807 | u32 i; | 808 | u32 i; |
809 | u32 required_length; | ||
810 | void *new_buffer; | ||
808 | 811 | ||
809 | ACPI_FUNCTION_TRACE(ex_insert_into_field); | 812 | ACPI_FUNCTION_TRACE(ex_insert_into_field); |
810 | 813 | ||
811 | /* Validate input buffer */ | 814 | /* Validate input buffer */ |
812 | 815 | ||
813 | if (buffer_length < | 816 | new_buffer = NULL; |
814 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { | 817 | required_length = |
815 | ACPI_ERROR((AE_INFO, | 818 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); |
816 | "Field size %X (bits) is too large for buffer (%X)", | 819 | /* |
817 | 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) { | ||
818 | 826 | ||
819 | 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; | ||
820 | } | 842 | } |
821 | 843 | ||
822 | /* | 844 | /* |
@@ -866,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
866 | merged_datum, | 888 | merged_datum, |
867 | field_offset); | 889 | field_offset); |
868 | if (ACPI_FAILURE(status)) { | 890 | if (ACPI_FAILURE(status)) { |
869 | return_ACPI_STATUS(status); | 891 | goto exit; |
870 | } | 892 | } |
871 | 893 | ||
872 | field_offset += obj_desc->common_field.access_byte_width; | 894 | field_offset += obj_desc->common_field.access_byte_width; |
@@ -924,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, | |||
924 | mask, merged_datum, | 946 | mask, merged_datum, |
925 | field_offset); | 947 | field_offset); |
926 | 948 | ||
949 | exit: | ||
950 | /* Free temporary buffer if we used one */ | ||
951 | |||
952 | if (new_buffer) { | ||
953 | ACPI_FREE(new_buffer); | ||
954 | } | ||
927 | return_ACPI_STATUS(status); | 955 | return_ACPI_STATUS(status); |
928 | } | 956 | } |