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