ACPICA: Integrate package handling with module-level code

ACPICA commit 8faf6fca445eb7219963d80543fb802302a7a8c7

This change completes the integration of the recent changes to
package object handling with the module-level code support.

For acpi_exec, the -ep flag is removed.

This change allows table load to behave as if it were a method
invocation. Before this, the definition block definition below would
have loaded all named objects at the root scope. After loading, it
would execute the if statements at the root scope.

DefinitionBlock (...)
{
  Name(OBJ1, 0)

  if (1)
  {
    Device (DEV1)
    {
      Name (_HID,0x0)
    }
  }
  Scope (DEV1)
  {
    Name (OBJ2)
  }
}

The above code would load OBJ1 to the namespace, defer the execution
of the if statement and attempt to add OBJ2 within the scope of DEV1.
Since DEV1 is not in scope, this would incur an AE_NOT_FOUND error.
After this error is emitted, the if block is invoked and DEV1 and its
_HID is added to the namespace.

This commit changes the behavior to execute the if block in place
rather than deferring it until all tables are loaded. The new
behavior is as follows: insert OBJ1 in the namespace, invoke the if
statement and add DEV1 and its _HID to the namespace, add OBJ2 to the
scope of DEV1.

Bug report links:
Link: https://bugs.acpica.org/show_bug.cgi?id=963
Link: https://bugzilla.kernel.org/show_bug.cgi?id=153541
Link: https://bugzilla.kernel.org/show_bug.cgi?id=196165
Link: https://bugzilla.kernel.org/show_bug.cgi?id=192621
Link: https://bugzilla.kernel.org/show_bug.cgi?id=197207
Link: https://bugzilla.kernel.org/show_bug.cgi?id=198051
Link: https://bugzilla.kernel.org/show_bug.cgi?id=198515

ACPICA repo:
Link: https://github.com/acpica/acpica/commit/8faf6fca

Tested-by: Kai-Heng Feng <kai.heng.feng@canonical.com>
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Erik Schmauss <erik.schmauss@intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
This commit is contained in:
Schmauss, Erik 2018-02-15 13:09:30 -08:00 коммит произвёл Rafael J. Wysocki
Родитель 7decc66df9
Коммит 5a8361f7ec
5 изменённых файлов: 85 добавлений и 63 удалений

Просмотреть файл

