xref: /freebsd/sys/contrib/dev/acpica/compiler/aslopt.c (revision 722b16673c40aedf280895f2f2f676bb494518d7)
153289f6aSNate Lawson /******************************************************************************
253289f6aSNate Lawson  *
353289f6aSNate Lawson  * Module Name: aslopt- Compiler optimizations
453289f6aSNate Lawson  *
553289f6aSNate Lawson  *****************************************************************************/
653289f6aSNate Lawson 
70d84335fSJung-uk Kim /******************************************************************************
80d84335fSJung-uk Kim  *
90d84335fSJung-uk Kim  * 1. Copyright Notice
100d84335fSJung-uk Kim  *
11*722b1667SJung-uk Kim  * Some or all of this work - Copyright (c) 1999 - 2023, Intel Corp.
1253289f6aSNate Lawson  * All rights reserved.
1353289f6aSNate Lawson  *
140d84335fSJung-uk Kim  * 2. License
150d84335fSJung-uk Kim  *
160d84335fSJung-uk Kim  * 2.1. This is your license from Intel Corp. under its intellectual property
170d84335fSJung-uk Kim  * rights. You may have additional license terms from the party that provided
180d84335fSJung-uk Kim  * you this software, covering your right to use that party's intellectual
190d84335fSJung-uk Kim  * property rights.
200d84335fSJung-uk Kim  *
210d84335fSJung-uk Kim  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
220d84335fSJung-uk Kim  * copy of the source code appearing in this file ("Covered Code") an
230d84335fSJung-uk Kim  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
240d84335fSJung-uk Kim  * base code distributed originally by Intel ("Original Intel Code") to copy,
250d84335fSJung-uk Kim  * make derivatives, distribute, use and display any portion of the Covered
260d84335fSJung-uk Kim  * Code in any form, with the right to sublicense such rights; and
270d84335fSJung-uk Kim  *
280d84335fSJung-uk Kim  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
290d84335fSJung-uk Kim  * license (with the right to sublicense), under only those claims of Intel
300d84335fSJung-uk Kim  * patents that are infringed by the Original Intel Code, to make, use, sell,
310d84335fSJung-uk Kim  * offer to sell, and import the Covered Code and derivative works thereof
320d84335fSJung-uk Kim  * solely to the minimum extent necessary to exercise the above copyright
330d84335fSJung-uk Kim  * license, and in no event shall the patent license extend to any additions
340d84335fSJung-uk Kim  * to or modifications of the Original Intel Code. No other license or right
350d84335fSJung-uk Kim  * is granted directly or by implication, estoppel or otherwise;
360d84335fSJung-uk Kim  *
370d84335fSJung-uk Kim  * The above copyright and patent license is granted only if the following
380d84335fSJung-uk Kim  * conditions are met:
390d84335fSJung-uk Kim  *
400d84335fSJung-uk Kim  * 3. Conditions
410d84335fSJung-uk Kim  *
420d84335fSJung-uk Kim  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
430d84335fSJung-uk Kim  * Redistribution of source code of any substantial portion of the Covered
440d84335fSJung-uk Kim  * Code or modification with rights to further distribute source must include
450d84335fSJung-uk Kim  * the above Copyright Notice, the above License, this list of Conditions,
460d84335fSJung-uk Kim  * and the following Disclaimer and Export Compliance provision. In addition,
470d84335fSJung-uk Kim  * Licensee must cause all Covered Code to which Licensee contributes to
480d84335fSJung-uk Kim  * contain a file documenting the changes Licensee made to create that Covered
490d84335fSJung-uk Kim  * Code and the date of any change. Licensee must include in that file the
500d84335fSJung-uk Kim  * documentation of any changes made by any predecessor Licensee. Licensee
510d84335fSJung-uk Kim  * must include a prominent statement that the modification is derived,
520d84335fSJung-uk Kim  * directly or indirectly, from Original Intel Code.
530d84335fSJung-uk Kim  *
540d84335fSJung-uk Kim  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
550d84335fSJung-uk Kim  * Redistribution of source code of any substantial portion of the Covered
560d84335fSJung-uk Kim  * Code or modification without rights to further distribute source must
570d84335fSJung-uk Kim  * include the following Disclaimer and Export Compliance provision in the
580d84335fSJung-uk Kim  * documentation and/or other materials provided with distribution. In
590d84335fSJung-uk Kim  * addition, Licensee may not authorize further sublicense of source of any
600d84335fSJung-uk Kim  * portion of the Covered Code, and must include terms to the effect that the
610d84335fSJung-uk Kim  * license from Licensee to its licensee is limited to the intellectual
620d84335fSJung-uk Kim  * property embodied in the software Licensee provides to its licensee, and
630d84335fSJung-uk Kim  * not to intellectual property embodied in modifications its licensee may
640d84335fSJung-uk Kim  * make.
650d84335fSJung-uk Kim  *
660d84335fSJung-uk Kim  * 3.3. Redistribution of Executable. Redistribution in executable form of any
670d84335fSJung-uk Kim  * substantial portion of the Covered Code or modification must reproduce the
680d84335fSJung-uk Kim  * above Copyright Notice, and the following Disclaimer and Export Compliance
690d84335fSJung-uk Kim  * provision in the documentation and/or other materials provided with the
700d84335fSJung-uk Kim  * distribution.
710d84335fSJung-uk Kim  *
720d84335fSJung-uk Kim  * 3.4. Intel retains all right, title, and interest in and to the Original
730d84335fSJung-uk Kim  * Intel Code.
740d84335fSJung-uk Kim  *
750d84335fSJung-uk Kim  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
760d84335fSJung-uk Kim  * Intel shall be used in advertising or otherwise to promote the sale, use or
770d84335fSJung-uk Kim  * other dealings in products derived from or relating to the Covered Code
780d84335fSJung-uk Kim  * without prior written authorization from Intel.
790d84335fSJung-uk Kim  *
800d84335fSJung-uk Kim  * 4. Disclaimer and Export Compliance
810d84335fSJung-uk Kim  *
820d84335fSJung-uk Kim  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
830d84335fSJung-uk Kim  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
840d84335fSJung-uk Kim  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
850d84335fSJung-uk Kim  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
860d84335fSJung-uk Kim  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
870d84335fSJung-uk Kim  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
880d84335fSJung-uk Kim  * PARTICULAR PURPOSE.
890d84335fSJung-uk Kim  *
900d84335fSJung-uk Kim  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
910d84335fSJung-uk Kim  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
920d84335fSJung-uk Kim  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
930d84335fSJung-uk Kim  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
940d84335fSJung-uk Kim  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
950d84335fSJung-uk Kim  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
960d84335fSJung-uk Kim  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
970d84335fSJung-uk Kim  * LIMITED REMEDY.
980d84335fSJung-uk Kim  *
990d84335fSJung-uk Kim  * 4.3. Licensee shall not export, either directly or indirectly, any of this
1000d84335fSJung-uk Kim  * software or system incorporating such software without first obtaining any
1010d84335fSJung-uk Kim  * required license or other approval from the U. S. Department of Commerce or
1020d84335fSJung-uk Kim  * any other agency or department of the United States Government. In the
1030d84335fSJung-uk Kim  * event Licensee exports any such software from the United States or
1040d84335fSJung-uk Kim  * re-exports any such software from a foreign destination, Licensee shall
1050d84335fSJung-uk Kim  * ensure that the distribution and export/re-export of the software is in
1060d84335fSJung-uk Kim  * compliance with all laws, regulations, orders, or other restrictions of the
1070d84335fSJung-uk Kim  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
1080d84335fSJung-uk Kim  * any of its subsidiaries will export/re-export any technical data, process,
1090d84335fSJung-uk Kim  * software, or service, directly or indirectly, to any country for which the
1100d84335fSJung-uk Kim  * United States government or any agency thereof requires an export license,
1110d84335fSJung-uk Kim  * other governmental approval, or letter of assurance, without first obtaining
1120d84335fSJung-uk Kim  * such license, approval or letter.
1130d84335fSJung-uk Kim  *
1140d84335fSJung-uk Kim  *****************************************************************************
1150d84335fSJung-uk Kim  *
1160d84335fSJung-uk Kim  * Alternatively, you may choose to be licensed under the terms of the
1170d84335fSJung-uk Kim  * following license:
1180d84335fSJung-uk Kim  *
119d244b227SJung-uk Kim  * Redistribution and use in source and binary forms, with or without
120d244b227SJung-uk Kim  * modification, are permitted provided that the following conditions
121d244b227SJung-uk Kim  * are met:
122d244b227SJung-uk Kim  * 1. Redistributions of source code must retain the above copyright
123d244b227SJung-uk Kim  *    notice, this list of conditions, and the following disclaimer,
124d244b227SJung-uk Kim  *    without modification.
125d244b227SJung-uk Kim  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
126d244b227SJung-uk Kim  *    substantially similar to the "NO WARRANTY" disclaimer below
127d244b227SJung-uk Kim  *    ("Disclaimer") and any redistribution must be conditioned upon
128d244b227SJung-uk Kim  *    including a substantially similar Disclaimer requirement for further
129d244b227SJung-uk Kim  *    binary redistribution.
130d244b227SJung-uk Kim  * 3. Neither the names of the above-listed copyright holders nor the names
131d244b227SJung-uk Kim  *    of any contributors may be used to endorse or promote products derived
132d244b227SJung-uk Kim  *    from this software without specific prior written permission.
13353289f6aSNate Lawson  *
1340d84335fSJung-uk Kim  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
1350d84335fSJung-uk Kim  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
1360d84335fSJung-uk Kim  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
1370d84335fSJung-uk Kim  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
1380d84335fSJung-uk Kim  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
1390d84335fSJung-uk Kim  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
1400d84335fSJung-uk Kim  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
1410d84335fSJung-uk Kim  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
1420d84335fSJung-uk Kim  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
1430d84335fSJung-uk Kim  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
1440d84335fSJung-uk Kim  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
1450d84335fSJung-uk Kim  *
1460d84335fSJung-uk Kim  * Alternatively, you may choose to be licensed under the terms of the
147d244b227SJung-uk Kim  * GNU General Public License ("GPL") version 2 as published by the Free
148d244b227SJung-uk Kim  * Software Foundation.
14953289f6aSNate Lawson  *
1500d84335fSJung-uk Kim  *****************************************************************************/
15153289f6aSNate Lawson 
152ab6f3bf9SJung-uk Kim #include <contrib/dev/acpica/compiler/aslcompiler.h>
15353289f6aSNate Lawson #include "aslcompiler.y.h"
15453289f6aSNate Lawson 
155ab6f3bf9SJung-uk Kim #include <contrib/dev/acpica/include/acparser.h>
156ab6f3bf9SJung-uk Kim #include <contrib/dev/acpica/include/amlcode.h>
157ab6f3bf9SJung-uk Kim #include <contrib/dev/acpica/include/acnamesp.h>
15853289f6aSNate Lawson 
15953289f6aSNate Lawson 
16053289f6aSNate Lawson #define _COMPONENT          ACPI_COMPILER
16153289f6aSNate Lawson         ACPI_MODULE_NAME    ("aslopt")
16253289f6aSNate Lawson 
16353289f6aSNate Lawson 
164fba7fc7eSJung-uk Kim static UINT32               OptTotal = 0;
165fba7fc7eSJung-uk Kim 
166fba7fc7eSJung-uk Kim /* Local prototypes */
167fba7fc7eSJung-uk Kim 
168fba7fc7eSJung-uk Kim static ACPI_STATUS
169fba7fc7eSJung-uk Kim OptSearchToRoot (
170fba7fc7eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
171fba7fc7eSJung-uk Kim     ACPI_WALK_STATE         *WalkState,
172fba7fc7eSJung-uk Kim     ACPI_NAMESPACE_NODE     *CurrentNode,
173fba7fc7eSJung-uk Kim     ACPI_NAMESPACE_NODE     *TargetNode,
174fba7fc7eSJung-uk Kim     ACPI_BUFFER             *TargetPath,
175fba7fc7eSJung-uk Kim     char                    **NewPath);
176fba7fc7eSJung-uk Kim 
177fba7fc7eSJung-uk Kim static ACPI_STATUS
178fba7fc7eSJung-uk Kim OptBuildShortestPath (
179fba7fc7eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
180fba7fc7eSJung-uk Kim     ACPI_WALK_STATE         *WalkState,
181fba7fc7eSJung-uk Kim     ACPI_NAMESPACE_NODE     *CurrentNode,
182fba7fc7eSJung-uk Kim     ACPI_NAMESPACE_NODE     *TargetNode,
183fba7fc7eSJung-uk Kim     ACPI_BUFFER             *CurrentPath,
184fba7fc7eSJung-uk Kim     ACPI_BUFFER             *TargetPath,
185fba7fc7eSJung-uk Kim     ACPI_SIZE               AmlNameStringLength,
186fba7fc7eSJung-uk Kim     UINT8                   IsDeclaration,
187fba7fc7eSJung-uk Kim     char                    **ReturnNewPath);
188fba7fc7eSJung-uk Kim 
189fba7fc7eSJung-uk Kim static ACPI_STATUS
190fba7fc7eSJung-uk Kim OptOptimizeNameDeclaration (
191fba7fc7eSJung-uk Kim     ACPI_PARSE_OBJECT       *Op,
192fba7fc7eSJung-uk Kim     ACPI_WALK_STATE         *WalkState,
193fba7fc7eSJung-uk Kim     ACPI_NAMESPACE_NODE     *CurrentNode,
194fba7fc7eSJung-uk Kim     ACPI_NAMESPACE_NODE     *TargetNode,
195fba7fc7eSJung-uk Kim     char                    *AmlNameString,
196fba7fc7eSJung-uk Kim     char                    **NewPath);
19753289f6aSNate Lawson 
19853289f6aSNate Lawson 
19953289f6aSNate Lawson /*******************************************************************************
20053289f6aSNate Lawson  *
20153289f6aSNate Lawson  * FUNCTION:    OptSearchToRoot
20253289f6aSNate Lawson  *
20353289f6aSNate Lawson  * PARAMETERS:  Op                  - Current parser op
20453289f6aSNate Lawson  *              WalkState           - Current state
20553289f6aSNate Lawson  *              CurrentNode         - Where we are in the namespace
20653289f6aSNate Lawson  *              TargetNode          - Node to which we are referring
20753289f6aSNate Lawson  *              TargetPath          - External full path to the target node
20853289f6aSNate Lawson  *              NewPath             - Where the optimized path is returned
20953289f6aSNate Lawson  *
21053289f6aSNate Lawson  * RETURN:      Status
21153289f6aSNate Lawson  *
21253289f6aSNate Lawson  * DESCRIPTION: Attempt to optimize a reference to a single 4-character ACPI
21353289f6aSNate Lawson  *              name utilizing the search-to-root name resolution algorithm
21453289f6aSNate Lawson  *              that is used by AML interpreters.
21553289f6aSNate Lawson  *
21653289f6aSNate Lawson  ******************************************************************************/
21753289f6aSNate Lawson 
218fba7fc7eSJung-uk Kim static ACPI_STATUS
OptSearchToRoot(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState,ACPI_NAMESPACE_NODE * CurrentNode,ACPI_NAMESPACE_NODE * TargetNode,ACPI_BUFFER * TargetPath,char ** NewPath)21953289f6aSNate Lawson OptSearchToRoot (
22053289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op,
22153289f6aSNate Lawson     ACPI_WALK_STATE         *WalkState,
22253289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *CurrentNode,
22353289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *TargetNode,
22453289f6aSNate Lawson     ACPI_BUFFER             *TargetPath,
22553289f6aSNate Lawson     char                    **NewPath)
22653289f6aSNate Lawson {
22753289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *Node;
22853289f6aSNate Lawson     ACPI_GENERIC_STATE      ScopeInfo;
22953289f6aSNate Lawson     ACPI_STATUS             Status;
23053289f6aSNate Lawson     char                    *Path;
23153289f6aSNate Lawson 
23253289f6aSNate Lawson 
2331a39cfb0SJung-uk Kim     ACPI_FUNCTION_NAME (OptSearchToRoot);
23453289f6aSNate Lawson 
23553289f6aSNate Lawson 
23653289f6aSNate Lawson     /*
23753289f6aSNate Lawson      * Check if search-to-root can be utilized. Use the last NameSeg of
23853289f6aSNate Lawson      * the NamePath and 1) See if can be found and 2) If found, make
23953289f6aSNate Lawson      * sure that it is the same node that we want. If there is another
24053289f6aSNate Lawson      * name in the search path before the one we want, the nodes will
24153289f6aSNate Lawson      * not match, and we cannot use this optimization.
24253289f6aSNate Lawson      */
243f8146b88SJung-uk Kim     Path = &(((char *) TargetPath->Pointer)[
244278f0de6SJung-uk Kim         TargetPath->Length - ACPI_NAMESEG_SIZE]);
24553289f6aSNate Lawson     ScopeInfo.Scope.Node = CurrentNode;
24653289f6aSNate Lawson 
24753289f6aSNate Lawson     /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */
24853289f6aSNate Lawson 
24953289f6aSNate Lawson     Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
25053289f6aSNate Lawson         ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
25153289f6aSNate Lawson         WalkState, &(Node));
25253289f6aSNate Lawson     if (ACPI_FAILURE (Status))
25353289f6aSNate Lawson     {
25453289f6aSNate Lawson         return (Status);
25553289f6aSNate Lawson     }
25653289f6aSNate Lawson 
25753289f6aSNate Lawson     /*
25853289f6aSNate Lawson      * We found the name, but we must check to make sure that the node
25953289f6aSNate Lawson      * matches. Otherwise, there is another identical name in the search
26053289f6aSNate Lawson      * path that precludes the use of this optimization.
26153289f6aSNate Lawson      */
26253289f6aSNate Lawson     if (Node != TargetNode)
26353289f6aSNate Lawson     {
26453289f6aSNate Lawson         /*
26553289f6aSNate Lawson          * This means that another object with the same name was found first,
26653289f6aSNate Lawson          * and we cannot use this optimization.
26753289f6aSNate Lawson          */
26853289f6aSNate Lawson         return (AE_NOT_FOUND);
26953289f6aSNate Lawson     }
27053289f6aSNate Lawson 
27153289f6aSNate Lawson     /* Found the node, we can use this optimization */
27253289f6aSNate Lawson 
27353289f6aSNate Lawson     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
27453289f6aSNate Lawson         "NAMESEG:   %-24s", Path));
27553289f6aSNate Lawson 
27653289f6aSNate Lawson     /* We must allocate a new string for the name (TargetPath gets deleted) */
27753289f6aSNate Lawson 
278278f0de6SJung-uk Kim     *NewPath = UtLocalCacheCalloc (ACPI_NAMESEG_SIZE + 1);
2795ef50723SJung-uk Kim     strcpy (*NewPath, Path);
28053289f6aSNate Lawson 
2815ef50723SJung-uk Kim     if (strncmp (*NewPath, "_T_", 3))
282c8466860SMark Santcroos     {
283f8146b88SJung-uk Kim         AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION,
284f8146b88SJung-uk Kim             Op, *NewPath);
285c8466860SMark Santcroos     }
28653289f6aSNate Lawson 
28753289f6aSNate Lawson     return (AE_OK);
28853289f6aSNate Lawson }
28953289f6aSNate Lawson 
29053289f6aSNate Lawson 
29153289f6aSNate Lawson /*******************************************************************************
29253289f6aSNate Lawson  *
29353289f6aSNate Lawson  * FUNCTION:    OptBuildShortestPath
29453289f6aSNate Lawson  *
29553289f6aSNate Lawson  * PARAMETERS:  Op                  - Current parser op
29653289f6aSNate Lawson  *              WalkState           - Current state
29753289f6aSNate Lawson  *              CurrentNode         - Where we are in the namespace
29853289f6aSNate Lawson  *              TargetNode          - Node to which we are referring
29953289f6aSNate Lawson  *              CurrentPath         - External full path to the current node
30053289f6aSNate Lawson  *              TargetPath          - External full path to the target node
30153289f6aSNate Lawson  *              AmlNameStringLength - Length of the original namepath
30253289f6aSNate Lawson  *              IsDeclaration       - TRUE for declaration, FALSE for reference
30353289f6aSNate Lawson  *              ReturnNewPath       - Where the optimized path is returned
30453289f6aSNate Lawson  *
30553289f6aSNate Lawson  * RETURN:      Status
30653289f6aSNate Lawson  *
30753289f6aSNate Lawson  * DESCRIPTION: Build an optimal NamePath using carats
30853289f6aSNate Lawson  *
30953289f6aSNate Lawson  ******************************************************************************/
31053289f6aSNate Lawson 
311fba7fc7eSJung-uk Kim static ACPI_STATUS
OptBuildShortestPath(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState,ACPI_NAMESPACE_NODE * CurrentNode,ACPI_NAMESPACE_NODE * TargetNode,ACPI_BUFFER * CurrentPath,ACPI_BUFFER * TargetPath,ACPI_SIZE AmlNameStringLength,UINT8 IsDeclaration,char ** ReturnNewPath)31253289f6aSNate Lawson OptBuildShortestPath (
31353289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op,
31453289f6aSNate Lawson     ACPI_WALK_STATE         *WalkState,
31553289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *CurrentNode,
31653289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *TargetNode,
31753289f6aSNate Lawson     ACPI_BUFFER             *CurrentPath,
31853289f6aSNate Lawson     ACPI_BUFFER             *TargetPath,
31953289f6aSNate Lawson     ACPI_SIZE               AmlNameStringLength,
32053289f6aSNate Lawson     UINT8                   IsDeclaration,
32153289f6aSNate Lawson     char                    **ReturnNewPath)
32253289f6aSNate Lawson {
32353289f6aSNate Lawson     UINT32                  NumCommonSegments;
32453289f6aSNate Lawson     UINT32                  MaxCommonSegments;
325a9f12690SJung-uk Kim     UINT32                  Index;
32653289f6aSNate Lawson     UINT32                  NumCarats;
327a9f12690SJung-uk Kim     UINT32                  i;
328f8146b88SJung-uk Kim     char                    *NewPathInternal;
32953289f6aSNate Lawson     char                    *NewPathExternal;
33053289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *Node;
33153289f6aSNate Lawson     ACPI_GENERIC_STATE      ScopeInfo;
33253289f6aSNate Lawson     ACPI_STATUS             Status;
33353289f6aSNate Lawson     BOOLEAN                 SubPath = FALSE;
33453289f6aSNate Lawson 
33553289f6aSNate Lawson 
3361a39cfb0SJung-uk Kim     ACPI_FUNCTION_NAME (OptBuildShortestPath);
33753289f6aSNate Lawson 
33853289f6aSNate Lawson 
33953289f6aSNate Lawson     ScopeInfo.Scope.Node = CurrentNode;
34053289f6aSNate Lawson 
34153289f6aSNate Lawson     /*
34253289f6aSNate Lawson      * Determine the maximum number of NameSegs that the Target and Current paths
34353289f6aSNate Lawson      * can possibly have in common. (To optimize, we have to have at least 1)
34453289f6aSNate Lawson      *
34553289f6aSNate Lawson      * Note: The external NamePath string lengths are always a multiple of 5
346278f0de6SJung-uk Kim      * (ACPI_NAMESEG_SIZE + separator)
34753289f6aSNate Lawson      */
34853289f6aSNate Lawson     MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
34953289f6aSNate Lawson     if (CurrentPath->Length < TargetPath->Length)
35053289f6aSNate Lawson     {
35153289f6aSNate Lawson         MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
35253289f6aSNate Lawson     }
35353289f6aSNate Lawson 
35453289f6aSNate Lawson     /*
35553289f6aSNate Lawson      * Determine how many NameSegs the two paths have in common.
35653289f6aSNate Lawson      * (Starting from the root)
35753289f6aSNate Lawson      */
35853289f6aSNate Lawson     for (NumCommonSegments = 0;
35953289f6aSNate Lawson          NumCommonSegments < MaxCommonSegments;
36053289f6aSNate Lawson          NumCommonSegments++)
36153289f6aSNate Lawson     {
36253289f6aSNate Lawson         /* Compare two single NameSegs */
36353289f6aSNate Lawson 
364f8146b88SJung-uk Kim         Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
365f8146b88SJung-uk Kim 
366278f0de6SJung-uk Kim         if (!ACPI_COMPARE_NAMESEG (
367f8146b88SJung-uk Kim             &(ACPI_CAST_PTR (char, TargetPath->Pointer)) [Index],
368f8146b88SJung-uk Kim             &(ACPI_CAST_PTR (char, CurrentPath->Pointer)) [Index]))
36953289f6aSNate Lawson         {
37053289f6aSNate Lawson             /* Mismatch */
37153289f6aSNate Lawson 
37253289f6aSNate Lawson             break;
37353289f6aSNate Lawson         }
37453289f6aSNate Lawson     }
37553289f6aSNate Lawson 
376a88e22b7SJung-uk Kim     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %u",
377fba7fc7eSJung-uk Kim         NumCommonSegments));
37853289f6aSNate Lawson 
37953289f6aSNate Lawson     /* There must be at least 1 common NameSeg in order to optimize */
38053289f6aSNate Lawson 
38153289f6aSNate Lawson     if (NumCommonSegments == 0)
38253289f6aSNate Lawson     {
38353289f6aSNate Lawson         return (AE_NOT_FOUND);
38453289f6aSNate Lawson     }
38553289f6aSNate Lawson 
38653289f6aSNate Lawson     if (NumCommonSegments == MaxCommonSegments)
38753289f6aSNate Lawson     {
38853289f6aSNate Lawson         if (CurrentPath->Length == TargetPath->Length)
38953289f6aSNate Lawson         {
39053289f6aSNate Lawson             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
39153289f6aSNate Lawson             return (AE_NOT_FOUND);
39253289f6aSNate Lawson         }
39353289f6aSNate Lawson         else
39453289f6aSNate Lawson         {
39553289f6aSNate Lawson             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
39653289f6aSNate Lawson             SubPath = TRUE;
39753289f6aSNate Lawson         }
39853289f6aSNate Lawson     }
39953289f6aSNate Lawson 
40053289f6aSNate Lawson     /* Determine how many prefix Carats are required */
40153289f6aSNate Lawson 
402fba7fc7eSJung-uk Kim     NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) -
403fba7fc7eSJung-uk Kim         NumCommonSegments;
40453289f6aSNate Lawson 
40553289f6aSNate Lawson     /*
40653289f6aSNate Lawson      * Construct a new target string
40753289f6aSNate Lawson      */
408f8146b88SJung-uk Kim     NewPathExternal =
4096f1f1a63SJung-uk Kim         UtLocalCacheCalloc (TargetPath->Length + NumCarats + 1);
41053289f6aSNate Lawson 
41153289f6aSNate Lawson     /* Insert the Carats into the Target string */
41253289f6aSNate Lawson 
41353289f6aSNate Lawson     for (i = 0; i < NumCarats; i++)
41453289f6aSNate Lawson     {
415efcc2a30SJung-uk Kim         NewPathExternal[i] = AML_PARENT_PREFIX;
41653289f6aSNate Lawson     }
41753289f6aSNate Lawson 
418fba7fc7eSJung-uk Kim     /*
419fba7fc7eSJung-uk Kim      * Copy only the necessary (optimal) segments from the original
420fba7fc7eSJung-uk Kim      * target string
421fba7fc7eSJung-uk Kim      */
42253289f6aSNate Lawson     Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
42353289f6aSNate Lawson 
42453289f6aSNate Lawson     /* Special handling for exact subpath in a name declaration */
42553289f6aSNate Lawson 
426f8146b88SJung-uk Kim     if (IsDeclaration && SubPath &&
427f8146b88SJung-uk Kim         (CurrentPath->Length > TargetPath->Length))
42853289f6aSNate Lawson     {
42953289f6aSNate Lawson         /*
430fba7fc7eSJung-uk Kim          * The current path is longer than the target, and the target is a
431fba7fc7eSJung-uk Kim          * subpath of the current path. We must include one more NameSeg of
432fba7fc7eSJung-uk Kim          * the target path
43353289f6aSNate Lawson          */
43453289f6aSNate Lawson         Index -= ACPI_PATH_SEGMENT_LENGTH;
435c8466860SMark Santcroos 
436c8466860SMark Santcroos         /* Special handling for Scope() operator */
437c8466860SMark Santcroos 
438c8466860SMark Santcroos         if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
439c8466860SMark Santcroos         {
440efcc2a30SJung-uk Kim             NewPathExternal[i] = AML_PARENT_PREFIX;
441c8466860SMark Santcroos             i++;
442c8466860SMark Santcroos             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
443c8466860SMark Santcroos         }
44453289f6aSNate Lawson     }
44553289f6aSNate Lawson 
446fba7fc7eSJung-uk Kim     /* Make sure we haven't gone off the end of the target path */
447fba7fc7eSJung-uk Kim 
448fba7fc7eSJung-uk Kim     if (Index > TargetPath->Length)
449fba7fc7eSJung-uk Kim     {
450fba7fc7eSJung-uk Kim         Index = TargetPath->Length;
451fba7fc7eSJung-uk Kim     }
452fba7fc7eSJung-uk Kim 
453f8146b88SJung-uk Kim     strcpy (&NewPathExternal[i],
454f8146b88SJung-uk Kim         &(ACPI_CAST_PTR (char, TargetPath->Pointer))[Index]);
45553289f6aSNate Lawson     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));
45653289f6aSNate Lawson 
45753289f6aSNate Lawson     /*
458fba7fc7eSJung-uk Kim      * Internalize the new target string and check it against the original
459fba7fc7eSJung-uk Kim      * string to make sure that this is in fact an optimization. If the
460fba7fc7eSJung-uk Kim      * original string is already optimal, there is no point in continuing.
46153289f6aSNate Lawson      */
462f8146b88SJung-uk Kim     Status = AcpiNsInternalizeName (NewPathExternal, &NewPathInternal);
46353289f6aSNate Lawson     if (ACPI_FAILURE (Status))
46453289f6aSNate Lawson     {
465fba7fc7eSJung-uk Kim         AslCoreSubsystemError (Op, Status, "Internalizing new NamePath",
466fba7fc7eSJung-uk Kim             ASL_NO_ABORT);
467f8146b88SJung-uk Kim         goto Cleanup;
46853289f6aSNate Lawson     }
46953289f6aSNate Lawson 
470f8146b88SJung-uk Kim     if (strlen (NewPathInternal) >= AmlNameStringLength)
47153289f6aSNate Lawson     {
472fba7fc7eSJung-uk Kim         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
4731a39cfb0SJung-uk Kim             " NOT SHORTER (New %u old %u)",
474f8146b88SJung-uk Kim             (UINT32) strlen (NewPathInternal),
475f8146b88SJung-uk Kim             (UINT32) AmlNameStringLength));
476f8146b88SJung-uk Kim 
477f8146b88SJung-uk Kim         ACPI_FREE (NewPathInternal);
478f8146b88SJung-uk Kim         Status = AE_NOT_FOUND;
479f8146b88SJung-uk Kim         goto Cleanup;
48053289f6aSNate Lawson     }
48153289f6aSNate Lawson 
48253289f6aSNate Lawson     /*
48353289f6aSNate Lawson      * Check to make sure that the optimization finds the node we are
48453289f6aSNate Lawson      * looking for. This is simply a sanity check on the new
48553289f6aSNate Lawson      * path that has been created.
48653289f6aSNate Lawson      */
487f8146b88SJung-uk Kim     Status = AcpiNsLookup (&ScopeInfo, NewPathInternal,
48853289f6aSNate Lawson         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
48953289f6aSNate Lawson         ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
49053289f6aSNate Lawson     if (ACPI_SUCCESS (Status))
49153289f6aSNate Lawson     {
49253289f6aSNate Lawson         /* Found the namepath, but make sure the node is correct */
49353289f6aSNate Lawson 
49453289f6aSNate Lawson         if (Node == TargetNode)
49553289f6aSNate Lawson         {
49653289f6aSNate Lawson             /* The lookup matched the node, accept this optimization */
49753289f6aSNate Lawson 
49853289f6aSNate Lawson             AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
49953289f6aSNate Lawson                 Op, NewPathExternal);
500f8146b88SJung-uk Kim             *ReturnNewPath = NewPathInternal;
50153289f6aSNate Lawson         }
50253289f6aSNate Lawson         else
50353289f6aSNate Lawson         {
50453289f6aSNate Lawson             /* Node is not correct, do not use this optimization */
50553289f6aSNate Lawson 
50653289f6aSNate Lawson             Status = AE_NOT_FOUND;
50753289f6aSNate Lawson             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
50853289f6aSNate Lawson             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
50953289f6aSNate Lawson                 "Not using optimized name - found wrong node");
51053289f6aSNate Lawson         }
51153289f6aSNate Lawson     }
51253289f6aSNate Lawson     else
51353289f6aSNate Lawson     {
51453289f6aSNate Lawson         /* The lookup failed, we obviously cannot use this optimization */
51553289f6aSNate Lawson 
516f8146b88SJung-uk Kim         ACPI_FREE (NewPathInternal);
517f8146b88SJung-uk Kim 
51853289f6aSNate Lawson         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
51953289f6aSNate Lawson         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
52053289f6aSNate Lawson             "Not using optimized name - did not find node");
52153289f6aSNate Lawson     }
52253289f6aSNate Lawson 
523f8146b88SJung-uk Kim Cleanup:
524f8146b88SJung-uk Kim 
52553289f6aSNate Lawson     return (Status);
52653289f6aSNate Lawson }
52753289f6aSNate Lawson 
52853289f6aSNate Lawson 
52953289f6aSNate Lawson /*******************************************************************************
53053289f6aSNate Lawson  *
53153289f6aSNate Lawson  * FUNCTION:    OptOptimizeNameDeclaration
53253289f6aSNate Lawson  *
53353289f6aSNate Lawson  * PARAMETERS:  Op                  - Current parser op
53453289f6aSNate Lawson  *              WalkState           - Current state
53553289f6aSNate Lawson  *              CurrentNode         - Where we are in the namespace
53653289f6aSNate Lawson  *              AmlNameString       - Unoptimized namepath
53753289f6aSNate Lawson  *              NewPath             - Where the optimized path is returned
53853289f6aSNate Lawson  *
53953289f6aSNate Lawson  * RETURN:      Status. AE_OK If path is optimized
54053289f6aSNate Lawson  *
54153289f6aSNate Lawson  * DESCRIPTION: Perform a simple optimization of removing an extraneous
54253289f6aSNate Lawson  *              backslash prefix if we are already at the root scope.
54353289f6aSNate Lawson  *
54453289f6aSNate Lawson  ******************************************************************************/
54553289f6aSNate Lawson 
546fba7fc7eSJung-uk Kim static ACPI_STATUS
OptOptimizeNameDeclaration(ACPI_PARSE_OBJECT * Op,ACPI_WALK_STATE * WalkState,ACPI_NAMESPACE_NODE * CurrentNode,ACPI_NAMESPACE_NODE * TargetNode,char * AmlNameString,char ** NewPath)54753289f6aSNate Lawson OptOptimizeNameDeclaration (
54853289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op,
54953289f6aSNate Lawson     ACPI_WALK_STATE         *WalkState,
55053289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *CurrentNode,
55153289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *TargetNode,
55253289f6aSNate Lawson     char                    *AmlNameString,
55353289f6aSNate Lawson     char                    **NewPath)
55453289f6aSNate Lawson {
55553289f6aSNate Lawson     ACPI_STATUS             Status;
55653289f6aSNate Lawson     char                    *NewPathExternal;
55753289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *Node;
55853289f6aSNate Lawson 
55953289f6aSNate Lawson 
5601a39cfb0SJung-uk Kim     ACPI_FUNCTION_TRACE (OptOptimizeNameDeclaration);
56153289f6aSNate Lawson 
56253289f6aSNate Lawson 
56353289f6aSNate Lawson     if (((CurrentNode == AcpiGbl_RootNode) ||
564f8146b88SJung-uk Kim         (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITION_BLOCK)) &&
565efcc2a30SJung-uk Kim             (ACPI_IS_ROOT_PREFIX (AmlNameString[0])))
56653289f6aSNate Lawson     {
56753289f6aSNate Lawson         /*
56853289f6aSNate Lawson          * The current scope is the root, and the namepath has a root prefix
56953289f6aSNate Lawson          * that is therefore extraneous. Remove it.
57053289f6aSNate Lawson          */
57153289f6aSNate Lawson         *NewPath = &AmlNameString[1];
57253289f6aSNate Lawson 
57353289f6aSNate Lawson         /* Debug output */
57453289f6aSNate Lawson 
57553289f6aSNate Lawson         Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath,
57653289f6aSNate Lawson             NULL, &NewPathExternal);
57753289f6aSNate Lawson         if (ACPI_FAILURE (Status))
57853289f6aSNate Lawson         {
579fba7fc7eSJung-uk Kim             AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
580fba7fc7eSJung-uk Kim                 ASL_NO_ABORT);
58153289f6aSNate Lawson             return (Status);
58253289f6aSNate Lawson         }
58353289f6aSNate Lawson 
58453289f6aSNate Lawson         /*
58553289f6aSNate Lawson          * Check to make sure that the optimization finds the node we are
58653289f6aSNate Lawson          * looking for. This is simply a sanity check on the new
58753289f6aSNate Lawson          * path that has been created.
588042ff955SJung-uk Kim          *
589042ff955SJung-uk Kim          * We know that we are at the root, so NULL is used for the scope.
59053289f6aSNate Lawson          */
591042ff955SJung-uk Kim         Status = AcpiNsLookup (NULL, *NewPath,
59253289f6aSNate Lawson             ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
59353289f6aSNate Lawson             ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
59453289f6aSNate Lawson         if (ACPI_SUCCESS (Status))
59553289f6aSNate Lawson         {
59653289f6aSNate Lawson             /* Found the namepath, but make sure the node is correct */
59753289f6aSNate Lawson 
59853289f6aSNate Lawson             if (Node == TargetNode)
59953289f6aSNate Lawson             {
60053289f6aSNate Lawson                 /* The lookup matched the node, accept this optimization */
60153289f6aSNate Lawson 
60253289f6aSNate Lawson                 AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
60353289f6aSNate Lawson                     Op, NewPathExternal);
60453289f6aSNate Lawson 
60553289f6aSNate Lawson                 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
60653289f6aSNate Lawson                     "AT ROOT:   %-24s", NewPathExternal));
60753289f6aSNate Lawson             }
60853289f6aSNate Lawson             else
60953289f6aSNate Lawson             {
61053289f6aSNate Lawson                 /* Node is not correct, do not use this optimization */
61153289f6aSNate Lawson 
61253289f6aSNate Lawson                 Status = AE_NOT_FOUND;
613fba7fc7eSJung-uk Kim                 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
614fba7fc7eSJung-uk Kim                     " ***** WRONG NODE"));
61553289f6aSNate Lawson                 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
61653289f6aSNate Lawson                     "Not using optimized name - found wrong node");
61753289f6aSNate Lawson             }
61853289f6aSNate Lawson         }
61953289f6aSNate Lawson         else
62053289f6aSNate Lawson         {
62153289f6aSNate Lawson             /* The lookup failed, we obviously cannot use this optimization */
62253289f6aSNate Lawson 
623fba7fc7eSJung-uk Kim             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
624fba7fc7eSJung-uk Kim                 " ***** NOT FOUND"));
62553289f6aSNate Lawson             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
62653289f6aSNate Lawson                 "Not using optimized name - did not find node");
62753289f6aSNate Lawson         }
62853289f6aSNate Lawson 
6291a39cfb0SJung-uk Kim         ACPI_FREE (NewPathExternal);
63053289f6aSNate Lawson         return (Status);
63153289f6aSNate Lawson     }
63253289f6aSNate Lawson 
63353289f6aSNate Lawson     /* Could not optimize */
63453289f6aSNate Lawson 
63553289f6aSNate Lawson     return (AE_NOT_FOUND);
63653289f6aSNate Lawson }
63753289f6aSNate Lawson 
63853289f6aSNate Lawson 
63953289f6aSNate Lawson /*******************************************************************************
64053289f6aSNate Lawson  *
64153289f6aSNate Lawson  * FUNCTION:    OptOptimizeNamePath
64253289f6aSNate Lawson  *
64353289f6aSNate Lawson  * PARAMETERS:  Op                  - Current parser op
64453289f6aSNate Lawson  *              Flags               - Opcode info flags
64553289f6aSNate Lawson  *              WalkState           - Current state
64653289f6aSNate Lawson  *              AmlNameString       - Unoptimized namepath
64753289f6aSNate Lawson  *              TargetNode          - Node to which AmlNameString refers
64853289f6aSNate Lawson  *
64953289f6aSNate Lawson  * RETURN:      None. If path is optimized, the Op is updated with new path
65053289f6aSNate Lawson  *
65153289f6aSNate Lawson  * DESCRIPTION: Optimize a Named Declaration or Reference to the minimal length.
65253289f6aSNate Lawson  *              Must take into account both the current location in the
65353289f6aSNate Lawson  *              namespace and the actual reference path.
65453289f6aSNate Lawson  *
65553289f6aSNate Lawson  ******************************************************************************/
65653289f6aSNate Lawson 
65753289f6aSNate Lawson void
OptOptimizeNamePath(ACPI_PARSE_OBJECT * Op,UINT32 Flags,ACPI_WALK_STATE * WalkState,char * AmlNameString,ACPI_NAMESPACE_NODE * TargetNode)65853289f6aSNate Lawson OptOptimizeNamePath (
65953289f6aSNate Lawson     ACPI_PARSE_OBJECT       *Op,
66053289f6aSNate Lawson     UINT32                  Flags,
66153289f6aSNate Lawson     ACPI_WALK_STATE         *WalkState,
66253289f6aSNate Lawson     char                    *AmlNameString,
66353289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *TargetNode)
66453289f6aSNate Lawson {
66553289f6aSNate Lawson     ACPI_STATUS             Status;
66653289f6aSNate Lawson     ACPI_BUFFER             TargetPath;
66753289f6aSNate Lawson     ACPI_BUFFER             CurrentPath;
66853289f6aSNate Lawson     ACPI_SIZE               AmlNameStringLength;
66953289f6aSNate Lawson     ACPI_NAMESPACE_NODE     *CurrentNode;
67053289f6aSNate Lawson     char                    *ExternalNameString;
67153289f6aSNate Lawson     char                    *NewPath = NULL;
67253289f6aSNate Lawson     ACPI_SIZE               HowMuchShorter;
67353289f6aSNate Lawson     ACPI_PARSE_OBJECT       *NextOp;
67453289f6aSNate Lawson 
67553289f6aSNate Lawson 
6761a39cfb0SJung-uk Kim     ACPI_FUNCTION_TRACE (OptOptimizeNamePath);
67753289f6aSNate Lawson 
67853289f6aSNate Lawson 
67953289f6aSNate Lawson     /* This is an optional optimization */
68053289f6aSNate Lawson 
6816f1f1a63SJung-uk Kim     if (!AslGbl_ReferenceOptimizationFlag)
68253289f6aSNate Lawson     {
68353289f6aSNate Lawson         return_VOID;
68453289f6aSNate Lawson     }
68553289f6aSNate Lawson 
68653289f6aSNate Lawson     /* Various required items */
68753289f6aSNate Lawson 
688c8466860SMark Santcroos     if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent)
68953289f6aSNate Lawson     {
69053289f6aSNate Lawson         return_VOID;
69153289f6aSNate Lawson     }
69253289f6aSNate Lawson 
693313a0c13SJung-uk Kim     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
694313a0c13SJung-uk Kim         "PATH OPTIMIZE: Line %5d ParentOp [%12.12s] ThisOp [%12.12s] ",
69553289f6aSNate Lawson         Op->Asl.LogicalLineNumber,
69653289f6aSNate Lawson         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode),
69753289f6aSNate Lawson         AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
69853289f6aSNate Lawson 
69953289f6aSNate Lawson     if (!(Flags & (AML_NAMED | AML_CREATE)))
70053289f6aSNate Lawson     {
7015f9b24faSJung-uk Kim         if (Op->Asl.CompileFlags & OP_IS_NAME_DECLARATION)
70253289f6aSNate Lawson         {
70353289f6aSNate Lawson             /* We don't want to fuss with actual name declaration nodes here */
70453289f6aSNate Lawson 
70553289f6aSNate Lawson             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
70653289f6aSNate Lawson                 "******* NAME DECLARATION\n"));
70753289f6aSNate Lawson             return_VOID;
70853289f6aSNate Lawson         }
70953289f6aSNate Lawson     }
71053289f6aSNate Lawson 
71153289f6aSNate Lawson     /*
71253289f6aSNate Lawson      * The original path must be longer than one NameSeg (4 chars) for there
71353289f6aSNate Lawson      * to be any possibility that it can be optimized to a shorter string
71453289f6aSNate Lawson      */
7155ef50723SJung-uk Kim     AmlNameStringLength = strlen (AmlNameString);
716278f0de6SJung-uk Kim     if (AmlNameStringLength <= ACPI_NAMESEG_SIZE)
71753289f6aSNate Lawson     {
71853289f6aSNate Lawson         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
71953289f6aSNate Lawson             "NAMESEG %4.4s\n", AmlNameString));
72053289f6aSNate Lawson         return_VOID;
72153289f6aSNate Lawson     }
72253289f6aSNate Lawson 
72353289f6aSNate Lawson     /*
72453289f6aSNate Lawson      * We need to obtain the node that represents the current scope -- where
72553289f6aSNate Lawson      * we are right now in the namespace. We will compare this path
72653289f6aSNate Lawson      * against the Namepath, looking for commonality.
72753289f6aSNate Lawson      */
72853289f6aSNate Lawson     CurrentNode = AcpiGbl_RootNode;
72953289f6aSNate Lawson     if (WalkState->ScopeInfo)
73053289f6aSNate Lawson     {
73153289f6aSNate Lawson         CurrentNode = WalkState->ScopeInfo->Scope.Node;
73253289f6aSNate Lawson     }
73353289f6aSNate Lawson 
73453289f6aSNate Lawson     if (Flags & (AML_NAMED | AML_CREATE))
73553289f6aSNate Lawson     {
73653289f6aSNate Lawson         /* This is the declaration of a new name */
73753289f6aSNate Lawson 
738313a0c13SJung-uk Kim         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME\n"));
73953289f6aSNate Lawson 
740fba7fc7eSJung-uk Kim         /*
741042ff955SJung-uk Kim          * The node of interest is the parent of this node (the containing
742042ff955SJung-uk Kim          * scope). The actual namespace node may be up more than one level
743042ff955SJung-uk Kim          * of parse op or it may not exist at all (if we traverse back
744042ff955SJung-uk Kim          * up to the root.)
745fba7fc7eSJung-uk Kim          */
746042ff955SJung-uk Kim         NextOp = Op->Asl.Parent;
747042ff955SJung-uk Kim         while (NextOp && (!NextOp->Asl.Node))
748042ff955SJung-uk Kim         {
749042ff955SJung-uk Kim             NextOp = NextOp->Asl.Parent;
750042ff955SJung-uk Kim         }
751f8146b88SJung-uk Kim 
752042ff955SJung-uk Kim         if (NextOp && NextOp->Asl.Node)
753042ff955SJung-uk Kim         {
754042ff955SJung-uk Kim             CurrentNode = NextOp->Asl.Node;
755042ff955SJung-uk Kim         }
756042ff955SJung-uk Kim         else
75753289f6aSNate Lawson         {
75853289f6aSNate Lawson             CurrentNode = AcpiGbl_RootNode;
75953289f6aSNate Lawson         }
76053289f6aSNate Lawson     }
76153289f6aSNate Lawson     else
76253289f6aSNate Lawson     {
76353289f6aSNate Lawson         /* This is a reference to an existing named object */
76453289f6aSNate Lawson 
765313a0c13SJung-uk Kim         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REFERENCE\n"));
76653289f6aSNate Lawson     }
76753289f6aSNate Lawson 
76853289f6aSNate Lawson     /*
76953289f6aSNate Lawson      * Obtain the full paths to the two nodes that we are interested in
77053289f6aSNate Lawson      * (Target and current namespace location) in external
77153289f6aSNate Lawson      * format -- something we can easily manipulate
77253289f6aSNate Lawson      */
77353289f6aSNate Lawson     TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
774fe0f0bbbSJung-uk Kim     Status = AcpiNsHandleToPathname (TargetNode, &TargetPath, FALSE);
77553289f6aSNate Lawson     if (ACPI_FAILURE (Status))
77653289f6aSNate Lawson     {
777fba7fc7eSJung-uk Kim         AslCoreSubsystemError (Op, Status, "Getting Target NamePath",
778fba7fc7eSJung-uk Kim             ASL_NO_ABORT);
77953289f6aSNate Lawson         return_VOID;
78053289f6aSNate Lawson     }
781f8146b88SJung-uk Kim 
78253289f6aSNate Lawson     TargetPath.Length--;    /* Subtract one for null terminator */
78353289f6aSNate Lawson 
78453289f6aSNate Lawson     /* CurrentPath is the path to this scope (where we are in the namespace) */
78553289f6aSNate Lawson 
78653289f6aSNate Lawson     CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
787fe0f0bbbSJung-uk Kim     Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath, FALSE);
78853289f6aSNate Lawson     if (ACPI_FAILURE (Status))
78953289f6aSNate Lawson     {
790fba7fc7eSJung-uk Kim         AslCoreSubsystemError (Op, Status, "Getting Current NamePath",
791fba7fc7eSJung-uk Kim             ASL_NO_ABORT);
79253289f6aSNate Lawson         return_VOID;
79353289f6aSNate Lawson     }
794f8146b88SJung-uk Kim 
79553289f6aSNate Lawson     CurrentPath.Length--;   /* Subtract one for null terminator */
79653289f6aSNate Lawson 
79753289f6aSNate Lawson     /* Debug output only */
79853289f6aSNate Lawson 
79953289f6aSNate Lawson     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString,
80053289f6aSNate Lawson         NULL, &ExternalNameString);
80153289f6aSNate Lawson     if (ACPI_FAILURE (Status))
80253289f6aSNate Lawson     {
803fba7fc7eSJung-uk Kim         AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
804fba7fc7eSJung-uk Kim             ASL_NO_ABORT);
80553289f6aSNate Lawson         return_VOID;
80653289f6aSNate Lawson     }
80753289f6aSNate Lawson 
80853289f6aSNate Lawson     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
809313a0c13SJung-uk Kim         "CURRENT SCOPE: (%2u) %-37s FULL PATH TO NAME: (%2u) %-32s ACTUAL AML:%-32s\n",
810313a0c13SJung-uk Kim         (UINT32) CurrentPath.Length, (char *) CurrentPath.Pointer,
811313a0c13SJung-uk Kim         (UINT32) TargetPath.Length, (char *) TargetPath.Pointer,
812313a0c13SJung-uk Kim         ExternalNameString));
81353289f6aSNate Lawson 
8141a39cfb0SJung-uk Kim     ACPI_FREE (ExternalNameString);
81553289f6aSNate Lawson 
81653289f6aSNate Lawson     /*
817cd6518c7SJung-uk Kim      * Attempt an optimization depending on the type of namepath
81853289f6aSNate Lawson      */
81953289f6aSNate Lawson     if (Flags & (AML_NAMED | AML_CREATE))
82053289f6aSNate Lawson     {
82153289f6aSNate Lawson         /*
82253289f6aSNate Lawson          * This is a named opcode and the namepath is a name declaration, not
82353289f6aSNate Lawson          * a reference.
82453289f6aSNate Lawson          */
82553289f6aSNate Lawson         Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode,
82653289f6aSNate Lawson             TargetNode, AmlNameString, &NewPath);
82753289f6aSNate Lawson         if (ACPI_FAILURE (Status))
82853289f6aSNate Lawson         {
82953289f6aSNate Lawson             /*
83053289f6aSNate Lawson              * 2) now attempt to
83153289f6aSNate Lawson              *    optimize the namestring with carats (up-arrow)
83253289f6aSNate Lawson              */
83353289f6aSNate Lawson             Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
83453289f6aSNate Lawson                 TargetNode, &CurrentPath, &TargetPath,
83553289f6aSNate Lawson                 AmlNameStringLength, 1, &NewPath);
83653289f6aSNate Lawson         }
83753289f6aSNate Lawson     }
83853289f6aSNate Lawson     else
83953289f6aSNate Lawson     {
84053289f6aSNate Lawson         /*
84153289f6aSNate Lawson          * This is a reference to an existing named object
84253289f6aSNate Lawson          *
84353289f6aSNate Lawson          * 1) Check if search-to-root can be utilized using the last
84453289f6aSNate Lawson          *    NameSeg of the NamePath
84553289f6aSNate Lawson          */
84653289f6aSNate Lawson         Status = OptSearchToRoot (Op, WalkState, CurrentNode,
84753289f6aSNate Lawson             TargetNode, &TargetPath, &NewPath);
84853289f6aSNate Lawson         if (ACPI_FAILURE (Status))
84953289f6aSNate Lawson         {
85053289f6aSNate Lawson             /*
85153289f6aSNate Lawson              * 2) Search-to-root could not be used, now attempt to
85253289f6aSNate Lawson              *    optimize the namestring with carats (up-arrow)
85353289f6aSNate Lawson              */
85453289f6aSNate Lawson             Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
85553289f6aSNate Lawson                 TargetNode, &CurrentPath, &TargetPath,
85653289f6aSNate Lawson                 AmlNameStringLength, 0, &NewPath);
85753289f6aSNate Lawson         }
85853289f6aSNate Lawson     }
85953289f6aSNate Lawson 
86053289f6aSNate Lawson     /*
86153289f6aSNate Lawson      * Success from above indicates that the NamePath was successfully
86253289f6aSNate Lawson      * optimized. We need to update the parse op with the new name
86353289f6aSNate Lawson      */
86453289f6aSNate Lawson     if (ACPI_SUCCESS (Status))
86553289f6aSNate Lawson     {
8665ef50723SJung-uk Kim         HowMuchShorter = (AmlNameStringLength - strlen (NewPath));
86753289f6aSNate Lawson         OptTotal += HowMuchShorter;
86853289f6aSNate Lawson 
869313a0c13SJung-uk Kim         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
870313a0c13SJung-uk Kim             " REDUCED BY %2u (TOTAL SAVED %2u)",
871a9f12690SJung-uk Kim             (UINT32) HowMuchShorter, OptTotal));
87253289f6aSNate Lawson 
87353289f6aSNate Lawson         if (Flags & AML_NAMED)
87453289f6aSNate Lawson         {
87553289f6aSNate Lawson             if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
87653289f6aSNate Lawson             {
87753289f6aSNate Lawson                 /*
87853289f6aSNate Lawson                  * ALIAS is the only oddball opcode, the name declaration
87953289f6aSNate Lawson                  * (alias name) is the second operand
88053289f6aSNate Lawson                  */
88153289f6aSNate Lawson                 Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath;
8825ef50723SJung-uk Kim                 Op->Asl.Child->Asl.Next->Asl.AmlLength = strlen (NewPath);
88353289f6aSNate Lawson             }
88453289f6aSNate Lawson             else
88553289f6aSNate Lawson             {
88653289f6aSNate Lawson                 Op->Asl.Child->Asl.Value.String = NewPath;
8875ef50723SJung-uk Kim                 Op->Asl.Child->Asl.AmlLength = strlen (NewPath);
88853289f6aSNate Lawson             }
88953289f6aSNate Lawson         }
89053289f6aSNate Lawson         else if (Flags & AML_CREATE)
89153289f6aSNate Lawson         {
89253289f6aSNate Lawson             /* Name must appear as the last parameter */
89353289f6aSNate Lawson 
89453289f6aSNate Lawson             NextOp = Op->Asl.Child;
8955f9b24faSJung-uk Kim             while (!(NextOp->Asl.CompileFlags & OP_IS_NAME_DECLARATION))
89653289f6aSNate Lawson             {
89753289f6aSNate Lawson                 NextOp = NextOp->Asl.Next;
89853289f6aSNate Lawson             }
89953289f6aSNate Lawson             /* Update the parse node with the new NamePath */
90053289f6aSNate Lawson 
90153289f6aSNate Lawson             NextOp->Asl.Value.String = NewPath;
9025ef50723SJung-uk Kim             NextOp->Asl.AmlLength = strlen (NewPath);
90353289f6aSNate Lawson         }
90453289f6aSNate Lawson         else
90553289f6aSNate Lawson         {
90653289f6aSNate Lawson             /* Update the parse node with the new NamePath */
90753289f6aSNate Lawson 
90853289f6aSNate Lawson             Op->Asl.Value.String = NewPath;
9095ef50723SJung-uk Kim             Op->Asl.AmlLength = strlen (NewPath);
91053289f6aSNate Lawson         }
91153289f6aSNate Lawson     }
91253289f6aSNate Lawson     else
91353289f6aSNate Lawson     {
91453289f6aSNate Lawson         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL"));
91553289f6aSNate Lawson     }
91653289f6aSNate Lawson 
91753289f6aSNate Lawson     /* Cleanup path buffers */
91853289f6aSNate Lawson 
9191a39cfb0SJung-uk Kim     ACPI_FREE (TargetPath.Pointer);
9201a39cfb0SJung-uk Kim     ACPI_FREE (CurrentPath.Pointer);
92153289f6aSNate Lawson 
92253289f6aSNate Lawson     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n"));
92353289f6aSNate Lawson     return_VOID;
92453289f6aSNate Lawson }
925