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>
This commit is contained in:
Bob Moore 2008-04-10 19:06:41 +04:00 committed by Len Brown
parent 549f46044e
commit 9aa6169f47
2 changed files with 34 additions and 44 deletions

View File

@ -210,9 +210,7 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
{ {
acpi_status status; acpi_status status;
u32 length; u32 length;
u32 required_length;
void *buffer; void *buffer;
void *new_buffer;
union acpi_operand_object *buffer_desc; union acpi_operand_object *buffer_desc;
ACPI_FUNCTION_TRACE_PTR(ex_write_data_to_field, obj_desc); 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,
return_ACPI_STATUS(AE_AML_OPERAND_TYPE); return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
} }
/*
* 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.
*/
new_buffer = NULL;
required_length =
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
if (length < required_length) {
/* 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, length);
buffer = new_buffer;
length = required_length;
}
ACPI_DEBUG_PRINT((ACPI_DB_BFIELD, ACPI_DEBUG_PRINT((ACPI_DB_BFIELD,
"FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n", "FieldWrite [FROM]: Obj %p (%s:%X), Buf %p, ByteLen %X\n",
source_desc, source_desc,
@ -366,11 +335,5 @@ acpi_ex_write_data_to_field(union acpi_operand_object *source_desc,
status = acpi_ex_insert_into_field(obj_desc, buffer, length); status = acpi_ex_insert_into_field(obj_desc, buffer, length);
acpi_ex_release_global_lock(obj_desc->common_field.field_flags); acpi_ex_release_global_lock(obj_desc->common_field.field_flags);
/* Free temporary buffer if we used one */
if (new_buffer) {
ACPI_FREE(new_buffer);
}
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }

View File

@ -806,18 +806,39 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
u32 datum_count; u32 datum_count;
u32 field_datum_count; u32 field_datum_count;
u32 i; u32 i;
u32 required_length;
void *new_buffer;
ACPI_FUNCTION_TRACE(ex_insert_into_field); ACPI_FUNCTION_TRACE(ex_insert_into_field);
/* Validate input buffer */ /* Validate input buffer */
if (buffer_length < new_buffer = NULL;
ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length)) { required_length =
ACPI_ERROR((AE_INFO, ACPI_ROUND_BITS_UP_TO_BYTES(obj_desc->common_field.bit_length);
"Field size %X (bits) is too large for buffer (%X)", /*
obj_desc->common_field.bit_length, buffer_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;
} }
/* /*
@ -867,7 +888,7 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
merged_datum, merged_datum,
field_offset); field_offset);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_ACPI_STATUS(status); goto exit;
} }
field_offset += obj_desc->common_field.access_byte_width; field_offset += obj_desc->common_field.access_byte_width;
@ -925,5 +946,11 @@ acpi_ex_insert_into_field(union acpi_operand_object *obj_desc,
mask, merged_datum, mask, merged_datum,
field_offset); field_offset);
exit:
/* Free temporary buffer if we used one */
if (new_buffer) {
ACPI_FREE(new_buffer);
}
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }