xref: /openbmc/linux/drivers/acpi/acpica/psscope.c (revision 612c2932)
195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown  *
495b482a8SLen Brown  * Module Name: psscope - Parser scope stack management routines
595b482a8SLen Brown  *
6*612c2932SBob Moore  * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown  *
895857638SErik Schmauss  *****************************************************************************/
995b482a8SLen Brown 
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "acparser.h"
1395b482a8SLen Brown 
1495b482a8SLen Brown #define _COMPONENT          ACPI_PARSER
1595b482a8SLen Brown ACPI_MODULE_NAME("psscope")
1695b482a8SLen Brown 
1795b482a8SLen Brown /*******************************************************************************
1895b482a8SLen Brown  *
1995b482a8SLen Brown  * FUNCTION:    acpi_ps_get_parent_scope
2095b482a8SLen Brown  *
2195b482a8SLen Brown  * PARAMETERS:  parser_state        - Current parser state object
2295b482a8SLen Brown  *
2395b482a8SLen Brown  * RETURN:      Pointer to an Op object
2495b482a8SLen Brown  *
2595b482a8SLen Brown  * DESCRIPTION: Get parent of current op being parsed
2695b482a8SLen Brown  *
2795b482a8SLen Brown  ******************************************************************************/
acpi_ps_get_parent_scope(struct acpi_parse_state * parser_state)2895b482a8SLen Brown union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state
2995b482a8SLen Brown 						  *parser_state)
3095b482a8SLen Brown {
3195b482a8SLen Brown 
3295b482a8SLen Brown 	return (parser_state->scope->parse_scope.op);
3395b482a8SLen Brown }
3495b482a8SLen Brown 
3595b482a8SLen Brown /*******************************************************************************
3695b482a8SLen Brown  *
3795b482a8SLen Brown  * FUNCTION:    acpi_ps_has_completed_scope
3895b482a8SLen Brown  *
3995b482a8SLen Brown  * PARAMETERS:  parser_state        - Current parser state object
4095b482a8SLen Brown  *
4195b482a8SLen Brown  * RETURN:      Boolean, TRUE = scope completed.
4295b482a8SLen Brown  *
4395b482a8SLen Brown  * DESCRIPTION: Is parsing of current argument complete?  Determined by
4495b482a8SLen Brown  *              1) AML pointer is at or beyond the end of the scope
4595b482a8SLen Brown  *              2) The scope argument count has reached zero.
4695b482a8SLen Brown  *
4795b482a8SLen Brown  ******************************************************************************/
4895b482a8SLen Brown 
acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state)4995b482a8SLen Brown u8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state)
5095b482a8SLen Brown {
5195b482a8SLen Brown 
5295b482a8SLen Brown 	return ((u8)
5395b482a8SLen Brown 		((parser_state->aml >= parser_state->scope->parse_scope.arg_end
5495b482a8SLen Brown 		  || !parser_state->scope->parse_scope.arg_count)));
5595b482a8SLen Brown }
5695b482a8SLen Brown 
5795b482a8SLen Brown /*******************************************************************************
5895b482a8SLen Brown  *
5995b482a8SLen Brown  * FUNCTION:    acpi_ps_init_scope
6095b482a8SLen Brown  *
6195b482a8SLen Brown  * PARAMETERS:  parser_state        - Current parser state object
62ba494beeSBob Moore  *              root                - the Root Node of this new scope
6395b482a8SLen Brown  *
6495b482a8SLen Brown  * RETURN:      Status
6595b482a8SLen Brown  *
6695b482a8SLen Brown  * DESCRIPTION: Allocate and init a new scope object
6795b482a8SLen Brown  *
6895b482a8SLen Brown  ******************************************************************************/
6995b482a8SLen Brown 
7095b482a8SLen Brown acpi_status
acpi_ps_init_scope(struct acpi_parse_state * parser_state,union acpi_parse_object * root_op)7195b482a8SLen Brown acpi_ps_init_scope(struct acpi_parse_state * parser_state,
7295b482a8SLen Brown 		   union acpi_parse_object * root_op)
7395b482a8SLen Brown {
7495b482a8SLen Brown 	union acpi_generic_state *scope;
7595b482a8SLen Brown 
7695b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op);
7795b482a8SLen Brown 
7895b482a8SLen Brown 	scope = acpi_ut_create_generic_state();
7995b482a8SLen Brown 	if (!scope) {
8095b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
8195b482a8SLen Brown 	}
8295b482a8SLen Brown 
8395b482a8SLen Brown 	scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE;
8495b482a8SLen Brown 	scope->parse_scope.op = root_op;
8595b482a8SLen Brown 	scope->parse_scope.arg_count = ACPI_VAR_ARGS;
8695b482a8SLen Brown 	scope->parse_scope.arg_end = parser_state->aml_end;
8795b482a8SLen Brown 	scope->parse_scope.pkg_end = parser_state->aml_end;
8895b482a8SLen Brown 
8995b482a8SLen Brown 	parser_state->scope = scope;
9095b482a8SLen Brown 	parser_state->start_op = root_op;
9195b482a8SLen Brown 
9295b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
9395b482a8SLen Brown }
9495b482a8SLen Brown 
9595b482a8SLen Brown /*******************************************************************************
9695b482a8SLen Brown  *
9795b482a8SLen Brown  * FUNCTION:    acpi_ps_push_scope
9895b482a8SLen Brown  *
9995b482a8SLen Brown  * PARAMETERS:  parser_state        - Current parser state object
100ba494beeSBob Moore  *              op                  - Current op to be pushed
10195b482a8SLen Brown  *              remaining_args      - List of args remaining
10295b482a8SLen Brown  *              arg_count           - Fixed or variable number of args
10395b482a8SLen Brown  *
10495b482a8SLen Brown  * RETURN:      Status
10595b482a8SLen Brown  *
10695b482a8SLen Brown  * DESCRIPTION: Push current op to begin parsing its argument
10795b482a8SLen Brown  *
10895b482a8SLen Brown  ******************************************************************************/
10995b482a8SLen Brown 
11095b482a8SLen Brown acpi_status
acpi_ps_push_scope(struct acpi_parse_state * parser_state,union acpi_parse_object * op,u32 remaining_args,u32 arg_count)11195b482a8SLen Brown acpi_ps_push_scope(struct acpi_parse_state *parser_state,
11295b482a8SLen Brown 		   union acpi_parse_object *op,
11395b482a8SLen Brown 		   u32 remaining_args, u32 arg_count)
11495b482a8SLen Brown {
11595b482a8SLen Brown 	union acpi_generic_state *scope;
11695b482a8SLen Brown 
11795b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op);
11895b482a8SLen Brown 
11995b482a8SLen Brown 	scope = acpi_ut_create_generic_state();
12095b482a8SLen Brown 	if (!scope) {
12195b482a8SLen Brown 		return_ACPI_STATUS(AE_NO_MEMORY);
12295b482a8SLen Brown 	}
12395b482a8SLen Brown 
12495b482a8SLen Brown 	scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE;
12595b482a8SLen Brown 	scope->parse_scope.op = op;
12695b482a8SLen Brown 	scope->parse_scope.arg_list = remaining_args;
12795b482a8SLen Brown 	scope->parse_scope.arg_count = arg_count;
12895b482a8SLen Brown 	scope->parse_scope.pkg_end = parser_state->pkg_end;
12995b482a8SLen Brown 
13095b482a8SLen Brown 	/* Push onto scope stack */
13195b482a8SLen Brown 
13295b482a8SLen Brown 	acpi_ut_push_generic_state(&parser_state->scope, scope);
13395b482a8SLen Brown 
13495b482a8SLen Brown 	if (arg_count == ACPI_VAR_ARGS) {
13595b482a8SLen Brown 
13695b482a8SLen Brown 		/* Multiple arguments */
13795b482a8SLen Brown 
13895b482a8SLen Brown 		scope->parse_scope.arg_end = parser_state->pkg_end;
13995b482a8SLen Brown 	} else {
14095b482a8SLen Brown 		/* Single argument */
14195b482a8SLen Brown 
14295b482a8SLen Brown 		scope->parse_scope.arg_end = ACPI_TO_POINTER(ACPI_MAX_PTR);
14395b482a8SLen Brown 	}
14495b482a8SLen Brown 
14595b482a8SLen Brown 	return_ACPI_STATUS(AE_OK);
14695b482a8SLen Brown }
14795b482a8SLen Brown 
14895b482a8SLen Brown /*******************************************************************************
14995b482a8SLen Brown  *
15095b482a8SLen Brown  * FUNCTION:    acpi_ps_pop_scope
15195b482a8SLen Brown  *
15295b482a8SLen Brown  * PARAMETERS:  parser_state        - Current parser state object
153ba494beeSBob Moore  *              op                  - Where the popped op is returned
15495b482a8SLen Brown  *              arg_list            - Where the popped "next argument" is
15595b482a8SLen Brown  *                                    returned
15695b482a8SLen Brown  *              arg_count           - Count of objects in arg_list
15795b482a8SLen Brown  *
15895b482a8SLen Brown  * RETURN:      Status
15995b482a8SLen Brown  *
16095b482a8SLen Brown  * DESCRIPTION: Return to parsing a previous op
16195b482a8SLen Brown  *
16295b482a8SLen Brown  ******************************************************************************/
16395b482a8SLen Brown 
16495b482a8SLen Brown void
acpi_ps_pop_scope(struct acpi_parse_state * parser_state,union acpi_parse_object ** op,u32 * arg_list,u32 * arg_count)16595b482a8SLen Brown acpi_ps_pop_scope(struct acpi_parse_state *parser_state,
16695b482a8SLen Brown 		  union acpi_parse_object **op, u32 * arg_list, u32 * arg_count)
16795b482a8SLen Brown {
16895b482a8SLen Brown 	union acpi_generic_state *scope = parser_state->scope;
16995b482a8SLen Brown 
17095b482a8SLen Brown 	ACPI_FUNCTION_TRACE(ps_pop_scope);
17195b482a8SLen Brown 
17295b482a8SLen Brown 	/* Only pop the scope if there is in fact a next scope */
17395b482a8SLen Brown 
17495b482a8SLen Brown 	if (scope->common.next) {
17595b482a8SLen Brown 		scope = acpi_ut_pop_generic_state(&parser_state->scope);
17695b482a8SLen Brown 
17795b482a8SLen Brown 		/* Return to parsing previous op */
17895b482a8SLen Brown 
17995b482a8SLen Brown 		*op = scope->parse_scope.op;
18095b482a8SLen Brown 		*arg_list = scope->parse_scope.arg_list;
18195b482a8SLen Brown 		*arg_count = scope->parse_scope.arg_count;
18295b482a8SLen Brown 		parser_state->pkg_end = scope->parse_scope.pkg_end;
18395b482a8SLen Brown 
18495b482a8SLen Brown 		/* All done with this scope state structure */
18595b482a8SLen Brown 
18695b482a8SLen Brown 		acpi_ut_delete_generic_state(scope);
18795b482a8SLen Brown 	} else {
18895b482a8SLen Brown 		/* Empty parse stack, prepare to fetch next opcode */
18995b482a8SLen Brown 
19095b482a8SLen Brown 		*op = NULL;
19195b482a8SLen Brown 		*arg_list = 0;
19295b482a8SLen Brown 		*arg_count = 0;
19395b482a8SLen Brown 	}
19495b482a8SLen Brown 
19595b482a8SLen Brown 	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
19695b482a8SLen Brown 			  "Popped Op %p Args %X\n", *op, *arg_count));
19795b482a8SLen Brown 	return_VOID;
19895b482a8SLen Brown }
19995b482a8SLen Brown 
20095b482a8SLen Brown /*******************************************************************************
20195b482a8SLen Brown  *
20295b482a8SLen Brown  * FUNCTION:    acpi_ps_cleanup_scope
20395b482a8SLen Brown  *
20495b482a8SLen Brown  * PARAMETERS:  parser_state        - Current parser state object
20595b482a8SLen Brown  *
20695b482a8SLen Brown  * RETURN:      None
20795b482a8SLen Brown  *
20895b482a8SLen Brown  * DESCRIPTION: Destroy available list, remaining stack levels, and return
20995b482a8SLen Brown  *              root scope
21095b482a8SLen Brown  *
21195b482a8SLen Brown  ******************************************************************************/
21295b482a8SLen Brown 
acpi_ps_cleanup_scope(struct acpi_parse_state * parser_state)21395b482a8SLen Brown void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state)
21495b482a8SLen Brown {
21595b482a8SLen Brown 	union acpi_generic_state *scope;
21695b482a8SLen Brown 
21795b482a8SLen Brown 	ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state);
21895b482a8SLen Brown 
21995b482a8SLen Brown 	if (!parser_state) {
22095b482a8SLen Brown 		return_VOID;
22195b482a8SLen Brown 	}
22295b482a8SLen Brown 
22395b482a8SLen Brown 	/* Delete anything on the scope stack */
22495b482a8SLen Brown 
22595b482a8SLen Brown 	while (parser_state->scope) {
22695b482a8SLen Brown 		scope = acpi_ut_pop_generic_state(&parser_state->scope);
22795b482a8SLen Brown 		acpi_ut_delete_generic_state(scope);
22895b482a8SLen Brown 	}
22995b482a8SLen Brown 
23095b482a8SLen Brown 	return_VOID;
23195b482a8SLen Brown }
232