diff options
Diffstat (limited to 'drivers/acpi/acpica/dswload.c')
| -rw-r--r-- | drivers/acpi/acpica/dswload.c | 172 |
1 files changed, 107 insertions, 65 deletions
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c index 95e681a36f9c..666419b6a5c6 100644 --- a/drivers/acpi/acpica/dswload.c +++ b/drivers/acpi/acpica/dswload.c @@ -1,45 +1,11 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 /****************************************************************************** * * Module Name: dswload - Dispatcher first pass namespace load callbacks * - *****************************************************************************/ - -/* - * Copyright (C) 2000 - 2013, Intel Corp. - * All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions, and the following disclaimer, - * without modification. - * 2. Redistributions in binary form must reproduce at minimum a disclaimer - * substantially similar to the "NO WARRANTY" disclaimer below - * ("Disclaimer") and any redistribution must be conditioned upon - * including a substantially similar Disclaimer requirement for further - * binary redistribution. - * 3. Neither the names of the above-listed copyright holders nor the names - * of any contributors may be used to endorse or promote products derived - * from this software without specific prior written permission. + * Copyright (C) 2000 - 2025, Intel Corp. * - * Alternatively, this software may be distributed under the terms of the - * GNU General Public License ("GPL") version 2 as published by the Free - * Software Foundation. - * - * NO WARRANTY - * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS - * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT - * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR - * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT - * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, - * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING - * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE - * POSSIBILITY OF SUCH DAMAGES. - */ + *****************************************************************************/ #include <acpi/acpi.h> #include "accommon.h" @@ -48,7 +14,6 @@ #include "acdispat.h" #include "acinterp.h" #include "acnamesp.h" - #ifdef ACPI_ASL_COMPILER #include "acdisasm.h" #endif @@ -73,8 +38,20 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) { switch (pass_number) { + case 0: + + /* Parse only - caller will setup callbacks */ + + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | + ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE; + walk_state->descending_callback = NULL; + walk_state->ascending_callback = NULL; + break; + case 1: + /* Load pass 1 */ + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE; walk_state->descending_callback = acpi_ds_load1_begin_op; @@ -83,6 +60,8 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) case 2: + /* Load pass 2 */ + walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | ACPI_PARSE_DELETE_TREE; walk_state->descending_callback = acpi_ds_load2_begin_op; @@ -91,12 +70,12 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) case 3: -#ifndef ACPI_NO_METHOD_EXECUTION + /* Execution pass */ + walk_state->parse_flags |= ACPI_PARSE_EXECUTE | ACPI_PARSE_DELETE_TREE; walk_state->descending_callback = acpi_ds_exec_begin_op; walk_state->ascending_callback = acpi_ds_exec_end_op; -#endif break; default: @@ -121,8 +100,8 @@ acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) ******************************************************************************/ acpi_status -acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, - union acpi_parse_object ** out_op) +acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state, + union acpi_parse_object **out_op) { union acpi_parse_object *op; struct acpi_namespace_node *node; @@ -131,7 +110,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, char *path; u32 flags; - ACPI_FUNCTION_TRACE(ds_load1_begin_op); + ACPI_FUNCTION_TRACE_PTR(ds_load1_begin_op, walk_state->op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, @@ -181,8 +160,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, * Target of Scope() not found. Generate an External for it, and * insert the name into the namespace. */ - acpi_dm_add_to_external_list(op, path, ACPI_TYPE_DEVICE, - 0); + acpi_dm_add_op_to_external_list(op, path, + ACPI_TYPE_DEVICE, 0, 0); status = acpi_ns_lookup(walk_state->scope_info, path, object_type, ACPI_IMODE_LOAD_PASS1, @@ -191,7 +170,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, } #endif if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, path, + status); return_ACPI_STATUS(status); } @@ -244,7 +224,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, break; } - /*lint -fallthrough */ + ACPI_FALLTHROUGH; default: @@ -299,10 +279,19 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, flags = ACPI_NS_NO_UPSEARCH; if ((walk_state->opcode != AML_SCOPE_OP) && (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { - flags |= ACPI_NS_ERROR_IF_FOUND; - ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, - "[%s] Cannot already exist\n", - acpi_ut_get_type_name(object_type))); + if (walk_state->namespace_override) { + flags |= ACPI_NS_OVERRIDE_IF_FOUND; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[%s] Override allowed\n", + acpi_ut_get_type_name + (object_type))); + } else { + flags |= ACPI_NS_ERROR_IF_FOUND; + ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, + "[%s] Cannot already exist\n", + acpi_ut_get_type_name + (object_type))); + } } else { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[%s] Both Find or Create allowed\n", @@ -350,7 +339,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, } if (ACPI_FAILURE(status)) { - ACPI_ERROR_NAMESPACE(path, status); + ACPI_ERROR_NAMESPACE(walk_state->scope_info, + path, status); return_ACPI_STATUS(status); } } @@ -363,7 +353,7 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, /* Create a new op */ - op = acpi_ps_alloc_op(walk_state->opcode); + op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } @@ -371,8 +361,8 @@ acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, /* Initialize the op */ -#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) - op->named.path = ACPI_CAST_PTR(u8, path); +#ifdef ACPI_CONSTANT_EVAL_ONLY + op->named.path = path; #endif if (node) { @@ -408,6 +398,9 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) union acpi_parse_object *op; acpi_object_type object_type; acpi_status status = AE_OK; +#ifdef ACPI_ASL_COMPILER + u8 param_count; +#endif ACPI_FUNCTION_TRACE(ds_load1_end_op); @@ -415,6 +408,27 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); + /* + * Disassembler: handle create field operators here. + * + * create_buffer_field is a deferred op that is typically processed in load + * pass 2. However, disassembly of control method contents walk the parse + * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed + * in a later walk. This is a problem when there is a control method that + * has the same name as the AML_CREATE object. In this case, any use of the + * name segment will be detected as a method call rather than a reference + * to a buffer field. + * + * This earlier creation during disassembly solves this issue by inserting + * the named object in the ACPI namespace so that references to this name + * would be a name string rather than a method call. + */ + if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) && + (walk_state->op_info->flags & AML_CREATE)) { + status = acpi_ds_create_buffer_field(op, walk_state); + return_ACPI_STATUS(status); + } + /* We are only interested in opcodes that have an associated name */ if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { @@ -425,7 +439,6 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) object_type = walk_state->op_info->object_type; -#ifndef ACPI_NO_METHOD_EXECUTION if (walk_state->op_info->flags & AML_FIELD) { /* * If we are executing a method, do not create any namespace objects @@ -451,13 +464,9 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) status = acpi_ex_create_region(op->named.data, op->named.length, - (acpi_adr_space_type) ((op-> - common. - value. - arg)-> - common. - value. - integer), + (acpi_adr_space_type) + ((op->common.value.arg)-> + common.value.integer), walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -473,7 +482,6 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) } } } -#endif if (op->common.aml_opcode == AML_NAME_OP) { @@ -493,6 +501,38 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) } } } +#ifdef ACPI_ASL_COMPILER + /* + * For external opcode, get the object type from the argument and + * get the parameter count from the argument's next. + */ + if (acpi_gbl_disasm_flag && + op->common.node && op->common.aml_opcode == AML_EXTERNAL_OP) { + /* + * Note, if this external is not a method + * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0 + * Therefore, param_count will be 0. + */ + param_count = + (u8)op->common.value.arg->common.next->common.value.integer; + object_type = (u8)op->common.value.arg->common.value.integer; + op->common.node->flags |= ANOBJ_IS_EXTERNAL; + op->common.node->type = (u8)object_type; + + acpi_dm_create_subobject_for_external((u8)object_type, + &op->common.node, + param_count); + + /* + * Add the external to the external list because we may be + * emitting code based off of the items within the external list. + */ + acpi_dm_add_op_to_external_list(op, op->named.path, + (u8)object_type, param_count, + ACPI_EXT_ORIGIN_FROM_OPCODE | + ACPI_EXT_RESOLVED_REFERENCE); + } +#endif /* * If we are executing a method, do not create any namespace objects @@ -542,7 +582,9 @@ acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) /* Pop the scope stack (only if loading a table) */ - if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) { + if (!walk_state->method_node && + op->common.aml_opcode != AML_EXTERNAL_OP && + acpi_ns_opens_scope(object_type)) { ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "(%s): Popping scope for Op %p\n", acpi_ut_get_type_name(object_type), op)); |
