| /****************************************************************************** |
| * |
| * Module Name: asltransform - Parse tree transforms |
| * |
| *****************************************************************************/ |
| |
| /* |
| * Copyright (C) 2000 - 2016, Intel Corp. |
| * All rights reserved. |
| * |
| * Redistribution and use in source and binary forms, with or without |
| * modification, are permitted provided that the following conditions |
| * are met: |
| * 1. Redistributions of source code must retain the above copyright |
| * notice, this list of conditions, and the following disclaimer, |
| * without modification. |
| * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
| * substantially similar to the "NO WARRANTY" disclaimer below |
| * ("Disclaimer") and any redistribution must be conditioned upon |
| * including a substantially similar Disclaimer requirement for further |
| * binary redistribution. |
| * 3. Neither the names of the above-listed copyright holders nor the names |
| * of any contributors may be used to endorse or promote products derived |
| * from this software without specific prior written permission. |
| * |
| * Alternatively, this software may be distributed under the terms of the |
| * GNU General Public License ("GPL") version 2 as published by the Free |
| * Software Foundation. |
| * |
| * NO WARRANTY |
| * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
| * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
| * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
| * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
| * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
| * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
| * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
| * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
| * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
| * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
| * POSSIBILITY OF SUCH DAMAGES. |
| */ |
| |
| #include "aslcompiler.h" |
| #include "aslcompiler.y.h" |
| |
| #define _COMPONENT ACPI_COMPILER |
| ACPI_MODULE_NAME ("asltransform") |
| |
| /* Local prototypes */ |
| |
| static void |
| TrTransformSubtree ( |
| ACPI_PARSE_OBJECT *Op); |
| |
| static char * |
| TrAmlGetNextTempName ( |
| ACPI_PARSE_OBJECT *Op, |
| UINT8 *TempCount); |
| |
| static void |
| TrAmlInitLineNumbers ( |
| ACPI_PARSE_OBJECT *Op, |
| ACPI_PARSE_OBJECT *Neighbor); |
| |
| static void |
| TrAmlInitNode ( |
| ACPI_PARSE_OBJECT *Op, |
| UINT16 ParseOpcode); |
| |
| static void |
| TrAmlSetSubtreeParent ( |
| ACPI_PARSE_OBJECT *Op, |
| ACPI_PARSE_OBJECT *Parent); |
| |
| static void |
| TrAmlInsertPeer ( |
| ACPI_PARSE_OBJECT *Op, |
| ACPI_PARSE_OBJECT *NewPeer); |
| |
| static void |
| TrDoDefinitionBlock ( |
| ACPI_PARSE_OBJECT *Op); |
| |
| static void |
| TrDoSwitch ( |
| ACPI_PARSE_OBJECT *StartNode); |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrAmlGetNextTempName |
| * |
| * PARAMETERS: Op - Current parse op |
| * TempCount - Current temporary counter. Was originally |
| * per-module; Currently per method, could be |
| * expanded to per-scope. |
| * |
| * RETURN: A pointer to name (allocated here). |
| * |
| * DESCRIPTION: Generate an ACPI name of the form _T_x. These names are |
| * reserved for use by the ASL compiler. (_T_0 through _T_Z) |
| * |
| ******************************************************************************/ |
| |
| static char * |
| TrAmlGetNextTempName ( |
| ACPI_PARSE_OBJECT *Op, |
| UINT8 *TempCount) |
| { |
| char *TempName; |
| |
| |
| if (*TempCount >= (10 + 26)) /* 0-35 valid: 0-9 and A-Z for TempName[3] */ |
| { |
| /* Too many temps */ |
| |
| AslError (ASL_ERROR, ASL_MSG_TOO_MANY_TEMPS, Op, NULL); |
| return (NULL); |
| } |
| |
| TempName = UtLocalCalloc (5); |
| |
| if (*TempCount < 10) /* 0-9 */ |
| { |
| TempName[3] = (char) (*TempCount + '0'); |
| } |
| else /* 10-35: A-Z */ |
| { |
| TempName[3] = (char) (*TempCount + ('A' - 10)); |
| } |
| |
| (*TempCount)++; |
| |
| /* First three characters are always "_T_" */ |
| |
| TempName[0] = '_'; |
| TempName[1] = 'T'; |
| TempName[2] = '_'; |
| |
| return (TempName); |
| } |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrAmlInitLineNumbers |
| * |
| * PARAMETERS: Op - Op to be initialized |
| * Neighbor - Op used for initialization values |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Initialized the various line numbers for a parse node. |
| * |
| ******************************************************************************/ |
| |
| static void |
| TrAmlInitLineNumbers ( |
| ACPI_PARSE_OBJECT *Op, |
| ACPI_PARSE_OBJECT *Neighbor) |
| { |
| |
| Op->Asl.EndLine = Neighbor->Asl.EndLine; |
| Op->Asl.EndLogicalLine = Neighbor->Asl.EndLogicalLine; |
| Op->Asl.LineNumber = Neighbor->Asl.LineNumber; |
| Op->Asl.LogicalByteOffset = Neighbor->Asl.LogicalByteOffset; |
| Op->Asl.LogicalLineNumber = Neighbor->Asl.LogicalLineNumber; |
| } |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrAmlInitNode |
| * |
| * PARAMETERS: Op - Op to be initialized |
| * ParseOpcode - Opcode for this node |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Initialize a node with the parse opcode and opcode name. |
| * |
| ******************************************************************************/ |
| |
| static void |
| TrAmlInitNode ( |
| ACPI_PARSE_OBJECT *Op, |
| UINT16 ParseOpcode) |
| { |
| |
| Op->Asl.ParseOpcode = ParseOpcode; |
| UtSetParseOpName (Op); |
| } |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrAmlSetSubtreeParent |
| * |
| * PARAMETERS: Op - First node in a list of peer nodes |
| * Parent - Parent of the subtree |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Set the parent for all peer nodes in a subtree |
| * |
| ******************************************************************************/ |
| |
| static void |
| TrAmlSetSubtreeParent ( |
| ACPI_PARSE_OBJECT *Op, |
| ACPI_PARSE_OBJECT *Parent) |
| { |
| ACPI_PARSE_OBJECT *Next; |
| |
| |
| Next = Op; |
| while (Next) |
| { |
| Next->Asl.Parent = Parent; |
| Next = Next->Asl.Next; |
| } |
| } |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrAmlInsertPeer |
| * |
| * PARAMETERS: Op - First node in a list of peer nodes |
| * NewPeer - Peer node to insert |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Insert a new peer node into a list of peers. |
| * |
| ******************************************************************************/ |
| |
| static void |
| TrAmlInsertPeer ( |
| ACPI_PARSE_OBJECT *Op, |
| ACPI_PARSE_OBJECT *NewPeer) |
| { |
| |
| NewPeer->Asl.Next = Op->Asl.Next; |
| Op->Asl.Next = NewPeer; |
| } |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrAmlTransformWalk |
| * |
| * PARAMETERS: ASL_WALK_CALLBACK |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Parse tree walk to generate both the AML opcodes and the AML |
| * operands. |
| * |
| ******************************************************************************/ |
| |
| ACPI_STATUS |
| TrAmlTransformWalk ( |
| ACPI_PARSE_OBJECT *Op, |
| UINT32 Level, |
| void *Context) |
| { |
| |
| TrTransformSubtree (Op); |
| return (AE_OK); |
| } |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrTransformSubtree |
| * |
| * PARAMETERS: Op - The parent parse node |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Prepare nodes to be output as AML data and operands. The more |
| * complex AML opcodes require processing of the child nodes |
| * (arguments/operands). |
| * |
| ******************************************************************************/ |
| |
| static void |
| TrTransformSubtree ( |
| ACPI_PARSE_OBJECT *Op) |
| { |
| |
| if (Op->Asl.AmlOpcode == AML_RAW_DATA_BYTE) |
| { |
| return; |
| } |
| |
| switch (Op->Asl.ParseOpcode) |
| { |
| case PARSEOP_DEFINITION_BLOCK: |
| |
| TrDoDefinitionBlock (Op); |
| break; |
| |
| case PARSEOP_SWITCH: |
| |
| TrDoSwitch (Op); |
| break; |
| |
| case PARSEOP_METHOD: |
| /* |
| * TBD: Zero the tempname (_T_x) count. Probably shouldn't be a global, |
| * however |
| */ |
| Gbl_TempCount = 0; |
| break; |
| |
| default: |
| |
| /* Nothing to do here for other opcodes */ |
| |
| break; |
| } |
| } |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrDoDefinitionBlock |
| * |
| * PARAMETERS: Op - Parse node |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Find the end of the definition block and set a global to this |
| * node. It is used by the compiler to insert compiler-generated |
| * names at the root level of the namespace. |
| * |
| ******************************************************************************/ |
| |
| static void |
| TrDoDefinitionBlock ( |
| ACPI_PARSE_OBJECT *Op) |
| { |
| ACPI_PARSE_OBJECT *Next; |
| UINT32 i; |
| |
| |
| Next = Op->Asl.Child; |
| for (i = 0; i < 5; i++) |
| { |
| Next = Next->Asl.Next; |
| if (i == 0) |
| { |
| /* |
| * This is the table signature. Only the DSDT can be assumed |
| * to be at the root of the namespace; Therefore, namepath |
| * optimization can only be performed on the DSDT. |
| */ |
| if (!ACPI_COMPARE_NAME (Next->Asl.Value.String, ACPI_SIG_DSDT)) |
| { |
| Gbl_ReferenceOptimizationFlag = FALSE; |
| } |
| } |
| } |
| |
| Gbl_FirstLevelInsertionNode = Next; |
| } |
| |
| |
| /******************************************************************************* |
| * |
| * FUNCTION: TrDoSwitch |
| * |
| * PARAMETERS: StartNode - Parse node for SWITCH |
| * |
| * RETURN: None |
| * |
| * DESCRIPTION: Translate ASL SWITCH statement to if/else pairs. There is |
| * no actual AML opcode for SWITCH -- it must be simulated. |
| * |
| ******************************************************************************/ |
| |
| static void |
| TrDoSwitch ( |
| ACPI_PARSE_OBJECT *StartNode) |
| { |
| ACPI_PARSE_OBJECT *Next; |
| ACPI_PARSE_OBJECT *CaseOp = NULL; |
| ACPI_PARSE_OBJECT *CaseBlock = NULL; |
| ACPI_PARSE_OBJECT *DefaultOp = NULL; |
| ACPI_PARSE_OBJECT *CurrentParentNode; |
| ACPI_PARSE_OBJECT *Conditional = NULL; |
| ACPI_PARSE_OBJECT *Predicate; |
| ACPI_PARSE_OBJECT *Peer; |
| ACPI_PARSE_OBJECT *NewOp; |
| ACPI_PARSE_OBJECT *NewOp2; |
| ACPI_PARSE_OBJECT *MethodOp; |
| ACPI_PARSE_OBJECT *StoreOp; |
| ACPI_PARSE_OBJECT *BreakOp; |
| ACPI_PARSE_OBJECT *BufferOp; |
| char *PredicateValueName; |
| UINT16 Index; |
| UINT32 Btype; |
| |
| |
| /* Start node is the Switch() node */ |
| |
| CurrentParentNode = StartNode; |
| |
| /* Create a new temp name of the form _T_x */ |
| |
| PredicateValueName = TrAmlGetNextTempName (StartNode, &Gbl_TempCount); |
| if (!PredicateValueName) |
| { |
| return; |
| } |
| |
| /* First child is the Switch() predicate */ |
| |
| Next = StartNode->Asl.Child; |
| |
| /* |
| * Examine the return type of the Switch Value - |
| * must be Integer/Buffer/String |
| */ |
| Index = (UINT16) (Next->Asl.ParseOpcode - ASL_PARSE_OPCODE_BASE); |
| Btype = AslKeywordMapping[Index].AcpiBtype; |
| if ((Btype != ACPI_BTYPE_INTEGER) && |
| (Btype != ACPI_BTYPE_STRING) && |
| (Btype != ACPI_BTYPE_BUFFER)) |
| { |
| AslError (ASL_WARNING, ASL_MSG_SWITCH_TYPE, Next, NULL); |
| Btype = ACPI_BTYPE_INTEGER; |
| } |
| |
| /* CASE statements start at next child */ |
| |
| Peer = Next->Asl.Next; |
| while (Peer) |
| { |
| Next = Peer; |
| Peer = Next->Asl.Next; |
| |
| if (Next->Asl.ParseOpcode == PARSEOP_CASE) |
| { |
| if (CaseOp) |
| { |
| /* Add an ELSE to complete the previous CASE */ |
| |
| NewOp = TrCreateLeafNode (PARSEOP_ELSE); |
| NewOp->Asl.Parent = Conditional->Asl.Parent; |
| TrAmlInitLineNumbers (NewOp, NewOp->Asl.Parent); |
| |
| /* Link ELSE node as a peer to the previous IF */ |
| |
| TrAmlInsertPeer (Conditional, NewOp); |
| CurrentParentNode = NewOp; |
| } |
| |
| CaseOp = Next; |
| Conditional = CaseOp; |
| CaseBlock = CaseOp->Asl.Child->Asl.Next; |
| Conditional->Asl.Child->Asl.Next = NULL; |
| Predicate = CaseOp->Asl.Child; |
| |
| if ((Predicate->Asl.ParseOpcode == PARSEOP_PACKAGE) || |
| (Predicate->Asl.ParseOpcode == PARSEOP_VAR_PACKAGE)) |
| { |
| /* |
| * Convert the package declaration to this form: |
| * |
| * If (LNotEqual (Match (Package(<size>){<data>}, |
| * MEQ, _T_x, MTR, Zero, Zero), Ones)) |
| */ |
| NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MEQ); |
| Predicate->Asl.Next = NewOp2; |
| TrAmlInitLineNumbers (NewOp2, Conditional); |
| |
| NewOp = NewOp2; |
| NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, |
| (UINT64) ACPI_TO_INTEGER (PredicateValueName)); |
| NewOp->Asl.Next = NewOp2; |
| TrAmlInitLineNumbers (NewOp2, Predicate); |
| |
| NewOp = NewOp2; |
| NewOp2 = TrCreateLeafNode (PARSEOP_MATCHTYPE_MTR); |
| NewOp->Asl.Next = NewOp2; |
| TrAmlInitLineNumbers (NewOp2, Predicate); |
| |
| NewOp = NewOp2; |
| NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); |
| NewOp->Asl.Next = NewOp2; |
| TrAmlInitLineNumbers (NewOp2, Predicate); |
| |
| NewOp = NewOp2; |
| NewOp2 = TrCreateLeafNode (PARSEOP_ZERO); |
| NewOp->Asl.Next = NewOp2; |
| TrAmlInitLineNumbers (NewOp2, Predicate); |
| |
| NewOp2 = TrCreateLeafNode (PARSEOP_MATCH); |
| NewOp2->Asl.Child = Predicate; /* PARSEOP_PACKAGE */ |
| TrAmlInitLineNumbers (NewOp2, Conditional); |
| TrAmlSetSubtreeParent (Predicate, NewOp2); |
| |
| NewOp = NewOp2; |
| NewOp2 = TrCreateLeafNode (PARSEOP_ONES); |
| NewOp->Asl.Next = NewOp2; |
| TrAmlInitLineNumbers (NewOp2, Conditional); |
| |
| NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); |
| NewOp2->Asl.Child = NewOp; |
| NewOp->Asl.Parent = NewOp2; |
| TrAmlInitLineNumbers (NewOp2, Conditional); |
| TrAmlSetSubtreeParent (NewOp, NewOp2); |
| |
| NewOp = NewOp2; |
| NewOp2 = TrCreateLeafNode (PARSEOP_LNOT); |
| NewOp2->Asl.Child = NewOp; |
| NewOp2->Asl.Parent = Conditional; |
| NewOp->Asl.Parent = NewOp2; |
| TrAmlInitLineNumbers (NewOp2, Conditional); |
| |
| Conditional->Asl.Child = NewOp2; |
| NewOp2->Asl.Next = CaseBlock; |
| } |
| else |
| { |
| /* |
| * Integer and Buffer case. |
| * |
| * Change CaseOp() to: If (LEqual (SwitchValue, CaseValue)) {...} |
| * Note: SwitchValue is first to allow the CaseValue to be implicitly |
| * converted to the type of SwitchValue if necessary. |
| * |
| * CaseOp->Child is the case value |
| * CaseOp->Child->Peer is the beginning of the case block |
| */ |
| NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESTRING, |
| (UINT64) ACPI_TO_INTEGER (PredicateValueName)); |
| NewOp->Asl.Next = Predicate; |
| TrAmlInitLineNumbers (NewOp, Predicate); |
| |
| NewOp2 = TrCreateLeafNode (PARSEOP_LEQUAL); |
| NewOp2->Asl.Parent = Conditional; |
| NewOp2->Asl.Child = NewOp; |
| TrAmlInitLineNumbers (NewOp2, Conditional); |
| |
| TrAmlSetSubtreeParent (NewOp, NewOp2); |
| |
| Predicate = NewOp2; |
| Predicate->Asl.Next = CaseBlock; |
| |
| TrAmlSetSubtreeParent (Predicate, Conditional); |
| Conditional->Asl.Child = Predicate; |
| } |
| |
| /* Reinitialize the CASE node to an IF node */ |
| |
| TrAmlInitNode (Conditional, PARSEOP_IF); |
| |
| /* |
| * The first CASE(IF) is not nested under an ELSE. |
| * All other CASEs are children of a parent ELSE. |
| */ |
| if (CurrentParentNode == StartNode) |
| { |
| Conditional->Asl.Next = NULL; |
| } |
| else |
| { |
| /* |
| * The IF is a child of previous IF/ELSE. It |
| * is therefore without peer. |
| */ |
| CurrentParentNode->Asl.Child = Conditional; |
| Conditional->Asl.Parent = CurrentParentNode; |
| Conditional->Asl.Next = NULL; |
| } |
| } |
| else if (Next->Asl.ParseOpcode == PARSEOP_DEFAULT) |
| { |
| if (DefaultOp) |
| { |
| /* |
| * More than one Default |
| * (Parser does not catch this, must check here) |
| */ |
| AslError (ASL_ERROR, ASL_MSG_MULTIPLE_DEFAULT, Next, NULL); |
| } |
| else |
| { |
| /* Save the DEFAULT node for later, after CASEs */ |
| |
| DefaultOp = Next; |
| } |
| } |
| else |
| { |
| /* Unknown peer opcode */ |
| |
| AcpiOsPrintf ("Unknown parse opcode for switch statement: %s (%u)\n", |
| Next->Asl.ParseOpName, Next->Asl.ParseOpcode); |
| } |
| } |
| |
| /* Add the default case at the end of the if/else construct */ |
| |
| if (DefaultOp) |
| { |
| /* If no CASE statements, this is an error - see below */ |
| |
| if (CaseOp) |
| { |
| /* Convert the DEFAULT node to an ELSE */ |
| |
| TrAmlInitNode (DefaultOp, PARSEOP_ELSE); |
| DefaultOp->Asl.Parent = Conditional->Asl.Parent; |
| |
| /* Link ELSE node as a peer to the previous IF */ |
| |
| TrAmlInsertPeer (Conditional, DefaultOp); |
| } |
| } |
| |
| if (!CaseOp) |
| { |
| AslError (ASL_ERROR, ASL_MSG_NO_CASES, StartNode, NULL); |
| } |
| |
| |
| /* |
| * Create a Name(_T_x, ...) statement. This statement must appear at the |
| * method level, in case a loop surrounds the switch statement and could |
| * cause the name to be created twice (error). |
| */ |
| |
| /* Create the Name node */ |
| |
| Predicate = StartNode->Asl.Child; |
| NewOp = TrCreateLeafNode (PARSEOP_NAME); |
| TrAmlInitLineNumbers (NewOp, StartNode); |
| |
| /* Find the parent method */ |
| |
| Next = StartNode; |
| while ((Next->Asl.ParseOpcode != PARSEOP_METHOD) && |
| (Next->Asl.ParseOpcode != PARSEOP_DEFINITION_BLOCK)) |
| { |
| Next = Next->Asl.Parent; |
| } |
| MethodOp = Next; |
| |
| NewOp->Asl.CompileFlags |= NODE_COMPILER_EMITTED; |
| NewOp->Asl.Parent = Next; |
| |
| /* Insert name after the method name and arguments */ |
| |
| Next = Next->Asl.Child; /* Name */ |
| Next = Next->Asl.Next; /* NumArgs */ |
| Next = Next->Asl.Next; /* SerializeRule */ |
| |
| /* |
| * If method is not Serialized, we must make is so, because of the way |
| * that Switch() must be implemented -- we cannot allow multiple threads |
| * to execute this method concurrently since we need to create local |
| * temporary name(s). |
| */ |
| if (Next->Asl.ParseOpcode != PARSEOP_SERIALIZERULE_SERIAL) |
| { |
| AslError (ASL_REMARK, ASL_MSG_SERIALIZED, MethodOp, |
| "Due to use of Switch operator"); |
| Next->Asl.ParseOpcode = PARSEOP_SERIALIZERULE_SERIAL; |
| } |
| |
| Next = Next->Asl.Next; /* SyncLevel */ |
| Next = Next->Asl.Next; /* ReturnType */ |
| Next = Next->Asl.Next; /* ParameterTypes */ |
| |
| TrAmlInsertPeer (Next, NewOp); |
| TrAmlInitLineNumbers (NewOp, Next); |
| |
| /* Create the NameSeg child for the Name node */ |
| |
| NewOp2 = TrCreateValuedLeafNode (PARSEOP_NAMESEG, |
| (UINT64) ACPI_TO_INTEGER (PredicateValueName)); |
| TrAmlInitLineNumbers (NewOp2, NewOp); |
| NewOp2->Asl.CompileFlags |= NODE_IS_NAME_DECLARATION; |
| NewOp->Asl.Child = NewOp2; |
| |
| /* Create the initial value for the Name. Btype was already validated above */ |
| |
| switch (Btype) |
| { |
| case ACPI_BTYPE_INTEGER: |
| |
| NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_ZERO, |
| (UINT64) 0); |
| TrAmlInitLineNumbers (NewOp2->Asl.Next, NewOp); |
| break; |
| |
| case ACPI_BTYPE_STRING: |
| |
| NewOp2->Asl.Next = TrCreateValuedLeafNode (PARSEOP_STRING_LITERAL, |
| (UINT64) ACPI_TO_INTEGER ("")); |
| TrAmlInitLineNumbers (NewOp2->Asl.Next, NewOp); |
| break; |
| |
| case ACPI_BTYPE_BUFFER: |
| |
| (void) TrLinkPeerNode (NewOp2, TrCreateValuedLeafNode (PARSEOP_BUFFER, |
| (UINT64) 0)); |
| Next = NewOp2->Asl.Next; |
| TrAmlInitLineNumbers (Next, NewOp2); |
| (void) TrLinkChildren (Next, 1, TrCreateValuedLeafNode (PARSEOP_ZERO, |
| (UINT64) 1)); |
| TrAmlInitLineNumbers (Next->Asl.Child, Next); |
| |
| BufferOp = TrCreateValuedLeafNode (PARSEOP_DEFAULT_ARG, (UINT64) 0); |
| TrAmlInitLineNumbers (BufferOp, Next->Asl.Child); |
| (void) TrLinkPeerNode (Next->Asl.Child, BufferOp); |
| |
| TrAmlSetSubtreeParent (Next->Asl.Child, Next); |
| break; |
| |
| default: |
| |
| break; |
| } |
| |
| TrAmlSetSubtreeParent (NewOp2, NewOp); |
| |
| /* |
| * Transform the Switch() into a While(One)-Break node. |
| * And create a Store() node which will be used to save the |
| * Switch() value. The store is of the form: Store (Value, _T_x) |
| * where _T_x is the temp variable. |
| */ |
| TrAmlInitNode (StartNode, PARSEOP_WHILE); |
| NewOp = TrCreateLeafNode (PARSEOP_ONE); |
| TrAmlInitLineNumbers (NewOp, StartNode); |
| NewOp->Asl.Next = Predicate->Asl.Next; |
| NewOp->Asl.Parent = StartNode; |
| StartNode->Asl.Child = NewOp; |
| |
| /* Create a Store() node */ |
| |
| StoreOp = TrCreateLeafNode (PARSEOP_STORE); |
| TrAmlInitLineNumbers (StoreOp, NewOp); |
| StoreOp->Asl.Parent = StartNode; |
| TrAmlInsertPeer (NewOp, StoreOp); |
| |
| /* Complete the Store subtree */ |
| |
| StoreOp->Asl.Child = Predicate; |
| Predicate->Asl.Parent = StoreOp; |
| |
| NewOp = TrCreateValuedLeafNode (PARSEOP_NAMESEG, |
| (UINT64) ACPI_TO_INTEGER (PredicateValueName)); |
| TrAmlInitLineNumbers (NewOp, StoreOp); |
| NewOp->Asl.Parent = StoreOp; |
| Predicate->Asl.Next = NewOp; |
| |
| /* Create a Break() node and insert it into the end of While() */ |
| |
| Conditional = StartNode->Asl.Child; |
| while (Conditional->Asl.Next) |
| { |
| Conditional = Conditional->Asl.Next; |
| } |
| |
| BreakOp = TrCreateLeafNode (PARSEOP_BREAK); |
| TrAmlInitLineNumbers (BreakOp, NewOp); |
| BreakOp->Asl.Parent = StartNode; |
| TrAmlInsertPeer (Conditional, BreakOp); |
| } |