1 2 /****************************************************************************** 3 * 4 * Module Name: asltransform - Parse tree transforms 5 * $Revision: 25 $ 6 * 7 *****************************************************************************/ 8 9 /****************************************************************************** 10 * 11 * 1. Copyright Notice 12 * 13 * Some or all of this work - Copyright (c) 1999 - 2004, Intel Corp. 14 * All rights reserved. 15 * 16 * 2. License 17 * 18 * 2.1. This is your license from Intel Corp. under its intellectual property 19 * rights. You may have additional license terms from the party that provided 20 * you this software, covering your right to use that party's intellectual 21 * property rights. 22 * 23 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 24 * copy of the source code appearing in this file ("Covered Code") an 25 * irrevocable, perpetual, worldwide license under Intel's copyrights in the 26 * base code distributed originally by Intel ("Original Intel Code") to copy, 27 * make derivatives, distribute, use and display any portion of the Covered 28 * Code in any form, with the right to sublicense such rights; and 29 * 30 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 31 * license (with the right to sublicense), under only those claims of Intel 32 * patents that are infringed by the Original Intel Code, to make, use, sell, 33 * offer to sell, and import the Covered Code and derivative works thereof 34 * solely to the minimum extent necessary to exercise the above copyright 35 * license, and in no event shall the patent license extend to any additions 36 * to or modifications of the Original Intel Code. No other license or right 37 * is granted directly or by implication, estoppel or otherwise; 38 * 39 * The above copyright and patent license is granted only if the following 40 * conditions are met: 41 * 42 * 3. Conditions 43 * 44 * 3.1. Redistribution of Source with Rights to Further Distribute Source. 45 * Redistribution of source code of any substantial portion of the Covered 46 * Code or modification with rights to further distribute source must include 47 * the above Copyright Notice, the above License, this list of Conditions, 48 * and the following Disclaimer and Export Compliance provision. In addition, 49 * Licensee must cause all Covered Code to which Licensee contributes to 50 * contain a file documenting the changes Licensee made to create that Covered 51 * Code and the date of any change. Licensee must include in that file the 52 * documentation of any changes made by any predecessor Licensee. Licensee 53 * must include a prominent statement that the modification is derived, 54 * directly or indirectly, from Original Intel Code. 55 * 56 * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 57 * Redistribution of source code of any substantial portion of the Covered 58 * Code or modification without rights to further distribute source must 59 * include the following Disclaimer and Export Compliance provision in the 60 * documentation and/or other materials provided with distribution. In 61 * addition, Licensee may not authorize further sublicense of source of any 62 * portion of the Covered Code, and must include terms to the effect that the 63 * license from Licensee to its licensee is limited to the intellectual 64 * property embodied in the software Licensee provides to its licensee, and 65 * not to intellectual property embodied in modifications its licensee may 66 * make. 67 * 68 * 3.3. Redistribution of Executable. Redistribution in executable form of any 69 * substantial portion of the Covered Code or modification must reproduce the 70 * above Copyright Notice, and the following Disclaimer and Export Compliance 71 * provision in the documentation and/or other materials provided with the 72 * distribution. 73 * 74 * 3.4. Intel retains all right, title, and interest in and to the Original 75 * Intel Code. 76 * 77 * 3.5. Neither the name Intel nor any other trademark owned or controlled by 78 * Intel shall be used in advertising or otherwise to promote the sale, use or 79 * other dealings in products derived from or relating to the Covered Code 80 * without prior written authorization from Intel. 81 * 82 * 4. Disclaimer and Export Compliance 83 * 84 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 85 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 86 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 87 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 88 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 89 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 90 * PARTICULAR PURPOSE. 91 * 92 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 93 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 94 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 95 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 96 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 97 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 98 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 99 * LIMITED REMEDY. 100 * 101 * 4.3. Licensee shall not export, either directly or indirectly, any of this 102 * software or system incorporating such software without first obtaining any 103 * required license or other approval from the U. S. Department of Commerce or 104 * any other agency or department of the United States Government. In the 105 * event Licensee exports any such software from the United States or 106 * re-exports any such software from a foreign destination, Licensee shall 107 * ensure that the distribution and export/re-export of the software is in 108 * compliance with all laws, regulations, orders, or other restrictions of the 109 * U.S. Export Administration Regulations. Licensee agrees that neither it nor 110 * any of its subsidiaries will export/re-export any technical data, process, 111 * software, or service, directly or indirectly, to any country for which the 112 * United States government or any agency thereof requires an export license, 113 * other governmental approval, or letter of assurance, without first obtaining 114 * such license, approval or letter. 115 * 116 *****************************************************************************/ 117 118 119 #include "aslcompiler.h" 120 #include "aslcompiler.y.h" 121 122 #define _COMPONENT ACPI_COMPILER 123 ACPI_MODULE_NAME ("asltransform") 124 125 126 /******************************************************************************* 127 * 128 * FUNCTION: TrAmlGetNextTempName 129 * 130 * PARAMETERS: NamePath - Where a pointer to the temp name is returned 131 * 132 * RETURN: A pointer to the second character of the name 133 * 134 * DESCRIPTION: Generate an ACPI name of the form _T_x. These names are 135 * reserved for use by the ASL compiler. 136 * 137 ******************************************************************************/ 138 139 char * 140 TrAmlGetNextTempName ( 141 char **NamePath) 142 { 143 char *TempName; 144 145 146 if (Gbl_TempCount > (9+26+26)) 147 { 148 /* Too many temps */ 149 /* TBD: issue eror message */ 150 *NamePath = "ERROR"; 151 return ("Error"); 152 } 153 154 TempName = UtLocalCalloc (6); 155 156 if (Gbl_TempCount < 9) 157 { 158 TempName[4] = (char) (Gbl_TempCount + 0x30); 159 } 160 else if (Gbl_TempCount < (9 + 26)) 161 { 162 TempName[4] = (char) (Gbl_TempCount + 0x41); 163 } 164 else 165 { 166 TempName[4] = (char) (Gbl_TempCount + 0x61); 167 } 168 Gbl_TempCount++; 169 170 /* First four characters are always "\_T_" */ 171 172 TempName[0] = '\\'; 173 TempName[1] = '_'; 174 TempName[2] = 'T'; 175 TempName[3] = '_'; 176 177 *NamePath = TempName; 178 return (&TempName[1]); 179 } 180 181 182 /******************************************************************************* 183 * 184 * FUNCTION: TrAmlInitLineNumbers 185 * 186 * PARAMETERS: Op - Op to be initialized 187 * Neighbor - Op used for initialization values 188 * 189 * RETURN: None 190 * 191 * DESCRIPTION: Initialized the various line numbers for a parse node. 192 * 193 ******************************************************************************/ 194 195 void 196 TrAmlInitLineNumbers ( 197 ACPI_PARSE_OBJECT *Op, 198 ACPI_PARSE_OBJECT *Neighbor) 199 { 200 201 Op->Asl.EndLine = Neighbor->Asl.EndLine; 202 Op->Asl.EndLogicalLine = Neighbor->Asl.EndLogicalLine; 203 Op->Asl.LineNumber = Neighbor->Asl.LineNumber; 204 Op->Asl.LogicalByteOffset = Neighbor->Asl.LogicalByteOffset; 205 Op->Asl.LogicalLineNumber = Neighbor->Asl.LogicalLineNumber; 206 } 207 208 209 /******************************************************************************* 210 * 211 * FUNCTION: TrAmlInitNode 212 * 213 * PARAMETERS: Op - Op to be initialized 214 * ParseOpcode - Opcode for this node 215 * 216 * RETURN: None 217 * 218 * DESCRIPTION: Initialize a node with the parse opcode and opcode name. 219 * 220 ******************************************************************************/ 221 222 void 223 TrAmlInitNode ( 224 ACPI_PARSE_OBJECT *Op, 225 UINT16 ParseOpcode) 226 { 227 228 Op->Asl.ParseOpcode = ParseOpcode; 229 UtSetParseOpName (Op); 230 } 231 232 233 /******************************************************************************* 234 * 235 * FUNCTION: TrAmlSetSubtreeParent 236 * 237 * PARAMETERS: Op - First node in a list of peer nodes 238 * Parent - Parent of the subtree 239 * 240 * RETURN: None 241 * 242 * DESCRIPTION: Set the parent for all peer nodes in a subtree 243 * 244 ******************************************************************************/ 245 246 void 247 TrAmlSetSubtreeParent ( 248 ACPI_PARSE_OBJECT *Op, 249 ACPI_PARSE_OBJECT *Parent) 250 { 251 ACPI_PARSE_OBJECT *Next; 252 253 254 Next = Op; 255 while (Next) 256 { 257 Next->Asl.Parent = Parent; 258 Next = Next->Asl.Next; 259 } 260 } 261 262 263 /******************************************************************************* 264 * 265 * FUNCTION: TrAmlInsertPeer 266 * 267 * PARAMETERS: Op - First node in a list of peer nodes 268 * NewPeer - Peer node to insert 269 * 270 * RETURN: None 271 * 272 * DESCRIPTION: Insert a new peer node into a list of peers. 273 * 274 ******************************************************************************/ 275 276 void 277 TrAmlInsertPeer ( 278 ACPI_PARSE_OBJECT *Op, 279 ACPI_PARSE_OBJECT *NewPeer) 280 { 281 282 NewPeer->Asl.Next = Op->Asl.Next; 283 Op->Asl.Next = NewPeer; 284 } 285 286 287 /******************************************************************************* 288 * 289 * FUNCTION: TrAmlTransformWalk 290 * 291 * PARAMETERS: ASL_WALK_CALLBACK 292 * 293 * RETURN: None 294 * 295 * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML 296 * operands. 297 * 298 ******************************************************************************/ 299 300 ACPI_STATUS 301 TrAmlTransformWalk ( 302 ACPI_PARSE_OBJECT *Op, 303 UINT32 Level, 304 void *Context) 305 { 306 307 TrTransformSubtree (Op); 308 return (AE_OK); 309 } 310 311 312 /******************************************************************************* 313 * 314 * FUNCTION: TrTransformSubtree 315 * 316 * PARAMETERS: Op - The parent parse node 317 * 318 * RETURN: None 319 * 320 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more 321 * complex AML opcodes require processing of the child nodes 322 * (arguments/operands). 323 * 324 ******************************************************************************/ 325 326 void 327 TrTransformSubtree ( 328 ACPI_PARSE_OBJECT *Op) 329 { 330 331 if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) 332 { 333 return; 334 } 335 336 switch (Op->Asl.ParseOpcode) 337 { 338 case PARSEOP_DEFINITIONBLOCK: 339 TrDoDefinitionBlock (Op); 340 break; 341 342 case PARSEOP_SWITCH: 343 TrDoSwitch (Op); 344 break; 345 346 default: 347 /* Nothing to do here for other opcodes */ 348 break; 349 } 350 } 351 352 353 /******************************************************************************* 354 * 355 * FUNCTION: TrDoDefinitionBlock 356 * 357 * PARAMETERS: Op - Parse node 358 * 359 * RETURN: None 360 * 361 * DESCRIPTION: Find the end of the definition block and set a global to this 362 * node. It is used by the compiler to insert compiler-generated 363 * names at the root level of the namespace. 364 * 365 ******************************************************************************/ 366 367 void 368 TrDoDefinitionBlock ( 369 ACPI_PARSE_OBJECT *Op) 370 { 371 ACPI_PARSE_OBJECT *Next; 372 UINT32 i; 373 374 375 Next = Op->Asl.Child; 376 for (i = 0; i < 5; i++) 377 { 378 Next = Next->Asl.Next; 379 } 380 381 Gbl_FirstLevelInsertionNode = Next; 382 } 383 384 385 /******************************************************************************* 386 * 387 * FUNCTION: TrDoSwitch 388 * 389 * PARAMETERS: StartNode - Parse node for SWITCH 390 * 391 * RETURN: None 392 * 393 * 394 * DESCRIPTION: Translate ASL SWITCH statement to if/else pairs. There is 395 * no actual AML opcode for SWITCH -- it must be simulated. 396 * 397 ******************************************************************************/ 398 399 void 400 TrDoSwitch ( 401 ACPI_PARSE_OBJECT *StartNode) 402 { 403 ACPI_PARSE_OBJECT *Next; 404 ACPI_PARSE_OBJECT *CaseOp = NULL; 405 ACPI_PARSE_OBJECT *CaseBlock = NULL; 406 ACPI_PARSE_OBJECT *DefaultOp = NULL; 407 ACPI_PARSE_OBJECT *CurrentParentNode; 408 ACPI_PARSE_OBJECT *Conditional = NULL; 409 ACPI_PARSE_OBJECT *Predicate; 410 ACPI_PARSE_OBJECT *Peer; 411 ACPI_PARSE_OBJECT *NewOp; 412 ACPI_PARSE_OBJECT *NewOp2; 413 char *PredicateValueName; 414 char *PredicateValuePath; 415 416 417 CurrentParentNode = StartNode; 418 PredicateValueName = TrAmlGetNextTempName (&PredicateValuePath); 419 420 /* First child is the predicate */ 421 422 Next = StartNode->Asl.Child; 423 Peer = Next->Asl.Next; 424 425 /* CASE statements start at next child */ 426 427 while (Peer) 428 { 429 Next = Peer; 430 Peer = Next->Asl.Next; 431 432 if (Next->Asl.ParseOpcode == PARSEOP_CASE) 433 { 434 if (CaseOp) 435 { 436 /* Add an ELSE to complete the previous CASE */ 437 438 NewOp = TrCreateLeafNode (PARSEOP_ELSE); 439 NewOp->Asl.Parent = Conditional->Asl.Parent; 440 TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent); 441 442 /* Link ELSE node as a peer to the previous IF */ 443 444 TrAmlInsertPeer (Conditional, NewOp); 445 CurrentParentNode = NewOp; 446 } 447 448 CaseOp = Next; 449 Conditional = CaseOp; 450 CaseBlock = CaseOp->Asl.Child->Asl.Next; 451 Conditional->Asl.Child->Asl.Next = NULL; 452 Predicate = CaseOp->Asl.Child; 453 454 if (Predicate->Asl.ParseOpcode == PARSEOP_PACKAGE) 455 { 456 AcpiOsPrintf ("Package\n"); 457 458 /* 459 * Convert the package declaration to this form: 460 * 461 * If (LNotEqual (Match (Package(){4}, MEQ, _Txx, MTR, 0, 0), Ones)) 462 */ 463 NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ); 464 Predicate->Asl.Next = NewOp2; 465 TrAmlInitLineNumbers (NewOp2, Conditional); 466 467 NewOp = NewOp2; 468 NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 469 (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValuePath)); 470 NewOp->Asl.Next = NewOp2; 471 TrAmlInitLineNumbers (NewOp2, Predicate); 472 473 NewOp = NewOp2; 474 NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR); 475 NewOp->Asl.Next = NewOp2; 476 TrAmlInitLineNumbers (NewOp2, Predicate); 477 478 NewOp = NewOp2; 479 NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); 480 NewOp->Asl.Next = NewOp2; 481 TrAmlInitLineNumbers (NewOp2, Predicate); 482 483 NewOp = NewOp2; 484 NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); 485 NewOp->Asl.Next = NewOp2; 486 TrAmlInitLineNumbers (NewOp2, Predicate); 487 488 NewOp2 = TrCreateLeafNode (PARSEOP_MATCH); 489 NewOp2->Asl.Child = Predicate; /* PARSEOP_PACKAGE */ 490 TrAmlInitLineNumbers (NewOp2, Conditional); 491 TrAmlSetSubtreeParent (Predicate, NewOp2); 492 493 NewOp = NewOp2; 494 NewOp2 = TrCreateLeafNode (PARSEOP_ONES); 495 NewOp->Asl.Next = NewOp2; 496 TrAmlInitLineNumbers (NewOp2, Conditional); 497 498 NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); 499 NewOp2->Asl.Child = NewOp; 500 NewOp->Asl.Parent = NewOp2; 501 TrAmlInitLineNumbers (NewOp2, Conditional); 502 TrAmlSetSubtreeParent (NewOp, NewOp2); 503 504 NewOp = NewOp2; 505 NewOp2 = TrCreateLeafNode (PARSEOP_LNOT); 506 NewOp2->Asl.Child = NewOp; 507 NewOp2->Asl.Parent = Conditional; 508 NewOp->Asl.Parent = NewOp2; 509 TrAmlInitLineNumbers (NewOp2, Conditional); 510 511 Conditional->Asl.Child = NewOp2; 512 NewOp2->Asl.Next = CaseBlock; 513 } 514 else 515 { 516 /* 517 * Change CaseOp() to: If (PredicateValue == CaseValue) {...} 518 * CaseOp->Child is the case value 519 * CaseOp->Child->Peer is the beginning of the case block 520 */ 521 NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 522 (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValuePath)); 523 Predicate->Asl.Next = NewOp; 524 TrAmlInitLineNumbers (NewOp, Predicate); 525 526 NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); 527 NewOp2->Asl.Parent = Conditional; 528 NewOp2->Asl.Child = Predicate; 529 TrAmlInitLineNumbers (NewOp2, Conditional); 530 531 TrAmlSetSubtreeParent (Predicate, NewOp2); 532 533 Predicate = NewOp2; 534 Predicate->Asl.Next = CaseBlock; 535 536 TrAmlSetSubtreeParent (Predicate, Conditional); 537 Conditional->Asl.Child = Predicate; 538 } 539 540 /* Reinitialize the CASE node to an IF node */ 541 542 TrAmlInitNode (Conditional, PARSEOP_IF); 543 544 /* 545 * The first CASE(IF) is not nested under an ELSE. 546 * All other CASEs are children of a parent ELSE. 547 */ 548 if (CurrentParentNode == StartNode) 549 { 550 Conditional->Asl.Parent = CurrentParentNode->Asl.Parent; 551 552 /* Link IF into the peer list */ 553 554 TrAmlInsertPeer (CurrentParentNode, Conditional); 555 } 556 else 557 { 558 /* 559 * The IF is a child of previous IF/ELSE. It 560 * is therefore without peer. 561 */ 562 CurrentParentNode->Asl.Child = Conditional; 563 Conditional->Asl.Parent = CurrentParentNode; 564 Conditional->Asl.Next = NULL; 565 } 566 } 567 else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT) 568 { 569 if (DefaultOp) 570 { 571 /* 572 * More than one Default 573 * (Parser should catch this, should not get here) 574 */ 575 AslError (ASL_ERROR, ASL_MSG_COMPILER_INTERNAL, Next, 576 "Found more than one Default()"); 577 } 578 579 /* Save the DEFAULT node for later, after CASEs */ 580 581 DefaultOp = Next; 582 } 583 else 584 { 585 /* Unknown peer opcode */ 586 587 printf ("Unknown parse opcode for switch statement: %s (%d)\n", 588 Next->Asl.ParseOpName, Next->Asl.ParseOpcode); 589 } 590 } 591 592 /* 593 * Add the default case at the end of the if/else construct 594 */ 595 if (DefaultOp) 596 { 597 /* If no CASE statements, this is an error - see below */ 598 599 if (CaseOp) 600 { 601 /* Convert the DEFAULT node to an ELSE */ 602 603 TrAmlInitNode (DefaultOp, PARSEOP_ELSE); 604 DefaultOp->Asl.Parent = Conditional->Asl.Parent; 605 606 /* Link ELSE node as a peer to the previous IF */ 607 608 TrAmlInsertPeer (Conditional, DefaultOp); 609 } 610 } 611 612 if (!CaseOp) 613 { 614 AslError (ASL_ERROR, ASL_MSG_NO_CASES, StartNode, NULL); 615 } 616 617 /* 618 * Add a NAME node for the temp integer 619 */ 620 NewOp = TrCreateLeafNode (PARSEOP_NAME); 621 NewOp->Asl.Parent = Gbl_FirstLevelInsertionNode->Asl.Parent; 622 NewOp->Asl.CompileFlags |= NODE_COMPILER_EMITTED; 623 624 NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 625 (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValueName)); 626 NewOp->Asl.Child = NewOp2; 627 NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_INTEGER, (ACPI_INTEGER) 0); 628 629 TrAmlSetSubtreeParent (NewOp2, NewOp); 630 631 /* Insert this node at the global level of the ASL */ 632 633 TrAmlInsertPeer (Gbl_FirstLevelInsertionNode, NewOp); 634 TrAmlInitLineNumbers (NewOp, Gbl_FirstLevelInsertionNode); 635 TrAmlInitLineNumbers (NewOp2, Gbl_FirstLevelInsertionNode); 636 TrAmlInitLineNumbers (NewOp2->Asl.Next, Gbl_FirstLevelInsertionNode); 637 638 /* 639 * Change the SWITCH node to a STORE (predicate value, _Txx) 640 */ 641 TrAmlInitNode (StartNode, PARSEOP_STORE); 642 643 Predicate = StartNode->Asl.Child; 644 NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 645 (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValuePath)); 646 NewOp->Asl.Parent = StartNode; 647 Predicate->Asl.Next = NewOp; 648 } 649 650 651