diff options
Diffstat (limited to 'drivers/acpi/acpica/dsopcode.c')
| -rw-r--r-- | drivers/acpi/acpica/dsopcode.c | 152 |
1 files changed, 78 insertions, 74 deletions
diff --git a/drivers/acpi/acpica/dsopcode.c b/drivers/acpi/acpica/dsopcode.c index 1fc1ff114f26..5699b0872848 100644 --- a/drivers/acpi/acpica/dsopcode.c +++ b/drivers/acpi/acpica/dsopcode.c @@ -1,46 +1,12 @@ +// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 /****************************************************************************** * * Module Name: dsopcode - Dispatcher support for regions and fields * + * Copyright (C) 2000 - 2025, Intel Corp. + * *****************************************************************************/ -/* - * 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. - * - * 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" #include "acparser.h" @@ -84,7 +50,7 @@ acpi_status acpi_ds_initialize_region(acpi_handle obj_handle) /* Namespace is NOT locked */ - status = acpi_ev_initialize_region(obj_desc, FALSE); + status = acpi_ev_initialize_region(obj_desc); return (status); } @@ -164,8 +130,8 @@ acpi_ds_init_buffer_field(u16 aml_opcode, /* Must have a valid (>0) bit count */ if (bit_count == 0) { - ACPI_ERROR((AE_INFO, - "Attempt to CreateField of length zero")); + ACPI_BIOS_ERROR((AE_INFO, + "Attempt to CreateField of length zero")); status = AE_AML_OPERAND_VALUE; goto cleanup; } @@ -227,14 +193,14 @@ acpi_ds_init_buffer_field(u16 aml_opcode, /* Entire field must fit within the current length of the buffer */ - if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { - ACPI_ERROR((AE_INFO, - "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)", - acpi_ut_get_node_name(result_desc), - bit_offset + bit_count, - acpi_ut_get_node_name(buffer_desc->buffer.node), - 8 * (u32) buffer_desc->buffer.length)); + if ((bit_offset + bit_count) > (8 * (u32)buffer_desc->buffer.length)) { status = AE_AML_BUFFER_LIMIT; + ACPI_BIOS_EXCEPTION((AE_INFO, status, + "Field [%4.4s] at bit offset/length %u/%u " + "exceeds size of target Buffer (%u bits)", + acpi_ut_get_node_name(result_desc), + bit_offset, bit_count, + 8 * (u32)buffer_desc->buffer.length)); goto cleanup; } @@ -243,13 +209,16 @@ acpi_ds_init_buffer_field(u16 aml_opcode, * For field_flags, use LOCK_RULE = 0 (NO_LOCK), * UPDATE_RULE = 0 (UPDATE_PRESERVE) */ - status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, - bit_offset, bit_count); + status = + acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, + bit_offset, bit_count); if (ACPI_FAILURE(status)) { goto cleanup; } obj_desc->buffer_field.buffer_obj = buffer_desc; + obj_desc->buffer_field.is_create_field = + aml_opcode == AML_CREATE_FIELD_OP; /* Reference count for buffer_desc inherits obj_desc count */ @@ -257,7 +226,7 @@ acpi_ds_init_buffer_field(u16 aml_opcode, (buffer_desc->common.reference_count + obj_desc->common.reference_count); - cleanup: +cleanup: /* Always delete the operands */ @@ -330,8 +299,9 @@ acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, /* Resolve the operands */ - status = acpi_ex_resolve_operands(op->common.aml_opcode, - ACPI_WALK_OPERANDS, walk_state); + status = + acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, + walk_state); if (ACPI_FAILURE(status)) { ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X", acpi_ps_get_opcode_name(op->common.aml_opcode), @@ -388,6 +358,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, union acpi_operand_object *operand_desc; struct acpi_namespace_node *node; union acpi_parse_object *next_op; + acpi_adr_space_type space_id; ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); @@ -400,6 +371,7 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, /* next_op points to the op that holds the space_ID */ next_op = op->common.value.arg; + space_id = (acpi_adr_space_type)next_op->common.value.integer; /* next_op points to address op */ @@ -414,8 +386,9 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, /* Resolve the length and address operands to numbers */ - status = acpi_ex_resolve_operands(op->common.aml_opcode, - ACPI_WALK_OPERANDS, walk_state); + status = + acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, + walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } @@ -434,6 +407,15 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, obj_desc->region.length = (u32) operand_desc->integer.value; acpi_ut_remove_reference(operand_desc); + /* A zero-length operation region is unusable. Just warn */ + + if (!obj_desc->region.length + && (space_id < ACPI_NUM_PREDEFINED_REGIONS)) { + ACPI_WARNING((AE_INFO, + "Operation Region [%4.4s] has zero length (SpaceId %X)", + node->name.ascii, space_id)); + } + /* * Get the address and save it * (at top of stack - 1) @@ -446,13 +428,16 @@ acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", obj_desc, - ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), + ACPI_FORMAT_UINT64(obj_desc->region.address), obj_desc->region.length)); + status = acpi_ut_add_address_range(obj_desc->region.space_id, + obj_desc->region.address, + obj_desc->region.length, node); + /* Now the address and length are valid for this opregion */ obj_desc->region.flags |= AOPOBJ_DATA_VALID; - return_ACPI_STATUS(status); } @@ -480,8 +465,8 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, union acpi_operand_object **operand; struct acpi_namespace_node *node; union acpi_parse_object *next_op; - u32 table_index; struct acpi_table_header *table; + u32 table_index; ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); @@ -504,54 +489,64 @@ acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, return_ACPI_STATUS(status); } + operand = &walk_state->operands[0]; + /* * Resolve the Signature string, oem_id string, * and oem_table_id string operands */ - status = acpi_ex_resolve_operands(op->common.aml_opcode, - ACPI_WALK_OPERANDS, walk_state); + status = + acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, + walk_state); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } - operand = &walk_state->operands[0]; - /* Find the ACPI table */ status = acpi_tb_find_table(operand[0]->string.pointer, operand[1]->string.pointer, operand[2]->string.pointer, &table_index); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + if (status == AE_NOT_FOUND) { + ACPI_ERROR((AE_INFO, + "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT", + operand[0]->string.pointer, + operand[1]->string.pointer, + operand[2]->string.pointer)); + } + goto cleanup; } - acpi_ut_remove_reference(operand[0]); - acpi_ut_remove_reference(operand[1]); - acpi_ut_remove_reference(operand[2]); - status = acpi_get_table_by_index(table_index, &table); if (ACPI_FAILURE(status)) { - return_ACPI_STATUS(status); + goto cleanup; } obj_desc = acpi_ns_get_attached_object(node); if (!obj_desc) { - return_ACPI_STATUS(AE_NOT_EXIST); + status = AE_NOT_EXIST; + goto cleanup; } - obj_desc->region.address = - (acpi_physical_address) ACPI_TO_INTEGER(table); + obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); obj_desc->region.length = table->length; + obj_desc->region.pointer = table; ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", obj_desc, - ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), + ACPI_FORMAT_UINT64(obj_desc->region.address), obj_desc->region.length)); /* Now the address and length are valid for this opregion */ obj_desc->region.flags |= AOPOBJ_DATA_VALID; +cleanup: + acpi_ut_remove_reference(operand[0]); + acpi_ut_remove_reference(operand[1]); + acpi_ut_remove_reference(operand[2]); + return_ACPI_STATUS(status); } @@ -589,6 +584,15 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, */ walk_state->operand_index = walk_state->num_operands; + /* Ignore if child is not valid */ + + if (!op->common.value.arg) { + ACPI_ERROR((AE_INFO, + "Missing child while evaluating opcode %4.4X, Op %p", + op->common.aml_opcode, op)); + return_ACPI_STATUS(AE_OK); + } + status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); @@ -628,7 +632,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, break; case AML_PACKAGE_OP: - case AML_VAR_PACKAGE_OP: + case AML_VARIABLE_PACKAGE_OP: status = acpi_ds_build_internal_package_obj(walk_state, op, length, @@ -649,7 +653,7 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, if ((!op->common.parent) || ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && (op->common.parent->common.aml_opcode != - AML_VAR_PACKAGE_OP) + AML_VARIABLE_PACKAGE_OP) && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { walk_state->result_obj = obj_desc; |
