1 /******************************************************************************
   2  *
   3  * Module Name: psxface - Parser external interfaces
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, Intel Corp.
   9  * All rights reserved.
  10  *
  11  * Redistribution and use in source and binary forms, with or without
  12  * modification, are permitted provided that the following conditions
  13  * are met:
  14  * 1. Redistributions of source code must retain the above copyright
  15  *    notice, this list of conditions, and the following disclaimer,
  16  *    without modification.
  17  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18  *    substantially similar to the "NO WARRANTY" disclaimer below
  19  *    ("Disclaimer") and any redistribution must be conditioned upon
  20  *    including a substantially similar Disclaimer requirement for further
  21  *    binary redistribution.
  22  * 3. Neither the names of the above-listed copyright holders nor the names
  23  *    of any contributors may be used to endorse or promote products derived
  24  *    from this software without specific prior written permission.
  25  *
  26  * Alternatively, this software may be distributed under the terms of the
  27  * GNU General Public License ("GPL") version 2 as published by the Free
  28  * Software Foundation.
  29  *
  30  * NO WARRANTY
  31  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41  * POSSIBILITY OF SUCH DAMAGES.
  42  */
  43 
  44 #define __PSXFACE_C__
  45 
  46 #include "acpi.h"
  47 #include "accommon.h"
  48 #include "acparser.h"
  49 #include "acdispat.h"
  50 #include "acinterp.h"
  51 #include "actables.h"
  52 
  53 
  54 #define _COMPONENT          ACPI_PARSER
  55         ACPI_MODULE_NAME    ("psxface")
  56 
  57 /* Local Prototypes */
  58 
  59 static void
  60 AcpiPsStartTrace (
  61     ACPI_EVALUATE_INFO      *Info);
  62 
  63 static void
  64 AcpiPsStopTrace (
  65     ACPI_EVALUATE_INFO      *Info);
  66 
  67 static void
  68 AcpiPsUpdateParameterList (
  69     ACPI_EVALUATE_INFO      *Info,
  70     UINT16                  Action);
  71 
  72 
  73 /*******************************************************************************
  74  *
  75  * FUNCTION:    AcpiDebugTrace
  76  *
  77  * PARAMETERS:  MethodName      - Valid ACPI name string
  78  *              DebugLevel      - Optional level mask. 0 to use default
  79  *              DebugLayer      - Optional layer mask. 0 to use default
  80  *              Flags           - bit 1: one shot(1) or persistent(0)
  81  *
  82  * RETURN:      Status
  83  *
  84  * DESCRIPTION: External interface to enable debug tracing during control
  85  *              method execution
  86  *
  87  ******************************************************************************/
  88 
  89 ACPI_STATUS
  90 AcpiDebugTrace (
  91     char                    *Name,
  92     UINT32                  DebugLevel,
  93     UINT32                  DebugLayer,
  94     UINT32                  Flags)
  95 {
  96     ACPI_STATUS             Status;
  97 
  98 
  99     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 100     if (ACPI_FAILURE (Status))
 101     {
 102         return (Status);
 103     }
 104 
 105     /* TBDs: Validate name, allow full path or just nameseg */
 106 
 107     AcpiGbl_TraceMethodName = *ACPI_CAST_PTR (UINT32, Name);
 108     AcpiGbl_TraceFlags = Flags;
 109 
 110     if (DebugLevel)
 111     {
 112         AcpiGbl_TraceDbgLevel = DebugLevel;
 113     }
 114     if (DebugLayer)
 115     {
 116         AcpiGbl_TraceDbgLayer = DebugLayer;
 117     }
 118 
 119     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 120     return (AE_OK);
 121 }
 122 
 123 
 124 /*******************************************************************************
 125  *
 126  * FUNCTION:    AcpiPsStartTrace
 127  *
 128  * PARAMETERS:  Info        - Method info struct
 129  *
 130  * RETURN:      None
 131  *
 132  * DESCRIPTION: Start control method execution trace
 133  *
 134  ******************************************************************************/
 135 
 136 static void
 137 AcpiPsStartTrace (
 138     ACPI_EVALUATE_INFO      *Info)
 139 {
 140     ACPI_STATUS             Status;
 141 
 142 
 143     ACPI_FUNCTION_ENTRY ();
 144 
 145 
 146     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 147     if (ACPI_FAILURE (Status))
 148     {
 149         return;
 150     }
 151 
 152     if ((!AcpiGbl_TraceMethodName) ||
 153         (AcpiGbl_TraceMethodName != Info->Node->Name.Integer))
 154     {
 155         goto Exit;
 156     }
 157 
 158     AcpiGbl_OriginalDbgLevel = AcpiDbgLevel;
 159     AcpiGbl_OriginalDbgLayer = AcpiDbgLayer;
 160 
 161     AcpiDbgLevel = 0x00FFFFFF;
 162     AcpiDbgLayer = ACPI_UINT32_MAX;
 163 
 164     if (AcpiGbl_TraceDbgLevel)
 165     {
 166         AcpiDbgLevel = AcpiGbl_TraceDbgLevel;
 167     }
 168     if (AcpiGbl_TraceDbgLayer)
 169     {
 170         AcpiDbgLayer = AcpiGbl_TraceDbgLayer;
 171     }
 172 
 173 
 174 Exit:
 175     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 176 }
 177 
 178 
 179 /*******************************************************************************
 180  *
 181  * FUNCTION:    AcpiPsStopTrace
 182  *
 183  * PARAMETERS:  Info        - Method info struct
 184  *
 185  * RETURN:      None
 186  *
 187  * DESCRIPTION: Stop control method execution trace
 188  *
 189  ******************************************************************************/
 190 
 191 static void
 192 AcpiPsStopTrace (
 193     ACPI_EVALUATE_INFO      *Info)
 194 {
 195     ACPI_STATUS             Status;
 196 
 197 
 198     ACPI_FUNCTION_ENTRY ();
 199 
 200 
 201     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
 202     if (ACPI_FAILURE (Status))
 203     {
 204         return;
 205     }
 206 
 207     if ((!AcpiGbl_TraceMethodName) ||
 208         (AcpiGbl_TraceMethodName != Info->Node->Name.Integer))
 209     {
 210         goto Exit;
 211     }
 212 
 213     /* Disable further tracing if type is one-shot */
 214 
 215     if (AcpiGbl_TraceFlags & 1)
 216     {
 217         AcpiGbl_TraceMethodName = 0;
 218         AcpiGbl_TraceDbgLevel = 0;
 219         AcpiGbl_TraceDbgLayer = 0;
 220     }
 221 
 222     AcpiDbgLevel = AcpiGbl_OriginalDbgLevel;
 223     AcpiDbgLayer = AcpiGbl_OriginalDbgLayer;
 224 
 225 Exit:
 226     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
 227 }
 228 
 229 
 230 /*******************************************************************************
 231  *
 232  * FUNCTION:    AcpiPsExecuteMethod
 233  *
 234  * PARAMETERS:  Info            - Method info block, contains:
 235  *                  Node            - Method Node to execute
 236  *                  ObjDesc         - Method object
 237  *                  Parameters      - List of parameters to pass to the method,
 238  *                                    terminated by NULL. Params itself may be
 239  *                                    NULL if no parameters are being passed.
 240  *                  ReturnObject    - Where to put method's return value (if
 241  *                                    any). If NULL, no value is returned.
 242  *                  ParameterType   - Type of Parameter list
 243  *                  ReturnObject    - Where to put method's return value (if
 244  *                                    any). If NULL, no value is returned.
 245  *                  PassNumber      - Parse or execute pass
 246  *
 247  * RETURN:      Status
 248  *
 249  * DESCRIPTION: Execute a control method
 250  *
 251  ******************************************************************************/
 252 
 253 ACPI_STATUS
 254 AcpiPsExecuteMethod (
 255     ACPI_EVALUATE_INFO      *Info)
 256 {
 257     ACPI_STATUS             Status;
 258     ACPI_PARSE_OBJECT       *Op;
 259     ACPI_WALK_STATE         *WalkState;
 260 
 261 
 262     ACPI_FUNCTION_TRACE (PsExecuteMethod);
 263 
 264 
 265     /* Quick validation of DSDT header */
 266 
 267     AcpiTbCheckDsdtHeader ();
 268 
 269     /* Validate the Info and method Node */
 270 
 271     if (!Info || !Info->Node)
 272     {
 273         return_ACPI_STATUS (AE_NULL_ENTRY);
 274     }
 275 
 276     /* Init for new method, wait on concurrency semaphore */
 277 
 278     Status = AcpiDsBeginMethodExecution (Info->Node, Info->ObjDesc, NULL);
 279     if (ACPI_FAILURE (Status))
 280     {
 281         return_ACPI_STATUS (Status);
 282     }
 283 
 284     /*
 285      * The caller "owns" the parameters, so give each one an extra reference
 286      */
 287     AcpiPsUpdateParameterList (Info, REF_INCREMENT);
 288 
 289     /* Begin tracing if requested */
 290 
 291     AcpiPsStartTrace (Info);
 292 
 293     /*
 294      * Execute the method. Performs parse simultaneously
 295      */
 296     ACPI_DEBUG_PRINT ((ACPI_DB_PARSE,
 297         "**** Begin Method Parse/Execute [%4.4s] **** Node=%p Obj=%p\n",
 298         Info->Node->Name.Ascii, Info->Node, Info->ObjDesc));
 299 
 300     /* Create and init a Root Node */
 301 
 302     Op = AcpiPsCreateScopeOp ();
 303     if (!Op)
 304     {
 305         Status = AE_NO_MEMORY;
 306         goto Cleanup;
 307     }
 308 
 309     /* Create and initialize a new walk state */
 310 
 311     Info->PassNumber = ACPI_IMODE_EXECUTE;
 312     WalkState = AcpiDsCreateWalkState (
 313                     Info->ObjDesc->Method.OwnerId, NULL, NULL, NULL);
 314     if (!WalkState)
 315     {
 316         Status = AE_NO_MEMORY;
 317         goto Cleanup;
 318     }
 319 
 320     Status = AcpiDsInitAmlWalk (WalkState, Op, Info->Node,
 321                 Info->ObjDesc->Method.AmlStart,
 322                 Info->ObjDesc->Method.AmlLength, Info, Info->PassNumber);
 323     if (ACPI_FAILURE (Status))
 324     {
 325         AcpiDsDeleteWalkState (WalkState);
 326         goto Cleanup;
 327     }
 328 
 329     if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_MODULE_LEVEL)
 330     {
 331         WalkState->ParseFlags |= ACPI_PARSE_MODULE_LEVEL;
 332     }
 333 
 334     /* Invoke an internal method if necessary */
 335 
 336     if (Info->ObjDesc->Method.InfoFlags & ACPI_METHOD_INTERNAL_ONLY)
 337     {
 338         Status = Info->ObjDesc->Method.Dispatch.Implementation (WalkState);
 339         Info->ReturnObject = WalkState->ReturnDesc;
 340 
 341         /* Cleanup states */
 342 
 343         AcpiDsScopeStackClear (WalkState);
 344         AcpiPsCleanupScope (&WalkState->ParserState);
 345         AcpiDsTerminateControlMethod (WalkState->MethodDesc, WalkState);
 346         AcpiDsDeleteWalkState (WalkState);
 347         goto Cleanup;
 348     }
 349 
 350     /*
 351      * Start method evaluation with an implicit return of zero.
 352      * This is done for Windows compatibility.
 353      */
 354     if (AcpiGbl_EnableInterpreterSlack)
 355     {
 356         WalkState->ImplicitReturnObj =
 357             AcpiUtCreateIntegerObject ((UINT64) 0);
 358         if (!WalkState->ImplicitReturnObj)
 359         {
 360             Status = AE_NO_MEMORY;
 361             AcpiDsDeleteWalkState (WalkState);
 362             goto Cleanup;
 363         }
 364     }
 365 
 366     /* Parse the AML */
 367 
 368     Status = AcpiPsParseAml (WalkState);
 369 
 370     /* WalkState was deleted by ParseAml */
 371 
 372 Cleanup:
 373     AcpiPsDeleteParseTree (Op);
 374 
 375     /* End optional tracing */
 376 
 377     AcpiPsStopTrace (Info);
 378 
 379     /* Take away the extra reference that we gave the parameters above */
 380 
 381     AcpiPsUpdateParameterList (Info, REF_DECREMENT);
 382 
 383     /* Exit now if error above */
 384 
 385     if (ACPI_FAILURE (Status))
 386     {
 387         return_ACPI_STATUS (Status);
 388     }
 389 
 390     /*
 391      * If the method has returned an object, signal this to the caller with
 392      * a control exception code
 393      */
 394     if (Info->ReturnObject)
 395     {
 396         ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Method returned ObjDesc=%p\n",
 397             Info->ReturnObject));
 398         ACPI_DUMP_STACK_ENTRY (Info->ReturnObject);
 399 
 400         Status = AE_CTRL_RETURN_VALUE;
 401     }
 402 
 403     return_ACPI_STATUS (Status);
 404 }
 405 
 406 
 407 /*******************************************************************************
 408  *
 409  * FUNCTION:    AcpiPsUpdateParameterList
 410  *
 411  * PARAMETERS:  Info            - See ACPI_EVALUATE_INFO
 412  *                                (Used: ParameterType and Parameters)
 413  *              Action          - Add or Remove reference
 414  *
 415  * RETURN:      Status
 416  *
 417  * DESCRIPTION: Update reference count on all method parameter objects
 418  *
 419  ******************************************************************************/
 420 
 421 static void
 422 AcpiPsUpdateParameterList (
 423     ACPI_EVALUATE_INFO      *Info,
 424     UINT16                  Action)
 425 {
 426     UINT32                  i;
 427 
 428 
 429     if (Info->Parameters)
 430     {
 431         /* Update reference count for each parameter */
 432 
 433         for (i = 0; Info->Parameters[i]; i++)
 434         {
 435             /* Ignore errors, just do them all */
 436 
 437             (void) AcpiUtUpdateObjectReference (Info->Parameters[i], Action);
 438         }
 439     }
 440 }