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: 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:
parent
1c12a7dde1
commit
53cf174409
2 changed files with 74 additions and 40 deletions
|
@ -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)
|
||||||
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,44 +581,68 @@ acpi_ns_lookup(union acpi_generic_state *scope_info,
|
||||||
return_ACPI_STATUS(status);
|
return_ACPI_STATUS(status);
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/* More segments to follow? */
|
||||||
* Sanity typecheck of the target object:
|
|
||||||
*
|
|
||||||
* If 1) This is the last segment (num_segments == 0)
|
|
||||||
* 2) And we are looking for a specific type
|
|
||||||
* (Not checking for TYPE_ANY)
|
|
||||||
* 3) Which is not an alias
|
|
||||||
* 4) Which is not a local type (TYPE_SCOPE)
|
|
||||||
* 5) And the type of target object is known (not TYPE_ANY)
|
|
||||||
* 6) And target object does not match what we are looking for
|
|
||||||
*
|
|
||||||
* Then we have a type mismatch. Just warn and ignore it.
|
|
||||||
*/
|
|
||||||
if ((num_segments == 0) &&
|
|
||||||
(type_to_check_for != ACPI_TYPE_ANY) &&
|
|
||||||
(type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
|
|
||||||
(type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS) &&
|
|
||||||
(type_to_check_for != ACPI_TYPE_LOCAL_SCOPE) &&
|
|
||||||
(this_node->type != ACPI_TYPE_ANY) &&
|
|
||||||
(this_node->type != type_to_check_for)) {
|
|
||||||
|
|
||||||
/* Complain about a type mismatch */
|
if (num_segments > 0) {
|
||||||
|
/*
|
||||||
ACPI_WARNING((AE_INFO,
|
* If we have an alias to an object that opens a scope (such as a
|
||||||
"NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
|
* device or processor), we need to dereference the alias here so that
|
||||||
ACPI_CAST_PTR(char, &simple_name),
|
* we can access any children of the original node (via the remaining
|
||||||
acpi_ut_get_type_name(this_node->type),
|
* segments).
|
||||||
acpi_ut_get_type_name
|
*/
|
||||||
(type_to_check_for)));
|
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) */
|
||||||
* 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
|
else {
|
||||||
* to see if it opens a scope.
|
/*
|
||||||
*/
|
* Sanity typecheck of the target object:
|
||||||
if ((num_segments == 0) && (type == ACPI_TYPE_ANY)) {
|
*
|
||||||
type = this_node->type;
|
* If 1) This is the last segment (num_segments == 0)
|
||||||
|
* 2) And we are looking for a specific type
|
||||||
|
* (Not checking for TYPE_ANY)
|
||||||
|
* 3) Which is not an alias
|
||||||
|
* 4) Which is not a local type (TYPE_SCOPE)
|
||||||
|
* 5) And the type of target object is known (not TYPE_ANY)
|
||||||
|
* 6) And target object does not match what we are looking for
|
||||||
|
*
|
||||||
|
* Then we have a type mismatch. Just warn and ignore it.
|
||||||
|
*/
|
||||||
|
if ((type_to_check_for != ACPI_TYPE_ANY) &&
|
||||||
|
(type_to_check_for != ACPI_TYPE_LOCAL_ALIAS) &&
|
||||||
|
(type_to_check_for != ACPI_TYPE_LOCAL_METHOD_ALIAS)
|
||||||
|
&& (type_to_check_for != ACPI_TYPE_LOCAL_SCOPE)
|
||||||
|
&& (this_node->type != ACPI_TYPE_ANY)
|
||||||
|
&& (this_node->type != type_to_check_for)) {
|
||||||
|
|
||||||
|
/* Complain about a type mismatch */
|
||||||
|
|
||||||
|
ACPI_WARNING((AE_INFO,
|
||||||
|
"NsLookup: Type mismatch on %4.4s (%s), searching for (%s)",
|
||||||
|
ACPI_CAST_PTR(char, &simple_name),
|
||||||
|
acpi_ut_get_type_name(this_node->
|
||||||
|
type),
|
||||||
|
acpi_ut_get_type_name
|
||||||
|
(type_to_check_for)));
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* 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
|
||||||
|
* to (later) see if it opens a scope.
|
||||||
|
*/
|
||||||
|
if (type == ACPI_TYPE_ANY) {
|
||||||
|
type = this_node->type;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Point to next name segment and make this node current */
|
/* Point to next name segment and make this node current */
|
||||||
|
|
Reference in a new issue