xref: /netbsd-src/sys/external/bsd/acpica/dist/namespace/nsxfeval.c (revision 2c7d7e3ca2e4f0b675c6c58e614f6aede66c678e)
128c506b8Sjruoho /*******************************************************************************
228c506b8Sjruoho  *
328c506b8Sjruoho  * Module Name: nsxfeval - Public interfaces to the ACPI subsystem
428c506b8Sjruoho  *                         ACPI Object evaluation interfaces
528c506b8Sjruoho  *
628c506b8Sjruoho  ******************************************************************************/
728c506b8Sjruoho 
8159c4e26Sjruoho /*
9*2c7d7e3cSchristos  * Copyright (C) 2000 - 2023, Intel Corp.
1028c506b8Sjruoho  * All rights reserved.
1128c506b8Sjruoho  *
12159c4e26Sjruoho  * Redistribution and use in source and binary forms, with or without
13159c4e26Sjruoho  * modification, are permitted provided that the following conditions
14159c4e26Sjruoho  * are met:
15159c4e26Sjruoho  * 1. Redistributions of source code must retain the above copyright
16159c4e26Sjruoho  *    notice, this list of conditions, and the following disclaimer,
17159c4e26Sjruoho  *    without modification.
18159c4e26Sjruoho  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19159c4e26Sjruoho  *    substantially similar to the "NO WARRANTY" disclaimer below
20159c4e26Sjruoho  *    ("Disclaimer") and any redistribution must be conditioned upon
21159c4e26Sjruoho  *    including a substantially similar Disclaimer requirement for further
22159c4e26Sjruoho  *    binary redistribution.
23159c4e26Sjruoho  * 3. Neither the names of the above-listed copyright holders nor the names
24159c4e26Sjruoho  *    of any contributors may be used to endorse or promote products derived
25159c4e26Sjruoho  *    from this software without specific prior written permission.
2628c506b8Sjruoho  *
27159c4e26Sjruoho  * Alternatively, this software may be distributed under the terms of the
28159c4e26Sjruoho  * GNU General Public License ("GPL") version 2 as published by the Free
29159c4e26Sjruoho  * Software Foundation.
3028c506b8Sjruoho  *
31159c4e26Sjruoho  * NO WARRANTY
32159c4e26Sjruoho  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33159c4e26Sjruoho  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3498244dcfSchristos  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
35159c4e26Sjruoho  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36159c4e26Sjruoho  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37159c4e26Sjruoho  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38159c4e26Sjruoho  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39159c4e26Sjruoho  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40159c4e26Sjruoho  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41159c4e26Sjruoho  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42159c4e26Sjruoho  * POSSIBILITY OF SUCH DAMAGES.
43159c4e26Sjruoho  */
4428c506b8Sjruoho 
45a2c051a9Schristos #define EXPORT_ACPI_INTERFACES
4628c506b8Sjruoho 
4728c506b8Sjruoho #include "acpi.h"
4828c506b8Sjruoho #include "accommon.h"
4928c506b8Sjruoho #include "acnamesp.h"
5028c506b8Sjruoho #include "acinterp.h"
5128c506b8Sjruoho 
5228c506b8Sjruoho 
5328c506b8Sjruoho #define _COMPONENT          ACPI_NAMESPACE
5428c506b8Sjruoho         ACPI_MODULE_NAME    ("nsxfeval")
5528c506b8Sjruoho 
5628c506b8Sjruoho /* Local prototypes */
5728c506b8Sjruoho 
5828c506b8Sjruoho static void
5928c506b8Sjruoho AcpiNsResolveReferences (
6028c506b8Sjruoho     ACPI_EVALUATE_INFO      *Info);
6128c506b8Sjruoho 
6228c506b8Sjruoho 
6328c506b8Sjruoho /*******************************************************************************
6428c506b8Sjruoho  *
6528c506b8Sjruoho  * FUNCTION:    AcpiEvaluateObjectTyped
6628c506b8Sjruoho  *
6728c506b8Sjruoho  * PARAMETERS:  Handle              - Object handle (optional)
6828c506b8Sjruoho  *              Pathname            - Object pathname (optional)
69f45f09e8Schristos  *              ExternalParams      - List of parameters to pass to a method,
7028c506b8Sjruoho  *                                    terminated by NULL. May be NULL
7128c506b8Sjruoho  *                                    if no parameters are being passed.
72f45f09e8Schristos  *              ReturnBuffer        - Where to put the object return value (if
73f45f09e8Schristos  *                                    any). Required.
7428c506b8Sjruoho  *              ReturnType          - Expected type of return object
7528c506b8Sjruoho  *
7628c506b8Sjruoho  * RETURN:      Status
7728c506b8Sjruoho  *
7828c506b8Sjruoho  * DESCRIPTION: Find and evaluate the given object, passing the given
7928c506b8Sjruoho  *              parameters if necessary. One of "Handle" or "Pathname" must
8028c506b8Sjruoho  *              be valid (non-null)
8128c506b8Sjruoho  *
8228c506b8Sjruoho  ******************************************************************************/
8328c506b8Sjruoho 
8428c506b8Sjruoho ACPI_STATUS
AcpiEvaluateObjectTyped(ACPI_HANDLE Handle,ACPI_CONST_STRING Pathname,ACPI_OBJECT_LIST * ExternalParams,ACPI_BUFFER * ReturnBuffer,ACPI_OBJECT_TYPE ReturnType)8528c506b8Sjruoho AcpiEvaluateObjectTyped (
8628c506b8Sjruoho     ACPI_HANDLE             Handle,
87716c1ee0Sjruoho     ACPI_CONST_STRING       Pathname,
8828c506b8Sjruoho     ACPI_OBJECT_LIST        *ExternalParams,
8928c506b8Sjruoho     ACPI_BUFFER             *ReturnBuffer,
9028c506b8Sjruoho     ACPI_OBJECT_TYPE        ReturnType)
9128c506b8Sjruoho {
9228c506b8Sjruoho     ACPI_STATUS             Status;
93a2c051a9Schristos     BOOLEAN                 FreeBufferOnError = FALSE;
94ae01dbf5Schristos     ACPI_HANDLE             TargetHandle;
95ae01dbf5Schristos     char                    *FullPathname;
9628c506b8Sjruoho 
972489d3bdSrin 
9828c506b8Sjruoho     ACPI_FUNCTION_TRACE (AcpiEvaluateObjectTyped);
9928c506b8Sjruoho 
10028c506b8Sjruoho 
10128c506b8Sjruoho     /* Return buffer must be valid */
10228c506b8Sjruoho 
10328c506b8Sjruoho     if (!ReturnBuffer)
10428c506b8Sjruoho     {
10528c506b8Sjruoho         return_ACPI_STATUS (AE_BAD_PARAMETER);
10628c506b8Sjruoho     }
10728c506b8Sjruoho 
10828c506b8Sjruoho     if (ReturnBuffer->Length == ACPI_ALLOCATE_BUFFER)
10928c506b8Sjruoho     {
110a2c051a9Schristos         FreeBufferOnError = TRUE;
11128c506b8Sjruoho     }
11228c506b8Sjruoho 
113f45f09e8Schristos     /* Get a handle here, in order to build an error message if needed */
114f45f09e8Schristos 
115f45f09e8Schristos     TargetHandle = Handle;
116f45f09e8Schristos     if (Pathname)
117f45f09e8Schristos     {
118ae01dbf5Schristos         Status = AcpiGetHandle (Handle, Pathname, &TargetHandle);
11928c506b8Sjruoho         if (ACPI_FAILURE (Status))
12028c506b8Sjruoho         {
12128c506b8Sjruoho             return_ACPI_STATUS (Status);
12228c506b8Sjruoho         }
123f45f09e8Schristos     }
12428c506b8Sjruoho 
125ae01dbf5Schristos     FullPathname = AcpiNsGetExternalPathname (TargetHandle);
126ae01dbf5Schristos     if (!FullPathname)
127ae01dbf5Schristos     {
128ae01dbf5Schristos         return_ACPI_STATUS (AE_NO_MEMORY);
129ae01dbf5Schristos     }
130ae01dbf5Schristos 
131ae01dbf5Schristos     /* Evaluate the object */
132ae01dbf5Schristos 
133ae01dbf5Schristos     Status = AcpiEvaluateObject (TargetHandle, NULL, ExternalParams,
134ae01dbf5Schristos         ReturnBuffer);
135ae01dbf5Schristos     if (ACPI_FAILURE (Status))
136ae01dbf5Schristos     {
137ae01dbf5Schristos         goto Exit;
138ae01dbf5Schristos     }
139ae01dbf5Schristos 
140ae01dbf5Schristos     /* Type ANY means "don't care about return value type" */
14128c506b8Sjruoho 
14228c506b8Sjruoho     if (ReturnType == ACPI_TYPE_ANY)
14328c506b8Sjruoho     {
144ae01dbf5Schristos         goto Exit;
14528c506b8Sjruoho     }
14628c506b8Sjruoho 
14728c506b8Sjruoho     if (ReturnBuffer->Length == 0)
14828c506b8Sjruoho     {
14928c506b8Sjruoho         /* Error because caller specifically asked for a return value */
15028c506b8Sjruoho 
151ae01dbf5Schristos         ACPI_ERROR ((AE_INFO, "%s did not return any object",
152ae01dbf5Schristos             FullPathname));
153ae01dbf5Schristos         Status = AE_NULL_OBJECT;
154ae01dbf5Schristos         goto Exit;
15528c506b8Sjruoho     }
15628c506b8Sjruoho 
15728c506b8Sjruoho     /* Examine the object type returned from EvaluateObject */
15828c506b8Sjruoho 
15928c506b8Sjruoho     if (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type == ReturnType)
16028c506b8Sjruoho     {
161ae01dbf5Schristos         goto Exit;
16228c506b8Sjruoho     }
16328c506b8Sjruoho 
16428c506b8Sjruoho     /* Return object type does not match requested type */
16528c506b8Sjruoho 
16628c506b8Sjruoho     ACPI_ERROR ((AE_INFO,
167ae01dbf5Schristos         "Incorrect return type from %s - received [%s], requested [%s]",
168ae01dbf5Schristos         FullPathname,
16928c506b8Sjruoho         AcpiUtGetTypeName (((ACPI_OBJECT *) ReturnBuffer->Pointer)->Type),
17028c506b8Sjruoho         AcpiUtGetTypeName (ReturnType)));
17128c506b8Sjruoho 
172a2c051a9Schristos     if (FreeBufferOnError)
17328c506b8Sjruoho     {
174a2c051a9Schristos         /*
175a2c051a9Schristos          * Free a buffer created via ACPI_ALLOCATE_BUFFER.
176a2c051a9Schristos          * Note: We use AcpiOsFree here because AcpiOsAllocate was used
177a2c051a9Schristos          * to allocate the buffer. This purposefully bypasses the
178a2c051a9Schristos          * (optionally enabled) allocation tracking mechanism since we
179a2c051a9Schristos          * only want to track internal allocations.
180a2c051a9Schristos          */
18128c506b8Sjruoho         AcpiOsFree (ReturnBuffer->Pointer);
18228c506b8Sjruoho         ReturnBuffer->Pointer = NULL;
18328c506b8Sjruoho     }
18428c506b8Sjruoho 
18528c506b8Sjruoho     ReturnBuffer->Length = 0;
186ae01dbf5Schristos     Status = AE_TYPE;
187ae01dbf5Schristos 
188ae01dbf5Schristos Exit:
189ae01dbf5Schristos     ACPI_FREE (FullPathname);
190ae01dbf5Schristos     return_ACPI_STATUS (Status);
19128c506b8Sjruoho }
19228c506b8Sjruoho 
ACPI_EXPORT_SYMBOL(AcpiEvaluateObjectTyped)19328c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiEvaluateObjectTyped)
19428c506b8Sjruoho 
19528c506b8Sjruoho 
19628c506b8Sjruoho /*******************************************************************************
19728c506b8Sjruoho  *
19828c506b8Sjruoho  * FUNCTION:    AcpiEvaluateObject
19928c506b8Sjruoho  *
20028c506b8Sjruoho  * PARAMETERS:  Handle              - Object handle (optional)
20128c506b8Sjruoho  *              Pathname            - Object pathname (optional)
20228c506b8Sjruoho  *              ExternalParams      - List of parameters to pass to method,
20328c506b8Sjruoho  *                                    terminated by NULL. May be NULL
20428c506b8Sjruoho  *                                    if no parameters are being passed.
20528c506b8Sjruoho  *              ReturnBuffer        - Where to put method's return value (if
20628c506b8Sjruoho  *                                    any). If NULL, no value is returned.
20728c506b8Sjruoho  *
20828c506b8Sjruoho  * RETURN:      Status
20928c506b8Sjruoho  *
21028c506b8Sjruoho  * DESCRIPTION: Find and evaluate the given object, passing the given
21128c506b8Sjruoho  *              parameters if necessary. One of "Handle" or "Pathname" must
21228c506b8Sjruoho  *              be valid (non-null)
21328c506b8Sjruoho  *
21428c506b8Sjruoho  ******************************************************************************/
21528c506b8Sjruoho 
21628c506b8Sjruoho ACPI_STATUS
21728c506b8Sjruoho AcpiEvaluateObject (
21828c506b8Sjruoho     ACPI_HANDLE             Handle,
219716c1ee0Sjruoho     ACPI_CONST_STRING       Pathname,
22028c506b8Sjruoho     ACPI_OBJECT_LIST        *ExternalParams,
22128c506b8Sjruoho     ACPI_BUFFER             *ReturnBuffer)
22228c506b8Sjruoho {
22328c506b8Sjruoho     ACPI_STATUS             Status;
22428c506b8Sjruoho     ACPI_EVALUATE_INFO      *Info;
22528c506b8Sjruoho     ACPI_SIZE               BufferSpaceNeeded;
22628c506b8Sjruoho     UINT32                  i;
22728c506b8Sjruoho 
22828c506b8Sjruoho 
22928c506b8Sjruoho     ACPI_FUNCTION_TRACE (AcpiEvaluateObject);
23028c506b8Sjruoho 
23128c506b8Sjruoho 
23228c506b8Sjruoho     /* Allocate and initialize the evaluation information block */
23328c506b8Sjruoho 
23428c506b8Sjruoho     Info = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EVALUATE_INFO));
23528c506b8Sjruoho     if (!Info)
23628c506b8Sjruoho     {
23728c506b8Sjruoho         return_ACPI_STATUS (AE_NO_MEMORY);
23828c506b8Sjruoho     }
23928c506b8Sjruoho 
24028c506b8Sjruoho     /* Convert and validate the device handle */
24128c506b8Sjruoho 
24228c506b8Sjruoho     Info->PrefixNode = AcpiNsValidateHandle (Handle);
24328c506b8Sjruoho     if (!Info->PrefixNode)
24428c506b8Sjruoho     {
24528c506b8Sjruoho         Status = AE_BAD_PARAMETER;
24628c506b8Sjruoho         goto Cleanup;
24728c506b8Sjruoho     }
24828c506b8Sjruoho 
24928c506b8Sjruoho     /*
250a2c051a9Schristos      * Get the actual namespace node for the target object.
251a2c051a9Schristos      * Handles these cases:
252a2c051a9Schristos      *
253a2c051a9Schristos      * 1) Null node, valid pathname from root (absolute path)
254a2c051a9Schristos      * 2) Node and valid pathname (path relative to Node)
255a2c051a9Schristos      * 3) Node, Null pathname
25628c506b8Sjruoho      */
25728c506b8Sjruoho     if ((Pathname) &&
258a2c051a9Schristos         (ACPI_IS_ROOT_PREFIX (Pathname[0])))
25928c506b8Sjruoho     {
26028c506b8Sjruoho         /* The path is fully qualified, just evaluate by name */
26128c506b8Sjruoho 
26228c506b8Sjruoho         Info->PrefixNode = NULL;
26328c506b8Sjruoho     }
26428c506b8Sjruoho     else if (!Handle)
26528c506b8Sjruoho     {
26628c506b8Sjruoho         /*
26728c506b8Sjruoho          * A handle is optional iff a fully qualified pathname is specified.
26828c506b8Sjruoho          * Since we've already handled fully qualified names above, this is
269a2c051a9Schristos          * an error.
27028c506b8Sjruoho          */
27128c506b8Sjruoho         if (!Pathname)
27228c506b8Sjruoho         {
27328c506b8Sjruoho             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
27428c506b8Sjruoho                 "Both Handle and Pathname are NULL"));
27528c506b8Sjruoho         }
27628c506b8Sjruoho         else
27728c506b8Sjruoho         {
27828c506b8Sjruoho             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
27928c506b8Sjruoho                 "Null Handle with relative pathname [%s]", Pathname));
28028c506b8Sjruoho         }
28128c506b8Sjruoho 
28228c506b8Sjruoho         Status = AE_BAD_PARAMETER;
283a2c051a9Schristos         goto Cleanup;
28428c506b8Sjruoho     }
285a2c051a9Schristos 
286a2c051a9Schristos     Info->RelativePathname = __UNCONST(Pathname);
287a2c051a9Schristos 
288a2c051a9Schristos     /*
289a2c051a9Schristos      * Convert all external objects passed as arguments to the
290a2c051a9Schristos      * internal version(s).
291a2c051a9Schristos      */
292a2c051a9Schristos     if (ExternalParams && ExternalParams->Count)
29328c506b8Sjruoho     {
294a2c051a9Schristos         Info->ParamCount = (UINT16) ExternalParams->Count;
295a2c051a9Schristos 
296a2c051a9Schristos         /* Warn on impossible argument count */
297a2c051a9Schristos 
298a2c051a9Schristos         if (Info->ParamCount > ACPI_METHOD_NUM_ARGS)
299a2c051a9Schristos         {
300a2c051a9Schristos             ACPI_WARN_PREDEFINED ((AE_INFO, __UNCONST(Pathname), ACPI_WARN_ALWAYS,
301a2c051a9Schristos                 "Excess arguments (%u) - using only %u",
302a2c051a9Schristos                 Info->ParamCount, ACPI_METHOD_NUM_ARGS));
303a2c051a9Schristos 
304a2c051a9Schristos             Info->ParamCount = ACPI_METHOD_NUM_ARGS;
305a2c051a9Schristos         }
306a2c051a9Schristos 
307a2c051a9Schristos         /*
308a2c051a9Schristos          * Allocate a new parameter block for the internal objects
309a2c051a9Schristos          * Add 1 to count to allow for null terminated internal list
310a2c051a9Schristos          */
311a2c051a9Schristos         Info->Parameters = ACPI_ALLOCATE_ZEROED (
312a2c051a9Schristos             ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
313a2c051a9Schristos         if (!Info->Parameters)
314a2c051a9Schristos         {
315a2c051a9Schristos             Status = AE_NO_MEMORY;
316a2c051a9Schristos             goto Cleanup;
317a2c051a9Schristos         }
318a2c051a9Schristos 
319a2c051a9Schristos         /* Convert each external object in the list to an internal object */
320a2c051a9Schristos 
321a2c051a9Schristos         for (i = 0; i < Info->ParamCount; i++)
322a2c051a9Schristos         {
323a2c051a9Schristos             Status = AcpiUtCopyEobjectToIobject (
324a2c051a9Schristos                 &ExternalParams->Pointer[i], &Info->Parameters[i]);
325a2c051a9Schristos             if (ACPI_FAILURE (Status))
326a2c051a9Schristos             {
327a2c051a9Schristos                 goto Cleanup;
328a2c051a9Schristos             }
329a2c051a9Schristos         }
330a2c051a9Schristos 
331a2c051a9Schristos         Info->Parameters[Info->ParamCount] = NULL;
332a2c051a9Schristos     }
333a2c051a9Schristos 
334a2c051a9Schristos 
33549c2f1f4Schristos #ifdef _FUTURE_FEATURE
336a2c051a9Schristos 
337a2c051a9Schristos     /*
338a2c051a9Schristos      * Begin incoming argument count analysis. Check for too few args
339a2c051a9Schristos      * and too many args.
340a2c051a9Schristos      */
341a2c051a9Schristos     switch (AcpiNsGetType (Info->Node))
342a2c051a9Schristos     {
343a2c051a9Schristos     case ACPI_TYPE_METHOD:
344a2c051a9Schristos 
345a2c051a9Schristos         /* Check incoming argument count against the method definition */
346a2c051a9Schristos 
347a2c051a9Schristos         if (Info->ObjDesc->Method.ParamCount > Info->ParamCount)
348a2c051a9Schristos         {
349a2c051a9Schristos             ACPI_ERROR ((AE_INFO,
350a2c051a9Schristos                 "Insufficient arguments (%u) - %u are required",
351a2c051a9Schristos                 Info->ParamCount,
352a2c051a9Schristos                 Info->ObjDesc->Method.ParamCount));
353a2c051a9Schristos 
354a2c051a9Schristos             Status = AE_MISSING_ARGUMENTS;
355a2c051a9Schristos             goto Cleanup;
356a2c051a9Schristos         }
357a2c051a9Schristos 
358a2c051a9Schristos         else if (Info->ObjDesc->Method.ParamCount < Info->ParamCount)
359a2c051a9Schristos         {
360a2c051a9Schristos             ACPI_WARNING ((AE_INFO,
361a2c051a9Schristos                 "Excess arguments (%u) - only %u are required",
362a2c051a9Schristos                 Info->ParamCount,
363a2c051a9Schristos                 Info->ObjDesc->Method.ParamCount));
364a2c051a9Schristos 
365a2c051a9Schristos             /* Just pass the required number of arguments */
366a2c051a9Schristos 
367a2c051a9Schristos             Info->ParamCount = Info->ObjDesc->Method.ParamCount;
368a2c051a9Schristos         }
369a2c051a9Schristos 
370a2c051a9Schristos         /*
371a2c051a9Schristos          * Any incoming external objects to be passed as arguments to the
372a2c051a9Schristos          * method must be converted to internal objects
373a2c051a9Schristos          */
374a2c051a9Schristos         if (Info->ParamCount)
375a2c051a9Schristos         {
376a2c051a9Schristos             /*
377a2c051a9Schristos              * Allocate a new parameter block for the internal objects
378a2c051a9Schristos              * Add 1 to count to allow for null terminated internal list
379a2c051a9Schristos              */
380a2c051a9Schristos             Info->Parameters = ACPI_ALLOCATE_ZEROED (
381a2c051a9Schristos                 ((ACPI_SIZE) Info->ParamCount + 1) * sizeof (void *));
382a2c051a9Schristos             if (!Info->Parameters)
383a2c051a9Schristos             {
384a2c051a9Schristos                 Status = AE_NO_MEMORY;
385a2c051a9Schristos                 goto Cleanup;
386a2c051a9Schristos             }
387a2c051a9Schristos 
388a2c051a9Schristos             /* Convert each external object in the list to an internal object */
389a2c051a9Schristos 
390a2c051a9Schristos             for (i = 0; i < Info->ParamCount; i++)
391a2c051a9Schristos             {
392a2c051a9Schristos                 Status = AcpiUtCopyEobjectToIobject (
393a2c051a9Schristos                     &ExternalParams->Pointer[i], &Info->Parameters[i]);
394a2c051a9Schristos                 if (ACPI_FAILURE (Status))
395a2c051a9Schristos                 {
396a2c051a9Schristos                     goto Cleanup;
397a2c051a9Schristos                 }
398a2c051a9Schristos             }
399a2c051a9Schristos 
400a2c051a9Schristos             Info->Parameters[Info->ParamCount] = NULL;
401a2c051a9Schristos         }
402a2c051a9Schristos         break;
403a2c051a9Schristos 
404a2c051a9Schristos     default:
405a2c051a9Schristos 
406a2c051a9Schristos         /* Warn if arguments passed to an object that is not a method */
407a2c051a9Schristos 
408a2c051a9Schristos         if (Info->ParamCount)
409a2c051a9Schristos         {
410a2c051a9Schristos             ACPI_WARNING ((AE_INFO,
411a2c051a9Schristos                 "%u arguments were passed to a non-method ACPI object",
412a2c051a9Schristos                 Info->ParamCount));
413a2c051a9Schristos         }
414a2c051a9Schristos         break;
415a2c051a9Schristos     }
416a2c051a9Schristos 
417a2c051a9Schristos #endif
418a2c051a9Schristos 
419a2c051a9Schristos 
420a2c051a9Schristos     /* Now we can evaluate the object */
42128c506b8Sjruoho 
42228c506b8Sjruoho     Status = AcpiNsEvaluate (Info);
42328c506b8Sjruoho 
42428c506b8Sjruoho     /*
42528c506b8Sjruoho      * If we are expecting a return value, and all went well above,
42628c506b8Sjruoho      * copy the return value to an external object.
42728c506b8Sjruoho      */
42849c2f1f4Schristos     if (!ReturnBuffer)
42928c506b8Sjruoho     {
43049c2f1f4Schristos         goto CleanupReturnObject;
43149c2f1f4Schristos     }
43249c2f1f4Schristos 
43328c506b8Sjruoho     if (!Info->ReturnObject)
43428c506b8Sjruoho     {
43528c506b8Sjruoho         ReturnBuffer->Length = 0;
43649c2f1f4Schristos         goto Cleanup;
43728c506b8Sjruoho     }
43849c2f1f4Schristos 
43928c506b8Sjruoho     if (ACPI_GET_DESCRIPTOR_TYPE (Info->ReturnObject) ==
44028c506b8Sjruoho         ACPI_DESC_TYPE_NAMED)
44128c506b8Sjruoho     {
44228c506b8Sjruoho         /*
44328c506b8Sjruoho          * If we received a NS Node as a return object, this means that
44428c506b8Sjruoho          * the object we are evaluating has nothing interesting to
44528c506b8Sjruoho          * return (such as a mutex, etc.)  We return an error because
44628c506b8Sjruoho          * these types are essentially unsupported by this interface.
44728c506b8Sjruoho          * We don't check up front because this makes it easier to add
44828c506b8Sjruoho          * support for various types at a later date if necessary.
44928c506b8Sjruoho          */
45028c506b8Sjruoho         Status = AE_TYPE;
45128c506b8Sjruoho         Info->ReturnObject = NULL;   /* No need to delete a NS Node */
45228c506b8Sjruoho         ReturnBuffer->Length = 0;
45328c506b8Sjruoho     }
45428c506b8Sjruoho 
45549c2f1f4Schristos     if (ACPI_FAILURE (Status))
45628c506b8Sjruoho     {
45749c2f1f4Schristos         goto CleanupReturnObject;
45849c2f1f4Schristos     }
45949c2f1f4Schristos 
46028c506b8Sjruoho     /* Dereference Index and RefOf references */
46128c506b8Sjruoho 
46228c506b8Sjruoho     AcpiNsResolveReferences (Info);
46328c506b8Sjruoho 
46428c506b8Sjruoho     /* Get the size of the returned object */
46528c506b8Sjruoho 
46628c506b8Sjruoho     Status = AcpiUtGetObjectSize (Info->ReturnObject,
46728c506b8Sjruoho         &BufferSpaceNeeded);
46828c506b8Sjruoho     if (ACPI_SUCCESS (Status))
46928c506b8Sjruoho     {
47028c506b8Sjruoho         /* Validate/Allocate/Clear caller buffer */
47128c506b8Sjruoho 
47228c506b8Sjruoho         Status = AcpiUtInitializeBuffer (ReturnBuffer,
47328c506b8Sjruoho             BufferSpaceNeeded);
47428c506b8Sjruoho         if (ACPI_FAILURE (Status))
47528c506b8Sjruoho         {
47628c506b8Sjruoho             /*
47728c506b8Sjruoho              * Caller's buffer is too small or a new one can't
47828c506b8Sjruoho              * be allocated
47928c506b8Sjruoho              */
48028c506b8Sjruoho             ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
48128c506b8Sjruoho                 "Needed buffer size %X, %s\n",
48228c506b8Sjruoho                 (UINT32) BufferSpaceNeeded,
48328c506b8Sjruoho                 AcpiFormatException (Status)));
48428c506b8Sjruoho         }
48528c506b8Sjruoho         else
48628c506b8Sjruoho         {
48728c506b8Sjruoho             /* We have enough space for the object, build it */
48828c506b8Sjruoho 
48981bd9c9cSchristos             Status = AcpiUtCopyIobjectToEobject (
49081bd9c9cSchristos                 Info->ReturnObject, ReturnBuffer);
49128c506b8Sjruoho         }
49228c506b8Sjruoho     }
49349c2f1f4Schristos 
49449c2f1f4Schristos CleanupReturnObject:
49528c506b8Sjruoho 
49628c506b8Sjruoho     if (Info->ReturnObject)
49728c506b8Sjruoho     {
49828c506b8Sjruoho         /*
49928c506b8Sjruoho          * Delete the internal return object. NOTE: Interpreter must be
50028c506b8Sjruoho          * locked to avoid race condition.
50128c506b8Sjruoho          */
50228c506b8Sjruoho         AcpiExEnterInterpreter ();
50328c506b8Sjruoho 
50428c506b8Sjruoho         /* Remove one reference on the return object (should delete it) */
50528c506b8Sjruoho 
50628c506b8Sjruoho         AcpiUtRemoveReference (Info->ReturnObject);
50728c506b8Sjruoho         AcpiExExitInterpreter ();
50828c506b8Sjruoho     }
50928c506b8Sjruoho 
51028c506b8Sjruoho 
51128c506b8Sjruoho Cleanup:
51228c506b8Sjruoho 
51328c506b8Sjruoho     /* Free the input parameter list (if we created one) */
51428c506b8Sjruoho 
51528c506b8Sjruoho     if (Info->Parameters)
51628c506b8Sjruoho     {
51728c506b8Sjruoho         /* Free the allocated parameter block */
51828c506b8Sjruoho 
51928c506b8Sjruoho         AcpiUtDeleteInternalObjectList (Info->Parameters);
52028c506b8Sjruoho     }
52128c506b8Sjruoho 
52228c506b8Sjruoho     ACPI_FREE (Info);
52328c506b8Sjruoho     return_ACPI_STATUS (Status);
52428c506b8Sjruoho }
52528c506b8Sjruoho 
ACPI_EXPORT_SYMBOL(AcpiEvaluateObject)52628c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiEvaluateObject)
52728c506b8Sjruoho 
52828c506b8Sjruoho 
52928c506b8Sjruoho /*******************************************************************************
53028c506b8Sjruoho  *
53128c506b8Sjruoho  * FUNCTION:    AcpiNsResolveReferences
53228c506b8Sjruoho  *
53328c506b8Sjruoho  * PARAMETERS:  Info                    - Evaluation info block
53428c506b8Sjruoho  *
53528c506b8Sjruoho  * RETURN:      Info->ReturnObject is replaced with the dereferenced object
53628c506b8Sjruoho  *
53728c506b8Sjruoho  * DESCRIPTION: Dereference certain reference objects. Called before an
53828c506b8Sjruoho  *              internal return object is converted to an external ACPI_OBJECT.
53928c506b8Sjruoho  *
54028c506b8Sjruoho  * Performs an automatic dereference of Index and RefOf reference objects.
54128c506b8Sjruoho  * These reference objects are not supported by the ACPI_OBJECT, so this is a
54228c506b8Sjruoho  * last resort effort to return something useful. Also, provides compatibility
54328c506b8Sjruoho  * with other ACPI implementations.
54428c506b8Sjruoho  *
54528c506b8Sjruoho  * NOTE: does not handle references within returned package objects or nested
54628c506b8Sjruoho  * references, but this support could be added later if found to be necessary.
54728c506b8Sjruoho  *
54828c506b8Sjruoho  ******************************************************************************/
54928c506b8Sjruoho 
55028c506b8Sjruoho static void
55128c506b8Sjruoho AcpiNsResolveReferences (
55228c506b8Sjruoho     ACPI_EVALUATE_INFO      *Info)
55328c506b8Sjruoho {
55428c506b8Sjruoho     ACPI_OPERAND_OBJECT     *ObjDesc = NULL;
55528c506b8Sjruoho     ACPI_NAMESPACE_NODE     *Node;
55628c506b8Sjruoho 
55728c506b8Sjruoho 
55828c506b8Sjruoho     /* We are interested in reference objects only */
55928c506b8Sjruoho 
56028c506b8Sjruoho     if ((Info->ReturnObject)->Common.Type != ACPI_TYPE_LOCAL_REFERENCE)
56128c506b8Sjruoho     {
56228c506b8Sjruoho         return;
56328c506b8Sjruoho     }
56428c506b8Sjruoho 
56528c506b8Sjruoho     /*
56628c506b8Sjruoho      * Two types of references are supported - those created by Index and
56728c506b8Sjruoho      * RefOf operators. A name reference (AML_NAMEPATH_OP) can be converted
56828c506b8Sjruoho      * to an ACPI_OBJECT, so it is not dereferenced here. A DdbHandle
56928c506b8Sjruoho      * (AML_LOAD_OP) cannot be dereferenced, nor can it be converted to
57028c506b8Sjruoho      * an ACPI_OBJECT.
57128c506b8Sjruoho      */
57228c506b8Sjruoho     switch (Info->ReturnObject->Reference.Class)
57328c506b8Sjruoho     {
57428c506b8Sjruoho     case ACPI_REFCLASS_INDEX:
57528c506b8Sjruoho 
57628c506b8Sjruoho         ObjDesc = *(Info->ReturnObject->Reference.Where);
57728c506b8Sjruoho         break;
57828c506b8Sjruoho 
57928c506b8Sjruoho     case ACPI_REFCLASS_REFOF:
58028c506b8Sjruoho 
58128c506b8Sjruoho         Node = Info->ReturnObject->Reference.Object;
58228c506b8Sjruoho         if (Node)
58328c506b8Sjruoho         {
58428c506b8Sjruoho             ObjDesc = Node->Object;
58528c506b8Sjruoho         }
58628c506b8Sjruoho         break;
58728c506b8Sjruoho 
58828c506b8Sjruoho     default:
589a2c051a9Schristos 
59028c506b8Sjruoho         return;
59128c506b8Sjruoho     }
59228c506b8Sjruoho 
59328c506b8Sjruoho     /* Replace the existing reference object */
59428c506b8Sjruoho 
59528c506b8Sjruoho     if (ObjDesc)
59628c506b8Sjruoho     {
59728c506b8Sjruoho         AcpiUtAddReference (ObjDesc);
59828c506b8Sjruoho         AcpiUtRemoveReference (Info->ReturnObject);
59928c506b8Sjruoho         Info->ReturnObject = ObjDesc;
60028c506b8Sjruoho     }
60128c506b8Sjruoho 
60228c506b8Sjruoho     return;
60328c506b8Sjruoho }
60428c506b8Sjruoho 
60528c506b8Sjruoho 
60628c506b8Sjruoho /*******************************************************************************
60728c506b8Sjruoho  *
60828c506b8Sjruoho  * FUNCTION:    AcpiWalkNamespace
60928c506b8Sjruoho  *
61028c506b8Sjruoho  * PARAMETERS:  Type                - ACPI_OBJECT_TYPE to search for
61128c506b8Sjruoho  *              StartObject         - Handle in namespace where search begins
61228c506b8Sjruoho  *              MaxDepth            - Depth to which search is to reach
613a2c051a9Schristos  *              DescendingCallback  - Called during tree descent
61428c506b8Sjruoho  *                                    when an object of "Type" is found
615a2c051a9Schristos  *              AscendingCallback   - Called during tree ascent
61628c506b8Sjruoho  *                                    when an object of "Type" is found
61728c506b8Sjruoho  *              Context             - Passed to user function(s) above
61828c506b8Sjruoho  *              ReturnValue         - Location where return value of
61928c506b8Sjruoho  *                                    UserFunction is put if terminated early
62028c506b8Sjruoho  *
62128c506b8Sjruoho  * RETURNS      Return value from the UserFunction if terminated early.
62228c506b8Sjruoho  *              Otherwise, returns NULL.
62328c506b8Sjruoho  *
62428c506b8Sjruoho  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
62528c506b8Sjruoho  *              starting (and ending) at the object specified by StartHandle.
62628c506b8Sjruoho  *              The callback function is called whenever an object that matches
62728c506b8Sjruoho  *              the type parameter is found. If the callback function returns
62828c506b8Sjruoho  *              a non-zero value, the search is terminated immediately and this
62928c506b8Sjruoho  *              value is returned to the caller.
63028c506b8Sjruoho  *
63128c506b8Sjruoho  *              The point of this procedure is to provide a generic namespace
63228c506b8Sjruoho  *              walk routine that can be called from multiple places to
63328c506b8Sjruoho  *              provide multiple services; the callback function(s) can be
63428c506b8Sjruoho  *              tailored to each task, whether it is a print function,
63528c506b8Sjruoho  *              a compare function, etc.
63628c506b8Sjruoho  *
63728c506b8Sjruoho  ******************************************************************************/
63828c506b8Sjruoho 
63928c506b8Sjruoho ACPI_STATUS
AcpiWalkNamespace(ACPI_OBJECT_TYPE Type,ACPI_HANDLE StartObject,UINT32 MaxDepth,ACPI_WALK_CALLBACK DescendingCallback,ACPI_WALK_CALLBACK AscendingCallback,void * Context,void ** ReturnValue)64028c506b8Sjruoho AcpiWalkNamespace (
64128c506b8Sjruoho     ACPI_OBJECT_TYPE        Type,
64228c506b8Sjruoho     ACPI_HANDLE             StartObject,
64328c506b8Sjruoho     UINT32                  MaxDepth,
644a2c051a9Schristos     ACPI_WALK_CALLBACK      DescendingCallback,
645a2c051a9Schristos     ACPI_WALK_CALLBACK      AscendingCallback,
64628c506b8Sjruoho     void                    *Context,
64728c506b8Sjruoho     void                    **ReturnValue)
64828c506b8Sjruoho {
64928c506b8Sjruoho     ACPI_STATUS             Status;
65028c506b8Sjruoho 
65128c506b8Sjruoho 
65228c506b8Sjruoho     ACPI_FUNCTION_TRACE (AcpiWalkNamespace);
65328c506b8Sjruoho 
65428c506b8Sjruoho 
65528c506b8Sjruoho     /* Parameter validation */
65628c506b8Sjruoho 
65728c506b8Sjruoho     if ((Type > ACPI_TYPE_LOCAL_MAX) ||
65828c506b8Sjruoho         (!MaxDepth)                  ||
659a2c051a9Schristos         (!DescendingCallback && !AscendingCallback))
66028c506b8Sjruoho     {
66128c506b8Sjruoho         return_ACPI_STATUS (AE_BAD_PARAMETER);
66228c506b8Sjruoho     }
66328c506b8Sjruoho 
66428c506b8Sjruoho     /*
66528c506b8Sjruoho      * Need to acquire the namespace reader lock to prevent interference
66628c506b8Sjruoho      * with any concurrent table unloads (which causes the deletion of
66728c506b8Sjruoho      * namespace objects). We cannot allow the deletion of a namespace node
66828c506b8Sjruoho      * while the user function is using it. The exception to this are the
66928c506b8Sjruoho      * nodes created and deleted during control method execution -- these
67028c506b8Sjruoho      * nodes are marked as temporary nodes and are ignored by the namespace
67128c506b8Sjruoho      * walk. Thus, control methods can be executed while holding the
67228c506b8Sjruoho      * namespace deletion lock (and the user function can execute control
67328c506b8Sjruoho      * methods.)
67428c506b8Sjruoho      */
67528c506b8Sjruoho     Status = AcpiUtAcquireReadLock (&AcpiGbl_NamespaceRwLock);
67628c506b8Sjruoho     if (ACPI_FAILURE (Status))
67728c506b8Sjruoho     {
678a2c051a9Schristos         return_ACPI_STATUS (Status);
67928c506b8Sjruoho     }
68028c506b8Sjruoho 
68128c506b8Sjruoho     /*
68228c506b8Sjruoho      * Lock the namespace around the walk. The namespace will be
68328c506b8Sjruoho      * unlocked/locked around each call to the user function - since the user
68428c506b8Sjruoho      * function must be allowed to make ACPICA calls itself (for example, it
68528c506b8Sjruoho      * will typically execute control methods during device enumeration.)
68628c506b8Sjruoho      */
68728c506b8Sjruoho     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
68828c506b8Sjruoho     if (ACPI_FAILURE (Status))
68928c506b8Sjruoho     {
69028c506b8Sjruoho         goto UnlockAndExit;
69128c506b8Sjruoho     }
69228c506b8Sjruoho 
693a2c051a9Schristos     /* Now we can validate the starting node */
69428c506b8Sjruoho 
695a2c051a9Schristos     if (!AcpiNsValidateHandle (StartObject))
696a2c051a9Schristos     {
697a2c051a9Schristos         Status = AE_BAD_PARAMETER;
698a2c051a9Schristos         goto UnlockAndExit2;
699a2c051a9Schristos     }
700a2c051a9Schristos 
701a2c051a9Schristos     Status = AcpiNsWalkNamespace (Type, StartObject, MaxDepth,
702a2c051a9Schristos         ACPI_NS_WALK_UNLOCK, DescendingCallback,
703a2c051a9Schristos         AscendingCallback, Context, ReturnValue);
704a2c051a9Schristos 
705a2c051a9Schristos UnlockAndExit2:
70628c506b8Sjruoho     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
70728c506b8Sjruoho 
70828c506b8Sjruoho UnlockAndExit:
70928c506b8Sjruoho     (void) AcpiUtReleaseReadLock (&AcpiGbl_NamespaceRwLock);
71028c506b8Sjruoho     return_ACPI_STATUS (Status);
71128c506b8Sjruoho }
71228c506b8Sjruoho 
ACPI_EXPORT_SYMBOL(AcpiWalkNamespace)71328c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiWalkNamespace)
71428c506b8Sjruoho 
71528c506b8Sjruoho 
71628c506b8Sjruoho /*******************************************************************************
71728c506b8Sjruoho  *
71828c506b8Sjruoho  * FUNCTION:    AcpiNsGetDeviceCallback
71928c506b8Sjruoho  *
72028c506b8Sjruoho  * PARAMETERS:  Callback from AcpiGetDevice
72128c506b8Sjruoho  *
72228c506b8Sjruoho  * RETURN:      Status
72328c506b8Sjruoho  *
72428c506b8Sjruoho  * DESCRIPTION: Takes callbacks from WalkNamespace and filters out all non-
72528c506b8Sjruoho  *              present devices, or if they specified a HID, it filters based
72628c506b8Sjruoho  *              on that.
72728c506b8Sjruoho  *
72828c506b8Sjruoho  ******************************************************************************/
72928c506b8Sjruoho 
73028c506b8Sjruoho static ACPI_STATUS
73128c506b8Sjruoho AcpiNsGetDeviceCallback (
73228c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
73328c506b8Sjruoho     UINT32                  NestingLevel,
73428c506b8Sjruoho     void                    *Context,
73528c506b8Sjruoho     void                    **ReturnValue)
73628c506b8Sjruoho {
73728c506b8Sjruoho     ACPI_GET_DEVICES_INFO   *Info = Context;
73828c506b8Sjruoho     ACPI_STATUS             Status;
73928c506b8Sjruoho     ACPI_NAMESPACE_NODE     *Node;
74028c506b8Sjruoho     UINT32                  Flags;
741a2c051a9Schristos     ACPI_PNP_DEVICE_ID      *Hid;
742a2c051a9Schristos     ACPI_PNP_DEVICE_ID_LIST *Cid;
74328c506b8Sjruoho     UINT32                  i;
74428c506b8Sjruoho     BOOLEAN                 Found;
74528c506b8Sjruoho     int                     NoMatch;
74628c506b8Sjruoho 
74728c506b8Sjruoho 
74828c506b8Sjruoho     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
74928c506b8Sjruoho     if (ACPI_FAILURE (Status))
75028c506b8Sjruoho     {
75128c506b8Sjruoho         return (Status);
75228c506b8Sjruoho     }
75328c506b8Sjruoho 
75428c506b8Sjruoho     Node = AcpiNsValidateHandle (ObjHandle);
75528c506b8Sjruoho     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
75628c506b8Sjruoho     if (ACPI_FAILURE (Status))
75728c506b8Sjruoho     {
75828c506b8Sjruoho         return (Status);
75928c506b8Sjruoho     }
76028c506b8Sjruoho 
76128c506b8Sjruoho     if (!Node)
76228c506b8Sjruoho     {
76328c506b8Sjruoho         return (AE_BAD_PARAMETER);
76428c506b8Sjruoho     }
76528c506b8Sjruoho 
76628c506b8Sjruoho     /*
76728c506b8Sjruoho      * First, filter based on the device HID and CID.
76828c506b8Sjruoho      *
76928c506b8Sjruoho      * 01/2010: For this case where a specific HID is requested, we don't
77028c506b8Sjruoho      * want to run _STA until we have an actual HID match. Thus, we will
77128c506b8Sjruoho      * not unnecessarily execute _STA on devices for which the caller
77228c506b8Sjruoho      * doesn't care about. Previously, _STA was executed unconditionally
77328c506b8Sjruoho      * on all devices found here.
77428c506b8Sjruoho      *
77528c506b8Sjruoho      * A side-effect of this change is that now we will continue to search
77628c506b8Sjruoho      * for a matching HID even under device trees where the parent device
77728c506b8Sjruoho      * would have returned a _STA that indicates it is not present or
77828c506b8Sjruoho      * not functioning (thus aborting the search on that branch).
77928c506b8Sjruoho      */
78028c506b8Sjruoho     if (Info->Hid != NULL)
78128c506b8Sjruoho     {
78228c506b8Sjruoho         Status = AcpiUtExecute_HID (Node, &Hid);
78328c506b8Sjruoho         if (Status == AE_NOT_FOUND)
78428c506b8Sjruoho         {
78528c506b8Sjruoho             return (AE_OK);
78628c506b8Sjruoho         }
78728c506b8Sjruoho         else if (ACPI_FAILURE (Status))
78828c506b8Sjruoho         {
78928c506b8Sjruoho             return (AE_CTRL_DEPTH);
79028c506b8Sjruoho         }
79128c506b8Sjruoho 
7929b9ee194Schristos         NoMatch = strcmp (Hid->String, Info->Hid);
79328c506b8Sjruoho         ACPI_FREE (Hid);
79428c506b8Sjruoho 
79528c506b8Sjruoho         if (NoMatch)
79628c506b8Sjruoho         {
79728c506b8Sjruoho             /*
79828c506b8Sjruoho              * HID does not match, attempt match within the
79928c506b8Sjruoho              * list of Compatible IDs (CIDs)
80028c506b8Sjruoho              */
80128c506b8Sjruoho             Status = AcpiUtExecute_CID (Node, &Cid);
80228c506b8Sjruoho             if (Status == AE_NOT_FOUND)
80328c506b8Sjruoho             {
80428c506b8Sjruoho                 return (AE_OK);
80528c506b8Sjruoho             }
80628c506b8Sjruoho             else if (ACPI_FAILURE (Status))
80728c506b8Sjruoho             {
80828c506b8Sjruoho                 return (AE_CTRL_DEPTH);
80928c506b8Sjruoho             }
81028c506b8Sjruoho 
81128c506b8Sjruoho             /* Walk the CID list */
81228c506b8Sjruoho 
81328c506b8Sjruoho             Found = FALSE;
81428c506b8Sjruoho             for (i = 0; i < Cid->Count; i++)
81528c506b8Sjruoho             {
8169b9ee194Schristos                 if (strcmp (Cid->Ids[i].String, Info->Hid) == 0)
81728c506b8Sjruoho                 {
81828c506b8Sjruoho                     /* Found a matching CID */
81928c506b8Sjruoho 
82028c506b8Sjruoho                     Found = TRUE;
82128c506b8Sjruoho                     break;
82228c506b8Sjruoho                 }
82328c506b8Sjruoho             }
82428c506b8Sjruoho 
82528c506b8Sjruoho             ACPI_FREE (Cid);
82628c506b8Sjruoho             if (!Found)
82728c506b8Sjruoho             {
82828c506b8Sjruoho                 return (AE_OK);
82928c506b8Sjruoho             }
83028c506b8Sjruoho         }
83128c506b8Sjruoho     }
83228c506b8Sjruoho 
83328c506b8Sjruoho     /* Run _STA to determine if device is present */
83428c506b8Sjruoho 
83528c506b8Sjruoho     Status = AcpiUtExecute_STA (Node, &Flags);
83628c506b8Sjruoho     if (ACPI_FAILURE (Status))
83728c506b8Sjruoho     {
83828c506b8Sjruoho         return (AE_CTRL_DEPTH);
83928c506b8Sjruoho     }
84028c506b8Sjruoho 
84128c506b8Sjruoho     if (!(Flags & ACPI_STA_DEVICE_PRESENT) &&
84228c506b8Sjruoho         !(Flags & ACPI_STA_DEVICE_FUNCTIONING))
84328c506b8Sjruoho     {
84428c506b8Sjruoho         /*
84528c506b8Sjruoho          * Don't examine the children of the device only when the
84628c506b8Sjruoho          * device is neither present nor functional. See ACPI spec,
84728c506b8Sjruoho          * description of _STA for more information.
84828c506b8Sjruoho          */
84928c506b8Sjruoho         return (AE_CTRL_DEPTH);
85028c506b8Sjruoho     }
85128c506b8Sjruoho 
85228c506b8Sjruoho     /* We have a valid device, invoke the user function */
85328c506b8Sjruoho 
85481bd9c9cSchristos     Status = Info->UserFunction (ObjHandle, NestingLevel,
85581bd9c9cSchristos         Info->Context, ReturnValue);
85628c506b8Sjruoho     return (Status);
85728c506b8Sjruoho }
85828c506b8Sjruoho 
85928c506b8Sjruoho 
86028c506b8Sjruoho /*******************************************************************************
86128c506b8Sjruoho  *
86228c506b8Sjruoho  * FUNCTION:    AcpiGetDevices
86328c506b8Sjruoho  *
86428c506b8Sjruoho  * PARAMETERS:  HID                 - HID to search for. Can be NULL.
86528c506b8Sjruoho  *              UserFunction        - Called when a matching object is found
86628c506b8Sjruoho  *              Context             - Passed to user function
86728c506b8Sjruoho  *              ReturnValue         - Location where return value of
86828c506b8Sjruoho  *                                    UserFunction is put if terminated early
86928c506b8Sjruoho  *
87028c506b8Sjruoho  * RETURNS      Return value from the UserFunction if terminated early.
87128c506b8Sjruoho  *              Otherwise, returns NULL.
87228c506b8Sjruoho  *
87328c506b8Sjruoho  * DESCRIPTION: Performs a modified depth-first walk of the namespace tree,
87428c506b8Sjruoho  *              starting (and ending) at the object specified by StartHandle.
87528c506b8Sjruoho  *              The UserFunction is called whenever an object of type
87628c506b8Sjruoho  *              Device is found. If the user function returns
87728c506b8Sjruoho  *              a non-zero value, the search is terminated immediately and this
87828c506b8Sjruoho  *              value is returned to the caller.
87928c506b8Sjruoho  *
88028c506b8Sjruoho  *              This is a wrapper for WalkNamespace, but the callback performs
88128c506b8Sjruoho  *              additional filtering. Please see AcpiNsGetDeviceCallback.
88228c506b8Sjruoho  *
88328c506b8Sjruoho  ******************************************************************************/
88428c506b8Sjruoho 
88528c506b8Sjruoho ACPI_STATUS
AcpiGetDevices(char * HID,ACPI_WALK_CALLBACK UserFunction,void * Context,void ** ReturnValue)88628c506b8Sjruoho AcpiGetDevices (
88728c506b8Sjruoho     char                    *HID,
88828c506b8Sjruoho     ACPI_WALK_CALLBACK      UserFunction,
88928c506b8Sjruoho     void                    *Context,
89028c506b8Sjruoho     void                    **ReturnValue)
89128c506b8Sjruoho {
89228c506b8Sjruoho     ACPI_STATUS             Status;
89328c506b8Sjruoho     ACPI_GET_DEVICES_INFO   Info;
89428c506b8Sjruoho 
89528c506b8Sjruoho 
89628c506b8Sjruoho     ACPI_FUNCTION_TRACE (AcpiGetDevices);
89728c506b8Sjruoho 
89828c506b8Sjruoho 
89928c506b8Sjruoho     /* Parameter validation */
90028c506b8Sjruoho 
90128c506b8Sjruoho     if (!UserFunction)
90228c506b8Sjruoho     {
90328c506b8Sjruoho         return_ACPI_STATUS (AE_BAD_PARAMETER);
90428c506b8Sjruoho     }
90528c506b8Sjruoho 
90628c506b8Sjruoho     /*
90728c506b8Sjruoho      * We're going to call their callback from OUR callback, so we need
90828c506b8Sjruoho      * to know what it is, and their context parameter.
90928c506b8Sjruoho      */
91028c506b8Sjruoho     Info.Hid = HID;
91128c506b8Sjruoho     Info.Context = Context;
91228c506b8Sjruoho     Info.UserFunction = UserFunction;
91328c506b8Sjruoho 
91428c506b8Sjruoho     /*
91528c506b8Sjruoho      * Lock the namespace around the walk.
91628c506b8Sjruoho      * The namespace will be unlocked/locked around each call
91728c506b8Sjruoho      * to the user function - since this function
91828c506b8Sjruoho      * must be allowed to make Acpi calls itself.
91928c506b8Sjruoho      */
92028c506b8Sjruoho     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
92128c506b8Sjruoho     if (ACPI_FAILURE (Status))
92228c506b8Sjruoho     {
92328c506b8Sjruoho         return_ACPI_STATUS (Status);
92428c506b8Sjruoho     }
92528c506b8Sjruoho 
92628c506b8Sjruoho     Status = AcpiNsWalkNamespace (ACPI_TYPE_DEVICE, ACPI_ROOT_OBJECT,
92728c506b8Sjruoho         ACPI_UINT32_MAX, ACPI_NS_WALK_UNLOCK,
92828c506b8Sjruoho         AcpiNsGetDeviceCallback, NULL, &Info, ReturnValue);
92928c506b8Sjruoho 
93028c506b8Sjruoho     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
93128c506b8Sjruoho     return_ACPI_STATUS (Status);
93228c506b8Sjruoho }
93328c506b8Sjruoho 
ACPI_EXPORT_SYMBOL(AcpiGetDevices)93428c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiGetDevices)
93528c506b8Sjruoho 
93628c506b8Sjruoho 
93728c506b8Sjruoho /*******************************************************************************
93828c506b8Sjruoho  *
93928c506b8Sjruoho  * FUNCTION:    AcpiAttachData
94028c506b8Sjruoho  *
94128c506b8Sjruoho  * PARAMETERS:  ObjHandle           - Namespace node
94228c506b8Sjruoho  *              Handler             - Handler for this attachment
94328c506b8Sjruoho  *              Data                - Pointer to data to be attached
94428c506b8Sjruoho  *
94528c506b8Sjruoho  * RETURN:      Status
94628c506b8Sjruoho  *
94728c506b8Sjruoho  * DESCRIPTION: Attach arbitrary data and handler to a namespace node.
94828c506b8Sjruoho  *
94928c506b8Sjruoho  ******************************************************************************/
95028c506b8Sjruoho 
95128c506b8Sjruoho ACPI_STATUS
95228c506b8Sjruoho AcpiAttachData (
95328c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
95428c506b8Sjruoho     ACPI_OBJECT_HANDLER     Handler,
95528c506b8Sjruoho     void                    *Data)
95628c506b8Sjruoho {
95728c506b8Sjruoho     ACPI_NAMESPACE_NODE     *Node;
95828c506b8Sjruoho     ACPI_STATUS             Status;
95928c506b8Sjruoho 
96028c506b8Sjruoho 
96128c506b8Sjruoho     /* Parameter validation */
96228c506b8Sjruoho 
96328c506b8Sjruoho     if (!ObjHandle  ||
96428c506b8Sjruoho         !Handler    ||
96528c506b8Sjruoho         !Data)
96628c506b8Sjruoho     {
96728c506b8Sjruoho         return (AE_BAD_PARAMETER);
96828c506b8Sjruoho     }
96928c506b8Sjruoho 
97028c506b8Sjruoho     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
97128c506b8Sjruoho     if (ACPI_FAILURE (Status))
97228c506b8Sjruoho     {
97328c506b8Sjruoho         return (Status);
97428c506b8Sjruoho     }
97528c506b8Sjruoho 
97628c506b8Sjruoho     /* Convert and validate the handle */
97728c506b8Sjruoho 
97828c506b8Sjruoho     Node = AcpiNsValidateHandle (ObjHandle);
97928c506b8Sjruoho     if (!Node)
98028c506b8Sjruoho     {
98128c506b8Sjruoho         Status = AE_BAD_PARAMETER;
98228c506b8Sjruoho         goto UnlockAndExit;
98328c506b8Sjruoho     }
98428c506b8Sjruoho 
98528c506b8Sjruoho     Status = AcpiNsAttachData (Node, Handler, Data);
98628c506b8Sjruoho 
98728c506b8Sjruoho UnlockAndExit:
98828c506b8Sjruoho     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
98928c506b8Sjruoho     return (Status);
99028c506b8Sjruoho }
99128c506b8Sjruoho 
ACPI_EXPORT_SYMBOL(AcpiAttachData)99228c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiAttachData)
99328c506b8Sjruoho 
99428c506b8Sjruoho 
99528c506b8Sjruoho /*******************************************************************************
99628c506b8Sjruoho  *
99728c506b8Sjruoho  * FUNCTION:    AcpiDetachData
99828c506b8Sjruoho  *
99928c506b8Sjruoho  * PARAMETERS:  ObjHandle           - Namespace node handle
100028c506b8Sjruoho  *              Handler             - Handler used in call to AcpiAttachData
100128c506b8Sjruoho  *
100228c506b8Sjruoho  * RETURN:      Status
100328c506b8Sjruoho  *
100428c506b8Sjruoho  * DESCRIPTION: Remove data that was previously attached to a node.
100528c506b8Sjruoho  *
100628c506b8Sjruoho  ******************************************************************************/
100728c506b8Sjruoho 
100828c506b8Sjruoho ACPI_STATUS
100928c506b8Sjruoho AcpiDetachData (
101028c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
101128c506b8Sjruoho     ACPI_OBJECT_HANDLER     Handler)
101228c506b8Sjruoho {
101328c506b8Sjruoho     ACPI_NAMESPACE_NODE     *Node;
101428c506b8Sjruoho     ACPI_STATUS             Status;
101528c506b8Sjruoho 
101628c506b8Sjruoho 
101728c506b8Sjruoho     /* Parameter validation */
101828c506b8Sjruoho 
101928c506b8Sjruoho     if (!ObjHandle  ||
102028c506b8Sjruoho         !Handler)
102128c506b8Sjruoho     {
102228c506b8Sjruoho         return (AE_BAD_PARAMETER);
102328c506b8Sjruoho     }
102428c506b8Sjruoho 
102528c506b8Sjruoho     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
102628c506b8Sjruoho     if (ACPI_FAILURE (Status))
102728c506b8Sjruoho     {
102828c506b8Sjruoho         return (Status);
102928c506b8Sjruoho     }
103028c506b8Sjruoho 
103128c506b8Sjruoho     /* Convert and validate the handle */
103228c506b8Sjruoho 
103328c506b8Sjruoho     Node = AcpiNsValidateHandle (ObjHandle);
103428c506b8Sjruoho     if (!Node)
103528c506b8Sjruoho     {
103628c506b8Sjruoho         Status = AE_BAD_PARAMETER;
103728c506b8Sjruoho         goto UnlockAndExit;
103828c506b8Sjruoho     }
103928c506b8Sjruoho 
104028c506b8Sjruoho     Status = AcpiNsDetachData (Node, Handler);
104128c506b8Sjruoho 
104228c506b8Sjruoho UnlockAndExit:
104328c506b8Sjruoho     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
104428c506b8Sjruoho     return (Status);
104528c506b8Sjruoho }
104628c506b8Sjruoho 
ACPI_EXPORT_SYMBOL(AcpiDetachData)104728c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiDetachData)
104828c506b8Sjruoho 
104928c506b8Sjruoho 
105028c506b8Sjruoho /*******************************************************************************
105128c506b8Sjruoho  *
105228c506b8Sjruoho  * FUNCTION:    AcpiGetData
105328c506b8Sjruoho  *
105428c506b8Sjruoho  * PARAMETERS:  ObjHandle           - Namespace node
105528c506b8Sjruoho  *              Handler             - Handler used in call to AttachData
105628c506b8Sjruoho  *              Data                - Where the data is returned
105728c506b8Sjruoho  *
105828c506b8Sjruoho  * RETURN:      Status
105928c506b8Sjruoho  *
106028c506b8Sjruoho  * DESCRIPTION: Retrieve data that was previously attached to a namespace node.
106128c506b8Sjruoho  *
106228c506b8Sjruoho  ******************************************************************************/
106328c506b8Sjruoho 
106428c506b8Sjruoho ACPI_STATUS
106528c506b8Sjruoho AcpiGetData (
106628c506b8Sjruoho     ACPI_HANDLE             ObjHandle,
106728c506b8Sjruoho     ACPI_OBJECT_HANDLER     Handler,
106828c506b8Sjruoho     void                    **Data)
106928c506b8Sjruoho {
107028c506b8Sjruoho     ACPI_NAMESPACE_NODE     *Node;
107128c506b8Sjruoho     ACPI_STATUS             Status;
107228c506b8Sjruoho 
107328c506b8Sjruoho 
107428c506b8Sjruoho     /* Parameter validation */
107528c506b8Sjruoho 
107628c506b8Sjruoho     if (!ObjHandle  ||
107728c506b8Sjruoho         !Handler    ||
107828c506b8Sjruoho         !Data)
107928c506b8Sjruoho     {
108028c506b8Sjruoho         return (AE_BAD_PARAMETER);
108128c506b8Sjruoho     }
108228c506b8Sjruoho 
108328c506b8Sjruoho     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
108428c506b8Sjruoho     if (ACPI_FAILURE (Status))
108528c506b8Sjruoho     {
108628c506b8Sjruoho         return (Status);
108728c506b8Sjruoho     }
108828c506b8Sjruoho 
108928c506b8Sjruoho     /* Convert and validate the handle */
109028c506b8Sjruoho 
109128c506b8Sjruoho     Node = AcpiNsValidateHandle (ObjHandle);
109228c506b8Sjruoho     if (!Node)
109328c506b8Sjruoho     {
109428c506b8Sjruoho         Status = AE_BAD_PARAMETER;
109528c506b8Sjruoho         goto UnlockAndExit;
109628c506b8Sjruoho     }
109728c506b8Sjruoho 
109828c506b8Sjruoho     Status = AcpiNsGetAttachedData (Node, Handler, Data);
109928c506b8Sjruoho 
110028c506b8Sjruoho UnlockAndExit:
110128c506b8Sjruoho     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
110228c506b8Sjruoho     return (Status);
110328c506b8Sjruoho }
110428c506b8Sjruoho 
110528c506b8Sjruoho ACPI_EXPORT_SYMBOL (AcpiGetData)
1106