summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLen Brown <len.brown@intel.com>2004-12-06 07:12:37 -0500
committerLen Brown <len.brown@intel.com>2004-12-06 07:12:37 -0500
commit46bcd6adfaa55dfe17dfd5097c5123049b401992 (patch)
tree1c15dcea68e051e33667eef64f90c186d0ca7d7b
parent8c15f7c986178c796f127698acae8c03a1f96e41 (diff)
[ACPI] ACPICA 20041203 from Bob Moore and Alexey Starikovskiy
The low-level field insertion/extraction code (exfldio) has been completely rewritten to eliminate unnecessary complexity, bugs, and boundary conditions. Fixed a problem in the ToInteger, ToBuffer, ToHexString, and ToDecimalString operators where the input operand could be inadvertently deleted if no conversion was necessary (e.g., if the input to ToInteger was an Integer object.) Fixed a problem with the ToDecimalString and ToHexString where an incorrect exception code was returned if the resulting string would be > 200 chars. AE_STRING_LIMIT is now returned. Fixed a problem with the Concatenate operator where AE_OK was always returned, even if the operation failed. Fixed a problem in oswinxf (used by AcpiExec and iASL) to allow > 128 semaphores to be allocated. Signed-off-by: Len Brown <len.brown@intel.com>
-rw-r--r--drivers/acpi/dispatcher/dsopcode.c5
-rw-r--r--drivers/acpi/dispatcher/dswexec.c24
-rw-r--r--drivers/acpi/events/evgpe.c26
-rw-r--r--drivers/acpi/executer/exdump.c3
-rw-r--r--drivers/acpi/executer/exfldio.c542
-rw-r--r--drivers/acpi/executer/exmisc.c2
-rw-r--r--drivers/acpi/executer/exoparg1.c26
-rw-r--r--drivers/acpi/executer/exprep.c24
-rw-r--r--drivers/acpi/parser/psopcode.c8
-rw-r--r--include/acpi/acconfig.h2
-rw-r--r--include/acpi/acmacros.h1
-rw-r--r--include/acpi/acobject.h4
-rw-r--r--include/acpi/amlcode.h1
13 files changed, 176 insertions, 492 deletions
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c
index 68084760ec76..c9e8f39df156 100644
--- a/drivers/acpi/dispatcher/dsopcode.c
+++ b/drivers/acpi/dispatcher/dsopcode.c
@@ -762,9 +762,8 @@ acpi_ds_eval_region_operands (
*
* RETURN: Status
*
- * DESCRIPTION: Get the operands and complete the following data objec types:
- * Buffer
- * Package
+ * DESCRIPTION: Get the operands and complete the following data object types:
+ * Buffer, Package.
*
****************************************************************************/
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c
index 56196605d36d..0a078f0caeed 100644
--- a/drivers/acpi/dispatcher/dswexec.c
+++ b/drivers/acpi/dispatcher/dswexec.c
@@ -399,16 +399,24 @@ acpi_ds_exec_end_op (
goto cleanup;
}
- /* Resolve all operands */
+ /*
+ * All opcodes require operand resolution, with the only exceptions
+ * being the object_type and size_of operators.
+ */
+ if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) {
+ /* Resolve all operands */
+
+ status = acpi_ex_resolve_operands (walk_state->opcode,
+ &(walk_state->operands [walk_state->num_operands -1]),
+ walk_state);
+ if (ACPI_SUCCESS (status)) {
+ ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
+ acpi_ps_get_opcode_name (walk_state->opcode),
+ walk_state->num_operands, "after ex_resolve_operands");
+ }
+ }
- status = acpi_ex_resolve_operands (walk_state->opcode,
- &(walk_state->operands [walk_state->num_operands -1]),
- walk_state);
if (ACPI_SUCCESS (status)) {
- ACPI_DUMP_OPERANDS (ACPI_WALK_OPERANDS, ACPI_IMODE_EXECUTE,
- acpi_ps_get_opcode_name (walk_state->opcode),
- walk_state->num_operands, "after ex_resolve_operands");
-
/*
* Dispatch the request to the appropriate interpreter handler
* routine. There is one routine per opcode "type" based upon the
diff --git a/drivers/acpi/events/evgpe.c b/drivers/acpi/events/evgpe.c
index 0c54d314a357..5b69f3a39d8f 100644
--- a/drivers/acpi/events/evgpe.c
+++ b/drivers/acpi/events/evgpe.c
@@ -605,8 +605,8 @@ acpi_ev_gpe_dispatch (
if ((gpe_event_info->flags & ACPI_GPE_XRUPT_TYPE_MASK) == ACPI_GPE_EDGE_TRIGGERED) {
status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
- ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
- gpe_number));
+ ACPI_REPORT_ERROR (("acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
+ acpi_format_exception (status), gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
}
@@ -643,8 +643,8 @@ acpi_ev_gpe_dispatch (
status = acpi_hw_clear_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: Unable to clear GPE[%2X]\n",
- gpe_number));
+ "acpi_ev_gpe_dispatch: %s, Unable to clear GPE[%2X]\n",
+ acpi_format_exception (status), gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
}
@@ -659,8 +659,8 @@ acpi_ev_gpe_dispatch (
status = acpi_ev_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
- gpe_number));
+ "acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
+ acpi_format_exception (status), gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
@@ -668,12 +668,12 @@ acpi_ev_gpe_dispatch (
* Execute the method associated with the GPE
* NOTE: Level-triggered GPEs are cleared after the method completes.
*/
- if (ACPI_FAILURE (acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
- acpi_ev_asynch_execute_gpe_method,
- gpe_event_info))) {
+ status = acpi_os_queue_for_execution (OSD_PRIORITY_GPE,
+ acpi_ev_asynch_execute_gpe_method, gpe_event_info);
+ if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: Unable to queue handler for GPE[%2X], event is disabled\n",
- gpe_number));
+ "acpi_ev_gpe_dispatch: %s, Unable to queue handler for GPE[%2X] - event disabled\n",
+ acpi_format_exception (status), gpe_number));
}
break;
@@ -692,8 +692,8 @@ acpi_ev_gpe_dispatch (
status = acpi_ev_disable_gpe (gpe_event_info);
if (ACPI_FAILURE (status)) {
ACPI_REPORT_ERROR ((
- "acpi_ev_gpe_dispatch: Unable to disable GPE[%2X]\n",
- gpe_number));
+ "acpi_ev_gpe_dispatch: %s, Unable to disable GPE[%2X]\n",
+ acpi_format_exception (status), gpe_number));
return_VALUE (ACPI_INTERRUPT_NOT_HANDLED);
}
break;
diff --git a/drivers/acpi/executer/exdump.c b/drivers/acpi/executer/exdump.c
index fc4fca556907..dac5e3ff7cdd 100644
--- a/drivers/acpi/executer/exdump.c
+++ b/drivers/acpi/executer/exdump.c
@@ -714,9 +714,6 @@ acpi_ex_dump_object_descriptor (
acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length);
acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset);
acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset);
- acpi_ex_out_integer ("datum_valid_bits", obj_desc->common_field.datum_valid_bits);
- acpi_ex_out_integer ("end_fld_valid_bits",obj_desc->common_field.end_field_valid_bits);
- acpi_ex_out_integer ("end_buf_valid_bits",obj_desc->common_field.end_buffer_valid_bits);
acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node);
switch (ACPI_GET_OBJECT_TYPE (obj_desc)) {
diff --git a/drivers/acpi/executer/exfldio.c b/drivers/acpi/executer/exfldio.c
index 5f8fbdb16e11..8248ec38530d 100644
--- a/drivers/acpi/executer/exfldio.c
+++ b/drivers/acpi/executer/exfldio.c
@@ -612,210 +612,6 @@ acpi_ex_write_with_update_rule (
/*******************************************************************************
*
- * FUNCTION: acpi_ex_get_buffer_datum
- *
- * PARAMETERS: Datum - Where the Datum is returned
- * Buffer - Raw field buffer
- * buffer_length - Entire length (used for big-endian only)
- * byte_granularity - 1/2/4/8 Granularity of the field
- * (aka Datum Size)
- * buffer_offset - Datum offset into the buffer
- *
- * RETURN: none
- *
- * DESCRIPTION: Get a datum from the buffer according to the buffer field
- * byte granularity
- *
- ******************************************************************************/
-
-void
-acpi_ex_get_buffer_datum (
- acpi_integer *datum,
- void *buffer,
- u32 buffer_length,
- u32 byte_granularity,
- u32 buffer_offset)
-{
- u32 index;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_get_buffer_datum", byte_granularity);
-
-
- /* Get proper index into buffer (handles big/little endian) */
-
- index = ACPI_BUFFER_INDEX (buffer_length, buffer_offset, byte_granularity);
-
- /* Move the requested number of bytes */
-
- switch (byte_granularity) {
- case ACPI_FIELD_BYTE_GRANULARITY:
-
- *datum = ((u8 *) buffer) [index];
- break;
-
- case ACPI_FIELD_WORD_GRANULARITY:
-
- ACPI_MOVE_16_TO_64 (datum, &(((u16 *) buffer) [index]));
- break;
-
- case ACPI_FIELD_DWORD_GRANULARITY:
-
- ACPI_MOVE_32_TO_64 (datum, &(((u32 *) buffer) [index]));
- break;
-
- case ACPI_FIELD_QWORD_GRANULARITY:
-
- ACPI_MOVE_64_TO_64 (datum, &(((u64 *) buffer) [index]));
- break;
-
- default:
- /* Should not get here */
- break;
- }
-
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ex_set_buffer_datum
- *
- * PARAMETERS: merged_datum - Value to store
- * Buffer - Receiving buffer
- * buffer_length - Entire length (used for big-endian only)
- * byte_granularity - 1/2/4/8 Granularity of the field
- * (aka Datum Size)
- * buffer_offset - Datum offset into the buffer
- *
- * RETURN: none
- *
- * DESCRIPTION: Store the merged datum to the buffer according to the
- * byte granularity
- *
- ******************************************************************************/
-
-void
-acpi_ex_set_buffer_datum (
- acpi_integer merged_datum,
- void *buffer,
- u32 buffer_length,
- u32 byte_granularity,
- u32 buffer_offset)
-{
- u32 index;
-
-
- ACPI_FUNCTION_TRACE_U32 ("ex_set_buffer_datum", byte_granularity);
-
-
- /* Get proper index into buffer (handles big/little endian) */
-
- index = ACPI_BUFFER_INDEX (buffer_length, buffer_offset, byte_granularity);
-
- /* Move the requested number of bytes */
-
- switch (byte_granularity) {
- case ACPI_FIELD_BYTE_GRANULARITY:
-
- ((u8 *) buffer) [index] = (u8) merged_datum;
- break;
-
- case ACPI_FIELD_WORD_GRANULARITY:
-
- ACPI_MOVE_64_TO_16 (&(((u16 *) buffer)[index]), &merged_datum);
- break;
-
- case ACPI_FIELD_DWORD_GRANULARITY:
-
- ACPI_MOVE_64_TO_32 (&(((u32 *) buffer)[index]), &merged_datum);
- break;
-
- case ACPI_FIELD_QWORD_GRANULARITY:
-
- ACPI_MOVE_64_TO_64 (&(((u64 *) buffer)[index]), &merged_datum);
- break;
-
- default:
- /* Should not get here */
- break;
- }
-
- return_VOID;
-}
-
-
-/*******************************************************************************
- *
- * FUNCTION: acpi_ex_common_buffer_setup
- *
- * PARAMETERS: obj_desc - Field object
- * buffer_length - Length of caller's buffer
- * datum_count - Where the datum_count is returned
- *
- * RETURN: Status, datum_count
- *
- * DESCRIPTION: Common code to validate the incoming buffer size and compute
- * the number of field "datums" that must be read or written.
- * A "datum" is the smallest unit that can be read or written
- * to the field, it is either 1,2,4, or 8 bytes.
- *
- ******************************************************************************/
-
-acpi_status
-acpi_ex_common_buffer_setup (
- union acpi_operand_object *obj_desc,
- u32 buffer_length,
- u32 *datum_count)
-{
- u32 byte_field_length;
- u32 actual_byte_field_length;
-
-
- ACPI_FUNCTION_TRACE ("ex_common_buffer_setup");
-
-
- /*
- * Incoming buffer must be at least as long as the field, we do not
- * allow "partial" field reads/writes. We do not care if the buffer is
- * larger than the field, this typically happens when an integer is
- * read/written to a field that is actually smaller than an integer.
- */
- byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
- obj_desc->common_field.bit_length);
- if (byte_field_length > buffer_length) {
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "Field size %X (bytes) is too large for buffer (%X)\n",
- byte_field_length, buffer_length));
-
- return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
- }
-
- /*
- * Create "actual" field byte count (minimum number of bytes that
- * must be read), then convert to datum count (minimum number
- * of datum-sized units that must be read)
- */
- actual_byte_field_length = ACPI_ROUND_BITS_UP_TO_BYTES (
- obj_desc->common_field.start_field_bit_offset +
- obj_desc->common_field.bit_length);
-
-
- *datum_count = ACPI_ROUND_UP_TO (actual_byte_field_length,
- obj_desc->common_field.access_byte_width);
-
- ACPI_DEBUG_PRINT ((ACPI_DB_BFIELD,
- "buffer_bytes %X, actual_bytes %X, Datums %X, byte_gran %X\n",
- byte_field_length, actual_byte_field_length,
- *datum_count, obj_desc->common_field.access_byte_width));
-
- return_ACPI_STATUS (AE_OK);
-}
-
-
-/*******************************************************************************
- *
* FUNCTION: acpi_ex_extract_from_field
*
* PARAMETERS: obj_desc - Field to be read
@@ -835,128 +631,92 @@ acpi_ex_extract_from_field (
u32 buffer_length)
{
acpi_status status;
- u32 field_datum_byte_offset;
- u32 buffer_datum_offset;
- acpi_integer previous_raw_datum = 0;
- acpi_integer this_raw_datum = 0;
- acpi_integer merged_datum = 0;
+ acpi_integer raw_datum;
+ acpi_integer merged_datum;
+ u32 field_offset = 0;
+ u32 buffer_offset = 0;
+ u32 buffer_tail_bits;
u32 datum_count;
+ u32 field_datum_count;
u32 i;
ACPI_FUNCTION_TRACE ("ex_extract_from_field");
- /* Validate buffer, compute number of datums */
+ /* Validate target buffer and clear it */
- status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
+ obj_desc->common_field.bit_length)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Field size %X (bits) is too large for buffer (%X)\n",
+ obj_desc->common_field.bit_length, buffer_length));
- /*
- * Clear the caller's buffer (the whole buffer length as given)
- * This is very important, especially in the cases where the buffer
- * is longer than the size of the field.
- */
+ return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
+ }
ACPI_MEMSET (buffer, 0, buffer_length);
- field_datum_byte_offset = 0;
- buffer_datum_offset= 0;
-
- /* Read the entire field */
-
- for (i = 0; i < datum_count; i++) {
- status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
- &this_raw_datum, ACPI_READ);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
-
- /* We might actually be done if the request fits in one datum */
-
- if ((datum_count == 1) &&
- (obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) {
- /* 1) Shift the valid data bits down to start at bit 0 */
+ /* Compute the number of datums (access width data items) */
- merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset);
+ datum_count = ACPI_ROUND_UP_TO (
+ obj_desc->common_field.bit_length,
+ obj_desc->common_field.access_bit_width);
+ field_datum_count = ACPI_ROUND_UP_TO (
+ obj_desc->common_field.bit_length +
+ obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.access_bit_width);
- /* 2) Mask off any upper unused bits (bits not part of the field) */
+ /* Priming read from the field */
- if (obj_desc->common_field.end_buffer_valid_bits) {
- merged_datum &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_buffer_valid_bits);
- }
+ status = acpi_ex_field_datum_io (obj_desc, field_offset, &raw_datum, ACPI_READ);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
+ merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
- /* Store the datum to the caller buffer */
+ /* Read the rest of the field */
- acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,
- obj_desc->common_field.access_byte_width, buffer_datum_offset);
+ for (i = 1; i < field_datum_count; i++) {
+ /* Get next input datum from the field */
- return_ACPI_STATUS (AE_OK);
+ field_offset += obj_desc->common_field.access_byte_width;
+ status = acpi_ex_field_datum_io (obj_desc, field_offset,
+ &raw_datum, ACPI_READ);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
}
- /* Special handling for the last datum to ignore extra bits */
-
- if ((i >= (datum_count -1)) &&
- (obj_desc->common_field.end_field_valid_bits)) {
- /*
- * This is the last iteration of the loop. We need to clear
- * any unused bits (bits that are not part of this field) before
- * we store the final merged datum into the caller buffer.
- */
- this_raw_datum &=
- ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
- }
+ /* Merge with previous datum if necessary */
- /*
- * Create the (possibly) merged datum to be stored to the caller buffer
- */
- if (obj_desc->common_field.start_field_bit_offset == 0) {
- /* Field is not skewed and we can just copy the datum */
+ merged_datum |= raw_datum <<
+ (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
- acpi_ex_set_buffer_datum (this_raw_datum, buffer, buffer_length,
- obj_desc->common_field.access_byte_width, buffer_datum_offset);
- buffer_datum_offset++;
+ if (i == datum_count) {
+ break;
}
- else {
- /* Not aligned -- on the first iteration, just save the datum */
- if (i != 0) {
- /*
- * Put together the appropriate bits of the two raw data to make a
- * single complete field datum
- *
- * 1) Normalize the first datum down to bit 0
- */
- merged_datum = (previous_raw_datum >> obj_desc->common_field.start_field_bit_offset);
+ /* Write merged datum to target buffer */
- /* 2) Insert the second datum "above" the first datum */
+ ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
- merged_datum |= (this_raw_datum << obj_desc->common_field.datum_valid_bits);
-
- acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,
- obj_desc->common_field.access_byte_width, buffer_datum_offset);
- buffer_datum_offset++;
- }
+ buffer_offset += obj_desc->common_field.access_byte_width;
+ merged_datum = raw_datum >> obj_desc->common_field.start_field_bit_offset;
+ }
- /*
- * Save the raw datum that was just acquired since it may contain bits
- * of the *next* field datum
- */
- previous_raw_datum = this_raw_datum;
- }
+ /* Mask off any extra bits in the last datum */
- field_datum_byte_offset += obj_desc->common_field.access_byte_width;
+ buffer_tail_bits = obj_desc->common_field.bit_length % obj_desc->common_field.access_bit_width;
+ if (buffer_tail_bits) {
+ merged_datum &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
}
- /* For non-aligned case, there is one last datum to insert */
+ /* Write the last datum to the buffer */
- if (obj_desc->common_field.start_field_bit_offset != 0) {
- merged_datum = (this_raw_datum >> obj_desc->common_field.start_field_bit_offset);
-
- acpi_ex_set_buffer_datum (merged_datum, buffer, buffer_length,
- obj_desc->common_field.access_byte_width, buffer_datum_offset);
- }
+ ACPI_MEMCPY (((char *) buffer) + buffer_offset, &merged_datum,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
return_ACPI_STATUS (AE_OK);
}
@@ -983,169 +743,91 @@ acpi_ex_insert_into_field (
u32 buffer_length)
{
acpi_status status;
- u32 field_datum_byte_offset;
- u32 datum_offset;
acpi_integer mask;
acpi_integer merged_datum;
- acpi_integer previous_raw_datum;
- acpi_integer this_raw_datum;
+ acpi_integer raw_datum = 0;
+ u32 field_offset = 0;
+ u32 buffer_offset = 0;
+ u32 buffer_tail_bits;
u32 datum_count;
+ u32 field_datum_count;
+ u32 i;
ACPI_FUNCTION_TRACE ("ex_insert_into_field");
- /* Validate buffer, compute number of datums */
-
- status = acpi_ex_common_buffer_setup (obj_desc, buffer_length, &datum_count);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
-
- /*
- * Break the request into up to three parts (similar to an I/O request):
- * 1) non-aligned part at start
- * 2) aligned part in middle
- * 3) non-aligned part at the end
- */
- field_datum_byte_offset = 0;
- datum_offset= 0;
-
- /* Get a single datum from the caller's buffer */
-
- acpi_ex_get_buffer_datum (&previous_raw_datum, buffer, buffer_length,
- obj_desc->common_field.access_byte_width, datum_offset);
-
- /*
- * Part1:
- * Write a partial field datum if field does not begin on a datum boundary
- * Note: The code in this section also handles the aligned case
- *
- * Construct Mask with 1 bits where the field is, 0 bits elsewhere
- * (Only the bottom 5 bits of bit_length are valid for a shift operation)
- *
- * Mask off bits that are "below" the field (if any)
- */
- mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
-
- /* If the field fits in one datum, may need to mask upper bits */
+ /* Validate input buffer */
- if ((obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM) &&
- obj_desc->common_field.end_field_valid_bits) {
- /* There are bits above the field, mask them off also */
+ if (buffer_length < ACPI_ROUND_BITS_UP_TO_BYTES (
+ obj_desc->common_field.bit_length)) {
+ ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
+ "Field size %X (bits) is too large for buffer (%X)\n",
+ obj_desc->common_field.bit_length, buffer_length));
- mask &= ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
+ return_ACPI_STATUS (AE_BUFFER_OVERFLOW);
}
- /* Shift and mask the value into the field position */
-
- merged_datum = (previous_raw_datum << obj_desc->common_field.start_field_bit_offset);
- merged_datum &= mask;
-
- /* Apply the update rule (if necessary) and write the datum to the field */
+ /* Compute the number of datums (access width data items) */
- status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum,
- field_datum_byte_offset);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
+ mask = ACPI_MASK_BITS_BELOW (obj_desc->common_field.start_field_bit_offset);
+ datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length,
+ obj_desc->common_field.access_bit_width);
+ field_datum_count = ACPI_ROUND_UP_TO (obj_desc->common_field.bit_length +
+ obj_desc->common_field.start_field_bit_offset,
+ obj_desc->common_field.access_bit_width);
- /* We just wrote the first datum */
+ /* Get initial Datum from the input buffer */
- datum_offset++;
+ ACPI_MEMCPY (&raw_datum, buffer,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
- /* If the entire field fits within one datum, we are done. */
+ merged_datum = raw_datum << obj_desc->common_field.start_field_bit_offset;
- if ((datum_count == 1) &&
- (obj_desc->common_field.flags & AOPOBJ_SINGLE_DATUM)) {
- return_ACPI_STATUS (AE_OK);
- }
+ /* Write the entire field */
- /*
- * Part2:
- * Write the aligned data.
- *
- * We don't need to worry about the update rule for these data, because
- * all of the bits in each datum are part of the field.
- *
- * The last datum must be special cased because it might contain bits
- * that are not part of the field -- therefore the "update rule" must be
- * applied in Part3 below.
- */
- while (datum_offset < datum_count) {
- field_datum_byte_offset += obj_desc->common_field.access_byte_width;
+ for (i = 1; i < field_datum_count; i++) {
+ /* Write merged datum to the target field */
- /*
- * Get the next raw buffer datum. It may contain bits of the previous
- * field datum
- */
- acpi_ex_get_buffer_datum (&this_raw_datum, buffer, buffer_length,
- obj_desc->common_field.access_byte_width, datum_offset);
+ merged_datum &= mask;
+ status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
+ if (ACPI_FAILURE (status)) {
+ return_ACPI_STATUS (status);
+ }
- /* Create the field datum based on the field alignment */
+ /* Start new output datum by merging with previous input datum */
- if (obj_desc->common_field.start_field_bit_offset != 0) {
- /*
- * Put together appropriate bits of the two raw buffer data to make
- * a single complete field datum
- */
- merged_datum =
- (previous_raw_datum >> obj_desc->common_field.datum_valid_bits) |
- (this_raw_datum << obj_desc->common_field.start_field_bit_offset);
- }
- else {
- /* Field began aligned on datum boundary */
+ field_offset += obj_desc->common_field.access_byte_width;
+ merged_datum = raw_datum >>
+ (obj_desc->common_field.access_bit_width - obj_desc->common_field.start_field_bit_offset);
+ mask = ACPI_INTEGER_MAX;
- merged_datum = this_raw_datum;
+ if (i == datum_count) {
+ break;
}
- /*
- * Special handling for the last datum if the field does NOT end on
- * a datum boundary. Update Rule must be applied to the bits outside
- * the field.
- */
- datum_offset++;
- if ((datum_offset == datum_count) &&
- (obj_desc->common_field.end_field_valid_bits)) {
- /*
- * If there are dangling non-aligned bits, perform one more merged write
- * Else - field is aligned at the end, no need for any more writes
- */
+ /* Get the next input datum from the buffer */
- /*
- * Part3:
- * This is the last datum and the field does not end on a datum boundary.
- * Build the partial datum and write with the update rule.
- *
- * Mask off the unused bits above (after) the end-of-field
- */
- mask = ACPI_MASK_BITS_ABOVE (obj_desc->common_field.end_field_valid_bits);
- merged_datum &= mask;
+ buffer_offset += obj_desc->common_field.access_byte_width;
+ ACPI_MEMCPY (&raw_datum, ((char *) buffer) + buffer_offset,
+ ACPI_MIN(obj_desc->common_field.access_byte_width,
+ buffer_length - buffer_offset));
+ merged_datum |= raw_datum << obj_desc->common_field.start_field_bit_offset;
+ }
- /* Write the last datum with the update rule */
+ /* Mask off any extra bits in the last datum */
- status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum,
- field_datum_byte_offset);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
- }
- else {
- /* Normal (aligned) case -- write the completed datum */
+ buffer_tail_bits = (obj_desc->common_field.bit_length +
+ obj_desc->common_field.start_field_bit_offset) % obj_desc->common_field.access_bit_width;
+ if (buffer_tail_bits) {
+ mask &= ACPI_MASK_BITS_ABOVE (buffer_tail_bits);
+ }
- status = acpi_ex_field_datum_io (obj_desc, field_datum_byte_offset,
- &merged_datum, ACPI_WRITE);
- if (ACPI_FAILURE (status)) {
- return_ACPI_STATUS (status);
- }
- }
+ /* Write the last datum to the field */
- /*
- * Save the most recent datum since it may contain bits of the *next*
- * field datum. Update current byte offset.
- */
- previous_raw_datum = this_raw_datum;
- }
+ merged_datum &= mask;
+ status = acpi_ex_write_with_update_rule (obj_desc, mask, merged_datum, field_offset);
return_ACPI_STATUS (status);
}
diff --git a/drivers/acpi/executer/exmisc.c b/drivers/acpi/executer/exmisc.c
index 6bd793424a22..4addb47dd0f2 100644
--- a/drivers/acpi/executer/exmisc.c
+++ b/drivers/acpi/executer/exmisc.c
@@ -389,7 +389,7 @@ cleanup:
if (local_operand1 != operand1) {
acpi_ut_remove_reference (local_operand1);
}
- return_ACPI_STATUS (AE_OK);
+ return_ACPI_STATUS (status);
}
diff --git a/drivers/acpi/executer/exoparg1.c b/drivers/acpi/executer/exoparg1.c
index 6e3193964540..d57fc8195223 100644
--- a/drivers/acpi/executer/exoparg1.c
+++ b/drivers/acpi/executer/exoparg1.c
@@ -507,6 +507,10 @@ acpi_ex_opcode_1A_1T_1R (
status = acpi_ex_convert_to_string (operand[0], &return_desc,
ACPI_EXPLICIT_CONVERT_DECIMAL);
+ if (return_desc == operand[0]) {
+ /* No conversion performed, add ref to handle return value */
+ acpi_ut_add_reference (return_desc);
+ }
break;
@@ -514,12 +518,20 @@ acpi_ex_opcode_1A_1T_1R (
status = acpi_ex_convert_to_string (operand[0], &return_desc,
ACPI_EXPLICIT_CONVERT_HEX);
+ if (return_desc == operand[0]) {
+ /* No conversion performed, add ref to handle return value */
+ acpi_ut_add_reference (return_desc);
+ }
break;
case AML_TO_BUFFER_OP: /* to_buffer (Data, Result) */
status = acpi_ex_convert_to_buffer (operand[0], &return_desc);
+ if (return_desc == operand[0]) {
+ /* No conversion performed, add ref to handle return value */
+ acpi_ut_add_reference (return_desc);
+ }
break;
@@ -527,6 +539,10 @@ acpi_ex_opcode_1A_1T_1R (
status = acpi_ex_convert_to_integer (operand[0], &return_desc,
ACPI_ANY_BASE);
+ if (return_desc == operand[0]) {
+ /* No conversion performed, add ref to handle return value */
+ acpi_ut_add_reference (return_desc);
+ }
break;
@@ -551,10 +567,12 @@ acpi_ex_opcode_1A_1T_1R (
goto cleanup;
}
- /*
- * Store the return value computed above into the target object
- */
- status = acpi_ex_store (return_desc, operand[1], walk_state);
+ if (ACPI_SUCCESS (status)) {
+ /*
+ * Store the return value computed above into the target object
+ */
+ status = acpi_ex_store (return_desc, operand[1], walk_state);
+ }
cleanup:
diff --git a/drivers/acpi/executer/exprep.c b/drivers/acpi/executer/exprep.c
index 0834af85f971..f12c480668e9 100644
--- a/drivers/acpi/executer/exprep.c
+++ b/drivers/acpi/executer/exprep.c
@@ -339,6 +339,8 @@ acpi_ex_prep_common_field_object (
obj_desc->common_field.access_byte_width = (u8)
ACPI_DIV_8 (access_bit_width); /* 1, 2, 4, 8 */
+ obj_desc->common_field.access_bit_width = (u8) access_bit_width;
+
/*
* base_byte_offset is the address of the start of the field within the
* region. It is the byte address of the first *datum* (field-width data
@@ -362,28 +364,6 @@ acpi_ex_prep_common_field_object (
(field_bit_position - ACPI_MUL_8 (obj_desc->common_field.base_byte_offset));
/*
- * Valid bits -- the number of bits that compose a partial datum,
- * 1) At the end of the field within the region (arbitrary starting bit
- * offset)
- * 2) At the end of a buffer used to contain the field (starting offset
- * always zero)
- */
- obj_desc->common_field.end_field_valid_bits = (u8)
- ((obj_desc->common_field.start_field_bit_offset + field_bit_length) %
- access_bit_width);
- /* start_buffer_bit_offset always = 0 */
-
- obj_desc->common_field.end_buffer_valid_bits = (u8)
- (field_bit_length % access_bit_width);
-
- /*
- * datum_valid_bits is the number of valid field bits in the first
- * field datum.
- */
- obj_desc->common_field.datum_valid_bits = (u8)
- (access_bit_width - obj_desc->common_field.start_field_bit_offset);
-
- /*
* Does the entire field fit within a single field access element? (datum)
* (i.e., without crossing a datum boundary)
*/
diff --git a/drivers/acpi/parser/psopcode.c b/drivers/acpi/parser/psopcode.c
index 6025b75d7539..eff2272f930a 100644
--- a/drivers/acpi/parser/psopcode.c
+++ b/drivers/acpi/parser/psopcode.c
@@ -318,7 +318,7 @@
#define ARGI_SHIFT_LEFT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SHIFT_RIGHT_OP ARGI_LIST3 (ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
#define ARGI_SIGNAL_OP ARGI_LIST1 (ARGI_EVENT)
-#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_REFERENCE) /* Force delay of operand resolution */
+#define ARGI_SIZE_OF_OP ARGI_LIST1 (ARGI_DATAOBJECT)
#define ARGI_SLEEP_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_STALL_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_STATICSTRING_OP ARGI_INVALID_OPCODE
@@ -333,7 +333,7 @@
#define ARGI_TO_HEX_STR_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_INTEGER_OP ARGI_LIST2 (ARGI_COMPUTEDATA,ARGI_FIXED_TARGET)
#define ARGI_TO_STRING_OP ARGI_LIST3 (ARGI_BUFFER, ARGI_INTEGER, ARGI_FIXED_TARGET)
-#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_REFERENCE) /* Force delay of operand resolution */
+#define ARGI_TYPE_OP ARGI_LIST1 (ARGI_ANYTYPE)
#define ARGI_UNLOAD_OP ARGI_LIST1 (ARGI_DDBHANDLE)
#define ARGI_VAR_PACKAGE_OP ARGI_LIST1 (ARGI_INTEGER)
#define ARGI_WAIT_OP ARGI_LIST2 (ARGI_EVENT, ARGI_INTEGER)
@@ -521,14 +521,14 @@ const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES] =
/* 2D */ ACPI_OP ("FindSetRightBit", ARGP_FIND_SET_RIGHT_BIT_OP,ARGI_FIND_SET_RIGHT_BIT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_1T_1R, AML_FLAGS_EXEC_1A_1T_1R | AML_CONSTANT),
/* 2E */ ACPI_OP ("DerefOf", ARGP_DEREF_OF_OP, ARGI_DEREF_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
/* 2F */ ACPI_OP ("Notify", ARGP_NOTIFY_OP, ARGI_NOTIFY_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_0R, AML_FLAGS_EXEC_2A_0T_0R),
-/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
+/* 30 */ ACPI_OP ("SizeOf", ARGP_SIZE_OF_OP, ARGI_SIZE_OF_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
/* 31 */ ACPI_OP ("Index", ARGP_INDEX_OP, ARGI_INDEX_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_1T_1R, AML_FLAGS_EXEC_2A_1T_1R | AML_CONSTANT),
/* 32 */ ACPI_OP ("Match", ARGP_MATCH_OP, ARGI_MATCH_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_6A_0T_1R, AML_FLAGS_EXEC_6A_0T_1R | AML_CONSTANT),
/* 33 */ ACPI_OP ("CreateDWordField", ARGP_CREATE_DWORD_FIELD_OP,ARGI_CREATE_DWORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 34 */ ACPI_OP ("CreateWordField", ARGP_CREATE_WORD_FIELD_OP, ARGI_CREATE_WORD_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 35 */ ACPI_OP ("CreateByteField", ARGP_CREATE_BYTE_FIELD_OP, ARGI_CREATE_BYTE_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
/* 36 */ ACPI_OP ("CreateBitField", ARGP_CREATE_BIT_FIELD_OP, ARGI_CREATE_BIT_FIELD_OP, ACPI_TYPE_BUFFER_FIELD, AML_CLASS_CREATE, AML_TYPE_CREATE_FIELD, AML_HAS_ARGS | AML_NSOBJECT | AML_NSNODE | AML_DEFER | AML_CREATE),
-/* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R),
+/* 37 */ ACPI_OP ("ObjectType", ARGP_TYPE_OP, ARGI_TYPE_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_NO_OPERAND_RESOLVE),
/* 38 */ ACPI_OP ("LAnd", ARGP_LAND_OP, ARGI_LAND_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
/* 39 */ ACPI_OP ("LOr", ARGP_LOR_OP, ARGI_LOR_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_2A_0T_1R, AML_FLAGS_EXEC_2A_0T_1R | AML_LOGICAL_NUMERIC | AML_CONSTANT),
/* 3A */ ACPI_OP ("LNot", ARGP_LNOT_OP, ARGI_LNOT_OP, ACPI_TYPE_ANY, AML_CLASS_EXECUTE, AML_TYPE_EXEC_1A_0T_1R, AML_FLAGS_EXEC_1A_0T_1R | AML_CONSTANT),
diff --git a/include/acpi/acconfig.h b/include/acpi/acconfig.h
index 8d9170cc1f4e..9949b1c51c22 100644
--- a/include/acpi/acconfig.h
+++ b/include/acpi/acconfig.h
@@ -64,7 +64,7 @@
/* Version string */
-#define ACPI_CA_VERSION 0x20041119
+#define ACPI_CA_VERSION 0x20041203
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
diff --git a/include/acpi/acmacros.h b/include/acpi/acmacros.h
index 22be6763de9e..7e30ff9e5ecb 100644
--- a/include/acpi/acmacros.h
+++ b/include/acpi/acmacros.h
@@ -55,6 +55,7 @@
#define ACPI_SET_BIT(target,bit) ((target) |= (bit))
#define ACPI_CLEAR_BIT(target,bit) ((target) &= ~(bit))
+#define ACPI_MIN(a,b) (((a)<(b))?(a):(b))
#if ACPI_MACHINE_WIDTH == 16
diff --git a/include/acpi/acobject.h b/include/acpi/acobject.h
index 09d6a5af268c..5fb2969ea481 100644
--- a/include/acpi/acobject.h
+++ b/include/acpi/acobject.h
@@ -94,9 +94,7 @@
u32 bit_length; /* Length of field in bits */\
u32 base_byte_offset; /* Byte offset within containing object */\
u8 start_field_bit_offset;/* Bit offset within first field datum (0-63) */\
- u8 datum_valid_bits; /* Valid bit in first "Field datum" */\
- u8 end_field_valid_bits; /* Valid bits in the last "field datum" */\
- u8 end_buffer_valid_bits; /* Valid bits in the last "buffer datum" */\
+ u8 access_bit_width; /* Read/Write size in bits (8-64) */\
u32 value; /* Value to store into the Bank or Index register */\
struct acpi_namespace_node *node; /* Link back to parent node */
diff --git a/include/acpi/amlcode.h b/include/acpi/amlcode.h
index c4fa67dfec64..263c69b35ecb 100644
--- a/include/acpi/amlcode.h
+++ b/include/acpi/amlcode.h
@@ -320,6 +320,7 @@
#define AML_HAS_TARGET 0x0800
#define AML_HAS_ARGS 0x1000
#define AML_CONSTANT 0x2000
+#define AML_NO_OPERAND_RESOLVE 0x4000
/* Convenient flag groupings */