diff options
Diffstat (limited to 'drivers/acpi/acpica/dspkginit.c')
-rw-r--r-- | drivers/acpi/acpica/dspkginit.c | 128 |
1 files changed, 71 insertions, 57 deletions
diff --git a/drivers/acpi/acpica/dspkginit.c b/drivers/acpi/acpica/dspkginit.c index 902bee78036c..a307a07aeacd 100644 --- a/drivers/acpi/acpica/dspkginit.c +++ b/drivers/acpi/acpica/dspkginit.c @@ -47,6 +47,7 @@ #include "amlcode.h" #include "acdispat.h" #include "acinterp.h" +#include "acparser.h" #define _COMPONENT ACPI_NAMESPACE 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_operand_object *obj_desc = NULL; acpi_status status = AE_OK; + u8 module_level_code = FALSE; u16 reference_count; u32 index; u32 i; 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 */ 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 - * objects) based on the num_elements parameter. Add an extra pointer slot - * so that the list is always null terminated. + * objects) if necessary. the count is based on the num_elements + * 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) { - acpi_ut_delete_object_desc(obj_desc); - return_ACPI_STATUS(AE_NO_MEMORY); + obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) + 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 = 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")); } - /* - * Initialize this package element. This function handles the - * resolution of named references within the package. - */ - acpi_ds_init_package_element(0, - obj_desc->package. - elements[i], NULL, - &obj_desc->package. - elements[i]); + if (!module_level_code) { + /* + * Initialize this package element. This function handles the + * resolution of named references within the package. + * Forward references from module-level code are deferred + * until all ACPI tables are loaded. + */ + acpi_ds_init_package_element(0, + obj_desc->package. + elements[i], NULL, + &obj_desc->package. + elements[i]); + } } if (*obj_desc_ptr) { @@ -265,15 +297,21 @@ acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, * num_elements count. * * 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, - "Package List length (%u) smaller than NumElements " - "count (%u), padded with null elements\n", - i, element_count)); + ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, + "%s: Package List length (%u) smaller than NumElements " + "count (%u), padded with null elements\n", + 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); 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 */ if (element->reference.resolved) { + ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE, + "%s: Package element is already resolved\n", + ACPI_GET_FUNCTION_NAME)); + 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", external_path)); + /* Not found, set the element to NULL */ + ACPI_FREE(external_path); + acpi_ut_remove_reference(*element_ptr); *element_ptr = NULL; return_VOID; } 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; 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 @@ -449,20 +477,6 @@ acpi_ds_resolve_package_element(union acpi_operand_object **element_ptr) if (ACPI_FAILURE(status)) { 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) { /* |