162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: psscope - Parser scope stack management routines 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci#include "acparser.h" 1362306a36Sopenharmony_ci 1462306a36Sopenharmony_ci#define _COMPONENT ACPI_PARSER 1562306a36Sopenharmony_ciACPI_MODULE_NAME("psscope") 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci/******************************************************************************* 1862306a36Sopenharmony_ci * 1962306a36Sopenharmony_ci * FUNCTION: acpi_ps_get_parent_scope 2062306a36Sopenharmony_ci * 2162306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 2262306a36Sopenharmony_ci * 2362306a36Sopenharmony_ci * RETURN: Pointer to an Op object 2462306a36Sopenharmony_ci * 2562306a36Sopenharmony_ci * DESCRIPTION: Get parent of current op being parsed 2662306a36Sopenharmony_ci * 2762306a36Sopenharmony_ci ******************************************************************************/ 2862306a36Sopenharmony_ciunion acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state 2962306a36Sopenharmony_ci *parser_state) 3062306a36Sopenharmony_ci{ 3162306a36Sopenharmony_ci 3262306a36Sopenharmony_ci return (parser_state->scope->parse_scope.op); 3362306a36Sopenharmony_ci} 3462306a36Sopenharmony_ci 3562306a36Sopenharmony_ci/******************************************************************************* 3662306a36Sopenharmony_ci * 3762306a36Sopenharmony_ci * FUNCTION: acpi_ps_has_completed_scope 3862306a36Sopenharmony_ci * 3962306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 4062306a36Sopenharmony_ci * 4162306a36Sopenharmony_ci * RETURN: Boolean, TRUE = scope completed. 4262306a36Sopenharmony_ci * 4362306a36Sopenharmony_ci * DESCRIPTION: Is parsing of current argument complete? Determined by 4462306a36Sopenharmony_ci * 1) AML pointer is at or beyond the end of the scope 4562306a36Sopenharmony_ci * 2) The scope argument count has reached zero. 4662306a36Sopenharmony_ci * 4762306a36Sopenharmony_ci ******************************************************************************/ 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ciu8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state) 5062306a36Sopenharmony_ci{ 5162306a36Sopenharmony_ci 5262306a36Sopenharmony_ci return ((u8) 5362306a36Sopenharmony_ci ((parser_state->aml >= parser_state->scope->parse_scope.arg_end 5462306a36Sopenharmony_ci || !parser_state->scope->parse_scope.arg_count))); 5562306a36Sopenharmony_ci} 5662306a36Sopenharmony_ci 5762306a36Sopenharmony_ci/******************************************************************************* 5862306a36Sopenharmony_ci * 5962306a36Sopenharmony_ci * FUNCTION: acpi_ps_init_scope 6062306a36Sopenharmony_ci * 6162306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 6262306a36Sopenharmony_ci * root - the Root Node of this new scope 6362306a36Sopenharmony_ci * 6462306a36Sopenharmony_ci * RETURN: Status 6562306a36Sopenharmony_ci * 6662306a36Sopenharmony_ci * DESCRIPTION: Allocate and init a new scope object 6762306a36Sopenharmony_ci * 6862306a36Sopenharmony_ci ******************************************************************************/ 6962306a36Sopenharmony_ci 7062306a36Sopenharmony_ciacpi_status 7162306a36Sopenharmony_ciacpi_ps_init_scope(struct acpi_parse_state * parser_state, 7262306a36Sopenharmony_ci union acpi_parse_object * root_op) 7362306a36Sopenharmony_ci{ 7462306a36Sopenharmony_ci union acpi_generic_state *scope; 7562306a36Sopenharmony_ci 7662306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op); 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci scope = acpi_ut_create_generic_state(); 7962306a36Sopenharmony_ci if (!scope) { 8062306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 8162306a36Sopenharmony_ci } 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE; 8462306a36Sopenharmony_ci scope->parse_scope.op = root_op; 8562306a36Sopenharmony_ci scope->parse_scope.arg_count = ACPI_VAR_ARGS; 8662306a36Sopenharmony_ci scope->parse_scope.arg_end = parser_state->aml_end; 8762306a36Sopenharmony_ci scope->parse_scope.pkg_end = parser_state->aml_end; 8862306a36Sopenharmony_ci 8962306a36Sopenharmony_ci parser_state->scope = scope; 9062306a36Sopenharmony_ci parser_state->start_op = root_op; 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 9362306a36Sopenharmony_ci} 9462306a36Sopenharmony_ci 9562306a36Sopenharmony_ci/******************************************************************************* 9662306a36Sopenharmony_ci * 9762306a36Sopenharmony_ci * FUNCTION: acpi_ps_push_scope 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 10062306a36Sopenharmony_ci * op - Current op to be pushed 10162306a36Sopenharmony_ci * remaining_args - List of args remaining 10262306a36Sopenharmony_ci * arg_count - Fixed or variable number of args 10362306a36Sopenharmony_ci * 10462306a36Sopenharmony_ci * RETURN: Status 10562306a36Sopenharmony_ci * 10662306a36Sopenharmony_ci * DESCRIPTION: Push current op to begin parsing its argument 10762306a36Sopenharmony_ci * 10862306a36Sopenharmony_ci ******************************************************************************/ 10962306a36Sopenharmony_ci 11062306a36Sopenharmony_ciacpi_status 11162306a36Sopenharmony_ciacpi_ps_push_scope(struct acpi_parse_state *parser_state, 11262306a36Sopenharmony_ci union acpi_parse_object *op, 11362306a36Sopenharmony_ci u32 remaining_args, u32 arg_count) 11462306a36Sopenharmony_ci{ 11562306a36Sopenharmony_ci union acpi_generic_state *scope; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op); 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci scope = acpi_ut_create_generic_state(); 12062306a36Sopenharmony_ci if (!scope) { 12162306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 12262306a36Sopenharmony_ci } 12362306a36Sopenharmony_ci 12462306a36Sopenharmony_ci scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE; 12562306a36Sopenharmony_ci scope->parse_scope.op = op; 12662306a36Sopenharmony_ci scope->parse_scope.arg_list = remaining_args; 12762306a36Sopenharmony_ci scope->parse_scope.arg_count = arg_count; 12862306a36Sopenharmony_ci scope->parse_scope.pkg_end = parser_state->pkg_end; 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci /* Push onto scope stack */ 13162306a36Sopenharmony_ci 13262306a36Sopenharmony_ci acpi_ut_push_generic_state(&parser_state->scope, scope); 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci if (arg_count == ACPI_VAR_ARGS) { 13562306a36Sopenharmony_ci 13662306a36Sopenharmony_ci /* Multiple arguments */ 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci scope->parse_scope.arg_end = parser_state->pkg_end; 13962306a36Sopenharmony_ci } else { 14062306a36Sopenharmony_ci /* Single argument */ 14162306a36Sopenharmony_ci 14262306a36Sopenharmony_ci scope->parse_scope.arg_end = ACPI_TO_POINTER(ACPI_MAX_PTR); 14362306a36Sopenharmony_ci } 14462306a36Sopenharmony_ci 14562306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 14662306a36Sopenharmony_ci} 14762306a36Sopenharmony_ci 14862306a36Sopenharmony_ci/******************************************************************************* 14962306a36Sopenharmony_ci * 15062306a36Sopenharmony_ci * FUNCTION: acpi_ps_pop_scope 15162306a36Sopenharmony_ci * 15262306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 15362306a36Sopenharmony_ci * op - Where the popped op is returned 15462306a36Sopenharmony_ci * arg_list - Where the popped "next argument" is 15562306a36Sopenharmony_ci * returned 15662306a36Sopenharmony_ci * arg_count - Count of objects in arg_list 15762306a36Sopenharmony_ci * 15862306a36Sopenharmony_ci * RETURN: Status 15962306a36Sopenharmony_ci * 16062306a36Sopenharmony_ci * DESCRIPTION: Return to parsing a previous op 16162306a36Sopenharmony_ci * 16262306a36Sopenharmony_ci ******************************************************************************/ 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_civoid 16562306a36Sopenharmony_ciacpi_ps_pop_scope(struct acpi_parse_state *parser_state, 16662306a36Sopenharmony_ci union acpi_parse_object **op, u32 * arg_list, u32 * arg_count) 16762306a36Sopenharmony_ci{ 16862306a36Sopenharmony_ci union acpi_generic_state *scope = parser_state->scope; 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ps_pop_scope); 17162306a36Sopenharmony_ci 17262306a36Sopenharmony_ci /* Only pop the scope if there is in fact a next scope */ 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci if (scope->common.next) { 17562306a36Sopenharmony_ci scope = acpi_ut_pop_generic_state(&parser_state->scope); 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci /* Return to parsing previous op */ 17862306a36Sopenharmony_ci 17962306a36Sopenharmony_ci *op = scope->parse_scope.op; 18062306a36Sopenharmony_ci *arg_list = scope->parse_scope.arg_list; 18162306a36Sopenharmony_ci *arg_count = scope->parse_scope.arg_count; 18262306a36Sopenharmony_ci parser_state->pkg_end = scope->parse_scope.pkg_end; 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci /* All done with this scope state structure */ 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci acpi_ut_delete_generic_state(scope); 18762306a36Sopenharmony_ci } else { 18862306a36Sopenharmony_ci /* Empty parse stack, prepare to fetch next opcode */ 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_ci *op = NULL; 19162306a36Sopenharmony_ci *arg_list = 0; 19262306a36Sopenharmony_ci *arg_count = 0; 19362306a36Sopenharmony_ci } 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 19662306a36Sopenharmony_ci "Popped Op %p Args %X\n", *op, *arg_count)); 19762306a36Sopenharmony_ci return_VOID; 19862306a36Sopenharmony_ci} 19962306a36Sopenharmony_ci 20062306a36Sopenharmony_ci/******************************************************************************* 20162306a36Sopenharmony_ci * 20262306a36Sopenharmony_ci * FUNCTION: acpi_ps_cleanup_scope 20362306a36Sopenharmony_ci * 20462306a36Sopenharmony_ci * PARAMETERS: parser_state - Current parser state object 20562306a36Sopenharmony_ci * 20662306a36Sopenharmony_ci * RETURN: None 20762306a36Sopenharmony_ci * 20862306a36Sopenharmony_ci * DESCRIPTION: Destroy available list, remaining stack levels, and return 20962306a36Sopenharmony_ci * root scope 21062306a36Sopenharmony_ci * 21162306a36Sopenharmony_ci ******************************************************************************/ 21262306a36Sopenharmony_ci 21362306a36Sopenharmony_civoid acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state) 21462306a36Sopenharmony_ci{ 21562306a36Sopenharmony_ci union acpi_generic_state *scope; 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state); 21862306a36Sopenharmony_ci 21962306a36Sopenharmony_ci if (!parser_state) { 22062306a36Sopenharmony_ci return_VOID; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci /* Delete anything on the scope stack */ 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci while (parser_state->scope) { 22662306a36Sopenharmony_ci scope = acpi_ut_pop_generic_state(&parser_state->scope); 22762306a36Sopenharmony_ci acpi_ut_delete_generic_state(scope); 22862306a36Sopenharmony_ci } 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci return_VOID; 23162306a36Sopenharmony_ci} 232