nsxfeval.c revision 193341
138363Swpaul/******************************************************************************* 238363Swpaul * 338363Swpaul * Module Name: nsxfeval - Public interfaces to the ACPI subsystem 438363Swpaul * ACPI Object evaluation interfaces 538363Swpaul * 638363Swpaul ******************************************************************************/ 738363Swpaul 838363Swpaul/****************************************************************************** 938363Swpaul * 1038363Swpaul * 1. Copyright Notice 1138363Swpaul * 1238363Swpaul * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 1338363Swpaul * All rights reserved. 1438363Swpaul * 1538363Swpaul * 2. License 1638363Swpaul * 1738363Swpaul * 2.1. This is your license from Intel Corp. under its intellectual property 1838363Swpaul * rights. You may have additional license terms from the party that provided 1938363Swpaul * you this software, covering your right to use that party's intellectual 2038363Swpaul * property rights. 2138363Swpaul * 2238363Swpaul * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 2338363Swpaul * copy of the source code appearing in this file ("Covered Code") an 2438363Swpaul * irrevocable, perpetual, worldwide license under Intel's copyrights in the 2538363Swpaul * base code distributed originally by Intel ("Original Intel Code") to copy, 2638363Swpaul * make derivatives, distribute, use and display any portion of the Covered 2738363Swpaul * Code in any form, with the right to sublicense such rights; and 2838363Swpaul * 2938363Swpaul * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 3038363Swpaul * license (with the right to sublicense), under only those claims of Intel 3138363Swpaul * patents that are infringed by the Original Intel Code, to make, use, sell, 3238526Swpaul * offer to sell, and import the Covered Code and derivative works thereof 3338363Swpaul * solely to the minimum extent necessary to exercise the above copyright 3438363Swpaul * license, and in no event shall the patent license extend to any additions 3538363Swpaul * to or modifications of the Original Intel Code. No other license or right 3638363Swpaul * is granted directly or by implication, estoppel or otherwise; 3738363Swpaul * 3838363Swpaul * The above copyright and patent license is granted only if the following 3938363Swpaul * conditions are met: 4038363Swpaul * 4138363Swpaul * 3. Conditions 4238363Swpaul * 4338363Swpaul * 3.1. Redistribution of Source with Rights to Further Distribute Source. 4438363Swpaul * Redistribution of source code of any substantial portion of the Covered 4538363Swpaul * Code or modification with rights to further distribute source must include 4638363Swpaul * the above Copyright Notice, the above License, this list of Conditions, 4738363Swpaul * and the following Disclaimer and Export Compliance provision. In addition, 4838363Swpaul * Licensee must cause all Covered Code to which Licensee contributes to 4938363Swpaul * contain a file documenting the changes Licensee made to create that Covered 5038363Swpaul * Code and the date of any change. Licensee must include in that file the 5138363Swpaul * documentation of any changes made by any predecessor Licensee. Licensee 5238363Swpaul * must include a prominent statement that the modification is derived, 5338363Swpaul * directly or indirectly, from Original Intel Code. 5438363Swpaul * 5538363Swpaul * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 5638363Swpaul * Redistribution of source code of any substantial portion of the Covered 5738363Swpaul * Code or modification without rights to further distribute source must 5838363Swpaul * include the following Disclaimer and Export Compliance provision in the 5938363Swpaul * documentation and/or other materials provided with distribution. In 6038363Swpaul * addition, Licensee may not authorize further sublicense of source of any 6138363Swpaul * portion of the Covered Code, and must include terms to the effect that the 6238363Swpaul * license from Licensee to its licensee is limited to the intellectual 6338363Swpaul * property embodied in the software Licensee provides to its licensee, and 6438363Swpaul * not to intellectual property embodied in modifications its licensee may 6538363Swpaul * make. 6638363Swpaul * 6738363Swpaul * 3.3. Redistribution of Executable. Redistribution in executable form of any 6838363Swpaul * substantial portion of the Covered Code or modification must reproduce the 6938363Swpaul * above Copyright Notice, and the following Disclaimer and Export Compliance 7038363Swpaul * provision in the documentation and/or other materials provided with the 7138363Swpaul * distribution. 7238363Swpaul * 7338363Swpaul * 3.4. Intel retains all right, title, and interest in and to the Original 7438363Swpaul * Intel Code. 7538363Swpaul * 7638363Swpaul * 3.5. Neither the name Intel nor any other trademark owned or controlled by 7738363Swpaul * Intel shall be used in advertising or otherwise to promote the sale, use or 7838363Swpaul * other dealings in products derived from or relating to the Covered Code 7938363Swpaul * without prior written authorization from Intel. 8038363Swpaul * 8138363Swpaul * 4. Disclaimer and Export Compliance 8238363Swpaul * 8338363Swpaul * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 8438363Swpaul * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 8538363Swpaul * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 8638363Swpaul * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 8738363Swpaul * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 8838363Swpaul * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 8938363Swpaul * PARTICULAR PURPOSE. 9038363Swpaul * 9138363Swpaul * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 9238363Swpaul * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 9338363Swpaul * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 9438363Swpaul * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 9538363Swpaul * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 9638363Swpaul * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 9738363Swpaul * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 9838363Swpaul * LIMITED REMEDY. 9938363Swpaul * 10038363Swpaul * 4.3. Licensee shall not export, either directly or indirectly, any of this 10138363Swpaul * software or system incorporating such software without first obtaining any 10238363Swpaul * required license or other approval from the U. S. Department of Commerce or 10338363Swpaul * any other agency or department of the United States Government. In the 10438363Swpaul * event Licensee exports any such software from the United States or 10538363Swpaul * re-exports any such software from a foreign destination, Licensee shall 10638363Swpaul * ensure that the distribution and export/re-export of the software is in 10738363Swpaul * compliance with all laws, regulations, orders, or other restrictions of the 10838363Swpaul * U.S. Export Administration Regulations. Licensee agrees that neither it nor 10938363Swpaul * any of its subsidiaries will export/re-export any technical data, process, 11038363Swpaul * software, or service, directly or indirectly, to any country for which the 11138363Swpaul * United States government or any agency thereof requires an export license, 11238363Swpaul * other governmental approval, or letter of assurance, without first obtaining 11338363Swpaul * such license, approval or letter. 11438363Swpaul * 11538363Swpaul *****************************************************************************/ 11638363Swpaul 11738363Swpaul 11838363Swpaul#define __NSXFEVAL_C__ 11938363Swpaul 12038363Swpaul#include <contrib/dev/acpica/include/acpi.h> 12138363Swpaul#include <contrib/dev/acpica/include/accommon.h> 12238363Swpaul#include <contrib/dev/acpica/include/acnamesp.h> 12338363Swpaul#include <contrib/dev/acpica/include/acinterp.h> 12438363Swpaul 12538363Swpaul 12638363Swpaul#define _COMPONENT ACPI_NAMESPACE 12738363Swpaul ACPI_MODULE_NAME ("nsxfeval") 12838363Swpaul 12938363Swpaul/* Local prototypes */ 13038363Swpaul 13138363Swpaulstatic void 13238363SwpaulAcpiNsResolveReferences ( 13338363Swpaul ACPI_EVALUATE_INFO *Info); 13438363Swpaul 13538363Swpaul 13638363Swpaul/******************************************************************************* 13738363Swpaul * 13838363Swpaul * FUNCTION: AcpiEvaluateObjectTyped 13938363Swpaul * 14038363Swpaul * PARAMETERS: Handle - Object handle (optional) 14138363Swpaul * Pathname - Object pathname (optional) 14238363Swpaul * ExternalParams - List of parameters to pass to method, 14338363Swpaul * terminated by NULL. May be NULL 14438363Swpaul * if no parameters are being passed. 14538363Swpaul * ReturnBuffer - Where to put method's return value (if 14638363Swpaul * any). If NULL, no value is returned. 14738363Swpaul * ReturnType - Expected type of return object 14838363Swpaul * 14938363Swpaul * RETURN: Status 15038363Swpaul * 15138363Swpaul * DESCRIPTION: Find and evaluate the given object, passing the given 15238363Swpaul * parameters if necessary. One of "Handle" or "Pathname" must 15338363Swpaul * be valid (non-null) 15438363Swpaul * 15538363Swpaul ******************************************************************************/ 15638363Swpaul 15738363SwpaulACPI_STATUS 15838363SwpaulAcpiEvaluateObjectTyped ( 15938363Swpaul ACPI_HANDLE Handle, 16038363Swpaul ACPI_STRING Pathname, 16138363Swpaul ACPI_OBJECT_LIST *ExternalParams, 16238363Swpaul ACPI_BUFFER *ReturnBuffer, 16338363Swpaul ACPI_OBJECT_TYPE ReturnType) 16438363Swpaul{ 16538363Swpaul ACPI_STATUS Status; 16638363Swpaul BOOLEAN MustFree = FALSE; 16738363Swpaul 16838363Swpaul 16938363Swpaul ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped); 17038363Swpaul 17138363Swpaul 17238363Swpaul /* Return buffer must be valid */ 17338363Swpaul 17438526Swpaul if (!ReturnBuffer) 17538526Swpaul { 17638526Swpaul return_ACPI_STATUS (AE_BAD_PARAMETER); 17738526Swpaul } 17838526Swpaul 17938526Swpaul if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER) 18038526Swpaul { 18138363Swpaul MustFree = TRUE; 18238363Swpaul } 18338363Swpaul 18438363Swpaul /* Evaluate the object */ 18538363Swpaul 18638363Swpaul Status = AcpiEvaluateObject (Handle, Pathname, ExternalParams, ReturnBuffer); 18738363Swpaul if (ACPI_FAILURE (Status)) 18838363Swpaul { 18938363Swpaul return_ACPI_STATUS (Status); 19038363Swpaul } 19138363Swpaul 19238363Swpaul /* Type ANY means "don't care" */ 19338363Swpaul 19438363Swpaul if (ReturnType == ACPI_TYPE_ANY) 19538363Swpaul { 19638363Swpaul return_ACPI_STATUS (AE_OK); 19738363Swpaul } 19838363Swpaul 19938363Swpaul if (ReturnBuffer->Length == 0) 20038363Swpaul { 20138363Swpaul /* Error because caller specifically asked for a return value */ 20238363Swpaul 20338363Swpaul ACPI_ERROR ((AE_INFO, "No return value")); 20438363Swpaul return_ACPI_STATUS (AE_NULL_OBJECT); 20538363Swpaul } 20638363Swpaul 20738363Swpaul /* Examine the object type returned from EvaluateObject */ 20838363Swpaul 20938363Swpaul if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType) 21038363Swpaul { 21138363Swpaul return_ACPI_STATUS (AE_OK); 21238363Swpaul } 21338363Swpaul 21438363Swpaul /* Return object type does not match requested type */ 21538363Swpaul 21638363Swpaul ACPI_ERROR ((AE_INFO, 21738363Swpaul "Incorrect return type [%s] requested [%s]", 21838363Swpaul AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type), 21938363Swpaul AcpiUtGetTypeName (ReturnType))); 22038363Swpaul 22138363Swpaul if (MustFree) 22238363Swpaul { 22338363Swpaul /* Caller used ACPI_ALLOCATE_BUFFER, free the return buffer */ 22438363Swpaul 22538363Swpaul AcpiOsFree (ReturnBuffer->Pointer); 22638363Swpaul ReturnBuffer->Pointer = NULL; 22738363Swpaul } 22838363Swpaul 22938363Swpaul ReturnBuffer->Length = 0; 23038363Swpaul return_ACPI_STATUS (AE_TYPE); 23138363Swpaul} 23238363Swpaul 23338363SwpaulACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped) 23438363Swpaul 23538363Swpaul 23638363Swpaul/******************************************************************************* 23738363Swpaul * 23838363Swpaul * FUNCTION: AcpiEvaluateObject 23938363Swpaul * 24038363Swpaul * PARAMETERS: Handle - Object handle (optional) 24138363Swpaul * Pathname - Object pathname (optional) 24238363Swpaul * ExternalParams - List of parameters to pass to method, 24338363Swpaul * terminated by NULL. May be NULL 24438363Swpaul * if no parameters are being passed. 24538363Swpaul * ReturnBuffer - Where to put method's return value (if 24638363Swpaul * any). If NULL, no value is returned. 24738363Swpaul * 24838363Swpaul * RETURN: Status 24938363Swpaul * 25038363Swpaul * DESCRIPTION: Find and evaluate the given object, passing the given 25138363Swpaul * parameters if necessary. One of "Handle" or "Pathname" must 25238363Swpaul * be valid (non-null) 25338363Swpaul * 25438363Swpaul ******************************************************************************/ 25538363Swpaul 25638363SwpaulACPI_STATUS 25738363SwpaulAcpiEvaluateObject ( 25838363Swpaul ACPI_HANDLE Handle, 25938363Swpaul ACPI_STRING Pathname, 26038363Swpaul ACPI_OBJECT_LIST *ExternalParams, 26138363Swpaul ACPI_BUFFER *ReturnBuffer) 26238363Swpaul{ 26338363Swpaul ACPI_STATUS Status; 26438363Swpaul ACPI_EVALUATE_INFO *Info; 26538363Swpaul ACPI_SIZE BufferSpaceNeeded; 26638363Swpaul UINT32 i; 26738363Swpaul 26838363Swpaul 26938363Swpaul ACPI_FUNCTION_TRACE (AcpiEvaluateObject); 27038363Swpaul 27138363Swpaul 27238363Swpaul /* Allocate and initialize the evaluation information block */ 27338363Swpaul 27438363Swpaul Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO)); 27538363Swpaul if (!Info) 27638363Swpaul { 27738363Swpaul return_ACPI_STATUS (AE_NO_MEMORY); 27838363Swpaul } 27938363Swpaul 28038363Swpaul Info->Pathname = Pathname; 28138363Swpaul 28238363Swpaul /* Convert and validate the device handle */ 28338363Swpaul 28438363Swpaul Info->PrefixNode = AcpiNsMapHandleToNode (Handle); 28538363Swpaul if (!Info->PrefixNode) 28638363Swpaul { 28738363Swpaul Status = AE_BAD_PARAMETER; 28838363Swpaul goto Cleanup; 28938363Swpaul } 29038363Swpaul 29138363Swpaul /* 29238363Swpaul * If there are parameters to be passed to a control method, the external 29338363Swpaul * objects must all be converted to internal objects 29438363Swpaul */ 29538363Swpaul if (ExternalParams && ExternalParams->Count) 29638363Swpaul { 29738363Swpaul /* 29838363Swpaul * Allocate a new parameter block for the internal objects 29938363Swpaul * Add 1 to count to allow for null terminated internal list 30038363Swpaul */ 30138363Swpaul Info->Parameters = ACPI_ALLOCATE_ZEROED ( 30238363Swpaul ((ACPI_SIZE) ExternalParams->Count + 1) * sizeof (void *)); 30338363Swpaul if (!Info->Parameters) 30438363Swpaul { 30538363Swpaul Status = AE_NO_MEMORY; 30638363Swpaul goto Cleanup; 30738363Swpaul } 30838363Swpaul 30938363Swpaul /* Convert each external object in the list to an internal object */ 31038363Swpaul 31138363Swpaul for (i = 0; i < ExternalParams->Count; i++) 31238363Swpaul { 31338363Swpaul Status = AcpiUtCopyEobjectToIobject ( 31438363Swpaul &ExternalParams->Pointer[i], &Info->Parameters[i]); 31538363Swpaul if (ACPI_FAILURE (Status)) 31638363Swpaul { 31738363Swpaul goto Cleanup; 31838363Swpaul } 31938363Swpaul } 32038363Swpaul Info->Parameters[ExternalParams->Count] = NULL; 32138363Swpaul } 32238363Swpaul 32338363Swpaul /* 32438363Swpaul * Three major cases: 32538363Swpaul * 1) Fully qualified pathname 32638363Swpaul * 2) No handle, not fully qualified pathname (error) 32738363Swpaul * 3) Valid handle 32838363Swpaul */ 32938363Swpaul if ((Pathname) && 33038363Swpaul (AcpiNsValidRootPrefix (Pathname[0]))) 33138363Swpaul { 33238363Swpaul /* The path is fully qualified, just evaluate by name */ 33338363Swpaul 33438363Swpaul Info->PrefixNode = NULL; 33538363Swpaul Status = AcpiNsEvaluate (Info); 33638363Swpaul } 33738363Swpaul else if (!Handle) 33838363Swpaul { 33938363Swpaul /* 34038363Swpaul * A handle is optional iff a fully qualified pathname is specified. 34138363Swpaul * Since we've already handled fully qualified names above, this is 34238363Swpaul * an error 34338363Swpaul */ 34438363Swpaul if (!Pathname) 34538363Swpaul { 34638363Swpaul ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 34738363Swpaul "Both Handle and Pathname are NULL")); 34838363Swpaul } 34938363Swpaul else 35038363Swpaul { 35138363Swpaul ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 35238363Swpaul "Null Handle with relative pathname [%s]", Pathname)); 35338363Swpaul } 35438363Swpaul 35538363Swpaul Status = AE_BAD_PARAMETER; 35638363Swpaul } 35738363Swpaul else 35838363Swpaul { 35938363Swpaul /* We have a namespace a node and a possible relative path */ 36038363Swpaul 36138363Swpaul Status = AcpiNsEvaluate (Info); 36238363Swpaul } 36338363Swpaul 36438363Swpaul /* 36538363Swpaul * If we are expecting a return value, and all went well above, 36638363Swpaul * copy the return value to an external object. 36738363Swpaul */ 36838363Swpaul if (ReturnBuffer) 36938363Swpaul { 37038363Swpaul if (!Info->ReturnObject) 37138363Swpaul { 37238363Swpaul ReturnBuffer->Length = 0; 37338363Swpaul } 37438363Swpaul else 37538363Swpaul { 37638363Swpaul if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) == 37738363Swpaul ACPI_DESC_TYPE_NAMED) 37838363Swpaul { 37938363Swpaul /* 38038363Swpaul * If we received a NS Node as a return object, this means that 38138363Swpaul * the object we are evaluating has nothing interesting to 38238363Swpaul * return (such as a mutex, etc.) We return an error because 38338363Swpaul * these types are essentially unsupported by this interface. 38438363Swpaul * We don't check up front because this makes it easier to add 38538363Swpaul * support for various types at a later date if necessary. 38638363Swpaul */ 38738363Swpaul Status = AE_TYPE; 38838363Swpaul Info->ReturnObject = NULL; /* No need to delete a NS Node */ 38938363Swpaul ReturnBuffer->Length = 0; 39038363Swpaul } 39138363Swpaul 39238363Swpaul if (ACPI_SUCCESS (Status)) 39338363Swpaul { 39438363Swpaul /* Dereference Index and RefOf references */ 39538363Swpaul 39638363Swpaul AcpiNsResolveReferences (Info); 39738363Swpaul 39838363Swpaul /* Get the size of the returned object */ 39938363Swpaul 40038363Swpaul Status = AcpiUtGetObjectSize (Info->ReturnObject, 40138363Swpaul &BufferSpaceNeeded); 40238363Swpaul if (ACPI_SUCCESS (Status)) 40338363Swpaul { 40438363Swpaul /* Validate/Allocate/Clear caller buffer */ 40538363Swpaul 40638363Swpaul Status = AcpiUtInitializeBuffer (ReturnBuffer, 40738363Swpaul BufferSpaceNeeded); 40838363Swpaul if (ACPI_FAILURE (Status)) 40938363Swpaul { 41038363Swpaul /* 41138363Swpaul * Caller's buffer is too small or a new one can't 41238363Swpaul * be allocated 41338363Swpaul */ 41438363Swpaul ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 41538363Swpaul "Needed buffer size %X, %s\n", 41638363Swpaul (UINT32) BufferSpaceNeeded, 41738363Swpaul AcpiFormatException (Status))); 41838363Swpaul } 41938363Swpaul else 42038363Swpaul { 42138363Swpaul /* We have enough space for the object, build it */ 42238363Swpaul 42338363Swpaul Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject, 42438363Swpaul ReturnBuffer); 42538363Swpaul } 42638363Swpaul } 42738363Swpaul } 42838363Swpaul } 42938363Swpaul } 43038363Swpaul 43138363Swpaul if (Info->ReturnObject) 43238363Swpaul { 43338363Swpaul /* 43438363Swpaul * Delete the internal return object. NOTE: Interpreter must be 43538363Swpaul * locked to avoid race condition. 43638363Swpaul */ 43738363Swpaul AcpiExEnterInterpreter (); 43838363Swpaul 43938469Swpaul /* Remove one reference on the return object (should delete it) */ 44038363Swpaul 44138363Swpaul AcpiUtRemoveReference (Info->ReturnObject); 44238363Swpaul AcpiExExitInterpreter (); 44338363Swpaul } 44438363Swpaul 44538363Swpaul 44638363SwpaulCleanup: 44738363Swpaul 44838363Swpaul /* Free the input parameter list (if we created one) */ 44938363Swpaul 45038363Swpaul if (Info->Parameters) 45138363Swpaul { 45238363Swpaul /* Free the allocated parameter block */ 45338363Swpaul 45438363Swpaul AcpiUtDeleteInternalObjectList (Info->Parameters); 45538363Swpaul } 45638363Swpaul 45738363Swpaul ACPI_FREE (Info); 45838363Swpaul return_ACPI_STATUS (Status); 45938363Swpaul} 46038363Swpaul 46138363SwpaulACPI_EXPORT_SYMBOL (AcpiEvaluateObject) 46238363Swpaul 46338363Swpaul 46438363Swpaul/******************************************************************************* 46538363Swpaul * 46638363Swpaul * FUNCTION: AcpiNsResolveReferences 46738363Swpaul * 46838363Swpaul * PARAMETERS: Info - Evaluation info block 46938363Swpaul * 47038363Swpaul * RETURN: Info->ReturnObject is replaced with the dereferenced object 47138363Swpaul * 47238363Swpaul * DESCRIPTION: Dereference certain reference objects. Called before an 47338363Swpaul * internal return object is converted to an external ACPI_OBJECT. 47438363Swpaul * 47538363Swpaul * Performs an automatic dereference of Index and RefOf reference objects. 47638363Swpaul * These reference objects are not supported by the ACPI_OBJECT, so this is a 47738363Swpaul * last resort effort to return something useful. Also, provides compatibility 47838363Swpaul * with other ACPI implementations. 47938363Swpaul * 48038363Swpaul * NOTE: does not handle references within returned package objects or nested 48138363Swpaul * references, but this support could be added later if found to be necessary. 48238363Swpaul * 48338363Swpaul ******************************************************************************/ 48438363Swpaul 48538363Swpaulstatic void 48638363SwpaulAcpiNsResolveReferences ( 48738363Swpaul ACPI_EVALUATE_INFO *Info) 48838363Swpaul{ 48938363Swpaul ACPI_OPERAND_OBJECT *ObjDesc = NULL; 49038363Swpaul ACPI_NAMESPACE_NODE *Node; 49138363Swpaul 49238363Swpaul 49338363Swpaul /* We are interested in reference objects only */ 49438363Swpaul 49538363Swpaul if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE) 49638363Swpaul { 49738363Swpaul return; 49838363Swpaul } 49938363Swpaul 50038363Swpaul /* 50138363Swpaul * Two types of references are supported - those created by Index and 50238363Swpaul * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted 50338363Swpaul * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle 50438363Swpaul * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to 50538363Swpaul * an ACPI_OBJECT. 50638363Swpaul */ 50738363Swpaul switch (Info->ReturnObject->Reference.Class) 50838363Swpaul { 50938363Swpaul case ACPI_REFCLASS_INDEX: 51038363Swpaul 51138363Swpaul ObjDesc = *(Info->ReturnObject->Reference.Where); 51238363Swpaul break; 51338363Swpaul 51438363Swpaul case ACPI_REFCLASS_REFOF: 51538363Swpaul 51638363Swpaul Node = Info->ReturnObject->Reference.Object; 51738363Swpaul if (Node) 51838363Swpaul { 51938363Swpaul ObjDesc = Node->Object; 52038363Swpaul } 52138363Swpaul break; 52238363Swpaul 52338363Swpaul default: 52438363Swpaul return; 52538363Swpaul } 52638363Swpaul 52738363Swpaul /* Replace the existing reference object */ 52838363Swpaul 52938363Swpaul if (ObjDesc) 53038363Swpaul { 53138363Swpaul AcpiUtAddReference (ObjDesc); 53238363Swpaul AcpiUtRemoveReference (Info->ReturnObject); 53338363Swpaul Info->ReturnObject = ObjDesc; 53438363Swpaul } 53538363Swpaul 53638363Swpaul return; 53738363Swpaul} 53838363Swpaul 53938363Swpaul 54038363Swpaul/******************************************************************************* 54138363Swpaul * 54238363Swpaul * FUNCTION: AcpiWalkNamespace 54338363Swpaul * 54438363Swpaul * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for 54538363Swpaul * StartObject - Handle in namespace where search begins 54638363Swpaul * MaxDepth - Depth to which search is to reach 54738363Swpaul * UserFunction - Called when an object of "Type" is found 54838363Swpaul * Context - Passed to user function 54938363Swpaul * ReturnValue - Location where return value of 55038363Swpaul * UserFunction is put if terminated early 55138363Swpaul * 55238363Swpaul * RETURNS Return value from the UserFunction if terminated early. 55338363Swpaul * Otherwise, returns NULL. 55438363Swpaul * 55538363Swpaul * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 55638363Swpaul * starting (and ending) at the object specified by StartHandle. 55738363Swpaul * The UserFunction is called whenever an object that matches 55838363Swpaul * the type parameter is found. If the user function returns 55938363Swpaul * a non-zero value, the search is terminated immediately and this 56038363Swpaul * value is returned to the caller. 56138363Swpaul * 56238363Swpaul * The point of this procedure is to provide a generic namespace 56338363Swpaul * walk routine that can be called from multiple places to 56438363Swpaul * provide multiple services; the User Function can be tailored 56538363Swpaul * to each task, whether it is a print function, a compare 56638363Swpaul * function, etc. 56738363Swpaul * 56838363Swpaul ******************************************************************************/ 56938363Swpaul 57038363SwpaulACPI_STATUS 57138363SwpaulAcpiWalkNamespace ( 57238363Swpaul ACPI_OBJECT_TYPE Type, 57338363Swpaul ACPI_HANDLE StartObject, 57438363Swpaul UINT32 MaxDepth, 57538363Swpaul ACPI_WALK_CALLBACK UserFunction, 57638363Swpaul void *Context, 57738363Swpaul void **ReturnValue) 57838363Swpaul{ 57938363Swpaul ACPI_STATUS Status; 58038363Swpaul 58138363Swpaul 58238363Swpaul ACPI_FUNCTION_TRACE (AcpiWalkNamespace); 58338363Swpaul 58438363Swpaul 58538363Swpaul /* Parameter validation */ 58638363Swpaul 58738363Swpaul if ((Type > ACPI_TYPE_LOCAL_MAX) || 58838363Swpaul (!MaxDepth) || 58938363Swpaul (!UserFunction)) 59038363Swpaul { 59138363Swpaul return_ACPI_STATUS (AE_BAD_PARAMETER); 59238363Swpaul } 59338363Swpaul 59438363Swpaul /* 59538363Swpaul * Need to acquire the namespace reader lock to prevent interference 59638363Swpaul * with any concurrent table unloads (which causes the deletion of 59738363Swpaul * namespace objects). We cannot allow the deletion of a namespace node 59838363Swpaul * while the user function is using it. The exception to this are the 59938363Swpaul * nodes created and deleted during control method execution -- these 60038363Swpaul * nodes are marked as temporary nodes and are ignored by the namespace 60138363Swpaul * walk. Thus, control methods can be executed while holding the 60238363Swpaul * namespace deletion lock (and the user function can execute control 60338363Swpaul * methods.) 60438363Swpaul */ 60538363Swpaul Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock); 60638363Swpaul if (ACPI_FAILURE (Status)) 60738363Swpaul { 60838363Swpaul return (Status); 60938363Swpaul } 61038363Swpaul 61138363Swpaul /* 61238363Swpaul * Lock the namespace around the walk. The namespace will be 61338363Swpaul * unlocked/locked around each call to the user function - since the user 61438363Swpaul * function must be allowed to make ACPICA calls itself (for example, it 61538363Swpaul * will typically execute control methods during device enumeration.) 61638363Swpaul */ 61738363Swpaul Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 61838363Swpaul if (ACPI_FAILURE (Status)) 61938363Swpaul { 62038363Swpaul goto UnlockAndExit; 62138363Swpaul } 62238363Swpaul 62338363Swpaul Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth, 62438363Swpaul ACPI_NS_WALK_UNLOCK, UserFunction, Context, ReturnValue); 62538363Swpaul 62638363Swpaul (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 62738363Swpaul 62838363SwpaulUnlockAndExit: 62938363Swpaul (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock); 63038363Swpaul return_ACPI_STATUS (Status); 63138363Swpaul} 63238363Swpaul 63338363SwpaulACPI_EXPORT_SYMBOL (AcpiWalkNamespace) 63438363Swpaul 63538363Swpaul 63638363Swpaul/******************************************************************************* 63738363Swpaul * 63838363Swpaul * FUNCTION: AcpiNsGetDeviceCallback 63938363Swpaul * 64038363Swpaul * PARAMETERS: Callback from AcpiGetDevice 64138363Swpaul * 64238363Swpaul * RETURN: Status 64338363Swpaul * 64438363Swpaul * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non- 64538363Swpaul * present devices, or if they specified a HID, it filters based 64638363Swpaul * on that. 64738363Swpaul * 64838363Swpaul ******************************************************************************/ 64938363Swpaul 65038363Swpaulstatic ACPI_STATUS 65138363SwpaulAcpiNsGetDeviceCallback ( 65238363Swpaul ACPI_HANDLE ObjHandle, 65338363Swpaul UINT32 NestingLevel, 65438363Swpaul void *Context, 65538363Swpaul void **ReturnValue) 65638363Swpaul{ 65738363Swpaul ACPI_GET_DEVICES_INFO *Info = Context; 65838363Swpaul ACPI_STATUS Status; 65938363Swpaul ACPI_NAMESPACE_NODE *Node; 66038363Swpaul UINT32 Flags; 66138363Swpaul ACPI_DEVICE_ID Hid; 66238363Swpaul ACPI_COMPATIBLE_ID_LIST *Cid; 66338363Swpaul UINT32 i; 66438363Swpaul BOOLEAN Found; 66538363Swpaul 66638363Swpaul 66738363Swpaul Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 66838363Swpaul if (ACPI_FAILURE (Status)) 66938363Swpaul { 67038363Swpaul return (Status); 67138363Swpaul } 67238363Swpaul 67338363Swpaul Node = AcpiNsMapHandleToNode (ObjHandle); 67438363Swpaul Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 67538363Swpaul if (ACPI_FAILURE (Status)) 67638363Swpaul { 67738363Swpaul return (Status); 67838363Swpaul } 67938363Swpaul 68038363Swpaul if (!Node) 68138363Swpaul { 68238363Swpaul return (AE_BAD_PARAMETER); 68338363Swpaul } 68438363Swpaul 68538363Swpaul /* Run _STA to determine if device is present */ 68638363Swpaul 68738363Swpaul Status = AcpiUtExecute_STA (Node, &Flags); 68838363Swpaul if (ACPI_FAILURE (Status)) 68938363Swpaul { 69038363Swpaul return (AE_CTRL_DEPTH); 69138363Swpaul } 69238363Swpaul 69338363Swpaul if (!(Flags & ACPI_STA_DEVICE_PRESENT) && 69438363Swpaul !(Flags & ACPI_STA_DEVICE_FUNCTIONING)) 69538363Swpaul { 69638363Swpaul /* 69738363Swpaul * Don't examine the children of the device only when the 69838363Swpaul * device is neither present nor functional. See ACPI spec, 69938363Swpaul * description of _STA for more information. 70038363Swpaul */ 70138363Swpaul return (AE_CTRL_DEPTH); 70238363Swpaul } 70338363Swpaul 70438363Swpaul /* Filter based on device HID & CID */ 70538363Swpaul 70638363Swpaul if (Info->Hid != NULL) 70738363Swpaul { 70838363Swpaul Status = AcpiUtExecute_HID (Node, &Hid); 70938363Swpaul if (Status == AE_NOT_FOUND) 71038363Swpaul { 71138363Swpaul return (AE_OK); 71238363Swpaul } 71338363Swpaul else if (ACPI_FAILURE (Status)) 71438363Swpaul { 71538363Swpaul return (AE_CTRL_DEPTH); 71638363Swpaul } 71738363Swpaul 71838363Swpaul if (ACPI_STRNCMP (Hid.Value, Info->Hid, sizeof (Hid.Value)) != 0) 71938363Swpaul { 72038363Swpaul /* 72138363Swpaul * HID does not match, attempt match within the 72238363Swpaul * list of Compatible IDs (CIDs) 72338363Swpaul */ 72438363Swpaul Status = AcpiUtExecute_CID (Node, &Cid); 72538363Swpaul if (Status == AE_NOT_FOUND) 72638363Swpaul { 72738363Swpaul return (AE_OK); 72838363Swpaul } 72938363Swpaul else if (ACPI_FAILURE (Status)) 73038363Swpaul { 73138363Swpaul return (AE_CTRL_DEPTH); 73238363Swpaul } 73338363Swpaul 73438363Swpaul /* Walk the CID list */ 73538363Swpaul 73638363Swpaul Found = FALSE; 73738363Swpaul for (i = 0; i < Cid->Count; i++) 73838363Swpaul { 73938363Swpaul if (ACPI_STRNCMP (Cid->Id[i].Value, Info->Hid, 74038363Swpaul sizeof (ACPI_COMPATIBLE_ID)) == 0) 74138363Swpaul { 74238363Swpaul /* Found a matching CID */ 74338363Swpaul 74438363Swpaul Found = TRUE; 74538363Swpaul break; 74638363Swpaul } 74738363Swpaul } 74838363Swpaul 74938363Swpaul ACPI_FREE (Cid); 75038363Swpaul if (!Found) 75138363Swpaul { 75238363Swpaul return (AE_OK); 75338363Swpaul } 75438363Swpaul } 75538363Swpaul } 75638363Swpaul 75738363Swpaul /* We have a valid device, invoke the user function */ 75838363Swpaul 75938363Swpaul Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context, 76038363Swpaul ReturnValue); 76138363Swpaul return (Status); 76238363Swpaul} 76338363Swpaul 76438363Swpaul 76538363Swpaul/******************************************************************************* 76638363Swpaul * 76738363Swpaul * FUNCTION: AcpiGetDevices 76838363Swpaul * 76938363Swpaul * PARAMETERS: HID - HID to search for. Can be NULL. 77038363Swpaul * UserFunction - Called when a matching object is found 77138363Swpaul * Context - Passed to user function 77238363Swpaul * ReturnValue - Location where return value of 77338363Swpaul * UserFunction is put if terminated early 77438363Swpaul * 77538363Swpaul * RETURNS Return value from the UserFunction if terminated early. 77638363Swpaul * Otherwise, returns NULL. 77738363Swpaul * 77838363Swpaul * DESCRIPTION: Performs a modified depth-first walk of the namespace tree, 77938363Swpaul * starting (and ending) at the object specified by StartHandle. 78038363Swpaul * The UserFunction is called whenever an object of type 78138363Swpaul * Device is found. If the user function returns 78238363Swpaul * a non-zero value, the search is terminated immediately and this 78338363Swpaul * value is returned to the caller. 78438363Swpaul * 78538363Swpaul * This is a wrapper for WalkNamespace, but the callback performs 78638363Swpaul * additional filtering. Please see AcpiNsGetDeviceCallback. 78738363Swpaul * 78838363Swpaul ******************************************************************************/ 78938363Swpaul 79038363SwpaulACPI_STATUS 79138363SwpaulAcpiGetDevices ( 79238363Swpaul char *HID, 79338363Swpaul ACPI_WALK_CALLBACK UserFunction, 79438363Swpaul void *Context, 79538363Swpaul void **ReturnValue) 79638363Swpaul{ 79738363Swpaul ACPI_STATUS Status; 79838363Swpaul ACPI_GET_DEVICES_INFO Info; 79938363Swpaul 80038363Swpaul 80138363Swpaul ACPI_FUNCTION_TRACE (AcpiGetDevices); 80238363Swpaul 80338363Swpaul 80438363Swpaul /* Parameter validation */ 80538363Swpaul 80638363Swpaul if (!UserFunction) 80738363Swpaul { 80838363Swpaul return_ACPI_STATUS (AE_BAD_PARAMETER); 80938363Swpaul } 81038363Swpaul 81138363Swpaul /* 81238363Swpaul * We're going to call their callback from OUR callback, so we need 81338363Swpaul * to know what it is, and their context parameter. 81438363Swpaul */ 81538363Swpaul Info.Hid = HID; 81638363Swpaul Info.Context = Context; 81738363Swpaul Info.UserFunction = UserFunction; 81838363Swpaul 81938363Swpaul /* 82038363Swpaul * Lock the namespace around the walk. 82138363Swpaul * The namespace will be unlocked/locked around each call 82238363Swpaul * to the user function - since this function 823 * must be allowed to make Acpi calls itself. 824 */ 825 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 826 if (ACPI_FAILURE (Status)) 827 { 828 return_ACPI_STATUS (Status); 829 } 830 831 Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT, 832 ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK, 833 AcpiNsGetDeviceCallback, &Info, ReturnValue); 834 835 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 836 return_ACPI_STATUS (Status); 837} 838 839ACPI_EXPORT_SYMBOL (AcpiGetDevices) 840 841 842/******************************************************************************* 843 * 844 * FUNCTION: AcpiAttachData 845 * 846 * PARAMETERS: ObjHandle - Namespace node 847 * Handler - Handler for this attachment 848 * Data - Pointer to data to be attached 849 * 850 * RETURN: Status 851 * 852 * DESCRIPTION: Attach arbitrary data and handler to a namespace node. 853 * 854 ******************************************************************************/ 855 856ACPI_STATUS 857AcpiAttachData ( 858 ACPI_HANDLE ObjHandle, 859 ACPI_OBJECT_HANDLER Handler, 860 void *Data) 861{ 862 ACPI_NAMESPACE_NODE *Node; 863 ACPI_STATUS Status; 864 865 866 /* Parameter validation */ 867 868 if (!ObjHandle || 869 !Handler || 870 !Data) 871 { 872 return (AE_BAD_PARAMETER); 873 } 874 875 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 876 if (ACPI_FAILURE (Status)) 877 { 878 return (Status); 879 } 880 881 /* Convert and validate the handle */ 882 883 Node = AcpiNsMapHandleToNode (ObjHandle); 884 if (!Node) 885 { 886 Status = AE_BAD_PARAMETER; 887 goto UnlockAndExit; 888 } 889 890 Status = AcpiNsAttachData (Node, Handler, Data); 891 892UnlockAndExit: 893 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 894 return (Status); 895} 896 897ACPI_EXPORT_SYMBOL (AcpiAttachData) 898 899 900/******************************************************************************* 901 * 902 * FUNCTION: AcpiDetachData 903 * 904 * PARAMETERS: ObjHandle - Namespace node handle 905 * Handler - Handler used in call to AcpiAttachData 906 * 907 * RETURN: Status 908 * 909 * DESCRIPTION: Remove data that was previously attached to a node. 910 * 911 ******************************************************************************/ 912 913ACPI_STATUS 914AcpiDetachData ( 915 ACPI_HANDLE ObjHandle, 916 ACPI_OBJECT_HANDLER Handler) 917{ 918 ACPI_NAMESPACE_NODE *Node; 919 ACPI_STATUS Status; 920 921 922 /* Parameter validation */ 923 924 if (!ObjHandle || 925 !Handler) 926 { 927 return (AE_BAD_PARAMETER); 928 } 929 930 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 931 if (ACPI_FAILURE (Status)) 932 { 933 return (Status); 934 } 935 936 /* Convert and validate the handle */ 937 938 Node = AcpiNsMapHandleToNode (ObjHandle); 939 if (!Node) 940 { 941 Status = AE_BAD_PARAMETER; 942 goto UnlockAndExit; 943 } 944 945 Status = AcpiNsDetachData (Node, Handler); 946 947UnlockAndExit: 948 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 949 return (Status); 950} 951 952ACPI_EXPORT_SYMBOL (AcpiDetachData) 953 954 955/******************************************************************************* 956 * 957 * FUNCTION: AcpiGetData 958 * 959 * PARAMETERS: ObjHandle - Namespace node 960 * Handler - Handler used in call to AttachData 961 * Data - Where the data is returned 962 * 963 * RETURN: Status 964 * 965 * DESCRIPTION: Retrieve data that was previously attached to a namespace node. 966 * 967 ******************************************************************************/ 968 969ACPI_STATUS 970AcpiGetData ( 971 ACPI_HANDLE ObjHandle, 972 ACPI_OBJECT_HANDLER Handler, 973 void **Data) 974{ 975 ACPI_NAMESPACE_NODE *Node; 976 ACPI_STATUS Status; 977 978 979 /* Parameter validation */ 980 981 if (!ObjHandle || 982 !Handler || 983 !Data) 984 { 985 return (AE_BAD_PARAMETER); 986 } 987 988 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 989 if (ACPI_FAILURE (Status)) 990 { 991 return (Status); 992 } 993 994 /* Convert and validate the handle */ 995 996 Node = AcpiNsMapHandleToNode (ObjHandle); 997 if (!Node) 998 { 999 Status = AE_BAD_PARAMETER; 1000 goto UnlockAndExit; 1001 } 1002 1003 Status = AcpiNsGetAttachedData (Node, Handler, Data); 1004 1005UnlockAndExit: 1006 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 1007 return (Status); 1008} 1009 1010ACPI_EXPORT_SYMBOL (AcpiGetData) 1011 1012 1013