1*95b482a8SLen Brown /******************************************************************************* 2*95b482a8SLen Brown * 3*95b482a8SLen Brown * Module Name: nsxfeval - Public interfaces to the ACPI subsystem 4*95b482a8SLen Brown * ACPI Object evaluation interfaces 5*95b482a8SLen Brown * 6*95b482a8SLen Brown ******************************************************************************/ 7*95b482a8SLen Brown 8*95b482a8SLen Brown /* 9*95b482a8SLen Brown * Copyright (C) 2000 - 2008, Intel Corp. 10*95b482a8SLen Brown * All rights reserved. 11*95b482a8SLen Brown * 12*95b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 13*95b482a8SLen Brown * modification, are permitted provided that the following conditions 14*95b482a8SLen Brown * are met: 15*95b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 16*95b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 17*95b482a8SLen Brown * without modification. 18*95b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 19*95b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 20*95b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 21*95b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 22*95b482a8SLen Brown * binary redistribution. 23*95b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 24*95b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 25*95b482a8SLen Brown * from this software without specific prior written permission. 26*95b482a8SLen Brown * 27*95b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 28*95b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 29*95b482a8SLen Brown * Software Foundation. 30*95b482a8SLen Brown * 31*95b482a8SLen Brown * NO WARRANTY 32*95b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 33*95b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 34*95b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 35*95b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 36*95b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 37*95b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 38*95b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 39*95b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 40*95b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 41*95b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 42*95b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 43*95b482a8SLen Brown */ 44*95b482a8SLen Brown 45*95b482a8SLen Brown #include <acpi/acpi.h> 46*95b482a8SLen Brown #include <acpi/accommon.h> 47*95b482a8SLen Brown #include <acpi/acnamesp.h> 48*95b482a8SLen Brown #include <acpi/acinterp.h> 49*95b482a8SLen Brown 50*95b482a8SLen Brown #define _COMPONENT ACPI_NAMESPACE 51*95b482a8SLen Brown ACPI_MODULE_NAME("nsxfeval") 52*95b482a8SLen Brown 53*95b482a8SLen Brown /* Local prototypes */ 54*95b482a8SLen Brown static void acpi_ns_resolve_references(struct acpi_evaluate_info *info); 55*95b482a8SLen Brown 56*95b482a8SLen Brown #ifdef ACPI_FUTURE_USAGE 57*95b482a8SLen Brown /******************************************************************************* 58*95b482a8SLen Brown * 59*95b482a8SLen Brown * FUNCTION: acpi_evaluate_object_typed 60*95b482a8SLen Brown * 61*95b482a8SLen Brown * PARAMETERS: Handle - Object handle (optional) 62*95b482a8SLen Brown * Pathname - Object pathname (optional) 63*95b482a8SLen Brown * external_params - List of parameters to pass to method, 64*95b482a8SLen Brown * terminated by NULL. May be NULL 65*95b482a8SLen Brown * if no parameters are being passed. 66*95b482a8SLen Brown * return_buffer - Where to put method's return value (if 67*95b482a8SLen Brown * any). If NULL, no value is returned. 68*95b482a8SLen Brown * return_type - Expected type of return object 69*95b482a8SLen Brown * 70*95b482a8SLen Brown * RETURN: Status 71*95b482a8SLen Brown * 72*95b482a8SLen Brown * DESCRIPTION: Find and evaluate the given object, passing the given 73*95b482a8SLen Brown * parameters if necessary. One of "Handle" or "Pathname" must 74*95b482a8SLen Brown * be valid (non-null) 75*95b482a8SLen Brown * 76*95b482a8SLen Brown ******************************************************************************/ 77*95b482a8SLen Brown 78*95b482a8SLen Brown acpi_status 79*95b482a8SLen Brown acpi_evaluate_object_typed(acpi_handle handle, 80*95b482a8SLen Brown acpi_string pathname, 81*95b482a8SLen Brown struct acpi_object_list *external_params, 82*95b482a8SLen Brown struct acpi_buffer *return_buffer, 83*95b482a8SLen Brown acpi_object_type return_type) 84*95b482a8SLen Brown { 85*95b482a8SLen Brown acpi_status status; 86*95b482a8SLen Brown u8 must_free = FALSE; 87*95b482a8SLen Brown 88*95b482a8SLen Brown ACPI_FUNCTION_TRACE(acpi_evaluate_object_typed); 89*95b482a8SLen Brown 90*95b482a8SLen Brown /* Return buffer must be valid */ 91*95b482a8SLen Brown 92*95b482a8SLen Brown if (!return_buffer) { 93*95b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 94*95b482a8SLen Brown } 95*95b482a8SLen Brown 96*95b482a8SLen Brown if (return_buffer->length == ACPI_ALLOCATE_BUFFER) { 97*95b482a8SLen Brown must_free = TRUE; 98*95b482a8SLen Brown } 99*95b482a8SLen Brown 100*95b482a8SLen Brown /* Evaluate the object */ 101*95b482a8SLen Brown 102*95b482a8SLen Brown status = 103*95b482a8SLen Brown acpi_evaluate_object(handle, pathname, external_params, 104*95b482a8SLen Brown return_buffer); 105*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 106*95b482a8SLen Brown return_ACPI_STATUS(status); 107*95b482a8SLen Brown } 108*95b482a8SLen Brown 109*95b482a8SLen Brown /* Type ANY means "don't care" */ 110*95b482a8SLen Brown 111*95b482a8SLen Brown if (return_type == ACPI_TYPE_ANY) { 112*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 113*95b482a8SLen Brown } 114*95b482a8SLen Brown 115*95b482a8SLen Brown if (return_buffer->length == 0) { 116*95b482a8SLen Brown 117*95b482a8SLen Brown /* Error because caller specifically asked for a return value */ 118*95b482a8SLen Brown 119*95b482a8SLen Brown ACPI_ERROR((AE_INFO, "No return value")); 120*95b482a8SLen Brown return_ACPI_STATUS(AE_NULL_OBJECT); 121*95b482a8SLen Brown } 122*95b482a8SLen Brown 123*95b482a8SLen Brown /* Examine the object type returned from evaluate_object */ 124*95b482a8SLen Brown 125*95b482a8SLen Brown if (((union acpi_object *)return_buffer->pointer)->type == return_type) { 126*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 127*95b482a8SLen Brown } 128*95b482a8SLen Brown 129*95b482a8SLen Brown /* Return object type does not match requested type */ 130*95b482a8SLen Brown 131*95b482a8SLen Brown ACPI_ERROR((AE_INFO, 132*95b482a8SLen Brown "Incorrect return type [%s] requested [%s]", 133*95b482a8SLen Brown acpi_ut_get_type_name(((union acpi_object *)return_buffer-> 134*95b482a8SLen Brown pointer)->type), 135*95b482a8SLen Brown acpi_ut_get_type_name(return_type))); 136*95b482a8SLen Brown 137*95b482a8SLen Brown if (must_free) { 138*95b482a8SLen Brown 139*95b482a8SLen Brown /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ 140*95b482a8SLen Brown 141*95b482a8SLen Brown ACPI_FREE(return_buffer->pointer); 142*95b482a8SLen Brown return_buffer->pointer = NULL; 143*95b482a8SLen Brown } 144*95b482a8SLen Brown 145*95b482a8SLen Brown return_buffer->length = 0; 146*95b482a8SLen Brown return_ACPI_STATUS(AE_TYPE); 147*95b482a8SLen Brown } 148*95b482a8SLen Brown 149*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_evaluate_object_typed) 150*95b482a8SLen Brown #endif /* ACPI_FUTURE_USAGE */ 151*95b482a8SLen Brown /******************************************************************************* 152*95b482a8SLen Brown * 153*95b482a8SLen Brown * FUNCTION: acpi_evaluate_object 154*95b482a8SLen Brown * 155*95b482a8SLen Brown * PARAMETERS: Handle - Object handle (optional) 156*95b482a8SLen Brown * Pathname - Object pathname (optional) 157*95b482a8SLen Brown * external_params - List of parameters to pass to method, 158*95b482a8SLen Brown * terminated by NULL. May be NULL 159*95b482a8SLen Brown * if no parameters are being passed. 160*95b482a8SLen Brown * return_buffer - Where to put method's return value (if 161*95b482a8SLen Brown * any). If NULL, no value is returned. 162*95b482a8SLen Brown * 163*95b482a8SLen Brown * RETURN: Status 164*95b482a8SLen Brown * 165*95b482a8SLen Brown * DESCRIPTION: Find and evaluate the given object, passing the given 166*95b482a8SLen Brown * parameters if necessary. One of "Handle" or "Pathname" must 167*95b482a8SLen Brown * be valid (non-null) 168*95b482a8SLen Brown * 169*95b482a8SLen Brown ******************************************************************************/ 170*95b482a8SLen Brown acpi_status 171*95b482a8SLen Brown acpi_evaluate_object(acpi_handle handle, 172*95b482a8SLen Brown acpi_string pathname, 173*95b482a8SLen Brown struct acpi_object_list *external_params, 174*95b482a8SLen Brown struct acpi_buffer *return_buffer) 175*95b482a8SLen Brown { 176*95b482a8SLen Brown acpi_status status; 177*95b482a8SLen Brown struct acpi_evaluate_info *info; 178*95b482a8SLen Brown acpi_size buffer_space_needed; 179*95b482a8SLen Brown u32 i; 180*95b482a8SLen Brown 181*95b482a8SLen Brown ACPI_FUNCTION_TRACE(acpi_evaluate_object); 182*95b482a8SLen Brown 183*95b482a8SLen Brown /* Allocate and initialize the evaluation information block */ 184*95b482a8SLen Brown 185*95b482a8SLen Brown info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); 186*95b482a8SLen Brown if (!info) { 187*95b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 188*95b482a8SLen Brown } 189*95b482a8SLen Brown 190*95b482a8SLen Brown info->pathname = pathname; 191*95b482a8SLen Brown 192*95b482a8SLen Brown /* Convert and validate the device handle */ 193*95b482a8SLen Brown 194*95b482a8SLen Brown info->prefix_node = acpi_ns_map_handle_to_node(handle); 195*95b482a8SLen Brown if (!info->prefix_node) { 196*95b482a8SLen Brown status = AE_BAD_PARAMETER; 197*95b482a8SLen Brown goto cleanup; 198*95b482a8SLen Brown } 199*95b482a8SLen Brown 200*95b482a8SLen Brown /* 201*95b482a8SLen Brown * If there are parameters to be passed to a control method, the external 202*95b482a8SLen Brown * objects must all be converted to internal objects 203*95b482a8SLen Brown */ 204*95b482a8SLen Brown if (external_params && external_params->count) { 205*95b482a8SLen Brown /* 206*95b482a8SLen Brown * Allocate a new parameter block for the internal objects 207*95b482a8SLen Brown * Add 1 to count to allow for null terminated internal list 208*95b482a8SLen Brown */ 209*95b482a8SLen Brown info->parameters = ACPI_ALLOCATE_ZEROED(((acpi_size) 210*95b482a8SLen Brown external_params-> 211*95b482a8SLen Brown count + 212*95b482a8SLen Brown 1) * sizeof(void *)); 213*95b482a8SLen Brown if (!info->parameters) { 214*95b482a8SLen Brown status = AE_NO_MEMORY; 215*95b482a8SLen Brown goto cleanup; 216*95b482a8SLen Brown } 217*95b482a8SLen Brown 218*95b482a8SLen Brown /* Convert each external object in the list to an internal object */ 219*95b482a8SLen Brown 220*95b482a8SLen Brown for (i = 0; i < external_params->count; i++) { 221*95b482a8SLen Brown status = 222*95b482a8SLen Brown acpi_ut_copy_eobject_to_iobject(&external_params-> 223*95b482a8SLen Brown pointer[i], 224*95b482a8SLen Brown &info-> 225*95b482a8SLen Brown parameters[i]); 226*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 227*95b482a8SLen Brown goto cleanup; 228*95b482a8SLen Brown } 229*95b482a8SLen Brown } 230*95b482a8SLen Brown info->parameters[external_params->count] = NULL; 231*95b482a8SLen Brown } 232*95b482a8SLen Brown 233*95b482a8SLen Brown /* 234*95b482a8SLen Brown * Three major cases: 235*95b482a8SLen Brown * 1) Fully qualified pathname 236*95b482a8SLen Brown * 2) No handle, not fully qualified pathname (error) 237*95b482a8SLen Brown * 3) Valid handle 238*95b482a8SLen Brown */ 239*95b482a8SLen Brown if ((pathname) && (acpi_ns_valid_root_prefix(pathname[0]))) { 240*95b482a8SLen Brown 241*95b482a8SLen Brown /* The path is fully qualified, just evaluate by name */ 242*95b482a8SLen Brown 243*95b482a8SLen Brown info->prefix_node = NULL; 244*95b482a8SLen Brown status = acpi_ns_evaluate(info); 245*95b482a8SLen Brown } else if (!handle) { 246*95b482a8SLen Brown /* 247*95b482a8SLen Brown * A handle is optional iff a fully qualified pathname is specified. 248*95b482a8SLen Brown * Since we've already handled fully qualified names above, this is 249*95b482a8SLen Brown * an error 250*95b482a8SLen Brown */ 251*95b482a8SLen Brown if (!pathname) { 252*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 253*95b482a8SLen Brown "Both Handle and Pathname are NULL")); 254*95b482a8SLen Brown } else { 255*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 256*95b482a8SLen Brown "Null Handle with relative pathname [%s]", 257*95b482a8SLen Brown pathname)); 258*95b482a8SLen Brown } 259*95b482a8SLen Brown 260*95b482a8SLen Brown status = AE_BAD_PARAMETER; 261*95b482a8SLen Brown } else { 262*95b482a8SLen Brown /* We have a namespace a node and a possible relative path */ 263*95b482a8SLen Brown 264*95b482a8SLen Brown status = acpi_ns_evaluate(info); 265*95b482a8SLen Brown } 266*95b482a8SLen Brown 267*95b482a8SLen Brown /* 268*95b482a8SLen Brown * If we are expecting a return value, and all went well above, 269*95b482a8SLen Brown * copy the return value to an external object. 270*95b482a8SLen Brown */ 271*95b482a8SLen Brown if (return_buffer) { 272*95b482a8SLen Brown if (!info->return_object) { 273*95b482a8SLen Brown return_buffer->length = 0; 274*95b482a8SLen Brown } else { 275*95b482a8SLen Brown if (ACPI_GET_DESCRIPTOR_TYPE(info->return_object) == 276*95b482a8SLen Brown ACPI_DESC_TYPE_NAMED) { 277*95b482a8SLen Brown /* 278*95b482a8SLen Brown * If we received a NS Node as a return object, this means that 279*95b482a8SLen Brown * the object we are evaluating has nothing interesting to 280*95b482a8SLen Brown * return (such as a mutex, etc.) We return an error because 281*95b482a8SLen Brown * these types are essentially unsupported by this interface. 282*95b482a8SLen Brown * We don't check up front because this makes it easier to add 283*95b482a8SLen Brown * support for various types at a later date if necessary. 284*95b482a8SLen Brown */ 285*95b482a8SLen Brown status = AE_TYPE; 286*95b482a8SLen Brown info->return_object = NULL; /* No need to delete a NS Node */ 287*95b482a8SLen Brown return_buffer->length = 0; 288*95b482a8SLen Brown } 289*95b482a8SLen Brown 290*95b482a8SLen Brown if (ACPI_SUCCESS(status)) { 291*95b482a8SLen Brown 292*95b482a8SLen Brown /* Dereference Index and ref_of references */ 293*95b482a8SLen Brown 294*95b482a8SLen Brown acpi_ns_resolve_references(info); 295*95b482a8SLen Brown 296*95b482a8SLen Brown /* Get the size of the returned object */ 297*95b482a8SLen Brown 298*95b482a8SLen Brown status = 299*95b482a8SLen Brown acpi_ut_get_object_size(info->return_object, 300*95b482a8SLen Brown &buffer_space_needed); 301*95b482a8SLen Brown if (ACPI_SUCCESS(status)) { 302*95b482a8SLen Brown 303*95b482a8SLen Brown /* Validate/Allocate/Clear caller buffer */ 304*95b482a8SLen Brown 305*95b482a8SLen Brown status = 306*95b482a8SLen Brown acpi_ut_initialize_buffer 307*95b482a8SLen Brown (return_buffer, 308*95b482a8SLen Brown buffer_space_needed); 309*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 310*95b482a8SLen Brown /* 311*95b482a8SLen Brown * Caller's buffer is too small or a new one can't 312*95b482a8SLen Brown * be allocated 313*95b482a8SLen Brown */ 314*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_INFO, 315*95b482a8SLen Brown "Needed buffer size %X, %s\n", 316*95b482a8SLen Brown (u32) 317*95b482a8SLen Brown buffer_space_needed, 318*95b482a8SLen Brown acpi_format_exception 319*95b482a8SLen Brown (status))); 320*95b482a8SLen Brown } else { 321*95b482a8SLen Brown /* We have enough space for the object, build it */ 322*95b482a8SLen Brown 323*95b482a8SLen Brown status = 324*95b482a8SLen Brown acpi_ut_copy_iobject_to_eobject 325*95b482a8SLen Brown (info->return_object, 326*95b482a8SLen Brown return_buffer); 327*95b482a8SLen Brown } 328*95b482a8SLen Brown } 329*95b482a8SLen Brown } 330*95b482a8SLen Brown } 331*95b482a8SLen Brown } 332*95b482a8SLen Brown 333*95b482a8SLen Brown if (info->return_object) { 334*95b482a8SLen Brown /* 335*95b482a8SLen Brown * Delete the internal return object. NOTE: Interpreter must be 336*95b482a8SLen Brown * locked to avoid race condition. 337*95b482a8SLen Brown */ 338*95b482a8SLen Brown acpi_ex_enter_interpreter(); 339*95b482a8SLen Brown 340*95b482a8SLen Brown /* Remove one reference on the return object (should delete it) */ 341*95b482a8SLen Brown 342*95b482a8SLen Brown acpi_ut_remove_reference(info->return_object); 343*95b482a8SLen Brown acpi_ex_exit_interpreter(); 344*95b482a8SLen Brown } 345*95b482a8SLen Brown 346*95b482a8SLen Brown cleanup: 347*95b482a8SLen Brown 348*95b482a8SLen Brown /* Free the input parameter list (if we created one) */ 349*95b482a8SLen Brown 350*95b482a8SLen Brown if (info->parameters) { 351*95b482a8SLen Brown 352*95b482a8SLen Brown /* Free the allocated parameter block */ 353*95b482a8SLen Brown 354*95b482a8SLen Brown acpi_ut_delete_internal_object_list(info->parameters); 355*95b482a8SLen Brown } 356*95b482a8SLen Brown 357*95b482a8SLen Brown ACPI_FREE(info); 358*95b482a8SLen Brown return_ACPI_STATUS(status); 359*95b482a8SLen Brown } 360*95b482a8SLen Brown 361*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_evaluate_object) 362*95b482a8SLen Brown 363*95b482a8SLen Brown /******************************************************************************* 364*95b482a8SLen Brown * 365*95b482a8SLen Brown * FUNCTION: acpi_ns_resolve_references 366*95b482a8SLen Brown * 367*95b482a8SLen Brown * PARAMETERS: Info - Evaluation info block 368*95b482a8SLen Brown * 369*95b482a8SLen Brown * RETURN: Info->return_object is replaced with the dereferenced object 370*95b482a8SLen Brown * 371*95b482a8SLen Brown * DESCRIPTION: Dereference certain reference objects. Called before an 372*95b482a8SLen Brown * internal return object is converted to an external union acpi_object. 373*95b482a8SLen Brown * 374*95b482a8SLen Brown * Performs an automatic dereference of Index and ref_of reference objects. 375*95b482a8SLen Brown * These reference objects are not supported by the union acpi_object, so this is a 376*95b482a8SLen Brown * last resort effort to return something useful. Also, provides compatibility 377*95b482a8SLen Brown * with other ACPI implementations. 378*95b482a8SLen Brown * 379*95b482a8SLen Brown * NOTE: does not handle references within returned package objects or nested 380*95b482a8SLen Brown * references, but this support could be added later if found to be necessary. 381*95b482a8SLen Brown * 382*95b482a8SLen Brown ******************************************************************************/ 383*95b482a8SLen Brown static void acpi_ns_resolve_references(struct acpi_evaluate_info *info) 384*95b482a8SLen Brown { 385*95b482a8SLen Brown union acpi_operand_object *obj_desc = NULL; 386*95b482a8SLen Brown struct acpi_namespace_node *node; 387*95b482a8SLen Brown 388*95b482a8SLen Brown /* We are interested in reference objects only */ 389*95b482a8SLen Brown 390*95b482a8SLen Brown if (ACPI_GET_OBJECT_TYPE(info->return_object) != 391*95b482a8SLen Brown ACPI_TYPE_LOCAL_REFERENCE) { 392*95b482a8SLen Brown return; 393*95b482a8SLen Brown } 394*95b482a8SLen Brown 395*95b482a8SLen Brown /* 396*95b482a8SLen Brown * Two types of references are supported - those created by Index and 397*95b482a8SLen Brown * ref_of operators. A name reference (AML_NAMEPATH_OP) can be converted 398*95b482a8SLen Brown * to an union acpi_object, so it is not dereferenced here. A ddb_handle 399*95b482a8SLen Brown * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to 400*95b482a8SLen Brown * an union acpi_object. 401*95b482a8SLen Brown */ 402*95b482a8SLen Brown switch (info->return_object->reference.class) { 403*95b482a8SLen Brown case ACPI_REFCLASS_INDEX: 404*95b482a8SLen Brown 405*95b482a8SLen Brown obj_desc = *(info->return_object->reference.where); 406*95b482a8SLen Brown break; 407*95b482a8SLen Brown 408*95b482a8SLen Brown case ACPI_REFCLASS_REFOF: 409*95b482a8SLen Brown 410*95b482a8SLen Brown node = info->return_object->reference.object; 411*95b482a8SLen Brown if (node) { 412*95b482a8SLen Brown obj_desc = node->object; 413*95b482a8SLen Brown } 414*95b482a8SLen Brown break; 415*95b482a8SLen Brown 416*95b482a8SLen Brown default: 417*95b482a8SLen Brown return; 418*95b482a8SLen Brown } 419*95b482a8SLen Brown 420*95b482a8SLen Brown /* Replace the existing reference object */ 421*95b482a8SLen Brown 422*95b482a8SLen Brown if (obj_desc) { 423*95b482a8SLen Brown acpi_ut_add_reference(obj_desc); 424*95b482a8SLen Brown acpi_ut_remove_reference(info->return_object); 425*95b482a8SLen Brown info->return_object = obj_desc; 426*95b482a8SLen Brown } 427*95b482a8SLen Brown 428*95b482a8SLen Brown return; 429*95b482a8SLen Brown } 430*95b482a8SLen Brown 431*95b482a8SLen Brown /******************************************************************************* 432*95b482a8SLen Brown * 433*95b482a8SLen Brown * FUNCTION: acpi_walk_namespace 434*95b482a8SLen Brown * 435*95b482a8SLen Brown * PARAMETERS: Type - acpi_object_type to search for 436*95b482a8SLen Brown * start_object - Handle in namespace where search begins 437*95b482a8SLen Brown * max_depth - Depth to which search is to reach 438*95b482a8SLen Brown * user_function - Called when an object of "Type" is found 439*95b482a8SLen Brown * Context - Passed to user function 440*95b482a8SLen Brown * return_value - Location where return value of 441*95b482a8SLen Brown * user_function is put if terminated early 442*95b482a8SLen Brown * 443*95b482a8SLen Brown * RETURNS Return value from the user_function if terminated early. 444*95b482a8SLen Brown * Otherwise, returns NULL. 445*95b482a8SLen Brown * 446*95b482a8SLen Brown * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 447*95b482a8SLen Brown * starting (and ending) at the object specified by start_handle. 448*95b482a8SLen Brown * The user_function is called whenever an object that matches 449*95b482a8SLen Brown * the type parameter is found. If the user function returns 450*95b482a8SLen Brown * a non-zero value, the search is terminated immediately and this 451*95b482a8SLen Brown * value is returned to the caller. 452*95b482a8SLen Brown * 453*95b482a8SLen Brown * The point of this procedure is to provide a generic namespace 454*95b482a8SLen Brown * walk routine that can be called from multiple places to 455*95b482a8SLen Brown * provide multiple services; the User Function can be tailored 456*95b482a8SLen Brown * to each task, whether it is a print function, a compare 457*95b482a8SLen Brown * function, etc. 458*95b482a8SLen Brown * 459*95b482a8SLen Brown ******************************************************************************/ 460*95b482a8SLen Brown 461*95b482a8SLen Brown acpi_status 462*95b482a8SLen Brown acpi_walk_namespace(acpi_object_type type, 463*95b482a8SLen Brown acpi_handle start_object, 464*95b482a8SLen Brown u32 max_depth, 465*95b482a8SLen Brown acpi_walk_callback user_function, 466*95b482a8SLen Brown void *context, void **return_value) 467*95b482a8SLen Brown { 468*95b482a8SLen Brown acpi_status status; 469*95b482a8SLen Brown 470*95b482a8SLen Brown ACPI_FUNCTION_TRACE(acpi_walk_namespace); 471*95b482a8SLen Brown 472*95b482a8SLen Brown /* Parameter validation */ 473*95b482a8SLen Brown 474*95b482a8SLen Brown if ((type > ACPI_TYPE_LOCAL_MAX) || (!max_depth) || (!user_function)) { 475*95b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 476*95b482a8SLen Brown } 477*95b482a8SLen Brown 478*95b482a8SLen Brown /* 479*95b482a8SLen Brown * Lock the namespace around the walk. 480*95b482a8SLen Brown * The namespace will be unlocked/locked around each call 481*95b482a8SLen Brown * to the user function - since this function 482*95b482a8SLen Brown * must be allowed to make Acpi calls itself. 483*95b482a8SLen Brown */ 484*95b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 485*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 486*95b482a8SLen Brown return_ACPI_STATUS(status); 487*95b482a8SLen Brown } 488*95b482a8SLen Brown 489*95b482a8SLen Brown status = acpi_ns_walk_namespace(type, start_object, max_depth, 490*95b482a8SLen Brown ACPI_NS_WALK_UNLOCK, 491*95b482a8SLen Brown user_function, context, return_value); 492*95b482a8SLen Brown 493*95b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 494*95b482a8SLen Brown return_ACPI_STATUS(status); 495*95b482a8SLen Brown } 496*95b482a8SLen Brown 497*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_walk_namespace) 498*95b482a8SLen Brown 499*95b482a8SLen Brown /******************************************************************************* 500*95b482a8SLen Brown * 501*95b482a8SLen Brown * FUNCTION: acpi_ns_get_device_callback 502*95b482a8SLen Brown * 503*95b482a8SLen Brown * PARAMETERS: Callback from acpi_get_device 504*95b482a8SLen Brown * 505*95b482a8SLen Brown * RETURN: Status 506*95b482a8SLen Brown * 507*95b482a8SLen Brown * DESCRIPTION: Takes callbacks from walk_namespace and filters out all non- 508*95b482a8SLen Brown * present devices, or if they specified a HID, it filters based 509*95b482a8SLen Brown * on that. 510*95b482a8SLen Brown * 511*95b482a8SLen Brown ******************************************************************************/ 512*95b482a8SLen Brown static acpi_status 513*95b482a8SLen Brown acpi_ns_get_device_callback(acpi_handle obj_handle, 514*95b482a8SLen Brown u32 nesting_level, 515*95b482a8SLen Brown void *context, void **return_value) 516*95b482a8SLen Brown { 517*95b482a8SLen Brown struct acpi_get_devices_info *info = context; 518*95b482a8SLen Brown acpi_status status; 519*95b482a8SLen Brown struct acpi_namespace_node *node; 520*95b482a8SLen Brown u32 flags; 521*95b482a8SLen Brown struct acpica_device_id hid; 522*95b482a8SLen Brown struct acpi_compatible_id_list *cid; 523*95b482a8SLen Brown u32 i; 524*95b482a8SLen Brown int found; 525*95b482a8SLen Brown 526*95b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 527*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 528*95b482a8SLen Brown return (status); 529*95b482a8SLen Brown } 530*95b482a8SLen Brown 531*95b482a8SLen Brown node = acpi_ns_map_handle_to_node(obj_handle); 532*95b482a8SLen Brown status = acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 533*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 534*95b482a8SLen Brown return (status); 535*95b482a8SLen Brown } 536*95b482a8SLen Brown 537*95b482a8SLen Brown if (!node) { 538*95b482a8SLen Brown return (AE_BAD_PARAMETER); 539*95b482a8SLen Brown } 540*95b482a8SLen Brown 541*95b482a8SLen Brown /* Run _STA to determine if device is present */ 542*95b482a8SLen Brown 543*95b482a8SLen Brown status = acpi_ut_execute_STA(node, &flags); 544*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 545*95b482a8SLen Brown return (AE_CTRL_DEPTH); 546*95b482a8SLen Brown } 547*95b482a8SLen Brown 548*95b482a8SLen Brown if (!(flags & ACPI_STA_DEVICE_PRESENT) && 549*95b482a8SLen Brown !(flags & ACPI_STA_DEVICE_FUNCTIONING)) { 550*95b482a8SLen Brown /* 551*95b482a8SLen Brown * Don't examine the children of the device only when the 552*95b482a8SLen Brown * device is neither present nor functional. See ACPI spec, 553*95b482a8SLen Brown * description of _STA for more information. 554*95b482a8SLen Brown */ 555*95b482a8SLen Brown return (AE_CTRL_DEPTH); 556*95b482a8SLen Brown } 557*95b482a8SLen Brown 558*95b482a8SLen Brown /* Filter based on device HID & CID */ 559*95b482a8SLen Brown 560*95b482a8SLen Brown if (info->hid != NULL) { 561*95b482a8SLen Brown status = acpi_ut_execute_HID(node, &hid); 562*95b482a8SLen Brown if (status == AE_NOT_FOUND) { 563*95b482a8SLen Brown return (AE_OK); 564*95b482a8SLen Brown } else if (ACPI_FAILURE(status)) { 565*95b482a8SLen Brown return (AE_CTRL_DEPTH); 566*95b482a8SLen Brown } 567*95b482a8SLen Brown 568*95b482a8SLen Brown if (ACPI_STRNCMP(hid.value, info->hid, sizeof(hid.value)) != 0) { 569*95b482a8SLen Brown 570*95b482a8SLen Brown /* Get the list of Compatible IDs */ 571*95b482a8SLen Brown 572*95b482a8SLen Brown status = acpi_ut_execute_CID(node, &cid); 573*95b482a8SLen Brown if (status == AE_NOT_FOUND) { 574*95b482a8SLen Brown return (AE_OK); 575*95b482a8SLen Brown } else if (ACPI_FAILURE(status)) { 576*95b482a8SLen Brown return (AE_CTRL_DEPTH); 577*95b482a8SLen Brown } 578*95b482a8SLen Brown 579*95b482a8SLen Brown /* Walk the CID list */ 580*95b482a8SLen Brown 581*95b482a8SLen Brown found = 0; 582*95b482a8SLen Brown for (i = 0; i < cid->count; i++) { 583*95b482a8SLen Brown if (ACPI_STRNCMP(cid->id[i].value, info->hid, 584*95b482a8SLen Brown sizeof(struct 585*95b482a8SLen Brown acpi_compatible_id)) == 586*95b482a8SLen Brown 0) { 587*95b482a8SLen Brown found = 1; 588*95b482a8SLen Brown break; 589*95b482a8SLen Brown } 590*95b482a8SLen Brown } 591*95b482a8SLen Brown ACPI_FREE(cid); 592*95b482a8SLen Brown if (!found) 593*95b482a8SLen Brown return (AE_OK); 594*95b482a8SLen Brown } 595*95b482a8SLen Brown } 596*95b482a8SLen Brown 597*95b482a8SLen Brown status = info->user_function(obj_handle, nesting_level, info->context, 598*95b482a8SLen Brown return_value); 599*95b482a8SLen Brown return (status); 600*95b482a8SLen Brown } 601*95b482a8SLen Brown 602*95b482a8SLen Brown /******************************************************************************* 603*95b482a8SLen Brown * 604*95b482a8SLen Brown * FUNCTION: acpi_get_devices 605*95b482a8SLen Brown * 606*95b482a8SLen Brown * PARAMETERS: HID - HID to search for. Can be NULL. 607*95b482a8SLen Brown * user_function - Called when a matching object is found 608*95b482a8SLen Brown * Context - Passed to user function 609*95b482a8SLen Brown * return_value - Location where return value of 610*95b482a8SLen Brown * user_function is put if terminated early 611*95b482a8SLen Brown * 612*95b482a8SLen Brown * RETURNS Return value from the user_function if terminated early. 613*95b482a8SLen Brown * Otherwise, returns NULL. 614*95b482a8SLen Brown * 615*95b482a8SLen Brown * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 616*95b482a8SLen Brown * starting (and ending) at the object specified by start_handle. 617*95b482a8SLen Brown * The user_function is called whenever an object of type 618*95b482a8SLen Brown * Device is found. If the user function returns 619*95b482a8SLen Brown * a non-zero value, the search is terminated immediately and this 620*95b482a8SLen Brown * value is returned to the caller. 621*95b482a8SLen Brown * 622*95b482a8SLen Brown * This is a wrapper for walk_namespace, but the callback performs 623*95b482a8SLen Brown * additional filtering. Please see acpi_ns_get_device_callback. 624*95b482a8SLen Brown * 625*95b482a8SLen Brown ******************************************************************************/ 626*95b482a8SLen Brown 627*95b482a8SLen Brown acpi_status 628*95b482a8SLen Brown acpi_get_devices(const char *HID, 629*95b482a8SLen Brown acpi_walk_callback user_function, 630*95b482a8SLen Brown void *context, void **return_value) 631*95b482a8SLen Brown { 632*95b482a8SLen Brown acpi_status status; 633*95b482a8SLen Brown struct acpi_get_devices_info info; 634*95b482a8SLen Brown 635*95b482a8SLen Brown ACPI_FUNCTION_TRACE(acpi_get_devices); 636*95b482a8SLen Brown 637*95b482a8SLen Brown /* Parameter validation */ 638*95b482a8SLen Brown 639*95b482a8SLen Brown if (!user_function) { 640*95b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 641*95b482a8SLen Brown } 642*95b482a8SLen Brown 643*95b482a8SLen Brown /* 644*95b482a8SLen Brown * We're going to call their callback from OUR callback, so we need 645*95b482a8SLen Brown * to know what it is, and their context parameter. 646*95b482a8SLen Brown */ 647*95b482a8SLen Brown info.hid = HID; 648*95b482a8SLen Brown info.context = context; 649*95b482a8SLen Brown info.user_function = user_function; 650*95b482a8SLen Brown 651*95b482a8SLen Brown /* 652*95b482a8SLen Brown * Lock the namespace around the walk. 653*95b482a8SLen Brown * The namespace will be unlocked/locked around each call 654*95b482a8SLen Brown * to the user function - since this function 655*95b482a8SLen Brown * must be allowed to make Acpi calls itself. 656*95b482a8SLen Brown */ 657*95b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 658*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 659*95b482a8SLen Brown return_ACPI_STATUS(status); 660*95b482a8SLen Brown } 661*95b482a8SLen Brown 662*95b482a8SLen Brown status = acpi_ns_walk_namespace(ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 663*95b482a8SLen Brown ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, 664*95b482a8SLen Brown acpi_ns_get_device_callback, &info, 665*95b482a8SLen Brown return_value); 666*95b482a8SLen Brown 667*95b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 668*95b482a8SLen Brown return_ACPI_STATUS(status); 669*95b482a8SLen Brown } 670*95b482a8SLen Brown 671*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_devices) 672*95b482a8SLen Brown 673*95b482a8SLen Brown /******************************************************************************* 674*95b482a8SLen Brown * 675*95b482a8SLen Brown * FUNCTION: acpi_attach_data 676*95b482a8SLen Brown * 677*95b482a8SLen Brown * PARAMETERS: obj_handle - Namespace node 678*95b482a8SLen Brown * Handler - Handler for this attachment 679*95b482a8SLen Brown * Data - Pointer to data to be attached 680*95b482a8SLen Brown * 681*95b482a8SLen Brown * RETURN: Status 682*95b482a8SLen Brown * 683*95b482a8SLen Brown * DESCRIPTION: Attach arbitrary data and handler to a namespace node. 684*95b482a8SLen Brown * 685*95b482a8SLen Brown ******************************************************************************/ 686*95b482a8SLen Brown acpi_status 687*95b482a8SLen Brown acpi_attach_data(acpi_handle obj_handle, 688*95b482a8SLen Brown acpi_object_handler handler, void *data) 689*95b482a8SLen Brown { 690*95b482a8SLen Brown struct acpi_namespace_node *node; 691*95b482a8SLen Brown acpi_status status; 692*95b482a8SLen Brown 693*95b482a8SLen Brown /* Parameter validation */ 694*95b482a8SLen Brown 695*95b482a8SLen Brown if (!obj_handle || !handler || !data) { 696*95b482a8SLen Brown return (AE_BAD_PARAMETER); 697*95b482a8SLen Brown } 698*95b482a8SLen Brown 699*95b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 700*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 701*95b482a8SLen Brown return (status); 702*95b482a8SLen Brown } 703*95b482a8SLen Brown 704*95b482a8SLen Brown /* Convert and validate the handle */ 705*95b482a8SLen Brown 706*95b482a8SLen Brown node = acpi_ns_map_handle_to_node(obj_handle); 707*95b482a8SLen Brown if (!node) { 708*95b482a8SLen Brown status = AE_BAD_PARAMETER; 709*95b482a8SLen Brown goto unlock_and_exit; 710*95b482a8SLen Brown } 711*95b482a8SLen Brown 712*95b482a8SLen Brown status = acpi_ns_attach_data(node, handler, data); 713*95b482a8SLen Brown 714*95b482a8SLen Brown unlock_and_exit: 715*95b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 716*95b482a8SLen Brown return (status); 717*95b482a8SLen Brown } 718*95b482a8SLen Brown 719*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_attach_data) 720*95b482a8SLen Brown 721*95b482a8SLen Brown /******************************************************************************* 722*95b482a8SLen Brown * 723*95b482a8SLen Brown * FUNCTION: acpi_detach_data 724*95b482a8SLen Brown * 725*95b482a8SLen Brown * PARAMETERS: obj_handle - Namespace node handle 726*95b482a8SLen Brown * Handler - Handler used in call to acpi_attach_data 727*95b482a8SLen Brown * 728*95b482a8SLen Brown * RETURN: Status 729*95b482a8SLen Brown * 730*95b482a8SLen Brown * DESCRIPTION: Remove data that was previously attached to a node. 731*95b482a8SLen Brown * 732*95b482a8SLen Brown ******************************************************************************/ 733*95b482a8SLen Brown acpi_status 734*95b482a8SLen Brown acpi_detach_data(acpi_handle obj_handle, acpi_object_handler handler) 735*95b482a8SLen Brown { 736*95b482a8SLen Brown struct acpi_namespace_node *node; 737*95b482a8SLen Brown acpi_status status; 738*95b482a8SLen Brown 739*95b482a8SLen Brown /* Parameter validation */ 740*95b482a8SLen Brown 741*95b482a8SLen Brown if (!obj_handle || !handler) { 742*95b482a8SLen Brown return (AE_BAD_PARAMETER); 743*95b482a8SLen Brown } 744*95b482a8SLen Brown 745*95b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 746*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 747*95b482a8SLen Brown return (status); 748*95b482a8SLen Brown } 749*95b482a8SLen Brown 750*95b482a8SLen Brown /* Convert and validate the handle */ 751*95b482a8SLen Brown 752*95b482a8SLen Brown node = acpi_ns_map_handle_to_node(obj_handle); 753*95b482a8SLen Brown if (!node) { 754*95b482a8SLen Brown status = AE_BAD_PARAMETER; 755*95b482a8SLen Brown goto unlock_and_exit; 756*95b482a8SLen Brown } 757*95b482a8SLen Brown 758*95b482a8SLen Brown status = acpi_ns_detach_data(node, handler); 759*95b482a8SLen Brown 760*95b482a8SLen Brown unlock_and_exit: 761*95b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 762*95b482a8SLen Brown return (status); 763*95b482a8SLen Brown } 764*95b482a8SLen Brown 765*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_detach_data) 766*95b482a8SLen Brown 767*95b482a8SLen Brown /******************************************************************************* 768*95b482a8SLen Brown * 769*95b482a8SLen Brown * FUNCTION: acpi_get_data 770*95b482a8SLen Brown * 771*95b482a8SLen Brown * PARAMETERS: obj_handle - Namespace node 772*95b482a8SLen Brown * Handler - Handler used in call to attach_data 773*95b482a8SLen Brown * Data - Where the data is returned 774*95b482a8SLen Brown * 775*95b482a8SLen Brown * RETURN: Status 776*95b482a8SLen Brown * 777*95b482a8SLen Brown * DESCRIPTION: Retrieve data that was previously attached to a namespace node. 778*95b482a8SLen Brown * 779*95b482a8SLen Brown ******************************************************************************/ 780*95b482a8SLen Brown acpi_status 781*95b482a8SLen Brown acpi_get_data(acpi_handle obj_handle, acpi_object_handler handler, void **data) 782*95b482a8SLen Brown { 783*95b482a8SLen Brown struct acpi_namespace_node *node; 784*95b482a8SLen Brown acpi_status status; 785*95b482a8SLen Brown 786*95b482a8SLen Brown /* Parameter validation */ 787*95b482a8SLen Brown 788*95b482a8SLen Brown if (!obj_handle || !handler || !data) { 789*95b482a8SLen Brown return (AE_BAD_PARAMETER); 790*95b482a8SLen Brown } 791*95b482a8SLen Brown 792*95b482a8SLen Brown status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 793*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 794*95b482a8SLen Brown return (status); 795*95b482a8SLen Brown } 796*95b482a8SLen Brown 797*95b482a8SLen Brown /* Convert and validate the handle */ 798*95b482a8SLen Brown 799*95b482a8SLen Brown node = acpi_ns_map_handle_to_node(obj_handle); 800*95b482a8SLen Brown if (!node) { 801*95b482a8SLen Brown status = AE_BAD_PARAMETER; 802*95b482a8SLen Brown goto unlock_and_exit; 803*95b482a8SLen Brown } 804*95b482a8SLen Brown 805*95b482a8SLen Brown status = acpi_ns_get_attached_data(node, handler, data); 806*95b482a8SLen Brown 807*95b482a8SLen Brown unlock_and_exit: 808*95b482a8SLen Brown (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 809*95b482a8SLen Brown return (status); 810*95b482a8SLen Brown } 811*95b482a8SLen Brown 812*95b482a8SLen Brown ACPI_EXPORT_SYMBOL(acpi_get_data) 813