X-Git-Url: https://err.no/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=drivers%2Facpi%2Fexecuter%2Fexfldio.c;h=9ff9d1f4615d8841eac8650bf4605e7e3cfb24fa;hb=HEAD;hp=65a48b6170ee3c9803771cad7a58c2caecc04b77;hpb=64106104dd2d4a6280777e88c1cbf9f7a52c30bd;p=linux-2.6 diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c index 65a48b6170..9ff9d1f461 100644 --- a/drivers/acpi/executer/exfldio.c +++ b/drivers/acpi/executer/exfldio.c @@ -5,7 +5,7 @@ *****************************************************************************/ /* - * Copyright (C) 2000 - 2007, R. Byron Moore + * Copyright (C) 2000 - 2008, Intel Corp. * All rights reserved. * * Redistribution and use in source and binary forms, with or without @@ -153,14 +153,15 @@ acpi_ex_setup_region(union acpi_operand_object *obj_desc, /* * Slack mode only: We will go ahead and allow access to this * field if it is within the region length rounded up to the next - * access width boundary. + * access width boundary. acpi_size cast for 64-bit compile. */ if (ACPI_ROUND_UP(rgn_desc->region.length, obj_desc->common_field. access_byte_width) >= - (obj_desc->common_field.base_byte_offset + - (acpi_native_uint) obj_desc->common_field. - access_byte_width + field_datum_byte_offset)) { + ((acpi_size) obj_desc->common_field. + base_byte_offset + + obj_desc->common_field.access_byte_width + + field_datum_byte_offset)) { return_ACPI_STATUS(AE_OK); } } @@ -263,7 +264,8 @@ acpi_ex_access_region(union acpi_operand_object *obj_desc, rgn_desc->region.space_id, obj_desc->common_field.access_byte_width, obj_desc->common_field.base_byte_offset, - field_datum_byte_offset, (void *)address)); + field_datum_byte_offset, ACPI_CAST_PTR(void, + address))); /* Invoke the appropriate address_space/op_region handler */ @@ -805,18 +807,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, u32 datum_count; u32 field_datum_count; u32 i; + u32 required_length; + void *new_buffer; ACPI_FUNCTION_TRACE(ex_insert_into_field); /* Validate input buffer */ - if (buffer_length < - ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { - ACPI_ERROR((AE_INFO, - "Field size %X (bits) is too large for buffer (%X)", - obj_desc->common_field.bit_length, buffer_length)); + new_buffer = NULL; + required_length = + ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length); + /* + * We must have a buffer that is at least as long as the field + * we are writing to. This is because individual fields are + * indivisible and partial writes are not supported -- as per + * the ACPI specification. + */ + if (buffer_length < required_length) { - return_ACPI_STATUS(AE_BUFFER_OVERFLOW); + /* We need to create a new buffer */ + + new_buffer = ACPI_ALLOCATE_ZEROED(required_length); + if (!new_buffer) { + return_ACPI_STATUS(AE_NO_MEMORY); + } + + /* + * Copy the original data to the new buffer, starting + * at Byte zero. All unused (upper) bytes of the + * buffer will be 0. + */ + ACPI_MEMCPY((char *)new_buffer, (char *)buffer, buffer_length); + buffer = new_buffer; + buffer_length = required_length; } /* @@ -866,7 +889,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, merged_datum, field_offset); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto exit; } field_offset += obj_desc->common_field.access_byte_width; @@ -924,5 +947,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc, mask, merged_datum, field_offset); + exit: + /* Free temporary buffer if we used one */ + + if (new_buffer) { + ACPI_FREE(new_buffer); + } return_ACPI_STATUS(status); }