Commit 82d6b1e6 authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] ACPICA 20050211 from Bob Moore

Implemented ACPI 3.0 support for implicit conversion within
the Match() operator. match_obj can now be of type
integer, buffer, or string instead of just type integer.
Package elements are implicitly converted to the type
of the match_obj. This change aligns the behavior of
Match() with the behavior of the other logical operators
(LLess(), etc.)  It also requires an errata change to the
ACPI specification as this support was intended for ACPI
3.0, but was inadvertently omitted.

Fixed a problem with the internal implicit "to buffer"
conversion.  Strings that are converted to buffers will
cause buffer truncation if the string is smaller than the
target buffer. Integers that are converted to buffers will
not cause buffer truncation, only zero extension (both as
per the ACPI spec.) The problem was introduced when code
was added to truncate the buffer, but this should not be
performed in all cases, only the string case.

Fixed a problem with the Buffer and Package operators
where the interpreter would get confused if two such
operators were used as operands to an ASL operator (such
as LLess(Buffer(1){0},Buffer(1){1}).  The internal result
stack was not being popped after the execution of these
operators, resulting in an AE_NO_RETURN_VALUE exception.

Fixed a problem with constructs of the form
Store(Index(...),...). The reference object returned from
Index was inadvertently resolved to an actual value. This
problem was introduced in version 20050114 when the
behavior of Store() was modified to restrict the object
types that can be used as the source operand (to match
the ACPI specification.)

Reduced stack use in acpi_get_object_info().
parent 7ba183e8
......@@ -578,6 +578,13 @@ acpi_ds_exec_end_op (
break;
}
/* Done with this result state (Now that operand stack is built) */
status = acpi_ds_result_stack_pop (walk_state);
if (ACPI_FAILURE (status)) {
goto cleanup;
}
/*
* If a result object was returned from above, push it on the
* current result stack
......
......@@ -81,75 +81,119 @@
* FUNCTION: acpi_ex_do_match
*
* PARAMETERS: match_op - The AML match operand
* package_value - Value from the target package
* match_value - Value to be matched
* package_obj - Object from the target package
* match_obj - Object to be matched
*
* RETURN: TRUE if the match is successful, FALSE otherwise
*
* DESCRIPTION: Implements the low-level match for the ASL Match operator
* DESCRIPTION: Implements the low-level match for the ASL Match operator.
* Package elements will be implicitly converted to the type of
* the match object (Integer/Buffer/String).
*
******************************************************************************/
u8
acpi_ex_do_match (
u32 match_op,
acpi_integer package_value,
acpi_integer match_value)
union acpi_operand_object *package_obj,
union acpi_operand_object *match_obj)
{
u8 logical_result = TRUE;
acpi_status status;
/*
* Note: Since the package_obj/match_obj ordering is opposite to that of
* the standard logical operators, we have to reverse them when we call
* do_logical_op in order to make the implicit conversion rules work
* correctly. However, this means we have to flip the entire equation
* also. A bit ugly perhaps, but overall, better than fussing the
* parameters around at runtime, over and over again.
*
* Below, P[i] refers to the package element, M refers to the Match object.
*/
switch (match_op) {
case MATCH_MTR: /* always true */
case MATCH_MTR:
break;
/* Always true */
break;
case MATCH_MEQ: /* true if equal */
case MATCH_MEQ:
if (package_value != match_value) {
/*
* True if equal: (P[i] == M)
* Change to: (M == P[i])
*/
status = acpi_ex_do_logical_op (AML_LEQUAL_OP, match_obj, package_obj,
&logical_result);
if (ACPI_FAILURE (status)) {
return (FALSE);
}
break;
case MATCH_MLE:
case MATCH_MLE: /* true if less than or equal */
if (package_value > match_value) {
/*
* True if less than or equal: (P[i] <= M) (P[i] not_greater than M)
* Change to: (M >= P[i]) (M not_less than P[i])
*/
status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
&logical_result);
if (ACPI_FAILURE (status)) {
return (FALSE);
}
logical_result = (u8) !logical_result;
break;
case MATCH_MLT:
case MATCH_MLT: /* true if less than */
if (package_value >= match_value) {
/*
* True if less than: (P[i] < M)
* Change to: (M > P[i])
*/
status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
&logical_result);
if (ACPI_FAILURE (status)) {
return (FALSE);
}
break;
case MATCH_MGE:
case MATCH_MGE: /* true if greater than or equal */
if (package_value < match_value) {
/*
* True if greater than or equal: (P[i] >= M) (P[i] not_less than M)
* Change to: (M <= P[i]) (M not_greater than P[i])
*/
status = acpi_ex_do_logical_op (AML_LGREATER_OP, match_obj, package_obj,
&logical_result);
if (ACPI_FAILURE (status)) {
return (FALSE);
}
logical_result = (u8)!logical_result;
break;
case MATCH_MGT:
case MATCH_MGT: /* true if greater than */
if (package_value <= match_value) {
/*
* True if greater than: (P[i] > M)
* Change to: (M < P[i])
*/
status = acpi_ex_do_logical_op (AML_LLESS_OP, match_obj, package_obj,
&logical_result);
if (ACPI_FAILURE (status)) {
return (FALSE);
}
break;
default:
default: /* undefined */
/* Undefined */
return (FALSE);
}
return TRUE;
return logical_result;
}
......@@ -182,19 +226,21 @@ acpi_ex_opcode_6A_0T_1R (
switch (walk_state->opcode) {
case AML_MATCH_OP:
/*
* Match (search_package[0], match_op1[1], match_object1[2],
* match_op2[3], match_object2[4], start_index[5])
* Match (search_pkg[0], match_op1[1], match_obj1[2],
* match_op2[3], match_obj2[4], start_index[5])
*/
/* Validate match comparison sub-opcodes */
/* Validate both Match Term Operators (MTR, MEQ, etc.) */
if ((operand[1]->integer.value > MAX_MATCH_OPERATOR) ||
(operand[3]->integer.value > MAX_MATCH_OPERATOR)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "operation encoding out of range\n"));
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Match operator out of range\n"));
status = AE_AML_OPERAND_VALUE;
goto cleanup;
}
/* Get the package start_index, validate against the package length */
index = (u32) operand[5]->integer.value;
if (index >= (u32) operand[0]->package.count) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index beyond package end\n"));
......@@ -202,6 +248,8 @@ acpi_ex_opcode_6A_0T_1R (
goto cleanup;
}
/* Create an integer for the return value */
return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
if (!return_desc) {
status = AE_NO_MEMORY;
......@@ -214,37 +262,39 @@ acpi_ex_opcode_6A_0T_1R (
return_desc->integer.value = ACPI_INTEGER_MAX;
/*
* Examine each element until a match is found. Within the loop,
* Examine each element until a match is found. Both match conditions
* must be satisfied for a match to occur. Within the loop,
* "continue" signifies that the current element does not match
* and the next should be examined.
*
* Upon finding a match, the loop will terminate via "break" at
* the bottom. If it terminates "normally", match_value will be -1
* (its initial value) indicating that no match was found. When
* returned as a Number, this will produce the Ones value as specified.
* the bottom. If it terminates "normally", match_value will be
* ACPI_INTEGER_MAX (Ones) (its initial value) indicating that no
* match was found.
*/
for ( ; index < operand[0]->package.count; index++) {
/* Get the current package element */
this_element = operand[0]->package.elements[index];
/*
* Treat any NULL or non-numeric elements as non-matching.
*/
if (!this_element ||
ACPI_GET_OBJECT_TYPE (this_element) != ACPI_TYPE_INTEGER) {
/* Treat any uninitialized (NULL) elements as non-matching */
if (!this_element) {
continue;
}
/*
* "continue" (proceed to next iteration of enclosing
* "for" loop) signifies a non-match.
* Both match conditions must be satisfied. Execution of a continue
* (proceed to next iteration of enclosing for loop) signifies a
* non-match.
*/
if (!acpi_ex_do_match ((u32) operand[1]->integer.value,
this_element->integer.value, operand[2]->integer.value)) {
this_element, operand[2])) {
continue;
}
if (!acpi_ex_do_match ((u32) operand[3]->integer.value,
this_element->integer.value, operand[4]->integer.value)) {
this_element, operand[4])) {
continue;
}
......@@ -253,7 +303,6 @@ acpi_ex_opcode_6A_0T_1R (
return_desc->integer.value = index;
break;
}
break;
......
......@@ -312,7 +312,7 @@ acpi_ex_resolve_operands (
goto next_operand;
case ARGI_ANYTYPE:
case ARGI_DATAREFOBJ: /* Store operator only */
/*
* We don't want to resolve index_op reference objects during
......
......@@ -206,6 +206,7 @@ acpi_ex_store_object_to_object (
{
union acpi_operand_object *actual_src_desc;
acpi_status status = AE_OK;
acpi_object_type original_src_type;
ACPI_FUNCTION_TRACE_PTR ("ex_store_object_to_object", source_desc);
......@@ -222,7 +223,8 @@ acpi_ex_store_object_to_object (
return_ACPI_STATUS (status);
}
if (ACPI_GET_OBJECT_TYPE (source_desc) != ACPI_GET_OBJECT_TYPE (dest_desc)) {
original_src_type = ACPI_GET_OBJECT_TYPE (source_desc);
if (original_src_type != ACPI_GET_OBJECT_TYPE (dest_desc)) {
/*
* The source type does not match the type of the destination.
* Perform the "implicit conversion" of the source to the current type
......@@ -232,8 +234,8 @@ acpi_ex_store_object_to_object (
* Otherwise, actual_src_desc is a temporary object to hold the
* converted object.
*/
status = acpi_ex_convert_to_target_type (ACPI_GET_OBJECT_TYPE (dest_desc), source_desc,
&actual_src_desc, walk_state);
status = acpi_ex_convert_to_target_type (ACPI_GET_OBJECT_TYPE (dest_desc),
source_desc, &actual_src_desc, walk_state);
if (ACPI_FAILURE (status)) {
return_ACPI_STATUS (status);
}
......@@ -269,12 +271,18 @@ acpi_ex_store_object_to_object (
case ACPI_TYPE_BUFFER:
status = acpi_ex_store_buffer_to_buffer (actual_src_desc, dest_desc);
/*
* Note: There is different store behavior depending on the original
* source type
*/
status = acpi_ex_store_buffer_to_buffer (original_src_type, actual_src_desc,
dest_desc);
break;
case ACPI_TYPE_PACKAGE:
status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, &dest_desc, walk_state);
status = acpi_ut_copy_iobject_to_iobject (actual_src_desc, &dest_desc,
walk_state);
break;
default:
......
......@@ -66,6 +66,7 @@
acpi_status
acpi_ex_store_buffer_to_buffer (
acpi_object_type original_src_type,
union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc)
{
......@@ -104,10 +105,17 @@ acpi_ex_store_buffer_to_buffer (
ACPI_MEMSET (target_desc->buffer.pointer, 0, target_desc->buffer.length);
ACPI_MEMCPY (target_desc->buffer.pointer, buffer, length);
/*
* If the original source was a string, we must truncate the buffer,
* according to the ACPI spec. Integer-to-Buffer and Buffer-to-Buffer
* copy must not truncate the original buffer.
*/
if (original_src_type == ACPI_TYPE_STRING) {
/* Set the new length of the target */
target_desc->buffer.length = length;
}
}
else {
/* Truncate the source, copy only what will fit */
......
......@@ -237,7 +237,7 @@ acpi_get_object_info (
{
acpi_status status;
struct acpi_namespace_node *node;
struct acpi_device_info info;
struct acpi_device_info *info;
struct acpi_device_info *return_info;
struct acpi_compatible_id_list *cid_list = NULL;
acpi_size size;
......@@ -254,55 +254,59 @@ acpi_get_object_info (
return (status);
}
info = ACPI_MEM_CALLOCATE (sizeof (struct acpi_device_info));
if (!info) {
return (AE_NO_MEMORY);
}
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return (status);
goto cleanup;
}
node = acpi_ns_map_handle_to_node (handle);
if (!node) {
(void) acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
return (AE_BAD_PARAMETER);
goto cleanup;
}
/* Init return structure */
size = sizeof (struct acpi_device_info);
ACPI_MEMSET (&info, 0, size);
info.type = node->type;
info.name = node->name.integer;
info.valid = 0;
info->type = node->type;
info->name = node->name.integer;
info->valid = 0;
status = acpi_ut_release_mutex (ACPI_MTX_NAMESPACE);
if (ACPI_FAILURE (status)) {
return (status);
goto cleanup;
}
/* If not a device, we are all done */
if (info.type == ACPI_TYPE_DEVICE) {
if (info->type == ACPI_TYPE_DEVICE) {
/*
* Get extra info for ACPI Devices objects only:
* Run the Device _HID, _UID, _CID, _STA, _ADR and _sx_d methods.
*
* Note: none of these methods are required, so they may or may
* not be present for this device. The Info.Valid bitfield is used
* not be present for this device. The Info->Valid bitfield is used
* to indicate which methods were found and ran successfully.
*/
/* Execute the Device._HID method */
status = acpi_ut_execute_HID (node, &info.hardware_id);
status = acpi_ut_execute_HID (node, &info->hardware_id);
if (ACPI_SUCCESS (status)) {
info.valid |= ACPI_VALID_HID;
info->valid |= ACPI_VALID_HID;
}
/* Execute the Device._UID method */
status = acpi_ut_execute_UID (node, &info.unique_id);
status = acpi_ut_execute_UID (node, &info->unique_id);
if (ACPI_SUCCESS (status)) {
info.valid |= ACPI_VALID_UID;
info->valid |= ACPI_VALID_UID;
}
/* Execute the Device._CID method */
......@@ -311,32 +315,30 @@ acpi_get_object_info (
if (ACPI_SUCCESS (status)) {
size += ((acpi_size) cid_list->count - 1) *
sizeof (struct acpi_compatible_id);
info.valid |= ACPI_VALID_CID;
info->valid |= ACPI_VALID_CID;
}
/* Execute the Device._STA method */
status = acpi_ut_execute_STA (node, &info.current_status);
status = acpi_ut_execute_STA (node, &info->current_status);
if (ACPI_SUCCESS (status)) {
info.valid |= ACPI_VALID_STA;
info->valid |= ACPI_VALID_STA;
}
/* Execute the Device._ADR method */
status = acpi_ut_evaluate_numeric_object (METHOD_NAME__ADR, node,
&info.address);
&info->address);
if (ACPI_SUCCESS (status)) {
info.valid |= ACPI_VALID_ADR;
info->valid |= ACPI_VALID_ADR;
}
/* Execute the Device._sx_d methods */
status = acpi_ut_execute_sxds (node, info.highest_dstates);
status = acpi_ut_execute_sxds (node, info->highest_dstates);
if (ACPI_SUCCESS (status)) {
info.valid |= ACPI_VALID_SXDS;
info->valid |= ACPI_VALID_SXDS;
}
status = AE_OK;
}
/* Validate/Allocate/Clear caller buffer */
......@@ -349,7 +351,7 @@ acpi_get_object_info (
/* Populate the return buffer */
return_info = buffer->pointer;
ACPI_MEMCPY (return_info, &info, sizeof (struct acpi_device_info));
ACPI_MEMCPY (return_info, info, sizeof (struct acpi_device_info));
if (cid_list) {
ACPI_MEMCPY (&return_info->compatibility_id, cid_list, cid_list->size);
......@@ -357,6 +359,7 @@ acpi_get_object_info (
cleanup:
ACPI_MEM_FREE (info);
if (cid_list) {
ACPI_MEM_FREE (cid_list);
}
......
......@@ -289,7 +289,7 @@
#define ARGI_LOCAL6 ARG_NONE
#define ARGI_LOCAL7 ARG_NONE
#define ARGI_LOR_OP ARGI_LIST2 (ARGI_INTEGER, ARGI_INTEGER)
#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER, ARGI_INTEGER)
#define ARGI_MATCH_OP ARGI_LIST6 (ARGI_PACKAGE, ARGI_INTEGER, ARGI_COMPUTEDATA, ARGI_INTEGER,ARGI_COMPUTEDATA,ARGI_INTEGER)
#define ARGI_METHOD_OP ARGI_INVALID_OPCODE
#define ARGI_METHODCALL_OP ARGI_INVALID_OPCODE
#define ARGI_MID_OP ARGI_LIST4 (ARGI_BUFFER_OR_STRING,ARGI_INTEGER, ARGI_INTEGER, ARGI_TARGETREF)
......
......@@ -269,7 +269,7 @@ acpi_tb_convert_fadt1 (
* that immediately follows.
*/
ACPI_MEMCPY (&local_fadt->reset_register,
&((struct fadt_descriptor_rev2_minus *) original_fadt)->reset_register,
&(ACPI_CAST_PTR (struct fadt_descriptor_rev2_minus, original_fadt))->reset_register,
sizeof (struct acpi_generic_address) + 1);
}
else {
......
......@@ -64,7 +64,7 @@
/* Version string */
#define ACPI_CA_VERSION 0x20050125
#define ACPI_CA_VERSION 0x20050211
/*
* OS name, used for the _OS object. The _OS object is essentially obsolete,
......
......@@ -217,8 +217,8 @@ acpi_ex_opcode_6A_0T_1R (
u8
acpi_ex_do_match (
u32 match_op,
acpi_integer package_value,
acpi_integer match_value);
union acpi_operand_object *package_obj,
union acpi_operand_object *match_obj);
acpi_status
acpi_ex_get_object_reference (
......@@ -617,6 +617,7 @@ acpi_ex_store_object_to_object (
acpi_status
acpi_ex_store_buffer_to_buffer (
acpi_object_type original_src_type,
union acpi_operand_object *source_desc,
union acpi_operand_object *target_desc);
......
......@@ -81,6 +81,8 @@
#define ACPI_USE_NATIVE_DIVIDE
#endif
#define __cdecl
#define ACPI_FLUSH_CPU_CACHE()
#endif /* __KERNEL__ */
/* Linux uses GCC */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment