OSDN Git Service

klibc基本機能実装. ACPICAの準備
[vaneos/DivergeMirror.git] / drivers / acpi / compiler / aslopt.c
1 /******************************************************************************
2  *
3  * Module Name: aslopt- Compiler optimizations
4  *
5  *****************************************************************************/
6
7 /******************************************************************************
8  *
9  * 1. Copyright Notice
10  *
11  * Some or all of this work - Copyright (c) 1999 - 2015, Intel Corp.
12  * All rights reserved.
13  *
14  * 2. License
15  *
16  * 2.1. This is your license from Intel Corp. under its intellectual property
17  * rights. You may have additional license terms from the party that provided
18  * you this software, covering your right to use that party's intellectual
19  * property rights.
20  *
21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22  * copy of the source code appearing in this file ("Covered Code") an
23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24  * base code distributed originally by Intel ("Original Intel Code") to copy,
25  * make derivatives, distribute, use and display any portion of the Covered
26  * Code in any form, with the right to sublicense such rights; and
27  *
28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29  * license (with the right to sublicense), under only those claims of Intel
30  * patents that are infringed by the Original Intel Code, to make, use, sell,
31  * offer to sell, and import the Covered Code and derivative works thereof
32  * solely to the minimum extent necessary to exercise the above copyright
33  * license, and in no event shall the patent license extend to any additions
34  * to or modifications of the Original Intel Code. No other license or right
35  * is granted directly or by implication, estoppel or otherwise;
36  *
37  * The above copyright and patent license is granted only if the following
38  * conditions are met:
39  *
40  * 3. Conditions
41  *
42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43  * Redistribution of source code of any substantial portion of the Covered
44  * Code or modification with rights to further distribute source must include
45  * the above Copyright Notice, the above License, this list of Conditions,
46  * and the following Disclaimer and Export Compliance provision. In addition,
47  * Licensee must cause all Covered Code to which Licensee contributes to
48  * contain a file documenting the changes Licensee made to create that Covered
49  * Code and the date of any change. Licensee must include in that file the
50  * documentation of any changes made by any predecessor Licensee. Licensee
51  * must include a prominent statement that the modification is derived,
52  * directly or indirectly, from Original Intel Code.
53  *
54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55  * Redistribution of source code of any substantial portion of the Covered
56  * Code or modification without rights to further distribute source must
57  * include the following Disclaimer and Export Compliance provision in the
58  * documentation and/or other materials provided with distribution. In
59  * addition, Licensee may not authorize further sublicense of source of any
60  * portion of the Covered Code, and must include terms to the effect that the
61  * license from Licensee to its licensee is limited to the intellectual
62  * property embodied in the software Licensee provides to its licensee, and
63  * not to intellectual property embodied in modifications its licensee may
64  * make.
65  *
66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
67  * substantial portion of the Covered Code or modification must reproduce the
68  * above Copyright Notice, and the following Disclaimer and Export Compliance
69  * provision in the documentation and/or other materials provided with the
70  * distribution.
71  *
72  * 3.4. Intel retains all right, title, and interest in and to the Original
73  * Intel Code.
74  *
75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76  * Intel shall be used in advertising or otherwise to promote the sale, use or
77  * other dealings in products derived from or relating to the Covered Code
78  * without prior written authorization from Intel.
79  *
80  * 4. Disclaimer and Export Compliance
81  *
82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88  * PARTICULAR PURPOSE.
89  *
90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97  * LIMITED REMEDY.
98  *
99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
100  * software or system incorporating such software without first obtaining any
101  * required license or other approval from the U. S. Department of Commerce or
102  * any other agency or department of the United States Government. In the
103  * event Licensee exports any such software from the United States or
104  * re-exports any such software from a foreign destination, Licensee shall
105  * ensure that the distribution and export/re-export of the software is in
106  * compliance with all laws, regulations, orders, or other restrictions of the
107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108  * any of its subsidiaries will export/re-export any technical data, process,
109  * software, or service, directly or indirectly, to any country for which the
110  * United States government or any agency thereof requires an export license,
111  * other governmental approval, or letter of assurance, without first obtaining
112  * such license, approval or letter.
113  *
114  *****************************************************************************/
115
116 #include "aslcompiler.h"
117 #include "aslcompiler.y.h"
118
119 #include "acparser.h"
120 #include "amlcode.h"
121 #include "acnamesp.h"
122
123
124 #define _COMPONENT          ACPI_COMPILER
125         ACPI_MODULE_NAME    ("aslopt")
126
127
128 static UINT32 OptTotal = 0;
129
130 /* Local prototypes */
131
132 static ACPI_STATUS
133 OptSearchToRoot (
134     ACPI_PARSE_OBJECT       *Op,
135     ACPI_WALK_STATE         *WalkState,
136     ACPI_NAMESPACE_NODE     *CurrentNode,
137     ACPI_NAMESPACE_NODE     *TargetNode,
138     ACPI_BUFFER             *TargetPath,
139     char                    **NewPath);
140
141 static ACPI_STATUS
142 OptBuildShortestPath (
143     ACPI_PARSE_OBJECT       *Op,
144     ACPI_WALK_STATE         *WalkState,
145     ACPI_NAMESPACE_NODE     *CurrentNode,
146     ACPI_NAMESPACE_NODE     *TargetNode,
147     ACPI_BUFFER             *CurrentPath,
148     ACPI_BUFFER             *TargetPath,
149     ACPI_SIZE               AmlNameStringLength,
150     UINT8                   IsDeclaration,
151     char                    **ReturnNewPath);
152
153 static ACPI_STATUS
154 OptOptimizeNameDeclaration (
155     ACPI_PARSE_OBJECT       *Op,
156     ACPI_WALK_STATE         *WalkState,
157     ACPI_NAMESPACE_NODE     *CurrentNode,
158     ACPI_NAMESPACE_NODE     *TargetNode,
159     char                    *AmlNameString,
160     char                    **NewPath);
161
162
163 /*******************************************************************************
164  *
165  * FUNCTION:    OptSearchToRoot
166  *
167  * PARAMETERS:  Op                  - Current parser op
168  *              WalkState           - Current state
169  *              CurrentNode         - Where we are in the namespace
170  *              TargetNode          - Node to which we are referring
171  *              TargetPath          - External full path to the target node
172  *              NewPath             - Where the optimized path is returned
173  *
174  * RETURN:      Status
175  *
176  * DESCRIPTION: Attempt to optimize a reference to a single 4-character ACPI
177  *              name utilizing the search-to-root name resolution algorithm
178  *              that is used by AML interpreters.
179  *
180  ******************************************************************************/
181
182 static ACPI_STATUS
183 OptSearchToRoot (
184     ACPI_PARSE_OBJECT       *Op,
185     ACPI_WALK_STATE         *WalkState,
186     ACPI_NAMESPACE_NODE     *CurrentNode,
187     ACPI_NAMESPACE_NODE     *TargetNode,
188     ACPI_BUFFER             *TargetPath,
189     char                    **NewPath)
190 {
191     ACPI_NAMESPACE_NODE     *Node;
192     ACPI_GENERIC_STATE      ScopeInfo;
193     ACPI_STATUS             Status;
194     char                    *Path;
195
196
197     ACPI_FUNCTION_NAME (OptSearchToRoot);
198
199
200     /*
201      * Check if search-to-root can be utilized. Use the last NameSeg of
202      * the NamePath and 1) See if can be found and 2) If found, make
203      * sure that it is the same node that we want. If there is another
204      * name in the search path before the one we want, the nodes will
205      * not match, and we cannot use this optimization.
206      */
207     Path = &(((char *) TargetPath->Pointer)[TargetPath->Length -
208                                             ACPI_NAME_SIZE]),
209     ScopeInfo.Scope.Node = CurrentNode;
210
211     /* Lookup the NameSeg using SEARCH_PARENT (search-to-root) */
212
213     Status = AcpiNsLookup (&ScopeInfo, Path, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
214                     ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE,
215                     WalkState, &(Node));
216     if (ACPI_FAILURE (Status))
217     {
218         return (Status);
219     }
220
221     /*
222      * We found the name, but we must check to make sure that the node
223      * matches. Otherwise, there is another identical name in the search
224      * path that precludes the use of this optimization.
225      */
226     if (Node != TargetNode)
227     {
228         /*
229          * This means that another object with the same name was found first,
230          * and we cannot use this optimization.
231          */
232         return (AE_NOT_FOUND);
233     }
234
235     /* Found the node, we can use this optimization */
236
237     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
238         "NAMESEG:   %-24s", Path));
239
240     /* We must allocate a new string for the name (TargetPath gets deleted) */
241
242     *NewPath = UtStringCacheCalloc (ACPI_NAME_SIZE + 1);
243     ACPI_STRCPY (*NewPath, Path);
244
245     if (ACPI_STRNCMP (*NewPath, "_T_", 3))
246     {
247         AslError (ASL_OPTIMIZATION, ASL_MSG_SINGLE_NAME_OPTIMIZATION, Op,
248                 *NewPath);
249     }
250
251     return (AE_OK);
252 }
253
254
255 /*******************************************************************************
256  *
257  * FUNCTION:    OptBuildShortestPath
258  *
259  * PARAMETERS:  Op                  - Current parser op
260  *              WalkState           - Current state
261  *              CurrentNode         - Where we are in the namespace
262  *              TargetNode          - Node to which we are referring
263  *              CurrentPath         - External full path to the current node
264  *              TargetPath          - External full path to the target node
265  *              AmlNameStringLength - Length of the original namepath
266  *              IsDeclaration       - TRUE for declaration, FALSE for reference
267  *              ReturnNewPath       - Where the optimized path is returned
268  *
269  * RETURN:      Status
270  *
271  * DESCRIPTION: Build an optimal NamePath using carats
272  *
273  ******************************************************************************/
274
275 static ACPI_STATUS
276 OptBuildShortestPath (
277     ACPI_PARSE_OBJECT       *Op,
278     ACPI_WALK_STATE         *WalkState,
279     ACPI_NAMESPACE_NODE     *CurrentNode,
280     ACPI_NAMESPACE_NODE     *TargetNode,
281     ACPI_BUFFER             *CurrentPath,
282     ACPI_BUFFER             *TargetPath,
283     ACPI_SIZE               AmlNameStringLength,
284     UINT8                   IsDeclaration,
285     char                    **ReturnNewPath)
286 {
287     UINT32                  NumCommonSegments;
288     UINT32                  MaxCommonSegments;
289     UINT32                  Index;
290     UINT32                  NumCarats;
291     UINT32                  i;
292     char                    *NewPath;
293     char                    *NewPathExternal;
294     ACPI_NAMESPACE_NODE     *Node;
295     ACPI_GENERIC_STATE      ScopeInfo;
296     ACPI_STATUS             Status;
297     BOOLEAN                 SubPath = FALSE;
298
299
300     ACPI_FUNCTION_NAME (OptBuildShortestPath);
301
302
303     ScopeInfo.Scope.Node = CurrentNode;
304
305     /*
306      * Determine the maximum number of NameSegs that the Target and Current paths
307      * can possibly have in common. (To optimize, we have to have at least 1)
308      *
309      * Note: The external NamePath string lengths are always a multiple of 5
310      * (ACPI_NAME_SIZE + separator)
311      */
312     MaxCommonSegments = TargetPath->Length / ACPI_PATH_SEGMENT_LENGTH;
313     if (CurrentPath->Length < TargetPath->Length)
314     {
315         MaxCommonSegments = CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH;
316     }
317
318     /*
319      * Determine how many NameSegs the two paths have in common.
320      * (Starting from the root)
321      */
322     for (NumCommonSegments = 0;
323          NumCommonSegments < MaxCommonSegments;
324          NumCommonSegments++)
325     {
326         /* Compare two single NameSegs */
327
328         if (!ACPI_COMPARE_NAME (
329             &((char *) TargetPath->Pointer)[
330                 (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1],
331             &((char *) CurrentPath->Pointer)[
332                 (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1]))
333         {
334             /* Mismatch */
335
336             break;
337         }
338     }
339
340     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " COMMON: %u",
341         NumCommonSegments));
342
343     /* There must be at least 1 common NameSeg in order to optimize */
344
345     if (NumCommonSegments == 0)
346     {
347         return (AE_NOT_FOUND);
348     }
349
350     if (NumCommonSegments == MaxCommonSegments)
351     {
352         if (CurrentPath->Length == TargetPath->Length)
353         {
354             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SAME PATH"));
355             return (AE_NOT_FOUND);
356         }
357         else
358         {
359             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " SUBPATH"));
360             SubPath = TRUE;
361         }
362     }
363
364     /* Determine how many prefix Carats are required */
365
366     NumCarats = (CurrentPath->Length / ACPI_PATH_SEGMENT_LENGTH) -
367                 NumCommonSegments;
368
369     /*
370      * Construct a new target string
371      */
372     NewPathExternal = ACPI_ALLOCATE_ZEROED (
373         TargetPath->Length + NumCarats + 1);
374
375     /* Insert the Carats into the Target string */
376
377     for (i = 0; i < NumCarats; i++)
378     {
379         NewPathExternal[i] = AML_PARENT_PREFIX;
380     }
381
382     /*
383      * Copy only the necessary (optimal) segments from the original
384      * target string
385      */
386     Index = (NumCommonSegments * ACPI_PATH_SEGMENT_LENGTH) + 1;
387
388     /* Special handling for exact subpath in a name declaration */
389
390     if (IsDeclaration && SubPath && (CurrentPath->Length > TargetPath->Length))
391     {
392         /*
393          * The current path is longer than the target, and the target is a
394          * subpath of the current path. We must include one more NameSeg of
395          * the target path
396          */
397         Index -= ACPI_PATH_SEGMENT_LENGTH;
398
399         /* Special handling for Scope() operator */
400
401         if (Op->Asl.AmlOpcode == AML_SCOPE_OP)
402         {
403             NewPathExternal[i] = AML_PARENT_PREFIX;
404             i++;
405             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "(EXTRA ^)"));
406         }
407     }
408
409     /* Make sure we haven't gone off the end of the target path */
410
411     if (Index > TargetPath->Length)
412     {
413         Index = TargetPath->Length;
414     }
415
416     ACPI_STRCPY (&NewPathExternal[i], &((char *) TargetPath->Pointer)[Index]);
417     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " %-24s", NewPathExternal));
418
419     /*
420      * Internalize the new target string and check it against the original
421      * string to make sure that this is in fact an optimization. If the
422      * original string is already optimal, there is no point in continuing.
423      */
424     Status = AcpiNsInternalizeName (NewPathExternal, &NewPath);
425     if (ACPI_FAILURE (Status))
426     {
427         AslCoreSubsystemError (Op, Status, "Internalizing new NamePath",
428             ASL_NO_ABORT);
429         ACPI_FREE (NewPathExternal);
430         return (Status);
431     }
432
433     if (ACPI_STRLEN (NewPath) >= AmlNameStringLength)
434     {
435         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
436             " NOT SHORTER (New %u old %u)",
437             (UINT32) ACPI_STRLEN (NewPath), (UINT32) AmlNameStringLength));
438         ACPI_FREE (NewPathExternal);
439         return (AE_NOT_FOUND);
440     }
441
442     /*
443      * Check to make sure that the optimization finds the node we are
444      * looking for. This is simply a sanity check on the new
445      * path that has been created.
446      */
447     Status = AcpiNsLookup (&ScopeInfo,  NewPath,
448                     ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
449                     ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
450     if (ACPI_SUCCESS (Status))
451     {
452         /* Found the namepath, but make sure the node is correct */
453
454         if (Node == TargetNode)
455         {
456             /* The lookup matched the node, accept this optimization */
457
458             AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
459                 Op, NewPathExternal);
460             *ReturnNewPath = NewPath;
461         }
462         else
463         {
464             /* Node is not correct, do not use this optimization */
465
466             Status = AE_NOT_FOUND;
467             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** WRONG NODE"));
468             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
469                 "Not using optimized name - found wrong node");
470         }
471     }
472     else
473     {
474         /* The lookup failed, we obviously cannot use this optimization */
475
476         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ***** NOT FOUND"));
477         AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
478             "Not using optimized name - did not find node");
479     }
480
481     ACPI_FREE (NewPathExternal);
482     return (Status);
483 }
484
485
486 /*******************************************************************************
487  *
488  * FUNCTION:    OptOptimizeNameDeclaration
489  *
490  * PARAMETERS:  Op                  - Current parser op
491  *              WalkState           - Current state
492  *              CurrentNode         - Where we are in the namespace
493  *              AmlNameString       - Unoptimized namepath
494  *              NewPath             - Where the optimized path is returned
495  *
496  * RETURN:      Status. AE_OK If path is optimized
497  *
498  * DESCRIPTION: Perform a simple optimization of removing an extraneous
499  *              backslash prefix if we are already at the root scope.
500  *
501  ******************************************************************************/
502
503 static ACPI_STATUS
504 OptOptimizeNameDeclaration (
505     ACPI_PARSE_OBJECT       *Op,
506     ACPI_WALK_STATE         *WalkState,
507     ACPI_NAMESPACE_NODE     *CurrentNode,
508     ACPI_NAMESPACE_NODE     *TargetNode,
509     char                    *AmlNameString,
510     char                    **NewPath)
511 {
512     ACPI_STATUS             Status;
513     char                    *NewPathExternal;
514     ACPI_NAMESPACE_NODE     *Node;
515
516
517     ACPI_FUNCTION_TRACE (OptOptimizeNameDeclaration);
518
519
520     if (((CurrentNode == AcpiGbl_RootNode) ||
521         (Op->Common.Parent->Asl.ParseOpcode == PARSEOP_DEFINITIONBLOCK)) &&
522             (ACPI_IS_ROOT_PREFIX (AmlNameString[0])))
523     {
524         /*
525          * The current scope is the root, and the namepath has a root prefix
526          * that is therefore extraneous. Remove it.
527          */
528         *NewPath = &AmlNameString[1];
529
530         /* Debug output */
531
532         Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, *NewPath,
533                     NULL, &NewPathExternal);
534         if (ACPI_FAILURE (Status))
535         {
536             AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
537                 ASL_NO_ABORT);
538             return (Status);
539         }
540
541         /*
542          * Check to make sure that the optimization finds the node we are
543          * looking for. This is simply a sanity check on the new
544          * path that has been created.
545          *
546          * We know that we are at the root, so NULL is used for the scope.
547          */
548         Status = AcpiNsLookup (NULL, *NewPath,
549                         ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE,
550                         ACPI_NS_DONT_OPEN_SCOPE, WalkState, &(Node));
551         if (ACPI_SUCCESS (Status))
552         {
553             /* Found the namepath, but make sure the node is correct */
554
555             if (Node == TargetNode)
556             {
557                 /* The lookup matched the node, accept this optimization */
558
559                 AslError (ASL_OPTIMIZATION, ASL_MSG_NAME_OPTIMIZATION,
560                     Op, NewPathExternal);
561
562                 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
563                     "AT ROOT:   %-24s", NewPathExternal));
564             }
565             else
566             {
567                 /* Node is not correct, do not use this optimization */
568
569                 Status = AE_NOT_FOUND;
570                 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
571                     " ***** WRONG NODE"));
572                 AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
573                     "Not using optimized name - found wrong node");
574             }
575         }
576         else
577         {
578             /* The lookup failed, we obviously cannot use this optimization */
579
580             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
581                 " ***** NOT FOUND"));
582             AslError (ASL_WARNING, ASL_MSG_COMPILER_INTERNAL, Op,
583                 "Not using optimized name - did not find node");
584         }
585
586         ACPI_FREE (NewPathExternal);
587         return (Status);
588     }
589
590     /* Could not optimize */
591
592     return (AE_NOT_FOUND);
593 }
594
595
596 /*******************************************************************************
597  *
598  * FUNCTION:    OptOptimizeNamePath
599  *
600  * PARAMETERS:  Op                  - Current parser op
601  *              Flags               - Opcode info flags
602  *              WalkState           - Current state
603  *              AmlNameString       - Unoptimized namepath
604  *              TargetNode          - Node to which AmlNameString refers
605  *
606  * RETURN:      None. If path is optimized, the Op is updated with new path
607  *
608  * DESCRIPTION: Optimize a Named Declaration or Reference to the minimal length.
609  *              Must take into account both the current location in the
610  *              namespace and the actual reference path.
611  *
612  ******************************************************************************/
613
614 void
615 OptOptimizeNamePath (
616     ACPI_PARSE_OBJECT       *Op,
617     UINT32                  Flags,
618     ACPI_WALK_STATE         *WalkState,
619     char                    *AmlNameString,
620     ACPI_NAMESPACE_NODE     *TargetNode)
621 {
622     ACPI_STATUS             Status;
623     ACPI_BUFFER             TargetPath;
624     ACPI_BUFFER             CurrentPath;
625     ACPI_SIZE               AmlNameStringLength;
626     ACPI_NAMESPACE_NODE     *CurrentNode;
627     char                    *ExternalNameString;
628     char                    *NewPath = NULL;
629     ACPI_SIZE               HowMuchShorter;
630     ACPI_PARSE_OBJECT       *NextOp;
631
632
633     ACPI_FUNCTION_TRACE (OptOptimizeNamePath);
634
635
636     /* This is an optional optimization */
637
638     if (!Gbl_ReferenceOptimizationFlag)
639     {
640         return_VOID;
641     }
642
643     /* Various required items */
644
645     if (!TargetNode || !WalkState || !AmlNameString || !Op->Common.Parent)
646     {
647         return_VOID;
648     }
649
650     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
651         "PATH OPTIMIZE: Line %5d ParentOp [%12.12s] ThisOp [%12.12s] ",
652         Op->Asl.LogicalLineNumber,
653         AcpiPsGetOpcodeName (Op->Common.Parent->Common.AmlOpcode),
654         AcpiPsGetOpcodeName (Op->Common.AmlOpcode)));
655
656     if (!(Flags & (AML_NAMED | AML_CREATE)))
657     {
658         if (Op->Asl.CompileFlags & NODE_IS_NAME_DECLARATION)
659         {
660             /* We don't want to fuss with actual name declaration nodes here */
661
662             ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
663                 "******* NAME DECLARATION\n"));
664             return_VOID;
665         }
666     }
667
668     /*
669      * The original path must be longer than one NameSeg (4 chars) for there
670      * to be any possibility that it can be optimized to a shorter string
671      */
672     AmlNameStringLength = ACPI_STRLEN (AmlNameString);
673     if (AmlNameStringLength <= ACPI_NAME_SIZE)
674     {
675         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
676             "NAMESEG %4.4s\n", AmlNameString));
677         return_VOID;
678     }
679
680     /*
681      * We need to obtain the node that represents the current scope -- where
682      * we are right now in the namespace. We will compare this path
683      * against the Namepath, looking for commonality.
684      */
685     CurrentNode = AcpiGbl_RootNode;
686     if (WalkState->ScopeInfo)
687     {
688         CurrentNode = WalkState->ScopeInfo->Scope.Node;
689     }
690
691     if (Flags & (AML_NAMED | AML_CREATE))
692     {
693         /* This is the declaration of a new name */
694
695         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "NAME\n"));
696
697         /*
698          * The node of interest is the parent of this node (the containing
699          * scope). The actual namespace node may be up more than one level
700          * of parse op or it may not exist at all (if we traverse back
701          * up to the root.)
702          */
703         NextOp = Op->Asl.Parent;
704         while (NextOp && (!NextOp->Asl.Node))
705         {
706             NextOp = NextOp->Asl.Parent;
707         }
708         if (NextOp && NextOp->Asl.Node)
709         {
710             CurrentNode = NextOp->Asl.Node;
711         }
712         else
713         {
714             CurrentNode = AcpiGbl_RootNode;
715         }
716     }
717     else
718     {
719         /* This is a reference to an existing named object */
720
721         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "REFERENCE\n"));
722     }
723
724     /*
725      * Obtain the full paths to the two nodes that we are interested in
726      * (Target and current namespace location) in external
727      * format -- something we can easily manipulate
728      */
729     TargetPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
730     Status = AcpiNsHandleToPathname (TargetNode, &TargetPath);
731     if (ACPI_FAILURE (Status))
732     {
733         AslCoreSubsystemError (Op, Status, "Getting Target NamePath",
734             ASL_NO_ABORT);
735         return_VOID;
736     }
737     TargetPath.Length--;    /* Subtract one for null terminator */
738
739     /* CurrentPath is the path to this scope (where we are in the namespace) */
740
741     CurrentPath.Length = ACPI_ALLOCATE_LOCAL_BUFFER;
742     Status = AcpiNsHandleToPathname (CurrentNode, &CurrentPath);
743     if (ACPI_FAILURE (Status))
744     {
745         AslCoreSubsystemError (Op, Status, "Getting Current NamePath",
746             ASL_NO_ABORT);
747         return_VOID;
748     }
749     CurrentPath.Length--;   /* Subtract one for null terminator */
750
751     /* Debug output only */
752
753     Status = AcpiNsExternalizeName (ACPI_UINT32_MAX, AmlNameString,
754                 NULL, &ExternalNameString);
755     if (ACPI_FAILURE (Status))
756     {
757         AslCoreSubsystemError (Op, Status, "Externalizing NamePath",
758             ASL_NO_ABORT);
759         return_VOID;
760     }
761
762     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
763         "CURRENT SCOPE: (%2u) %-37s FULL PATH TO NAME: (%2u) %-32s ACTUAL AML:%-32s\n",
764         (UINT32) CurrentPath.Length, (char *) CurrentPath.Pointer,
765         (UINT32) TargetPath.Length, (char *) TargetPath.Pointer,
766         ExternalNameString));
767
768     ACPI_FREE (ExternalNameString);
769
770     /*
771      * Attempt an optmization depending on the type of namepath
772      */
773     if (Flags & (AML_NAMED | AML_CREATE))
774     {
775         /*
776          * This is a named opcode and the namepath is a name declaration, not
777          * a reference.
778          */
779         Status = OptOptimizeNameDeclaration (Op, WalkState, CurrentNode,
780                     TargetNode, AmlNameString, &NewPath);
781         if (ACPI_FAILURE (Status))
782         {
783             /*
784              * 2) now attempt to
785              *    optimize the namestring with carats (up-arrow)
786              */
787             Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
788                             TargetNode, &CurrentPath, &TargetPath,
789                             AmlNameStringLength, 1, &NewPath);
790         }
791     }
792     else
793     {
794         /*
795          * This is a reference to an existing named object
796          *
797          * 1) Check if search-to-root can be utilized using the last
798          *    NameSeg of the NamePath
799          */
800         Status = OptSearchToRoot (Op, WalkState, CurrentNode,
801                         TargetNode, &TargetPath, &NewPath);
802         if (ACPI_FAILURE (Status))
803         {
804             /*
805              * 2) Search-to-root could not be used, now attempt to
806              *    optimize the namestring with carats (up-arrow)
807              */
808             Status = OptBuildShortestPath (Op, WalkState, CurrentNode,
809                             TargetNode, &CurrentPath, &TargetPath,
810                             AmlNameStringLength, 0, &NewPath);
811         }
812     }
813
814     /*
815      * Success from above indicates that the NamePath was successfully
816      * optimized. We need to update the parse op with the new name
817      */
818     if (ACPI_SUCCESS (Status))
819     {
820         HowMuchShorter = (AmlNameStringLength - ACPI_STRLEN (NewPath));
821         OptTotal += HowMuchShorter;
822
823         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS,
824             " REDUCED BY %2u (TOTAL SAVED %2u)",
825             (UINT32) HowMuchShorter, OptTotal));
826
827         if (Flags & AML_NAMED)
828         {
829             if (Op->Asl.AmlOpcode == AML_ALIAS_OP)
830             {
831                 /*
832                  * ALIAS is the only oddball opcode, the name declaration
833                  * (alias name) is the second operand
834                  */
835                 Op->Asl.Child->Asl.Next->Asl.Value.String = NewPath;
836                 Op->Asl.Child->Asl.Next->Asl.AmlLength = ACPI_STRLEN (NewPath);
837             }
838             else
839             {
840                 Op->Asl.Child->Asl.Value.String = NewPath;
841                 Op->Asl.Child->Asl.AmlLength = ACPI_STRLEN (NewPath);
842             }
843         }
844         else if (Flags & AML_CREATE)
845         {
846             /* Name must appear as the last parameter */
847
848             NextOp = Op->Asl.Child;
849             while (!(NextOp->Asl.CompileFlags & NODE_IS_NAME_DECLARATION))
850             {
851                 NextOp = NextOp->Asl.Next;
852             }
853             /* Update the parse node with the new NamePath */
854
855             NextOp->Asl.Value.String = NewPath;
856             NextOp->Asl.AmlLength = ACPI_STRLEN (NewPath);
857         }
858         else
859         {
860             /* Update the parse node with the new NamePath */
861
862             Op->Asl.Value.String = NewPath;
863             Op->Asl.AmlLength = ACPI_STRLEN (NewPath);
864         }
865     }
866     else
867     {
868         ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, " ALREADY OPTIMAL"));
869     }
870
871     /* Cleanup path buffers */
872
873     ACPI_FREE (TargetPath.Pointer);
874     ACPI_FREE (CurrentPath.Pointer);
875
876     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_OPTIMIZATIONS, "\n"));
877     return_VOID;
878 }