xref: /illumos-gate/usr/src/cmd/acpi/iasl/cvparser.c (revision 8119dad84d6416f13557b0ba8e2aaf9064cbcfd3)
1 /******************************************************************************
2  *
3  * Module Name: cvparser - Converter functions that are called from the AML
4  *                         parser.
5  *
6  *****************************************************************************/
7 
8 /******************************************************************************
9  *
10  * 1. Copyright Notice
11  *
12  * Some or all of this work - Copyright (c) 1999 - 2018, Intel Corp.
13  * All rights reserved.
14  *
15  * 2. License
16  *
17  * 2.1. This is your license from Intel Corp. under its intellectual property
18  * rights. You may have additional license terms from the party that provided
19  * you this software, covering your right to use that party's intellectual
20  * property rights.
21  *
22  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
23  * copy of the source code appearing in this file ("Covered Code") an
24  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
25  * base code distributed originally by Intel ("Original Intel Code") to copy,
26  * make derivatives, distribute, use and display any portion of the Covered
27  * Code in any form, with the right to sublicense such rights; and
28  *
29  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
30  * license (with the right to sublicense), under only those claims of Intel
31  * patents that are infringed by the Original Intel Code, to make, use, sell,
32  * offer to sell, and import the Covered Code and derivative works thereof
33  * solely to the minimum extent necessary to exercise the above copyright
34  * license, and in no event shall the patent license extend to any additions
35  * to or modifications of the Original Intel Code. No other license or right
36  * is granted directly or by implication, estoppel or otherwise;
37  *
38  * The above copyright and patent license is granted only if the following
39  * conditions are met:
40  *
41  * 3. Conditions
42  *
43  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
44  * Redistribution of source code of any substantial portion of the Covered
45  * Code or modification with rights to further distribute source must include
46  * the above Copyright Notice, the above License, this list of Conditions,
47  * and the following Disclaimer and Export Compliance provision. In addition,
48  * Licensee must cause all Covered Code to which Licensee contributes to
49  * contain a file documenting the changes Licensee made to create that Covered
50  * Code and the date of any change. Licensee must include in that file the
51  * documentation of any changes made by any predecessor Licensee. Licensee
52  * must include a prominent statement that the modification is derived,
53  * directly or indirectly, from Original Intel Code.
54  *
55  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
56  * Redistribution of source code of any substantial portion of the Covered
57  * Code or modification without rights to further distribute source must
58  * include the following Disclaimer and Export Compliance provision in the
59  * documentation and/or other materials provided with distribution. In
60  * addition, Licensee may not authorize further sublicense of source of any
61  * portion of the Covered Code, and must include terms to the effect that the
62  * license from Licensee to its licensee is limited to the intellectual
63  * property embodied in the software Licensee provides to its licensee, and
64  * not to intellectual property embodied in modifications its licensee may
65  * make.
66  *
67  * 3.3. Redistribution of Executable. Redistribution in executable form of any
68  * substantial portion of the Covered Code or modification must reproduce the
69  * above Copyright Notice, and the following Disclaimer and Export Compliance
70  * provision in the documentation and/or other materials provided with the
71  * distribution.
72  *
73  * 3.4. Intel retains all right, title, and interest in and to the Original
74  * Intel Code.
75  *
76  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
77  * Intel shall be used in advertising or otherwise to promote the sale, use or
78  * other dealings in products derived from or relating to the Covered Code
79  * without prior written authorization from Intel.
80  *
81  * 4. Disclaimer and Export Compliance
82  *
83  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
84  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
85  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
86  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
87  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
88  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
89  * PARTICULAR PURPOSE.
90  *
91  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
92  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
93  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
94  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
95  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
96  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
97  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
98  * LIMITED REMEDY.
99  *
100  * 4.3. Licensee shall not export, either directly or indirectly, any of this
101  * software or system incorporating such software without first obtaining any
102  * required license or other approval from the U. S. Department of Commerce or
103  * any other agency or department of the United States Government. In the
104  * event Licensee exports any such software from the United States or
105  * re-exports any such software from a foreign destination, Licensee shall
106  * ensure that the distribution and export/re-export of the software is in
107  * compliance with all laws, regulations, orders, or other restrictions of the
108  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
109  * any of its subsidiaries will export/re-export any technical data, process,
110  * software, or service, directly or indirectly, to any country for which the
111  * United States government or any agency thereof requires an export license,
112  * other governmental approval, or letter of assurance, without first obtaining
113  * such license, approval or letter.
114  *
115  *****************************************************************************
116  *
117  * Alternatively, you may choose to be licensed under the terms of the
118  * following license:
119  *
120  * Redistribution and use in source and binary forms, with or without
121  * modification, are permitted provided that the following conditions
122  * are met:
123  * 1. Redistributions of source code must retain the above copyright
124  *    notice, this list of conditions, and the following disclaimer,
125  *    without modification.
126  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
127  *    substantially similar to the "NO WARRANTY" disclaimer below
128  *    ("Disclaimer") and any redistribution must be conditioned upon
129  *    including a substantially similar Disclaimer requirement for further
130  *    binary redistribution.
131  * 3. Neither the names of the above-listed copyright holders nor the names
132  *    of any contributors may be used to endorse or promote products derived
133  *    from this software without specific prior written permission.
134  *
135  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
136  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
137  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
138  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
139  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
140  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
141  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
142  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
143  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
144  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
145  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
146  *
147  * Alternatively, you may choose to be licensed under the terms of the
148  * GNU General Public License ("GPL") version 2 as published by the Free
149  * Software Foundation.
150  *
151  *****************************************************************************/
152 
153 #include "aslcompiler.h"
154 #include "acparser.h"
155 #include "acdispat.h"
156 #include "amlcode.h"
157 #include "acinterp.h"
158 #include "acdisasm.h"
159 #include "acconvert.h"
160 
161 
162 /* local prototypes */
163 
164 static BOOLEAN
165 CvCommentExists (
166     UINT8                   *Address);
167 
168 static BOOLEAN
169 CvIsFilename (
170     char                   *Filename);
171 
172 static ACPI_FILE_NODE*
173 CvFileAddressLookup(
174     char                    *Address,
175     ACPI_FILE_NODE          *Head);
176 
177 static void
178 CvAddToFileTree (
179     char                    *Filename,
180     char                    *PreviousFilename);
181 
182 static void
183 CvSetFileParent (
184     char                    *ChildFile,
185     char                    *ParentFile);
186 
187 
188 /*******************************************************************************
189  *
190  * FUNCTION:    CvIsFilename
191  *
192  * PARAMETERS:  filename - input filename
193  *
194  * RETURN:      BOOLEAN - TRUE if all characters are between 0x20 and 0x7f
195  *
196  * DESCRIPTION: Take a given char * and see if it contains all printable
197  *              characters. If all characters have hexvalues 20-7f and ends with
198  *              .dsl, we will assume that it is a proper filename.
199  *
200  ******************************************************************************/
201 
202 static BOOLEAN
203 CvIsFilename (
204     char                    *Filename)
205 {
206     UINT64                  Length = strlen(Filename);
207     char                    *FileExt = Filename + Length - 4;
208     UINT64                  i;
209 
210 
211     if ((Length > 4) && AcpiUtStricmp (FileExt, ".dsl"))
212     {
213         return (FALSE);
214     }
215 
216     for(i = 0; i<Length; ++i)
217     {
218         if (!isprint ((int) Filename[i]))
219         {
220             return (FALSE);
221         }
222     }
223 
224     return (TRUE);
225 }
226 
227 
228 /*******************************************************************************
229  *
230  * FUNCTION:    CvInitFileTree
231  *
232  * PARAMETERS:  Table      - input table
233  *              AmlStart   - Address of the starting point of the AML.
234  *              AmlLength  - Length of the AML file.
235  *
236  * RETURN:      None
237  *
238  * DESCRIPTION: Initialize the file dependency tree by scanning the AML.
239  *              This is referred as ASL_CV_INIT_FILETREE.
240  *
241  ******************************************************************************/
242 
243 void
244 CvInitFileTree (
245     ACPI_TABLE_HEADER       *Table,
246     UINT8                   *AmlStart,
247     UINT32                  AmlLength)
248 {
249     UINT8                   *TreeAml;
250     UINT8                   *FileEnd;
251     char                    *Filename = NULL;
252     char                    *PreviousFilename = NULL;
253     char                    *ParentFilename = NULL;
254     char                    *ChildFilename = NULL;
255 
256 
257     if (!AcpiGbl_CaptureComments)
258     {
259         return;
260     }
261 
262     CvDbgPrint ("AmlLength: %x\n", AmlLength);
263     CvDbgPrint ("AmlStart:  %p\n", AmlStart);
264     CvDbgPrint ("AmlEnd?:   %p\n", AmlStart+AmlLength);
265 
266     AcpiGbl_FileTreeRoot = AcpiOsAcquireObject (AcpiGbl_FileCache);
267 
268     AcpiGbl_FileTreeRoot->FileStart = (char *)(AmlStart);
269     AcpiGbl_FileTreeRoot->FileEnd = (char *)(AmlStart + Table->Length);
270     AcpiGbl_FileTreeRoot->Next = NULL;
271     AcpiGbl_FileTreeRoot->Parent = NULL;
272     AcpiGbl_FileTreeRoot->Filename = (char *)(AmlStart+2);
273 
274     /* Set the root file to the current open file */
275 
276     AcpiGbl_FileTreeRoot->File = AcpiGbl_OutputFile;
277 
278     /*
279      * Set this to true because we dont need to output
280      * an include statement for the topmost file
281      */
282     AcpiGbl_FileTreeRoot->IncludeWritten = TRUE;
283     Filename = NULL;
284     AcpiGbl_CurrentFilename = (char *)(AmlStart+2);
285     AcpiGbl_RootFilename    = (char *)(AmlStart+2);
286 
287     TreeAml = AmlStart;
288     FileEnd = AmlStart + AmlLength;
289 
290     while (TreeAml <= FileEnd)
291     {
292         /*
293          * Make sure that this filename contains all printable characters
294          * and a .dsl extension at the end. If not, then it must be some
295          * raw data that doesn't outline a filename.
296          */
297         if ((*TreeAml == AML_COMMENT_OP) &&
298             (*(TreeAml +1) == FILENAME_COMMENT) &&
299             (CvIsFilename ((char *)(TreeAml +2))))
300         {
301             CvDbgPrint ("A9 and a 08 file\n");
302             PreviousFilename = Filename;
303             Filename = (char *) (TreeAml +2);
304 
305             CvAddToFileTree (Filename, PreviousFilename);
306             ChildFilename = Filename;
307             CvDbgPrint ("%s\n", Filename);
308         }
309         else if ((*TreeAml == AML_COMMENT_OP) &&
310             (*(TreeAml +1) == PARENTFILENAME_COMMENT) &&
311             (CvIsFilename ((char *)(TreeAml +2))))
312         {
313             CvDbgPrint ("A9 and a 09 file\n");
314             ParentFilename = (char *)(TreeAml +2);
315             CvSetFileParent (ChildFilename, ParentFilename);
316             CvDbgPrint ("%s\n", ParentFilename);
317         }
318 
319         ++TreeAml;
320     }
321 }
322 
323 
324 /*******************************************************************************
325  *
326  * FUNCTION:    CvClearOpComments
327  *
328  * PARAMETERS:  Op -- clear all comments within this Op
329  *
330  * RETURN:      None
331  *
332  * DESCRIPTION: Clear all converter-related fields of the given Op.
333  *              This is referred as ASL_CV_CLEAR_OP_COMMENTS.
334  *
335  ******************************************************************************/
336 
337 void
338 CvClearOpComments (
339     ACPI_PARSE_OBJECT       *Op)
340 {
341 
342     Op->Common.InlineComment     = NULL;
343     Op->Common.EndNodeComment    = NULL;
344     Op->Common.NameComment       = NULL;
345     Op->Common.CommentList       = NULL;
346     Op->Common.EndBlkComment     = NULL;
347     Op->Common.CloseBraceComment = NULL;
348     Op->Common.CvFilename        = NULL;
349     Op->Common.CvParentFilename  = NULL;
350 }
351 
352 
353 /*******************************************************************************
354  *
355  * FUNCTION:    CvCommentExists
356  *
357  * PARAMETERS:  Address - check if this address appears in the list
358  *
359  * RETURN:      BOOLEAN - TRUE if the address exists.
360  *
361  * DESCRIPTION: Look at the pointer address and check if this appears in the
362  *              list of all addresses. If it exists in the list, return TRUE
363  *              if it exists. Otherwise add to the list and return FALSE.
364  *
365  ******************************************************************************/
366 
367 static BOOLEAN
368 CvCommentExists (
369     UINT8                    *Address)
370 {
371     ACPI_COMMENT_ADDR_NODE   *Current = AcpiGbl_CommentAddrListHead;
372     UINT8                    Option;
373 
374 
375     if (!Address)
376     {
377         return (FALSE);
378     }
379 
380     Option = *(Address + 1);
381 
382     /*
383      * FILENAME_COMMENT and PARENTFILENAME_COMMENT are not treated as
384      * comments. They serve as markers for where the file starts and ends.
385      */
386     if ((Option == FILENAME_COMMENT) ||
387         (Option == PARENTFILENAME_COMMENT))
388     {
389        return (FALSE);
390     }
391 
392     if (!Current)
393     {
394         AcpiGbl_CommentAddrListHead =
395             AcpiOsAcquireObject (AcpiGbl_RegCommentCache);
396         AcpiGbl_CommentAddrListHead->Addr = Address;
397         AcpiGbl_CommentAddrListHead->Next = NULL;
398         return (FALSE);
399     }
400     else
401     {
402         while (Current)
403         {
404             if (Current->Addr != Address)
405             {
406                 Current = Current->Next;
407             }
408             else
409             {
410                 return (TRUE);
411             }
412         }
413 
414         /*
415          * If the execution gets to this point, it means that this
416          * address does not exists in the list. Add this address to the
417          * beginning of the list.
418          */
419         Current = AcpiGbl_CommentAddrListHead;
420         AcpiGbl_CommentAddrListHead =
421             AcpiOsAcquireObject (AcpiGbl_RegCommentCache);
422 
423         AcpiGbl_CommentAddrListHead->Addr = Address;
424         AcpiGbl_CommentAddrListHead->Next = Current;
425         return (FALSE);
426     }
427 }
428 
429 
430 /*******************************************************************************
431  *
432  * FUNCTION:    CvFilenameExists
433  *
434  * PARAMETERS:  Filename        - filename to search
435  *
436  * RETURN:      ACPI_FILE_NODE - a pointer to a file node
437  *
438  * DESCRIPTION: Look for the given filename in the file dependency tree.
439  *              Returns the file node if it exists, returns NULL if it does not.
440  *
441  ******************************************************************************/
442 
443 ACPI_FILE_NODE*
444 CvFilenameExists(
445     char                    *Filename,
446     ACPI_FILE_NODE          *Head)
447 {
448     ACPI_FILE_NODE          *Current = Head;
449 
450 
451     if (!Filename)
452     {
453         return (NULL);
454     }
455 
456     while (Current)
457     {
458         if (!AcpiUtStricmp (Current->Filename, Filename))
459         {
460             return (Current);
461         }
462 
463         Current = Current->Next;
464     }
465     return (NULL);
466 }
467 
468 
469 /*******************************************************************************
470  *
471  * FUNCTION:    CvFileAddressLookup
472  *
473  * PARAMETERS:  Address        - address to look up
474  *              Head           - file dependency tree
475  *
476  * RETURN:      ACPI_FILE_NODE - pointer to a file node containing the address
477  *
478  * DESCRIPTION: Look for the given address in the file dependency tree.
479  *              Returns the first file node where the given address is within
480  *              the file node's starting and ending address.
481  *
482  ******************************************************************************/
483 
484 static ACPI_FILE_NODE *
485 CvFileAddressLookup(
486     char                    *Address,
487     ACPI_FILE_NODE          *Head)
488 {
489     ACPI_FILE_NODE          *Current = Head;
490 
491 
492     while (Current)
493     {
494         if ((Address >= Current->FileStart) &&
495             (Address < Current->FileEnd ||
496             !Current->FileEnd))
497         {
498             return (Current);
499         }
500 
501         Current = Current->Next;
502     }
503 
504     return (NULL);
505 }
506 
507 
508 /*******************************************************************************
509  *
510  * FUNCTION:    CvLabelFileNode
511  *
512  * PARAMETERS:  Op
513  *
514  * RETURN:      None
515  *
516  * DESCRIPTION: Takes a given parse op, looks up its Op->Common.Aml field
517  *              within the file tree and fills in approperiate file information
518  *              from a matching node within the tree.
519  *              This is referred as ASL_CV_LABEL_FILENODE.
520  *
521  ******************************************************************************/
522 
523 void
524 CvLabelFileNode(
525     ACPI_PARSE_OBJECT       *Op)
526 {
527     ACPI_FILE_NODE          *Node;
528 
529 
530     if (!Op)
531     {
532         return;
533     }
534 
535     Node = CvFileAddressLookup ((char *)
536         Op->Common.Aml, AcpiGbl_FileTreeRoot);
537     if (!Node)
538     {
539        return;
540     }
541 
542     Op->Common.CvFilename = Node->Filename;
543     if (Node->Parent)
544     {
545         Op->Common.CvParentFilename = Node->Parent->Filename;
546     }
547     else
548     {
549         Op->Common.CvParentFilename = Node->Filename;
550     }
551 }
552 
553 
554 /*******************************************************************************
555  *
556  * FUNCTION:    CvAddToFileTree
557  *
558  * PARAMETERS:  Filename          - Address containing the name of the current
559  *                                  filename
560  *              PreviousFilename  - Address containing the name of the previous
561  *                                  filename
562  *
563  * RETURN:      None
564  *
565  * DESCRIPTION: Add this filename to the AcpiGbl_FileTree if it does not exist.
566  *
567  ******************************************************************************/
568 
569 static void
570 CvAddToFileTree (
571     char                    *Filename,
572     char                    *PreviousFilename)
573 {
574     ACPI_FILE_NODE          *Node;
575 
576 
577     if (!AcpiUtStricmp(Filename, AcpiGbl_RootFilename) &&
578         PreviousFilename)
579     {
580         Node = CvFilenameExists (PreviousFilename, AcpiGbl_FileTreeRoot);
581         if (Node)
582         {
583             /*
584              * Set the end point of the PreviousFilename to the address
585              * of Filename.
586              */
587             Node->FileEnd = Filename;
588         }
589     }
590     else if (!AcpiUtStricmp(Filename, AcpiGbl_RootFilename) &&
591              !PreviousFilename)
592     {
593         return;
594     }
595 
596     Node = CvFilenameExists (Filename, AcpiGbl_FileTreeRoot);
597     if (Node && PreviousFilename)
598     {
599         /*
600          * Update the end of the previous file and all of their parents'
601          * ending addresses. This is done to ensure that parent file
602          * ranges extend to the end of their childrens' files.
603          */
604         Node = CvFilenameExists (PreviousFilename, AcpiGbl_FileTreeRoot);
605         if (Node && (Node->FileEnd < Filename))
606         {
607             Node->FileEnd = Filename;
608             Node = Node->Parent;
609             while (Node)
610             {
611                 if (Node->FileEnd < Filename)
612                 {
613                     Node->FileEnd = Filename;
614                 }
615 
616                 Node = Node->Parent;
617             }
618         }
619     }
620     else
621     {
622         Node = AcpiGbl_FileTreeRoot;
623         AcpiGbl_FileTreeRoot = AcpiOsAcquireObject (AcpiGbl_FileCache);
624 
625         AcpiGbl_FileTreeRoot->Next = Node;
626         AcpiGbl_FileTreeRoot->Parent = NULL;
627         AcpiGbl_FileTreeRoot->Filename = Filename;
628         AcpiGbl_FileTreeRoot->FileStart = Filename;
629         AcpiGbl_FileTreeRoot->IncludeWritten = FALSE;
630         AcpiGbl_FileTreeRoot->File = fopen(Filename, "w+");
631 
632         /*
633          * If we can't open the file, we need to abort here before we
634          * accidentally write to a NULL file.
635          */
636         if (!AcpiGbl_FileTreeRoot->File)
637         {
638             /* delete the .xxx file */
639 
640             FlDeleteFile (ASL_FILE_AML_OUTPUT);
641             sprintf (MsgBuffer, "\"%s\" - %s", Filename, strerror (errno));
642             AslCommonError (ASL_ERROR, ASL_MSG_OPEN, 0, 0, 0, 0,
643                 NULL, MsgBuffer);
644             AslAbort ();
645         }
646     }
647 }
648 
649 
650 /*******************************************************************************
651  *
652  * FUNCTION:    CvSetFileParent
653  *
654  * PARAMETERS:  ChildFile  - contains the filename of the child file
655  *              ParentFile - contains the filename of the parent file.
656  *
657  * RETURN:      None
658  *
659  * DESCRIPTION: Point the parent pointer of the Child to the node that
660  *              corresponds with the parent file node.
661  *
662  ******************************************************************************/
663 
664 static void
665 CvSetFileParent (
666     char                    *ChildFile,
667     char                    *ParentFile)
668 {
669     ACPI_FILE_NODE          *Child;
670     ACPI_FILE_NODE          *Parent;
671 
672 
673     Child  = CvFilenameExists (ChildFile, AcpiGbl_FileTreeRoot);
674     Parent = CvFilenameExists (ParentFile, AcpiGbl_FileTreeRoot);
675 
676     if (Child && Parent)
677     {
678         Child->Parent = Parent;
679 
680         while (Child->Parent)
681         {
682             if (Child->Parent->FileEnd < Child->FileStart)
683             {
684                 Child->Parent->FileEnd = Child->FileStart;
685             }
686 
687             Child = Child->Parent;
688         }
689     }
690 }
691 
692 
693 /*******************************************************************************
694  *
695  * FUNCTION:    CvCaptureCommentsOnly
696  *
697  * PARAMETERS:  ParserState         - A parser state object
698  *
699  * RETURN:      None
700  *
701  * DESCRIPTION: Look at the aml that the parser state is pointing to,
702  *              capture any AML_COMMENT_OP and it's arguments and increment the
703  *              aml pointer past the comment. Comments are transferred to parse
704  *              nodes through CvTransferComments() as well as
705  *              AcpiPsBuildNamedOp().
706  *              This is referred as ASL_CV_CAPTURE_COMMENTS_ONLY.
707  *
708  ******************************************************************************/
709 
710 void
711 CvCaptureCommentsOnly (
712     ACPI_PARSE_STATE        *ParserState)
713 {
714     UINT8                   *Aml = ParserState->Aml;
715     UINT16                  Opcode = (UINT16) ACPI_GET8 (Aml);
716     UINT32                  Length = 0;
717     UINT8                   CommentOption;
718     BOOLEAN                 StdDefBlockFlag = FALSE;
719     ACPI_COMMENT_NODE       *CommentNode;
720     ACPI_FILE_NODE          *FileNode;
721 
722 
723     if (!AcpiGbl_CaptureComments ||
724         Opcode != AML_COMMENT_OP)
725     {
726        return;
727     }
728 
729     while (Opcode == AML_COMMENT_OP)
730     {
731         CvDbgPrint ("comment aml address: %p\n", Aml);
732 
733         if (CvCommentExists(ParserState->Aml))
734         {
735             CvDbgPrint ("Avoiding capturing an existing comment.\n");
736         }
737         else
738         {
739             CommentOption = *(Aml +1);
740 
741             /*
742              * Increment past the comment option and point the
743              * appropriate char pointers
744              */
745             Aml += 2;
746 
747             /* Found a comment. Now, set pointers to these comments. */
748 
749             switch (CommentOption)
750             {
751                 case STD_DEFBLK_COMMENT:
752 
753                     StdDefBlockFlag = TRUE;
754 
755                     /*
756                      * Add to a linked list of nodes. This list will be
757                      * taken by the parse node created next.
758                      */
759                     CommentNode = AcpiOsAcquireObject (
760                         AcpiGbl_RegCommentCache);
761                     CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
762                     CommentNode->Next = NULL;
763 
764                     if (!AcpiGbl_DefBlkCommentListHead)
765                     {
766                         AcpiGbl_DefBlkCommentListHead = CommentNode;
767                         AcpiGbl_DefBlkCommentListTail = CommentNode;
768                     }
769                     else
770                     {
771                         AcpiGbl_DefBlkCommentListTail->Next = CommentNode;
772                         AcpiGbl_DefBlkCommentListTail =
773                             AcpiGbl_DefBlkCommentListTail->Next;
774                     }
775                     break;
776 
777                 case STANDARD_COMMENT:
778 
779                     CvDbgPrint ("found regular comment.\n");
780 
781                     /*
782                      * Add to a linked list of nodes. This list will be
783                      * taken by the parse node created next.
784                      */
785                     CommentNode = AcpiOsAcquireObject (
786                         AcpiGbl_RegCommentCache);
787                     CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
788                     CommentNode->Next    = NULL;
789 
790                     if (!AcpiGbl_RegCommentListHead)
791                     {
792                         AcpiGbl_RegCommentListHead = CommentNode;
793                         AcpiGbl_RegCommentListTail = CommentNode;
794                     }
795                     else
796                     {
797                         AcpiGbl_RegCommentListTail->Next = CommentNode;
798                         AcpiGbl_RegCommentListTail =
799                             AcpiGbl_RegCommentListTail->Next;
800                     }
801                     break;
802 
803                 case ENDBLK_COMMENT:
804 
805                     CvDbgPrint ("found endblk comment.\n");
806 
807                     /* Add to a linked list of nodes. This will be
808                      * taken by the next created parse node.
809                      */
810                     CommentNode = AcpiOsAcquireObject (
811                         AcpiGbl_RegCommentCache);
812                     CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
813                     CommentNode->Next    = NULL;
814 
815                     if (!AcpiGbl_EndBlkCommentListHead)
816                     {
817                         AcpiGbl_EndBlkCommentListHead = CommentNode;
818                         AcpiGbl_EndBlkCommentListTail = CommentNode;
819                     }
820                     else
821                     {
822                         AcpiGbl_EndBlkCommentListTail->Next = CommentNode;
823                         AcpiGbl_EndBlkCommentListTail =
824                             AcpiGbl_EndBlkCommentListTail->Next;
825                     }
826                     break;
827 
828                 case INLINE_COMMENT:
829 
830                     CvDbgPrint ("found inline comment.\n");
831                     AcpiGbl_CurrentInlineComment =
832                         ACPI_CAST_PTR (char, Aml);
833                     break;
834 
835                 case ENDNODE_COMMENT:
836 
837                     CvDbgPrint ("found EndNode comment.\n");
838                     AcpiGbl_CurrentEndNodeComment =
839                         ACPI_CAST_PTR (char, Aml);
840                     break;
841 
842                 case CLOSE_BRACE_COMMENT:
843 
844                     CvDbgPrint ("found close brace comment.\n");
845                     AcpiGbl_CurrentCloseBraceComment =
846                         ACPI_CAST_PTR (char, Aml);
847                     break;
848 
849                 case END_DEFBLK_COMMENT:
850 
851                     CvDbgPrint ("Found comment that belongs after"
852                         " the } for a definition block.\n");
853                     AcpiGbl_CurrentScope->Common.CloseBraceComment =
854                         ACPI_CAST_PTR (char, Aml);
855                     break;
856 
857                 case FILENAME_COMMENT:
858 
859                     CvDbgPrint ("Found a filename: %s\n",
860                         ACPI_CAST_PTR (char, Aml));
861                     FileNode = CvFilenameExists (
862                         ACPI_CAST_PTR (char, Aml), AcpiGbl_FileTreeRoot);
863 
864                     /*
865                      * If there is an INCLUDE_COMMENT followed by a
866                      * FILENAME_COMMENT, then the INCLUDE_COMMENT is a comment
867                      * that is emitted before the #include for the file.
868                      * We will save the IncludeComment within the FileNode
869                      * associated with this FILENAME_COMMENT.
870                      */
871                     if (FileNode && AcpiGbl_IncCommentListHead)
872                     {
873                         FileNode->IncludeComment = AcpiGbl_IncCommentListHead;
874                         AcpiGbl_IncCommentListHead = NULL;
875                         AcpiGbl_IncCommentListTail = NULL;
876                     }
877                     break;
878 
879                 case PARENTFILENAME_COMMENT:
880                     CvDbgPrint ("    Found a parent filename.\n");
881                     break;
882 
883                 case INCLUDE_COMMENT:
884 
885                     /*
886                      * Add to a linked list. This list will be taken by the
887                      * parse node created next. See the FILENAME_COMMENT case
888                      * for more details
889                      */
890                     CommentNode = AcpiOsAcquireObject (
891                         AcpiGbl_RegCommentCache);
892                     CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
893                     CommentNode->Next = NULL;
894 
895                     if (!AcpiGbl_IncCommentListHead)
896                     {
897                         AcpiGbl_IncCommentListHead = CommentNode;
898                         AcpiGbl_IncCommentListTail = CommentNode;
899                     }
900                     else
901                     {
902                         AcpiGbl_IncCommentListTail->Next = CommentNode;
903                         AcpiGbl_IncCommentListTail =
904                             AcpiGbl_IncCommentListTail->Next;
905                     }
906 
907                     CvDbgPrint ("Found a include comment: %s\n",
908                         CommentNode->Comment);
909                     break;
910 
911                 default:
912 
913                     /* Not a valid comment option. Revert the AML */
914 
915                     Aml -= 2;
916                     goto DefBlock;
917 
918             } /* End switch statement */
919 
920         } /* End else */
921 
922         /* Determine the length and move forward that amount */
923 
924         Length = 0;
925         while (ParserState->Aml[Length])
926         {
927             Length++;
928         }
929 
930         ParserState->Aml += Length + 1;
931 
932         /* Peek at the next Opcode. */
933 
934         Aml = ParserState->Aml;
935         Opcode = (UINT16) ACPI_GET8 (Aml);
936     }
937 
938 DefBlock:
939     if (StdDefBlockFlag)
940     {
941         /*
942          * Give all of its comments to the current scope, which is known as
943          * the definition block, since STD_DEFBLK_COMMENT only appears after
944          * definition block headers.
945          */
946         AcpiGbl_CurrentScope->Common.CommentList
947             = AcpiGbl_DefBlkCommentListHead;
948         AcpiGbl_DefBlkCommentListHead = NULL;
949         AcpiGbl_DefBlkCommentListTail = NULL;
950     }
951 }
952 
953 
954 /*******************************************************************************
955  *
956  * FUNCTION:    CvCaptureComments
957  *
958  * PARAMETERS:  ParserState         - A parser state object
959  *
960  * RETURN:      None
961  *
962  * DESCRIPTION: Wrapper function for CvCaptureCommentsOnly
963  *              This is referred as ASL_CV_CAPTURE_COMMENTS.
964  *
965  ******************************************************************************/
966 
967 void
968 CvCaptureComments (
969     ACPI_WALK_STATE         *WalkState)
970 {
971     UINT8                   *Aml;
972     UINT16                  Opcode;
973     const ACPI_OPCODE_INFO  *OpInfo;
974 
975 
976     if (!AcpiGbl_CaptureComments)
977     {
978         return;
979     }
980 
981     /*
982      * Before parsing, check to see that comments that come directly
983      * after deferred opcodes aren't being processed.
984      */
985     Aml = WalkState->ParserState.Aml;
986     Opcode = (UINT16) ACPI_GET8 (Aml);
987     OpInfo = AcpiPsGetOpcodeInfo (Opcode);
988 
989     if (!(OpInfo->Flags & AML_DEFER) ||
990         ((OpInfo->Flags & AML_DEFER) &&
991         (WalkState->PassNumber != ACPI_IMODE_LOAD_PASS1)))
992     {
993         CvCaptureCommentsOnly (&WalkState->ParserState);
994         WalkState->Aml = WalkState->ParserState.Aml;
995     }
996 
997 }
998 
999 
1000 /*******************************************************************************
1001  *
1002  * FUNCTION:    CvTransferComments
1003  *
1004  * PARAMETERS:  Op                  - Transfer comments to this Op
1005  *
1006  * RETURN:      None
1007  *
1008  * DESCRIPTION: Transfer all of the commments stored in global containers to the
1009  *              given Op. This will be invoked shortly after the parser creates
1010  *              a ParseOp.
1011  *              This is referred as ASL_CV_TRANSFER_COMMENTS.
1012  *
1013  ******************************************************************************/
1014 
1015 void
1016 CvTransferComments (
1017     ACPI_PARSE_OBJECT       *Op)
1018 {
1019 
1020     Op->Common.InlineComment = AcpiGbl_CurrentInlineComment;
1021     AcpiGbl_CurrentInlineComment = NULL;
1022 
1023     Op->Common.EndNodeComment = AcpiGbl_CurrentEndNodeComment;
1024     AcpiGbl_CurrentEndNodeComment = NULL;
1025 
1026     Op->Common.CloseBraceComment = AcpiGbl_CurrentCloseBraceComment;
1027     AcpiGbl_CurrentCloseBraceComment = NULL;
1028 
1029     Op->Common.CommentList = AcpiGbl_RegCommentListHead;
1030     AcpiGbl_RegCommentListHead = NULL;
1031     AcpiGbl_RegCommentListTail = NULL;
1032 
1033     Op->Common.EndBlkComment = AcpiGbl_EndBlkCommentListHead;
1034     AcpiGbl_EndBlkCommentListHead = NULL;
1035     AcpiGbl_EndBlkCommentListTail = NULL;
1036 }
1037