1 /******************************************************************************
2  *
3  * Module Name: aslmaputils - Utilities for the resource descriptor/device maps
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2016, Intel Corp.
9  * All rights reserved.
10  *
11  * Redistribution and use in source and binary forms, with or without
12  * modification, are permitted provided that the following conditions
13  * are met:
14  * 1. Redistributions of source code must retain the above copyright
15  *    notice, this list of conditions, and the following disclaimer,
16  *    without modification.
17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18  *    substantially similar to the "NO WARRANTY" disclaimer below
19  *    ("Disclaimer") and any redistribution must be conditioned upon
20  *    including a substantially similar Disclaimer requirement for further
21  *    binary redistribution.
22  * 3. Neither the names of the above-listed copyright holders nor the names
23  *    of any contributors may be used to endorse or promote products derived
24  *    from this software without specific prior written permission.
25  *
26  * Alternatively, this software may be distributed under the terms of the
27  * GNU General Public License ("GPL") version 2 as published by the Free
28  * Software Foundation.
29  *
30  * NO WARRANTY
31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41  * POSSIBILITY OF SUCH DAMAGES.
42  */
43 
44 #include "acpi.h"
45 #include "accommon.h"
46 #include "acapps.h"
47 #include "aslcompiler.h"
48 #include "aslcompiler.y.h"
49 #include "acinterp.h"
50 #include "acnamesp.h"
51 #include "amlcode.h"
52 
53 /* This module used for application-level code only */
54 
55 #define _COMPONENT          ACPI_COMPILER
56         ACPI_MODULE_NAME    ("aslmaputils")
57 
58 
59 /*******************************************************************************
60  *
61  * FUNCTION:    MpGetHidFromParseTree
62  *
63  * PARAMETERS:  HidNode             - Node for a _HID object
64  *
65  * RETURN:      An _HID string value. Automatically converts _HID integers
66  *              to strings. Never NULL.
67  *
68  * DESCRIPTION: Extract a _HID value from the parse tree, not the namespace.
69  *              Used when a fully initialized namespace is not available.
70  *
71  ******************************************************************************/
72 
73 char *
74 MpGetHidFromParseTree (
75     ACPI_NAMESPACE_NODE     *HidNode)
76 {
77     ACPI_PARSE_OBJECT       *Op;
78     ACPI_PARSE_OBJECT       *Arg;
79     char                    *HidString;
80 
81 
82     Op = HidNode->Op;
83     if (!Op)
84     {
85         /* Object is not resolved, probably an External */
86 
87         return ("Unresolved Symbol - referenced but not defined in this table");
88     }
89 
90     switch (Op->Asl.ParseOpcode)
91     {
92     case PARSEOP_NAME:
93 
94         Arg = Op->Asl.Child;  /* Get the NameSeg/NameString node */
95         Arg = Arg->Asl.Next;  /* First peer is the object to be associated with the name */
96 
97         switch (Arg->Asl.ParseOpcode)
98         {
99         case PARSEOP_STRING_LITERAL:
100 
101             return (Arg->Asl.Value.String);
102 
103         case PARSEOP_INTEGER:
104 
105             /* Convert EISAID to a string */
106 
107             HidString = UtStringCacheCalloc (ACPI_EISAID_STRING_SIZE);
108             AcpiExEisaIdToString (HidString, Arg->Asl.Value.Integer);
109             return (HidString);
110 
111         default:
112 
113             return ("UNKNOWN");
114         }
115 
116     default:
117         return ("-No HID-");
118     }
119 }
120 
121 
122 /*******************************************************************************
123  *
124  * FUNCTION:    MpGetHidValue
125  *
126  * PARAMETERS:  DeviceNode          - Node for parent device
127  *
128  * RETURN:      An _HID string value. Automatically converts _HID integers
129  *              to strings. Never NULL.
130  *
131  * DESCRIPTION: Extract _HID value from within a device scope. Does not
132  *              actually execute a method, just gets the string or integer
133  *              value for the _HID.
134  *
135  ******************************************************************************/
136 
137 char *
138 MpGetHidValue (
139     ACPI_NAMESPACE_NODE     *DeviceNode)
140 {
141     ACPI_NAMESPACE_NODE     *HidNode;
142     char                    *HidString;
143     ACPI_STATUS             Status;
144 
145 
146     Status = AcpiNsGetNode (DeviceNode, METHOD_NAME__HID,
147         ACPI_NS_NO_UPSEARCH, &HidNode);
148     if (ACPI_FAILURE (Status))
149     {
150         goto ErrorExit;
151     }
152 
153     /* If only partial namespace, get the _HID from the parse tree */
154 
155     if (!HidNode->Object)
156     {
157         return (MpGetHidFromParseTree (HidNode));
158     }
159 
160     /* Handle the different _HID flavors */
161 
162     switch (HidNode->Type)
163     {
164     case ACPI_TYPE_STRING:
165 
166         return (HidNode->Object->String.Pointer);
167 
168     case ACPI_TYPE_INTEGER:
169 
170         /* Convert EISAID to a string */
171 
172         HidString = UtStringCacheCalloc (ACPI_EISAID_STRING_SIZE);
173         AcpiExEisaIdToString (HidString, HidNode->Object->Integer.Value);
174         return (HidString);
175 
176     case ACPI_TYPE_METHOD:
177 
178         return ("-Method-");
179 
180     default:
181 
182         FlPrintFile (ASL_FILE_MAP_OUTPUT, "BAD HID TYPE: %u", HidNode->Type);
183         break;
184     }
185 
186 
187 ErrorExit:
188     return ("-No HID-");
189 }
190 
191 
192 /*******************************************************************************
193  *
194  * FUNCTION:    MpGetHidViaNamestring
195  *
196  * PARAMETERS:  DeviceName          - Namepath for parent device
197  *
198  * RETURN:      _HID string. Never NULL.
199  *
200  * DESCRIPTION: Get a _HID value via a device pathname (instead of just simply
201  *              a device node.)
202  *
203  ******************************************************************************/
204 
205 char *
206 MpGetHidViaNamestring (
207     char                    *DeviceName)
208 {
209     ACPI_NAMESPACE_NODE     *DeviceNode;
210     ACPI_STATUS             Status;
211 
212 
213     Status = AcpiNsGetNode (NULL, DeviceName, ACPI_NS_NO_UPSEARCH,
214         &DeviceNode);
215     if (ACPI_FAILURE (Status))
216     {
217         goto ErrorExit;
218     }
219 
220     return (MpGetHidValue (DeviceNode));
221 
222 
223 ErrorExit:
224     return ("-No HID-");
225 }
226 
227 
228 /*******************************************************************************
229  *
230  * FUNCTION:    MpGetParentDeviceHid
231  *
232  * PARAMETERS:  Op                      - Parse Op to be examined
233  *              TargetNode              - Where the field node is returned
234  *              ParentDeviceName        - Where the node path is returned
235  *
236  * RETURN:      _HID string. Never NULL.
237  *
238  * DESCRIPTION: Find the parent Device or Scope Op, get the full pathname to
239  *              the parent, and get the _HID associated with the parent.
240  *
241  ******************************************************************************/
242 
243 char *
244 MpGetParentDeviceHid (
245     ACPI_PARSE_OBJECT       *Op,
246     ACPI_NAMESPACE_NODE     **TargetNode,
247     char                    **ParentDeviceName)
248 {
249     ACPI_NAMESPACE_NODE     *DeviceNode;
250 
251 
252     /* Find parent Device() or Scope() Op */
253 
254     while (Op &&
255         (Op->Asl.AmlOpcode != AML_DEVICE_OP) &&
256         (Op->Asl.AmlOpcode != AML_SCOPE_OP))
257     {
258         Op = Op->Asl.Parent;
259     }
260 
261     if (!Op)
262     {
263         FlPrintFile (ASL_FILE_MAP_OUTPUT, " No_Parent_Device ");
264         goto ErrorExit;
265     }
266 
267     /* Get the full pathname to the device and the _HID */
268 
269     DeviceNode = Op->Asl.Node;
270     if (!DeviceNode)
271     {
272         FlPrintFile (ASL_FILE_MAP_OUTPUT, " No_Device_Node ");
273         goto ErrorExit;
274     }
275 
276     *ParentDeviceName = AcpiNsGetExternalPathname (DeviceNode);
277     return (MpGetHidValue (DeviceNode));
278 
279 
280 ErrorExit:
281     return ("-No HID-");
282 }
283 
284 
285 /*******************************************************************************
286  *
287  * FUNCTION:    MpGetDdnValue
288  *
289  * PARAMETERS:  DeviceName          - Namepath for parent device
290  *
291  * RETURN:      _DDN description string. NULL on failure.
292  *
293  * DESCRIPTION: Execute the _DDN method for the device.
294  *
295  ******************************************************************************/
296 
297 char *
298 MpGetDdnValue (
299     char                    *DeviceName)
300 {
301     ACPI_NAMESPACE_NODE     *DeviceNode;
302     ACPI_NAMESPACE_NODE     *DdnNode;
303     ACPI_STATUS             Status;
304 
305 
306     Status = AcpiNsGetNode (NULL, DeviceName, ACPI_NS_NO_UPSEARCH,
307         &DeviceNode);
308     if (ACPI_FAILURE (Status))
309     {
310         goto ErrorExit;
311     }
312 
313     Status = AcpiNsGetNode (DeviceNode, METHOD_NAME__DDN, ACPI_NS_NO_UPSEARCH,
314         &DdnNode);
315     if (ACPI_FAILURE (Status))
316     {
317         goto ErrorExit;
318     }
319 
320     if ((DdnNode->Type != ACPI_TYPE_STRING) ||
321         !DdnNode->Object)
322     {
323         goto ErrorExit;
324     }
325 
326     return (DdnNode->Object->String.Pointer);
327 
328 
329 ErrorExit:
330     return (NULL);
331 }
332 
333 
334 /*******************************************************************************
335  *
336  * FUNCTION:    MpGetConnectionInfo
337  *
338  * PARAMETERS:  Op                      - Parse Op to be examined
339  *              PinIndex                - Index into GPIO PinList
340  *              TargetNode              - Where the field node is returned
341  *              TargetName              - Where the node path is returned
342  *
343  * RETURN:      A substitute _HID string, indicating that the name is actually
344  *              a field. NULL if the Op does not refer to a Connection.
345  *
346  * DESCRIPTION: Get the Field Unit that corresponds to the PinIndex after
347  *              a Connection() invocation.
348  *
349  ******************************************************************************/
350 
351 char *
352 MpGetConnectionInfo (
353     ACPI_PARSE_OBJECT       *Op,
354     UINT32                  PinIndex,
355     ACPI_NAMESPACE_NODE     **TargetNode,
356     char                    **TargetName)
357 {
358     ACPI_PARSE_OBJECT       *NextOp;
359     UINT32                  i;
360 
361 
362     /*
363      * Handle Connection() here. Find the next named FieldUnit.
364      * Note: we look at the ParseOpcode for the compiler, look
365      * at the AmlOpcode for the disassembler.
366      */
367     if ((Op->Asl.AmlOpcode == AML_INT_CONNECTION_OP) ||
368         (Op->Asl.ParseOpcode == PARSEOP_CONNECTION))
369     {
370         /* Find the correct field unit definition */
371 
372         NextOp = Op;
373         for (i = 0; i <= PinIndex;)
374         {
375             NextOp = NextOp->Asl.Next;
376             while (NextOp &&
377                 (NextOp->Asl.ParseOpcode != PARSEOP_NAMESEG) &&
378                 (NextOp->Asl.AmlOpcode != AML_INT_NAMEDFIELD_OP))
379             {
380                 NextOp = NextOp->Asl.Next;
381             }
382 
383             if (!NextOp)
384             {
385                 return ("UNKNOWN");
386             }
387 
388             /* Add length of this field to the current pin index */
389 
390             if (NextOp->Asl.ParseOpcode == PARSEOP_NAMESEG)
391             {
392                 i += (UINT32) NextOp->Asl.Child->Asl.Value.Integer;
393             }
394             else /* AML_INT_NAMEDFIELD_OP */
395             {
396                 i += (UINT32) NextOp->Asl.Value.Integer;
397             }
398         }
399 
400         /* Return the node and pathname for the field unit */
401 
402         *TargetNode = NextOp->Asl.Node;
403         *TargetName = AcpiNsGetExternalPathname (*TargetNode);
404         return ("-Field-");
405     }
406 
407     return (NULL);
408 }
409