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