Commit 53cf1744 authored by Bob Moore's avatar Bob Moore Committed by Len Brown

ACPICA: Fix for Alias operator to see target child objects

Fixed a problem with the Alias operator when the target of the
alias is a named ASL operator that opens a new scope -- Scope,
Device, PowerResource, Processor, and ThermalZone. In these cases,
any children of the original operator could not be accessed via
the alias, potentially causing unexpected AE_NOT_FOUND exceptions.
Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarAlexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 1c12a7dd
...@@ -96,16 +96,28 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) ...@@ -96,16 +96,28 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
* to the original Node. * to the original Node.
*/ */
switch (target_node->type) { switch (target_node->type) {
/* For these types, the sub-object can change dynamically via a Store */
case ACPI_TYPE_INTEGER: case ACPI_TYPE_INTEGER:
case ACPI_TYPE_STRING: case ACPI_TYPE_STRING:
case ACPI_TYPE_BUFFER: case ACPI_TYPE_BUFFER:
case ACPI_TYPE_PACKAGE: case ACPI_TYPE_PACKAGE:
case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_BUFFER_FIELD:
/*
* These types open a new scope, so we need the NS node in order to access
* any children.
*/
case ACPI_TYPE_DEVICE:
case ACPI_TYPE_POWER:
case ACPI_TYPE_PROCESSOR:
case ACPI_TYPE_THERMAL:
case ACPI_TYPE_LOCAL_SCOPE:
/* /*
* The new alias has the type ALIAS and points to the original * The new alias has the type ALIAS and points to the original
* NS node, not the object itself. This is because for these * NS node, not the object itself.
* types, the object can change dynamically via a Store.
*/ */
alias_node->type = ACPI_TYPE_LOCAL_ALIAS; alias_node->type = ACPI_TYPE_LOCAL_ALIAS;
alias_node->object = alias_node->object =
...@@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state) ...@@ -115,9 +127,7 @@ acpi_status acpi_ex_create_alias(struct acpi_walk_state *walk_state)
case ACPI_TYPE_METHOD: case ACPI_TYPE_METHOD:
/* /*
* The new alias has the type ALIAS and points to the original * Control method aliases need to be differentiated
* NS node, not the object itself. This is because for these
* types, the object can change dynamically via a Store.
*/ */
alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS; alias_node->type = ACPI_TYPE_LOCAL_METHOD_ALIAS;
alias_node->object = alias_node->object =
......
...@@ -581,6 +581,29 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, ...@@ -581,6 +581,29 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
/* More segments to follow? */
if (num_segments > 0) {
/*
* If we have an alias to an object that opens a scope (such as a
* device or processor), we need to dereference the alias here so that
* we can access any children of the original node (via the remaining
* segments).
*/
if (this_node->type == ACPI_TYPE_LOCAL_ALIAS) {
if (acpi_ns_opens_scope
(((struct acpi_namespace_node *)this_node->
object)->type)) {
this_node =
(struct acpi_namespace_node *)
this_node->object;
}
}
}
/* Special handling for the last segment (num_segments == 0) */
else {
/* /*
* Sanity typecheck of the target object: * Sanity typecheck of the target object:
* *
...@@ -594,20 +617,20 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, ...@@ -594,20 +617,20 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
* *
* Then we have a type mismatch. Just warn and ignore it. * Then we have a type mismatch. Just warn and ignore it.
*/ */
if ((num_segments == 0) && if ((type_to_check_for != ACPI_TYPE_ANY) &&
(type_to_check_for != ACPI_TYPE_ANY) &&
(type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) && (type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
(type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) && (type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS)
(type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) && && (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE)
(this_node->type != ACPI_TYPE_ANY) && && (this_node->type != ACPI_TYPE_ANY)
(this_node->type != type_to_check_for)) { && (this_node->type != type_to_check_for)) {
/* Complain about a type mismatch */ /* Complain about a type mismatch */
ACPI_WARNING((AE_INFO, ACPI_WARNING((AE_INFO,
"NsLookup: Type mismatch on %4.4s (%s), searching for (%s)", "NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
ACPI_CAST_PTR(char, &simple_name), ACPI_CAST_PTR(char, &simple_name),
acpi_ut_get_type_name(this_node->type), acpi_ut_get_type_name(this_node->
type),
acpi_ut_get_type_name acpi_ut_get_type_name
(type_to_check_for))); (type_to_check_for)));
} }
...@@ -615,11 +638,12 @@ acpi_ns_lookup(union acpi_generic_state *scope_info, ...@@ -615,11 +638,12 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
/* /*
* If this is the last name segment and we are not looking for a * If this is the last name segment and we are not looking for a
* specific type, but the type of found object is known, use that type * specific type, but the type of found object is known, use that type
* to see if it opens a scope. * to (later) see if it opens a scope.
*/ */
if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) { if (type == ACPI_TYPE_ANY) {
type = this_node->type; type = this_node->type;
} }
}
/* Point to next name segment and make this node current */ /* Point to next name segment and make this node current */
......
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