@ -47,6 +47,7 @@
#include "amlcode.h" #include "amlcode.h"
#include "acdispat.h" #include "acdispat.h"
#include "acinterp.h" #include "acinterp.h"
#include "acparser.h"
#define _COMPONENT ACPI_NAMESPACE #define _COMPONENT ACPI_NAMESPACE
ACPI_MODULE_NAME("dspkginit") ACPI_MODULE_NAME("dspkginit")
@ -94,12 +95,19 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
union acpi_parse_object *parent; union acpi_parse_object *parent;
union acpi_operand_object *obj_desc = NULL; union acpi_operand_object *obj_desc = NULL;
acpi_status status = AE_OK; acpi_status status = AE_OK;
u8 module_level_code = FALSE;
u16 reference_count; u16 reference_count;
u32 index; u32 index;
u32 i; u32 i;
ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); ACPI_FUNCTION_TRACE(ds_build_internal_package_obj);
/* Check if we are executing module level code */
if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) {
module_level_code = TRUE;
}
/* Find the parent of a possibly nested package */ /* Find the parent of a possibly nested package */
parent = op->common.parent; parent = op->common.parent;
@ -130,24 +138,44 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
/* /*
* Allocate the element array (array of pointers to the individual * Allocate the element array (array of pointers to the individual
* objects) based on the num_elements parameter. Add an extra pointer slot * objects) if necessary. the count is based on the num_elements
* so that the list is always null terminated. * parameter. Add an extra pointer slot so that the list is always
* null terminated.
*/ */
obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
element_count +
1) * sizeof(void *));
if (!obj_desc->package.elements) { if (!obj_desc->package.elements) {
acpi_ut_delete_object_desc(obj_desc); obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
return_ACPI_STATUS(AE_NO_MEMORY); element_count
+
1) *
sizeof(void
*));
if (!obj_desc->package.elements) {
acpi_ut_delete_object_desc(obj_desc);
return_ACPI_STATUS(AE_NO_MEMORY);
}
obj_desc->package.count = element_count;
} }
obj_desc->package.count = element_count; /* First arg is element count. Second arg begins the initializer list */
arg = op->common.value.arg; arg = op->common.value.arg;
arg = arg->common.next; arg = arg->common.next;
if (arg) { /*
obj_desc->package.flags |= AOPOBJ_DATA_VALID; * If we are executing module-level code, we will defer the
* full resolution of the package elements in order to support
* forward references from the elements. This provides
* compatibility with other ACPI implementations.
*/
if (module_level_code) {
obj_desc->package.aml_start = walk_state->aml;
obj_desc->package.aml_length = 0;
ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
"%s: Deferring resolution of Package elements\n",
ACPI_GET_FUNCTION_NAME));
} }
/* /*
@ -187,15 +215,19 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
"****DS namepath not found")); "****DS namepath not found"));
} }
/* if (!module_level_code) {
* Initialize this package element. This function handles the /*
* resolution of named references within the package. * Initialize this package element. This function handles the
*/ * resolution of named references within the package.
acpi_ds_init_package_element(0, * Forward references from module-level code are deferred
obj_desc->package. * until all ACPI tables are loaded.
elements[i], NULL, */
&obj_desc->package. acpi_ds_init_package_element(0,
elements[i]); obj_desc->package.
elements[i], NULL,
&obj_desc->package.
elements[i]);
}
} }
if (*obj_desc_ptr) { if (*obj_desc_ptr) {
@ -265,15 +297,21 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state,
* num_elements count. * num_elements count.
* *
* Note: this is not an error, the package is padded out * Note: this is not an error, the package is padded out
* with NULLs. * with NULLs as per the ACPI specification.
*/ */
ACPI_DEBUG_PRINT((ACPI_DB_INFO, ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
"Package List length (%u) smaller than NumElements " "%s: Package List length (%u) smaller than NumElements "
"count (%u), padded with null elements\n", "count (%u), padded with null elements\n",
i, element_count)); ACPI_GET_FUNCTION_NAME, i,
element_count));
}
/* Module-level packages will be resolved later */
if (!module_level_code) {
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
} }
obj_desc->package.flags |= AOPOBJ_DATA_VALID;
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
return_ACPI_STATUS(status); return_ACPI_STATUS(status);
} }
@ -363,6 +401,10 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
/* Check if reference element is already resolved */ /* Check if reference element is already resolved */
if (element->reference.resolved) { if (element->reference.resolved) {
ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
"%s: Package element is already resolved\n",
ACPI_GET_FUNCTION_NAME));
return_VOID; return_VOID;
} }
@ -383,7 +425,10 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
"Could not find/resolve named package element: %s", "Could not find/resolve named package element: %s",
external_path)); external_path));
/* Not found, set the element to NULL */
ACPI_FREE(external_path); ACPI_FREE(external_path);
acpi_ut_remove_reference(*element_ptr);
*element_ptr = NULL; *element_ptr = NULL;
return_VOID; return_VOID;
} else if (resolved_node->type == ACPI_TYPE_ANY) { } else if (resolved_node->type == ACPI_TYPE_ANY) {
@ -397,23 +442,6 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
*element_ptr = NULL; *element_ptr = NULL;
return_VOID; return_VOID;
} }
#if 0
else if (resolved_node->flags & ANOBJ_TEMPORARY) {
/*
* A temporary node found here indicates that the reference is
* to a node that was created within this method. We are not
* going to allow it (especially if the package is returned
* from the method) -- the temporary node will be deleted out
* from under the method. (05/2017).
*/
ACPI_ERROR((AE_INFO,
"Package element refers to a temporary name [%4.4s], "
"inserting a NULL element",
resolved_node->name.ascii));
*element_ptr = NULL;
return_VOID;
}
#endif
/* /*
* Special handling for Alias objects. We need resolved_node to point * Special handling for Alias objects. We need resolved_node to point
@ -449,20 +477,6 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr)
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {
return_VOID; return_VOID;
} }
#if 0
/* TBD - alias support */
/*
* Special handling for Alias objects. We need to setup the type
* and the Op->Common.Node to point to the Alias target. Note,
* Alias has at most one level of indirection internally.
*/
type = op->common.node->type;
if (type == ACPI_TYPE_LOCAL_ALIAS) {
type = obj_desc->common.type;
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node,
op->common.node->object);
}
#endif
switch (type) { switch (type) {
/* /*

Просмотреть файл

@ -576,8 +576,10 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
case AML_TYPE_CREATE_OBJECT: case AML_TYPE_CREATE_OBJECT:
ACPI_DEBUG_PRINT((ACPI_DB_EXEC, ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
"Executing CreateObject (Buffer/Package) Op=%p AMLPtr=%p\n", "Executing CreateObject (Buffer/Package) Op=%p Child=%p ParentOpcode=%4.4X\n",
op, op->named.data)); op, op->named.value.arg,
op->common.parent->common.
aml_opcode));
switch (op->common.parent->common.aml_opcode) { switch (op->common.parent->common.aml_opcode) {
case AML_NAME_OP: case AML_NAME_OP:

Просмотреть файл

@ -267,8 +267,9 @@ acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
ACPI_FUNCTION_TRACE(ns_parse_table); ACPI_FUNCTION_TRACE(ns_parse_table);
if (acpi_gbl_parse_table_as_term_list) { if (acpi_gbl_parse_table_as_term_list) {
ACPI_DEBUG_PRINT((ACPI_DB_PARSE, ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
"**** Start table execution pass\n")); "%s: **** Start table execution pass\n",
ACPI_GET_FUNCTION_NAME));
status = acpi_ns_execute_table(table_index, start_node); status = acpi_ns_execute_table(table_index, start_node);
if (ACPI_FAILURE(status)) { if (ACPI_FAILURE(status)) {

Просмотреть файл

@ -295,6 +295,7 @@ union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)
case AML_BUFFER_OP: case AML_BUFFER_OP:
case AML_PACKAGE_OP: case AML_PACKAGE_OP:
case AML_VARIABLE_PACKAGE_OP:
case AML_METHOD_OP: case AML_METHOD_OP:
case AML_IF_OP: case AML_IF_OP:
case AML_WHILE_OP: case AML_WHILE_OP:

Просмотреть файл

@ -192,15 +192,19 @@ ACPI_INIT_GLOBAL(u8, acpi_gbl_do_not_use_xsdt, FALSE);
/* /*
* Optionally support group module level code. * Optionally support group module level code.
* NOTE, this is essentially obsolete and will be removed soon
* (01/2018).
*/ */
ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, TRUE); ACPI_INIT_GLOBAL(u8, acpi_gbl_group_module_level_code, FALSE);
/* /*
* Optionally support module level code by parsing the entire table as * Optionally support module level code by parsing the entire table as
* a term_list. Default is FALSE, do not execute entire table until some * a term_list. Default is FALSE, do not execute entire table until some
* lock order issues are fixed. * lock order issues are fixed.
* NOTE, this is essentially obsolete and will be removed soon
* (01/2018).
*/ */
ACPI_INIT_GLOBAL(u8, acpi_gbl_parse_table_as_term_list, FALSE); ACPI_INIT_GLOBAL(u8, acpi_gbl_parse_table_as_term_list, TRUE);
/* /*
* Optionally use 32-bit FADT addresses if and when there is a conflict * Optionally use 32-bit FADT addresses if and when there is a conflict