xref: /freebsd/sys/contrib/dev/acpica/common/dmextern.c (revision ed17e06e2cdf97a1c05c04d88ef6c54cbdb34871)
1f556842eSJung-uk Kim /******************************************************************************
2f556842eSJung-uk Kim  *
3f556842eSJung-uk Kim  * Module Name: dmextern - Support for External() ASL statements
4f556842eSJung-uk Kim  *
5f556842eSJung-uk Kim  *****************************************************************************/
6f556842eSJung-uk Kim 
7d244b227SJung-uk Kim /*
8ec3fc72fSJung-uk Kim  * Copyright (C) 2000 - 2012, Intel Corp.
9f556842eSJung-uk Kim  * All rights reserved.
10f556842eSJung-uk Kim  *
11d244b227SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
12d244b227SJung-uk Kim  * modification, are permitted provided that the following conditions
13d244b227SJung-uk Kim  * are met:
14d244b227SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
15d244b227SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
16d244b227SJung-uk Kim  *    without modification.
17d244b227SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18d244b227SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
19d244b227SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
20d244b227SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
21d244b227SJung-uk Kim  *    binary redistribution.
22d244b227SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
23d244b227SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
24d244b227SJung-uk Kim  *    from this software without specific prior written permission.
25f556842eSJung-uk Kim  *
26d244b227SJung-uk Kim  * Alternatively, this software may be distributed under the terms of the
27d244b227SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
28d244b227SJung-uk Kim  * Software Foundation.
29f556842eSJung-uk Kim  *
30d244b227SJung-uk Kim  * NO WARRANTY
31d244b227SJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32d244b227SJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33d244b227SJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34d244b227SJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35d244b227SJung-uk Kim  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36d244b227SJung-uk Kim  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37d244b227SJung-uk Kim  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38d244b227SJung-uk Kim  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39d244b227SJung-uk Kim  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40d244b227SJung-uk Kim  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41d244b227SJung-uk Kim  * POSSIBILITY OF SUCH DAMAGES.
42d244b227SJung-uk Kim  */
43f556842eSJung-uk Kim 
44f556842eSJung-uk Kim #include <contrib/dev/acpica/include/acpi.h>
45f556842eSJung-uk Kim #include <contrib/dev/acpica/include/accommon.h>
46f556842eSJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h>
47f556842eSJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h>
48f556842eSJung-uk Kim #include <contrib/dev/acpica/include/acdisasm.h>
49f556842eSJung-uk Kim 
50f556842eSJung-uk Kim 
51f556842eSJung-uk Kim /*
52f556842eSJung-uk Kim  * This module is used for application-level code (iASL disassembler) only.
53f556842eSJung-uk Kim  *
54f556842eSJung-uk Kim  * It contains the code to create and emit any necessary External() ASL
55f556842eSJung-uk Kim  * statements for the module being disassembled.
56f556842eSJung-uk Kim  */
57f556842eSJung-uk Kim #define _COMPONENT          ACPI_CA_DISASSEMBLER
58f556842eSJung-uk Kim         ACPI_MODULE_NAME    ("dmextern")
59f556842eSJung-uk Kim 
60f556842eSJung-uk Kim 
61f556842eSJung-uk Kim /*
62f556842eSJung-uk Kim  * This table maps ACPI_OBJECT_TYPEs to the corresponding ASL
63f556842eSJung-uk Kim  * ObjectTypeKeyword. Used to generate typed external declarations
64f556842eSJung-uk Kim  */
65f556842eSJung-uk Kim static const char           *AcpiGbl_DmTypeNames[] =
66f556842eSJung-uk Kim {
67f556842eSJung-uk Kim     /* 00 */ "",                    /* Type ANY */
68f556842eSJung-uk Kim     /* 01 */ ", IntObj",
69f556842eSJung-uk Kim     /* 02 */ ", StrObj",
70f556842eSJung-uk Kim     /* 03 */ ", BuffObj",
71f556842eSJung-uk Kim     /* 04 */ ", PkgObj",
72f556842eSJung-uk Kim     /* 05 */ ", FieldUnitObj",
73f556842eSJung-uk Kim     /* 06 */ ", DeviceObj",
74f556842eSJung-uk Kim     /* 07 */ ", EventObj",
75f556842eSJung-uk Kim     /* 08 */ ", MethodObj",
76f556842eSJung-uk Kim     /* 09 */ ", MutexObj",
77f556842eSJung-uk Kim     /* 10 */ ", OpRegionObj",
78f556842eSJung-uk Kim     /* 11 */ ", PowerResObj",
79f556842eSJung-uk Kim     /* 12 */ ", ProcessorObj",
80f556842eSJung-uk Kim     /* 13 */ ", ThermalZoneObj",
81f556842eSJung-uk Kim     /* 14 */ ", BuffFieldObj",
82f556842eSJung-uk Kim     /* 15 */ ", DDBHandleObj",
83f556842eSJung-uk Kim     /* 16 */ "",                    /* Debug object */
84f556842eSJung-uk Kim     /* 17 */ ", FieldUnitObj",
85f556842eSJung-uk Kim     /* 18 */ ", FieldUnitObj",
86f556842eSJung-uk Kim     /* 19 */ ", FieldUnitObj"
87f556842eSJung-uk Kim };
88f556842eSJung-uk Kim 
89f556842eSJung-uk Kim 
90f556842eSJung-uk Kim /* Local prototypes */
91f556842eSJung-uk Kim 
92f556842eSJung-uk Kim static const char *
93f556842eSJung-uk Kim AcpiDmGetObjectTypeName (
94f556842eSJung-uk Kim     ACPI_OBJECT_TYPE        Type);
95f556842eSJung-uk Kim 
96f556842eSJung-uk Kim static char *
97f556842eSJung-uk Kim AcpiDmNormalizeParentPrefix (
98f556842eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
99f556842eSJung-uk Kim     char                    *Path);
100f556842eSJung-uk Kim 
101f556842eSJung-uk Kim 
102f556842eSJung-uk Kim /*******************************************************************************
103f556842eSJung-uk Kim  *
104f556842eSJung-uk Kim  * FUNCTION:    AcpiDmGetObjectTypeName
105f556842eSJung-uk Kim  *
106f556842eSJung-uk Kim  * PARAMETERS:  Type                - An ACPI_OBJECT_TYPE
107f556842eSJung-uk Kim  *
108f556842eSJung-uk Kim  * RETURN:      Pointer to a string
109f556842eSJung-uk Kim  *
110f556842eSJung-uk Kim  * DESCRIPTION: Map an object type to the ASL object type string.
111f556842eSJung-uk Kim  *
112f556842eSJung-uk Kim  ******************************************************************************/
113f556842eSJung-uk Kim 
114f556842eSJung-uk Kim static const char *
115f556842eSJung-uk Kim AcpiDmGetObjectTypeName (
116f556842eSJung-uk Kim     ACPI_OBJECT_TYPE        Type)
117f556842eSJung-uk Kim {
118f556842eSJung-uk Kim 
119f556842eSJung-uk Kim     if (Type == ACPI_TYPE_LOCAL_SCOPE)
120f556842eSJung-uk Kim     {
121f556842eSJung-uk Kim         Type = ACPI_TYPE_DEVICE;
122f556842eSJung-uk Kim     }
123f556842eSJung-uk Kim 
124f556842eSJung-uk Kim     else if (Type > ACPI_TYPE_LOCAL_INDEX_FIELD)
125f556842eSJung-uk Kim     {
126f556842eSJung-uk Kim         return ("");
127f556842eSJung-uk Kim     }
128f556842eSJung-uk Kim 
129f556842eSJung-uk Kim     return (AcpiGbl_DmTypeNames[Type]);
130f556842eSJung-uk Kim }
131f556842eSJung-uk Kim 
132f556842eSJung-uk Kim 
133f556842eSJung-uk Kim /*******************************************************************************
134f556842eSJung-uk Kim  *
135f556842eSJung-uk Kim  * FUNCTION:    AcpiDmNormalizeParentPrefix
136f556842eSJung-uk Kim  *
137f556842eSJung-uk Kim  * PARAMETERS:  Op                  - Parse op
138f556842eSJung-uk Kim  *              Path                - Path with parent prefix
139f556842eSJung-uk Kim  *
140f556842eSJung-uk Kim  * RETURN:      The full pathname to the object (from the namespace root)
141f556842eSJung-uk Kim  *
142f556842eSJung-uk Kim  * DESCRIPTION: Returns the full pathname of a path with parent prefix
143f556842eSJung-uk Kim  *              The caller must free the fullpath returned.
144f556842eSJung-uk Kim  *
145f556842eSJung-uk Kim  ******************************************************************************/
146f556842eSJung-uk Kim 
147f556842eSJung-uk Kim static char *
148f556842eSJung-uk Kim AcpiDmNormalizeParentPrefix (
149f556842eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
150f556842eSJung-uk Kim     char                    *Path)
151f556842eSJung-uk Kim {
152f556842eSJung-uk Kim     ACPI_NAMESPACE_NODE     *Node;
153f556842eSJung-uk Kim     char                    *Fullpath;
154f556842eSJung-uk Kim     char                    *ParentPath;
155f556842eSJung-uk Kim     ACPI_SIZE               Length;
156*ed17e06eSJung-uk Kim     UINT32                  Index = 0;
157f556842eSJung-uk Kim 
158f556842eSJung-uk Kim 
159*ed17e06eSJung-uk Kim     if (!Op)
160*ed17e06eSJung-uk Kim     {
161*ed17e06eSJung-uk Kim         return (NULL);
162*ed17e06eSJung-uk Kim     }
163f556842eSJung-uk Kim 
164*ed17e06eSJung-uk Kim     /* Search upwards in the parse tree until we reach the next namespace node */
165*ed17e06eSJung-uk Kim 
166*ed17e06eSJung-uk Kim     Op = Op->Common.Parent;
167f556842eSJung-uk Kim     while (Op)
168f556842eSJung-uk Kim     {
169f556842eSJung-uk Kim         if (Op->Common.Node)
170f556842eSJung-uk Kim         {
171f556842eSJung-uk Kim             break;
172f556842eSJung-uk Kim         }
173f556842eSJung-uk Kim 
174f556842eSJung-uk Kim         Op = Op->Common.Parent;
175f556842eSJung-uk Kim     }
176f556842eSJung-uk Kim 
177f556842eSJung-uk Kim     if (!Op)
178f556842eSJung-uk Kim     {
179f556842eSJung-uk Kim         return (NULL);
180f556842eSJung-uk Kim     }
181f556842eSJung-uk Kim 
182f556842eSJung-uk Kim     /*
183f556842eSJung-uk Kim      * Find the actual parent node for the reference:
184f556842eSJung-uk Kim      * Remove all carat prefixes from the input path.
185f556842eSJung-uk Kim      * There may be multiple parent prefixes (For example, ^^^M000)
186f556842eSJung-uk Kim      */
187f556842eSJung-uk Kim     Node = Op->Common.Node;
188f556842eSJung-uk Kim     while (Node && (*Path == (UINT8) AML_PARENT_PREFIX))
189f556842eSJung-uk Kim     {
190a88e22b7SJung-uk Kim         Node = Node->Parent;
191f556842eSJung-uk Kim         Path++;
192f556842eSJung-uk Kim     }
193f556842eSJung-uk Kim 
194f556842eSJung-uk Kim     if (!Node)
195f556842eSJung-uk Kim     {
196f556842eSJung-uk Kim         return (NULL);
197f556842eSJung-uk Kim     }
198f556842eSJung-uk Kim 
199f556842eSJung-uk Kim     /* Get the full pathname for the parent node */
200f556842eSJung-uk Kim 
201f556842eSJung-uk Kim     ParentPath = AcpiNsGetExternalPathname (Node);
202f556842eSJung-uk Kim     if (!ParentPath)
203f556842eSJung-uk Kim     {
204f556842eSJung-uk Kim         return (NULL);
205f556842eSJung-uk Kim     }
206f556842eSJung-uk Kim 
207f556842eSJung-uk Kim     Length = (ACPI_STRLEN (ParentPath) + ACPI_STRLEN (Path) + 1);
2088c8be05fSJung-uk Kim     if (ParentPath[1])
2098c8be05fSJung-uk Kim     {
2108c8be05fSJung-uk Kim         /*
2118c8be05fSJung-uk Kim          * If ParentPath is not just a simple '\', increment the length
2128c8be05fSJung-uk Kim          * for the required dot separator (ParentPath.Path)
2138c8be05fSJung-uk Kim          */
2148c8be05fSJung-uk Kim         Length++;
215*ed17e06eSJung-uk Kim 
216*ed17e06eSJung-uk Kim         /* For External() statements, we do not want a leading '\' */
217*ed17e06eSJung-uk Kim 
218*ed17e06eSJung-uk Kim         if (*ParentPath == AML_ROOT_PREFIX)
219*ed17e06eSJung-uk Kim         {
220*ed17e06eSJung-uk Kim             Index = 1;
221*ed17e06eSJung-uk Kim         }
2228c8be05fSJung-uk Kim     }
2238c8be05fSJung-uk Kim 
224f556842eSJung-uk Kim     Fullpath = ACPI_ALLOCATE_ZEROED (Length);
225f556842eSJung-uk Kim     if (!Fullpath)
226f556842eSJung-uk Kim     {
227f556842eSJung-uk Kim         goto Cleanup;
228f556842eSJung-uk Kim     }
229f556842eSJung-uk Kim 
230f556842eSJung-uk Kim     /*
231f556842eSJung-uk Kim      * Concatenate parent fullpath and path. For example,
232f556842eSJung-uk Kim      * parent fullpath "\_SB_", Path "^INIT", Fullpath "\_SB_.INIT"
233f556842eSJung-uk Kim      *
234f556842eSJung-uk Kim      * Copy the parent path
235f556842eSJung-uk Kim      */
236*ed17e06eSJung-uk Kim     ACPI_STRCPY (Fullpath, &ParentPath[Index]);
237f556842eSJung-uk Kim 
238f38b0f21SJung-uk Kim     /*
239f38b0f21SJung-uk Kim      * Add dot separator
240f38b0f21SJung-uk Kim      * (don't need dot if parent fullpath is a single backslash)
241f38b0f21SJung-uk Kim      */
242f556842eSJung-uk Kim     if (ParentPath[1])
243f556842eSJung-uk Kim     {
244f556842eSJung-uk Kim         ACPI_STRCAT (Fullpath, ".");
245f556842eSJung-uk Kim     }
246f556842eSJung-uk Kim 
247f556842eSJung-uk Kim     /* Copy child path (carat parent prefix(es) were skipped above) */
248f556842eSJung-uk Kim 
249f556842eSJung-uk Kim     ACPI_STRCAT (Fullpath, Path);
250f556842eSJung-uk Kim 
251f556842eSJung-uk Kim Cleanup:
252f556842eSJung-uk Kim     ACPI_FREE (ParentPath);
253f556842eSJung-uk Kim     return (Fullpath);
254f556842eSJung-uk Kim }
255f556842eSJung-uk Kim 
256f556842eSJung-uk Kim 
257f556842eSJung-uk Kim /*******************************************************************************
258f556842eSJung-uk Kim  *
259709fac06SJung-uk Kim  * FUNCTION:    AcpiDmAddToExternalFileList
260709fac06SJung-uk Kim  *
261709fac06SJung-uk Kim  * PARAMETERS:  PathList            - Single path or list separated by comma
262709fac06SJung-uk Kim  *
263709fac06SJung-uk Kim  * RETURN:      None
264709fac06SJung-uk Kim  *
265709fac06SJung-uk Kim  * DESCRIPTION: Add external files to global list
266709fac06SJung-uk Kim  *
267709fac06SJung-uk Kim  ******************************************************************************/
268709fac06SJung-uk Kim 
269709fac06SJung-uk Kim ACPI_STATUS
270709fac06SJung-uk Kim AcpiDmAddToExternalFileList (
271709fac06SJung-uk Kim     char                    *PathList)
272709fac06SJung-uk Kim {
273709fac06SJung-uk Kim     ACPI_EXTERNAL_FILE      *ExternalFile;
274709fac06SJung-uk Kim     char                    *Path;
275709fac06SJung-uk Kim     char                    *TmpPath;
276709fac06SJung-uk Kim 
277709fac06SJung-uk Kim 
278709fac06SJung-uk Kim     if (!PathList)
279709fac06SJung-uk Kim     {
280709fac06SJung-uk Kim         return (AE_OK);
281709fac06SJung-uk Kim     }
282709fac06SJung-uk Kim 
283709fac06SJung-uk Kim     Path = strtok (PathList, ",");
284709fac06SJung-uk Kim 
285709fac06SJung-uk Kim     while (Path)
286709fac06SJung-uk Kim     {
287709fac06SJung-uk Kim         TmpPath = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (Path) + 1);
288709fac06SJung-uk Kim         if (!TmpPath)
289709fac06SJung-uk Kim         {
290709fac06SJung-uk Kim             return (AE_NO_MEMORY);
291709fac06SJung-uk Kim         }
292709fac06SJung-uk Kim 
293709fac06SJung-uk Kim         ACPI_STRCPY (TmpPath, Path);
294709fac06SJung-uk Kim 
295709fac06SJung-uk Kim         ExternalFile = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_FILE));
296709fac06SJung-uk Kim         if (!ExternalFile)
297709fac06SJung-uk Kim         {
298709fac06SJung-uk Kim             ACPI_FREE (TmpPath);
299709fac06SJung-uk Kim             return (AE_NO_MEMORY);
300709fac06SJung-uk Kim         }
301709fac06SJung-uk Kim 
302709fac06SJung-uk Kim         ExternalFile->Path = TmpPath;
303709fac06SJung-uk Kim 
304709fac06SJung-uk Kim         if (AcpiGbl_ExternalFileList)
305709fac06SJung-uk Kim         {
306709fac06SJung-uk Kim             ExternalFile->Next = AcpiGbl_ExternalFileList;
307709fac06SJung-uk Kim         }
308709fac06SJung-uk Kim 
309709fac06SJung-uk Kim         AcpiGbl_ExternalFileList = ExternalFile;
310709fac06SJung-uk Kim         Path = strtok (NULL, ",");
311709fac06SJung-uk Kim     }
312709fac06SJung-uk Kim 
313709fac06SJung-uk Kim     return (AE_OK);
314709fac06SJung-uk Kim }
315709fac06SJung-uk Kim 
316709fac06SJung-uk Kim 
317709fac06SJung-uk Kim /*******************************************************************************
318709fac06SJung-uk Kim  *
319709fac06SJung-uk Kim  * FUNCTION:    AcpiDmClearExternalFileList
320709fac06SJung-uk Kim  *
321709fac06SJung-uk Kim  * PARAMETERS:  None
322709fac06SJung-uk Kim  *
323709fac06SJung-uk Kim  * RETURN:      None
324709fac06SJung-uk Kim  *
325709fac06SJung-uk Kim  * DESCRIPTION: Clear the external file list
326709fac06SJung-uk Kim  *
327709fac06SJung-uk Kim  ******************************************************************************/
328709fac06SJung-uk Kim 
329709fac06SJung-uk Kim void
330709fac06SJung-uk Kim AcpiDmClearExternalFileList (
331709fac06SJung-uk Kim     void)
332709fac06SJung-uk Kim {
333709fac06SJung-uk Kim     ACPI_EXTERNAL_FILE      *NextExternal;
334709fac06SJung-uk Kim 
335709fac06SJung-uk Kim 
336709fac06SJung-uk Kim     while (AcpiGbl_ExternalFileList)
337709fac06SJung-uk Kim     {
338709fac06SJung-uk Kim         NextExternal = AcpiGbl_ExternalFileList->Next;
339709fac06SJung-uk Kim         ACPI_FREE (AcpiGbl_ExternalFileList->Path);
340709fac06SJung-uk Kim         ACPI_FREE (AcpiGbl_ExternalFileList);
341709fac06SJung-uk Kim         AcpiGbl_ExternalFileList = NextExternal;
342709fac06SJung-uk Kim     }
343709fac06SJung-uk Kim }
344709fac06SJung-uk Kim 
345709fac06SJung-uk Kim 
346709fac06SJung-uk Kim /*******************************************************************************
347709fac06SJung-uk Kim  *
348f556842eSJung-uk Kim  * FUNCTION:    AcpiDmAddToExternalList
349f556842eSJung-uk Kim  *
350f556842eSJung-uk Kim  * PARAMETERS:  Op                  - Current parser Op
351f556842eSJung-uk Kim  *              Path                - Internal (AML) path to the object
352f556842eSJung-uk Kim  *              Type                - ACPI object type to be added
353f556842eSJung-uk Kim  *              Value               - Arg count if adding a Method object
354f556842eSJung-uk Kim  *
355f556842eSJung-uk Kim  * RETURN:      None
356f556842eSJung-uk Kim  *
357f556842eSJung-uk Kim  * DESCRIPTION: Insert a new name into the global list of Externals which
358f556842eSJung-uk Kim  *              will in turn be later emitted as an External() declaration
359f556842eSJung-uk Kim  *              in the disassembled output.
360f556842eSJung-uk Kim  *
361f556842eSJung-uk Kim  ******************************************************************************/
362f556842eSJung-uk Kim 
363f556842eSJung-uk Kim void
364f556842eSJung-uk Kim AcpiDmAddToExternalList (
365f556842eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
366f556842eSJung-uk Kim     char                    *Path,
367f556842eSJung-uk Kim     UINT8                   Type,
368f556842eSJung-uk Kim     UINT32                  Value)
369f556842eSJung-uk Kim {
370f556842eSJung-uk Kim     char                    *ExternalPath;
371f556842eSJung-uk Kim     char                    *Fullpath = NULL;
372f556842eSJung-uk Kim     ACPI_EXTERNAL_LIST      *NewExternal;
373f556842eSJung-uk Kim     ACPI_EXTERNAL_LIST      *NextExternal;
374f556842eSJung-uk Kim     ACPI_EXTERNAL_LIST      *PrevExternal = NULL;
375f556842eSJung-uk Kim     ACPI_STATUS             Status;
376f556842eSJung-uk Kim 
377f556842eSJung-uk Kim 
378f556842eSJung-uk Kim     if (!Path)
379f556842eSJung-uk Kim     {
380f556842eSJung-uk Kim         return;
381f556842eSJung-uk Kim     }
382f556842eSJung-uk Kim 
383*ed17e06eSJung-uk Kim     /*
384*ed17e06eSJung-uk Kim      * We don't want External() statements to contain a leading '\'.
385*ed17e06eSJung-uk Kim      * This prevents duplicate external statements of the form:
386*ed17e06eSJung-uk Kim      *
387*ed17e06eSJung-uk Kim      *    External (\ABCD)
388*ed17e06eSJung-uk Kim      *    External (ABCD)
389*ed17e06eSJung-uk Kim      *
390*ed17e06eSJung-uk Kim      * This would cause a compile time error when the disassembled
391*ed17e06eSJung-uk Kim      * output file is recompiled.
392*ed17e06eSJung-uk Kim      */
393*ed17e06eSJung-uk Kim     if ((*Path == AML_ROOT_PREFIX) && (Path[1]))
394*ed17e06eSJung-uk Kim     {
395*ed17e06eSJung-uk Kim         Path++;
396*ed17e06eSJung-uk Kim     }
397*ed17e06eSJung-uk Kim 
398*ed17e06eSJung-uk Kim     /* Externalize the ACPI pathname */
399f556842eSJung-uk Kim 
400f556842eSJung-uk Kim     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, Path,
401f556842eSJung-uk Kim                 NULL, &ExternalPath);
402f556842eSJung-uk Kim     if (ACPI_FAILURE (Status))
403f556842eSJung-uk Kim     {
404f556842eSJung-uk Kim         return;
405f556842eSJung-uk Kim     }
406f556842eSJung-uk Kim 
407*ed17e06eSJung-uk Kim     /*
408*ed17e06eSJung-uk Kim      * Get the full pathname from the root if "Path" has one or more
409*ed17e06eSJung-uk Kim      * parent prefixes (^). Note: path will not contain a leading '\'.
410*ed17e06eSJung-uk Kim      */
411f556842eSJung-uk Kim     if (*Path == (UINT8) AML_PARENT_PREFIX)
412f556842eSJung-uk Kim     {
413f556842eSJung-uk Kim         Fullpath = AcpiDmNormalizeParentPrefix (Op, ExternalPath);
414f556842eSJung-uk Kim         if (Fullpath)
415f556842eSJung-uk Kim         {
416f556842eSJung-uk Kim             /* Set new external path */
417f556842eSJung-uk Kim 
418f556842eSJung-uk Kim             ACPI_FREE (ExternalPath);
419f556842eSJung-uk Kim             ExternalPath = Fullpath;
420f556842eSJung-uk Kim         }
421f556842eSJung-uk Kim     }
422f556842eSJung-uk Kim 
423f556842eSJung-uk Kim     /* Check all existing externals to ensure no duplicates */
424f556842eSJung-uk Kim 
425f556842eSJung-uk Kim     NextExternal = AcpiGbl_ExternalList;
426f556842eSJung-uk Kim     while (NextExternal)
427f556842eSJung-uk Kim     {
428f556842eSJung-uk Kim         if (!ACPI_STRCMP (ExternalPath, NextExternal->Path))
429f556842eSJung-uk Kim         {
430f556842eSJung-uk Kim             /* Duplicate method, check that the Value (ArgCount) is the same */
431f556842eSJung-uk Kim 
432f556842eSJung-uk Kim             if ((NextExternal->Type == ACPI_TYPE_METHOD) &&
433f556842eSJung-uk Kim                 (NextExternal->Value != Value))
434f556842eSJung-uk Kim             {
435f556842eSJung-uk Kim                 ACPI_ERROR ((AE_INFO,
436ca3cf4faSJung-uk Kim                     "Argument count mismatch for method %s %u %u",
437f556842eSJung-uk Kim                     NextExternal->Path, NextExternal->Value, Value));
438f556842eSJung-uk Kim             }
439f556842eSJung-uk Kim 
440f556842eSJung-uk Kim             /* Allow upgrade of type from ANY */
441f556842eSJung-uk Kim 
442f556842eSJung-uk Kim             else if (NextExternal->Type == ACPI_TYPE_ANY)
443f556842eSJung-uk Kim             {
444f556842eSJung-uk Kim                 NextExternal->Type = Type;
445f556842eSJung-uk Kim                 NextExternal->Value = Value;
446f556842eSJung-uk Kim             }
447f556842eSJung-uk Kim 
448f556842eSJung-uk Kim             ACPI_FREE (ExternalPath);
449f556842eSJung-uk Kim             return;
450f556842eSJung-uk Kim         }
451f556842eSJung-uk Kim 
452f556842eSJung-uk Kim         NextExternal = NextExternal->Next;
453f556842eSJung-uk Kim     }
454f556842eSJung-uk Kim 
455f556842eSJung-uk Kim     /* Allocate and init a new External() descriptor */
456f556842eSJung-uk Kim 
457f556842eSJung-uk Kim     NewExternal = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_EXTERNAL_LIST));
458f556842eSJung-uk Kim     if (!NewExternal)
459f556842eSJung-uk Kim     {
460f556842eSJung-uk Kim         ACPI_FREE (ExternalPath);
461f556842eSJung-uk Kim         return;
462f556842eSJung-uk Kim     }
463f556842eSJung-uk Kim 
464f556842eSJung-uk Kim     NewExternal->Path = ExternalPath;
465f556842eSJung-uk Kim     NewExternal->Type = Type;
466f556842eSJung-uk Kim     NewExternal->Value = Value;
467f556842eSJung-uk Kim     NewExternal->Length = (UINT16) ACPI_STRLEN (ExternalPath);
468f556842eSJung-uk Kim 
469f556842eSJung-uk Kim     /* Was the external path with parent prefix normalized to a fullpath? */
470f556842eSJung-uk Kim 
471f556842eSJung-uk Kim     if (Fullpath == ExternalPath)
472f556842eSJung-uk Kim     {
473f556842eSJung-uk Kim         /* Get new internal path */
474f556842eSJung-uk Kim 
475f556842eSJung-uk Kim         Status = AcpiNsInternalizeName (ExternalPath, &Path);
476f556842eSJung-uk Kim         if (ACPI_FAILURE (Status))
477f556842eSJung-uk Kim         {
478f556842eSJung-uk Kim             ACPI_FREE (ExternalPath);
479f556842eSJung-uk Kim             ACPI_FREE (NewExternal);
480f556842eSJung-uk Kim             return;
481f556842eSJung-uk Kim         }
482f556842eSJung-uk Kim 
483f556842eSJung-uk Kim         /* Set flag to indicate External->InternalPath need to be freed */
484f556842eSJung-uk Kim 
485f556842eSJung-uk Kim         NewExternal->Flags |= ACPI_IPATH_ALLOCATED;
486f556842eSJung-uk Kim     }
487f556842eSJung-uk Kim 
488f556842eSJung-uk Kim     NewExternal->InternalPath = Path;
489f556842eSJung-uk Kim 
490a7a3b383SJung-uk Kim     /* Link the new descriptor into the global list, alphabetically ordered */
491f556842eSJung-uk Kim 
492f556842eSJung-uk Kim     NextExternal = AcpiGbl_ExternalList;
493f556842eSJung-uk Kim     while (NextExternal)
494f556842eSJung-uk Kim     {
495a7a3b383SJung-uk Kim         if (AcpiUtStricmp (NewExternal->Path, NextExternal->Path) < 0)
496f556842eSJung-uk Kim         {
497f556842eSJung-uk Kim             if (PrevExternal)
498f556842eSJung-uk Kim             {
499f556842eSJung-uk Kim                 PrevExternal->Next = NewExternal;
500f556842eSJung-uk Kim             }
501f556842eSJung-uk Kim             else
502f556842eSJung-uk Kim             {
503f556842eSJung-uk Kim                 AcpiGbl_ExternalList = NewExternal;
504f556842eSJung-uk Kim             }
505f556842eSJung-uk Kim 
506f556842eSJung-uk Kim             NewExternal->Next = NextExternal;
507f556842eSJung-uk Kim             return;
508f556842eSJung-uk Kim         }
509f556842eSJung-uk Kim 
510f556842eSJung-uk Kim         PrevExternal = NextExternal;
511f556842eSJung-uk Kim         NextExternal = NextExternal->Next;
512f556842eSJung-uk Kim     }
513f556842eSJung-uk Kim 
514f556842eSJung-uk Kim     if (PrevExternal)
515f556842eSJung-uk Kim     {
516f556842eSJung-uk Kim         PrevExternal->Next = NewExternal;
517f556842eSJung-uk Kim     }
518f556842eSJung-uk Kim     else
519f556842eSJung-uk Kim     {
520f556842eSJung-uk Kim         AcpiGbl_ExternalList = NewExternal;
521f556842eSJung-uk Kim     }
522f556842eSJung-uk Kim }
523f556842eSJung-uk Kim 
524f556842eSJung-uk Kim 
525f556842eSJung-uk Kim /*******************************************************************************
526f556842eSJung-uk Kim  *
527f556842eSJung-uk Kim  * FUNCTION:    AcpiDmAddExternalsToNamespace
528f556842eSJung-uk Kim  *
529f556842eSJung-uk Kim  * PARAMETERS:  None
530f556842eSJung-uk Kim  *
531f556842eSJung-uk Kim  * RETURN:      None
532f556842eSJung-uk Kim  *
533f556842eSJung-uk Kim  * DESCRIPTION: Add all externals to the namespace. Allows externals to be
534f556842eSJung-uk Kim  *              "resolved".
535f556842eSJung-uk Kim  *
536f556842eSJung-uk Kim  ******************************************************************************/
537f556842eSJung-uk Kim 
538f556842eSJung-uk Kim void
539f556842eSJung-uk Kim AcpiDmAddExternalsToNamespace (
540f556842eSJung-uk Kim     void)
541f556842eSJung-uk Kim {
542f556842eSJung-uk Kim     ACPI_STATUS             Status;
543f556842eSJung-uk Kim     ACPI_NAMESPACE_NODE     *Node;
544a7a3b383SJung-uk Kim     ACPI_OPERAND_OBJECT     *ObjDesc;
545f556842eSJung-uk Kim     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
546f556842eSJung-uk Kim 
547f556842eSJung-uk Kim 
548f556842eSJung-uk Kim     while (External)
549f556842eSJung-uk Kim     {
550f556842eSJung-uk Kim         /* Add the external name (object) into the namespace */
551f556842eSJung-uk Kim 
552f556842eSJung-uk Kim         Status = AcpiNsLookup (NULL, External->InternalPath, External->Type,
553f556842eSJung-uk Kim                    ACPI_IMODE_LOAD_PASS1,
554f556842eSJung-uk Kim                    ACPI_NS_EXTERNAL | ACPI_NS_DONT_OPEN_SCOPE,
555f556842eSJung-uk Kim                    NULL, &Node);
556f556842eSJung-uk Kim 
557f556842eSJung-uk Kim         if (ACPI_FAILURE (Status))
558f556842eSJung-uk Kim         {
559f556842eSJung-uk Kim             ACPI_EXCEPTION ((AE_INFO, Status,
560f556842eSJung-uk Kim                 "while adding external to namespace [%s]",
561f556842eSJung-uk Kim                 External->Path));
562f556842eSJung-uk Kim         }
563a7a3b383SJung-uk Kim 
564a7a3b383SJung-uk Kim         else switch (External->Type)
565f556842eSJung-uk Kim         {
566a7a3b383SJung-uk Kim         case ACPI_TYPE_METHOD:
567a7a3b383SJung-uk Kim 
568f556842eSJung-uk Kim             /* For methods, we need to save the argument count */
569f556842eSJung-uk Kim 
570a7a3b383SJung-uk Kim             ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
571a7a3b383SJung-uk Kim             ObjDesc->Method.ParamCount = (UINT8) External->Value;
572a7a3b383SJung-uk Kim             Node->Object = ObjDesc;
573a7a3b383SJung-uk Kim             break;
574a7a3b383SJung-uk Kim 
575a7a3b383SJung-uk Kim         case ACPI_TYPE_REGION:
576a7a3b383SJung-uk Kim 
577a7a3b383SJung-uk Kim             /* Regions require a region sub-object */
578a7a3b383SJung-uk Kim 
579a7a3b383SJung-uk Kim             ObjDesc = AcpiUtCreateInternalObject (ACPI_TYPE_REGION);
580a7a3b383SJung-uk Kim             ObjDesc->Region.Node = Node;
581a7a3b383SJung-uk Kim             Node->Object = ObjDesc;
582a7a3b383SJung-uk Kim             break;
583a7a3b383SJung-uk Kim 
584a7a3b383SJung-uk Kim         default:
585a7a3b383SJung-uk Kim             break;
586f556842eSJung-uk Kim         }
587f556842eSJung-uk Kim 
588f556842eSJung-uk Kim         External = External->Next;
589f556842eSJung-uk Kim     }
590f556842eSJung-uk Kim }
591f556842eSJung-uk Kim 
592f556842eSJung-uk Kim 
593f556842eSJung-uk Kim /*******************************************************************************
594f556842eSJung-uk Kim  *
595f556842eSJung-uk Kim  * FUNCTION:    AcpiDmGetExternalMethodCount
596f556842eSJung-uk Kim  *
597f556842eSJung-uk Kim  * PARAMETERS:  None
598f556842eSJung-uk Kim  *
599f556842eSJung-uk Kim  * RETURN:      The number of control method externals in the external list
600f556842eSJung-uk Kim  *
601f556842eSJung-uk Kim  * DESCRIPTION: Return the number of method externals that have been generated.
602f556842eSJung-uk Kim  *              If any control method externals have been found, we must
603f556842eSJung-uk Kim  *              re-parse the entire definition block with the new information
604f556842eSJung-uk Kim  *              (number of arguments for the methods.) This is limitation of
605f556842eSJung-uk Kim  *              AML, we don't know the number of arguments from the control
606f556842eSJung-uk Kim  *              method invocation itself.
607f556842eSJung-uk Kim  *
608f556842eSJung-uk Kim  ******************************************************************************/
609f556842eSJung-uk Kim 
610f556842eSJung-uk Kim UINT32
611f556842eSJung-uk Kim AcpiDmGetExternalMethodCount (
612f556842eSJung-uk Kim     void)
613f556842eSJung-uk Kim {
614f556842eSJung-uk Kim     ACPI_EXTERNAL_LIST      *External = AcpiGbl_ExternalList;
615f556842eSJung-uk Kim     UINT32                  Count = 0;
616f556842eSJung-uk Kim 
617f556842eSJung-uk Kim 
618f556842eSJung-uk Kim     while (External)
619f556842eSJung-uk Kim     {
620f556842eSJung-uk Kim         if (External->Type == ACPI_TYPE_METHOD)
621f556842eSJung-uk Kim         {
622f556842eSJung-uk Kim             Count++;
623f556842eSJung-uk Kim         }
624f556842eSJung-uk Kim 
625f556842eSJung-uk Kim         External = External->Next;
626f556842eSJung-uk Kim     }
627f556842eSJung-uk Kim 
628f556842eSJung-uk Kim     return (Count);
629f556842eSJung-uk Kim }
630f556842eSJung-uk Kim 
631f556842eSJung-uk Kim 
632f556842eSJung-uk Kim /*******************************************************************************
633f556842eSJung-uk Kim  *
634f556842eSJung-uk Kim  * FUNCTION:    AcpiDmClearExternalList
635f556842eSJung-uk Kim  *
636f556842eSJung-uk Kim  * PARAMETERS:  None
637f556842eSJung-uk Kim  *
638f556842eSJung-uk Kim  * RETURN:      None
639f556842eSJung-uk Kim  *
640f556842eSJung-uk Kim  * DESCRIPTION: Free the entire External info list
641f556842eSJung-uk Kim  *
642f556842eSJung-uk Kim  ******************************************************************************/
643f556842eSJung-uk Kim 
644f556842eSJung-uk Kim void
645f556842eSJung-uk Kim AcpiDmClearExternalList (
646f556842eSJung-uk Kim     void)
647f556842eSJung-uk Kim {
648f556842eSJung-uk Kim     ACPI_EXTERNAL_LIST      *NextExternal;
649f556842eSJung-uk Kim 
650f556842eSJung-uk Kim 
651f556842eSJung-uk Kim     while (AcpiGbl_ExternalList)
652f556842eSJung-uk Kim     {
653f556842eSJung-uk Kim         NextExternal = AcpiGbl_ExternalList->Next;
654f556842eSJung-uk Kim         ACPI_FREE (AcpiGbl_ExternalList->Path);
655f556842eSJung-uk Kim         ACPI_FREE (AcpiGbl_ExternalList);
656f556842eSJung-uk Kim         AcpiGbl_ExternalList = NextExternal;
657f556842eSJung-uk Kim     }
658f556842eSJung-uk Kim }
659f556842eSJung-uk Kim 
660f556842eSJung-uk Kim 
661f556842eSJung-uk Kim /*******************************************************************************
662f556842eSJung-uk Kim  *
663f556842eSJung-uk Kim  * FUNCTION:    AcpiDmEmitExternals
664f556842eSJung-uk Kim  *
665f556842eSJung-uk Kim  * PARAMETERS:  None
666f556842eSJung-uk Kim  *
667f556842eSJung-uk Kim  * RETURN:      None
668f556842eSJung-uk Kim  *
669f556842eSJung-uk Kim  * DESCRIPTION: Emit an External() ASL statement for each of the externals in
670f556842eSJung-uk Kim  *              the global external info list.
671f556842eSJung-uk Kim  *
672f556842eSJung-uk Kim  ******************************************************************************/
673f556842eSJung-uk Kim 
674f556842eSJung-uk Kim void
675f556842eSJung-uk Kim AcpiDmEmitExternals (
676f556842eSJung-uk Kim     void)
677f556842eSJung-uk Kim {
678f556842eSJung-uk Kim     ACPI_EXTERNAL_LIST      *NextExternal;
679f556842eSJung-uk Kim 
680f556842eSJung-uk Kim 
681f556842eSJung-uk Kim     if (!AcpiGbl_ExternalList)
682f556842eSJung-uk Kim     {
683f556842eSJung-uk Kim         return;
684f556842eSJung-uk Kim     }
685f556842eSJung-uk Kim 
686f556842eSJung-uk Kim     /*
687f556842eSJung-uk Kim      * Walk the list of externals (unresolved references)
688f556842eSJung-uk Kim      * found during the AML parsing
689f556842eSJung-uk Kim      */
690f556842eSJung-uk Kim     while (AcpiGbl_ExternalList)
691f556842eSJung-uk Kim     {
692f556842eSJung-uk Kim         AcpiOsPrintf ("    External (%s%s",
693f556842eSJung-uk Kim             AcpiGbl_ExternalList->Path,
694f556842eSJung-uk Kim             AcpiDmGetObjectTypeName (AcpiGbl_ExternalList->Type));
695f556842eSJung-uk Kim 
696f556842eSJung-uk Kim         if (AcpiGbl_ExternalList->Type == ACPI_TYPE_METHOD)
697f556842eSJung-uk Kim         {
698a88e22b7SJung-uk Kim             AcpiOsPrintf (")    // %u Arguments\n",
699f556842eSJung-uk Kim                 AcpiGbl_ExternalList->Value);
700f556842eSJung-uk Kim         }
701f556842eSJung-uk Kim         else
702f556842eSJung-uk Kim         {
703f556842eSJung-uk Kim             AcpiOsPrintf (")\n");
704f556842eSJung-uk Kim         }
705f556842eSJung-uk Kim 
706f556842eSJung-uk Kim         /* Free this external info block and move on to next external */
707f556842eSJung-uk Kim 
708f556842eSJung-uk Kim         NextExternal = AcpiGbl_ExternalList->Next;
709f556842eSJung-uk Kim         if (AcpiGbl_ExternalList->Flags & ACPI_IPATH_ALLOCATED)
710f556842eSJung-uk Kim         {
711f556842eSJung-uk Kim             ACPI_FREE (AcpiGbl_ExternalList->InternalPath);
712f556842eSJung-uk Kim         }
713f556842eSJung-uk Kim 
714f556842eSJung-uk Kim         ACPI_FREE (AcpiGbl_ExternalList->Path);
715f556842eSJung-uk Kim         ACPI_FREE (AcpiGbl_ExternalList);
716f556842eSJung-uk Kim         AcpiGbl_ExternalList = NextExternal;
717f556842eSJung-uk Kim     }
718f556842eSJung-uk Kim 
719f556842eSJung-uk Kim     AcpiOsPrintf ("\n");
720f556842eSJung-uk Kim }
721