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