diff options
-rw-r--r-- | drivers/acpi/executer/exfield.c | 37 | ||||
-rw-r--r-- | drivers/acpi/executer/exfldio.c | 41 |
2 files changed, 34 insertions, 44 deletions
diff --git a/drivers/acpi/executer/exfield.c b/drivers/acpi/executer/exfield.c index da772cb91d7f..aef8db82570a 100644 --- a/drivers/acpi/executer/exfield.c +++ b/drivers/acpi/executer/exfield.c | |||
@@ -210,9 +210,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
210 | { | 210 | { |
211 | acpi_status status; | 211 | acpi_status status; |
212 | u32 length; | 212 | u32 length; |
213 | u32 required_length; | ||
214 | void *buffer; | 213 | void *buffer; |
215 | void *new_buffer; | ||
216 | union acpi_operand_object *buffer_desc; | 214 | union acpi_operand_object *buffer_desc; |
217 | 215 | ||
218 | ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); | 216 | ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); |
@@ -312,35 +310,6 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
312 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | 310 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); |
313 | } | 311 | } |
314 | 312 | ||
315 | /* | ||
316 | * We must have a buffer that is at least as long as the field | ||
317 | * we are writing to. This is because individual fields are | ||
318 | * indivisible and partial writes are not supported -- as per | ||
319 | * the ACPI specification. | ||
320 | */ | ||
321 | new_buffer = NULL; | ||
322 | required_length = | ||
323 | ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); | ||
324 | |||
325 | if (length < required_length) { | ||
326 | |||
327 | /* We need to create a new buffer */ | ||
328 | |||
329 | new_buffer = ACPI_ALLOCATE_ZEROED(required_length); | ||
330 | if (!new_buffer) { | ||
331 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
332 | } | ||
333 | |||
334 | /* | ||
335 | * Copy the original data to the new buffer, starting | ||
336 | * at Byte zero. All unused (upper) bytes of the | ||
337 | * buffer will be 0. | ||
338 | */ | ||
339 | ACPI_MEMCPY((char *)new_buffer, (char *)buffer, length); | ||
340 | buffer = new_buffer; | ||
341 | length = required_length; | ||
342 | } | ||
343 | |||
344 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, | 313 | ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, |
345 | "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", | 314 | "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", |
346 | source_desc, | 315 | source_desc, |
@@ -366,11 +335,5 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc, | |||
366 | status = acpi_ex_insert_into_field(obj_desc, buffer, length); | 335 | status = acpi_ex_insert_into_field(obj_desc, buffer, length); |
367 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); | 336 | acpi_ex_release_global_lock(obj_desc->common_field.field_flags); |
368 | 337 | ||
369 | /* Free temporary buffer if we used one */ | ||
370 | |||
371 | if (new_buffer) { | ||
372 | ACPI_FREE(new_buffer); | ||
373 | } | ||
374 | |||
375 | return_ACPI_STATUS(status); | 338 | return_ACPI_STATUS(status); |
376 | } | 339 | } |
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 | } |