1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: psscope - Parser scope stack management routines 5 * 6 * Copyright (C) 2000 - 2023, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "acparser.h" 13 14 #define _COMPONENT ACPI_PARSER 15 ACPI_MODULE_NAME("psscope") 16 17 /******************************************************************************* 18 * 19 * FUNCTION: acpi_ps_get_parent_scope 20 * 21 * PARAMETERS: parser_state - Current parser state object 22 * 23 * RETURN: Pointer to an Op object 24 * 25 * DESCRIPTION: Get parent of current op being parsed 26 * 27 ******************************************************************************/ 28 union acpi_parse_object *acpi_ps_get_parent_scope(struct acpi_parse_state 29 *parser_state) 30 { 31 32 return (parser_state->scope->parse_scope.op); 33 } 34 35 /******************************************************************************* 36 * 37 * FUNCTION: acpi_ps_has_completed_scope 38 * 39 * PARAMETERS: parser_state - Current parser state object 40 * 41 * RETURN: Boolean, TRUE = scope completed. 42 * 43 * DESCRIPTION: Is parsing of current argument complete? Determined by 44 * 1) AML pointer is at or beyond the end of the scope 45 * 2) The scope argument count has reached zero. 46 * 47 ******************************************************************************/ 48 49 u8 acpi_ps_has_completed_scope(struct acpi_parse_state * parser_state) 50 { 51 52 return ((u8) 53 ((parser_state->aml >= parser_state->scope->parse_scope.arg_end 54 || !parser_state->scope->parse_scope.arg_count))); 55 } 56 57 /******************************************************************************* 58 * 59 * FUNCTION: acpi_ps_init_scope 60 * 61 * PARAMETERS: parser_state - Current parser state object 62 * root - the Root Node of this new scope 63 * 64 * RETURN: Status 65 * 66 * DESCRIPTION: Allocate and init a new scope object 67 * 68 ******************************************************************************/ 69 70 acpi_status 71 acpi_ps_init_scope(struct acpi_parse_state * parser_state, 72 union acpi_parse_object * root_op) 73 { 74 union acpi_generic_state *scope; 75 76 ACPI_FUNCTION_TRACE_PTR(ps_init_scope, root_op); 77 78 scope = acpi_ut_create_generic_state(); 79 if (!scope) { 80 return_ACPI_STATUS(AE_NO_MEMORY); 81 } 82 83 scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_RPSCOPE; 84 scope->parse_scope.op = root_op; 85 scope->parse_scope.arg_count = ACPI_VAR_ARGS; 86 scope->parse_scope.arg_end = parser_state->aml_end; 87 scope->parse_scope.pkg_end = parser_state->aml_end; 88 89 parser_state->scope = scope; 90 parser_state->start_op = root_op; 91 92 return_ACPI_STATUS(AE_OK); 93 } 94 95 /******************************************************************************* 96 * 97 * FUNCTION: acpi_ps_push_scope 98 * 99 * PARAMETERS: parser_state - Current parser state object 100 * op - Current op to be pushed 101 * remaining_args - List of args remaining 102 * arg_count - Fixed or variable number of args 103 * 104 * RETURN: Status 105 * 106 * DESCRIPTION: Push current op to begin parsing its argument 107 * 108 ******************************************************************************/ 109 110 acpi_status 111 acpi_ps_push_scope(struct acpi_parse_state *parser_state, 112 union acpi_parse_object *op, 113 u32 remaining_args, u32 arg_count) 114 { 115 union acpi_generic_state *scope; 116 117 ACPI_FUNCTION_TRACE_PTR(ps_push_scope, op); 118 119 scope = acpi_ut_create_generic_state(); 120 if (!scope) { 121 return_ACPI_STATUS(AE_NO_MEMORY); 122 } 123 124 scope->common.descriptor_type = ACPI_DESC_TYPE_STATE_PSCOPE; 125 scope->parse_scope.op = op; 126 scope->parse_scope.arg_list = remaining_args; 127 scope->parse_scope.arg_count = arg_count; 128 scope->parse_scope.pkg_end = parser_state->pkg_end; 129 130 /* Push onto scope stack */ 131 132 acpi_ut_push_generic_state(&parser_state->scope, scope); 133 134 if (arg_count == ACPI_VAR_ARGS) { 135 136 /* Multiple arguments */ 137 138 scope->parse_scope.arg_end = parser_state->pkg_end; 139 } else { 140 /* Single argument */ 141 142 scope->parse_scope.arg_end = ACPI_TO_POINTER(ACPI_MAX_PTR); 143 } 144 145 return_ACPI_STATUS(AE_OK); 146 } 147 148 /******************************************************************************* 149 * 150 * FUNCTION: acpi_ps_pop_scope 151 * 152 * PARAMETERS: parser_state - Current parser state object 153 * op - Where the popped op is returned 154 * arg_list - Where the popped "next argument" is 155 * returned 156 * arg_count - Count of objects in arg_list 157 * 158 * RETURN: Status 159 * 160 * DESCRIPTION: Return to parsing a previous op 161 * 162 ******************************************************************************/ 163 164 void 165 acpi_ps_pop_scope(struct acpi_parse_state *parser_state, 166 union acpi_parse_object **op, u32 * arg_list, u32 * arg_count) 167 { 168 union acpi_generic_state *scope = parser_state->scope; 169 170 ACPI_FUNCTION_TRACE(ps_pop_scope); 171 172 /* Only pop the scope if there is in fact a next scope */ 173 174 if (scope->common.next) { 175 scope = acpi_ut_pop_generic_state(&parser_state->scope); 176 177 /* Return to parsing previous op */ 178 179 *op = scope->parse_scope.op; 180 *arg_list = scope->parse_scope.arg_list; 181 *arg_count = scope->parse_scope.arg_count; 182 parser_state->pkg_end = scope->parse_scope.pkg_end; 183 184 /* All done with this scope state structure */ 185 186 acpi_ut_delete_generic_state(scope); 187 } else { 188 /* Empty parse stack, prepare to fetch next opcode */ 189 190 *op = NULL; 191 *arg_list = 0; 192 *arg_count = 0; 193 } 194 195 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 196 "Popped Op %p Args %X\n", *op, *arg_count)); 197 return_VOID; 198 } 199 200 /******************************************************************************* 201 * 202 * FUNCTION: acpi_ps_cleanup_scope 203 * 204 * PARAMETERS: parser_state - Current parser state object 205 * 206 * RETURN: None 207 * 208 * DESCRIPTION: Destroy available list, remaining stack levels, and return 209 * root scope 210 * 211 ******************************************************************************/ 212 213 void acpi_ps_cleanup_scope(struct acpi_parse_state *parser_state) 214 { 215 union acpi_generic_state *scope; 216 217 ACPI_FUNCTION_TRACE_PTR(ps_cleanup_scope, parser_state); 218 219 if (!parser_state) { 220 return_VOID; 221 } 222 223 /* Delete anything on the scope stack */ 224 225 while (parser_state->scope) { 226 scope = acpi_ut_pop_generic_state(&parser_state->scope); 227 acpi_ut_delete_generic_state(scope); 228 } 229 230 return_VOID; 231 } 232