Print this page
acpica-unix2-20130823
PANKOVs restructure
   1 /******************************************************************************
   2  *
   3  * Module Name: dscontrol - Support for execution control opcodes -
   4  *                          if/else/while/return
   5  *
   6  *****************************************************************************/
   7 
   8 /*
   9  * Copyright (C) 2000 - 2011, 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.


  69  ******************************************************************************/
  70 
  71 ACPI_STATUS
  72 AcpiDsExecBeginControlOp (
  73     ACPI_WALK_STATE         *WalkState,
  74     ACPI_PARSE_OBJECT       *Op)
  75 {
  76     ACPI_STATUS             Status = AE_OK;
  77     ACPI_GENERIC_STATE      *ControlState;
  78 
  79 
  80     ACPI_FUNCTION_NAME (DsExecBeginControlOp);
  81 
  82 
  83     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n",
  84         Op, Op->Common.AmlOpcode, WalkState));
  85 
  86     switch (Op->Common.AmlOpcode)
  87     {
  88     case AML_WHILE_OP:
  89 
  90         /*
  91          * If this is an additional iteration of a while loop, continue.
  92          * There is no need to allocate a new control state.
  93          */
  94         if (WalkState->ControlState)
  95         {
  96             if (WalkState->ControlState->Control.AmlPredicateStart ==
  97                 (WalkState->ParserState.Aml - 1))
  98             {
  99                 /* Reset the state to start-of-loop */
 100 
 101                 WalkState->ControlState->Common.State =
 102                     ACPI_CONTROL_CONDITIONAL_EXECUTING;
 103                 break;
 104             }
 105         }
 106 
 107         /*lint -fallthrough */
 108 
 109     case AML_IF_OP:
 110 
 111         /*
 112          * IF/WHILE: Create a new control state to manage these
 113          * constructs. We need to manage these as a stack, in order
 114          * to handle nesting.
 115          */
 116         ControlState = AcpiUtCreateControlState ();
 117         if (!ControlState)
 118         {
 119             Status = AE_NO_MEMORY;
 120             break;
 121         }
 122         /*
 123          * Save a pointer to the predicate for multiple executions
 124          * of a loop
 125          */
 126         ControlState->Control.AmlPredicateStart = WalkState->ParserState.Aml - 1;
 127         ControlState->Control.PackageEnd = WalkState->ParserState.PkgEnd;
 128         ControlState->Control.Opcode = Op->Common.AmlOpcode;
 129 
 130 


 133         AcpiUtPushGenericState (&WalkState->ControlState, ControlState);
 134         break;
 135 
 136     case AML_ELSE_OP:
 137 
 138         /* Predicate is in the state object */
 139         /* If predicate is true, the IF was executed, ignore ELSE part */
 140 
 141         if (WalkState->LastPredicate)
 142         {
 143             Status = AE_CTRL_TRUE;
 144         }
 145 
 146         break;
 147 
 148     case AML_RETURN_OP:
 149 
 150         break;
 151 
 152     default:

 153         break;
 154     }
 155 
 156     return (Status);
 157 }
 158 
 159 
 160 /*******************************************************************************
 161  *
 162  * FUNCTION:    AcpiDsExecEndControlOp
 163  *
 164  * PARAMETERS:  WalkList        - The list that owns the walk stack
 165  *              Op              - The control Op
 166  *
 167  * RETURN:      Status
 168  *
 169  * DESCRIPTION: Handles all control ops encountered during control method
 170  *              execution.
 171  *
 172  ******************************************************************************/


 187     {
 188     case AML_IF_OP:
 189 
 190         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op));
 191 
 192         /*
 193          * Save the result of the predicate in case there is an
 194          * ELSE to come
 195          */
 196         WalkState->LastPredicate =
 197             (BOOLEAN) WalkState->ControlState->Common.Value;
 198 
 199         /*
 200          * Pop the control state that was created at the start
 201          * of the IF and free it
 202          */
 203         ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
 204         AcpiUtDeleteGenericState (ControlState);
 205         break;
 206 
 207 
 208     case AML_ELSE_OP:
 209 
 210         break;
 211 
 212 
 213     case AML_WHILE_OP:
 214 
 215         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op));
 216 
 217         ControlState = WalkState->ControlState;
 218         if (ControlState->Common.Value)
 219         {
 220             /* Predicate was true, the body of the loop was just executed */
 221 
 222             /*
 223              * This loop counter mechanism allows the interpreter to escape
 224              * possibly infinite loops. This can occur in poorly written AML
 225              * when the hardware does not respond within a while loop and the
 226              * loop does not implement a timeout.
 227              */
 228             ControlState->Control.LoopCount++;
 229             if (ControlState->Control.LoopCount > ACPI_MAX_LOOP_ITERATIONS)
 230             {
 231                 Status = AE_AML_INFINITE_LOOP;
 232                 break;


 235             /*
 236              * Go back and evaluate the predicate and maybe execute the loop
 237              * another time
 238              */
 239             Status = AE_CTRL_PENDING;
 240             WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart;
 241             break;
 242         }
 243 
 244         /* Predicate was false, terminate this while loop */
 245 
 246         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 247             "[WHILE_OP] termination! Op=%p\n",Op));
 248 
 249         /* Pop this control state and free it */
 250 
 251         ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
 252         AcpiUtDeleteGenericState (ControlState);
 253         break;
 254 
 255 
 256     case AML_RETURN_OP:
 257 
 258         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 259             "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg));
 260 
 261         /*
 262          * One optional operand -- the return value
 263          * It can be either an immediate operand or a result that
 264          * has been bubbled up the tree
 265          */
 266         if (Op->Common.Value.Arg)
 267         {
 268             /* Since we have a real Return(), delete any implicit return */
 269 
 270             AcpiDsClearImplicitReturn (WalkState);
 271 
 272             /* Return statement has an immediate operand */
 273 
 274             Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg);
 275             if (ACPI_FAILURE (Status))


 331             if (WalkState->NumOperands)
 332             {
 333                 AcpiUtRemoveReference (WalkState->Operands [0]);
 334             }
 335 
 336             WalkState->Operands [0]     = NULL;
 337             WalkState->NumOperands      = 0;
 338             WalkState->ReturnDesc       = NULL;
 339         }
 340 
 341 
 342         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 343             "Completed RETURN_OP State=%p, RetVal=%p\n",
 344             WalkState, WalkState->ReturnDesc));
 345 
 346         /* End the control method execution right now */
 347 
 348         Status = AE_CTRL_TERMINATE;
 349         break;
 350 
 351 
 352     case AML_NOOP_OP:
 353 
 354         /* Just do nothing! */

 355         break;
 356 
 357 
 358     case AML_BREAK_POINT_OP:
 359 
 360         /*
 361          * Set the single-step flag. This will cause the debugger (if present)
 362          * to break to the console within the AML debugger at the start of the
 363          * next AML instruction.
 364          */
 365         ACPI_DEBUGGER_EXEC (
 366             AcpiGbl_CmSingleStep = TRUE);
 367         ACPI_DEBUGGER_EXEC (
 368             AcpiOsPrintf ("**break** Executed AML BreakPoint opcode\n"));
 369 
 370         /* Call to the OSL in case OS wants a piece of the action */
 371 
 372         Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT,
 373                     "Executed AML Breakpoint opcode");
 374         break;
 375 
 376 
 377     case AML_BREAK_OP:
 378     case AML_CONTINUE_OP: /* ACPI 2.0 */
 379 
 380 
 381         /* Pop and delete control states until we find a while */
 382 
 383         while (WalkState->ControlState &&
 384                 (WalkState->ControlState->Control.Opcode != AML_WHILE_OP))
 385         {
 386             ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
 387             AcpiUtDeleteGenericState (ControlState);
 388         }
 389 
 390         /* No while found? */
 391 
 392         if (!WalkState->ControlState)
 393         {
 394             return (AE_AML_NO_WHILE);
 395         }
 396 
 397         /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */
 398 
 399         WalkState->AmlLastWhile = WalkState->ControlState->Control.PackageEnd;
 400 
 401         /* Return status depending on opcode */
 402 
 403         if (Op->Common.AmlOpcode == AML_BREAK_OP)
 404         {
 405             Status = AE_CTRL_BREAK;
 406         }
 407         else
 408         {
 409             Status = AE_CTRL_CONTINUE;
 410         }
 411         break;
 412 
 413 
 414     default:
 415 
 416         ACPI_ERROR ((AE_INFO, "Unknown control opcode=0x%X Op=%p",
 417             Op->Common.AmlOpcode, Op));
 418 
 419         Status = AE_AML_BAD_OPCODE;
 420         break;
 421     }
 422 
 423     return (Status);
 424 }
   1 /******************************************************************************
   2  *
   3  * Module Name: dscontrol - Support for execution control opcodes -
   4  *                          if/else/while/return
   5  *
   6  *****************************************************************************/
   7 
   8 /*
   9  * Copyright (C) 2000 - 2013, 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.


  69  ******************************************************************************/
  70 
  71 ACPI_STATUS
  72 AcpiDsExecBeginControlOp (
  73     ACPI_WALK_STATE         *WalkState,
  74     ACPI_PARSE_OBJECT       *Op)
  75 {
  76     ACPI_STATUS             Status = AE_OK;
  77     ACPI_GENERIC_STATE      *ControlState;
  78 
  79 
  80     ACPI_FUNCTION_NAME (DsExecBeginControlOp);
  81 
  82 
  83     ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n",
  84         Op, Op->Common.AmlOpcode, WalkState));
  85 
  86     switch (Op->Common.AmlOpcode)
  87     {
  88     case AML_WHILE_OP:

  89         /*
  90          * If this is an additional iteration of a while loop, continue.
  91          * There is no need to allocate a new control state.
  92          */
  93         if (WalkState->ControlState)
  94         {
  95             if (WalkState->ControlState->Control.AmlPredicateStart ==
  96                 (WalkState->ParserState.Aml - 1))
  97             {
  98                 /* Reset the state to start-of-loop */
  99 
 100                 WalkState->ControlState->Common.State =
 101                     ACPI_CONTROL_CONDITIONAL_EXECUTING;
 102                 break;
 103             }
 104         }
 105 
 106         /*lint -fallthrough */
 107 
 108     case AML_IF_OP:

 109         /*
 110          * IF/WHILE: Create a new control state to manage these
 111          * constructs. We need to manage these as a stack, in order
 112          * to handle nesting.
 113          */
 114         ControlState = AcpiUtCreateControlState ();
 115         if (!ControlState)
 116         {
 117             Status = AE_NO_MEMORY;
 118             break;
 119         }
 120         /*
 121          * Save a pointer to the predicate for multiple executions
 122          * of a loop
 123          */
 124         ControlState->Control.AmlPredicateStart = WalkState->ParserState.Aml - 1;
 125         ControlState->Control.PackageEnd = WalkState->ParserState.PkgEnd;
 126         ControlState->Control.Opcode = Op->Common.AmlOpcode;
 127 
 128 


 131         AcpiUtPushGenericState (&WalkState->ControlState, ControlState);
 132         break;
 133 
 134     case AML_ELSE_OP:
 135 
 136         /* Predicate is in the state object */
 137         /* If predicate is true, the IF was executed, ignore ELSE part */
 138 
 139         if (WalkState->LastPredicate)
 140         {
 141             Status = AE_CTRL_TRUE;
 142         }
 143 
 144         break;
 145 
 146     case AML_RETURN_OP:
 147 
 148         break;
 149 
 150     default:
 151 
 152         break;
 153     }
 154 
 155     return (Status);
 156 }
 157 
 158 
 159 /*******************************************************************************
 160  *
 161  * FUNCTION:    AcpiDsExecEndControlOp
 162  *
 163  * PARAMETERS:  WalkList        - The list that owns the walk stack
 164  *              Op              - The control Op
 165  *
 166  * RETURN:      Status
 167  *
 168  * DESCRIPTION: Handles all control ops encountered during control method
 169  *              execution.
 170  *
 171  ******************************************************************************/


 186     {
 187     case AML_IF_OP:
 188 
 189         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", Op));
 190 
 191         /*
 192          * Save the result of the predicate in case there is an
 193          * ELSE to come
 194          */
 195         WalkState->LastPredicate =
 196             (BOOLEAN) WalkState->ControlState->Common.Value;
 197 
 198         /*
 199          * Pop the control state that was created at the start
 200          * of the IF and free it
 201          */
 202         ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
 203         AcpiUtDeleteGenericState (ControlState);
 204         break;
 205 

 206     case AML_ELSE_OP:
 207 
 208         break;
 209 

 210     case AML_WHILE_OP:
 211 
 212         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", Op));
 213 
 214         ControlState = WalkState->ControlState;
 215         if (ControlState->Common.Value)
 216         {
 217             /* Predicate was true, the body of the loop was just executed */
 218 
 219             /*
 220              * This loop counter mechanism allows the interpreter to escape
 221              * possibly infinite loops. This can occur in poorly written AML
 222              * when the hardware does not respond within a while loop and the
 223              * loop does not implement a timeout.
 224              */
 225             ControlState->Control.LoopCount++;
 226             if (ControlState->Control.LoopCount > ACPI_MAX_LOOP_ITERATIONS)
 227             {
 228                 Status = AE_AML_INFINITE_LOOP;
 229                 break;


 232             /*
 233              * Go back and evaluate the predicate and maybe execute the loop
 234              * another time
 235              */
 236             Status = AE_CTRL_PENDING;
 237             WalkState->AmlLastWhile = ControlState->Control.AmlPredicateStart;
 238             break;
 239         }
 240 
 241         /* Predicate was false, terminate this while loop */
 242 
 243         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 244             "[WHILE_OP] termination! Op=%p\n",Op));
 245 
 246         /* Pop this control state and free it */
 247 
 248         ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
 249         AcpiUtDeleteGenericState (ControlState);
 250         break;
 251 

 252     case AML_RETURN_OP:
 253 
 254         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 255             "[RETURN_OP] Op=%p Arg=%p\n",Op, Op->Common.Value.Arg));
 256 
 257         /*
 258          * One optional operand -- the return value
 259          * It can be either an immediate operand or a result that
 260          * has been bubbled up the tree
 261          */
 262         if (Op->Common.Value.Arg)
 263         {
 264             /* Since we have a real Return(), delete any implicit return */
 265 
 266             AcpiDsClearImplicitReturn (WalkState);
 267 
 268             /* Return statement has an immediate operand */
 269 
 270             Status = AcpiDsCreateOperands (WalkState, Op->Common.Value.Arg);
 271             if (ACPI_FAILURE (Status))


 327             if (WalkState->NumOperands)
 328             {
 329                 AcpiUtRemoveReference (WalkState->Operands [0]);
 330             }
 331 
 332             WalkState->Operands [0]     = NULL;
 333             WalkState->NumOperands      = 0;
 334             WalkState->ReturnDesc       = NULL;
 335         }
 336 
 337 
 338         ACPI_DEBUG_PRINT ((ACPI_DB_DISPATCH,
 339             "Completed RETURN_OP State=%p, RetVal=%p\n",
 340             WalkState, WalkState->ReturnDesc));
 341 
 342         /* End the control method execution right now */
 343 
 344         Status = AE_CTRL_TERMINATE;
 345         break;
 346 

 347     case AML_NOOP_OP:
 348 
 349         /* Just do nothing! */
 350 
 351         break;
 352 

 353     case AML_BREAK_POINT_OP:
 354 
 355         /*
 356          * Set the single-step flag. This will cause the debugger (if present)
 357          * to break to the console within the AML debugger at the start of the
 358          * next AML instruction.
 359          */
 360         ACPI_DEBUGGER_EXEC (
 361             AcpiGbl_CmSingleStep = TRUE);
 362         ACPI_DEBUGGER_EXEC (
 363             AcpiOsPrintf ("**break** Executed AML BreakPoint opcode\n"));
 364 
 365         /* Call to the OSL in case OS wants a piece of the action */
 366 
 367         Status = AcpiOsSignal (ACPI_SIGNAL_BREAKPOINT,
 368                     "Executed AML Breakpoint opcode");
 369         break;
 370 

 371     case AML_BREAK_OP:
 372     case AML_CONTINUE_OP: /* ACPI 2.0 */
 373 

 374         /* Pop and delete control states until we find a while */
 375 
 376         while (WalkState->ControlState &&
 377                 (WalkState->ControlState->Control.Opcode != AML_WHILE_OP))
 378         {
 379             ControlState = AcpiUtPopGenericState (&WalkState->ControlState);
 380             AcpiUtDeleteGenericState (ControlState);
 381         }
 382 
 383         /* No while found? */
 384 
 385         if (!WalkState->ControlState)
 386         {
 387             return (AE_AML_NO_WHILE);
 388         }
 389 
 390         /* Was: WalkState->AmlLastWhile = WalkState->ControlState->Control.AmlPredicateStart; */
 391 
 392         WalkState->AmlLastWhile = WalkState->ControlState->Control.PackageEnd;
 393 
 394         /* Return status depending on opcode */
 395 
 396         if (Op->Common.AmlOpcode == AML_BREAK_OP)
 397         {
 398             Status = AE_CTRL_BREAK;
 399         }
 400         else
 401         {
 402             Status = AE_CTRL_CONTINUE;
 403         }
 404         break;
 405 

 406     default:
 407 
 408         ACPI_ERROR ((AE_INFO, "Unknown control opcode=0x%X Op=%p",
 409             Op->Common.AmlOpcode, Op));
 410 
 411         Status = AE_AML_BAD_OPCODE;
 412         break;
 413     }
 414 
 415     return (Status);
 416 }