Commit 954c9189 authored by Len Brown's avatar Len Brown Committed by Len Brown

[ACPI] ACPICA 20040311 from Bob Moore

Fixed a problem where errors occurring during the parse phase of control
method execution did not abort cleanly.  For example, objects created
and installed in the namespace were not deleted.  This caused all
subsequent invocations of the method to return the AE_ALREADY_EXISTS
exception.

Implemented a mechanism to force a control method to "Serialized"
execution if the method attempts to create namespace objects.
(The root of the AE_ALREADY_EXISTS problem.)

Implemented support for the predefined _OSI "internal" control method.
Initial supported strings are "Linux", "Windows 2000", "Windows 2001",
and "Windows 2001.1", and can be easily upgraded for new strings as
necessary.  This feature allows Linux to execute
the fully tested, "Windows" code path through the ASL code

Global Lock Support:  Now allows multiple acquires and releases with any
internal thread.  Removed concept of "owning thread" for this special
mutex.

Fixed two functions that were inappropriately declaring large objects on
the CPU stack: ps_parse_loop() and ns_evaluate_relative().
Reduces the stack usage during method execution considerably.

Fixed a problem in the ACPI 2.0 FACS descriptor (actbl2.h) where the
S4Bios_f field was incorrectly defined as UINT32 instead of UINT32_BIT.

Fixed a problem where acpi_ev_gpe_detect() would fault
if there were no GPEs defined on the machine.

