1 2 /****************************************************************************** 3 * 4 * Module Name: asltransform - Parse tree transforms 5 * $Revision: 20 $ 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 _Txx. 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 > 255) 147 { 148 /* Too many temps */ 149 /* TBD: issue eror message */ 150 *NamePath = "ERROR"; 151 return ("Error"); 152 } 153 154 TempName = UtLocalCalloc (6); 155 UtConvertByteToHex ((UINT8) Gbl_TempCount, (UINT8 *) &TempName [1]); 156 Gbl_TempCount++; 157 158 /* First three characters are always "\_T" */ 159 160 TempName[0] = '\\'; 161 TempName[1] = '_'; 162 TempName[2] = 'T'; 163 164 *NamePath = TempName; 165 return (&TempName[1]); 166 } 167 168 169 /******************************************************************************* 170 * 171 * FUNCTION: TrAmlInitLineNumbers 172 * 173 * PARAMETERS: Op - Op to be initialized 174 * Neighbor - Op used for initialization values 175 * 176 * RETURN: None 177 * 178 * DESCRIPTION: Initialized the various line numbers for a parse node. 179 * 180 ******************************************************************************/ 181 182 void 183 TrAmlInitLineNumbers ( 184 ACPI_PARSE_OBJECT *Op, 185 ACPI_PARSE_OBJECT *Neighbor) 186 { 187 188 Op->Asl.EndLine = Neighbor->Asl.EndLine; 189 Op->Asl.EndLogicalLine = Neighbor->Asl.EndLogicalLine; 190 Op->Asl.LineNumber = Neighbor->Asl.LineNumber; 191 Op->Asl.LogicalByteOffset = Neighbor->Asl.LogicalByteOffset; 192 Op->Asl.LogicalLineNumber = Neighbor->Asl.LogicalLineNumber; 193 } 194 195 196 /******************************************************************************* 197 * 198 * FUNCTION: TrAmlInitNode 199 * 200 * PARAMETERS: Op - Op to be initialized 201 * ParseOpcode - Opcode for this node 202 * 203 * RETURN: None 204 * 205 * DESCRIPTION: Initialize a node with the parse opcode and opcode name. 206 * 207 ******************************************************************************/ 208 209 void 210 TrAmlInitNode ( 211 ACPI_PARSE_OBJECT *Op, 212 UINT16 ParseOpcode) 213 { 214 215 Op->Asl.ParseOpcode = ParseOpcode; 216 UtSetParseOpName (Op); 217 } 218 219 220 /******************************************************************************* 221 * 222 * FUNCTION: TrAmlSetSubtreeParent 223 * 224 * PARAMETERS: Op - First node in a list of peer nodes 225 * Parent - Parent of the subtree 226 * 227 * RETURN: None 228 * 229 * DESCRIPTION: Set the parent for all peer nodes in a subtree 230 * 231 ******************************************************************************/ 232 233 void 234 TrAmlSetSubtreeParent ( 235 ACPI_PARSE_OBJECT *Op, 236 ACPI_PARSE_OBJECT *Parent) 237 { 238 ACPI_PARSE_OBJECT *Next; 239 240 241 Next = Op; 242 while (Next) 243 { 244 Next->Asl.Parent = Parent; 245 Next = Next->Asl.Next; 246 } 247 } 248 249 250 /******************************************************************************* 251 * 252 * FUNCTION: TrAmlInsertPeer 253 * 254 * PARAMETERS: Op - First node in a list of peer nodes 255 * NewPeer - Peer node to insert 256 * 257 * RETURN: None 258 * 259 * DESCRIPTION: Insert a new peer node into a list of peers. 260 * 261 ******************************************************************************/ 262 263 void 264 TrAmlInsertPeer ( 265 ACPI_PARSE_OBJECT *Op, 266 ACPI_PARSE_OBJECT *NewPeer) 267 { 268 269 NewPeer->Asl.Next = Op->Asl.Next; 270 Op->Asl.Next = NewPeer; 271 } 272 273 274 /******************************************************************************* 275 * 276 * FUNCTION: TrAmlTransformWalk 277 * 278 * PARAMETERS: ASL_WALK_CALLBACK 279 * 280 * RETURN: None 281 * 282 * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML 283 * operands. 284 * 285 ******************************************************************************/ 286 287 ACPI_STATUS 288 TrAmlTransformWalk ( 289 ACPI_PARSE_OBJECT *Op, 290 UINT32 Level, 291 void *Context) 292 { 293 294 TrTransformSubtree (Op); 295 return (AE_OK); 296 } 297 298 299 /******************************************************************************* 300 * 301 * FUNCTION: TrTransformSubtree 302 * 303 * PARAMETERS: Op - The parent parse node 304 * 305 * RETURN: None 306 * 307 * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more 308 * complex AML opcodes require processing of the child nodes 309 * (arguments/operands). 310 * 311 ******************************************************************************/ 312 313 void 314 TrTransformSubtree ( 315 ACPI_PARSE_OBJECT *Op) 316 { 317 318 if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) 319 { 320 return; 321 } 322 323 switch (Op->Asl.ParseOpcode) 324 { 325 case PARSEOP_DEFINITIONBLOCK: 326 TrDoDefinitionBlock (Op); 327 break; 328 329 case PARSEOP_ELSEIF: 330 TrDoElseif (Op); 331 break; 332 333 case PARSEOP_SWITCH: 334 TrDoSwitch (Op); 335 break; 336 337 default: 338 /* Nothing to do here for other opcodes */ 339 break; 340 } 341 } 342 343 344 /******************************************************************************* 345 * 346 * FUNCTION: TrDoDefinitionBlock 347 * 348 * PARAMETERS: Op - Parse node 349 * 350 * RETURN: None 351 * 352 * DESCRIPTION: Find the end of the definition block and set a global to this 353 * node. It is used by the compiler to insert compiler-generated 354 * names at the root level of the namespace. 355 * 356 ******************************************************************************/ 357 358 void 359 TrDoDefinitionBlock ( 360 ACPI_PARSE_OBJECT *Op) 361 { 362 ACPI_PARSE_OBJECT *Next; 363 UINT32 i; 364 365 366 Next = Op->Asl.Child; 367 for (i = 0; i < 5; i++) 368 { 369 Next = Next->Asl.Next; 370 } 371 372 Gbl_FirstLevelInsertionNode = Next; 373 } 374 375 376 /******************************************************************************* 377 * 378 * FUNCTION: TrDoElseif 379 * 380 * PARAMETERS: Op - Parse node for ELSEIF 381 * 382 * RETURN: None 383 * 384 * DESCRIPTION: Transform an Elseif into an Else and If AML opcode pair. 385 * There is no AML opcode for ELSEIF -- it must be simulated 386 * with an if/else pair. 387 * 388 ******************************************************************************/ 389 390 void 391 TrDoElseif ( 392 ACPI_PARSE_OBJECT *ElseNode) 393 { 394 ACPI_PARSE_OBJECT *IfNode = NULL; 395 ACPI_PARSE_OBJECT *NextNode; 396 397 398 /* Change the ELSEIF into an ELSE */ 399 400 TrAmlInitNode (ElseNode, PARSEOP_ELSE); 401 402 /* Create a new IF node */ 403 404 IfNode = TrCreateLeafNode (PARSEOP_IF); 405 IfNode->Asl.Parent = ElseNode; 406 TrAmlInitLineNumbers (IfNode, ElseNode); 407 408 /* Insert the the IF node first in the ELSE child list */ 409 410 IfNode->Asl.Child = ElseNode->Asl.Child; 411 ElseNode->Asl.Child = IfNode; 412 413 /* Go to the end of the IF <Predicate><TermList> block */ 414 415 NextNode = IfNode->Asl.Child; /* Next = Predicate */ 416 NextNode = NextNode->Asl.Next; /* Nest = TermList */ 417 418 /* Make the next node after the IF the rest of the original tree */ 419 420 IfNode->Asl.Next = NextNode->Asl.Next; 421 422 /* Terminate the IF subtree and set IF node as the parent for all nodes */ 423 424 NextNode->Asl.Next = NULL; 425 TrAmlSetSubtreeParent (IfNode->Asl.Child, IfNode); 426 } 427 428 429 /******************************************************************************* 430 * 431 * FUNCTION: TrDoSwitch 432 * 433 * PARAMETERS: StartNode - Parse node for SWITCH 434 * 435 * RETURN: None 436 * 437 * 438 * DESCRIPTION: Translate ASL SWITCH statement to if/else pairs. There is 439 * no actual AML opcode for SWITCH -- it must be simulated. 440 * 441 ******************************************************************************/ 442 443 void 444 TrDoSwitch ( 445 ACPI_PARSE_OBJECT *StartNode) 446 { 447 ACPI_PARSE_OBJECT *Next; 448 ACPI_PARSE_OBJECT *CaseOp = NULL; 449 ACPI_PARSE_OBJECT *CaseBlock = NULL; 450 ACPI_PARSE_OBJECT *DefaultOp = NULL; 451 ACPI_PARSE_OBJECT *CurrentParentNode; 452 ACPI_PARSE_OBJECT *Conditional = NULL; 453 ACPI_PARSE_OBJECT *Predicate; 454 ACPI_PARSE_OBJECT *Peer; 455 ACPI_PARSE_OBJECT *NewOp; 456 ACPI_PARSE_OBJECT *NewOp2; 457 char *PredicateValueName; 458 char *PredicateValuePath; 459 460 461 CurrentParentNode = StartNode; 462 PredicateValueName = TrAmlGetNextTempName (&PredicateValuePath); 463 464 /* First child is the predicate */ 465 466 Next = StartNode->Asl.Child; 467 Peer = Next->Asl.Next; 468 469 /* CASE statements start at next child */ 470 471 while (Peer) 472 { 473 Next = Peer; 474 Peer = Next->Asl.Next; 475 476 if (Next->Asl.ParseOpcode == PARSEOP_CASE) 477 { 478 if (CaseOp) 479 { 480 /* Add an ELSE to complete the previous CASE */ 481 482 NewOp = TrCreateLeafNode (PARSEOP_ELSE); 483 NewOp->Asl.Parent = Conditional->Asl.Parent; 484 TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent); 485 486 /* Link ELSE node as a peer to the previous IF */ 487 488 TrAmlInsertPeer (Conditional, NewOp); 489 CurrentParentNode = NewOp; 490 } 491 492 CaseOp = Next; 493 Conditional = CaseOp; 494 CaseBlock = CaseOp->Asl.Child->Asl.Next; 495 Conditional->Asl.Child->Asl.Next = NULL; 496 497 /* 498 * change CaseOp() to: If (PredicateValue == CaseValue) {...} 499 * CaseOp->Child is the case value 500 * CaseOp->Child->Peer is the beginning of the case block 501 */ 502 NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 503 (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValuePath)); 504 505 Predicate = CaseOp->Asl.Child; 506 Predicate->Asl.Next = NewOp; 507 TrAmlInitLineNumbers (NewOp, Predicate); 508 509 NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); 510 NewOp2->Asl.Parent = Conditional; 511 NewOp2->Asl.Child = Predicate; 512 TrAmlInitLineNumbers (NewOp2, Conditional); 513 514 TrAmlSetSubtreeParent (Predicate, NewOp2); 515 516 Predicate = NewOp2; 517 Predicate->Asl.Next = CaseBlock; 518 519 TrAmlSetSubtreeParent (Predicate, Conditional); 520 521 /* Reinitialize the CASE node to an IF node */ 522 523 Conditional->Asl.Child = Predicate; 524 TrAmlInitNode (Conditional, PARSEOP_IF); 525 526 /* 527 * The first CASE(IF) is not nested under an ELSE. 528 * All other CASEs are children of a parent ELSE. 529 */ 530 if (CurrentParentNode == StartNode) 531 { 532 Conditional->Asl.Parent = CurrentParentNode->Asl.Parent; 533 534 /* Link IF into the peer list */ 535 536 TrAmlInsertPeer (CurrentParentNode, Conditional); 537 } 538 else 539 { 540 /* 541 * The IF is a child of previous IF/ELSE. It 542 * is therefore without peer. 543 */ 544 CurrentParentNode->Asl.Child = Conditional; 545 Conditional->Asl.Parent = CurrentParentNode; 546 Conditional->Asl.Next = NULL; 547 } 548 } 549 else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT) 550 { 551 if (DefaultOp) 552 { 553 /* More than one Default */ 554 } 555 556 /* Save the DEFAULT node for later, after CASEs */ 557 558 DefaultOp = Next; 559 } 560 else 561 { 562 /* Unkown peer opcode */ 563 564 printf ("Unknown parse opcode for switch statement: %s (%d)\n", 565 Next->Asl.ParseOpName, Next->Asl.ParseOpcode); 566 } 567 } 568 569 /* 570 * Add the default at the end of the if/else construct 571 */ 572 if (DefaultOp) 573 { 574 if (CaseOp) 575 { 576 /* Add an ELSE first */ 577 578 TrAmlInitNode (DefaultOp, PARSEOP_ELSE); 579 DefaultOp->Asl.Parent = Conditional->Asl.Parent; 580 } 581 else 582 { 583 /* There were no CASE statements, no ELSE needed */ 584 585 TrAmlInsertPeer (CurrentParentNode, DefaultOp->Asl.Child); 586 } 587 } 588 589 /* 590 * Add a NAME node for the temp integer 591 */ 592 NewOp = TrCreateLeafNode (PARSEOP_NAME); 593 NewOp->Asl.Parent = Gbl_FirstLevelInsertionNode->Asl.Parent; 594 595 NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 596 (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValueName)); 597 NewOp->Asl.Child = NewOp2; 598 NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_INTEGER, (ACPI_INTEGER) 0); 599 600 TrAmlSetSubtreeParent (NewOp2, NewOp); 601 602 /* Insert this node at the global level of the ASL */ 603 604 TrAmlInsertPeer (Gbl_FirstLevelInsertionNode, NewOp); 605 TrAmlInitLineNumbers (NewOp, Gbl_FirstLevelInsertionNode); 606 TrAmlInitLineNumbers (NewOp2, Gbl_FirstLevelInsertionNode); 607 TrAmlInitLineNumbers (NewOp2->Asl.Next, Gbl_FirstLevelInsertionNode); 608 609 /* 610 * Change the SWITCH node to a STORE (predicate value, _Txx) 611 */ 612 TrAmlInitNode (StartNode, PARSEOP_STORE); 613 614 Predicate = StartNode->Asl.Child; 615 Predicate->Asl.Child = NULL; 616 617 NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, 618 (ACPI_INTEGER) ACPI_TO_INTEGER (PredicateValuePath)); 619 NewOp->Asl.Parent = StartNode; 620 Predicate->Asl.Next = NewOp; 621 } 622 623 624