xref: /freebsd/sys/contrib/dev/acpica/components/namespace/nsxfname.c (revision a159c266a93c3c4f229864954c5f963acd8f60f2)
1*a159c266SJung-uk Kim /******************************************************************************
2*a159c266SJung-uk Kim  *
3*a159c266SJung-uk Kim  * Module Name: nsxfname - Public interfaces to the ACPI subsystem
4*a159c266SJung-uk Kim  *                         ACPI Namespace oriented interfaces
5*a159c266SJung-uk Kim  *
6*a159c266SJung-uk Kim  *****************************************************************************/
7*a159c266SJung-uk Kim 
8*a159c266SJung-uk Kim /*
9*a159c266SJung-uk Kim  * Copyright (C) 2000 - 2012, Intel Corp.
10*a159c266SJung-uk Kim  * All rights reserved.
11*a159c266SJung-uk Kim  *
12*a159c266SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
13*a159c266SJung-uk Kim  * modification, are permitted provided that the following conditions
14*a159c266SJung-uk Kim  * are met:
15*a159c266SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
16*a159c266SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
17*a159c266SJung-uk Kim  *    without modification.
18*a159c266SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19*a159c266SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
20*a159c266SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
21*a159c266SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
22*a159c266SJung-uk Kim  *    binary redistribution.
23*a159c266SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
24*a159c266SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
25*a159c266SJung-uk Kim  *    from this software without specific prior written permission.
26*a159c266SJung-uk Kim  *
27*a159c266SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
28*a159c266SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
29*a159c266SJung-uk Kim  * Software Foundation.
30*a159c266SJung-uk Kim  *
31*a159c266SJung-uk Kim  * NO WARRANTY
32*a159c266SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33*a159c266SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34*a159c266SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35*a159c266SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36*a159c266SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37*a159c266SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38*a159c266SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39*a159c266SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40*a159c266SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41*a159c266SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42*a159c266SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
43*a159c266SJung-uk Kim  */
44*a159c266SJung-uk Kim 
45*a159c266SJung-uk Kim #define __NSXFNAME_C__
46*a159c266SJung-uk Kim 
47*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
48*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
49*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h>
50*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/acparser.h>
51*a159c266SJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h>
52*a159c266SJung-uk Kim 
53*a159c266SJung-uk Kim 
54*a159c266SJung-uk Kim #define _COMPONENT          ACPI_NAMESPACE
55*a159c266SJung-uk Kim         ACPI_MODULE_NAME    ("nsxfname")
56*a159c266SJung-uk Kim 
57*a159c266SJung-uk Kim /* Local prototypes */
58*a159c266SJung-uk Kim 
59*a159c266SJung-uk Kim static char *
60*a159c266SJung-uk Kim AcpiNsCopyDeviceId (
61*a159c266SJung-uk Kim     ACPI_DEVICE_ID          *Dest,
62*a159c266SJung-uk Kim     ACPI_DEVICE_ID          *Source,
63*a159c266SJung-uk Kim     char                    *StringArea);
64*a159c266SJung-uk Kim 
65*a159c266SJung-uk Kim 
66*a159c266SJung-uk Kim /******************************************************************************
67*a159c266SJung-uk Kim  *
68*a159c266SJung-uk Kim  * FUNCTION:    AcpiGetHandle
69*a159c266SJung-uk Kim  *
70*a159c266SJung-uk Kim  * PARAMETERS:  Parent          - Object to search under (search scope).
71*a159c266SJung-uk Kim  *              Pathname        - Pointer to an asciiz string containing the
72*a159c266SJung-uk Kim  *                                name
73*a159c266SJung-uk Kim  *              RetHandle       - Where the return handle is returned
74*a159c266SJung-uk Kim  *
75*a159c266SJung-uk Kim  * RETURN:      Status
76*a159c266SJung-uk Kim  *
77*a159c266SJung-uk Kim  * DESCRIPTION: This routine will search for a caller specified name in the
78*a159c266SJung-uk Kim  *              name space.  The caller can restrict the search region by
79*a159c266SJung-uk Kim  *              specifying a non NULL parent.  The parent value is itself a
80*a159c266SJung-uk Kim  *              namespace handle.
81*a159c266SJung-uk Kim  *
82*a159c266SJung-uk Kim  ******************************************************************************/
83*a159c266SJung-uk Kim 
84*a159c266SJung-uk Kim ACPI_STATUS
85*a159c266SJung-uk Kim AcpiGetHandle (
86*a159c266SJung-uk Kim     ACPI_HANDLE             Parent,
87*a159c266SJung-uk Kim     ACPI_STRING             Pathname,
88*a159c266SJung-uk Kim     ACPI_HANDLE             *RetHandle)
89*a159c266SJung-uk Kim {
90*a159c266SJung-uk Kim     ACPI_STATUS             Status;
91*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node = NULL;
92*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *PrefixNode = NULL;
93*a159c266SJung-uk Kim 
94*a159c266SJung-uk Kim 
95*a159c266SJung-uk Kim     ACPI_FUNCTION_ENTRY ();
96*a159c266SJung-uk Kim 
97*a159c266SJung-uk Kim 
98*a159c266SJung-uk Kim     /* Parameter Validation */
99*a159c266SJung-uk Kim 
100*a159c266SJung-uk Kim     if (!RetHandle || !Pathname)
101*a159c266SJung-uk Kim     {
102*a159c266SJung-uk Kim         return (AE_BAD_PARAMETER);
103*a159c266SJung-uk Kim     }
104*a159c266SJung-uk Kim 
105*a159c266SJung-uk Kim     /* Convert a parent handle to a prefix node */
106*a159c266SJung-uk Kim 
107*a159c266SJung-uk Kim     if (Parent)
108*a159c266SJung-uk Kim     {
109*a159c266SJung-uk Kim         PrefixNode = AcpiNsValidateHandle (Parent);
110*a159c266SJung-uk Kim         if (!PrefixNode)
111*a159c266SJung-uk Kim         {
112*a159c266SJung-uk Kim             return (AE_BAD_PARAMETER);
113*a159c266SJung-uk Kim         }
114*a159c266SJung-uk Kim     }
115*a159c266SJung-uk Kim 
116*a159c266SJung-uk Kim     /*
117*a159c266SJung-uk Kim      * Valid cases are:
118*a159c266SJung-uk Kim      * 1) Fully qualified pathname
119*a159c266SJung-uk Kim      * 2) Parent + Relative pathname
120*a159c266SJung-uk Kim      *
121*a159c266SJung-uk Kim      * Error for <null Parent + relative path>
122*a159c266SJung-uk Kim      */
123*a159c266SJung-uk Kim     if (AcpiNsValidRootPrefix (Pathname[0]))
124*a159c266SJung-uk Kim     {
125*a159c266SJung-uk Kim         /* Pathname is fully qualified (starts with '\') */
126*a159c266SJung-uk Kim 
127*a159c266SJung-uk Kim         /* Special case for root-only, since we can't search for it */
128*a159c266SJung-uk Kim 
129*a159c266SJung-uk Kim         if (!ACPI_STRCMP (Pathname, ACPI_NS_ROOT_PATH))
130*a159c266SJung-uk Kim         {
131*a159c266SJung-uk Kim             *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, AcpiGbl_RootNode);
132*a159c266SJung-uk Kim             return (AE_OK);
133*a159c266SJung-uk Kim         }
134*a159c266SJung-uk Kim     }
135*a159c266SJung-uk Kim     else if (!PrefixNode)
136*a159c266SJung-uk Kim     {
137*a159c266SJung-uk Kim         /* Relative path with null prefix is disallowed */
138*a159c266SJung-uk Kim 
139*a159c266SJung-uk Kim         return (AE_BAD_PARAMETER);
140*a159c266SJung-uk Kim     }
141*a159c266SJung-uk Kim 
142*a159c266SJung-uk Kim     /* Find the Node and convert to a handle */
143*a159c266SJung-uk Kim 
144*a159c266SJung-uk Kim     Status = AcpiNsGetNode (PrefixNode, Pathname, ACPI_NS_NO_UPSEARCH, &Node);
145*a159c266SJung-uk Kim     if (ACPI_SUCCESS (Status))
146*a159c266SJung-uk Kim     {
147*a159c266SJung-uk Kim         *RetHandle = ACPI_CAST_PTR (ACPI_HANDLE, Node);
148*a159c266SJung-uk Kim     }
149*a159c266SJung-uk Kim 
150*a159c266SJung-uk Kim     return (Status);
151*a159c266SJung-uk Kim }
152*a159c266SJung-uk Kim 
153*a159c266SJung-uk Kim ACPI_EXPORT_SYMBOL (AcpiGetHandle)
154*a159c266SJung-uk Kim 
155*a159c266SJung-uk Kim 
156*a159c266SJung-uk Kim /******************************************************************************
157*a159c266SJung-uk Kim  *
158*a159c266SJung-uk Kim  * FUNCTION:    AcpiGetName
159*a159c266SJung-uk Kim  *
160*a159c266SJung-uk Kim  * PARAMETERS:  Handle          - Handle to be converted to a pathname
161*a159c266SJung-uk Kim  *              NameType        - Full pathname or single segment
162*a159c266SJung-uk Kim  *              Buffer          - Buffer for returned path
163*a159c266SJung-uk Kim  *
164*a159c266SJung-uk Kim  * RETURN:      Pointer to a string containing the fully qualified Name.
165*a159c266SJung-uk Kim  *
166*a159c266SJung-uk Kim  * DESCRIPTION: This routine returns the fully qualified name associated with
167*a159c266SJung-uk Kim  *              the Handle parameter.  This and the AcpiPathnameToHandle are
168*a159c266SJung-uk Kim  *              complementary functions.
169*a159c266SJung-uk Kim  *
170*a159c266SJung-uk Kim  ******************************************************************************/
171*a159c266SJung-uk Kim 
172*a159c266SJung-uk Kim ACPI_STATUS
173*a159c266SJung-uk Kim AcpiGetName (
174*a159c266SJung-uk Kim     ACPI_HANDLE             Handle,
175*a159c266SJung-uk Kim     UINT32                  NameType,
176*a159c266SJung-uk Kim     ACPI_BUFFER             *Buffer)
177*a159c266SJung-uk Kim {
178*a159c266SJung-uk Kim     ACPI_STATUS             Status;
179*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node;
180*a159c266SJung-uk Kim 
181*a159c266SJung-uk Kim 
182*a159c266SJung-uk Kim     /* Parameter validation */
183*a159c266SJung-uk Kim 
184*a159c266SJung-uk Kim     if (NameType > ACPI_NAME_TYPE_MAX)
185*a159c266SJung-uk Kim     {
186*a159c266SJung-uk Kim         return (AE_BAD_PARAMETER);
187*a159c266SJung-uk Kim     }
188*a159c266SJung-uk Kim 
189*a159c266SJung-uk Kim     Status = AcpiUtValidateBuffer (Buffer);
190*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
191*a159c266SJung-uk Kim     {
192*a159c266SJung-uk Kim         return (Status);
193*a159c266SJung-uk Kim     }
194*a159c266SJung-uk Kim 
195*a159c266SJung-uk Kim     if (NameType == ACPI_FULL_PATHNAME)
196*a159c266SJung-uk Kim     {
197*a159c266SJung-uk Kim         /* Get the full pathname (From the namespace root) */
198*a159c266SJung-uk Kim 
199*a159c266SJung-uk Kim         Status = AcpiNsHandleToPathname (Handle, Buffer);
200*a159c266SJung-uk Kim         return (Status);
201*a159c266SJung-uk Kim     }
202*a159c266SJung-uk Kim 
203*a159c266SJung-uk Kim     /*
204*a159c266SJung-uk Kim      * Wants the single segment ACPI name.
205*a159c266SJung-uk Kim      * Validate handle and convert to a namespace Node
206*a159c266SJung-uk Kim      */
207*a159c266SJung-uk Kim     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
208*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
209*a159c266SJung-uk Kim     {
210*a159c266SJung-uk Kim         return (Status);
211*a159c266SJung-uk Kim     }
212*a159c266SJung-uk Kim 
213*a159c266SJung-uk Kim     Node = AcpiNsValidateHandle (Handle);
214*a159c266SJung-uk Kim     if (!Node)
215*a159c266SJung-uk Kim     {
216*a159c266SJung-uk Kim         Status = AE_BAD_PARAMETER;
217*a159c266SJung-uk Kim         goto UnlockAndExit;
218*a159c266SJung-uk Kim     }
219*a159c266SJung-uk Kim 
220*a159c266SJung-uk Kim     /* Validate/Allocate/Clear caller buffer */
221*a159c266SJung-uk Kim 
222*a159c266SJung-uk Kim     Status = AcpiUtInitializeBuffer (Buffer, ACPI_PATH_SEGMENT_LENGTH);
223*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
224*a159c266SJung-uk Kim     {
225*a159c266SJung-uk Kim         goto UnlockAndExit;
226*a159c266SJung-uk Kim     }
227*a159c266SJung-uk Kim 
228*a159c266SJung-uk Kim     /* Just copy the ACPI name from the Node and zero terminate it */
229*a159c266SJung-uk Kim 
230*a159c266SJung-uk Kim     ACPI_STRNCPY (Buffer->Pointer, AcpiUtGetNodeName (Node),
231*a159c266SJung-uk Kim                 ACPI_NAME_SIZE);
232*a159c266SJung-uk Kim     ((char *) Buffer->Pointer) [ACPI_NAME_SIZE] = 0;
233*a159c266SJung-uk Kim     Status = AE_OK;
234*a159c266SJung-uk Kim 
235*a159c266SJung-uk Kim 
236*a159c266SJung-uk Kim UnlockAndExit:
237*a159c266SJung-uk Kim 
238*a159c266SJung-uk Kim     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
239*a159c266SJung-uk Kim     return (Status);
240*a159c266SJung-uk Kim }
241*a159c266SJung-uk Kim 
242*a159c266SJung-uk Kim ACPI_EXPORT_SYMBOL (AcpiGetName)
243*a159c266SJung-uk Kim 
244*a159c266SJung-uk Kim 
245*a159c266SJung-uk Kim /******************************************************************************
246*a159c266SJung-uk Kim  *
247*a159c266SJung-uk Kim  * FUNCTION:    AcpiNsCopyDeviceId
248*a159c266SJung-uk Kim  *
249*a159c266SJung-uk Kim  * PARAMETERS:  Dest                - Pointer to the destination DEVICE_ID
250*a159c266SJung-uk Kim  *              Source              - Pointer to the source DEVICE_ID
251*a159c266SJung-uk Kim  *              StringArea          - Pointer to where to copy the dest string
252*a159c266SJung-uk Kim  *
253*a159c266SJung-uk Kim  * RETURN:      Pointer to the next string area
254*a159c266SJung-uk Kim  *
255*a159c266SJung-uk Kim  * DESCRIPTION: Copy a single DEVICE_ID, including the string data.
256*a159c266SJung-uk Kim  *
257*a159c266SJung-uk Kim  ******************************************************************************/
258*a159c266SJung-uk Kim 
259*a159c266SJung-uk Kim static char *
260*a159c266SJung-uk Kim AcpiNsCopyDeviceId (
261*a159c266SJung-uk Kim     ACPI_DEVICE_ID          *Dest,
262*a159c266SJung-uk Kim     ACPI_DEVICE_ID          *Source,
263*a159c266SJung-uk Kim     char                    *StringArea)
264*a159c266SJung-uk Kim {
265*a159c266SJung-uk Kim     /* Create the destination DEVICE_ID */
266*a159c266SJung-uk Kim 
267*a159c266SJung-uk Kim     Dest->String = StringArea;
268*a159c266SJung-uk Kim     Dest->Length = Source->Length;
269*a159c266SJung-uk Kim 
270*a159c266SJung-uk Kim     /* Copy actual string and return a pointer to the next string area */
271*a159c266SJung-uk Kim 
272*a159c266SJung-uk Kim     ACPI_MEMCPY (StringArea, Source->String, Source->Length);
273*a159c266SJung-uk Kim     return (StringArea + Source->Length);
274*a159c266SJung-uk Kim }
275*a159c266SJung-uk Kim 
276*a159c266SJung-uk Kim 
277*a159c266SJung-uk Kim /******************************************************************************
278*a159c266SJung-uk Kim  *
279*a159c266SJung-uk Kim  * FUNCTION:    AcpiGetObjectInfo
280*a159c266SJung-uk Kim  *
281*a159c266SJung-uk Kim  * PARAMETERS:  Handle              - Object Handle
282*a159c266SJung-uk Kim  *              ReturnBuffer        - Where the info is returned
283*a159c266SJung-uk Kim  *
284*a159c266SJung-uk Kim  * RETURN:      Status
285*a159c266SJung-uk Kim  *
286*a159c266SJung-uk Kim  * DESCRIPTION: Returns information about an object as gleaned from the
287*a159c266SJung-uk Kim  *              namespace node and possibly by running several standard
288*a159c266SJung-uk Kim  *              control methods (Such as in the case of a device.)
289*a159c266SJung-uk Kim  *
290*a159c266SJung-uk Kim  * For Device and Processor objects, run the Device _HID, _UID, _CID, _STA,
291*a159c266SJung-uk Kim  * _ADR, _SxW, and _SxD methods.
292*a159c266SJung-uk Kim  *
293*a159c266SJung-uk Kim  * Note: Allocates the return buffer, must be freed by the caller.
294*a159c266SJung-uk Kim  *
295*a159c266SJung-uk Kim  ******************************************************************************/
296*a159c266SJung-uk Kim 
297*a159c266SJung-uk Kim ACPI_STATUS
298*a159c266SJung-uk Kim AcpiGetObjectInfo (
299*a159c266SJung-uk Kim     ACPI_HANDLE             Handle,
300*a159c266SJung-uk Kim     ACPI_DEVICE_INFO        **ReturnBuffer)
301*a159c266SJung-uk Kim {
302*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node;
303*a159c266SJung-uk Kim     ACPI_DEVICE_INFO        *Info;
304*a159c266SJung-uk Kim     ACPI_DEVICE_ID_LIST     *CidList = NULL;
305*a159c266SJung-uk Kim     ACPI_DEVICE_ID          *Hid = NULL;
306*a159c266SJung-uk Kim     ACPI_DEVICE_ID          *Uid = NULL;
307*a159c266SJung-uk Kim     char                    *NextIdString;
308*a159c266SJung-uk Kim     ACPI_OBJECT_TYPE        Type;
309*a159c266SJung-uk Kim     ACPI_NAME               Name;
310*a159c266SJung-uk Kim     UINT8                   ParamCount= 0;
311*a159c266SJung-uk Kim     UINT8                   Valid = 0;
312*a159c266SJung-uk Kim     UINT32                  InfoSize;
313*a159c266SJung-uk Kim     UINT32                  i;
314*a159c266SJung-uk Kim     ACPI_STATUS             Status;
315*a159c266SJung-uk Kim 
316*a159c266SJung-uk Kim 
317*a159c266SJung-uk Kim     /* Parameter validation */
318*a159c266SJung-uk Kim 
319*a159c266SJung-uk Kim     if (!Handle || !ReturnBuffer)
320*a159c266SJung-uk Kim     {
321*a159c266SJung-uk Kim         return (AE_BAD_PARAMETER);
322*a159c266SJung-uk Kim     }
323*a159c266SJung-uk Kim 
324*a159c266SJung-uk Kim     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
325*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
326*a159c266SJung-uk Kim     {
327*a159c266SJung-uk Kim         goto Cleanup;
328*a159c266SJung-uk Kim     }
329*a159c266SJung-uk Kim 
330*a159c266SJung-uk Kim     Node = AcpiNsValidateHandle (Handle);
331*a159c266SJung-uk Kim     if (!Node)
332*a159c266SJung-uk Kim     {
333*a159c266SJung-uk Kim         (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
334*a159c266SJung-uk Kim         return (AE_BAD_PARAMETER);
335*a159c266SJung-uk Kim     }
336*a159c266SJung-uk Kim 
337*a159c266SJung-uk Kim     /* Get the namespace node data while the namespace is locked */
338*a159c266SJung-uk Kim 
339*a159c266SJung-uk Kim     InfoSize = sizeof (ACPI_DEVICE_INFO);
340*a159c266SJung-uk Kim     Type = Node->Type;
341*a159c266SJung-uk Kim     Name = Node->Name.Integer;
342*a159c266SJung-uk Kim 
343*a159c266SJung-uk Kim     if (Node->Type == ACPI_TYPE_METHOD)
344*a159c266SJung-uk Kim     {
345*a159c266SJung-uk Kim         ParamCount = Node->Object->Method.ParamCount;
346*a159c266SJung-uk Kim     }
347*a159c266SJung-uk Kim 
348*a159c266SJung-uk Kim     Status = AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
349*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
350*a159c266SJung-uk Kim     {
351*a159c266SJung-uk Kim         return (Status);
352*a159c266SJung-uk Kim     }
353*a159c266SJung-uk Kim 
354*a159c266SJung-uk Kim     if ((Type == ACPI_TYPE_DEVICE) ||
355*a159c266SJung-uk Kim         (Type == ACPI_TYPE_PROCESSOR))
356*a159c266SJung-uk Kim     {
357*a159c266SJung-uk Kim         /*
358*a159c266SJung-uk Kim          * Get extra info for ACPI Device/Processor objects only:
359*a159c266SJung-uk Kim          * Run the Device _HID, _UID, and _CID methods.
360*a159c266SJung-uk Kim          *
361*a159c266SJung-uk Kim          * Note: none of these methods are required, so they may or may
362*a159c266SJung-uk Kim          * not be present for this device. The Info->Valid bitfield is used
363*a159c266SJung-uk Kim          * to indicate which methods were found and run successfully.
364*a159c266SJung-uk Kim          */
365*a159c266SJung-uk Kim 
366*a159c266SJung-uk Kim         /* Execute the Device._HID method */
367*a159c266SJung-uk Kim 
368*a159c266SJung-uk Kim         Status = AcpiUtExecute_HID (Node, &Hid);
369*a159c266SJung-uk Kim         if (ACPI_SUCCESS (Status))
370*a159c266SJung-uk Kim         {
371*a159c266SJung-uk Kim             InfoSize += Hid->Length;
372*a159c266SJung-uk Kim             Valid |= ACPI_VALID_HID;
373*a159c266SJung-uk Kim         }
374*a159c266SJung-uk Kim 
375*a159c266SJung-uk Kim         /* Execute the Device._UID method */
376*a159c266SJung-uk Kim 
377*a159c266SJung-uk Kim         Status = AcpiUtExecute_UID (Node, &Uid);
378*a159c266SJung-uk Kim         if (ACPI_SUCCESS (Status))
379*a159c266SJung-uk Kim         {
380*a159c266SJung-uk Kim             InfoSize += Uid->Length;
381*a159c266SJung-uk Kim             Valid |= ACPI_VALID_UID;
382*a159c266SJung-uk Kim         }
383*a159c266SJung-uk Kim 
384*a159c266SJung-uk Kim         /* Execute the Device._CID method */
385*a159c266SJung-uk Kim 
386*a159c266SJung-uk Kim         Status = AcpiUtExecute_CID (Node, &CidList);
387*a159c266SJung-uk Kim         if (ACPI_SUCCESS (Status))
388*a159c266SJung-uk Kim         {
389*a159c266SJung-uk Kim             /* Add size of CID strings and CID pointer array */
390*a159c266SJung-uk Kim 
391*a159c266SJung-uk Kim             InfoSize += (CidList->ListSize - sizeof (ACPI_DEVICE_ID_LIST));
392*a159c266SJung-uk Kim             Valid |= ACPI_VALID_CID;
393*a159c266SJung-uk Kim         }
394*a159c266SJung-uk Kim     }
395*a159c266SJung-uk Kim 
396*a159c266SJung-uk Kim     /*
397*a159c266SJung-uk Kim      * Now that we have the variable-length data, we can allocate the
398*a159c266SJung-uk Kim      * return buffer
399*a159c266SJung-uk Kim      */
400*a159c266SJung-uk Kim     Info = ACPI_ALLOCATE_ZEROED (InfoSize);
401*a159c266SJung-uk Kim     if (!Info)
402*a159c266SJung-uk Kim     {
403*a159c266SJung-uk Kim         Status = AE_NO_MEMORY;
404*a159c266SJung-uk Kim         goto Cleanup;
405*a159c266SJung-uk Kim     }
406*a159c266SJung-uk Kim 
407*a159c266SJung-uk Kim     /* Get the fixed-length data */
408*a159c266SJung-uk Kim 
409*a159c266SJung-uk Kim     if ((Type == ACPI_TYPE_DEVICE) ||
410*a159c266SJung-uk Kim         (Type == ACPI_TYPE_PROCESSOR))
411*a159c266SJung-uk Kim     {
412*a159c266SJung-uk Kim         /*
413*a159c266SJung-uk Kim          * Get extra info for ACPI Device/Processor objects only:
414*a159c266SJung-uk Kim          * Run the _STA, _ADR and, SxW, and _SxD methods.
415*a159c266SJung-uk Kim          *
416*a159c266SJung-uk Kim          * Note: none of these methods are required, so they may or may
417*a159c266SJung-uk Kim          * not be present for this device. The Info->Valid bitfield is used
418*a159c266SJung-uk Kim          * to indicate which methods were found and run successfully.
419*a159c266SJung-uk Kim          */
420*a159c266SJung-uk Kim 
421*a159c266SJung-uk Kim         /* Execute the Device._STA method */
422*a159c266SJung-uk Kim 
423*a159c266SJung-uk Kim         Status = AcpiUtExecute_STA (Node, &Info->CurrentStatus);
424*a159c266SJung-uk Kim         if (ACPI_SUCCESS (Status))
425*a159c266SJung-uk Kim         {
426*a159c266SJung-uk Kim             Valid |= ACPI_VALID_STA;
427*a159c266SJung-uk Kim         }
428*a159c266SJung-uk Kim 
429*a159c266SJung-uk Kim         /* Execute the Device._ADR method */
430*a159c266SJung-uk Kim 
431*a159c266SJung-uk Kim         Status = AcpiUtEvaluateNumericObject (METHOD_NAME__ADR, Node,
432*a159c266SJung-uk Kim                     &Info->Address);
433*a159c266SJung-uk Kim         if (ACPI_SUCCESS (Status))
434*a159c266SJung-uk Kim         {
435*a159c266SJung-uk Kim             Valid |= ACPI_VALID_ADR;
436*a159c266SJung-uk Kim         }
437*a159c266SJung-uk Kim 
438*a159c266SJung-uk Kim         /* Execute the Device._SxW methods */
439*a159c266SJung-uk Kim 
440*a159c266SJung-uk Kim         Status = AcpiUtExecutePowerMethods (Node,
441*a159c266SJung-uk Kim                     AcpiGbl_LowestDstateNames, ACPI_NUM_SxW_METHODS,
442*a159c266SJung-uk Kim                     Info->LowestDstates);
443*a159c266SJung-uk Kim         if (ACPI_SUCCESS (Status))
444*a159c266SJung-uk Kim         {
445*a159c266SJung-uk Kim             Valid |= ACPI_VALID_SXWS;
446*a159c266SJung-uk Kim         }
447*a159c266SJung-uk Kim 
448*a159c266SJung-uk Kim         /* Execute the Device._SxD methods */
449*a159c266SJung-uk Kim 
450*a159c266SJung-uk Kim         Status = AcpiUtExecutePowerMethods (Node,
451*a159c266SJung-uk Kim                     AcpiGbl_HighestDstateNames, ACPI_NUM_SxD_METHODS,
452*a159c266SJung-uk Kim                     Info->HighestDstates);
453*a159c266SJung-uk Kim         if (ACPI_SUCCESS (Status))
454*a159c266SJung-uk Kim         {
455*a159c266SJung-uk Kim             Valid |= ACPI_VALID_SXDS;
456*a159c266SJung-uk Kim         }
457*a159c266SJung-uk Kim     }
458*a159c266SJung-uk Kim 
459*a159c266SJung-uk Kim     /*
460*a159c266SJung-uk Kim      * Create a pointer to the string area of the return buffer.
461*a159c266SJung-uk Kim      * Point to the end of the base ACPI_DEVICE_INFO structure.
462*a159c266SJung-uk Kim      */
463*a159c266SJung-uk Kim     NextIdString = ACPI_CAST_PTR (char, Info->CompatibleIdList.Ids);
464*a159c266SJung-uk Kim     if (CidList)
465*a159c266SJung-uk Kim     {
466*a159c266SJung-uk Kim         /* Point past the CID DEVICE_ID array */
467*a159c266SJung-uk Kim 
468*a159c266SJung-uk Kim         NextIdString += ((ACPI_SIZE) CidList->Count * sizeof (ACPI_DEVICE_ID));
469*a159c266SJung-uk Kim     }
470*a159c266SJung-uk Kim 
471*a159c266SJung-uk Kim     /*
472*a159c266SJung-uk Kim      * Copy the HID, UID, and CIDs to the return buffer. The variable-length
473*a159c266SJung-uk Kim      * strings are copied to the reserved area at the end of the buffer.
474*a159c266SJung-uk Kim      *
475*a159c266SJung-uk Kim      * For HID and CID, check if the ID is a PCI Root Bridge.
476*a159c266SJung-uk Kim      */
477*a159c266SJung-uk Kim     if (Hid)
478*a159c266SJung-uk Kim     {
479*a159c266SJung-uk Kim         NextIdString = AcpiNsCopyDeviceId (&Info->HardwareId,
480*a159c266SJung-uk Kim             Hid, NextIdString);
481*a159c266SJung-uk Kim 
482*a159c266SJung-uk Kim         if (AcpiUtIsPciRootBridge (Hid->String))
483*a159c266SJung-uk Kim         {
484*a159c266SJung-uk Kim             Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
485*a159c266SJung-uk Kim         }
486*a159c266SJung-uk Kim     }
487*a159c266SJung-uk Kim 
488*a159c266SJung-uk Kim     if (Uid)
489*a159c266SJung-uk Kim     {
490*a159c266SJung-uk Kim         NextIdString = AcpiNsCopyDeviceId (&Info->UniqueId,
491*a159c266SJung-uk Kim             Uid, NextIdString);
492*a159c266SJung-uk Kim     }
493*a159c266SJung-uk Kim 
494*a159c266SJung-uk Kim     if (CidList)
495*a159c266SJung-uk Kim     {
496*a159c266SJung-uk Kim         Info->CompatibleIdList.Count = CidList->Count;
497*a159c266SJung-uk Kim         Info->CompatibleIdList.ListSize = CidList->ListSize;
498*a159c266SJung-uk Kim 
499*a159c266SJung-uk Kim         /* Copy each CID */
500*a159c266SJung-uk Kim 
501*a159c266SJung-uk Kim         for (i = 0; i < CidList->Count; i++)
502*a159c266SJung-uk Kim         {
503*a159c266SJung-uk Kim             NextIdString = AcpiNsCopyDeviceId (&Info->CompatibleIdList.Ids[i],
504*a159c266SJung-uk Kim                 &CidList->Ids[i], NextIdString);
505*a159c266SJung-uk Kim 
506*a159c266SJung-uk Kim             if (AcpiUtIsPciRootBridge (CidList->Ids[i].String))
507*a159c266SJung-uk Kim             {
508*a159c266SJung-uk Kim                 Info->Flags |= ACPI_PCI_ROOT_BRIDGE;
509*a159c266SJung-uk Kim             }
510*a159c266SJung-uk Kim         }
511*a159c266SJung-uk Kim     }
512*a159c266SJung-uk Kim 
513*a159c266SJung-uk Kim     /* Copy the fixed-length data */
514*a159c266SJung-uk Kim 
515*a159c266SJung-uk Kim     Info->InfoSize = InfoSize;
516*a159c266SJung-uk Kim     Info->Type = Type;
517*a159c266SJung-uk Kim     Info->Name = Name;
518*a159c266SJung-uk Kim     Info->ParamCount = ParamCount;
519*a159c266SJung-uk Kim     Info->Valid = Valid;
520*a159c266SJung-uk Kim 
521*a159c266SJung-uk Kim     *ReturnBuffer = Info;
522*a159c266SJung-uk Kim     Status = AE_OK;
523*a159c266SJung-uk Kim 
524*a159c266SJung-uk Kim 
525*a159c266SJung-uk Kim Cleanup:
526*a159c266SJung-uk Kim     if (Hid)
527*a159c266SJung-uk Kim     {
528*a159c266SJung-uk Kim         ACPI_FREE (Hid);
529*a159c266SJung-uk Kim     }
530*a159c266SJung-uk Kim     if (Uid)
531*a159c266SJung-uk Kim     {
532*a159c266SJung-uk Kim         ACPI_FREE (Uid);
533*a159c266SJung-uk Kim     }
534*a159c266SJung-uk Kim     if (CidList)
535*a159c266SJung-uk Kim     {
536*a159c266SJung-uk Kim         ACPI_FREE (CidList);
537*a159c266SJung-uk Kim     }
538*a159c266SJung-uk Kim     return (Status);
539*a159c266SJung-uk Kim }
540*a159c266SJung-uk Kim 
541*a159c266SJung-uk Kim ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo)
542*a159c266SJung-uk Kim 
543*a159c266SJung-uk Kim 
544*a159c266SJung-uk Kim /******************************************************************************
545*a159c266SJung-uk Kim  *
546*a159c266SJung-uk Kim  * FUNCTION:    AcpiInstallMethod
547*a159c266SJung-uk Kim  *
548*a159c266SJung-uk Kim  * PARAMETERS:  Buffer         - An ACPI table containing one control method
549*a159c266SJung-uk Kim  *
550*a159c266SJung-uk Kim  * RETURN:      Status
551*a159c266SJung-uk Kim  *
552*a159c266SJung-uk Kim  * DESCRIPTION: Install a control method into the namespace. If the method
553*a159c266SJung-uk Kim  *              name already exists in the namespace, it is overwritten. The
554*a159c266SJung-uk Kim  *              input buffer must contain a valid DSDT or SSDT containing a
555*a159c266SJung-uk Kim  *              single control method.
556*a159c266SJung-uk Kim  *
557*a159c266SJung-uk Kim  ******************************************************************************/
558*a159c266SJung-uk Kim 
559*a159c266SJung-uk Kim ACPI_STATUS
560*a159c266SJung-uk Kim AcpiInstallMethod (
561*a159c266SJung-uk Kim     UINT8                   *Buffer)
562*a159c266SJung-uk Kim {
563*a159c266SJung-uk Kim     ACPI_TABLE_HEADER       *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer);
564*a159c266SJung-uk Kim     UINT8                   *AmlBuffer;
565*a159c266SJung-uk Kim     UINT8                   *AmlStart;
566*a159c266SJung-uk Kim     char                    *Path;
567*a159c266SJung-uk Kim     ACPI_NAMESPACE_NODE     *Node;
568*a159c266SJung-uk Kim     ACPI_OPERAND_OBJECT     *MethodObj;
569*a159c266SJung-uk Kim     ACPI_PARSE_STATE        ParserState;
570*a159c266SJung-uk Kim     UINT32                  AmlLength;
571*a159c266SJung-uk Kim     UINT16                  Opcode;
572*a159c266SJung-uk Kim     UINT8                   MethodFlags;
573*a159c266SJung-uk Kim     ACPI_STATUS             Status;
574*a159c266SJung-uk Kim 
575*a159c266SJung-uk Kim 
576*a159c266SJung-uk Kim     /* Parameter validation */
577*a159c266SJung-uk Kim 
578*a159c266SJung-uk Kim     if (!Buffer)
579*a159c266SJung-uk Kim     {
580*a159c266SJung-uk Kim         return (AE_BAD_PARAMETER);
581*a159c266SJung-uk Kim     }
582*a159c266SJung-uk Kim 
583*a159c266SJung-uk Kim     /* Table must be a DSDT or SSDT */
584*a159c266SJung-uk Kim 
585*a159c266SJung-uk Kim     if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) &&
586*a159c266SJung-uk Kim         !ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT))
587*a159c266SJung-uk Kim     {
588*a159c266SJung-uk Kim         return (AE_BAD_HEADER);
589*a159c266SJung-uk Kim     }
590*a159c266SJung-uk Kim 
591*a159c266SJung-uk Kim     /* First AML opcode in the table must be a control method */
592*a159c266SJung-uk Kim 
593*a159c266SJung-uk Kim     ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER);
594*a159c266SJung-uk Kim     Opcode = AcpiPsPeekOpcode (&ParserState);
595*a159c266SJung-uk Kim     if (Opcode != AML_METHOD_OP)
596*a159c266SJung-uk Kim     {
597*a159c266SJung-uk Kim         return (AE_BAD_PARAMETER);
598*a159c266SJung-uk Kim     }
599*a159c266SJung-uk Kim 
600*a159c266SJung-uk Kim     /* Extract method information from the raw AML */
601*a159c266SJung-uk Kim 
602*a159c266SJung-uk Kim     ParserState.Aml += AcpiPsGetOpcodeSize (Opcode);
603*a159c266SJung-uk Kim     ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState);
604*a159c266SJung-uk Kim     Path = AcpiPsGetNextNamestring (&ParserState);
605*a159c266SJung-uk Kim     MethodFlags = *ParserState.Aml++;
606*a159c266SJung-uk Kim     AmlStart = ParserState.Aml;
607*a159c266SJung-uk Kim     AmlLength = ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart);
608*a159c266SJung-uk Kim 
609*a159c266SJung-uk Kim     /*
610*a159c266SJung-uk Kim      * Allocate resources up-front. We don't want to have to delete a new
611*a159c266SJung-uk Kim      * node from the namespace if we cannot allocate memory.
612*a159c266SJung-uk Kim      */
613*a159c266SJung-uk Kim     AmlBuffer = ACPI_ALLOCATE (AmlLength);
614*a159c266SJung-uk Kim     if (!AmlBuffer)
615*a159c266SJung-uk Kim     {
616*a159c266SJung-uk Kim         return (AE_NO_MEMORY);
617*a159c266SJung-uk Kim     }
618*a159c266SJung-uk Kim 
619*a159c266SJung-uk Kim     MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
620*a159c266SJung-uk Kim     if (!MethodObj)
621*a159c266SJung-uk Kim     {
622*a159c266SJung-uk Kim         ACPI_FREE (AmlBuffer);
623*a159c266SJung-uk Kim         return (AE_NO_MEMORY);
624*a159c266SJung-uk Kim     }
625*a159c266SJung-uk Kim 
626*a159c266SJung-uk Kim     /* Lock namespace for AcpiNsLookup, we may be creating a new node */
627*a159c266SJung-uk Kim 
628*a159c266SJung-uk Kim     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
629*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status))
630*a159c266SJung-uk Kim     {
631*a159c266SJung-uk Kim         goto ErrorExit;
632*a159c266SJung-uk Kim     }
633*a159c266SJung-uk Kim 
634*a159c266SJung-uk Kim     /* The lookup either returns an existing node or creates a new one */
635*a159c266SJung-uk Kim 
636*a159c266SJung-uk Kim     Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
637*a159c266SJung-uk Kim                 ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node);
638*a159c266SJung-uk Kim 
639*a159c266SJung-uk Kim     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
640*a159c266SJung-uk Kim 
641*a159c266SJung-uk Kim     if (ACPI_FAILURE (Status)) /* NsLookup */
642*a159c266SJung-uk Kim     {
643*a159c266SJung-uk Kim         if (Status != AE_ALREADY_EXISTS)
644*a159c266SJung-uk Kim         {
645*a159c266SJung-uk Kim             goto ErrorExit;
646*a159c266SJung-uk Kim         }
647*a159c266SJung-uk Kim 
648*a159c266SJung-uk Kim         /* Node existed previously, make sure it is a method node */
649*a159c266SJung-uk Kim 
650*a159c266SJung-uk Kim         if (Node->Type != ACPI_TYPE_METHOD)
651*a159c266SJung-uk Kim         {
652*a159c266SJung-uk Kim             Status = AE_TYPE;
653*a159c266SJung-uk Kim             goto ErrorExit;
654*a159c266SJung-uk Kim         }
655*a159c266SJung-uk Kim     }
656*a159c266SJung-uk Kim 
657*a159c266SJung-uk Kim     /* Copy the method AML to the local buffer */
658*a159c266SJung-uk Kim 
659*a159c266SJung-uk Kim     ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength);
660*a159c266SJung-uk Kim 
661*a159c266SJung-uk Kim     /* Initialize the method object with the new method's information */
662*a159c266SJung-uk Kim 
663*a159c266SJung-uk Kim     MethodObj->Method.AmlStart = AmlBuffer;
664*a159c266SJung-uk Kim     MethodObj->Method.AmlLength = AmlLength;
665*a159c266SJung-uk Kim 
666*a159c266SJung-uk Kim     MethodObj->Method.ParamCount = (UINT8)
667*a159c266SJung-uk Kim         (MethodFlags & AML_METHOD_ARG_COUNT);
668*a159c266SJung-uk Kim 
669*a159c266SJung-uk Kim     if (MethodFlags & AML_METHOD_SERIALIZED)
670*a159c266SJung-uk Kim     {
671*a159c266SJung-uk Kim         MethodObj->Method.InfoFlags = ACPI_METHOD_SERIALIZED;
672*a159c266SJung-uk Kim 
673*a159c266SJung-uk Kim         MethodObj->Method.SyncLevel = (UINT8)
674*a159c266SJung-uk Kim             ((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
675*a159c266SJung-uk Kim     }
676*a159c266SJung-uk Kim 
677*a159c266SJung-uk Kim     /*
678*a159c266SJung-uk Kim      * Now that it is complete, we can attach the new method object to
679*a159c266SJung-uk Kim      * the method Node (detaches/deletes any existing object)
680*a159c266SJung-uk Kim      */
681*a159c266SJung-uk Kim     Status = AcpiNsAttachObject (Node, MethodObj, ACPI_TYPE_METHOD);
682*a159c266SJung-uk Kim 
683*a159c266SJung-uk Kim     /*
684*a159c266SJung-uk Kim      * Flag indicates AML buffer is dynamic, must be deleted later.
685*a159c266SJung-uk Kim      * Must be set only after attach above.
686*a159c266SJung-uk Kim      */
687*a159c266SJung-uk Kim     Node->Flags |= ANOBJ_ALLOCATED_BUFFER;
688*a159c266SJung-uk Kim 
689*a159c266SJung-uk Kim     /* Remove local reference to the method object */
690*a159c266SJung-uk Kim 
691*a159c266SJung-uk Kim     AcpiUtRemoveReference (MethodObj);
692*a159c266SJung-uk Kim     return (Status);
693*a159c266SJung-uk Kim 
694*a159c266SJung-uk Kim 
695*a159c266SJung-uk Kim ErrorExit:
696*a159c266SJung-uk Kim 
697*a159c266SJung-uk Kim     ACPI_FREE (AmlBuffer);
698*a159c266SJung-uk Kim     ACPI_FREE (MethodObj);
699*a159c266SJung-uk Kim     return (Status);
700*a159c266SJung-uk Kim }
701*a159c266SJung-uk Kim 
702*a159c266SJung-uk Kim ACPI_EXPORT_SYMBOL (AcpiInstallMethod)
703