Implemented two runtime options:  One to force all control method
execution to "Serialized" to mimic Windows behavior, another to disable
_OSI support if it causes problems on a given machine.
parent ae386697
...@@ -106,7 +106,7 @@ acpi_ds_parse_method ( ...@@ -106,7 +106,7 @@ acpi_ds_parse_method (
/* Create a mutex for the method if there is a concurrency limit */ /* Create a mutex for the method if there is a concurrency limit */
if ((obj_desc->method.concurrency != INFINITE_CONCURRENCY) && if ((obj_desc->method.concurrency != ACPI_INFINITE_CONCURRENCY) &&
(!obj_desc->method.semaphore)) { (!obj_desc->method.semaphore)) {
status = acpi_os_create_semaphore (obj_desc->method.concurrency, status = acpi_os_create_semaphore (obj_desc->method.concurrency,
obj_desc->method.concurrency, obj_desc->method.concurrency,
...@@ -300,6 +300,7 @@ acpi_ds_call_control_method ( ...@@ -300,6 +300,7 @@ acpi_ds_call_control_method (
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
if (!(obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY)) {
/* 1) Parse: Create a new walk state for the preempting walk */ /* 1) Parse: Create a new walk state for the preempting walk */
next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id, next_walk_state = acpi_ds_create_walk_state (obj_desc->method.owning_id,
...@@ -308,6 +309,7 @@ acpi_ds_call_control_method ( ...@@ -308,6 +309,7 @@ acpi_ds_call_control_method (
return_ACPI_STATUS (AE_NO_MEMORY); return_ACPI_STATUS (AE_NO_MEMORY);
} }
/* Create and init a Root Node */ /* Create and init a Root Node */
op = acpi_ps_create_scope_op (); op = acpi_ps_create_scope_op ();
...@@ -328,6 +330,7 @@ acpi_ds_call_control_method ( ...@@ -328,6 +330,7 @@ acpi_ds_call_control_method (
status = acpi_ps_parse_aml (next_walk_state); status = acpi_ps_parse_aml (next_walk_state);
acpi_ps_delete_parse_tree (op); acpi_ps_delete_parse_tree (op);
}
/* 2) Execute: Create a new state for the preempting walk */ /* 2) Execute: Create a new state for the preempting walk */
...@@ -337,7 +340,6 @@ acpi_ds_call_control_method ( ...@@ -337,7 +340,6 @@ acpi_ds_call_control_method (
status = AE_NO_MEMORY; status = AE_NO_MEMORY;
goto cleanup; goto cleanup;
} }
/* /*
* The resolved arguments were put on the previous walk state's operand * The resolved arguments were put on the previous walk state's operand
* stack. Operands on the previous walk state stack always * stack. Operands on the previous walk state stack always
...@@ -369,16 +371,25 @@ acpi_ds_call_control_method ( ...@@ -369,16 +371,25 @@ acpi_ds_call_control_method (
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"Starting nested execution, newstate=%p\n", next_walk_state)); "Starting nested execution, newstate=%p\n", next_walk_state));
if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) {
status = obj_desc->method.implementation (next_walk_state);
return_ACPI_STATUS (status);
}
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
/* On error, we must delete the new walk state */ /* On error, we must delete the new walk state */
cleanup: cleanup:
if (next_walk_state->method_desc) {
/* Decrement the thread count on the method parse tree */
next_walk_state->method_desc->method.thread_count--;
}
(void) acpi_ds_terminate_control_method (next_walk_state); (void) acpi_ds_terminate_control_method (next_walk_state);
acpi_ds_delete_walk_state (next_walk_state); acpi_ds_delete_walk_state (next_walk_state);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
...@@ -500,10 +511,30 @@ acpi_ds_terminate_control_method ( ...@@ -500,10 +511,30 @@ acpi_ds_terminate_control_method (
} }
} }
/* Decrement the thread count on the method parse tree */ if (walk_state->method_desc->method.thread_count) {
ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
"*** Not deleting method namespace, there are still %d threads\n",
walk_state->method_desc->method.thread_count));
}
walk_state->method_desc->method.thread_count--;
if (!walk_state->method_desc->method.thread_count) { if (!walk_state->method_desc->method.thread_count) {
/*
* Support to dynamically change a method from not_serialized to
* Serialized if it appears that the method is written foolishly and
* does not support multiple thread execution. The best example of this
* is if such a method creates namespace objects and blocks. A second
* thread will fail with an AE_ALREADY_EXISTS exception
*
* This code is here because we must wait until the last thread exits
* before creating the synchronization semaphore.
*/
if ((walk_state->method_desc->method.concurrency == 1) &&
(!walk_state->method_desc->method.semaphore)) {
status = acpi_os_create_semaphore (1,
1,
&walk_state->method_desc->method.semaphore);
}
/* /*
* There are no more threads executing this method. Perform * There are no more threads executing this method. Perform
* additional cleanup. * additional cleanup.
......
...@@ -149,6 +149,11 @@ acpi_ev_gpe_detect ( ...@@ -149,6 +149,11 @@ acpi_ev_gpe_detect (
ACPI_FUNCTION_NAME ("ev_gpe_detect"); ACPI_FUNCTION_NAME ("ev_gpe_detect");
/* Check for the case where there are no GPEs */
if (!gpe_xrupt_list) {
return (int_status);
}
/* Examine all GPE blocks attached to this interrupt level */ /* Examine all GPE blocks attached to this interrupt level */
......
...@@ -587,27 +587,33 @@ acpi_ex_create_method ( ...@@ -587,27 +587,33 @@ acpi_ex_create_method (
obj_desc->method.aml_start = aml_start; obj_desc->method.aml_start = aml_start;
obj_desc->method.aml_length = aml_length; obj_desc->method.aml_length = aml_length;
/* disassemble the method flags */ /*
* Disassemble the method flags. Split off the Arg Count
* for efficiency
*/
method_flags = (u8) operand[1]->integer.value; method_flags = (u8) operand[1]->integer.value;
obj_desc->method.method_flags = method_flags; obj_desc->method.method_flags = (u8) (method_flags & ~AML_METHOD_ARG_COUNT);
obj_desc->method.param_count = (u8) (method_flags & METHOD_FLAGS_ARG_COUNT); obj_desc->method.param_count = (u8) (method_flags & AML_METHOD_ARG_COUNT);
/* /*
* Get the concurrency count. If required, a semaphore will be * Get the concurrency count. If required, a semaphore will be
* created for this method when it is parsed. * created for this method when it is parsed.
*/ */
if (method_flags & METHOD_FLAGS_SERIALIZED) { if (acpi_gbl_all_methods_serialized) {
obj_desc->method.concurrency = 1;
obj_desc->method.method_flags |= AML_METHOD_SERIALIZED;
}
else if (method_flags & AML_METHOD_SERIALIZED) {
/* /*
* ACPI 1.0: Concurrency = 1 * ACPI 1.0: Concurrency = 1
* ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1) * ACPI 2.0: Concurrency = (sync_level (in method declaration) + 1)
*/ */
obj_desc->method.concurrency = (u8) obj_desc->method.concurrency = (u8)
(((method_flags & METHOD_FLAGS_SYNCH_LEVEL) >> 4) + 1); (((method_flags & AML_METHOD_SYNCH_LEVEL) >> 4) + 1);
} }
else { else {
obj_desc->method.concurrency = INFINITE_CONCURRENCY; obj_desc->method.concurrency = ACPI_INFINITE_CONCURRENCY;
} }
/* Attach the new object to the method Node */ /* Attach the new object to the method Node */
......
...@@ -176,9 +176,11 @@ acpi_ex_acquire_mutex ( ...@@ -176,9 +176,11 @@ acpi_ex_acquire_mutex (
/* /*
* Support for multiple acquires by the owning thread * Support for multiple acquires by the owning thread
*/ */
if (obj_desc->mutex.owner_thread) {
/* Special case for Global Lock, allow all threads */
if ((obj_desc->mutex.owner_thread) && if ((obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id) ||
(obj_desc->mutex.owner_thread->thread_id == walk_state->thread->thread_id)) { (obj_desc->mutex.semaphore == acpi_gbl_global_lock_semaphore)) {
/* /*
* The mutex is already owned by this thread, * The mutex is already owned by this thread,
* just increment the acquisition depth * just increment the acquisition depth
...@@ -186,6 +188,7 @@ acpi_ex_acquire_mutex ( ...@@ -186,6 +188,7 @@ acpi_ex_acquire_mutex (
obj_desc->mutex.acquisition_depth++; obj_desc->mutex.acquisition_depth++;
return_ACPI_STATUS (AE_OK); return_ACPI_STATUS (AE_OK);
} }
}
/* Acquire the mutex, wait if necessary */ /* Acquire the mutex, wait if necessary */
...@@ -254,9 +257,12 @@ acpi_ex_release_mutex ( ...@@ -254,9 +257,12 @@ acpi_ex_release_mutex (
return_ACPI_STATUS (AE_AML_INTERNAL); return_ACPI_STATUS (AE_AML_INTERNAL);
} }
/* The Mutex is owned, but this thread must be the owner */ /*
* The Mutex is owned, but this thread must be the owner.
if (obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) { * Special case for Global Lock, any thread can release
*/
if ((obj_desc->mutex.owner_thread->thread_id != walk_state->thread->thread_id) &&
(obj_desc->mutex.semaphore != acpi_gbl_global_lock_semaphore)) {
ACPI_REPORT_ERROR (( ACPI_REPORT_ERROR ((
"Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n", "Thread %X cannot release Mutex [%4.4s] acquired by thread %X\n",
walk_state->thread->thread_id, walk_state->thread->thread_id,
......
...@@ -105,8 +105,15 @@ acpi_ns_root_initialize (void) ...@@ -105,8 +105,15 @@ acpi_ns_root_initialize (void)
"Entering predefined entries into namespace\n")); "Entering predefined entries into namespace\n"));
for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) { for (init_val = acpi_gbl_pre_defined_names; init_val->name; init_val++) {
/* _OSI is optional for now, will be permanent later */
if (!ACPI_STRCMP (init_val->name, "_OSI") && !acpi_gbl_create_osi_method) {
continue;
}
status = acpi_ns_lookup (NULL, init_val->name, init_val->type, status = acpi_ns_lookup (NULL, init_val->name, init_val->type,
ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH, NULL, &new_node); ACPI_IMODE_LOAD_PASS2, ACPI_NS_NO_UPSEARCH,
NULL, &new_node);
if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ { if (ACPI_FAILURE (status) || (!new_node)) /* Must be on same line for code converter */ {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
...@@ -122,7 +129,8 @@ acpi_ns_root_initialize (void) ...@@ -122,7 +129,8 @@ acpi_ns_root_initialize (void)
if (init_val->val) { if (init_val->val) {
status = acpi_os_predefined_override (init_val, &val); status = acpi_os_predefined_override (init_val, &val);
if (ACPI_FAILURE (status)) { if (ACPI_FAILURE (status)) {
ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Could not override predefined %s\n", ACPI_DEBUG_PRINT ((ACPI_DB_ERROR,
"Could not override predefined %s\n",
init_val->name)); init_val->name));
} }
...@@ -147,15 +155,20 @@ acpi_ns_root_initialize (void) ...@@ -147,15 +155,20 @@ acpi_ns_root_initialize (void)
*/ */
switch (init_val->type) { switch (init_val->type) {
case ACPI_TYPE_METHOD: case ACPI_TYPE_METHOD:
obj_desc->method.param_count = obj_desc->method.param_count = (u8) ACPI_STRTOUL
(u8) ACPI_STRTOUL (val, NULL, 10); (val, NULL, 10);
obj_desc->common.flags |= AOPOBJ_DATA_VALID; obj_desc->common.flags |= AOPOBJ_DATA_VALID;
#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) #if defined (_ACPI_ASL_COMPILER) || defined (_ACPI_DUMP_App)
/* Compiler cheats by putting parameter count in the owner_iD */ /* i_aSL Compiler cheats by putting parameter count in the owner_iD */
new_node->owner_id = obj_desc->method.param_count; new_node->owner_id = obj_desc->method.param_count;
#else
/* Mark this as a very SPECIAL method */
obj_desc->method.method_flags = AML_METHOD_INTERNAL_ONLY;
obj_desc->method.implementation = acpi_ut_osi_implementation;
#endif #endif
break; break;
...@@ -180,8 +193,8 @@ acpi_ns_root_initialize (void) ...@@ -180,8 +193,8 @@ acpi_ns_root_initialize (void)
case ACPI_TYPE_MUTEX: case ACPI_TYPE_MUTEX:
obj_desc->mutex.node = new_node; obj_desc->mutex.node = new_node;
obj_desc->mutex.sync_level = obj_desc->mutex.sync_level = (u16) ACPI_STRTOUL
(u16) ACPI_STRTOUL (val, NULL, 10); (val, NULL, 10);
if (ACPI_STRCMP (init_val->name, "_GL_") == 0) { if (ACPI_STRCMP (init_val->name, "_GL_") == 0) {
/* /*
...@@ -213,6 +226,7 @@ acpi_ns_root_initialize (void) ...@@ -213,6 +226,7 @@ acpi_ns_root_initialize (void)
default: default:
ACPI_REPORT_ERROR (("Unsupported initial type value %X\n", ACPI_REPORT_ERROR (("Unsupported initial type value %X\n",
init_val->type)); init_val->type));
acpi_ut_remove_reference (obj_desc); acpi_ut_remove_reference (obj_desc);
......
...@@ -334,10 +334,11 @@ acpi_ns_install_node ( ...@@ -334,10 +334,11 @@ acpi_ns_install_node (
node->owner_id = owner_id; node->owner_id = owner_id;
node->type = (u8) type; node->type = (u8) type;
ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, "%4.4s (%s) added to %4.4s (%s) %p at %p\n", ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), "%4.4s (%s) [Node %p Owner %X] added to %4.4s (%s) [Node %p]\n",
acpi_ut_get_node_name (node), acpi_ut_get_type_name (node->type), node, owner_id,
acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type), acpi_ut_get_node_name (parent_node), acpi_ut_get_type_name (parent_node->type),
parent_node, node)); parent_node));
/* /*
* Increment the reference count(s) of all parents up to * Increment the reference count(s) of all parents up to
......
...@@ -82,11 +82,11 @@ acpi_ns_evaluate_relative ( ...@@ -82,11 +82,11 @@ acpi_ns_evaluate_relative (
union acpi_operand_object **params, union acpi_operand_object **params,
union acpi_operand_object **return_object) union acpi_operand_object **return_object)
{ {
struct acpi_namespace_node *prefix_node;
acpi_status status; acpi_status status;
struct acpi_namespace_node *prefix_node;
struct acpi_namespace_node *node = NULL; struct acpi_namespace_node *node = NULL;
union acpi_generic_state *scope_info;
char *internal_path = NULL; char *internal_path = NULL;
union acpi_generic_state scope_info;
ACPI_FUNCTION_TRACE ("ns_evaluate_relative"); ACPI_FUNCTION_TRACE ("ns_evaluate_relative");
...@@ -106,6 +106,11 @@ acpi_ns_evaluate_relative ( ...@@ -106,6 +106,11 @@ acpi_ns_evaluate_relative (
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
scope_info = acpi_ut_create_generic_state ();
if (!scope_info) {
goto cleanup1;
}
/* Get the prefix handle and Node */ /* Get the prefix handle and Node */
status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE); status = acpi_ut_acquire_mutex (ACPI_MTX_NAMESPACE);
...@@ -122,8 +127,8 @@ acpi_ns_evaluate_relative ( ...@@ -122,8 +127,8 @@ acpi_ns_evaluate_relative (
/* Lookup the name in the namespace */ /* Lookup the name in the namespace */
scope_info.scope.node = prefix_node; scope_info->scope.node = prefix_node;
status = acpi_ns_lookup (&scope_info, internal_path, ACPI_TYPE_ANY, status = acpi_ns_lookup (scope_info, internal_path, ACPI_TYPE_ANY,
ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL, ACPI_IMODE_EXECUTE, ACPI_NS_NO_UPSEARCH, NULL,
&node); &node);
...@@ -148,7 +153,9 @@ acpi_ns_evaluate_relative ( ...@@ -148,7 +153,9 @@ acpi_ns_evaluate_relative (
pathname)); pathname));
cleanup: cleanup:
acpi_ut_delete_generic_state (scope_info);
cleanup1:
ACPI_MEM_FREE (internal_path); ACPI_MEM_FREE (internal_path);
return_ACPI_STATUS (status); return_ACPI_STATUS (status);
} }
......
...@@ -426,7 +426,7 @@ acpi_ps_parse_loop ( ...@@ -426,7 +426,7 @@ acpi_ps_parse_loop (
acpi_status status = AE_OK; acpi_status status = AE_OK;
union acpi_parse_object *op = NULL; /* current op */ union acpi_parse_object *op = NULL; /* current op */
union acpi_parse_object *arg = NULL; union acpi_parse_object *arg = NULL;
union acpi_parse_object pre_op; union acpi_parse_object *pre_op = NULL;
struct acpi_parse_state *parser_state; struct acpi_parse_state *parser_state;
u8 *aml_op_start = NULL; u8 *aml_op_start = NULL;
...@@ -547,8 +547,17 @@ acpi_ps_parse_loop ( ...@@ -547,8 +547,17 @@ acpi_ps_parse_loop (
/* Create Op structure and append to parent's argument list */ /* Create Op structure and append to parent's argument list */
if (walk_state->op_info->flags & AML_NAMED) { if (walk_state->op_info->flags & AML_NAMED) {
pre_op.common.value.arg = NULL; /* Allocate a new pre_op if necessary */
pre_op.common.aml_opcode = walk_state->opcode;
if (!pre_op) {
pre_op = acpi_ps_alloc_op (walk_state->opcode);
if (!pre_op) {
return_ACPI_STATUS (AE_NO_MEMORY);
}
}
pre_op->common.value.arg = NULL;
pre_op->common.aml_opcode = walk_state->opcode;
/* /*
* Get and append arguments until we find the node that contains * Get and append arguments until we find the node that contains
...@@ -562,7 +571,7 @@ acpi_ps_parse_loop ( ...@@ -562,7 +571,7 @@ acpi_ps_parse_loop (
goto close_this_op; goto close_this_op;
} }
acpi_ps_append_arg (&pre_op, arg); acpi_ps_append_arg (pre_op, arg);
INCREMENT_ARG_LIST (walk_state->arg_types); INCREMENT_ARG_LIST (walk_state->arg_types);
} }
...@@ -603,7 +612,7 @@ acpi_ps_parse_loop ( ...@@ -603,7 +612,7 @@ acpi_ps_parse_loop (
goto close_this_op; goto close_this_op;
} }
acpi_ps_append_arg (op, pre_op.common.value.arg); acpi_ps_append_arg (op, pre_op->common.value.arg);
acpi_gbl_depth++; acpi_gbl_depth++;
if (op->common.aml_opcode == AML_REGION_OP) { if (op->common.aml_opcode == AML_REGION_OP) {
...@@ -854,6 +863,10 @@ acpi_ps_parse_loop ( ...@@ -854,6 +863,10 @@ acpi_ps_parse_loop (
acpi_ps_complete_this_op (walk_state, op); acpi_ps_complete_this_op (walk_state, op);
op = NULL; op = NULL;
if (pre_op) {
acpi_ps_free_op (pre_op);
pre_op = NULL;
}
switch (status) { switch (status) {
case AE_OK: case AE_OK:
...@@ -1118,6 +1131,27 @@ acpi_ps_parse_aml ( ...@@ -1118,6 +1131,27 @@ acpi_ps_parse_aml (
else if (status != AE_OK) { else if (status != AE_OK) {
ACPI_REPORT_METHOD_ERROR ("Method execution failed", ACPI_REPORT_METHOD_ERROR ("Method execution failed",
walk_state->method_node, NULL, status); walk_state->method_node, NULL, status);
/* Check for possible multi-thread reentrancy problem */
if ((status == AE_ALREADY_EXISTS) &&
(!walk_state->method_desc->method.semaphore)) {
/*
* This method is marked not_serialized, but it tried to create a named
* object, causing the second thread entrance to fail. We will workaround
* this by marking the method permanently as Serialized.
*/
walk_state->method_desc->method.method_flags |= AML_METHOD_SERIALIZED;
walk_state->method_desc->method.concurrency = 1;
}
}
if (walk_state->method_desc) {
/* Decrement the thread count on the method parse tree */
if (walk_state->method_desc->method.thread_count) {
walk_state->method_desc->method.thread_count--;
}
} }
/* We are done with this walk, move on to the parent if any */ /* We are done with this walk, move on to the parent if any */
......
...@@ -167,7 +167,6 @@ acpi_ps_push_scope ( ...@@ -167,7 +167,6 @@ acpi_ps_push_scope (
return_ACPI_STATUS (AE_NO_MEMORY); return_ACPI_STATUS (AE_NO_MEMORY);
} }
scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE; scope->common.data_type = ACPI_DESC_TYPE_STATE_PSCOPE;
scope->parse_scope.op = op; scope->parse_scope.op = op;
scope->parse_scope.arg_list = remaining_args; scope->parse_scope.arg_list = remaining_args;
...@@ -178,13 +177,11 @@ acpi_ps_push_scope ( ...@@ -178,13 +177,11 @@ acpi_ps_push_scope (
acpi_ut_push_generic_state (&parser_state->scope, scope); acpi_ut_push_generic_state (&parser_state->scope, scope);
if (arg_count == ACPI_VAR_ARGS) { if (arg_count == ACPI_VAR_ARGS) {
/* multiple arguments */ /* multiple arguments */
scope->parse_scope.arg_end = parser_state->pkg_end; scope->parse_scope.arg_end = parser_state->pkg_end;
} }
else { else {
/* single argument */ /* single argument */
...@@ -241,7 +238,6 @@ acpi_ps_pop_scope ( ...@@ -241,7 +238,6 @@ acpi_ps_pop_scope (
acpi_ut_delete_generic_state (scope); acpi_ut_delete_generic_state (scope);
} }
else { else {
/* empty parse stack, prepare to fetch next opcode */ /* empty parse stack, prepare to fetch next opcode */
...@@ -250,7 +246,6 @@ acpi_ps_pop_scope ( ...@@ -250,7 +246,6 @@ acpi_ps_pop_scope (
*arg_count = 0; *arg_count = 0;
} }
ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped Op %p Args %X\n", *op, *arg_count)); ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Popped Op %p Args %X\n", *op, *arg_count));
return_VOID; return_VOID;
} }
...@@ -275,14 +270,14 @@ acpi_ps_cleanup_scope ( ...@@ -275,14 +270,14 @@ acpi_ps_cleanup_scope (
{ {
union acpi_generic_state *scope; union acpi_generic_state *scope;
ACPI_FUNCTION_TRACE_PTR ("ps_cleanup_scope", parser_state); ACPI_FUNCTION_TRACE_PTR ("ps_cleanup_scope", parser_state);
if (!parser_state) { if (!parser_state) {
return; return_VOID;
} }
/* Delete anything on the scope stack */ /* Delete anything on the scope stack */
while (parser_state->scope) { while (parser_state->scope) {
......
...@@ -51,6 +51,62 @@ ...@@ -51,6 +51,62 @@
ACPI_MODULE_NAME ("uteval") ACPI_MODULE_NAME ("uteval")
/*******************************************************************************
*
* FUNCTION: acpi_ut_osi_implementation
*
* PARAMETERS: walk_state - Current walk state
*
* RETURN: Status
*
* DESCRIPTION: Implementation of _OSI predefined control method
* Supported = _OSI (String)
*
******************************************************************************/
acpi_status
acpi_ut_osi_implementation (
struct acpi_walk_state *walk_state)
{
union acpi_operand_object *string_desc;
union acpi_operand_object *return_desc;
acpi_native_uint i;
ACPI_FUNCTION_TRACE ("ut_osi_implementation");
/* Validate the string input argument */
string_desc = walk_state->arguments[0].object;
if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
return_ACPI_STATUS (AE_TYPE);
}
/* Create a return object (Default value = 0) */
return_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
if (!return_desc) {
return_ACPI_STATUS (AE_NO_MEMORY);
}
/* Compare input string to table of supported strings */
for (i = 0; i < ACPI_NUM_OSI_STRINGS; i++) {
if (!ACPI_STRCMP (string_desc->string.pointer,
(char *) acpi_gbl_valid_osi_strings[i])) {
/* This string is supported */
return_desc->integer.value = 0xFFFFFFFF;
break;
}
}
walk_state->return_desc = return_desc;
return_ACPI_STATUS (AE_CTRL_TERMINATE);
}
/******************************************************************************* /*******************************************************************************
* *
* FUNCTION: acpi_ut_evaluate_object * FUNCTION: acpi_ut_evaluate_object
......
...@@ -185,6 +185,15 @@ const char *acpi_gbl_highest_dstate_names[4] = { ...@@ -185,6 +185,15 @@ const char *acpi_gbl_highest_dstate_names[4] = {
"_S3D", "_S3D",
"_S4D"}; "_S4D"};
/* Strings supported by the _OSI predefined (internal) method */
const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS] = {
"Linux",
"Windows 2000",
"Windows 2001",
"Windows 2001.1"};
/****************************************************************************** /******************************************************************************
* *
* Namespace globals * Namespace globals
...@@ -195,14 +204,10 @@ const char *acpi_gbl_highest_dstate_names[4] = { ...@@ -195,14 +204,10 @@ const char *acpi_gbl_highest_dstate_names[4] = {
/* /*
* Predefined ACPI Names (Built-in to the Interpreter) * Predefined ACPI Names (Built-in to the Interpreter)
* *
* Initial values are currently supported only for types String and Number.
* Both are specified as strings in this table.
*
* NOTES: * NOTES:
* 1) _SB_ is defined to be a device to allow _SB_/_INI to be run * 1) _SB_ is defined to be a device to allow \_SB_._INI to be run
* during the initialization sequence. * during the initialization sequence.
*/ */
const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
{ {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL}, { {"_GPE", ACPI_TYPE_LOCAL_SCOPE, NULL},
{"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL}, {"_PR_", ACPI_TYPE_LOCAL_SCOPE, NULL},
...@@ -213,7 +218,7 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = ...@@ -213,7 +218,7 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
{"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME}, {"_OS_", ACPI_TYPE_STRING, ACPI_OS_NAME},
{"_GL_", ACPI_TYPE_MUTEX, "0"}, {"_GL_", ACPI_TYPE_MUTEX, "0"},
#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
{"_OSI", ACPI_TYPE_METHOD, "1"}, {"_OSI", ACPI_TYPE_METHOD, "1"},
#endif #endif
{NULL, ACPI_TYPE_ANY, NULL} /* Table terminator */ {NULL, ACPI_TYPE_ANY, NULL} /* Table terminator */
...@@ -224,7 +229,6 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] = ...@@ -224,7 +229,6 @@ const struct acpi_predefined_names acpi_gbl_pre_defined_names[] =
* Properties of the ACPI Object Types, both internal and external. * Properties of the ACPI Object Types, both internal and external.
* The table is indexed by values of acpi_object_type * The table is indexed by values of acpi_object_type
*/ */
const u8 acpi_gbl_ns_properties[] = const u8 acpi_gbl_ns_properties[] =
{ {
ACPI_NS_NORMAL, /* 00 Any */ ACPI_NS_NORMAL, /* 00 Any */
...@@ -303,10 +307,8 @@ acpi_ut_hex_to_ascii_char ( ...@@ -303,10 +307,8 @@ acpi_ut_hex_to_ascii_char (
* *
******************************************************************************/ ******************************************************************************/
struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES]; struct acpi_table_list acpi_gbl_table_lists[NUM_ACPI_TABLE_TYPES];
struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] = struct acpi_table_support acpi_gbl_table_data[NUM_ACPI_TABLE_TYPES] =
{ {
/*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */ /*********** Name, Signature, Global typed pointer Signature size, Type How many allowed?, Contains valid AML? */
...@@ -470,9 +472,8 @@ acpi_ut_get_event_name ( ...@@ -470,9 +472,8 @@ acpi_ut_get_event_name (
* *
* The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; when * The type ACPI_TYPE_ANY (Untyped) is used as a "don't care" when searching; when
* stored in a table it really means that we have thus far seen no evidence to * stored in a table it really means that we have thus far seen no evidence to
* indicatewhat type is actually going to be stored for this entry. * indicate what type is actually going to be stored for this entry.
*/ */
static const char acpi_gbl_bad_type[] = "UNDEFINED"; static const char acpi_gbl_bad_type[] = "UNDEFINED";
#define TYPE_NAME_LENGTH 12 /* Maximum length of each string */ #define TYPE_NAME_LENGTH 12 /* Maximum length of each string */
...@@ -777,6 +778,11 @@ acpi_ut_init_globals ( ...@@ -777,6 +778,11 @@ acpi_ut_init_globals (
ACPI_FUNCTION_TRACE ("ut_init_globals"); ACPI_FUNCTION_TRACE ("ut_init_globals");
/* Runtime configuration */
acpi_gbl_create_osi_method = TRUE;
acpi_gbl_all_methods_serialized = FALSE;
/* Memory allocation and cache lists */ /* Memory allocation and cache lists */
ACPI_MEMSET (acpi_gbl_memory_lists, 0, sizeof (struct acpi_memory_list) * ACPI_NUM_MEM_LISTS); ACPI_MEMSET (acpi_gbl_memory_lists, 0, sizeof (struct acpi_memory_list) * ACPI_NUM_MEM_LISTS);
......
...@@ -64,7 +64,7 @@ ...@@ -64,7 +64,7 @@
/* Version string */ /* Version string */
#define ACPI_CA_VERSION 0x20040220 #define ACPI_CA_VERSION 0x20040311
/* Maximum objects in the various object caches */ /* Maximum objects in the various object caches */
...@@ -185,6 +185,10 @@ ...@@ -185,6 +185,10 @@
#define ACPI_SMBUS_BUFFER_SIZE 34 #define ACPI_SMBUS_BUFFER_SIZE 34
/* Number of strings associated with the _OSI reserved method */
#define ACPI_NUM_OSI_STRINGS 4
/****************************************************************************** /******************************************************************************
* *
......
...@@ -79,6 +79,14 @@ extern u32 acpi_dbg_layer; ...@@ -79,6 +79,14 @@ extern u32 acpi_dbg_layer;
extern u32 acpi_gbl_nesting_level; extern u32 acpi_gbl_nesting_level;
/*****************************************************************************
*
* Runtime configuration
*
****************************************************************************/
ACPI_EXTERN u8 acpi_gbl_create_osi_method;
ACPI_EXTERN u8 acpi_gbl_all_methods_serialized;
/***************************************************************************** /*****************************************************************************
* *
...@@ -169,6 +177,7 @@ extern const char *acpi_gbl_sleep_state_names[ACPI_ ...@@ -169,6 +177,7 @@ extern const char *acpi_gbl_sleep_state_names[ACPI_
extern const char *acpi_gbl_highest_dstate_names[4]; extern const char *acpi_gbl_highest_dstate_names[4];
extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES]; extern const struct acpi_opcode_info acpi_gbl_aml_op_info[AML_NUM_OPCODES];
extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS]; extern const char *acpi_gbl_region_types[ACPI_NUM_PREDEFINED_REGIONS];
extern const char *acpi_gbl_valid_osi_strings[ACPI_NUM_OSI_STRINGS];
/***************************************************************************** /*****************************************************************************
...@@ -179,7 +188,7 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_P ...@@ -179,7 +188,7 @@ extern const char *acpi_gbl_region_types[ACPI_NUM_P
#define NUM_NS_TYPES ACPI_TYPE_INVALID+1 #define NUM_NS_TYPES ACPI_TYPE_INVALID+1
#if defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY) #if !defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)
#define NUM_PREDEFINED_NAMES 10 #define NUM_PREDEFINED_NAMES 10
#else #else
#define NUM_PREDEFINED_NAMES 9 #define NUM_PREDEFINED_NAMES 9
......
...@@ -681,7 +681,4 @@ ...@@ -681,7 +681,4 @@
#endif /* ACPI_DBG_TRACK_ALLOCATIONS */ #endif /* ACPI_DBG_TRACK_ALLOCATIONS */
#define ACPI_GET_STACK_POINTER _asm {mov eax, ebx}
#endif /* ACMACROS_H */ #endif /* ACMACROS_H */
...@@ -180,7 +180,11 @@ struct acpi_object_event ...@@ -180,7 +180,11 @@ struct acpi_object_event
}; };
#define INFINITE_CONCURRENCY 0xFF #define ACPI_INFINITE_CONCURRENCY 0xFF
typedef
acpi_status (*ACPI_INTERNAL_METHOD) (
struct acpi_walk_state *walk_state);
struct acpi_object_method struct acpi_object_method
{ {
...@@ -190,6 +194,7 @@ struct acpi_object_method ...@@ -190,6 +194,7 @@ struct acpi_object_method
u32 aml_length; u32 aml_length;
void *semaphore; void *semaphore;
u8 *aml_start; u8 *aml_start;
ACPI_INTERNAL_METHOD implementation;
u8 concurrency; u8 concurrency;
u8 thread_count; u8 thread_count;
acpi_owner_id owning_id; acpi_owner_id owning_id;
......
...@@ -349,7 +349,6 @@ typedef u64 acpi_integer; ...@@ -349,7 +349,6 @@ typedef u64 acpi_integer;
/* /*
* Power state values * Power state values
*/ */
#define ACPI_STATE_UNKNOWN (u8) 0xFF #define ACPI_STATE_UNKNOWN (u8) 0xFF
#define ACPI_STATE_S0 (u8) 0 #define ACPI_STATE_S0 (u8) 0
...@@ -393,7 +392,6 @@ typedef u64 acpi_integer; ...@@ -393,7 +392,6 @@ typedef u64 acpi_integer;
#define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6 #define ACPI_NOTIFY_BUS_MODE_MISMATCH (u8) 6
#define ACPI_NOTIFY_POWER_FAULT (u8) 7 #define ACPI_NOTIFY_POWER_FAULT (u8) 7
/* /*
* Table types. These values are passed to the table related APIs * Table types. These values are passed to the table related APIs
*/ */
...@@ -409,7 +407,6 @@ typedef u32 acpi_table_type; ...@@ -409,7 +407,6 @@ typedef u32 acpi_table_type;
#define ACPI_TABLE_MAX 6 #define ACPI_TABLE_MAX 6
#define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1) #define NUM_ACPI_TABLE_TYPES (ACPI_TABLE_MAX+1)
/* /*
* Types associated with ACPI names and objects. The first group of * Types associated with ACPI names and objects. The first group of
* values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition * values (up to ACPI_TYPE_EXTERNAL_MAX) correspond to the definition
...@@ -794,7 +791,7 @@ acpi_status (*acpi_init_handler) ( ...@@ -794,7 +791,7 @@ acpi_status (*acpi_init_handler) (
#define ACPI_INIT_DEVICE_INI 1 #define ACPI_INIT_DEVICE_INI 1
/* Address Spaces (Operation Regions */ /* Address Spaces (For Operation Regions) */
typedef typedef
acpi_status (*acpi_adr_space_handler) ( acpi_status (*acpi_adr_space_handler) (
......
...@@ -52,7 +52,6 @@ acpi_status (*acpi_pkg_callback) ( ...@@ -52,7 +52,6 @@ acpi_status (*acpi_pkg_callback) (
union acpi_generic_state *state, union acpi_generic_state *state,
void *context); void *context);
acpi_status acpi_status
acpi_ut_walk_package_tree ( acpi_ut_walk_package_tree (
union acpi_operand_object *source_object, union acpi_operand_object *source_object,
...@@ -60,7 +59,6 @@ acpi_ut_walk_package_tree ( ...@@ -60,7 +59,6 @@ acpi_ut_walk_package_tree (
acpi_pkg_callback walk_callback, acpi_pkg_callback walk_callback,
void *context); void *context);
struct acpi_pkg_info struct acpi_pkg_info
{ {
u8 *free_space; u8 *free_space;
...@@ -475,6 +473,10 @@ acpi_ut_delete_internal_object_list ( ...@@ -475,6 +473,10 @@ acpi_ut_delete_internal_object_list (
#define METHOD_NAME__PRS "_PRS" #define METHOD_NAME__PRS "_PRS"
acpi_status
acpi_ut_osi_implementation (
struct acpi_walk_state *walk_state);
acpi_status acpi_status
acpi_ut_evaluate_object ( acpi_ut_evaluate_object (
struct acpi_namespace_node *prefix_node, struct acpi_namespace_node *prefix_node,
......
...@@ -496,11 +496,17 @@ typedef enum ...@@ -496,11 +496,17 @@ typedef enum
} AML_ACCESS_ATTRIBUTE; } AML_ACCESS_ATTRIBUTE;
/* bit fields in method_flags byte */ /* Bit fields in method_flags byte */
#define METHOD_FLAGS_ARG_COUNT 0x07 #define AML_METHOD_ARG_COUNT 0x07
#define METHOD_FLAGS_SERIALIZED 0x08 #define AML_METHOD_SERIALIZED 0x08
#define METHOD_FLAGS_SYNCH_LEVEL 0xF0 #define AML_METHOD_SYNCH_LEVEL 0xF0
/* METHOD_FLAGS_ARG_COUNT is not used internally, define additional flags */
#define AML_METHOD_INTERNAL_ONLY 0x01
#define AML_METHOD_RESERVED1 0x02
#define AML_METHOD_RESERVED2 0x04
#endif /* __AMLCODE_H__ */ #endif /* __AMLCODE_H__ */
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment