diff options
Diffstat (limited to 'drivers/acpi')
-rw-r--r-- | drivers/acpi/acpica/acglobal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/acnamesp.h | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/acobject.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/acparser.h | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/dsfield.c | 18 | ||||
-rw-r--r-- | drivers/acpi/acpica/dsmethod.c | 15 | ||||
-rw-r--r-- | drivers/acpi/acpica/dswload.c | 41 | ||||
-rw-r--r-- | drivers/acpi/acpica/exconfig.c | 7 | ||||
-rw-r--r-- | drivers/acpi/acpica/nseval.c | 137 | ||||
-rw-r--r-- | drivers/acpi/acpica/psloop.c | 119 | ||||
-rw-r--r-- | drivers/acpi/acpica/psxface.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/utglobal.c | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/utxface.c | 10 |
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[]; | |||
295 | ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; | 295 | ACPI_EXTERN struct acpi_namespace_node acpi_gbl_root_node_struct; |
296 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; | 296 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_root_node; |
297 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; | 297 | ACPI_EXTERN struct acpi_namespace_node *acpi_gbl_fadt_gpe_device; |
298 | ACPI_EXTERN union acpi_operand_object *acpi_gbl_module_code_list; | ||
298 | 299 | ||
299 | extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; | 300 | extern const u8 acpi_gbl_ns_properties[ACPI_NUM_NS_TYPES]; |
300 | extern const struct acpi_predefined_names | 301 | extern 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 | */ |
197 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); | 197 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info *info); |
198 | 198 | ||
199 | void 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 |
51 | ACPI_MODULE_NAME("nseval") | 51 | ACPI_MODULE_NAME("nseval") |
52 | 52 | ||
53 | /* Local prototypes */ | ||
54 | static void | ||
55 | acpi_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 | |||
79 | acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) | 85 | acpi_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 | |||
300 | void 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 | |||
365 | static void | ||
366 | acpi_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 | |||
86 | acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, | 86 | acpi_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 | ||
89 | static void | ||
90 | acpi_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 | |||
613 | static void | ||
614 | acpi_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. |