2005-04-17 02:20:36 +04:00
/*******************************************************************************
*
2006-05-27 00:36:00 +04:00
* Module Name : nseval - Object evaluation , includes control method execution
2005-04-17 02:20:36 +04:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
/*
2016-01-15 03:17:03 +03:00
* Copyright ( C ) 2000 - 2016 , Intel Corp .
2005-04-17 02:20:36 +04:00
* All rights reserved .
*
* Redistribution and use in source and binary forms , with or without
* modification , are permitted provided that the following conditions
* are met :
* 1. Redistributions of source code must retain the above copyright
* notice , this list of conditions , and the following disclaimer ,
* without modification .
* 2. Redistributions in binary form must reproduce at minimum a disclaimer
* substantially similar to the " NO WARRANTY " disclaimer below
* ( " Disclaimer " ) and any redistribution must be conditioned upon
* including a substantially similar Disclaimer requirement for further
* binary redistribution .
* 3. Neither the names of the above - listed copyright holders nor the names
* of any contributors may be used to endorse or promote products derived
* from this software without specific prior written permission .
*
* Alternatively , this software may be distributed under the terms of the
* GNU General Public License ( " GPL " ) version 2 as published by the Free
* Software Foundation .
*
* NO WARRANTY
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* " AS IS " AND ANY EXPRESS OR IMPLIED WARRANTIES , INCLUDING , BUT NOT
* LIMITED TO , THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
* A PARTICULAR PURPOSE ARE DISCLAIMED . IN NO EVENT SHALL THE COPYRIGHT
* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL , EXEMPLARY , OR CONSEQUENTIAL
* DAMAGES ( INCLUDING , BUT NOT LIMITED TO , PROCUREMENT OF SUBSTITUTE GOODS
* OR SERVICES ; LOSS OF USE , DATA , OR PROFITS ; OR BUSINESS INTERRUPTION )
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY , WHETHER IN CONTRACT ,
* STRICT LIABILITY , OR TORT ( INCLUDING NEGLIGENCE OR OTHERWISE ) ARISING
* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE , EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGES .
*/
# include <acpi/acpi.h>
2009-01-09 08:30:03 +03:00
# include "accommon.h"
# include "acparser.h"
# include "acinterp.h"
# include "acnamesp.h"
2005-04-17 02:20:36 +04:00
# define _COMPONENT ACPI_NAMESPACE
2005-08-05 08:44:28 +04:00
ACPI_MODULE_NAME ( " nseval " )
2005-04-17 02:20:36 +04:00
2009-08-13 10:03:15 +04:00
/* Local prototypes */
static void
acpi_ns_exec_module_code ( union acpi_operand_object * method_obj ,
struct acpi_evaluate_info * info ) ;
2005-04-17 02:20:36 +04:00
/*******************************************************************************
*
2006-05-27 00:36:00 +04:00
* FUNCTION : acpi_ns_evaluate
2005-04-17 02:20:36 +04:00
*
2015-07-01 09:45:38 +03:00
* PARAMETERS : info - Evaluation info block , contains these fields
* and more :
2006-05-27 00:36:00 +04:00
* prefix_node - Prefix or Method / Object Node to execute
2013-05-30 06:00:01 +04:00
* relative_path - Name of method to execute , If NULL , the
2006-05-27 00:36:00 +04:00
* Node is the object to execute
2012-07-12 05:40:10 +04:00
* parameters - List of parameters to pass to the method ,
2005-04-19 06:49:35 +04:00
* terminated by NULL . Params itself may be
2005-04-17 02:20:36 +04:00
* NULL if no parameters are being passed .
2005-04-19 06:49:35 +04:00
* parameter_type - Type of Parameter list
* return_object - Where to put method ' s return value ( if
* any ) . If NULL , no value is returned .
2012-07-12 05:40:10 +04:00
* flags - ACPI_IGNORE_RETURN_VALUE to delete return
2005-04-17 02:20:36 +04:00
*
* RETURN : Status
*
2006-05-27 00:36:00 +04:00
* DESCRIPTION : Execute a control method or return the current value of an
* ACPI namespace object .
2005-04-17 02:20:36 +04:00
*
2006-05-27 00:36:00 +04:00
* MUTEX : Locks interpreter
2005-04-17 02:20:36 +04:00
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2009-08-13 10:03:15 +04:00
2013-05-30 06:00:01 +04:00
acpi_status acpi_ns_evaluate ( struct acpi_evaluate_info * info )
2005-04-17 02:20:36 +04:00
{
2005-08-05 08:44:28 +04:00
acpi_status status ;
2005-04-17 02:20:36 +04:00
2006-05-27 00:36:00 +04:00
ACPI_FUNCTION_TRACE ( ns_evaluate ) ;
2005-04-17 02:20:36 +04:00
if ( ! info ) {
2005-08-05 08:44:28 +04:00
return_ACPI_STATUS ( AE_BAD_PARAMETER ) ;
2005-04-17 02:20:36 +04:00
}
2013-05-30 06:00:01 +04:00
if ( ! info - > node ) {
2013-04-12 04:24:22 +04:00
/*
2013-05-30 06:00:01 +04:00
* Get the actual namespace node for the target object if we
* need to . Handles these cases :
2013-04-12 04:24:22 +04:00
*
2013-05-30 06:00:01 +04:00
* 1 ) Null node , valid pathname from root ( absolute path )
* 2 ) Node and valid pathname ( path relative to Node )
* 3 ) Node , Null pathname
2013-04-12 04:24:22 +04:00
*/
2013-05-30 06:00:01 +04:00
status =
acpi_ns_get_node ( info - > prefix_node , info - > relative_pathname ,
ACPI_NS_NO_UPSEARCH , & info - > node ) ;
2013-04-12 04:24:22 +04:00
if ( ACPI_FAILURE ( status ) ) {
return_ACPI_STATUS ( status ) ;
}
2005-04-17 02:20:36 +04:00
}
/*
2013-05-30 06:00:01 +04:00
* For a method alias , we must grab the actual method node so that
* proper scoping context will be established before execution .
2005-04-17 02:20:36 +04:00
*/
2013-05-30 06:00:01 +04:00
if ( acpi_ns_get_type ( info - > node ) = = ACPI_TYPE_LOCAL_METHOD_ALIAS ) {
info - > node =
2005-08-05 08:44:28 +04:00
ACPI_CAST_PTR ( struct acpi_namespace_node ,
2013-05-30 06:00:01 +04:00
info - > node - > object ) ;
}
/* Complete the info block initialization */
info - > return_object = NULL ;
info - > node_flags = info - > node - > flags ;
info - > obj_desc = acpi_ns_get_attached_object ( info - > node ) ;
ACPI_DEBUG_PRINT ( ( ACPI_DB_NAMES , " %s [%p] Value %p \n " ,
info - > relative_pathname , info - > node ,
acpi_ns_get_attached_object ( info - > node ) ) ) ;
/* Get info if we have a predefined name (_HID, etc.) */
info - > predefined =
acpi_ut_match_predefined_method ( info - > node - > name . ascii ) ;
/* Get the full pathname to the object, for use in warning messages */
2015-12-29 08:53:50 +03:00
info - > full_pathname = acpi_ns_get_normalized_pathname ( info - > node , TRUE ) ;
2013-05-30 06:00:01 +04:00
if ( ! info - > full_pathname ) {
return_ACPI_STATUS ( AE_NO_MEMORY ) ;
2005-04-17 02:20:36 +04:00
}
2013-05-30 06:00:01 +04:00
/* Count the number of arguments being passed in */
info - > param_count = 0 ;
if ( info - > parameters ) {
while ( info - > parameters [ info - > param_count ] ) {
info - > param_count + + ;
}
2006-05-27 00:36:00 +04:00
2013-05-30 06:00:01 +04:00
/* Warn on impossible argument count */
if ( info - > param_count > ACPI_METHOD_NUM_ARGS ) {
ACPI_WARN_PREDEFINED ( ( AE_INFO , info - > full_pathname ,
ACPI_WARN_ALWAYS ,
" Excess arguments (%u) - using only %u " ,
info - > param_count ,
ACPI_METHOD_NUM_ARGS ) ) ;
info - > param_count = ACPI_METHOD_NUM_ARGS ;
}
}
/*
* For predefined names : Check that the declared argument count
* matches the ACPI spec - - otherwise this is a BIOS error .
*/
acpi_ns_check_acpi_compliance ( info - > full_pathname , info - > node ,
info - > predefined ) ;
2008-09-28 11:26:17 +04:00
2005-04-17 02:20:36 +04:00
/*
2013-05-30 06:00:01 +04:00
* For all names : Check that the incoming argument count for
* this method / object matches the actual ASL / AML definition .
*/
acpi_ns_check_argument_count ( info - > full_pathname , info - > node ,
info - > param_count , info - > predefined ) ;
/* For predefined names: Typecheck all incoming arguments */
acpi_ns_check_argument_types ( info ) ;
/*
* Three major evaluation cases :
2005-04-17 02:20:36 +04:00
*
2013-05-30 06:00:01 +04:00
* 1 ) Object types that cannot be evaluated by definition
* 2 ) The object is a control method - - execute it
* 3 ) The object is not a method - - just return it ' s current value
2005-04-17 02:20:36 +04:00
*/
2013-05-30 06:00:01 +04:00
switch ( acpi_ns_get_type ( info - > node ) ) {
case ACPI_TYPE_DEVICE :
case ACPI_TYPE_EVENT :
case ACPI_TYPE_MUTEX :
case ACPI_TYPE_REGION :
case ACPI_TYPE_THERMAL :
case ACPI_TYPE_LOCAL_SCOPE :
/*
* 1 ) Disallow evaluation of certain object types . For these ,
* object evaluation is undefined and not supported .
*/
ACPI_ERROR ( ( AE_INFO ,
" %s: Evaluation of object type [%s] is not supported " ,
info - > full_pathname ,
acpi_ut_get_type_name ( info - > node - > type ) ) ) ;
status = AE_TYPE ;
goto cleanup ;
case ACPI_TYPE_METHOD :
2005-04-17 02:20:36 +04:00
/*
2013-05-30 06:00:01 +04:00
* 2 ) Object is a control method - execute it
2005-04-17 02:20:36 +04:00
*/
2006-05-27 00:36:00 +04:00
/* Verify that there is a method object associated with this node */
2005-04-17 02:20:36 +04:00
2006-05-27 00:36:00 +04:00
if ( ! info - > obj_desc ) {
ACPI_ERROR ( ( AE_INFO ,
2013-05-30 06:00:01 +04:00
" %s: Method has no attached sub-object " ,
info - > full_pathname ) ) ;
status = AE_NULL_OBJECT ;
goto cleanup ;
2006-05-27 00:36:00 +04:00
}
2005-04-17 02:20:36 +04:00
2006-05-27 00:36:00 +04:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_EXEC ,
2013-05-30 06:00:01 +04:00
" **** Execute method [%s] at AML address %p length %X \n " ,
info - > full_pathname ,
2006-05-27 00:36:00 +04:00
info - > obj_desc - > method . aml_start + 1 ,
info - > obj_desc - > method . aml_length - 1 ) ) ;
2005-04-17 02:20:36 +04:00
2006-05-27 00:36:00 +04:00
/*
* Any namespace deletion must acquire both the namespace and
* interpreter locks to ensure that no thread is using the portion of
* the namespace that is being deleted .
*
* Execute the method via the interpreter . The interpreter is locked
* here before calling into the AML parser
*/
2007-05-10 06:56:38 +04:00
acpi_ex_enter_interpreter ( ) ;
2006-05-27 00:36:00 +04:00
status = acpi_ps_execute_method ( info ) ;
acpi_ex_exit_interpreter ( ) ;
2013-05-30 06:00:01 +04:00
break ;
default :
2006-05-27 00:36:00 +04:00
/*
2013-05-30 06:00:01 +04:00
* 3 ) All other non - method objects - - get the current object value
2006-05-27 00:36:00 +04:00
*/
2005-04-17 02:20:36 +04:00
2006-05-27 00:36:00 +04:00
/*
2013-05-30 06:00:01 +04:00
* Some objects require additional resolution steps ( e . g . , the Node
* may be a field that must be read , etc . ) - - we can ' t just grab
* the object out of the node .
2006-05-27 00:36:00 +04:00
*
* Use resolve_node_to_value ( ) to get the associated value .
*
* NOTE : we can get away with passing in NULL for a walk state because
2013-05-30 06:00:01 +04:00
* the Node is guaranteed to not be a reference to either a method
2006-05-27 00:36:00 +04:00
* local or a method argument ( because this interface is never called
* from a running method . )
*
* Even though we do not directly invoke the interpreter for object
2013-05-30 06:00:01 +04:00
* resolution , we must lock it because we could access an op_region .
* The op_region access code assumes that the interpreter is locked .
2006-05-27 00:36:00 +04:00
*/
2007-05-10 06:56:38 +04:00
acpi_ex_enter_interpreter ( ) ;
2005-04-17 02:20:36 +04:00
2013-05-30 06:00:01 +04:00
/* TBD: resolve_node_to_value has a strange interface, fix */
info - > return_object =
ACPI_CAST_PTR ( union acpi_operand_object , info - > node ) ;
2005-04-17 02:20:36 +04:00
2006-05-27 00:36:00 +04:00
status =
2013-05-30 06:00:01 +04:00
acpi_ex_resolve_node_to_value ( ACPI_CAST_INDIRECT_PTR
( struct acpi_namespace_node ,
& info - > return_object ) , NULL ) ;
2006-05-27 00:36:00 +04:00
acpi_ex_exit_interpreter ( ) ;
2005-04-17 02:20:36 +04:00
2013-05-30 06:00:01 +04:00
if ( ACPI_FAILURE ( status ) ) {
2015-08-25 05:28:26 +03:00
info - > return_object = NULL ;
2013-05-30 06:00:01 +04:00
goto cleanup ;
2005-04-17 02:20:36 +04:00
}
2013-05-30 06:00:01 +04:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_NAMES , " Returned object %p [%s] \n " ,
info - > return_object ,
acpi_ut_get_object_type_name ( info - >
return_object ) ) ) ;
status = AE_CTRL_RETURN_VALUE ; /* Always has a "return value" */
break ;
2005-04-17 02:20:36 +04:00
}
2008-11-13 06:19:24 +03:00
/*
2013-05-30 06:00:01 +04:00
* For predefined names , check the return value against the ACPI
* specification . Some incorrect return value types are repaired .
2008-11-13 06:19:24 +03:00
*/
2013-05-30 06:00:01 +04:00
( void ) acpi_ns_check_return_value ( info - > node , info , info - > param_count ,
status , & info - > return_object ) ;
2008-09-28 11:26:17 +04:00
/* Check if there is a return value that must be dealt with */
2006-05-27 00:36:00 +04:00
if ( status = = AE_CTRL_RETURN_VALUE ) {
/* If caller does not want the return value, delete it */
2005-04-17 02:20:36 +04:00
2006-05-27 00:36:00 +04:00
if ( info - > flags & ACPI_IGNORE_RETURN_VALUE ) {
acpi_ut_remove_reference ( info - > return_object ) ;
info - > return_object = NULL ;
}
/* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */
status = AE_OK ;
}
ACPI_DEBUG_PRINT ( ( ACPI_DB_NAMES ,
" *** Completed evaluation of object %s *** \n " ,
2013-05-30 06:00:01 +04:00
info - > relative_pathname ) ) ;
2006-05-27 00:36:00 +04:00
2013-10-29 05:30:02 +04:00
cleanup :
2006-05-27 00:36:00 +04:00
/*
* Namespace was unlocked by the handling acpi_ns * function , so we
2013-05-30 06:00:01 +04:00
* just free the pathname and return
2006-05-27 00:36:00 +04:00
*/
2013-05-30 06:00:01 +04:00
ACPI_FREE ( info - > full_pathname ) ;
info - > full_pathname = NULL ;
2005-08-05 08:44:28 +04:00
return_ACPI_STATUS ( status ) ;
2005-04-17 02:20:36 +04:00
}
2009-08-13 10:03:15 +04:00
/*******************************************************************************
*
* FUNCTION : acpi_ns_exec_module_code_list
*
* PARAMETERS : None
*
* RETURN : None . Exceptions during method execution are ignored , since
* we cannot abort a table load .
*
* DESCRIPTION : Execute all elements of the global module - level code list .
* Each element is executed as a single control method .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
void acpi_ns_exec_module_code_list ( void )
{
union acpi_operand_object * prev ;
union acpi_operand_object * next ;
struct acpi_evaluate_info * info ;
u32 method_count = 0 ;
ACPI_FUNCTION_TRACE ( ns_exec_module_code_list ) ;
/* Exit now if the list is empty */
next = acpi_gbl_module_code_list ;
if ( ! next ) {
return_VOID ;
}
/* Allocate the evaluation information block */
info = ACPI_ALLOCATE ( sizeof ( struct acpi_evaluate_info ) ) ;
if ( ! info ) {
return_VOID ;
}
/* Walk the list, executing each "method" */
while ( next ) {
prev = next ;
next = next - > method . mutex ;
/* Clear the link field and execute the method */
prev - > method . mutex = NULL ;
acpi_ns_exec_module_code ( prev , info ) ;
method_count + + ;
/* Delete the (temporary) method object */
acpi_ut_remove_reference ( prev ) ;
}
2016-02-19 09:16:42 +03:00
ACPI_INFO ( ( " Executed %u blocks of module-level executable AML code " ,
2009-08-13 10:03:15 +04:00
method_count ) ) ;
ACPI_FREE ( info ) ;
acpi_gbl_module_code_list = NULL ;
return_VOID ;
}
/*******************************************************************************
*
* FUNCTION : acpi_ns_exec_module_code
*
* PARAMETERS : method_obj - Object container for the module - level code
2012-07-12 05:40:10 +04:00
* info - Info block for method evaluation
2009-08-13 10:03:15 +04:00
*
* RETURN : None . Exceptions during method execution are ignored , since
* we cannot abort a table load .
*
* DESCRIPTION : Execute a control method containing a block of module - level
* executable AML code . The control method is temporarily
* installed to the root node , then evaluated .
*
* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
static void
acpi_ns_exec_module_code ( union acpi_operand_object * method_obj ,
struct acpi_evaluate_info * info )
{
2009-11-12 04:57:53 +03:00
union acpi_operand_object * parent_obj ;
struct acpi_namespace_node * parent_node ;
acpi_object_type type ;
2009-08-13 10:03:15 +04:00
acpi_status status ;
ACPI_FUNCTION_TRACE ( ns_exec_module_code ) ;
2009-11-12 04:57:53 +03:00
/*
* Get the parent node . We cheat by using the next_object field
* of the method object descriptor .
*/
2016-01-15 03:16:57 +03:00
parent_node =
ACPI_CAST_PTR ( struct acpi_namespace_node ,
2009-11-12 04:57:53 +03:00
method_obj - > method . next_object ) ;
type = acpi_ns_get_type ( parent_node ) ;
2009-12-11 10:28:27 +03:00
/*
* Get the region handler and save it in the method object . We may need
* this if an operation region declaration causes a _REG method to be run .
*
* We can ' t do this in acpi_ps_link_module_code because
* acpi_gbl_root_node - > Object is NULL at PASS1 .
*/
if ( ( type = = ACPI_TYPE_DEVICE ) & & parent_node - > object ) {
2011-01-12 04:19:43 +03:00
method_obj - > method . dispatch . handler =
2009-12-11 10:28:27 +03:00
parent_node - > object - > device . handler ;
}
2009-11-12 04:57:53 +03:00
/* Must clear next_object (acpi_ns_attach_object needs the field) */
method_obj - > method . next_object = NULL ;
2009-08-13 10:03:15 +04:00
/* Initialize the evaluation information block */
2015-07-01 09:45:11 +03:00
memset ( info , 0 , sizeof ( struct acpi_evaluate_info ) ) ;
2009-11-12 04:57:53 +03:00
info - > prefix_node = parent_node ;
2009-08-13 10:03:15 +04:00
/*
2016-01-15 03:16:57 +03:00
* Get the currently attached parent object . Add a reference ,
* because the ref count will be decreased when the method object
* is installed to the parent node .
2009-08-13 10:03:15 +04:00
*/
2009-11-12 04:57:53 +03:00
parent_obj = acpi_ns_get_attached_object ( parent_node ) ;
if ( parent_obj ) {
acpi_ut_add_reference ( parent_obj ) ;
}
2009-08-13 10:03:15 +04:00
2009-11-12 04:57:53 +03:00
/* Install the method (module-level code) in the parent node */
2009-08-13 10:03:15 +04:00
2016-01-15 03:16:57 +03:00
status =
acpi_ns_attach_object ( parent_node , method_obj , ACPI_TYPE_METHOD ) ;
2009-08-13 10:03:15 +04:00
if ( ACPI_FAILURE ( status ) ) {
goto exit ;
}
2009-11-12 04:57:53 +03:00
/* Execute the parent node as a control method */
2009-08-13 10:03:15 +04:00
status = acpi_ns_evaluate ( info ) ;
2015-08-25 05:29:45 +03:00
ACPI_DEBUG_PRINT ( ( ACPI_DB_INIT_NAMES ,
" Executed module-level code at %p \n " ,
2009-08-13 10:03:15 +04:00
method_obj - > method . aml_start ) ) ;
2009-12-11 09:36:47 +03:00
/* Delete a possible implicit return value (in slack mode) */
if ( info - > return_object ) {
acpi_ut_remove_reference ( info - > return_object ) ;
}
2009-08-13 10:03:15 +04:00
/* Detach the temporary method object */
2009-11-12 04:57:53 +03:00
acpi_ns_detach_object ( parent_node ) ;
2009-08-13 10:03:15 +04:00
2009-11-12 04:57:53 +03:00
/* Restore the original parent object */
2009-08-13 10:03:15 +04:00
2009-11-12 04:57:53 +03:00
if ( parent_obj ) {
status = acpi_ns_attach_object ( parent_node , parent_obj , type ) ;
} else {
parent_node - > type = ( u8 ) type ;
}
2009-08-13 10:03:15 +04:00
2013-10-29 05:30:02 +04:00
exit :
2009-11-12 04:57:53 +03:00
if ( parent_obj ) {
acpi_ut_remove_reference ( parent_obj ) ;
}
2009-08-13 10:03:15 +04:00
return_VOID ;
}