1835858a6Schristos /******************************************************************************
2835858a6Schristos *
3835858a6Schristos * Module Name: cvparser - Converter functions that are called from the AML
4835858a6Schristos * parser.
5835858a6Schristos *
6835858a6Schristos *****************************************************************************/
7835858a6Schristos
8835858a6Schristos /*
9*046a2985Schristos * Copyright (C) 2000 - 2023, Intel Corp.
10835858a6Schristos * All rights reserved.
11835858a6Schristos *
12835858a6Schristos * Redistribution and use in source and binary forms, with or without
13835858a6Schristos * modification, are permitted provided that the following conditions
14835858a6Schristos * are met:
15835858a6Schristos * 1. Redistributions of source code must retain the above copyright
16835858a6Schristos * notice, this list of conditions, and the following disclaimer,
17835858a6Schristos * without modification.
18835858a6Schristos * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19835858a6Schristos * substantially similar to the "NO WARRANTY" disclaimer below
20835858a6Schristos * ("Disclaimer") and any redistribution must be conditioned upon
21835858a6Schristos * including a substantially similar Disclaimer requirement for further
22835858a6Schristos * binary redistribution.
23835858a6Schristos * 3. Neither the names of the above-listed copyright holders nor the names
24835858a6Schristos * of any contributors may be used to endorse or promote products derived
25835858a6Schristos * from this software without specific prior written permission.
26835858a6Schristos *
27835858a6Schristos * Alternatively, this software may be distributed under the terms of the
28835858a6Schristos * GNU General Public License ("GPL") version 2 as published by the Free
29835858a6Schristos * Software Foundation.
30835858a6Schristos *
31835858a6Schristos * NO WARRANTY
32835858a6Schristos * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33835858a6Schristos * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
3446a330b4Schristos * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
35835858a6Schristos * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36835858a6Schristos * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37835858a6Schristos * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38835858a6Schristos * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39835858a6Schristos * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40835858a6Schristos * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41835858a6Schristos * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42835858a6Schristos * POSSIBILITY OF SUCH DAMAGES.
43835858a6Schristos */
44835858a6Schristos
45835858a6Schristos #include "aslcompiler.h"
46835858a6Schristos #include "acparser.h"
47835858a6Schristos #include "acdispat.h"
48835858a6Schristos #include "amlcode.h"
49835858a6Schristos #include "acinterp.h"
50835858a6Schristos #include "acdisasm.h"
51835858a6Schristos #include "acconvert.h"
52835858a6Schristos
53835858a6Schristos
54835858a6Schristos /* local prototypes */
55835858a6Schristos
56835858a6Schristos static BOOLEAN
57835858a6Schristos CvCommentExists (
58835858a6Schristos UINT8 *Address);
59835858a6Schristos
60835858a6Schristos static BOOLEAN
61835858a6Schristos CvIsFilename (
62835858a6Schristos char *Filename);
63835858a6Schristos
64835858a6Schristos static ACPI_FILE_NODE*
65835858a6Schristos CvFileAddressLookup(
66835858a6Schristos char *Address,
67835858a6Schristos ACPI_FILE_NODE *Head);
68835858a6Schristos
69835858a6Schristos static void
70835858a6Schristos CvAddToFileTree (
71835858a6Schristos char *Filename,
72835858a6Schristos char *PreviousFilename);
73835858a6Schristos
74835858a6Schristos static void
75835858a6Schristos CvSetFileParent (
76835858a6Schristos char *ChildFile,
77835858a6Schristos char *ParentFile);
78835858a6Schristos
79835858a6Schristos
80835858a6Schristos /*******************************************************************************
81835858a6Schristos *
82835858a6Schristos * FUNCTION: CvIsFilename
83835858a6Schristos *
84835858a6Schristos * PARAMETERS: filename - input filename
85835858a6Schristos *
86835858a6Schristos * RETURN: BOOLEAN - TRUE if all characters are between 0x20 and 0x7f
87835858a6Schristos *
88835858a6Schristos * DESCRIPTION: Take a given char * and see if it contains all printable
89835858a6Schristos * characters. If all characters have hexvalues 20-7f and ends with
90835858a6Schristos * .dsl, we will assume that it is a proper filename.
91835858a6Schristos *
92835858a6Schristos ******************************************************************************/
93835858a6Schristos
94835858a6Schristos static BOOLEAN
CvIsFilename(char * Filename)95835858a6Schristos CvIsFilename (
96835858a6Schristos char *Filename)
97835858a6Schristos {
98835858a6Schristos UINT64 Length = strlen(Filename);
99835858a6Schristos char *FileExt = Filename + Length - 4;
10089b8eb6cSchristos UINT64 i;
101835858a6Schristos
102835858a6Schristos
103835858a6Schristos if ((Length > 4) && AcpiUtStricmp (FileExt, ".dsl"))
104835858a6Schristos {
10589b8eb6cSchristos return (FALSE);
106835858a6Schristos }
107835858a6Schristos
108835858a6Schristos for(i = 0; i<Length; ++i)
109835858a6Schristos {
11089b8eb6cSchristos if (!isprint ((int) Filename[i]))
111835858a6Schristos {
11289b8eb6cSchristos return (FALSE);
113835858a6Schristos }
114835858a6Schristos }
11589b8eb6cSchristos
11689b8eb6cSchristos return (TRUE);
117835858a6Schristos }
118835858a6Schristos
119835858a6Schristos
120835858a6Schristos /*******************************************************************************
121835858a6Schristos *
122835858a6Schristos * FUNCTION: CvInitFileTree
123835858a6Schristos *
124835858a6Schristos * PARAMETERS: Table - input table
1253fd31de5Schristos * RootFile - Output file that defines the DefinitionBlock
126835858a6Schristos *
12789b8eb6cSchristos * RETURN: None
128835858a6Schristos *
129835858a6Schristos * DESCRIPTION: Initialize the file dependency tree by scanning the AML.
130835858a6Schristos * This is referred as ASL_CV_INIT_FILETREE.
131835858a6Schristos *
132835858a6Schristos ******************************************************************************/
133835858a6Schristos
134835858a6Schristos void
CvInitFileTree(ACPI_TABLE_HEADER * Table,FILE * RootFile)135835858a6Schristos CvInitFileTree (
136835858a6Schristos ACPI_TABLE_HEADER *Table,
1373fd31de5Schristos FILE *RootFile)
138835858a6Schristos {
139835858a6Schristos UINT8 *TreeAml;
140835858a6Schristos UINT8 *FileEnd;
141835858a6Schristos char *Filename = NULL;
142835858a6Schristos char *PreviousFilename = NULL;
143835858a6Schristos char *ParentFilename = NULL;
144835858a6Schristos char *ChildFilename = NULL;
1453fd31de5Schristos UINT8 *AmlStart;
1463fd31de5Schristos UINT32 AmlLength;
147835858a6Schristos
148835858a6Schristos
149062782b3Schristos if (!AcpiGbl_CaptureComments)
150835858a6Schristos {
151835858a6Schristos return;
152835858a6Schristos }
153835858a6Schristos
1543fd31de5Schristos
1553fd31de5Schristos AmlLength = Table->Length - sizeof (ACPI_TABLE_HEADER);
1563fd31de5Schristos AmlStart = ((UINT8 *) Table + sizeof (ACPI_TABLE_HEADER));
1573fd31de5Schristos
158835858a6Schristos CvDbgPrint ("AmlLength: %x\n", AmlLength);
159835858a6Schristos CvDbgPrint ("AmlStart: %p\n", AmlStart);
1603fd31de5Schristos CvDbgPrint ("AmlEnd: %p\n", AmlStart+AmlLength);
161835858a6Schristos
162835858a6Schristos AcpiGbl_FileTreeRoot = AcpiOsAcquireObject (AcpiGbl_FileCache);
16389b8eb6cSchristos
164835858a6Schristos AcpiGbl_FileTreeRoot->FileStart = (char *)(AmlStart);
165835858a6Schristos AcpiGbl_FileTreeRoot->FileEnd = (char *)(AmlStart + Table->Length);
166835858a6Schristos AcpiGbl_FileTreeRoot->Next = NULL;
167835858a6Schristos AcpiGbl_FileTreeRoot->Parent = NULL;
168835858a6Schristos AcpiGbl_FileTreeRoot->Filename = (char *)(AmlStart+2);
169835858a6Schristos
170835858a6Schristos /* Set the root file to the current open file */
171835858a6Schristos
1723fd31de5Schristos AcpiGbl_FileTreeRoot->File = RootFile;
173835858a6Schristos
174835858a6Schristos /*
17594783addSchristos * Set this to true because we don't need to output
176835858a6Schristos * an include statement for the topmost file
177835858a6Schristos */
178835858a6Schristos AcpiGbl_FileTreeRoot->IncludeWritten = TRUE;
179835858a6Schristos Filename = NULL;
180835858a6Schristos AcpiGbl_CurrentFilename = (char *)(AmlStart+2);
181835858a6Schristos AcpiGbl_RootFilename = (char *)(AmlStart+2);
182835858a6Schristos
183835858a6Schristos TreeAml = AmlStart;
184835858a6Schristos FileEnd = AmlStart + AmlLength;
185835858a6Schristos
186835858a6Schristos while (TreeAml <= FileEnd)
187835858a6Schristos {
188835858a6Schristos /*
189835858a6Schristos * Make sure that this filename contains all printable characters
190835858a6Schristos * and a .dsl extension at the end. If not, then it must be some
191835858a6Schristos * raw data that doesn't outline a filename.
192835858a6Schristos */
193835858a6Schristos if ((*TreeAml == AML_COMMENT_OP) &&
194835858a6Schristos (*(TreeAml +1) == FILENAME_COMMENT) &&
195835858a6Schristos (CvIsFilename ((char *)(TreeAml +2))))
196835858a6Schristos {
197835858a6Schristos CvDbgPrint ("A9 and a 08 file\n");
198835858a6Schristos PreviousFilename = Filename;
199835858a6Schristos Filename = (char *) (TreeAml +2);
20089b8eb6cSchristos
201835858a6Schristos CvAddToFileTree (Filename, PreviousFilename);
202835858a6Schristos ChildFilename = Filename;
203835858a6Schristos CvDbgPrint ("%s\n", Filename);
204835858a6Schristos }
205835858a6Schristos else if ((*TreeAml == AML_COMMENT_OP) &&
206835858a6Schristos (*(TreeAml +1) == PARENTFILENAME_COMMENT) &&
207835858a6Schristos (CvIsFilename ((char *)(TreeAml +2))))
208835858a6Schristos {
209835858a6Schristos CvDbgPrint ("A9 and a 09 file\n");
210835858a6Schristos ParentFilename = (char *)(TreeAml +2);
211835858a6Schristos CvSetFileParent (ChildFilename, ParentFilename);
212835858a6Schristos CvDbgPrint ("%s\n", ParentFilename);
213835858a6Schristos }
21489b8eb6cSchristos
215835858a6Schristos ++TreeAml;
216835858a6Schristos }
217835858a6Schristos }
218835858a6Schristos
219835858a6Schristos
220835858a6Schristos /*******************************************************************************
221835858a6Schristos *
222835858a6Schristos * FUNCTION: CvClearOpComments
223835858a6Schristos *
224835858a6Schristos * PARAMETERS: Op -- clear all comments within this Op
225835858a6Schristos *
22689b8eb6cSchristos * RETURN: None
227835858a6Schristos *
228835858a6Schristos * DESCRIPTION: Clear all converter-related fields of the given Op.
229835858a6Schristos * This is referred as ASL_CV_CLEAR_OP_COMMENTS.
230835858a6Schristos *
231835858a6Schristos ******************************************************************************/
232835858a6Schristos
233835858a6Schristos void
CvClearOpComments(ACPI_PARSE_OBJECT * Op)234835858a6Schristos CvClearOpComments (
235835858a6Schristos ACPI_PARSE_OBJECT *Op)
236835858a6Schristos {
23789b8eb6cSchristos
238835858a6Schristos Op->Common.InlineComment = NULL;
239835858a6Schristos Op->Common.EndNodeComment = NULL;
240835858a6Schristos Op->Common.NameComment = NULL;
241835858a6Schristos Op->Common.CommentList = NULL;
242835858a6Schristos Op->Common.EndBlkComment = NULL;
243835858a6Schristos Op->Common.CloseBraceComment = NULL;
244835858a6Schristos Op->Common.CvFilename = NULL;
245835858a6Schristos Op->Common.CvParentFilename = NULL;
246835858a6Schristos }
247835858a6Schristos
248835858a6Schristos
249835858a6Schristos /*******************************************************************************
250835858a6Schristos *
251835858a6Schristos * FUNCTION: CvCommentExists
252835858a6Schristos *
25389b8eb6cSchristos * PARAMETERS: Address - check if this address appears in the list
254835858a6Schristos *
255835858a6Schristos * RETURN: BOOLEAN - TRUE if the address exists.
256835858a6Schristos *
25789b8eb6cSchristos * DESCRIPTION: Look at the pointer address and check if this appears in the
25889b8eb6cSchristos * list of all addresses. If it exists in the list, return TRUE
259835858a6Schristos * if it exists. Otherwise add to the list and return FALSE.
260835858a6Schristos *
261835858a6Schristos ******************************************************************************/
262835858a6Schristos
263835858a6Schristos static BOOLEAN
CvCommentExists(UINT8 * Address)264835858a6Schristos CvCommentExists (
265835858a6Schristos UINT8 *Address)
266835858a6Schristos {
267835858a6Schristos ACPI_COMMENT_ADDR_NODE *Current = AcpiGbl_CommentAddrListHead;
268835858a6Schristos UINT8 Option;
269835858a6Schristos
270835858a6Schristos
271835858a6Schristos if (!Address)
272835858a6Schristos {
273835858a6Schristos return (FALSE);
274835858a6Schristos }
27589b8eb6cSchristos
276835858a6Schristos Option = *(Address + 1);
277835858a6Schristos
278835858a6Schristos /*
27989b8eb6cSchristos * FILENAME_COMMENT and PARENTFILENAME_COMMENT are not treated as
28089b8eb6cSchristos * comments. They serve as markers for where the file starts and ends.
281835858a6Schristos */
28289b8eb6cSchristos if ((Option == FILENAME_COMMENT) ||
28389b8eb6cSchristos (Option == PARENTFILENAME_COMMENT))
284835858a6Schristos {
285835858a6Schristos return (FALSE);
286835858a6Schristos }
287835858a6Schristos
288835858a6Schristos if (!Current)
289835858a6Schristos {
290835858a6Schristos AcpiGbl_CommentAddrListHead =
291835858a6Schristos AcpiOsAcquireObject (AcpiGbl_RegCommentCache);
292835858a6Schristos AcpiGbl_CommentAddrListHead->Addr = Address;
293835858a6Schristos AcpiGbl_CommentAddrListHead->Next = NULL;
294835858a6Schristos return (FALSE);
295835858a6Schristos }
296835858a6Schristos else
297835858a6Schristos {
298835858a6Schristos while (Current)
299835858a6Schristos {
300835858a6Schristos if (Current->Addr != Address)
301835858a6Schristos {
302835858a6Schristos Current = Current->Next;
303835858a6Schristos }
304835858a6Schristos else
305835858a6Schristos {
306835858a6Schristos return (TRUE);
307835858a6Schristos }
308835858a6Schristos }
309835858a6Schristos
310835858a6Schristos /*
31189b8eb6cSchristos * If the execution gets to this point, it means that this
31289b8eb6cSchristos * address does not exists in the list. Add this address to the
313835858a6Schristos * beginning of the list.
314835858a6Schristos */
315835858a6Schristos Current = AcpiGbl_CommentAddrListHead;
316835858a6Schristos AcpiGbl_CommentAddrListHead =
317835858a6Schristos AcpiOsAcquireObject (AcpiGbl_RegCommentCache);
31889b8eb6cSchristos
319835858a6Schristos AcpiGbl_CommentAddrListHead->Addr = Address;
320835858a6Schristos AcpiGbl_CommentAddrListHead->Next = Current;
321835858a6Schristos return (FALSE);
322835858a6Schristos }
323835858a6Schristos }
324835858a6Schristos
325835858a6Schristos
326835858a6Schristos /*******************************************************************************
327835858a6Schristos *
328835858a6Schristos * FUNCTION: CvFilenameExists
329835858a6Schristos *
330835858a6Schristos * PARAMETERS: Filename - filename to search
331835858a6Schristos *
332835858a6Schristos * RETURN: ACPI_FILE_NODE - a pointer to a file node
333835858a6Schristos *
334835858a6Schristos * DESCRIPTION: Look for the given filename in the file dependency tree.
335835858a6Schristos * Returns the file node if it exists, returns NULL if it does not.
336835858a6Schristos *
337835858a6Schristos ******************************************************************************/
338835858a6Schristos
339835858a6Schristos ACPI_FILE_NODE*
CvFilenameExists(char * Filename,ACPI_FILE_NODE * Head)340835858a6Schristos CvFilenameExists(
341835858a6Schristos char *Filename,
342835858a6Schristos ACPI_FILE_NODE *Head)
343835858a6Schristos {
344835858a6Schristos ACPI_FILE_NODE *Current = Head;
345835858a6Schristos
346835858a6Schristos
34789b8eb6cSchristos if (!Filename)
34889b8eb6cSchristos {
34989b8eb6cSchristos return (NULL);
35089b8eb6cSchristos }
35189b8eb6cSchristos
352835858a6Schristos while (Current)
353835858a6Schristos {
354835858a6Schristos if (!AcpiUtStricmp (Current->Filename, Filename))
355835858a6Schristos {
356835858a6Schristos return (Current);
357835858a6Schristos }
35889b8eb6cSchristos
359835858a6Schristos Current = Current->Next;
360835858a6Schristos }
361835858a6Schristos return (NULL);
362835858a6Schristos }
363835858a6Schristos
364835858a6Schristos
365835858a6Schristos /*******************************************************************************
366835858a6Schristos *
367835858a6Schristos * FUNCTION: CvFileAddressLookup
368835858a6Schristos *
369835858a6Schristos * PARAMETERS: Address - address to look up
370835858a6Schristos * Head - file dependency tree
371835858a6Schristos *
37289b8eb6cSchristos * RETURN: ACPI_FILE_NODE - pointer to a file node containing the address
373835858a6Schristos *
374835858a6Schristos * DESCRIPTION: Look for the given address in the file dependency tree.
375835858a6Schristos * Returns the first file node where the given address is within
376835858a6Schristos * the file node's starting and ending address.
377835858a6Schristos *
378835858a6Schristos ******************************************************************************/
379835858a6Schristos
380835858a6Schristos static ACPI_FILE_NODE *
CvFileAddressLookup(char * Address,ACPI_FILE_NODE * Head)381835858a6Schristos CvFileAddressLookup(
382835858a6Schristos char *Address,
383835858a6Schristos ACPI_FILE_NODE *Head)
384835858a6Schristos {
385835858a6Schristos ACPI_FILE_NODE *Current = Head;
386835858a6Schristos
387835858a6Schristos
388835858a6Schristos while (Current)
389835858a6Schristos {
390835858a6Schristos if ((Address >= Current->FileStart) &&
391835858a6Schristos (Address < Current->FileEnd ||
392835858a6Schristos !Current->FileEnd))
393835858a6Schristos {
394835858a6Schristos return (Current);
395835858a6Schristos }
39689b8eb6cSchristos
397835858a6Schristos Current = Current->Next;
398835858a6Schristos }
399835858a6Schristos
400835858a6Schristos return (NULL);
401835858a6Schristos }
402835858a6Schristos
403835858a6Schristos
404835858a6Schristos /*******************************************************************************
405835858a6Schristos *
406835858a6Schristos * FUNCTION: CvLabelFileNode
407835858a6Schristos *
408835858a6Schristos * PARAMETERS: Op
409835858a6Schristos *
410835858a6Schristos * RETURN: None
411835858a6Schristos *
412835858a6Schristos * DESCRIPTION: Takes a given parse op, looks up its Op->Common.Aml field
41394783addSchristos * within the file tree and fills in appropriate file information
414835858a6Schristos * from a matching node within the tree.
415835858a6Schristos * This is referred as ASL_CV_LABEL_FILENODE.
416835858a6Schristos *
417835858a6Schristos ******************************************************************************/
418835858a6Schristos
419835858a6Schristos void
CvLabelFileNode(ACPI_PARSE_OBJECT * Op)420835858a6Schristos CvLabelFileNode(
421835858a6Schristos ACPI_PARSE_OBJECT *Op)
422835858a6Schristos {
423835858a6Schristos ACPI_FILE_NODE *Node;
424835858a6Schristos
425835858a6Schristos
426835858a6Schristos if (!Op)
427835858a6Schristos {
428835858a6Schristos return;
429835858a6Schristos }
430835858a6Schristos
43189b8eb6cSchristos Node = CvFileAddressLookup ((char *)
43289b8eb6cSchristos Op->Common.Aml, AcpiGbl_FileTreeRoot);
433835858a6Schristos if (!Node)
434835858a6Schristos {
435835858a6Schristos return;
436835858a6Schristos }
437835858a6Schristos
438835858a6Schristos Op->Common.CvFilename = Node->Filename;
439835858a6Schristos if (Node->Parent)
440835858a6Schristos {
441835858a6Schristos Op->Common.CvParentFilename = Node->Parent->Filename;
442835858a6Schristos }
443835858a6Schristos else
444835858a6Schristos {
445835858a6Schristos Op->Common.CvParentFilename = Node->Filename;
446835858a6Schristos }
447835858a6Schristos }
448835858a6Schristos
449835858a6Schristos
450835858a6Schristos /*******************************************************************************
451835858a6Schristos *
452835858a6Schristos * FUNCTION: CvAddToFileTree
453835858a6Schristos *
454835858a6Schristos * PARAMETERS: Filename - Address containing the name of the current
455835858a6Schristos * filename
456835858a6Schristos * PreviousFilename - Address containing the name of the previous
457835858a6Schristos * filename
458835858a6Schristos *
45989b8eb6cSchristos * RETURN: None
460835858a6Schristos *
461835858a6Schristos * DESCRIPTION: Add this filename to the AcpiGbl_FileTree if it does not exist.
462835858a6Schristos *
463835858a6Schristos ******************************************************************************/
464835858a6Schristos
465835858a6Schristos static void
CvAddToFileTree(char * Filename,char * PreviousFilename)466835858a6Schristos CvAddToFileTree (
467835858a6Schristos char *Filename,
468835858a6Schristos char *PreviousFilename)
469835858a6Schristos {
470835858a6Schristos ACPI_FILE_NODE *Node;
471835858a6Schristos
472835858a6Schristos
473835858a6Schristos if (!AcpiUtStricmp(Filename, AcpiGbl_RootFilename) &&
474835858a6Schristos PreviousFilename)
475835858a6Schristos {
476835858a6Schristos Node = CvFilenameExists (PreviousFilename, AcpiGbl_FileTreeRoot);
477835858a6Schristos if (Node)
478835858a6Schristos {
479835858a6Schristos /*
480835858a6Schristos * Set the end point of the PreviousFilename to the address
481835858a6Schristos * of Filename.
482835858a6Schristos */
483835858a6Schristos Node->FileEnd = Filename;
484835858a6Schristos }
485835858a6Schristos }
486835858a6Schristos else if (!AcpiUtStricmp(Filename, AcpiGbl_RootFilename) &&
487835858a6Schristos !PreviousFilename)
488835858a6Schristos {
489835858a6Schristos return;
490835858a6Schristos }
491835858a6Schristos
492835858a6Schristos Node = CvFilenameExists (Filename, AcpiGbl_FileTreeRoot);
493835858a6Schristos if (Node && PreviousFilename)
494835858a6Schristos {
495835858a6Schristos /*
49689b8eb6cSchristos * Update the end of the previous file and all of their parents'
49789b8eb6cSchristos * ending addresses. This is done to ensure that parent file
49889b8eb6cSchristos * ranges extend to the end of their childrens' files.
499835858a6Schristos */
500835858a6Schristos Node = CvFilenameExists (PreviousFilename, AcpiGbl_FileTreeRoot);
501835858a6Schristos if (Node && (Node->FileEnd < Filename))
502835858a6Schristos {
503835858a6Schristos Node->FileEnd = Filename;
504835858a6Schristos Node = Node->Parent;
505835858a6Schristos while (Node)
506835858a6Schristos {
507835858a6Schristos if (Node->FileEnd < Filename)
508835858a6Schristos {
509835858a6Schristos Node->FileEnd = Filename;
510835858a6Schristos }
51189b8eb6cSchristos
512835858a6Schristos Node = Node->Parent;
513835858a6Schristos }
514835858a6Schristos }
515835858a6Schristos }
516835858a6Schristos else
517835858a6Schristos {
518835858a6Schristos Node = AcpiGbl_FileTreeRoot;
519835858a6Schristos AcpiGbl_FileTreeRoot = AcpiOsAcquireObject (AcpiGbl_FileCache);
52089b8eb6cSchristos
521835858a6Schristos AcpiGbl_FileTreeRoot->Next = Node;
522835858a6Schristos AcpiGbl_FileTreeRoot->Parent = NULL;
523835858a6Schristos AcpiGbl_FileTreeRoot->Filename = Filename;
524835858a6Schristos AcpiGbl_FileTreeRoot->FileStart = Filename;
525835858a6Schristos AcpiGbl_FileTreeRoot->IncludeWritten = FALSE;
526835858a6Schristos AcpiGbl_FileTreeRoot->File = fopen(Filename, "w+");
527835858a6Schristos
528835858a6Schristos /*
529835858a6Schristos * If we can't open the file, we need to abort here before we
530835858a6Schristos * accidentally write to a NULL file.
531835858a6Schristos */
532835858a6Schristos if (!AcpiGbl_FileTreeRoot->File)
533835858a6Schristos {
534835858a6Schristos /* delete the .xxx file */
535835858a6Schristos
536835858a6Schristos FlDeleteFile (ASL_FILE_AML_OUTPUT);
5374c4e8184Schristos sprintf (AslGbl_MsgBuffer, "\"%s\" - %s", Filename, strerror (errno));
53889b8eb6cSchristos AslCommonError (ASL_ERROR, ASL_MSG_OPEN, 0, 0, 0, 0,
5394c4e8184Schristos NULL, AslGbl_MsgBuffer);
540835858a6Schristos AslAbort ();
541835858a6Schristos }
542835858a6Schristos }
543835858a6Schristos }
544835858a6Schristos
545835858a6Schristos
546835858a6Schristos /*******************************************************************************
547835858a6Schristos *
548835858a6Schristos * FUNCTION: CvSetFileParent
549835858a6Schristos *
550835858a6Schristos * PARAMETERS: ChildFile - contains the filename of the child file
551835858a6Schristos * ParentFile - contains the filename of the parent file.
552835858a6Schristos *
55389b8eb6cSchristos * RETURN: None
554835858a6Schristos *
55589b8eb6cSchristos * DESCRIPTION: Point the parent pointer of the Child to the node that
556835858a6Schristos * corresponds with the parent file node.
557835858a6Schristos *
558835858a6Schristos ******************************************************************************/
559835858a6Schristos
560835858a6Schristos static void
CvSetFileParent(char * ChildFile,char * ParentFile)561835858a6Schristos CvSetFileParent (
562835858a6Schristos char *ChildFile,
563835858a6Schristos char *ParentFile)
564835858a6Schristos {
565835858a6Schristos ACPI_FILE_NODE *Child;
566835858a6Schristos ACPI_FILE_NODE *Parent;
567835858a6Schristos
568835858a6Schristos
569835858a6Schristos Child = CvFilenameExists (ChildFile, AcpiGbl_FileTreeRoot);
570835858a6Schristos Parent = CvFilenameExists (ParentFile, AcpiGbl_FileTreeRoot);
57189b8eb6cSchristos
572835858a6Schristos if (Child && Parent)
573835858a6Schristos {
574835858a6Schristos Child->Parent = Parent;
575835858a6Schristos
576835858a6Schristos while (Child->Parent)
577835858a6Schristos {
578835858a6Schristos if (Child->Parent->FileEnd < Child->FileStart)
579835858a6Schristos {
580835858a6Schristos Child->Parent->FileEnd = Child->FileStart;
581835858a6Schristos }
58289b8eb6cSchristos
583835858a6Schristos Child = Child->Parent;
584835858a6Schristos }
585835858a6Schristos }
586835858a6Schristos }
587835858a6Schristos
588835858a6Schristos
589835858a6Schristos /*******************************************************************************
590835858a6Schristos *
591835858a6Schristos * FUNCTION: CvCaptureCommentsOnly
592835858a6Schristos *
593835858a6Schristos * PARAMETERS: ParserState - A parser state object
594835858a6Schristos *
59589b8eb6cSchristos * RETURN: None
596835858a6Schristos *
59789b8eb6cSchristos * DESCRIPTION: Look at the aml that the parser state is pointing to,
598835858a6Schristos * capture any AML_COMMENT_OP and it's arguments and increment the
599835858a6Schristos * aml pointer past the comment. Comments are transferred to parse
600835858a6Schristos * nodes through CvTransferComments() as well as
601835858a6Schristos * AcpiPsBuildNamedOp().
602835858a6Schristos * This is referred as ASL_CV_CAPTURE_COMMENTS_ONLY.
603835858a6Schristos *
604835858a6Schristos ******************************************************************************/
605835858a6Schristos
606835858a6Schristos void
CvCaptureCommentsOnly(ACPI_PARSE_STATE * ParserState)607835858a6Schristos CvCaptureCommentsOnly (
608835858a6Schristos ACPI_PARSE_STATE *ParserState)
609835858a6Schristos {
610835858a6Schristos UINT8 *Aml = ParserState->Aml;
611835858a6Schristos UINT16 Opcode = (UINT16) ACPI_GET8 (Aml);
612835858a6Schristos UINT32 Length = 0;
613b406f703Schristos UINT8 CommentOption;
614835858a6Schristos BOOLEAN StdDefBlockFlag = FALSE;
615835858a6Schristos ACPI_COMMENT_NODE *CommentNode;
616835858a6Schristos ACPI_FILE_NODE *FileNode;
617835858a6Schristos
618835858a6Schristos
619062782b3Schristos if (!AcpiGbl_CaptureComments ||
620835858a6Schristos Opcode != AML_COMMENT_OP)
621835858a6Schristos {
622835858a6Schristos return;
623835858a6Schristos }
624835858a6Schristos
625835858a6Schristos while (Opcode == AML_COMMENT_OP)
626835858a6Schristos {
627835858a6Schristos CvDbgPrint ("comment aml address: %p\n", Aml);
628835858a6Schristos
629835858a6Schristos if (CvCommentExists(ParserState->Aml))
630835858a6Schristos {
631835858a6Schristos CvDbgPrint ("Avoiding capturing an existing comment.\n");
632835858a6Schristos }
633835858a6Schristos else
634835858a6Schristos {
635835858a6Schristos CommentOption = *(Aml +1);
636835858a6Schristos
63789b8eb6cSchristos /*
63889b8eb6cSchristos * Increment past the comment option and point the
63989b8eb6cSchristos * appropriate char pointers
64089b8eb6cSchristos */
641835858a6Schristos Aml += 2;
642835858a6Schristos
64389b8eb6cSchristos /* Found a comment. Now, set pointers to these comments. */
644835858a6Schristos
645835858a6Schristos switch (CommentOption)
646835858a6Schristos {
647835858a6Schristos case STD_DEFBLK_COMMENT:
648835858a6Schristos
649835858a6Schristos StdDefBlockFlag = TRUE;
650835858a6Schristos
65189b8eb6cSchristos /*
65289b8eb6cSchristos * Add to a linked list of nodes. This list will be
65389b8eb6cSchristos * taken by the parse node created next.
65489b8eb6cSchristos */
65589b8eb6cSchristos CommentNode = AcpiOsAcquireObject (
65689b8eb6cSchristos AcpiGbl_RegCommentCache);
657835858a6Schristos CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
658835858a6Schristos CommentNode->Next = NULL;
659835858a6Schristos
660835858a6Schristos if (!AcpiGbl_DefBlkCommentListHead)
661835858a6Schristos {
662835858a6Schristos AcpiGbl_DefBlkCommentListHead = CommentNode;
663835858a6Schristos AcpiGbl_DefBlkCommentListTail = CommentNode;
664835858a6Schristos }
665835858a6Schristos else
666835858a6Schristos {
667835858a6Schristos AcpiGbl_DefBlkCommentListTail->Next = CommentNode;
66889b8eb6cSchristos AcpiGbl_DefBlkCommentListTail =
66989b8eb6cSchristos AcpiGbl_DefBlkCommentListTail->Next;
670835858a6Schristos }
671835858a6Schristos break;
672835858a6Schristos
673835858a6Schristos case STANDARD_COMMENT:
674835858a6Schristos
675835858a6Schristos CvDbgPrint ("found regular comment.\n");
676835858a6Schristos
67789b8eb6cSchristos /*
67889b8eb6cSchristos * Add to a linked list of nodes. This list will be
67989b8eb6cSchristos * taken by the parse node created next.
68089b8eb6cSchristos */
68189b8eb6cSchristos CommentNode = AcpiOsAcquireObject (
68289b8eb6cSchristos AcpiGbl_RegCommentCache);
683835858a6Schristos CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
684835858a6Schristos CommentNode->Next = NULL;
685835858a6Schristos
686835858a6Schristos if (!AcpiGbl_RegCommentListHead)
687835858a6Schristos {
688835858a6Schristos AcpiGbl_RegCommentListHead = CommentNode;
689835858a6Schristos AcpiGbl_RegCommentListTail = CommentNode;
690835858a6Schristos }
691835858a6Schristos else
692835858a6Schristos {
693835858a6Schristos AcpiGbl_RegCommentListTail->Next = CommentNode;
69489b8eb6cSchristos AcpiGbl_RegCommentListTail =
69589b8eb6cSchristos AcpiGbl_RegCommentListTail->Next;
696835858a6Schristos }
697835858a6Schristos break;
698835858a6Schristos
699835858a6Schristos case ENDBLK_COMMENT:
700835858a6Schristos
701835858a6Schristos CvDbgPrint ("found endblk comment.\n");
702835858a6Schristos
70389b8eb6cSchristos /* Add to a linked list of nodes. This will be
70489b8eb6cSchristos * taken by the next created parse node.
70589b8eb6cSchristos */
70689b8eb6cSchristos CommentNode = AcpiOsAcquireObject (
70789b8eb6cSchristos AcpiGbl_RegCommentCache);
708835858a6Schristos CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
709835858a6Schristos CommentNode->Next = NULL;
710835858a6Schristos
711835858a6Schristos if (!AcpiGbl_EndBlkCommentListHead)
712835858a6Schristos {
713835858a6Schristos AcpiGbl_EndBlkCommentListHead = CommentNode;
714835858a6Schristos AcpiGbl_EndBlkCommentListTail = CommentNode;
715835858a6Schristos }
716835858a6Schristos else
717835858a6Schristos {
718835858a6Schristos AcpiGbl_EndBlkCommentListTail->Next = CommentNode;
71989b8eb6cSchristos AcpiGbl_EndBlkCommentListTail =
72089b8eb6cSchristos AcpiGbl_EndBlkCommentListTail->Next;
721835858a6Schristos }
722835858a6Schristos break;
723835858a6Schristos
724835858a6Schristos case INLINE_COMMENT:
725835858a6Schristos
726835858a6Schristos CvDbgPrint ("found inline comment.\n");
72789b8eb6cSchristos AcpiGbl_CurrentInlineComment =
72889b8eb6cSchristos ACPI_CAST_PTR (char, Aml);
729835858a6Schristos break;
730835858a6Schristos
731835858a6Schristos case ENDNODE_COMMENT:
732835858a6Schristos
733835858a6Schristos CvDbgPrint ("found EndNode comment.\n");
73489b8eb6cSchristos AcpiGbl_CurrentEndNodeComment =
73589b8eb6cSchristos ACPI_CAST_PTR (char, Aml);
736835858a6Schristos break;
737835858a6Schristos
738835858a6Schristos case CLOSE_BRACE_COMMENT:
739835858a6Schristos
740835858a6Schristos CvDbgPrint ("found close brace comment.\n");
74189b8eb6cSchristos AcpiGbl_CurrentCloseBraceComment =
74289b8eb6cSchristos ACPI_CAST_PTR (char, Aml);
743835858a6Schristos break;
744835858a6Schristos
745835858a6Schristos case END_DEFBLK_COMMENT:
746835858a6Schristos
74789b8eb6cSchristos CvDbgPrint ("Found comment that belongs after"
74889b8eb6cSchristos " the } for a definition block.\n");
74989b8eb6cSchristos AcpiGbl_CurrentScope->Common.CloseBraceComment =
75089b8eb6cSchristos ACPI_CAST_PTR (char, Aml);
751835858a6Schristos break;
752835858a6Schristos
753835858a6Schristos case FILENAME_COMMENT:
754835858a6Schristos
75589b8eb6cSchristos CvDbgPrint ("Found a filename: %s\n",
75689b8eb6cSchristos ACPI_CAST_PTR (char, Aml));
75789b8eb6cSchristos FileNode = CvFilenameExists (
75889b8eb6cSchristos ACPI_CAST_PTR (char, Aml), AcpiGbl_FileTreeRoot);
759835858a6Schristos
760835858a6Schristos /*
761835858a6Schristos * If there is an INCLUDE_COMMENT followed by a
762835858a6Schristos * FILENAME_COMMENT, then the INCLUDE_COMMENT is a comment
763835858a6Schristos * that is emitted before the #include for the file.
764835858a6Schristos * We will save the IncludeComment within the FileNode
765835858a6Schristos * associated with this FILENAME_COMMENT.
766835858a6Schristos */
767835858a6Schristos if (FileNode && AcpiGbl_IncCommentListHead)
768835858a6Schristos {
769835858a6Schristos FileNode->IncludeComment = AcpiGbl_IncCommentListHead;
770835858a6Schristos AcpiGbl_IncCommentListHead = NULL;
771835858a6Schristos AcpiGbl_IncCommentListTail = NULL;
772835858a6Schristos }
773835858a6Schristos break;
774835858a6Schristos
775835858a6Schristos case PARENTFILENAME_COMMENT:
776835858a6Schristos CvDbgPrint (" Found a parent filename.\n");
777835858a6Schristos break;
778835858a6Schristos
779835858a6Schristos case INCLUDE_COMMENT:
780835858a6Schristos
781835858a6Schristos /*
782835858a6Schristos * Add to a linked list. This list will be taken by the
783835858a6Schristos * parse node created next. See the FILENAME_COMMENT case
784835858a6Schristos * for more details
785835858a6Schristos */
78689b8eb6cSchristos CommentNode = AcpiOsAcquireObject (
78789b8eb6cSchristos AcpiGbl_RegCommentCache);
788835858a6Schristos CommentNode->Comment = ACPI_CAST_PTR (char, Aml);
789835858a6Schristos CommentNode->Next = NULL;
790835858a6Schristos
791835858a6Schristos if (!AcpiGbl_IncCommentListHead)
792835858a6Schristos {
793835858a6Schristos AcpiGbl_IncCommentListHead = CommentNode;
794835858a6Schristos AcpiGbl_IncCommentListTail = CommentNode;
795835858a6Schristos }
796835858a6Schristos else
797835858a6Schristos {
798835858a6Schristos AcpiGbl_IncCommentListTail->Next = CommentNode;
79989b8eb6cSchristos AcpiGbl_IncCommentListTail =
80089b8eb6cSchristos AcpiGbl_IncCommentListTail->Next;
801835858a6Schristos }
802835858a6Schristos
80389b8eb6cSchristos CvDbgPrint ("Found a include comment: %s\n",
80489b8eb6cSchristos CommentNode->Comment);
805835858a6Schristos break;
806835858a6Schristos
807835858a6Schristos default:
808835858a6Schristos
809835858a6Schristos /* Not a valid comment option. Revert the AML */
810835858a6Schristos
811835858a6Schristos goto DefBlock;
812835858a6Schristos
81389b8eb6cSchristos } /* End switch statement */
814835858a6Schristos
81589b8eb6cSchristos } /* End else */
816835858a6Schristos
81789b8eb6cSchristos /* Determine the length and move forward that amount */
818835858a6Schristos
819835858a6Schristos Length = 0;
820835858a6Schristos while (ParserState->Aml[Length])
821835858a6Schristos {
822835858a6Schristos Length++;
823835858a6Schristos }
824835858a6Schristos
825835858a6Schristos ParserState->Aml += Length + 1;
826835858a6Schristos
827835858a6Schristos /* Peek at the next Opcode. */
828835858a6Schristos
829835858a6Schristos Aml = ParserState->Aml;
830835858a6Schristos Opcode = (UINT16) ACPI_GET8 (Aml);
831835858a6Schristos }
832835858a6Schristos
833835858a6Schristos DefBlock:
834835858a6Schristos if (StdDefBlockFlag)
835835858a6Schristos {
836835858a6Schristos /*
837835858a6Schristos * Give all of its comments to the current scope, which is known as
838835858a6Schristos * the definition block, since STD_DEFBLK_COMMENT only appears after
839835858a6Schristos * definition block headers.
840835858a6Schristos */
841835858a6Schristos AcpiGbl_CurrentScope->Common.CommentList
842835858a6Schristos = AcpiGbl_DefBlkCommentListHead;
843835858a6Schristos AcpiGbl_DefBlkCommentListHead = NULL;
844835858a6Schristos AcpiGbl_DefBlkCommentListTail = NULL;
845835858a6Schristos }
846835858a6Schristos }
847835858a6Schristos
848835858a6Schristos
849835858a6Schristos /*******************************************************************************
850835858a6Schristos *
851835858a6Schristos * FUNCTION: CvCaptureComments
852835858a6Schristos *
853835858a6Schristos * PARAMETERS: ParserState - A parser state object
854835858a6Schristos *
85589b8eb6cSchristos * RETURN: None
856835858a6Schristos *
857835858a6Schristos * DESCRIPTION: Wrapper function for CvCaptureCommentsOnly
858835858a6Schristos * This is referred as ASL_CV_CAPTURE_COMMENTS.
859835858a6Schristos *
860835858a6Schristos ******************************************************************************/
861835858a6Schristos
862835858a6Schristos void
CvCaptureComments(ACPI_WALK_STATE * WalkState)863835858a6Schristos CvCaptureComments (
864835858a6Schristos ACPI_WALK_STATE *WalkState)
865835858a6Schristos {
866835858a6Schristos UINT8 *Aml;
867835858a6Schristos UINT16 Opcode;
868835858a6Schristos const ACPI_OPCODE_INFO *OpInfo;
869835858a6Schristos
870835858a6Schristos
871062782b3Schristos if (!AcpiGbl_CaptureComments)
872835858a6Schristos {
873835858a6Schristos return;
874835858a6Schristos }
875835858a6Schristos
876835858a6Schristos /*
87789b8eb6cSchristos * Before parsing, check to see that comments that come directly
87889b8eb6cSchristos * after deferred opcodes aren't being processed.
879835858a6Schristos */
880835858a6Schristos Aml = WalkState->ParserState.Aml;
881835858a6Schristos Opcode = (UINT16) ACPI_GET8 (Aml);
882835858a6Schristos OpInfo = AcpiPsGetOpcodeInfo (Opcode);
883835858a6Schristos
884835858a6Schristos if (!(OpInfo->Flags & AML_DEFER) ||
885835858a6Schristos ((OpInfo->Flags & AML_DEFER) &&
886835858a6Schristos (WalkState->PassNumber != ACPI_IMODE_LOAD_PASS1)))
887835858a6Schristos {
888835858a6Schristos CvCaptureCommentsOnly (&WalkState->ParserState);
889835858a6Schristos WalkState->Aml = WalkState->ParserState.Aml;
890835858a6Schristos }
891835858a6Schristos
892835858a6Schristos }
893835858a6Schristos
894835858a6Schristos
895835858a6Schristos /*******************************************************************************
896835858a6Schristos *
897835858a6Schristos * FUNCTION: CvTransferComments
898835858a6Schristos *
899835858a6Schristos * PARAMETERS: Op - Transfer comments to this Op
900835858a6Schristos *
90189b8eb6cSchristos * RETURN: None
902835858a6Schristos *
90394783addSchristos * DESCRIPTION: Transfer all of the comments stored in global containers to the
904835858a6Schristos * given Op. This will be invoked shortly after the parser creates
905835858a6Schristos * a ParseOp.
906835858a6Schristos * This is referred as ASL_CV_TRANSFER_COMMENTS.
907835858a6Schristos *
908835858a6Schristos ******************************************************************************/
909835858a6Schristos
910835858a6Schristos void
CvTransferComments(ACPI_PARSE_OBJECT * Op)911835858a6Schristos CvTransferComments (
912835858a6Schristos ACPI_PARSE_OBJECT *Op)
913835858a6Schristos {
91489b8eb6cSchristos
915835858a6Schristos Op->Common.InlineComment = AcpiGbl_CurrentInlineComment;
916835858a6Schristos AcpiGbl_CurrentInlineComment = NULL;
917835858a6Schristos
918835858a6Schristos Op->Common.EndNodeComment = AcpiGbl_CurrentEndNodeComment;
919835858a6Schristos AcpiGbl_CurrentEndNodeComment = NULL;
920835858a6Schristos
921835858a6Schristos Op->Common.CloseBraceComment = AcpiGbl_CurrentCloseBraceComment;
922835858a6Schristos AcpiGbl_CurrentCloseBraceComment = NULL;
923835858a6Schristos
924835858a6Schristos Op->Common.CommentList = AcpiGbl_RegCommentListHead;
925835858a6Schristos AcpiGbl_RegCommentListHead = NULL;
926835858a6Schristos AcpiGbl_RegCommentListTail = NULL;
927835858a6Schristos
928835858a6Schristos Op->Common.EndBlkComment = AcpiGbl_EndBlkCommentListHead;
929835858a6Schristos AcpiGbl_EndBlkCommentListHead = NULL;
930835858a6Schristos AcpiGbl_EndBlkCommentListTail = NULL;
931835858a6Schristos }
932