1433d6423SLionel Sambuc /*******************************************************************************
2433d6423SLionel Sambuc *
3433d6423SLionel Sambuc * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
4433d6423SLionel Sambuc * ACPI Object evaluation interfaces
5433d6423SLionel Sambuc *
6433d6423SLionel Sambuc ******************************************************************************/
7433d6423SLionel Sambuc
8*29492bb7SDavid van Moolenbroek /*
9*29492bb7SDavid van Moolenbroek * Copyright (C) 2000 - 2014, Intel Corp.
10433d6423SLionel Sambuc * All rights reserved.
11433d6423SLionel Sambuc *
12*29492bb7SDavid van Moolenbroek * Redistribution and use in source and binary forms, with or without
13*29492bb7SDavid van Moolenbroek * modification, are permitted provided that the following conditions
14*29492bb7SDavid van Moolenbroek * are met:
15*29492bb7SDavid van Moolenbroek * 1. Redistributions of source code must retain the above copyright
16*29492bb7SDavid van Moolenbroek * notice, this list of conditions, and the following disclaimer,
17*29492bb7SDavid van Moolenbroek * without modification.
18*29492bb7SDavid van Moolenbroek * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19*29492bb7SDavid van Moolenbroek * substantially similar to the "NO WARRANTY" disclaimer below
20*29492bb7SDavid van Moolenbroek * ("Disclaimer") and any redistribution must be conditioned upon
21*29492bb7SDavid van Moolenbroek * including a substantially similar Disclaimer requirement for further
22*29492bb7SDavid van Moolenbroek * binary redistribution.
23*29492bb7SDavid van Moolenbroek * 3. Neither the names of the above-listed copyright holders nor the names
24*29492bb7SDavid van Moolenbroek * of any contributors may be used to endorse or promote products derived
25*29492bb7SDavid van Moolenbroek * from this software without specific prior written permission.
26433d6423SLionel Sambuc *
27*29492bb7SDavid van Moolenbroek * Alternatively, this software may be distributed under the terms of the
28*29492bb7SDavid van Moolenbroek * GNU General Public License ("GPL") version 2 as published by the Free
29*29492bb7SDavid van Moolenbroek * Software Foundation.
30433d6423SLionel Sambuc *
31*29492bb7SDavid van Moolenbroek * NO WARRANTY
32*29492bb7SDavid van Moolenbroek * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33*29492bb7SDavid van Moolenbroek * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34*29492bb7SDavid van Moolenbroek * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35*29492bb7SDavid van Moolenbroek * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36*29492bb7SDavid van Moolenbroek * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*29492bb7SDavid van Moolenbroek * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38*29492bb7SDavid van Moolenbroek * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39*29492bb7SDavid van Moolenbroek * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40*29492bb7SDavid van Moolenbroek * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41*29492bb7SDavid van Moolenbroek * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42*29492bb7SDavid van Moolenbroek * POSSIBILITY OF SUCH DAMAGES.
43*29492bb7SDavid van Moolenbroek */
44433d6423SLionel Sambuc
45*29492bb7SDavid van Moolenbroek #define EXPORT_ACPI_INTERFACES
46433d6423SLionel Sambuc
47433d6423SLionel Sambuc #include "acpi.h"
48433d6423SLionel Sambuc #include "accommon.h"
49433d6423SLionel Sambuc #include "acnamesp.h"
50433d6423SLionel Sambuc #include "acinterp.h"
51433d6423SLionel Sambuc
52433d6423SLionel Sambuc
53433d6423SLionel Sambuc #define _COMPONENT ACPI_NAMESPACE
54433d6423SLionel Sambuc ACPI_MODULE_NAME ("nsxfeval")
55433d6423SLionel Sambuc
56433d6423SLionel Sambuc /* Local prototypes */
57433d6423SLionel Sambuc
58433d6423SLionel Sambuc static void
59433d6423SLionel Sambuc AcpiNsResolveReferences (
60433d6423SLionel Sambuc ACPI_EVALUATE_INFO *Info);
61433d6423SLionel Sambuc
62433d6423SLionel Sambuc
63433d6423SLionel Sambuc /*******************************************************************************
64433d6423SLionel Sambuc *
65433d6423SLionel Sambuc * FUNCTION: AcpiEvaluateObjectTyped
66433d6423SLionel Sambuc *
67433d6423SLionel Sambuc * PARAMETERS: Handle - Object handle (optional)
68433d6423SLionel Sambuc * Pathname - Object pathname (optional)
69433d6423SLionel Sambuc * ExternalParams - List of parameters to pass to method,
70433d6423SLionel Sambuc * terminated by NULL. May be NULL
71433d6423SLionel Sambuc * if no parameters are being passed.
72433d6423SLionel Sambuc * ReturnBuffer - Where to put method's return value (if
73433d6423SLionel Sambuc * any). If NULL, no value is returned.
74433d6423SLionel Sambuc * ReturnType - Expected type of return object
75433d6423SLionel Sambuc *
76433d6423SLionel Sambuc * RETURN: Status
77433d6423SLionel Sambuc *
78433d6423SLionel Sambuc * DESCRIPTION: Find and evaluate the given object, passing the given
79433d6423SLionel Sambuc * parameters if necessary. One of "Handle" or "Pathname" must
80433d6423SLionel Sambuc * be valid (non-null)
81433d6423SLionel Sambuc *
82433d6423SLionel Sambuc ******************************************************************************/
83433d6423SLionel Sambuc
84433d6423SLionel Sambuc ACPI_STATUS
AcpiEvaluateObjectTyped(ACPI_HANDLE Handle,ACPI_STRING Pathname,ACPI_OBJECT_LIST * ExternalParams,ACPI_BUFFER * ReturnBuffer,ACPI_OBJECT_TYPE ReturnType)85433d6423SLionel Sambuc AcpiEvaluateObjectTyped (
86433d6423SLionel Sambuc ACPI_HANDLE Handle,
87433d6423SLionel Sambuc ACPI_STRING Pathname,
88433d6423SLionel Sambuc ACPI_OBJECT_LIST *ExternalParams,
89433d6423SLionel Sambuc ACPI_BUFFER *ReturnBuffer,
90433d6423SLionel Sambuc ACPI_OBJECT_TYPE ReturnType)
91433d6423SLionel Sambuc {
92433d6423SLionel Sambuc ACPI_STATUS Status;
93*29492bb7SDavid van Moolenbroek BOOLEAN FreeBufferOnError = FALSE;
94433d6423SLionel Sambuc
95433d6423SLionel Sambuc
96433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
97433d6423SLionel Sambuc
98433d6423SLionel Sambuc
99433d6423SLionel Sambuc /* Return buffer must be valid */
100433d6423SLionel Sambuc
101433d6423SLionel Sambuc if (!ReturnBuffer)
102433d6423SLionel Sambuc {
103433d6423SLionel Sambuc return_ACPI_STATUS (AE_BAD_PARAMETER);
104433d6423SLionel Sambuc }
105433d6423SLionel Sambuc
106433d6423SLionel Sambuc if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
107433d6423SLionel Sambuc {
108*29492bb7SDavid van Moolenbroek FreeBufferOnError = TRUE;
109433d6423SLionel Sambuc }
110433d6423SLionel Sambuc
111433d6423SLionel Sambuc /* Evaluate the object */
112433d6423SLionel Sambuc
113*29492bb7SDavid van Moolenbroek Status = AcpiEvaluateObject (Handle, Pathname,
114*29492bb7SDavid van Moolenbroek ExternalParams, ReturnBuffer);
115433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
116433d6423SLionel Sambuc {
117433d6423SLionel Sambuc return_ACPI_STATUS (Status);
118433d6423SLionel Sambuc }
119433d6423SLionel Sambuc
120433d6423SLionel Sambuc /* Type ANY means "don't care" */
121433d6423SLionel Sambuc
122433d6423SLionel Sambuc if (ReturnType == ACPI_TYPE_ANY)
123433d6423SLionel Sambuc {
124433d6423SLionel Sambuc return_ACPI_STATUS (AE_OK);
125433d6423SLionel Sambuc }
126433d6423SLionel Sambuc
127433d6423SLionel Sambuc if (ReturnBuffer->Length == 0)
128433d6423SLionel Sambuc {
129433d6423SLionel Sambuc /* Error because caller specifically asked for a return value */
130433d6423SLionel Sambuc
131433d6423SLionel Sambuc ACPI_ERROR ((AE_INFO, "No return value"));
132433d6423SLionel Sambuc return_ACPI_STATUS (AE_NULL_OBJECT);
133433d6423SLionel Sambuc }
134433d6423SLionel Sambuc
135433d6423SLionel Sambuc /* Examine the object type returned from EvaluateObject */
136433d6423SLionel Sambuc
137433d6423SLionel Sambuc if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
138433d6423SLionel Sambuc {
139433d6423SLionel Sambuc return_ACPI_STATUS (AE_OK);
140433d6423SLionel Sambuc }
141433d6423SLionel Sambuc
142433d6423SLionel Sambuc /* Return object type does not match requested type */
143433d6423SLionel Sambuc
144433d6423SLionel Sambuc ACPI_ERROR ((AE_INFO,
145433d6423SLionel Sambuc "Incorrect return type [%s] requested [%s]",
146433d6423SLionel Sambuc AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
147433d6423SLionel Sambuc AcpiUtGetTypeName (ReturnType)));
148433d6423SLionel Sambuc
149*29492bb7SDavid van Moolenbroek if (FreeBufferOnError)
150433d6423SLionel Sambuc {
151*29492bb7SDavid van Moolenbroek /*
152*29492bb7SDavid van Moolenbroek * Free a buffer created via ACPI_ALLOCATE_BUFFER.
153*29492bb7SDavid van Moolenbroek * Note: We use AcpiOsFree here because AcpiOsAllocate was used
154*29492bb7SDavid van Moolenbroek * to allocate the buffer. This purposefully bypasses the
155*29492bb7SDavid van Moolenbroek * (optionally enabled) allocation tracking mechanism since we
156*29492bb7SDavid van Moolenbroek * only want to track internal allocations.
157*29492bb7SDavid van Moolenbroek */
158433d6423SLionel Sambuc AcpiOsFree (ReturnBuffer->Pointer);
159433d6423SLionel Sambuc ReturnBuffer->Pointer = NULL;
160433d6423SLionel Sambuc }
161433d6423SLionel Sambuc
162433d6423SLionel Sambuc ReturnBuffer->Length = 0;
163433d6423SLionel Sambuc return_ACPI_STATUS (AE_TYPE);
164433d6423SLionel Sambuc }
165433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiEvaluateObjectTyped)166433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
167433d6423SLionel Sambuc
168433d6423SLionel Sambuc
169433d6423SLionel Sambuc /*******************************************************************************
170433d6423SLionel Sambuc *
171433d6423SLionel Sambuc * FUNCTION: AcpiEvaluateObject
172433d6423SLionel Sambuc *
173433d6423SLionel Sambuc * PARAMETERS: Handle - Object handle (optional)
174433d6423SLionel Sambuc * Pathname - Object pathname (optional)
175433d6423SLionel Sambuc * ExternalParams - List of parameters to pass to method,
176433d6423SLionel Sambuc * terminated by NULL. May be NULL
177433d6423SLionel Sambuc * if no parameters are being passed.
178433d6423SLionel Sambuc * ReturnBuffer - Where to put method's return value (if
179433d6423SLionel Sambuc * any). If NULL, no value is returned.
180433d6423SLionel Sambuc *
181433d6423SLionel Sambuc * RETURN: Status
182433d6423SLionel Sambuc *
183433d6423SLionel Sambuc * DESCRIPTION: Find and evaluate the given object, passing the given
184433d6423SLionel Sambuc * parameters if necessary. One of "Handle" or "Pathname" must
185433d6423SLionel Sambuc * be valid (non-null)
186433d6423SLionel Sambuc *
187433d6423SLionel Sambuc ******************************************************************************/
188433d6423SLionel Sambuc
189433d6423SLionel Sambuc ACPI_STATUS
190433d6423SLionel Sambuc AcpiEvaluateObject (
191433d6423SLionel Sambuc ACPI_HANDLE Handle,
192433d6423SLionel Sambuc ACPI_STRING Pathname,
193433d6423SLionel Sambuc ACPI_OBJECT_LIST *ExternalParams,
194433d6423SLionel Sambuc ACPI_BUFFER *ReturnBuffer)
195433d6423SLionel Sambuc {
196433d6423SLionel Sambuc ACPI_STATUS Status;
197433d6423SLionel Sambuc ACPI_EVALUATE_INFO *Info;
198433d6423SLionel Sambuc ACPI_SIZE BufferSpaceNeeded;
199433d6423SLionel Sambuc UINT32 i;
200433d6423SLionel Sambuc
201433d6423SLionel Sambuc
202433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
203433d6423SLionel Sambuc
204433d6423SLionel Sambuc
205433d6423SLionel Sambuc /* Allocate and initialize the evaluation information block */
206433d6423SLionel Sambuc
207433d6423SLionel Sambuc Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
208433d6423SLionel Sambuc if (!Info)
209433d6423SLionel Sambuc {
210433d6423SLionel Sambuc return_ACPI_STATUS (AE_NO_MEMORY);
211433d6423SLionel Sambuc }
212433d6423SLionel Sambuc
213433d6423SLionel Sambuc /* Convert and validate the device handle */
214433d6423SLionel Sambuc
215433d6423SLionel Sambuc Info->PrefixNode = AcpiNsValidateHandle (Handle);
216433d6423SLionel Sambuc if (!Info->PrefixNode)
217433d6423SLionel Sambuc {
218433d6423SLionel Sambuc Status = AE_BAD_PARAMETER;
219433d6423SLionel Sambuc goto Cleanup;
220433d6423SLionel Sambuc }
221433d6423SLionel Sambuc
222433d6423SLionel Sambuc /*
223*29492bb7SDavid van Moolenbroek * Get the actual namespace node for the target object.
224*29492bb7SDavid van Moolenbroek * Handles these cases:
225*29492bb7SDavid van Moolenbroek *
226*29492bb7SDavid van Moolenbroek * 1) Null node, valid pathname from root (absolute path)
227*29492bb7SDavid van Moolenbroek * 2) Node and valid pathname (path relative to Node)
228*29492bb7SDavid van Moolenbroek * 3) Node, Null pathname
229433d6423SLionel Sambuc */
230433d6423SLionel Sambuc if ((Pathname) &&
231*29492bb7SDavid van Moolenbroek (ACPI_IS_ROOT_PREFIX (Pathname[0])))
232433d6423SLionel Sambuc {
233433d6423SLionel Sambuc /* The path is fully qualified, just evaluate by name */
234433d6423SLionel Sambuc
235433d6423SLionel Sambuc Info->PrefixNode = NULL;
236433d6423SLionel Sambuc }
237433d6423SLionel Sambuc else if (!Handle)
238433d6423SLionel Sambuc {
239433d6423SLionel Sambuc /*
240433d6423SLionel Sambuc * A handle is optional iff a fully qualified pathname is specified.
241433d6423SLionel Sambuc * Since we've already handled fully qualified names above, this is
242*29492bb7SDavid van Moolenbroek * an error.
243433d6423SLionel Sambuc */
244433d6423SLionel Sambuc if (!Pathname)
245433d6423SLionel Sambuc {
246433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
247433d6423SLionel Sambuc "Both Handle and Pathname are NULL"));
248433d6423SLionel Sambuc }
249433d6423SLionel Sambuc else
250433d6423SLionel Sambuc {
251433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
252433d6423SLionel Sambuc "Null Handle with relative pathname [%s]", Pathname));
253433d6423SLionel Sambuc }
254433d6423SLionel Sambuc
255433d6423SLionel Sambuc Status = AE_BAD_PARAMETER;
256*29492bb7SDavid van Moolenbroek goto Cleanup;
257433d6423SLionel Sambuc }
258*29492bb7SDavid van Moolenbroek
259*29492bb7SDavid van Moolenbroek Info->RelativePathname = Pathname;
260*29492bb7SDavid van Moolenbroek
261*29492bb7SDavid van Moolenbroek /*
262*29492bb7SDavid van Moolenbroek * Convert all external objects passed as arguments to the
263*29492bb7SDavid van Moolenbroek * internal version(s).
264*29492bb7SDavid van Moolenbroek */
265*29492bb7SDavid van Moolenbroek if (ExternalParams && ExternalParams->Count)
266433d6423SLionel Sambuc {
267*29492bb7SDavid van Moolenbroek Info->ParamCount = (UINT16) ExternalParams->Count;
268*29492bb7SDavid van Moolenbroek
269*29492bb7SDavid van Moolenbroek /* Warn on impossible argument count */
270*29492bb7SDavid van Moolenbroek
271*29492bb7SDavid van Moolenbroek if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
272*29492bb7SDavid van Moolenbroek {
273*29492bb7SDavid van Moolenbroek ACPI_WARN_PREDEFINED ((AE_INFO, Pathname, ACPI_WARN_ALWAYS,
274*29492bb7SDavid van Moolenbroek "Excess arguments (%u) - using only %u",
275*29492bb7SDavid van Moolenbroek Info->ParamCount, ACPI_METHOD_NUM_ARGS));
276*29492bb7SDavid van Moolenbroek
277*29492bb7SDavid van Moolenbroek Info->ParamCount = ACPI_METHOD_NUM_ARGS;
278*29492bb7SDavid van Moolenbroek }
279*29492bb7SDavid van Moolenbroek
280*29492bb7SDavid van Moolenbroek /*
281*29492bb7SDavid van Moolenbroek * Allocate a new parameter block for the internal objects
282*29492bb7SDavid van Moolenbroek * Add 1 to count to allow for null terminated internal list
283*29492bb7SDavid van Moolenbroek */
284*29492bb7SDavid van Moolenbroek Info->Parameters = ACPI_ALLOCATE_ZEROED (
285*29492bb7SDavid van Moolenbroek ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
286*29492bb7SDavid van Moolenbroek if (!Info->Parameters)
287*29492bb7SDavid van Moolenbroek {
288*29492bb7SDavid van Moolenbroek Status = AE_NO_MEMORY;
289*29492bb7SDavid van Moolenbroek goto Cleanup;
290*29492bb7SDavid van Moolenbroek }
291*29492bb7SDavid van Moolenbroek
292*29492bb7SDavid van Moolenbroek /* Convert each external object in the list to an internal object */
293*29492bb7SDavid van Moolenbroek
294*29492bb7SDavid van Moolenbroek for (i = 0; i < Info->ParamCount; i++)
295*29492bb7SDavid van Moolenbroek {
296*29492bb7SDavid van Moolenbroek Status = AcpiUtCopyEobjectToIobject (
297*29492bb7SDavid van Moolenbroek &ExternalParams->Pointer[i], &Info->Parameters[i]);
298*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
299*29492bb7SDavid van Moolenbroek {
300*29492bb7SDavid van Moolenbroek goto Cleanup;
301*29492bb7SDavid van Moolenbroek }
302*29492bb7SDavid van Moolenbroek }
303*29492bb7SDavid van Moolenbroek
304*29492bb7SDavid van Moolenbroek Info->Parameters[Info->ParamCount] = NULL;
305*29492bb7SDavid van Moolenbroek }
306*29492bb7SDavid van Moolenbroek
307*29492bb7SDavid van Moolenbroek
308*29492bb7SDavid van Moolenbroek #if 0
309*29492bb7SDavid van Moolenbroek
310*29492bb7SDavid van Moolenbroek /*
311*29492bb7SDavid van Moolenbroek * Begin incoming argument count analysis. Check for too few args
312*29492bb7SDavid van Moolenbroek * and too many args.
313*29492bb7SDavid van Moolenbroek */
314*29492bb7SDavid van Moolenbroek
315*29492bb7SDavid van Moolenbroek switch (AcpiNsGetType (Info->Node))
316*29492bb7SDavid van Moolenbroek {
317*29492bb7SDavid van Moolenbroek case ACPI_TYPE_METHOD:
318*29492bb7SDavid van Moolenbroek
319*29492bb7SDavid van Moolenbroek /* Check incoming argument count against the method definition */
320*29492bb7SDavid van Moolenbroek
321*29492bb7SDavid van Moolenbroek if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
322*29492bb7SDavid van Moolenbroek {
323*29492bb7SDavid van Moolenbroek ACPI_ERROR ((AE_INFO,
324*29492bb7SDavid van Moolenbroek "Insufficient arguments (%u) - %u are required",
325*29492bb7SDavid van Moolenbroek Info->ParamCount,
326*29492bb7SDavid van Moolenbroek Info->ObjDesc->Method.ParamCount));
327*29492bb7SDavid van Moolenbroek
328*29492bb7SDavid van Moolenbroek Status = AE_MISSING_ARGUMENTS;
329*29492bb7SDavid van Moolenbroek goto Cleanup;
330*29492bb7SDavid van Moolenbroek }
331*29492bb7SDavid van Moolenbroek
332*29492bb7SDavid van Moolenbroek else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
333*29492bb7SDavid van Moolenbroek {
334*29492bb7SDavid van Moolenbroek ACPI_WARNING ((AE_INFO,
335*29492bb7SDavid van Moolenbroek "Excess arguments (%u) - only %u are required",
336*29492bb7SDavid van Moolenbroek Info->ParamCount,
337*29492bb7SDavid van Moolenbroek Info->ObjDesc->Method.ParamCount));
338*29492bb7SDavid van Moolenbroek
339*29492bb7SDavid van Moolenbroek /* Just pass the required number of arguments */
340*29492bb7SDavid van Moolenbroek
341*29492bb7SDavid van Moolenbroek Info->ParamCount = Info->ObjDesc->Method.ParamCount;
342*29492bb7SDavid van Moolenbroek }
343*29492bb7SDavid van Moolenbroek
344*29492bb7SDavid van Moolenbroek /*
345*29492bb7SDavid van Moolenbroek * Any incoming external objects to be passed as arguments to the
346*29492bb7SDavid van Moolenbroek * method must be converted to internal objects
347*29492bb7SDavid van Moolenbroek */
348*29492bb7SDavid van Moolenbroek if (Info->ParamCount)
349*29492bb7SDavid van Moolenbroek {
350*29492bb7SDavid van Moolenbroek /*
351*29492bb7SDavid van Moolenbroek * Allocate a new parameter block for the internal objects
352*29492bb7SDavid van Moolenbroek * Add 1 to count to allow for null terminated internal list
353*29492bb7SDavid van Moolenbroek */
354*29492bb7SDavid van Moolenbroek Info->Parameters = ACPI_ALLOCATE_ZEROED (
355*29492bb7SDavid van Moolenbroek ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
356*29492bb7SDavid van Moolenbroek if (!Info->Parameters)
357*29492bb7SDavid van Moolenbroek {
358*29492bb7SDavid van Moolenbroek Status = AE_NO_MEMORY;
359*29492bb7SDavid van Moolenbroek goto Cleanup;
360*29492bb7SDavid van Moolenbroek }
361*29492bb7SDavid van Moolenbroek
362*29492bb7SDavid van Moolenbroek /* Convert each external object in the list to an internal object */
363*29492bb7SDavid van Moolenbroek
364*29492bb7SDavid van Moolenbroek for (i = 0; i < Info->ParamCount; i++)
365*29492bb7SDavid van Moolenbroek {
366*29492bb7SDavid van Moolenbroek Status = AcpiUtCopyEobjectToIobject (
367*29492bb7SDavid van Moolenbroek &ExternalParams->Pointer[i], &Info->Parameters[i]);
368*29492bb7SDavid van Moolenbroek if (ACPI_FAILURE (Status))
369*29492bb7SDavid van Moolenbroek {
370*29492bb7SDavid van Moolenbroek goto Cleanup;
371*29492bb7SDavid van Moolenbroek }
372*29492bb7SDavid van Moolenbroek }
373*29492bb7SDavid van Moolenbroek
374*29492bb7SDavid van Moolenbroek Info->Parameters[Info->ParamCount] = NULL;
375*29492bb7SDavid van Moolenbroek }
376*29492bb7SDavid van Moolenbroek break;
377*29492bb7SDavid van Moolenbroek
378*29492bb7SDavid van Moolenbroek default:
379*29492bb7SDavid van Moolenbroek
380*29492bb7SDavid van Moolenbroek /* Warn if arguments passed to an object that is not a method */
381*29492bb7SDavid van Moolenbroek
382*29492bb7SDavid van Moolenbroek if (Info->ParamCount)
383*29492bb7SDavid van Moolenbroek {
384*29492bb7SDavid van Moolenbroek ACPI_WARNING ((AE_INFO,
385*29492bb7SDavid van Moolenbroek "%u arguments were passed to a non-method ACPI object",
386*29492bb7SDavid van Moolenbroek Info->ParamCount));
387*29492bb7SDavid van Moolenbroek }
388*29492bb7SDavid van Moolenbroek break;
389*29492bb7SDavid van Moolenbroek }
390*29492bb7SDavid van Moolenbroek
391*29492bb7SDavid van Moolenbroek #endif
392*29492bb7SDavid van Moolenbroek
393*29492bb7SDavid van Moolenbroek
394*29492bb7SDavid van Moolenbroek /* Now we can evaluate the object */
395433d6423SLionel Sambuc
396433d6423SLionel Sambuc Status = AcpiNsEvaluate (Info);
397433d6423SLionel Sambuc
398433d6423SLionel Sambuc /*
399433d6423SLionel Sambuc * If we are expecting a return value, and all went well above,
400433d6423SLionel Sambuc * copy the return value to an external object.
401433d6423SLionel Sambuc */
402433d6423SLionel Sambuc if (ReturnBuffer)
403433d6423SLionel Sambuc {
404433d6423SLionel Sambuc if (!Info->ReturnObject)
405433d6423SLionel Sambuc {
406433d6423SLionel Sambuc ReturnBuffer->Length = 0;
407433d6423SLionel Sambuc }
408433d6423SLionel Sambuc else
409433d6423SLionel Sambuc {
410433d6423SLionel Sambuc if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
411433d6423SLionel Sambuc ACPI_DESC_TYPE_NAMED)
412433d6423SLionel Sambuc {
413433d6423SLionel Sambuc /*
414433d6423SLionel Sambuc * If we received a NS Node as a return object, this means that
415433d6423SLionel Sambuc * the object we are evaluating has nothing interesting to
416433d6423SLionel Sambuc * return (such as a mutex, etc.) We return an error because
417433d6423SLionel Sambuc * these types are essentially unsupported by this interface.
418433d6423SLionel Sambuc * We don't check up front because this makes it easier to add
419433d6423SLionel Sambuc * support for various types at a later date if necessary.
420433d6423SLionel Sambuc */
421433d6423SLionel Sambuc Status = AE_TYPE;
422433d6423SLionel Sambuc Info->ReturnObject = NULL; /* No need to delete a NS Node */
423433d6423SLionel Sambuc ReturnBuffer->Length = 0;
424433d6423SLionel Sambuc }
425433d6423SLionel Sambuc
426433d6423SLionel Sambuc if (ACPI_SUCCESS (Status))
427433d6423SLionel Sambuc {
428433d6423SLionel Sambuc /* Dereference Index and RefOf references */
429433d6423SLionel Sambuc
430433d6423SLionel Sambuc AcpiNsResolveReferences (Info);
431433d6423SLionel Sambuc
432433d6423SLionel Sambuc /* Get the size of the returned object */
433433d6423SLionel Sambuc
434433d6423SLionel Sambuc Status = AcpiUtGetObjectSize (Info->ReturnObject,
435433d6423SLionel Sambuc &BufferSpaceNeeded);
436433d6423SLionel Sambuc if (ACPI_SUCCESS (Status))
437433d6423SLionel Sambuc {
438433d6423SLionel Sambuc /* Validate/Allocate/Clear caller buffer */
439433d6423SLionel Sambuc
440433d6423SLionel Sambuc Status = AcpiUtInitializeBuffer (ReturnBuffer,
441433d6423SLionel Sambuc BufferSpaceNeeded);
442433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
443433d6423SLionel Sambuc {
444433d6423SLionel Sambuc /*
445433d6423SLionel Sambuc * Caller's buffer is too small or a new one can't
446433d6423SLionel Sambuc * be allocated
447433d6423SLionel Sambuc */
448433d6423SLionel Sambuc ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
449433d6423SLionel Sambuc "Needed buffer size %X, %s\n",
450433d6423SLionel Sambuc (UINT32) BufferSpaceNeeded,
451433d6423SLionel Sambuc AcpiFormatException (Status)));
452433d6423SLionel Sambuc }
453433d6423SLionel Sambuc else
454433d6423SLionel Sambuc {
455433d6423SLionel Sambuc /* We have enough space for the object, build it */
456433d6423SLionel Sambuc
457433d6423SLionel Sambuc Status = AcpiUtCopyIobjectToEobject (Info->ReturnObject,
458433d6423SLionel Sambuc ReturnBuffer);
459433d6423SLionel Sambuc }
460433d6423SLionel Sambuc }
461433d6423SLionel Sambuc }
462433d6423SLionel Sambuc }
463433d6423SLionel Sambuc }
464433d6423SLionel Sambuc
465433d6423SLionel Sambuc if (Info->ReturnObject)
466433d6423SLionel Sambuc {
467433d6423SLionel Sambuc /*
468433d6423SLionel Sambuc * Delete the internal return object. NOTE: Interpreter must be
469433d6423SLionel Sambuc * locked to avoid race condition.
470433d6423SLionel Sambuc */
471433d6423SLionel Sambuc AcpiExEnterInterpreter ();
472433d6423SLionel Sambuc
473433d6423SLionel Sambuc /* Remove one reference on the return object (should delete it) */
474433d6423SLionel Sambuc
475433d6423SLionel Sambuc AcpiUtRemoveReference (Info->ReturnObject);
476433d6423SLionel Sambuc AcpiExExitInterpreter ();
477433d6423SLionel Sambuc }
478433d6423SLionel Sambuc
479433d6423SLionel Sambuc
480433d6423SLionel Sambuc Cleanup:
481433d6423SLionel Sambuc
482433d6423SLionel Sambuc /* Free the input parameter list (if we created one) */
483433d6423SLionel Sambuc
484433d6423SLionel Sambuc if (Info->Parameters)
485433d6423SLionel Sambuc {
486433d6423SLionel Sambuc /* Free the allocated parameter block */
487433d6423SLionel Sambuc
488433d6423SLionel Sambuc AcpiUtDeleteInternalObjectList (Info->Parameters);
489433d6423SLionel Sambuc }
490433d6423SLionel Sambuc
491433d6423SLionel Sambuc ACPI_FREE (Info);
492433d6423SLionel Sambuc return_ACPI_STATUS (Status);
493433d6423SLionel Sambuc }
494433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiEvaluateObject)495433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
496433d6423SLionel Sambuc
497433d6423SLionel Sambuc
498433d6423SLionel Sambuc /*******************************************************************************
499433d6423SLionel Sambuc *
500433d6423SLionel Sambuc * FUNCTION: AcpiNsResolveReferences
501433d6423SLionel Sambuc *
502433d6423SLionel Sambuc * PARAMETERS: Info - Evaluation info block
503433d6423SLionel Sambuc *
504433d6423SLionel Sambuc * RETURN: Info->ReturnObject is replaced with the dereferenced object
505433d6423SLionel Sambuc *
506433d6423SLionel Sambuc * DESCRIPTION: Dereference certain reference objects. Called before an
507433d6423SLionel Sambuc * internal return object is converted to an external ACPI_OBJECT.
508433d6423SLionel Sambuc *
509433d6423SLionel Sambuc * Performs an automatic dereference of Index and RefOf reference objects.
510433d6423SLionel Sambuc * These reference objects are not supported by the ACPI_OBJECT, so this is a
511433d6423SLionel Sambuc * last resort effort to return something useful. Also, provides compatibility
512433d6423SLionel Sambuc * with other ACPI implementations.
513433d6423SLionel Sambuc *
514433d6423SLionel Sambuc * NOTE: does not handle references within returned package objects or nested
515433d6423SLionel Sambuc * references, but this support could be added later if found to be necessary.
516433d6423SLionel Sambuc *
517433d6423SLionel Sambuc ******************************************************************************/
518433d6423SLionel Sambuc
519433d6423SLionel Sambuc static void
520433d6423SLionel Sambuc AcpiNsResolveReferences (
521433d6423SLionel Sambuc ACPI_EVALUATE_INFO *Info)
522433d6423SLionel Sambuc {
523433d6423SLionel Sambuc ACPI_OPERAND_OBJECT *ObjDesc = NULL;
524433d6423SLionel Sambuc ACPI_NAMESPACE_NODE *Node;
525433d6423SLionel Sambuc
526433d6423SLionel Sambuc
527433d6423SLionel Sambuc /* We are interested in reference objects only */
528433d6423SLionel Sambuc
529433d6423SLionel Sambuc if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
530433d6423SLionel Sambuc {
531433d6423SLionel Sambuc return;
532433d6423SLionel Sambuc }
533433d6423SLionel Sambuc
534433d6423SLionel Sambuc /*
535433d6423SLionel Sambuc * Two types of references are supported - those created by Index and
536433d6423SLionel Sambuc * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
537433d6423SLionel Sambuc * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
538433d6423SLionel Sambuc * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
539433d6423SLionel Sambuc * an ACPI_OBJECT.
540433d6423SLionel Sambuc */
541433d6423SLionel Sambuc switch (Info->ReturnObject->Reference.Class)
542433d6423SLionel Sambuc {
543433d6423SLionel Sambuc case ACPI_REFCLASS_INDEX:
544433d6423SLionel Sambuc
545433d6423SLionel Sambuc ObjDesc = *(Info->ReturnObject->Reference.Where);
546433d6423SLionel Sambuc break;
547433d6423SLionel Sambuc
548433d6423SLionel Sambuc case ACPI_REFCLASS_REFOF:
549433d6423SLionel Sambuc
550433d6423SLionel Sambuc Node = Info->ReturnObject->Reference.Object;
551433d6423SLionel Sambuc if (Node)
552433d6423SLionel Sambuc {
553433d6423SLionel Sambuc ObjDesc = Node->Object;
554433d6423SLionel Sambuc }
555433d6423SLionel Sambuc break;
556433d6423SLionel Sambuc
557433d6423SLionel Sambuc default:
558*29492bb7SDavid van Moolenbroek
559433d6423SLionel Sambuc return;
560433d6423SLionel Sambuc }
561433d6423SLionel Sambuc
562433d6423SLionel Sambuc /* Replace the existing reference object */
563433d6423SLionel Sambuc
564433d6423SLionel Sambuc if (ObjDesc)
565433d6423SLionel Sambuc {
566433d6423SLionel Sambuc AcpiUtAddReference (ObjDesc);
567433d6423SLionel Sambuc AcpiUtRemoveReference (Info->ReturnObject);
568433d6423SLionel Sambuc Info->ReturnObject = ObjDesc;
569433d6423SLionel Sambuc }
570433d6423SLionel Sambuc
571433d6423SLionel Sambuc return;
572433d6423SLionel Sambuc }
573433d6423SLionel Sambuc
574433d6423SLionel Sambuc
575433d6423SLionel Sambuc /*******************************************************************************
576433d6423SLionel Sambuc *
577433d6423SLionel Sambuc * FUNCTION: AcpiWalkNamespace
578433d6423SLionel Sambuc *
579433d6423SLionel Sambuc * PARAMETERS: Type - ACPI_OBJECT_TYPE to search for
580433d6423SLionel Sambuc * StartObject - Handle in namespace where search begins
581433d6423SLionel Sambuc * MaxDepth - Depth to which search is to reach
582*29492bb7SDavid van Moolenbroek * DescendingCallback - Called during tree descent
583433d6423SLionel Sambuc * when an object of "Type" is found
584*29492bb7SDavid van Moolenbroek * AscendingCallback - Called during tree ascent
585433d6423SLionel Sambuc * when an object of "Type" is found
586433d6423SLionel Sambuc * Context - Passed to user function(s) above
587433d6423SLionel Sambuc * ReturnValue - Location where return value of
588433d6423SLionel Sambuc * UserFunction is put if terminated early
589433d6423SLionel Sambuc *
590433d6423SLionel Sambuc * RETURNS Return value from the UserFunction if terminated early.
591433d6423SLionel Sambuc * Otherwise, returns NULL.
592433d6423SLionel Sambuc *
593433d6423SLionel Sambuc * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
594433d6423SLionel Sambuc * starting (and ending) at the object specified by StartHandle.
595433d6423SLionel Sambuc * The callback function is called whenever an object that matches
596433d6423SLionel Sambuc * the type parameter is found. If the callback function returns
597433d6423SLionel Sambuc * a non-zero value, the search is terminated immediately and this
598433d6423SLionel Sambuc * value is returned to the caller.
599433d6423SLionel Sambuc *
600433d6423SLionel Sambuc * The point of this procedure is to provide a generic namespace
601433d6423SLionel Sambuc * walk routine that can be called from multiple places to
602433d6423SLionel Sambuc * provide multiple services; the callback function(s) can be
603433d6423SLionel Sambuc * tailored to each task, whether it is a print function,
604433d6423SLionel Sambuc * a compare function, etc.
605433d6423SLionel Sambuc *
606433d6423SLionel Sambuc ******************************************************************************/
607433d6423SLionel Sambuc
608433d6423SLionel Sambuc ACPI_STATUS
AcpiWalkNamespace(ACPI_OBJECT_TYPE Type,ACPI_HANDLE StartObject,UINT32 MaxDepth,ACPI_WALK_CALLBACK DescendingCallback,ACPI_WALK_CALLBACK AscendingCallback,void * Context,void ** ReturnValue)609433d6423SLionel Sambuc AcpiWalkNamespace (
610433d6423SLionel Sambuc ACPI_OBJECT_TYPE Type,
611433d6423SLionel Sambuc ACPI_HANDLE StartObject,
612433d6423SLionel Sambuc UINT32 MaxDepth,
613*29492bb7SDavid van Moolenbroek ACPI_WALK_CALLBACK DescendingCallback,
614*29492bb7SDavid van Moolenbroek ACPI_WALK_CALLBACK AscendingCallback,
615433d6423SLionel Sambuc void *Context,
616433d6423SLionel Sambuc void **ReturnValue)
617433d6423SLionel Sambuc {
618433d6423SLionel Sambuc ACPI_STATUS Status;
619433d6423SLionel Sambuc
620433d6423SLionel Sambuc
621433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
622433d6423SLionel Sambuc
623433d6423SLionel Sambuc
624433d6423SLionel Sambuc /* Parameter validation */
625433d6423SLionel Sambuc
626433d6423SLionel Sambuc if ((Type > ACPI_TYPE_LOCAL_MAX) ||
627433d6423SLionel Sambuc (!MaxDepth) ||
628*29492bb7SDavid van Moolenbroek (!DescendingCallback && !AscendingCallback))
629433d6423SLionel Sambuc {
630433d6423SLionel Sambuc return_ACPI_STATUS (AE_BAD_PARAMETER);
631433d6423SLionel Sambuc }
632433d6423SLionel Sambuc
633433d6423SLionel Sambuc /*
634433d6423SLionel Sambuc * Need to acquire the namespace reader lock to prevent interference
635433d6423SLionel Sambuc * with any concurrent table unloads (which causes the deletion of
636433d6423SLionel Sambuc * namespace objects). We cannot allow the deletion of a namespace node
637433d6423SLionel Sambuc * while the user function is using it. The exception to this are the
638433d6423SLionel Sambuc * nodes created and deleted during control method execution -- these
639433d6423SLionel Sambuc * nodes are marked as temporary nodes and are ignored by the namespace
640433d6423SLionel Sambuc * walk. Thus, control methods can be executed while holding the
641433d6423SLionel Sambuc * namespace deletion lock (and the user function can execute control
642433d6423SLionel Sambuc * methods.)
643433d6423SLionel Sambuc */
644433d6423SLionel Sambuc Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
645433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
646433d6423SLionel Sambuc {
647*29492bb7SDavid van Moolenbroek return_ACPI_STATUS (Status);
648433d6423SLionel Sambuc }
649433d6423SLionel Sambuc
650433d6423SLionel Sambuc /*
651433d6423SLionel Sambuc * Lock the namespace around the walk. The namespace will be
652433d6423SLionel Sambuc * unlocked/locked around each call to the user function - since the user
653433d6423SLionel Sambuc * function must be allowed to make ACPICA calls itself (for example, it
654433d6423SLionel Sambuc * will typically execute control methods during device enumeration.)
655433d6423SLionel Sambuc */
656433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
657433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
658433d6423SLionel Sambuc {
659433d6423SLionel Sambuc goto UnlockAndExit;
660433d6423SLionel Sambuc }
661433d6423SLionel Sambuc
662*29492bb7SDavid van Moolenbroek /* Now we can validate the starting node */
663433d6423SLionel Sambuc
664*29492bb7SDavid van Moolenbroek if (!AcpiNsValidateHandle (StartObject))
665*29492bb7SDavid van Moolenbroek {
666*29492bb7SDavid van Moolenbroek Status = AE_BAD_PARAMETER;
667*29492bb7SDavid van Moolenbroek goto UnlockAndExit2;
668*29492bb7SDavid van Moolenbroek }
669*29492bb7SDavid van Moolenbroek
670*29492bb7SDavid van Moolenbroek Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
671*29492bb7SDavid van Moolenbroek ACPI_NS_WALK_UNLOCK, DescendingCallback,
672*29492bb7SDavid van Moolenbroek AscendingCallback, Context, ReturnValue);
673*29492bb7SDavid van Moolenbroek
674*29492bb7SDavid van Moolenbroek UnlockAndExit2:
675433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
676433d6423SLionel Sambuc
677433d6423SLionel Sambuc UnlockAndExit:
678433d6423SLionel Sambuc (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
679433d6423SLionel Sambuc return_ACPI_STATUS (Status);
680433d6423SLionel Sambuc }
681433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiWalkNamespace)682433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
683433d6423SLionel Sambuc
684433d6423SLionel Sambuc
685433d6423SLionel Sambuc /*******************************************************************************
686433d6423SLionel Sambuc *
687433d6423SLionel Sambuc * FUNCTION: AcpiNsGetDeviceCallback
688433d6423SLionel Sambuc *
689433d6423SLionel Sambuc * PARAMETERS: Callback from AcpiGetDevice
690433d6423SLionel Sambuc *
691433d6423SLionel Sambuc * RETURN: Status
692433d6423SLionel Sambuc *
693433d6423SLionel Sambuc * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
694433d6423SLionel Sambuc * present devices, or if they specified a HID, it filters based
695433d6423SLionel Sambuc * on that.
696433d6423SLionel Sambuc *
697433d6423SLionel Sambuc ******************************************************************************/
698433d6423SLionel Sambuc
699433d6423SLionel Sambuc static ACPI_STATUS
700433d6423SLionel Sambuc AcpiNsGetDeviceCallback (
701433d6423SLionel Sambuc ACPI_HANDLE ObjHandle,
702433d6423SLionel Sambuc UINT32 NestingLevel,
703433d6423SLionel Sambuc void *Context,
704433d6423SLionel Sambuc void **ReturnValue)
705433d6423SLionel Sambuc {
706433d6423SLionel Sambuc ACPI_GET_DEVICES_INFO *Info = Context;
707433d6423SLionel Sambuc ACPI_STATUS Status;
708433d6423SLionel Sambuc ACPI_NAMESPACE_NODE *Node;
709433d6423SLionel Sambuc UINT32 Flags;
710*29492bb7SDavid van Moolenbroek ACPI_PNP_DEVICE_ID *Hid;
711*29492bb7SDavid van Moolenbroek ACPI_PNP_DEVICE_ID_LIST *Cid;
712433d6423SLionel Sambuc UINT32 i;
713433d6423SLionel Sambuc BOOLEAN Found;
714433d6423SLionel Sambuc int NoMatch;
715433d6423SLionel Sambuc
716433d6423SLionel Sambuc
717433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
718433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
719433d6423SLionel Sambuc {
720433d6423SLionel Sambuc return (Status);
721433d6423SLionel Sambuc }
722433d6423SLionel Sambuc
723433d6423SLionel Sambuc Node = AcpiNsValidateHandle (ObjHandle);
724433d6423SLionel Sambuc Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
725433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
726433d6423SLionel Sambuc {
727433d6423SLionel Sambuc return (Status);
728433d6423SLionel Sambuc }
729433d6423SLionel Sambuc
730433d6423SLionel Sambuc if (!Node)
731433d6423SLionel Sambuc {
732433d6423SLionel Sambuc return (AE_BAD_PARAMETER);
733433d6423SLionel Sambuc }
734433d6423SLionel Sambuc
735433d6423SLionel Sambuc /*
736433d6423SLionel Sambuc * First, filter based on the device HID and CID.
737433d6423SLionel Sambuc *
738433d6423SLionel Sambuc * 01/2010: For this case where a specific HID is requested, we don't
739433d6423SLionel Sambuc * want to run _STA until we have an actual HID match. Thus, we will
740433d6423SLionel Sambuc * not unnecessarily execute _STA on devices for which the caller
741433d6423SLionel Sambuc * doesn't care about. Previously, _STA was executed unconditionally
742433d6423SLionel Sambuc * on all devices found here.
743433d6423SLionel Sambuc *
744433d6423SLionel Sambuc * A side-effect of this change is that now we will continue to search
745433d6423SLionel Sambuc * for a matching HID even under device trees where the parent device
746433d6423SLionel Sambuc * would have returned a _STA that indicates it is not present or
747433d6423SLionel Sambuc * not functioning (thus aborting the search on that branch).
748433d6423SLionel Sambuc */
749433d6423SLionel Sambuc if (Info->Hid != NULL)
750433d6423SLionel Sambuc {
751433d6423SLionel Sambuc Status = AcpiUtExecute_HID (Node, &Hid);
752433d6423SLionel Sambuc if (Status == AE_NOT_FOUND)
753433d6423SLionel Sambuc {
754433d6423SLionel Sambuc return (AE_OK);
755433d6423SLionel Sambuc }
756433d6423SLionel Sambuc else if (ACPI_FAILURE (Status))
757433d6423SLionel Sambuc {
758433d6423SLionel Sambuc return (AE_CTRL_DEPTH);
759433d6423SLionel Sambuc }
760433d6423SLionel Sambuc
761433d6423SLionel Sambuc NoMatch = ACPI_STRCMP (Hid->String, Info->Hid);
762433d6423SLionel Sambuc ACPI_FREE (Hid);
763433d6423SLionel Sambuc
764433d6423SLionel Sambuc if (NoMatch)
765433d6423SLionel Sambuc {
766433d6423SLionel Sambuc /*
767433d6423SLionel Sambuc * HID does not match, attempt match within the
768433d6423SLionel Sambuc * list of Compatible IDs (CIDs)
769433d6423SLionel Sambuc */
770433d6423SLionel Sambuc Status = AcpiUtExecute_CID (Node, &Cid);
771433d6423SLionel Sambuc if (Status == AE_NOT_FOUND)
772433d6423SLionel Sambuc {
773433d6423SLionel Sambuc return (AE_OK);
774433d6423SLionel Sambuc }
775433d6423SLionel Sambuc else if (ACPI_FAILURE (Status))
776433d6423SLionel Sambuc {
777433d6423SLionel Sambuc return (AE_CTRL_DEPTH);
778433d6423SLionel Sambuc }
779433d6423SLionel Sambuc
780433d6423SLionel Sambuc /* Walk the CID list */
781433d6423SLionel Sambuc
782433d6423SLionel Sambuc Found = FALSE;
783433d6423SLionel Sambuc for (i = 0; i < Cid->Count; i++)
784433d6423SLionel Sambuc {
785433d6423SLionel Sambuc if (ACPI_STRCMP (Cid->Ids[i].String, Info->Hid) == 0)
786433d6423SLionel Sambuc {
787433d6423SLionel Sambuc /* Found a matching CID */
788433d6423SLionel Sambuc
789433d6423SLionel Sambuc Found = TRUE;
790433d6423SLionel Sambuc break;
791433d6423SLionel Sambuc }
792433d6423SLionel Sambuc }
793433d6423SLionel Sambuc
794433d6423SLionel Sambuc ACPI_FREE (Cid);
795433d6423SLionel Sambuc if (!Found)
796433d6423SLionel Sambuc {
797433d6423SLionel Sambuc return (AE_OK);
798433d6423SLionel Sambuc }
799433d6423SLionel Sambuc }
800433d6423SLionel Sambuc }
801433d6423SLionel Sambuc
802433d6423SLionel Sambuc /* Run _STA to determine if device is present */
803433d6423SLionel Sambuc
804433d6423SLionel Sambuc Status = AcpiUtExecute_STA (Node, &Flags);
805433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
806433d6423SLionel Sambuc {
807433d6423SLionel Sambuc return (AE_CTRL_DEPTH);
808433d6423SLionel Sambuc }
809433d6423SLionel Sambuc
810433d6423SLionel Sambuc if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
811433d6423SLionel Sambuc !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
812433d6423SLionel Sambuc {
813433d6423SLionel Sambuc /*
814433d6423SLionel Sambuc * Don't examine the children of the device only when the
815433d6423SLionel Sambuc * device is neither present nor functional. See ACPI spec,
816433d6423SLionel Sambuc * description of _STA for more information.
817433d6423SLionel Sambuc */
818433d6423SLionel Sambuc return (AE_CTRL_DEPTH);
819433d6423SLionel Sambuc }
820433d6423SLionel Sambuc
821433d6423SLionel Sambuc /* We have a valid device, invoke the user function */
822433d6423SLionel Sambuc
823433d6423SLionel Sambuc Status = Info->UserFunction (ObjHandle, NestingLevel, Info->Context,
824433d6423SLionel Sambuc ReturnValue);
825433d6423SLionel Sambuc return (Status);
826433d6423SLionel Sambuc }
827433d6423SLionel Sambuc
828433d6423SLionel Sambuc
829433d6423SLionel Sambuc /*******************************************************************************
830433d6423SLionel Sambuc *
831433d6423SLionel Sambuc * FUNCTION: AcpiGetDevices
832433d6423SLionel Sambuc *
833433d6423SLionel Sambuc * PARAMETERS: HID - HID to search for. Can be NULL.
834433d6423SLionel Sambuc * UserFunction - Called when a matching object is found
835433d6423SLionel Sambuc * Context - Passed to user function
836433d6423SLionel Sambuc * ReturnValue - Location where return value of
837433d6423SLionel Sambuc * UserFunction is put if terminated early
838433d6423SLionel Sambuc *
839433d6423SLionel Sambuc * RETURNS Return value from the UserFunction if terminated early.
840433d6423SLionel Sambuc * Otherwise, returns NULL.
841433d6423SLionel Sambuc *
842433d6423SLionel Sambuc * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
843433d6423SLionel Sambuc * starting (and ending) at the object specified by StartHandle.
844433d6423SLionel Sambuc * The UserFunction is called whenever an object of type
845433d6423SLionel Sambuc * Device is found. If the user function returns
846433d6423SLionel Sambuc * a non-zero value, the search is terminated immediately and this
847433d6423SLionel Sambuc * value is returned to the caller.
848433d6423SLionel Sambuc *
849433d6423SLionel Sambuc * This is a wrapper for WalkNamespace, but the callback performs
850433d6423SLionel Sambuc * additional filtering. Please see AcpiNsGetDeviceCallback.
851433d6423SLionel Sambuc *
852433d6423SLionel Sambuc ******************************************************************************/
853433d6423SLionel Sambuc
854433d6423SLionel Sambuc ACPI_STATUS
AcpiGetDevices(char * HID,ACPI_WALK_CALLBACK UserFunction,void * Context,void ** ReturnValue)855433d6423SLionel Sambuc AcpiGetDevices (
856433d6423SLionel Sambuc char *HID,
857433d6423SLionel Sambuc ACPI_WALK_CALLBACK UserFunction,
858433d6423SLionel Sambuc void *Context,
859433d6423SLionel Sambuc void **ReturnValue)
860433d6423SLionel Sambuc {
861433d6423SLionel Sambuc ACPI_STATUS Status;
862433d6423SLionel Sambuc ACPI_GET_DEVICES_INFO Info;
863433d6423SLionel Sambuc
864433d6423SLionel Sambuc
865433d6423SLionel Sambuc ACPI_FUNCTION_TRACE (AcpiGetDevices);
866433d6423SLionel Sambuc
867433d6423SLionel Sambuc
868433d6423SLionel Sambuc /* Parameter validation */
869433d6423SLionel Sambuc
870433d6423SLionel Sambuc if (!UserFunction)
871433d6423SLionel Sambuc {
872433d6423SLionel Sambuc return_ACPI_STATUS (AE_BAD_PARAMETER);
873433d6423SLionel Sambuc }
874433d6423SLionel Sambuc
875433d6423SLionel Sambuc /*
876433d6423SLionel Sambuc * We're going to call their callback from OUR callback, so we need
877433d6423SLionel Sambuc * to know what it is, and their context parameter.
878433d6423SLionel Sambuc */
879433d6423SLionel Sambuc Info.Hid = HID;
880433d6423SLionel Sambuc Info.Context = Context;
881433d6423SLionel Sambuc Info.UserFunction = UserFunction;
882433d6423SLionel Sambuc
883433d6423SLionel Sambuc /*
884433d6423SLionel Sambuc * Lock the namespace around the walk.
885433d6423SLionel Sambuc * The namespace will be unlocked/locked around each call
886433d6423SLionel Sambuc * to the user function - since this function
887433d6423SLionel Sambuc * must be allowed to make Acpi calls itself.
888433d6423SLionel Sambuc */
889433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
890433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
891433d6423SLionel Sambuc {
892433d6423SLionel Sambuc return_ACPI_STATUS (Status);
893433d6423SLionel Sambuc }
894433d6423SLionel Sambuc
895433d6423SLionel Sambuc Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
896433d6423SLionel Sambuc ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
897433d6423SLionel Sambuc AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
898433d6423SLionel Sambuc
899433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
900433d6423SLionel Sambuc return_ACPI_STATUS (Status);
901433d6423SLionel Sambuc }
902433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiGetDevices)903433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiGetDevices)
904433d6423SLionel Sambuc
905433d6423SLionel Sambuc
906433d6423SLionel Sambuc /*******************************************************************************
907433d6423SLionel Sambuc *
908433d6423SLionel Sambuc * FUNCTION: AcpiAttachData
909433d6423SLionel Sambuc *
910433d6423SLionel Sambuc * PARAMETERS: ObjHandle - Namespace node
911433d6423SLionel Sambuc * Handler - Handler for this attachment
912433d6423SLionel Sambuc * Data - Pointer to data to be attached
913433d6423SLionel Sambuc *
914433d6423SLionel Sambuc * RETURN: Status
915433d6423SLionel Sambuc *
916433d6423SLionel Sambuc * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
917433d6423SLionel Sambuc *
918433d6423SLionel Sambuc ******************************************************************************/
919433d6423SLionel Sambuc
920433d6423SLionel Sambuc ACPI_STATUS
921433d6423SLionel Sambuc AcpiAttachData (
922433d6423SLionel Sambuc ACPI_HANDLE ObjHandle,
923433d6423SLionel Sambuc ACPI_OBJECT_HANDLER Handler,
924433d6423SLionel Sambuc void *Data)
925433d6423SLionel Sambuc {
926433d6423SLionel Sambuc ACPI_NAMESPACE_NODE *Node;
927433d6423SLionel Sambuc ACPI_STATUS Status;
928433d6423SLionel Sambuc
929433d6423SLionel Sambuc
930433d6423SLionel Sambuc /* Parameter validation */
931433d6423SLionel Sambuc
932433d6423SLionel Sambuc if (!ObjHandle ||
933433d6423SLionel Sambuc !Handler ||
934433d6423SLionel Sambuc !Data)
935433d6423SLionel Sambuc {
936433d6423SLionel Sambuc return (AE_BAD_PARAMETER);
937433d6423SLionel Sambuc }
938433d6423SLionel Sambuc
939433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
940433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
941433d6423SLionel Sambuc {
942433d6423SLionel Sambuc return (Status);
943433d6423SLionel Sambuc }
944433d6423SLionel Sambuc
945433d6423SLionel Sambuc /* Convert and validate the handle */
946433d6423SLionel Sambuc
947433d6423SLionel Sambuc Node = AcpiNsValidateHandle (ObjHandle);
948433d6423SLionel Sambuc if (!Node)
949433d6423SLionel Sambuc {
950433d6423SLionel Sambuc Status = AE_BAD_PARAMETER;
951433d6423SLionel Sambuc goto UnlockAndExit;
952433d6423SLionel Sambuc }
953433d6423SLionel Sambuc
954433d6423SLionel Sambuc Status = AcpiNsAttachData (Node, Handler, Data);
955433d6423SLionel Sambuc
956433d6423SLionel Sambuc UnlockAndExit:
957433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
958433d6423SLionel Sambuc return (Status);
959433d6423SLionel Sambuc }
960433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiAttachData)961433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiAttachData)
962433d6423SLionel Sambuc
963433d6423SLionel Sambuc
964433d6423SLionel Sambuc /*******************************************************************************
965433d6423SLionel Sambuc *
966433d6423SLionel Sambuc * FUNCTION: AcpiDetachData
967433d6423SLionel Sambuc *
968433d6423SLionel Sambuc * PARAMETERS: ObjHandle - Namespace node handle
969433d6423SLionel Sambuc * Handler - Handler used in call to AcpiAttachData
970433d6423SLionel Sambuc *
971433d6423SLionel Sambuc * RETURN: Status
972433d6423SLionel Sambuc *
973433d6423SLionel Sambuc * DESCRIPTION: Remove data that was previously attached to a node.
974433d6423SLionel Sambuc *
975433d6423SLionel Sambuc ******************************************************************************/
976433d6423SLionel Sambuc
977433d6423SLionel Sambuc ACPI_STATUS
978433d6423SLionel Sambuc AcpiDetachData (
979433d6423SLionel Sambuc ACPI_HANDLE ObjHandle,
980433d6423SLionel Sambuc ACPI_OBJECT_HANDLER Handler)
981433d6423SLionel Sambuc {
982433d6423SLionel Sambuc ACPI_NAMESPACE_NODE *Node;
983433d6423SLionel Sambuc ACPI_STATUS Status;
984433d6423SLionel Sambuc
985433d6423SLionel Sambuc
986433d6423SLionel Sambuc /* Parameter validation */
987433d6423SLionel Sambuc
988433d6423SLionel Sambuc if (!ObjHandle ||
989433d6423SLionel Sambuc !Handler)
990433d6423SLionel Sambuc {
991433d6423SLionel Sambuc return (AE_BAD_PARAMETER);
992433d6423SLionel Sambuc }
993433d6423SLionel Sambuc
994433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
995433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
996433d6423SLionel Sambuc {
997433d6423SLionel Sambuc return (Status);
998433d6423SLionel Sambuc }
999433d6423SLionel Sambuc
1000433d6423SLionel Sambuc /* Convert and validate the handle */
1001433d6423SLionel Sambuc
1002433d6423SLionel Sambuc Node = AcpiNsValidateHandle (ObjHandle);
1003433d6423SLionel Sambuc if (!Node)
1004433d6423SLionel Sambuc {
1005433d6423SLionel Sambuc Status = AE_BAD_PARAMETER;
1006433d6423SLionel Sambuc goto UnlockAndExit;
1007433d6423SLionel Sambuc }
1008433d6423SLionel Sambuc
1009433d6423SLionel Sambuc Status = AcpiNsDetachData (Node, Handler);
1010433d6423SLionel Sambuc
1011433d6423SLionel Sambuc UnlockAndExit:
1012433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1013433d6423SLionel Sambuc return (Status);
1014433d6423SLionel Sambuc }
1015433d6423SLionel Sambuc
ACPI_EXPORT_SYMBOL(AcpiDetachData)1016433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiDetachData)
1017433d6423SLionel Sambuc
1018433d6423SLionel Sambuc
1019433d6423SLionel Sambuc /*******************************************************************************
1020433d6423SLionel Sambuc *
1021433d6423SLionel Sambuc * FUNCTION: AcpiGetData
1022433d6423SLionel Sambuc *
1023433d6423SLionel Sambuc * PARAMETERS: ObjHandle - Namespace node
1024433d6423SLionel Sambuc * Handler - Handler used in call to AttachData
1025433d6423SLionel Sambuc * Data - Where the data is returned
1026433d6423SLionel Sambuc *
1027433d6423SLionel Sambuc * RETURN: Status
1028433d6423SLionel Sambuc *
1029433d6423SLionel Sambuc * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
1030433d6423SLionel Sambuc *
1031433d6423SLionel Sambuc ******************************************************************************/
1032433d6423SLionel Sambuc
1033433d6423SLionel Sambuc ACPI_STATUS
1034433d6423SLionel Sambuc AcpiGetData (
1035433d6423SLionel Sambuc ACPI_HANDLE ObjHandle,
1036433d6423SLionel Sambuc ACPI_OBJECT_HANDLER Handler,
1037433d6423SLionel Sambuc void **Data)
1038433d6423SLionel Sambuc {
1039433d6423SLionel Sambuc ACPI_NAMESPACE_NODE *Node;
1040433d6423SLionel Sambuc ACPI_STATUS Status;
1041433d6423SLionel Sambuc
1042433d6423SLionel Sambuc
1043433d6423SLionel Sambuc /* Parameter validation */
1044433d6423SLionel Sambuc
1045433d6423SLionel Sambuc if (!ObjHandle ||
1046433d6423SLionel Sambuc !Handler ||
1047433d6423SLionel Sambuc !Data)
1048433d6423SLionel Sambuc {
1049433d6423SLionel Sambuc return (AE_BAD_PARAMETER);
1050433d6423SLionel Sambuc }
1051433d6423SLionel Sambuc
1052433d6423SLionel Sambuc Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
1053433d6423SLionel Sambuc if (ACPI_FAILURE (Status))
1054433d6423SLionel Sambuc {
1055433d6423SLionel Sambuc return (Status);
1056433d6423SLionel Sambuc }
1057433d6423SLionel Sambuc
1058433d6423SLionel Sambuc /* Convert and validate the handle */
1059433d6423SLionel Sambuc
1060433d6423SLionel Sambuc Node = AcpiNsValidateHandle (ObjHandle);
1061433d6423SLionel Sambuc if (!Node)
1062433d6423SLionel Sambuc {
1063433d6423SLionel Sambuc Status = AE_BAD_PARAMETER;
1064433d6423SLionel Sambuc goto UnlockAndExit;
1065433d6423SLionel Sambuc }
1066433d6423SLionel Sambuc
1067433d6423SLionel Sambuc Status = AcpiNsGetAttachedData (Node, Handler, Data);
1068433d6423SLionel Sambuc
1069433d6423SLionel Sambuc UnlockAndExit:
1070433d6423SLionel Sambuc (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
1071433d6423SLionel Sambuc return (Status);
1072433d6423SLionel Sambuc }
1073433d6423SLionel Sambuc
1074433d6423SLionel Sambuc ACPI_EXPORT_SYMBOL (AcpiGetData)
1075