aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/psloop.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/acpi/acpica/psloop.c')
-rw-r--r--drivers/acpi/acpica/psloop.c119
1 files changed, 111 insertions, 8 deletions
diff --git a/drivers/acpi/acpica/psloop.c b/drivers/acpi/acpica/psloop.c
index c5f6ce19a401..cd7995b3aed4 100644
--- a/drivers/acpi/acpica/psloop.c
+++ b/drivers/acpi/acpica/psloop.c
@@ -86,6 +86,9 @@ static acpi_status
86acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, 86acpi_ps_complete_final_op(struct acpi_walk_state *walk_state,
87 union acpi_parse_object *op, acpi_status status); 87 union acpi_parse_object *op, acpi_status status);
88 88
89static void
90acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id);
91
89/******************************************************************************* 92/*******************************************************************************
90 * 93 *
91 * FUNCTION: acpi_ps_get_aml_opcode 94 * FUNCTION: acpi_ps_get_aml_opcode
@@ -390,6 +393,7 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
390{ 393{
391 acpi_status status = AE_OK; 394 acpi_status status = AE_OK;
392 union acpi_parse_object *arg = NULL; 395 union acpi_parse_object *arg = NULL;
396 const struct acpi_opcode_info *op_info;
393 397
394 ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); 398 ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
395 399
@@ -449,13 +453,11 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
449 INCREMENT_ARG_LIST(walk_state->arg_types); 453 INCREMENT_ARG_LIST(walk_state->arg_types);
450 } 454 }
451 455
452 /* Special processing for certain opcodes */ 456 /*
453 457 * Handle executable code at "module-level". This refers to
454 /* TBD (remove): Temporary mechanism to disable this code if needed */ 458 * executable opcodes that appear outside of any control method.
455 459 */
456#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE 460 if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2) &&
457
458 if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) &&
459 ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { 461 ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) {
460 /* 462 /*
461 * We want to skip If/Else/While constructs during Pass1 because we 463 * We want to skip If/Else/While constructs during Pass1 because we
@@ -469,6 +471,23 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
469 case AML_ELSE_OP: 471 case AML_ELSE_OP:
470 case AML_WHILE_OP: 472 case AML_WHILE_OP:
471 473
474 /*
475 * Currently supported module-level opcodes are:
476 * IF/ELSE/WHILE. These appear to be the most common,
477 * and easiest to support since they open an AML
478 * package.
479 */
480 if (walk_state->pass_number ==
481 ACPI_IMODE_LOAD_PASS1) {
482 acpi_ps_link_module_code(aml_op_start,
483 walk_state->
484 parser_state.
485 pkg_end -
486 aml_op_start,
487 walk_state->
488 owner_id);
489 }
490
472 ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 491 ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
473 "Pass1: Skipping an If/Else/While body\n")); 492 "Pass1: Skipping an If/Else/While body\n"));
474 493
@@ -480,10 +499,34 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
480 break; 499 break;
481 500
482 default: 501 default:
502 /*
503 * Check for an unsupported executable opcode at module
504 * level. We must be in PASS1, the parent must be a SCOPE,
505 * The opcode class must be EXECUTE, and the opcode must
506 * not be an argument to another opcode.
507 */
508 if ((walk_state->pass_number ==
509 ACPI_IMODE_LOAD_PASS1)
510 && (op->common.parent->common.aml_opcode ==
511 AML_SCOPE_OP)) {
512 op_info =
513 acpi_ps_get_opcode_info(op->common.
514 aml_opcode);
515 if ((op_info->class ==
516 AML_CLASS_EXECUTE) && (!arg)) {
517 ACPI_WARNING((AE_INFO,
518 "Detected an unsupported executable opcode "
519 "at module-level: [0x%.4X] at table offset 0x%.4X",
520 op->common.aml_opcode,
521 (u32)((aml_op_start - walk_state->parser_state.aml_start)
522 + sizeof(struct acpi_table_header))));
523 }
524 }
483 break; 525 break;
484 } 526 }
485 } 527 }
486#endif 528
529 /* Special processing for certain opcodes */
487 530
488 switch (op->common.aml_opcode) { 531 switch (op->common.aml_opcode) {
489 case AML_METHOD_OP: 532 case AML_METHOD_OP:
@@ -553,6 +596,66 @@ acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
553 596
554/******************************************************************************* 597/*******************************************************************************
555 * 598 *
599 * FUNCTION: acpi_ps_link_module_code
600 *
601 * PARAMETERS: aml_start - Pointer to the AML
602 * aml_length - Length of executable AML
603 * owner_id - owner_id of module level code
604 *
605 * RETURN: None.
606 *
607 * DESCRIPTION: Wrap the module-level code with a method object and link the
608 * object to the global list. Note, the mutex field of the method
609 * object is used to link multiple module-level code objects.
610 *
611 ******************************************************************************/
612
613static void
614acpi_ps_link_module_code(u8 *aml_start, u32 aml_length, acpi_owner_id owner_id)
615{
616 union acpi_operand_object *prev;
617 union acpi_operand_object *next;
618 union acpi_operand_object *method_obj;
619
620 /* Get the tail of the list */
621
622 prev = next = acpi_gbl_module_code_list;
623 while (next) {
624 prev = next;
625 next = next->method.mutex;
626 }
627
628 /*
629 * Insert the module level code into the list. Merge it if it is
630 * adjacent to the previous element.
631 */
632 if (!prev ||
633 ((prev->method.aml_start + prev->method.aml_length) != aml_start)) {
634
635 /* Create, initialize, and link a new temporary method object */
636
637 method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
638 if (!method_obj) {
639 return;
640 }
641
642 method_obj->method.aml_start = aml_start;
643 method_obj->method.aml_length = aml_length;
644 method_obj->method.owner_id = owner_id;
645 method_obj->method.flags |= AOPOBJ_MODULE_LEVEL;
646
647 if (!prev) {
648 acpi_gbl_module_code_list = method_obj;
649 } else {
650 prev->method.mutex = method_obj;
651 }
652 } else {
653 prev->method.aml_length += aml_length;
654 }
655}
656
657/*******************************************************************************
658 *
556 * FUNCTION: acpi_ps_complete_op 659 * FUNCTION: acpi_ps_complete_op
557 * 660 *
558 * PARAMETERS: walk_state - Current state 661 * PARAMETERS: walk_state - Current state