1 /******************************************************************************* 2 * 3 * Module Name: nseval - Object evaluation, includes control method execution 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2008, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include <acpi/acpi.h> 45 #include "accommon.h" 46 #include "acparser.h" 47 #include "acinterp.h" 48 #include "acnamesp.h" 49 50 #define _COMPONENT ACPI_NAMESPACE 51 ACPI_MODULE_NAME("nseval") 52 53 /******************************************************************************* 54 * 55 * FUNCTION: acpi_ns_evaluate 56 * 57 * PARAMETERS: Info - Evaluation info block, contains: 58 * prefix_node - Prefix or Method/Object Node to execute 59 * Pathname - Name of method to execute, If NULL, the 60 * Node is the object to execute 61 * Parameters - List of parameters to pass to the method, 62 * terminated by NULL. Params itself may be 63 * NULL if no parameters are being passed. 64 * return_object - Where to put method's return value (if 65 * any). If NULL, no value is returned. 66 * parameter_type - Type of Parameter list 67 * return_object - Where to put method's return value (if 68 * any). If NULL, no value is returned. 69 * Flags - ACPI_IGNORE_RETURN_VALUE to delete return 70 * 71 * RETURN: Status 72 * 73 * DESCRIPTION: Execute a control method or return the current value of an 74 * ACPI namespace object. 75 * 76 * MUTEX: Locks interpreter 77 * 78 ******************************************************************************/ 79 acpi_status acpi_ns_evaluate(struct acpi_evaluate_info * info) 80 { 81 acpi_status status; 82 struct acpi_namespace_node *node; 83 84 ACPI_FUNCTION_TRACE(ns_evaluate); 85 86 if (!info) { 87 return_ACPI_STATUS(AE_BAD_PARAMETER); 88 } 89 90 /* Initialize the return value to an invalid object */ 91 92 info->return_object = NULL; 93 info->param_count = 0; 94 95 /* 96 * Get the actual namespace node for the target object. Handles these cases: 97 * 98 * 1) Null node, Pathname (absolute path) 99 * 2) Node, Pathname (path relative to Node) 100 * 3) Node, Null Pathname 101 */ 102 status = acpi_ns_get_node(info->prefix_node, info->pathname, 103 ACPI_NS_NO_UPSEARCH, &info->resolved_node); 104 if (ACPI_FAILURE(status)) { 105 return_ACPI_STATUS(status); 106 } 107 108 /* 109 * For a method alias, we must grab the actual method node so that proper 110 * scoping context will be established before execution. 111 */ 112 if (acpi_ns_get_type(info->resolved_node) == 113 ACPI_TYPE_LOCAL_METHOD_ALIAS) { 114 info->resolved_node = 115 ACPI_CAST_PTR(struct acpi_namespace_node, 116 info->resolved_node->object); 117 } 118 119 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, "%s [%p] Value %p\n", info->pathname, 120 info->resolved_node, 121 acpi_ns_get_attached_object(info->resolved_node))); 122 123 node = info->resolved_node; 124 125 /* 126 * Two major cases here: 127 * 128 * 1) The object is a control method -- execute it 129 * 2) The object is not a method -- just return it's current value 130 */ 131 if (acpi_ns_get_type(info->resolved_node) == ACPI_TYPE_METHOD) { 132 /* 133 * 1) Object is a control method - execute it 134 */ 135 136 /* Verify that there is a method object associated with this node */ 137 138 info->obj_desc = 139 acpi_ns_get_attached_object(info->resolved_node); 140 if (!info->obj_desc) { 141 ACPI_ERROR((AE_INFO, 142 "Control method has no attached sub-object")); 143 return_ACPI_STATUS(AE_NULL_OBJECT); 144 } 145 146 /* Count the number of arguments being passed to the method */ 147 148 if (info->parameters) { 149 while (info->parameters[info->param_count]) { 150 if (info->param_count > ACPI_METHOD_MAX_ARG) { 151 return_ACPI_STATUS(AE_LIMIT); 152 } 153 info->param_count++; 154 } 155 } 156 157 158 ACPI_DUMP_PATHNAME(info->resolved_node, "ACPI: Execute Method", 159 ACPI_LV_INFO, _COMPONENT); 160 161 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 162 "Method at AML address %p Length %X\n", 163 info->obj_desc->method.aml_start + 1, 164 info->obj_desc->method.aml_length - 1)); 165 166 /* 167 * Any namespace deletion must acquire both the namespace and 168 * interpreter locks to ensure that no thread is using the portion of 169 * the namespace that is being deleted. 170 * 171 * Execute the method via the interpreter. The interpreter is locked 172 * here before calling into the AML parser 173 */ 174 acpi_ex_enter_interpreter(); 175 status = acpi_ps_execute_method(info); 176 acpi_ex_exit_interpreter(); 177 } else { 178 /* 179 * 2) Object is not a method, return its current value 180 * 181 * Disallow certain object types. For these, "evaluation" is undefined. 182 */ 183 switch (info->resolved_node->type) { 184 case ACPI_TYPE_DEVICE: 185 case ACPI_TYPE_EVENT: 186 case ACPI_TYPE_MUTEX: 187 case ACPI_TYPE_REGION: 188 case ACPI_TYPE_THERMAL: 189 case ACPI_TYPE_LOCAL_SCOPE: 190 191 ACPI_ERROR((AE_INFO, 192 "[%4.4s] Evaluation of object type [%s] is not supported", 193 info->resolved_node->name.ascii, 194 acpi_ut_get_type_name(info->resolved_node-> 195 type))); 196 197 return_ACPI_STATUS(AE_TYPE); 198 199 default: 200 break; 201 } 202 203 /* 204 * Objects require additional resolution steps (e.g., the Node may be 205 * a field that must be read, etc.) -- we can't just grab the object 206 * out of the node. 207 * 208 * Use resolve_node_to_value() to get the associated value. 209 * 210 * NOTE: we can get away with passing in NULL for a walk state because 211 * resolved_node is guaranteed to not be a reference to either a method 212 * local or a method argument (because this interface is never called 213 * from a running method.) 214 * 215 * Even though we do not directly invoke the interpreter for object 216 * resolution, we must lock it because we could access an opregion. 217 * The opregion access code assumes that the interpreter is locked. 218 */ 219 acpi_ex_enter_interpreter(); 220 221 /* Function has a strange interface */ 222 223 status = 224 acpi_ex_resolve_node_to_value(&info->resolved_node, NULL); 225 acpi_ex_exit_interpreter(); 226 227 /* 228 * If acpi_ex_resolve_node_to_value() succeeded, the return value was placed 229 * in resolved_node. 230 */ 231 if (ACPI_SUCCESS(status)) { 232 status = AE_CTRL_RETURN_VALUE; 233 info->return_object = 234 ACPI_CAST_PTR(union acpi_operand_object, 235 info->resolved_node); 236 237 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 238 "Returning object %p [%s]\n", 239 info->return_object, 240 acpi_ut_get_object_type_name(info-> 241 return_object))); 242 } 243 } 244 245 /* 246 * Check input argument count against the ASL-defined count for a method. 247 * Also check predefined names: argument count and return value against 248 * the ACPI specification. Some incorrect return value types are repaired. 249 */ 250 (void)acpi_ns_check_predefined_names(node, info->param_count, 251 status, &info->return_object); 252 253 /* Check if there is a return value that must be dealt with */ 254 255 if (status == AE_CTRL_RETURN_VALUE) { 256 257 /* If caller does not want the return value, delete it */ 258 259 if (info->flags & ACPI_IGNORE_RETURN_VALUE) { 260 acpi_ut_remove_reference(info->return_object); 261 info->return_object = NULL; 262 } 263 264 /* Map AE_CTRL_RETURN_VALUE to AE_OK, we are done with it */ 265 266 status = AE_OK; 267 } 268 269 ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 270 "*** Completed evaluation of object %s ***\n", 271 info->pathname)); 272 273 /* 274 * Namespace was unlocked by the handling acpi_ns* function, so we 275 * just return 276 */ 277 return_ACPI_STATUS(status); 278 } 279