aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/acpi
diff options
context:
space:
mode:
authorLin Ming <ming.m.lin@intel.com>2009-08-13 02:03:15 -0400
committerLen Brown <len.brown@intel.com>2009-08-28 19:40:39 -0400
commit7f0c826a437157d2b19662977e9cf3b472cf24a6 (patch)
tree359c14eddb406007350e8f8a7bf96c9f8d85a2ab /drivers/acpi
parent999e08f99846a1fd6ee9642ec306a2d318925116 (diff)
ACPICA: Add support for module-level executable AML code
Add limited support for executable AML code that exists outside of any control method. This type of code has been illegal since ACPI 2.0. The code must exist in an If/Else/While block. All AML tables are supported, including tables that are dynamically loaded. ACPICA BZ 762. http://acpica.org/bugzilla/show_bug.cgi?id=762 Signed-off-by: Lin Ming <ming.m.lin@intel.com> Signed-off-by: Bob Moore <robert.moore@intel.com> Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi')
-rw-r--r--drivers/acpi/acpica/acglobal.h1
-rw-r--r--drivers/acpi/acpica/acnamesp.h2
-rw-r--r--drivers/acpi/acpica/acobject.h1
-rw-r--r--drivers/acpi/acpica/acparser.h2
-rw-r--r--drivers/acpi/acpica/dsfield.c18
-rw-r--r--drivers/acpi/acpica/dsmethod.c15
-rw-r--r--drivers/acpi/acpica/dswload.c41
-rw-r--r--drivers/acpi/acpica/exconfig.c7
-rw-r--r--drivers/acpi/acpica/nseval.c137
-rw-r--r--drivers/acpi/acpica/psloop.c119
-rw-r--r--drivers/acpi/acpica/psxface.c4
-rw-r--r--drivers/acpi/acpica/utglobal.c1
-rw-r--r--drivers/acpi/acpica/utxface.c10
13 files changed, 306 insertions, 52 deletions
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h
index 6389f7c1de59..29ba66d5a790 100644
--- a/drivers/acpi/acpica/acglobal.h
+++ b/drivers/acpi/acpica/acglobal.h
@@ -295,6 +295,7 @@ extern char const *acpi_gbl_exception_names_ctrl[];
295ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; 295ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct;
296ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; 296ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node;
297ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; 297ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device;
298ACPI_EXTERN union acpi_operand_object *acpi_gbl_module_code_list;
298 299
299extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; 300extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES];
300extern const struct acpi_predefined_names 301extern const struct acpi_predefined_names
diff --git a/drivers/acpi/acpica/acnamesp.h b/drivers/acpi/acpica/acnamesp.h
index f75a7a01b875..09a2764c734b 100644
--- a/drivers/acpi/acpica/acnamesp.h
+++ b/drivers/acpi/acpica/acnamesp.h
@@ -196,6 +196,8 @@ acpi_ns_dump_objects(acpi_object_type type,
196 */ 196 */
197acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); 197acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info);
198 198
199void acpi_ns_exec_module_code_list(void);
200
199/* 201/*
200 * nspredef - Support for predefined/reserved names 202 * nspredef - Support for predefined/reserved names
201 */ 203 */
diff --git a/drivers/acpi/acpica/acobject.h b/drivers/acpi/acpica/acobject.h
index eb6f038b03d9..b39d682a2140 100644
--- a/drivers/acpi/acpica/acobject.h
+++ b/drivers/acpi/acpica/acobject.h
@@ -98,6 +98,7 @@
98#define AOPOBJ_SETUP_COMPLETE 0x10 98#define AOPOBJ_SETUP_COMPLETE 0x10
99#define AOPOBJ_SINGLE_DATUM 0x20 99#define AOPOBJ_SINGLE_DATUM 0x20
100#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */ 100#define AOPOBJ_INVALID 0x40 /* Used if host OS won't allow an op_region address */
101#define AOPOBJ_MODULE_LEVEL 0x80
101 102
102/****************************************************************************** 103/******************************************************************************
103 * 104 *
diff --git a/drivers/acpi/acpica/acparser.h b/drivers/acpi/acpica/acparser.h
index 23ee0fbf5619..22881e8ce229 100644
--- a/drivers/acpi/acpica/acparser.h
+++ b/drivers/acpi/acpica/acparser.h
@@ -62,6 +62,8 @@
62#define ACPI_PARSE_DEFERRED_OP 0x0100 62#define ACPI_PARSE_DEFERRED_OP 0x0100
63#define ACPI_PARSE_DISASSEMBLE 0x0200 63#define ACPI_PARSE_DISASSEMBLE 0x0200
64 64
65#define ACPI_PARSE_MODULE_LEVEL 0x0400
66
65/****************************************************************************** 67/******************************************************************************
66 * 68 *
67 * Parser interfaces 69 * Parser interfaces
diff --git a/drivers/acpi/acpica/dsfield.c b/drivers/acpi/acpica/dsfield.c
index 53e27bc5a734..54a225e56a64 100644
--- a/drivers/acpi/acpica/dsfield.c
+++ b/drivers/acpi/acpica/dsfield.c
@@ -123,9 +123,12 @@ acpi_ds_create_buffer_field(union acpi_parse_object *op,
123 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | 123 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
124 ACPI_NS_ERROR_IF_FOUND; 124 ACPI_NS_ERROR_IF_FOUND;
125 125
126 /* Mark node temporary if we are executing a method */ 126 /*
127 127 * Mark node temporary if we are executing a normal control
128 if (walk_state->method_node) { 128 * method. (Don't mark if this is a module-level code method)
129 */
130 if (walk_state->method_node &&
131 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
129 flags |= ACPI_NS_TEMPORARY; 132 flags |= ACPI_NS_TEMPORARY;
130 } 133 }
131 134
@@ -456,9 +459,12 @@ acpi_ds_init_field_objects(union acpi_parse_object *op,
456 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | 459 flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE |
457 ACPI_NS_ERROR_IF_FOUND; 460 ACPI_NS_ERROR_IF_FOUND;
458 461
459 /* Mark node(s) temporary if we are executing a method */ 462 /*
460 463 * Mark node(s) temporary if we are executing a normal control
461 if (walk_state->method_node) { 464 * method. (Don't mark if this is a module-level code method)
465 */
466 if (walk_state->method_node &&
467 !(walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
462 flags |= ACPI_NS_TEMPORARY; 468 flags |= ACPI_NS_TEMPORARY;
463 } 469 }
464 470
diff --git a/drivers/acpi/acpica/dsmethod.c b/drivers/acpi/acpica/dsmethod.c
index 14b8b8ed8023..567a4899a018 100644
--- a/drivers/acpi/acpica/dsmethod.c
+++ b/drivers/acpi/acpica/dsmethod.c
@@ -578,10 +578,15 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
578 } 578 }
579 579
580 /* 580 /*
581 * Delete any namespace objects created anywhere within 581 * Delete any namespace objects created anywhere within the
582 * the namespace by the execution of this method 582 * namespace by the execution of this method. Unless this method
583 * is a module-level executable code method, in which case we
584 * want make the objects permanent.
583 */ 585 */
584 acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id); 586 if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
587 acpi_ns_delete_namespace_by_owner(method_desc->method.
588 owner_id);
589 }
585 } 590 }
586 591
587 /* Decrement the thread count on the method */ 592 /* Decrement the thread count on the method */
@@ -622,7 +627,9 @@ acpi_ds_terminate_control_method(union acpi_operand_object *method_desc,
622 627
623 /* No more threads, we can free the owner_id */ 628 /* No more threads, we can free the owner_id */
624 629
625 acpi_ut_release_owner_id(&method_desc->method.owner_id); 630 if (!(method_desc->method.flags & AOPOBJ_MODULE_LEVEL)) {
631 acpi_ut_release_owner_id(&method_desc->method.owner_id);
632 }
626 } 633 }
627 634
628 return_VOID; 635 return_VOID;
diff --git a/drivers/acpi/acpica/dswload.c b/drivers/acpi/acpica/dswload.c
index 3023ceaa8d54..6de3a99d4cd4 100644
--- a/drivers/acpi/acpica/dswload.c
+++ b/drivers/acpi/acpica/dswload.c
@@ -581,21 +581,6 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
581 if ((!(walk_state->op_info->flags & AML_NSOPCODE) && 581 if ((!(walk_state->op_info->flags & AML_NSOPCODE) &&
582 (walk_state->opcode != AML_INT_NAMEPATH_OP)) || 582 (walk_state->opcode != AML_INT_NAMEPATH_OP)) ||
583 (!(walk_state->op_info->flags & AML_NAMED))) { 583 (!(walk_state->op_info->flags & AML_NAMED))) {
584#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
585 if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
586 (walk_state->op_info->class == AML_CLASS_CONTROL)) {
587 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
588 "Begin/EXEC: %s (fl %8.8X)\n",
589 walk_state->op_info->name,
590 walk_state->op_info->flags));
591
592 /* Executing a type1 or type2 opcode outside of a method */
593
594 status =
595 acpi_ds_exec_begin_op(walk_state, out_op);
596 return_ACPI_STATUS(status);
597 }
598#endif
599 return_ACPI_STATUS(AE_OK); 584 return_ACPI_STATUS(AE_OK);
600 } 585 }
601 586
@@ -768,7 +753,13 @@ acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state,
768 753
769 /* Execution mode, node cannot already exist, node is temporary */ 754 /* Execution mode, node cannot already exist, node is temporary */
770 755
771 flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY); 756 flags |= ACPI_NS_ERROR_IF_FOUND;
757
758 if (!
759 (walk_state->
760 parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
761 flags |= ACPI_NS_TEMPORARY;
762 }
772 } 763 }
773 764
774 /* Add new entry or lookup existing entry */ 765 /* Add new entry or lookup existing entry */
@@ -851,24 +842,6 @@ acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
851 /* Check if opcode had an associated namespace object */ 842 /* Check if opcode had an associated namespace object */
852 843
853 if (!(walk_state->op_info->flags & AML_NSOBJECT)) { 844 if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
854#ifndef ACPI_NO_METHOD_EXECUTION
855#ifdef ACPI_ENABLE_MODULE_LEVEL_CODE
856 /* No namespace object. Executable opcode? */
857
858 if ((walk_state->op_info->class == AML_CLASS_EXECUTE) ||
859 (walk_state->op_info->class == AML_CLASS_CONTROL)) {
860 ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
861 "End/EXEC: %s (fl %8.8X)\n",
862 walk_state->op_info->name,
863 walk_state->op_info->flags));
864
865 /* Executing a type1 or type2 opcode outside of a method */
866
867 status = acpi_ds_exec_end_op(walk_state);
868 return_ACPI_STATUS(status);
869 }
870#endif
871#endif
872 return_ACPI_STATUS(AE_OK); 845 return_ACPI_STATUS(AE_OK);
873 } 846 }
874 847
diff --git a/drivers/acpi/acpica/exconfig.c b/drivers/acpi/acpica/exconfig.c
index 277fd609611a..24afef81af39 100644
--- a/drivers/acpi/acpica/exconfig.c
+++ b/drivers/acpi/acpica/exconfig.c
@@ -110,8 +110,15 @@ acpi_ex_add_table(u32 table_index,
110 if (ACPI_FAILURE(status)) { 110 if (ACPI_FAILURE(status)) {
111 acpi_ut_remove_reference(obj_desc); 111 acpi_ut_remove_reference(obj_desc);
112 *ddb_handle = NULL; 112 *ddb_handle = NULL;
113 return_ACPI_STATUS(status);
113 } 114 }
114 115
116 /* Execute any module-level code that was found in the table */
117
118 acpi_ex_exit_interpreter();
119 acpi_ns_exec_module_code_list();
120 acpi_ex_enter_interpreter();
121
115 return_ACPI_STATUS(status); 122 return_ACPI_STATUS(status);
116} 123}
117 124
diff --git a/drivers/acpi/acpica/nseval.c b/drivers/acpi/acpica/nseval.c
index 8e7dec1176c9..846d1132feb1 100644
--- a/drivers/acpi/acpica/nseval.c
+++ b/drivers/acpi/acpica/nseval.c
@@ -50,6 +50,11 @@
50#define _COMPONENT ACPI_NAMESPACE 50#define _COMPONENT ACPI_NAMESPACE
51ACPI_MODULE_NAME("nseval") 51ACPI_MODULE_NAME("nseval")
52 52
53/* Local prototypes */
54static void
55acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
56 struct acpi_evaluate_info *info);
57
53/******************************************************************************* 58/*******************************************************************************
54 * 59 *
55 * FUNCTION: acpi_ns_evaluate 60 * FUNCTION: acpi_ns_evaluate
@@ -76,6 +81,7 @@ ACPI_MODULE_NAME("nseval")
76 * MUTEX: Locks interpreter 81 * MUTEX: Locks interpreter
77 * 82 *
78 ******************************************************************************/ 83 ******************************************************************************/
84
79acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) 85acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
80{ 86{
81 acpi_status status; 87 acpi_status status;
@@ -276,3 +282,134 @@ acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info)
276 */ 282 */
277 return_ACPI_STATUS(status); 283 return_ACPI_STATUS(status);
278} 284}
285
286/*******************************************************************************
287 *
288 * FUNCTION: acpi_ns_exec_module_code_list
289 *
290 * PARAMETERS: None
291 *
292 * RETURN: None. Exceptions during method execution are ignored, since
293 * we cannot abort a table load.
294 *
295 * DESCRIPTION: Execute all elements of the global module-level code list.
296 * Each element is executed as a single control method.
297 *
298 ******************************************************************************/
299
300void acpi_ns_exec_module_code_list(void)
301{
302 union acpi_operand_object *prev;
303 union acpi_operand_object *next;
304 struct acpi_evaluate_info *info;
305 u32 method_count = 0;
306
307 ACPI_FUNCTION_TRACE(ns_exec_module_code_list);
308
309 /* Exit now if the list is empty */
310
311 next = acpi_gbl_module_code_list;
312 if (!next) {
313 return_VOID;
314 }
315
316 /* Allocate the evaluation information block */
317
318 info = ACPI_ALLOCATE(sizeof(struct acpi_evaluate_info));
319 if (!info) {
320 return_VOID;
321 }
322
323 /* Walk the list, executing each "method" */
324
325 while (next) {
326 prev = next;
327 next = next->method.mutex;
328
329 /* Clear the link field and execute the method */
330
331 prev->method.mutex = NULL;
332 acpi_ns_exec_module_code(prev, info);
333 method_count++;
334
335 /* Delete the (temporary) method object */
336
337 acpi_ut_remove_reference(prev);
338 }
339
340 ACPI_INFO((AE_INFO,
341 "Executed %u blocks of module-level executable AML code",
342 method_count));
343
344 ACPI_FREE(info);
345 acpi_gbl_module_code_list = NULL;
346 return_VOID;
347}
348
349/*******************************************************************************
350 *
351 * FUNCTION: acpi_ns_exec_module_code
352 *
353 * PARAMETERS: method_obj - Object container for the module-level code
354 * Info - Info block for method evaluation
355 *
356 * RETURN: None. Exceptions during method execution are ignored, since
357 * we cannot abort a table load.
358 *
359 * DESCRIPTION: Execute a control method containing a block of module-level
360 * executable AML code. The control method is temporarily
361 * installed to the root node, then evaluated.
362 *
363 ******************************************************************************/
364
365static void
366acpi_ns_exec_module_code(union acpi_operand_object *method_obj,
367 struct acpi_evaluate_info *info)
368{
369 union acpi_operand_object *root_obj;
370 acpi_status status;
371
372 ACPI_FUNCTION_TRACE(ns_exec_module_code);
373
374 /* Initialize the evaluation information block */
375
376 ACPI_MEMSET(info, 0, sizeof(struct acpi_evaluate_info));
377 info->prefix_node = acpi_gbl_root_node;
378
379 /*
380 * Get the currently attached root object. Add a reference, because the
381 * ref count will be decreased when the method object is installed to
382 * the root node.
383 */
384 root_obj = acpi_ns_get_attached_object(acpi_gbl_root_node);
385 acpi_ut_add_reference(root_obj);
386
387 /* Install the method (module-level code) in the root node */
388
389 status = acpi_ns_attach_object(acpi_gbl_root_node, method_obj,
390 ACPI_TYPE_METHOD);
391 if (ACPI_FAILURE(status)) {
392 goto exit;
393 }
394
395 /* Execute the root node as a control method */
396
397 status = acpi_ns_evaluate(info);
398
399 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "Executed module-level code at %p\n",
400 method_obj->method.aml_start));
401
402 /* Detach the temporary method object */
403
404 acpi_ns_detach_object(acpi_gbl_root_node);
405
406 /* Restore the original root object */
407
408 status =
409 acpi_ns_attach_object(acpi_gbl_root_node, root_obj,
410 ACPI_TYPE_DEVICE);
411
412 exit:
413 acpi_ut_remove_reference(root_obj);
414 return_VOID;
415}
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
diff --git a/drivers/acpi/acpica/psxface.c b/drivers/acpi/acpica/psxface.c
index ff06032c0f06..dd9731c29a79 100644
--- a/drivers/acpi/acpica/psxface.c
+++ b/drivers/acpi/acpica/psxface.c
@@ -280,6 +280,10 @@ acpi_status acpi_ps_execute_method(struct acpi_evaluate_info *info)
280 goto cleanup; 280 goto cleanup;
281 } 281 }
282 282
283 if (info->obj_desc->method.flags & AOPOBJ_MODULE_LEVEL) {
284 walk_state->parse_flags |= ACPI_PARSE_MODULE_LEVEL;
285 }
286
283 /* Invoke an internal method if necessary */ 287 /* Invoke an internal method if necessary */
284 288
285 if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { 289 if (info->obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c
index 9e33b6261939..3f2c68f4e959 100644
--- a/drivers/acpi/acpica/utglobal.c
+++ b/drivers/acpi/acpica/utglobal.c
@@ -807,6 +807,7 @@ acpi_status acpi_ut_init_globals(void)
807 807
808 /* Namespace */ 808 /* Namespace */
809 809
810 acpi_gbl_module_code_list = NULL;
810 acpi_gbl_root_node = NULL; 811 acpi_gbl_root_node = NULL;
811 acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME; 812 acpi_gbl_root_node_struct.name.integer = ACPI_ROOT_NAME;
812 acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED; 813 acpi_gbl_root_node_struct.descriptor_type = ACPI_DESC_TYPE_NAMED;
diff --git a/drivers/acpi/acpica/utxface.c b/drivers/acpi/acpica/utxface.c
index 483edbb3f441..b1f5f680bc78 100644
--- a/drivers/acpi/acpica/utxface.c
+++ b/drivers/acpi/acpica/utxface.c
@@ -251,6 +251,16 @@ acpi_status acpi_initialize_objects(u32 flags)
251 } 251 }
252 252
253 /* 253 /*
254 * Execute any module-level code that was detected during the table load
255 * phase. Although illegal since ACPI 2.0, there are many machines that
256 * contain this type of code. Each block of detected executable AML code
257 * outside of any control method is wrapped with a temporary control
258 * method object and placed on a global list. The methods on this list
259 * are executed below.
260 */
261 acpi_ns_exec_module_code_list();
262
263 /*
254 * Initialize the objects that remain uninitialized. This runs the 264 * Initialize the objects that remain uninitialized. This runs the
255 * executable AML that may be part of the declaration of these objects: 265 * executable AML that may be part of the declaration of these objects:
256 * operation_regions, buffer_fields, Buffers, and Packages. 266 * operation_regions, buffer_fields, Buffers, and Packages.