| .. | .. |
|---|
| 3 | 3 | * |
|---|
| 4 | 4 | * Module Name: psloop - Main AML parse loop |
|---|
| 5 | 5 | * |
|---|
| 6 | | - * Copyright (C) 2000 - 2018, Intel Corp. |
|---|
| 6 | + * Copyright (C) 2000 - 2020, Intel Corp. |
|---|
| 7 | 7 | * |
|---|
| 8 | 8 | *****************************************************************************/ |
|---|
| 9 | 9 | |
|---|
| .. | .. |
|---|
| 32 | 32 | acpi_ps_get_arguments(struct acpi_walk_state *walk_state, |
|---|
| 33 | 33 | u8 * aml_op_start, union acpi_parse_object *op); |
|---|
| 34 | 34 | |
|---|
| 35 | | -static void |
|---|
| 36 | | -acpi_ps_link_module_code(union acpi_parse_object *parent_op, |
|---|
| 37 | | - u8 *aml_start, u32 aml_length, acpi_owner_id owner_id); |
|---|
| 38 | | - |
|---|
| 39 | 35 | /******************************************************************************* |
|---|
| 40 | 36 | * |
|---|
| 41 | 37 | * FUNCTION: acpi_ps_get_arguments |
|---|
| .. | .. |
|---|
| 56 | 52 | { |
|---|
| 57 | 53 | acpi_status status = AE_OK; |
|---|
| 58 | 54 | union acpi_parse_object *arg = NULL; |
|---|
| 59 | | - const struct acpi_opcode_info *op_info; |
|---|
| 60 | 55 | |
|---|
| 61 | 56 | ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); |
|---|
| 62 | 57 | |
|---|
| .. | .. |
|---|
| 136 | 131 | walk_state->arg_count, |
|---|
| 137 | 132 | walk_state->pass_number)); |
|---|
| 138 | 133 | |
|---|
| 139 | | - /* |
|---|
| 140 | | - * This case handles the legacy option that groups all module-level |
|---|
| 141 | | - * code blocks together and defers execution until all of the tables |
|---|
| 142 | | - * are loaded. Execute all of these blocks at this time. |
|---|
| 143 | | - * Execute any module-level code that was detected during the table |
|---|
| 144 | | - * load phase. |
|---|
| 145 | | - * |
|---|
| 146 | | - * Note: this option is deprecated and will be eliminated in the |
|---|
| 147 | | - * future. Use of this option can cause problems with AML code that |
|---|
| 148 | | - * depends upon in-order immediate execution of module-level code. |
|---|
| 149 | | - */ |
|---|
| 150 | | - if (acpi_gbl_group_module_level_code && |
|---|
| 151 | | - (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) && |
|---|
| 152 | | - ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { |
|---|
| 153 | | - /* |
|---|
| 154 | | - * We want to skip If/Else/While constructs during Pass1 because we |
|---|
| 155 | | - * want to actually conditionally execute the code during Pass2. |
|---|
| 156 | | - * |
|---|
| 157 | | - * Except for disassembly, where we always want to walk the |
|---|
| 158 | | - * If/Else/While packages |
|---|
| 159 | | - */ |
|---|
| 160 | | - switch (op->common.aml_opcode) { |
|---|
| 161 | | - case AML_IF_OP: |
|---|
| 162 | | - case AML_ELSE_OP: |
|---|
| 163 | | - case AML_WHILE_OP: |
|---|
| 164 | | - /* |
|---|
| 165 | | - * Currently supported module-level opcodes are: |
|---|
| 166 | | - * IF/ELSE/WHILE. These appear to be the most common, |
|---|
| 167 | | - * and easiest to support since they open an AML |
|---|
| 168 | | - * package. |
|---|
| 169 | | - */ |
|---|
| 170 | | - if (walk_state->pass_number == |
|---|
| 171 | | - ACPI_IMODE_LOAD_PASS1) { |
|---|
| 172 | | - acpi_ps_link_module_code(op->common. |
|---|
| 173 | | - parent, |
|---|
| 174 | | - aml_op_start, |
|---|
| 175 | | - (u32) |
|---|
| 176 | | - (walk_state-> |
|---|
| 177 | | - parser_state. |
|---|
| 178 | | - pkg_end - |
|---|
| 179 | | - aml_op_start), |
|---|
| 180 | | - walk_state-> |
|---|
| 181 | | - owner_id); |
|---|
| 182 | | - } |
|---|
| 183 | | - |
|---|
| 184 | | - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
|---|
| 185 | | - "Pass1: Skipping an If/Else/While body\n")); |
|---|
| 186 | | - |
|---|
| 187 | | - /* Skip body of if/else/while in pass 1 */ |
|---|
| 188 | | - |
|---|
| 189 | | - walk_state->parser_state.aml = |
|---|
| 190 | | - walk_state->parser_state.pkg_end; |
|---|
| 191 | | - walk_state->arg_count = 0; |
|---|
| 192 | | - break; |
|---|
| 193 | | - |
|---|
| 194 | | - default: |
|---|
| 195 | | - /* |
|---|
| 196 | | - * Check for an unsupported executable opcode at module |
|---|
| 197 | | - * level. We must be in PASS1, the parent must be a SCOPE, |
|---|
| 198 | | - * The opcode class must be EXECUTE, and the opcode must |
|---|
| 199 | | - * not be an argument to another opcode. |
|---|
| 200 | | - */ |
|---|
| 201 | | - if ((walk_state->pass_number == |
|---|
| 202 | | - ACPI_IMODE_LOAD_PASS1) |
|---|
| 203 | | - && (op->common.parent->common.aml_opcode == |
|---|
| 204 | | - AML_SCOPE_OP)) { |
|---|
| 205 | | - op_info = |
|---|
| 206 | | - acpi_ps_get_opcode_info(op->common. |
|---|
| 207 | | - aml_opcode); |
|---|
| 208 | | - if ((op_info->class == |
|---|
| 209 | | - AML_CLASS_EXECUTE) && (!arg)) { |
|---|
| 210 | | - ACPI_WARNING((AE_INFO, |
|---|
| 211 | | - "Unsupported module-level executable opcode " |
|---|
| 212 | | - "0x%.2X at table offset 0x%.4X", |
|---|
| 213 | | - op->common. |
|---|
| 214 | | - aml_opcode, |
|---|
| 215 | | - (u32) |
|---|
| 216 | | - (ACPI_PTR_DIFF |
|---|
| 217 | | - (aml_op_start, |
|---|
| 218 | | - walk_state-> |
|---|
| 219 | | - parser_state. |
|---|
| 220 | | - aml_start) + |
|---|
| 221 | | - sizeof(struct |
|---|
| 222 | | - acpi_table_header)))); |
|---|
| 223 | | - } |
|---|
| 224 | | - } |
|---|
| 225 | | - break; |
|---|
| 226 | | - } |
|---|
| 227 | | - } |
|---|
| 228 | | - |
|---|
| 229 | 134 | /* Special processing for certain opcodes */ |
|---|
| 230 | 135 | |
|---|
| 231 | 136 | switch (op->common.aml_opcode) { |
|---|
| .. | .. |
|---|
| 302 | 207 | |
|---|
| 303 | 208 | /******************************************************************************* |
|---|
| 304 | 209 | * |
|---|
| 305 | | - * FUNCTION: acpi_ps_link_module_code |
|---|
| 306 | | - * |
|---|
| 307 | | - * PARAMETERS: parent_op - Parent parser op |
|---|
| 308 | | - * aml_start - Pointer to the AML |
|---|
| 309 | | - * aml_length - Length of executable AML |
|---|
| 310 | | - * owner_id - owner_id of module level code |
|---|
| 311 | | - * |
|---|
| 312 | | - * RETURN: None. |
|---|
| 313 | | - * |
|---|
| 314 | | - * DESCRIPTION: Wrap the module-level code with a method object and link the |
|---|
| 315 | | - * object to the global list. Note, the mutex field of the method |
|---|
| 316 | | - * object is used to link multiple module-level code objects. |
|---|
| 317 | | - * |
|---|
| 318 | | - * NOTE: In this legacy option, each block of detected executable AML |
|---|
| 319 | | - * code that is outside of any control method is wrapped with a temporary |
|---|
| 320 | | - * control method object and placed on a global list below. |
|---|
| 321 | | - * |
|---|
| 322 | | - * This function executes the module-level code for all tables only after |
|---|
| 323 | | - * all of the tables have been loaded. It is a legacy option and is |
|---|
| 324 | | - * not compatible with other ACPI implementations. See acpi_ns_load_table. |
|---|
| 325 | | - * |
|---|
| 326 | | - * This function will be removed when the legacy option is removed. |
|---|
| 327 | | - * |
|---|
| 328 | | - ******************************************************************************/ |
|---|
| 329 | | - |
|---|
| 330 | | -static void |
|---|
| 331 | | -acpi_ps_link_module_code(union acpi_parse_object *parent_op, |
|---|
| 332 | | - u8 *aml_start, u32 aml_length, acpi_owner_id owner_id) |
|---|
| 333 | | -{ |
|---|
| 334 | | - union acpi_operand_object *prev; |
|---|
| 335 | | - union acpi_operand_object *next; |
|---|
| 336 | | - union acpi_operand_object *method_obj; |
|---|
| 337 | | - struct acpi_namespace_node *parent_node; |
|---|
| 338 | | - |
|---|
| 339 | | - ACPI_FUNCTION_TRACE(ps_link_module_code); |
|---|
| 340 | | - |
|---|
| 341 | | - /* Get the tail of the list */ |
|---|
| 342 | | - |
|---|
| 343 | | - prev = next = acpi_gbl_module_code_list; |
|---|
| 344 | | - while (next) { |
|---|
| 345 | | - prev = next; |
|---|
| 346 | | - next = next->method.mutex; |
|---|
| 347 | | - } |
|---|
| 348 | | - |
|---|
| 349 | | - /* |
|---|
| 350 | | - * Insert the module level code into the list. Merge it if it is |
|---|
| 351 | | - * adjacent to the previous element. |
|---|
| 352 | | - */ |
|---|
| 353 | | - if (!prev || |
|---|
| 354 | | - ((prev->method.aml_start + prev->method.aml_length) != aml_start)) { |
|---|
| 355 | | - |
|---|
| 356 | | - /* Create, initialize, and link a new temporary method object */ |
|---|
| 357 | | - |
|---|
| 358 | | - method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD); |
|---|
| 359 | | - if (!method_obj) { |
|---|
| 360 | | - return_VOID; |
|---|
| 361 | | - } |
|---|
| 362 | | - |
|---|
| 363 | | - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
|---|
| 364 | | - "Create/Link new code block: %p\n", |
|---|
| 365 | | - method_obj)); |
|---|
| 366 | | - |
|---|
| 367 | | - if (parent_op->common.node) { |
|---|
| 368 | | - parent_node = parent_op->common.node; |
|---|
| 369 | | - } else { |
|---|
| 370 | | - parent_node = acpi_gbl_root_node; |
|---|
| 371 | | - } |
|---|
| 372 | | - |
|---|
| 373 | | - method_obj->method.aml_start = aml_start; |
|---|
| 374 | | - method_obj->method.aml_length = aml_length; |
|---|
| 375 | | - method_obj->method.owner_id = owner_id; |
|---|
| 376 | | - method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL; |
|---|
| 377 | | - |
|---|
| 378 | | - /* |
|---|
| 379 | | - * Save the parent node in next_object. This is cheating, but we |
|---|
| 380 | | - * don't want to expand the method object. |
|---|
| 381 | | - */ |
|---|
| 382 | | - method_obj->method.next_object = |
|---|
| 383 | | - ACPI_CAST_PTR(union acpi_operand_object, parent_node); |
|---|
| 384 | | - |
|---|
| 385 | | - if (!prev) { |
|---|
| 386 | | - acpi_gbl_module_code_list = method_obj; |
|---|
| 387 | | - } else { |
|---|
| 388 | | - prev->method.mutex = method_obj; |
|---|
| 389 | | - } |
|---|
| 390 | | - } else { |
|---|
| 391 | | - ACPI_DEBUG_PRINT((ACPI_DB_PARSE, |
|---|
| 392 | | - "Appending to existing code block: %p\n", |
|---|
| 393 | | - prev)); |
|---|
| 394 | | - |
|---|
| 395 | | - prev->method.aml_length += aml_length; |
|---|
| 396 | | - } |
|---|
| 397 | | - |
|---|
| 398 | | - return_VOID; |
|---|
| 399 | | -} |
|---|
| 400 | | - |
|---|
| 401 | | -/******************************************************************************* |
|---|
| 402 | | - * |
|---|
| 403 | 210 | * FUNCTION: acpi_ps_parse_loop |
|---|
| 404 | 211 | * |
|---|
| 405 | 212 | * PARAMETERS: walk_state - Current state |
|---|
| .. | .. |
|---|
| 428 | 235 | parser_state = &walk_state->parser_state; |
|---|
| 429 | 236 | walk_state->arg_types = 0; |
|---|
| 430 | 237 | |
|---|
| 431 | | -#if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) |
|---|
| 238 | +#ifndef ACPI_CONSTANT_EVAL_ONLY |
|---|
| 432 | 239 | |
|---|
| 433 | 240 | if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { |
|---|
| 434 | 241 | |
|---|
| .. | .. |
|---|
| 508 | 315 | */ |
|---|
| 509 | 316 | if ((walk_state-> |
|---|
| 510 | 317 | parse_flags & ACPI_PARSE_MODULE_LEVEL) |
|---|
| 511 | | - && status == AE_ALREADY_EXISTS) { |
|---|
| 318 | + && ((status == AE_ALREADY_EXISTS) |
|---|
| 319 | + || (status == AE_NOT_FOUND))) { |
|---|
| 512 | 320 | status = AE_OK; |
|---|
| 513 | 321 | } |
|---|
| 514 | 322 | if (status == AE_CTRL_PARSE_CONTINUE) { |
|---|
| .. | .. |
|---|
| 537 | 345 | * the scope op because the parse failure indicates that |
|---|
| 538 | 346 | * the device may not exist. |
|---|
| 539 | 347 | */ |
|---|
| 540 | | - ACPI_ERROR((AE_INFO, |
|---|
| 541 | | - "Skip parsing opcode %s", |
|---|
| 542 | | - acpi_ps_get_opcode_name |
|---|
| 543 | | - (walk_state->opcode))); |
|---|
| 348 | + ACPI_INFO(("Skipping parse of AML opcode: %s (0x%4.4X)", acpi_ps_get_opcode_name(walk_state->opcode), walk_state->opcode)); |
|---|
| 544 | 349 | |
|---|
| 545 | 350 | /* |
|---|
| 546 | 351 | * Determine the opcode length before skipping the opcode. |
|---|