Home | History | Annotate | Line # | Download | only in debugger
      1 /*******************************************************************************
      2  *
      3  * Module Name: dbexec - debugger control method execution
      4  *
      5  ******************************************************************************/
      6 
      7 /******************************************************************************
      8  *
      9  * 1. Copyright Notice
     10  *
     11  * Some or all of this work - Copyright (c) 1999 - 2025, Intel Corp.
     12  * All rights reserved.
     13  *
     14  * 2. License
     15  *
     16  * 2.1. This is your license from Intel Corp. under its intellectual property
     17  * rights. You may have additional license terms from the party that provided
     18  * you this software, covering your right to use that party's intellectual
     19  * property rights.
     20  *
     21  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
     22  * copy of the source code appearing in this file ("Covered Code") an
     23  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
     24  * base code distributed originally by Intel ("Original Intel Code") to copy,
     25  * make derivatives, distribute, use and display any portion of the Covered
     26  * Code in any form, with the right to sublicense such rights; and
     27  *
     28  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
     29  * license (with the right to sublicense), under only those claims of Intel
     30  * patents that are infringed by the Original Intel Code, to make, use, sell,
     31  * offer to sell, and import the Covered Code and derivative works thereof
     32  * solely to the minimum extent necessary to exercise the above copyright
     33  * license, and in no event shall the patent license extend to any additions
     34  * to or modifications of the Original Intel Code. No other license or right
     35  * is granted directly or by implication, estoppel or otherwise;
     36  *
     37  * The above copyright and patent license is granted only if the following
     38  * conditions are met:
     39  *
     40  * 3. Conditions
     41  *
     42  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
     43  * Redistribution of source code of any substantial portion of the Covered
     44  * Code or modification with rights to further distribute source must include
     45  * the above Copyright Notice, the above License, this list of Conditions,
     46  * and the following Disclaimer and Export Compliance provision. In addition,
     47  * Licensee must cause all Covered Code to which Licensee contributes to
     48  * contain a file documenting the changes Licensee made to create that Covered
     49  * Code and the date of any change. Licensee must include in that file the
     50  * documentation of any changes made by any predecessor Licensee. Licensee
     51  * must include a prominent statement that the modification is derived,
     52  * directly or indirectly, from Original Intel Code.
     53  *
     54  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
     55  * Redistribution of source code of any substantial portion of the Covered
     56  * Code or modification without rights to further distribute source must
     57  * include the following Disclaimer and Export Compliance provision in the
     58  * documentation and/or other materials provided with distribution. In
     59  * addition, Licensee may not authorize further sublicense of source of any
     60  * portion of the Covered Code, and must include terms to the effect that the
     61  * license from Licensee to its licensee is limited to the intellectual
     62  * property embodied in the software Licensee provides to its licensee, and
     63  * not to intellectual property embodied in modifications its licensee may
     64  * make.
     65  *
     66  * 3.3. Redistribution of Executable. Redistribution in executable form of any
     67  * substantial portion of the Covered Code or modification must reproduce the
     68  * above Copyright Notice, and the following Disclaimer and Export Compliance
     69  * provision in the documentation and/or other materials provided with the
     70  * distribution.
     71  *
     72  * 3.4. Intel retains all right, title, and interest in and to the Original
     73  * Intel Code.
     74  *
     75  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
     76  * Intel shall be used in advertising or otherwise to promote the sale, use or
     77  * other dealings in products derived from or relating to the Covered Code
     78  * without prior written authorization from Intel.
     79  *
     80  * 4. Disclaimer and Export Compliance
     81  *
     82  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
     83  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
     84  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
     85  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
     86  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
     87  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
     88  * PARTICULAR PURPOSE.
     89  *
     90  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
     91  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
     92  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
     93  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
     94  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
     95  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
     96  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
     97  * LIMITED REMEDY.
     98  *
     99  * 4.3. Licensee shall not export, either directly or indirectly, any of this
    100  * software or system incorporating such software without first obtaining any
    101  * required license or other approval from the U. S. Department of Commerce or
    102  * any other agency or department of the United States Government. In the
    103  * event Licensee exports any such software from the United States or
    104  * re-exports any such software from a foreign destination, Licensee shall
    105  * ensure that the distribution and export/re-export of the software is in
    106  * compliance with all laws, regulations, orders, or other restrictions of the
    107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
    108  * any of its subsidiaries will export/re-export any technical data, process,
    109  * software, or service, directly or indirectly, to any country for which the
    110  * United States government or any agency thereof requires an export license,
    111  * other governmental approval, or letter of assurance, without first obtaining
    112  * such license, approval or letter.
    113  *
    114  *****************************************************************************
    115  *
    116  * Alternatively, you may choose to be licensed under the terms of the
    117  * following license:
    118  *
    119  * Redistribution and use in source and binary forms, with or without
    120  * modification, are permitted provided that the following conditions
    121  * are met:
    122  * 1. Redistributions of source code must retain the above copyright
    123  *    notice, this list of conditions, and the following disclaimer,
    124  *    without modification.
    125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
    126  *    substantially similar to the "NO WARRANTY" disclaimer below
    127  *    ("Disclaimer") and any redistribution must be conditioned upon
    128  *    including a substantially similar Disclaimer requirement for further
    129  *    binary redistribution.
    130  * 3. Neither the names of the above-listed copyright holders nor the names
    131  *    of any contributors may be used to endorse or promote products derived
    132  *    from this software without specific prior written permission.
    133  *
    134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
    135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
    136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
    137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
    138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
    139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
    140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
    141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
    142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
    143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
    144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
    145  *
    146  * Alternatively, you may choose to be licensed under the terms of the
    147  * GNU General Public License ("GPL") version 2 as published by the Free
    148  * Software Foundation.
    149  *
    150  *****************************************************************************/
    151 
    152 #include "acpi.h"
    153 #include "accommon.h"
    154 #include "acdebug.h"
    155 #include "acnamesp.h"
    156 
    157 
    158 #define _COMPONENT          ACPI_CA_DEBUGGER
    159         ACPI_MODULE_NAME    ("dbexec")
    160 
    161 
    162 static ACPI_DB_METHOD_INFO          AcpiGbl_DbMethodInfo;
    163 
    164 /* Local prototypes */
    165 
    166 static ACPI_STATUS
    167 AcpiDbExecuteMethod (
    168     ACPI_DB_METHOD_INFO     *Info,
    169     ACPI_BUFFER             *ReturnObj);
    170 
    171 static ACPI_STATUS
    172 AcpiDbExecuteSetup (
    173     ACPI_DB_METHOD_INFO     *Info);
    174 
    175 static UINT32
    176 AcpiDbGetOutstandingAllocations (
    177     void);
    178 
    179 static void ACPI_SYSTEM_XFACE
    180 AcpiDbMethodThread (
    181     void                    *Context);
    182 
    183 static ACPI_STATUS
    184 AcpiDbExecutionWalk (
    185     ACPI_HANDLE             ObjHandle,
    186     UINT32                  NestingLevel,
    187     void                    *Context,
    188     void                    **ReturnValue);
    189 
    190 static void ACPI_SYSTEM_XFACE
    191 AcpiDbSingleExecutionThread (
    192     void                    *Context);
    193 
    194 
    195 /*******************************************************************************
    196  *
    197  * FUNCTION:    AcpiDbDeleteObjects
    198  *
    199  * PARAMETERS:  Count               - Count of objects in the list
    200  *              Objects             - Array of ACPI_OBJECTs to be deleted
    201  *
    202  * RETURN:      None
    203  *
    204  * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
    205  *              packages via recursion.
    206  *
    207  ******************************************************************************/
    208 
    209 void
    210 AcpiDbDeleteObjects (
    211     UINT32                  Count,
    212     ACPI_OBJECT             *Objects)
    213 {
    214     UINT32                  i;
    215 
    216 
    217     for (i = 0; i < Count; i++)
    218     {
    219         switch (Objects[i].Type)
    220         {
    221         case ACPI_TYPE_BUFFER:
    222 
    223             ACPI_FREE (Objects[i].Buffer.Pointer);
    224             break;
    225 
    226         case ACPI_TYPE_PACKAGE:
    227 
    228             /* Recursive call to delete package elements */
    229 
    230             AcpiDbDeleteObjects (Objects[i].Package.Count,
    231                 Objects[i].Package.Elements);
    232 
    233             /* Free the elements array */
    234 
    235             ACPI_FREE (Objects[i].Package.Elements);
    236             break;
    237 
    238         default:
    239 
    240             break;
    241         }
    242     }
    243 }
    244 
    245 
    246 /*******************************************************************************
    247  *
    248  * FUNCTION:    AcpiDbExecuteMethod
    249  *
    250  * PARAMETERS:  Info            - Valid info segment
    251  *              ReturnObj       - Where to put return object
    252  *
    253  * RETURN:      Status
    254  *
    255  * DESCRIPTION: Execute a control method. Used to evaluate objects via the
    256  *              "EXECUTE" or "EVALUATE" commands.
    257  *
    258  ******************************************************************************/
    259 
    260 static ACPI_STATUS
    261 AcpiDbExecuteMethod (
    262     ACPI_DB_METHOD_INFO     *Info,
    263     ACPI_BUFFER             *ReturnObj)
    264 {
    265     ACPI_STATUS             Status;
    266     ACPI_OBJECT_LIST        ParamObjects;
    267     ACPI_OBJECT             Params[ACPI_DEBUGGER_MAX_ARGS + 1];
    268     UINT32                  i;
    269 
    270 
    271     ACPI_FUNCTION_TRACE (DbExecuteMethod);
    272 
    273 
    274     if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel)
    275     {
    276         AcpiOsPrintf ("Warning: debug output is not enabled!\n");
    277     }
    278 
    279     ParamObjects.Count = 0;
    280     ParamObjects.Pointer = NULL;
    281 
    282     /* Pass through any command-line arguments */
    283 
    284     if (Info->Args && Info->Args[0])
    285     {
    286         /* Get arguments passed on the command line */
    287 
    288         for (i = 0; (Info->Args[i] && *(Info->Args[i])); i++)
    289         {
    290             /* Convert input string (token) to an actual ACPI_OBJECT */
    291 
    292             Status = AcpiDbConvertToObject (Info->Types[i],
    293                 Info->Args[i], &Params[i]);
    294             if (ACPI_FAILURE (Status))
    295             {
    296                 ACPI_EXCEPTION ((AE_INFO, Status,
    297                     "While parsing method arguments"));
    298                 goto Cleanup;
    299             }
    300         }
    301 
    302         ParamObjects.Count = i;
    303         ParamObjects.Pointer = Params;
    304     }
    305 
    306     /* Prepare for a return object of arbitrary size */
    307 
    308     ReturnObj->Pointer = AcpiGbl_DbBuffer;
    309     ReturnObj->Length  = ACPI_DEBUG_BUFFER_SIZE;
    310 
    311     /* Do the actual method execution */
    312 
    313     AcpiGbl_MethodExecuting = TRUE;
    314     Status = AcpiEvaluateObject (NULL, Info->Pathname,
    315         &ParamObjects, ReturnObj);
    316 
    317     AcpiGbl_CmSingleStep = FALSE;
    318     AcpiGbl_MethodExecuting = FALSE;
    319 
    320     if (ACPI_FAILURE (Status))
    321     {
    322         if ((Status == AE_ABORT_METHOD) || AcpiGbl_AbortMethod)
    323         {
    324             /* Clear the abort and fall back to the debugger prompt */
    325 
    326             ACPI_EXCEPTION ((AE_INFO, Status,
    327                 "Aborting top-level method"));
    328 
    329             AcpiGbl_AbortMethod = FALSE;
    330             Status = AE_OK;
    331             goto Cleanup;
    332         }
    333 
    334         ACPI_EXCEPTION ((AE_INFO, Status,
    335             "while executing %s from AML Debugger", Info->Pathname));
    336 
    337         if (Status == AE_BUFFER_OVERFLOW)
    338         {
    339             ACPI_ERROR ((AE_INFO,
    340                 "Possible buffer overflow within AML Debugger "
    341                 "buffer (size 0x%X needed 0x%X)",
    342                 ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length));
    343         }
    344     }
    345 
    346 Cleanup:
    347     AcpiDbDeleteObjects (ParamObjects.Count, Params);
    348     return_ACPI_STATUS (Status);
    349 }
    350 
    351 
    352 /*******************************************************************************
    353  *
    354  * FUNCTION:    AcpiDbExecuteSetup
    355  *
    356  * PARAMETERS:  Info            - Valid method info
    357  *
    358  * RETURN:      None
    359  *
    360  * DESCRIPTION: Setup info segment prior to method execution
    361  *
    362  ******************************************************************************/
    363 
    364 static ACPI_STATUS
    365 AcpiDbExecuteSetup (
    366     ACPI_DB_METHOD_INFO     *Info)
    367 {
    368     ACPI_STATUS             Status;
    369 
    370 
    371     ACPI_FUNCTION_NAME (DbExecuteSetup);
    372 
    373 
    374     /* Concatenate the current scope to the supplied name */
    375 
    376     Info->Pathname[0] = 0;
    377     if ((Info->Name[0] != '\\') &&
    378         (Info->Name[0] != '/'))
    379     {
    380         if (AcpiUtSafeStrcat (Info->Pathname, sizeof (Info->Pathname),
    381             AcpiGbl_DbScopeBuf))
    382         {
    383             Status = AE_BUFFER_OVERFLOW;
    384             goto ErrorExit;
    385         }
    386     }
    387 
    388     if (AcpiUtSafeStrcat (Info->Pathname, sizeof (Info->Pathname),
    389         Info->Name))
    390     {
    391         Status = AE_BUFFER_OVERFLOW;
    392         goto ErrorExit;
    393     }
    394 
    395     AcpiDbPrepNamestring (Info->Pathname);
    396 
    397     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
    398     AcpiOsPrintf ("Evaluating %s\n", Info->Pathname);
    399 
    400     if (Info->Flags & EX_SINGLE_STEP)
    401     {
    402         AcpiGbl_CmSingleStep = TRUE;
    403         AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
    404     }
    405 
    406     else
    407     {
    408         /* No single step, allow redirection to a file */
    409 
    410         AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
    411     }
    412 
    413     return (AE_OK);
    414 
    415 ErrorExit:
    416 
    417     ACPI_EXCEPTION ((AE_INFO, Status, "During setup for method execution"));
    418     return (Status);
    419 }
    420 
    421 
    422 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
    423 UINT32
    424 AcpiDbGetCacheInfo (
    425     ACPI_MEMORY_LIST        *Cache)
    426 {
    427 
    428     return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth);
    429 }
    430 #endif
    431 
    432 /*******************************************************************************
    433  *
    434  * FUNCTION:    AcpiDbGetOutstandingAllocations
    435  *
    436  * PARAMETERS:  None
    437  *
    438  * RETURN:      Current global allocation count minus cache entries
    439  *
    440  * DESCRIPTION: Determine the current number of "outstanding" allocations --
    441  *              those allocations that have not been freed and also are not
    442  *              in one of the various object caches.
    443  *
    444  ******************************************************************************/
    445 
    446 #ifdef ACPI_DEBUG_OUTPUT
    447 static UINT32
    448 AcpiDbGetOutstandingAllocations (
    449     void)
    450 {
    451     UINT32                  Outstanding = 0;
    452 
    453 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
    454 
    455     Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache);
    456     Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache);
    457     Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache);
    458     Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache);
    459 #endif
    460 
    461     return (Outstanding);
    462 }
    463 #endif
    464 
    465 
    466 /*******************************************************************************
    467  *
    468  * FUNCTION:    AcpiDbExecutionWalk
    469  *
    470  * PARAMETERS:  WALK_CALLBACK
    471  *
    472  * RETURN:      Status
    473  *
    474  * DESCRIPTION: Execute a control method. Name is relative to the current
    475  *              scope.
    476  *
    477  ******************************************************************************/
    478 
    479 static ACPI_STATUS
    480 AcpiDbExecutionWalk (
    481     ACPI_HANDLE             ObjHandle,
    482     UINT32                  NestingLevel,
    483     void                    *Context,
    484     void                    **ReturnValue)
    485 {
    486     ACPI_OPERAND_OBJECT     *ObjDesc;
    487     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    488     ACPI_BUFFER             ReturnObj;
    489     ACPI_STATUS             Status;
    490 
    491 
    492     ObjDesc = AcpiNsGetAttachedObject (Node);
    493     if (ObjDesc->Method.ParamCount)
    494     {
    495         return (AE_OK);
    496     }
    497 
    498     ReturnObj.Pointer = NULL;
    499     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
    500 
    501     AcpiNsPrintNodePathname (Node, "Evaluating");
    502 
    503     /* Do the actual method execution */
    504 
    505     AcpiOsPrintf ("\n");
    506     AcpiGbl_MethodExecuting = TRUE;
    507 
    508     Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj);
    509 
    510     AcpiGbl_MethodExecuting = FALSE;
    511 
    512     AcpiOsPrintf ("Evaluation of [%4.4s] returned %s\n",
    513         AcpiUtGetNodeName (Node),
    514         AcpiFormatException (Status));
    515 
    516     return (AE_OK);
    517 }
    518 
    519 
    520 /*******************************************************************************
    521  *
    522  * FUNCTION:    AcpiDbExecute
    523  *
    524  * PARAMETERS:  Name                - Name of method to execute
    525  *              Args                - Parameters to the method
    526  *              Types               -
    527  *              Flags               - single step/no single step
    528  *
    529  * RETURN:      None
    530  *
    531  * DESCRIPTION: Execute a control method. Name is relative to the current
    532  *              scope. Function used for the "EXECUTE", "EVALUATE", and
    533  *              "ALL" commands
    534  *
    535  ******************************************************************************/
    536 
    537 void
    538 AcpiDbExecute (
    539     char                    *Name,
    540     char                    **Args,
    541     ACPI_OBJECT_TYPE        *Types,
    542     UINT32                  Flags)
    543 {
    544     ACPI_STATUS             Status;
    545     ACPI_BUFFER             ReturnObj;
    546     char                    *NameString;
    547 
    548 #ifdef ACPI_DEBUG_OUTPUT
    549     UINT32                  PreviousAllocations;
    550     UINT32                  Allocations;
    551 #endif
    552 
    553 
    554     /*
    555      * Allow one execution to be performed by debugger or single step
    556      * execution will be dead locked by the interpreter mutexes.
    557      */
    558     if (AcpiGbl_MethodExecuting)
    559     {
    560         AcpiOsPrintf ("Only one debugger execution is allowed.\n");
    561         return;
    562     }
    563 
    564 #ifdef ACPI_DEBUG_OUTPUT
    565     /* Memory allocation tracking */
    566 
    567     PreviousAllocations = AcpiDbGetOutstandingAllocations ();
    568 #endif
    569 
    570     if (*Name == '*')
    571     {
    572         (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
    573             ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL);
    574         return;
    575     }
    576 
    577     if ((Flags & EX_ALL) && (strlen (Name) > 4))
    578     {
    579         AcpiOsPrintf ("Input name (%s) must be a 4-char NameSeg\n", Name);
    580         return;
    581     }
    582 
    583     NameString = ACPI_ALLOCATE (strlen (Name) + 1);
    584     if (!NameString)
    585     {
    586         return;
    587     }
    588 
    589     memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));
    590     strcpy (NameString, Name);
    591     AcpiUtStrupr (NameString);
    592 
    593     /* Subcommand to Execute all predefined names in the namespace */
    594 
    595     if (!strncmp (NameString, "PREDEF", 6))
    596     {
    597         AcpiDbEvaluatePredefinedNames ();
    598         ACPI_FREE (NameString);
    599         return;
    600     }
    601 
    602     /* Command (ALL <nameseg>) to execute all methods of a particular name */
    603 
    604     else if (Flags & EX_ALL)
    605     {
    606         AcpiGbl_DbMethodInfo.Name = NameString;
    607         ReturnObj.Pointer = NULL;
    608         ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
    609         AcpiDbEvaluateAll (NameString);
    610         ACPI_FREE (NameString);
    611         return;
    612     }
    613     else
    614     {
    615         AcpiGbl_DbMethodInfo.Name = NameString;
    616         AcpiGbl_DbMethodInfo.Args = Args;
    617         AcpiGbl_DbMethodInfo.Types = Types;
    618         AcpiGbl_DbMethodInfo.Flags = Flags;
    619 
    620         ReturnObj.Pointer = NULL;
    621         ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
    622     }
    623 
    624     Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
    625     if (ACPI_FAILURE (Status))
    626     {
    627         ACPI_FREE (NameString);
    628         return;
    629     }
    630 
    631     /* Get the NS node, determines existence also */
    632 
    633     Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,
    634         &AcpiGbl_DbMethodInfo.Method);
    635     if (ACPI_SUCCESS (Status))
    636     {
    637         Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo,
    638             &ReturnObj);
    639     }
    640     ACPI_FREE (NameString);
    641 
    642     /*
    643      * Allow any handlers in separate threads to complete.
    644      * (Such as Notify handlers invoked from AML executed above).
    645      */
    646     AcpiOsSleep ((UINT64) 10);
    647 
    648 #ifdef ACPI_DEBUG_OUTPUT
    649 
    650     /* Memory allocation tracking */
    651 
    652     Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations;
    653 
    654     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
    655 
    656     if (Allocations > 0)
    657     {
    658         AcpiOsPrintf (
    659             "0x%X Outstanding allocations after evaluation of %s\n",
    660             Allocations, AcpiGbl_DbMethodInfo.Pathname);
    661     }
    662 #endif
    663 
    664     if (ACPI_FAILURE (Status))
    665     {
    666         AcpiOsPrintf ("Evaluation of %s failed with status %s\n",
    667             AcpiGbl_DbMethodInfo.Pathname,
    668             AcpiFormatException (Status));
    669     }
    670     else
    671     {
    672         /* Display a return object, if any */
    673 
    674         if (ReturnObj.Length)
    675         {
    676             AcpiOsPrintf (
    677                 "Evaluation of %s returned object %p, "
    678                 "external buffer length %X\n",
    679                 AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer,
    680                 (UINT32) ReturnObj.Length);
    681 
    682             AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);
    683             AcpiOsPrintf ("\n");
    684 
    685             /* Dump a _PLD buffer if present */
    686 
    687             if (ACPI_COMPARE_NAMESEG ((ACPI_CAST_PTR (ACPI_NAMESPACE_NODE,
    688                 AcpiGbl_DbMethodInfo.Method)->Name.Ascii),
    689                 METHOD_NAME__PLD))
    690             {
    691                 AcpiDbDumpPldBuffer (ReturnObj.Pointer);
    692             }
    693         }
    694         else
    695         {
    696             AcpiOsPrintf ("No object was returned from evaluation of %s\n",
    697                 AcpiGbl_DbMethodInfo.Pathname);
    698         }
    699     }
    700 
    701     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
    702 }
    703 
    704 
    705 /*******************************************************************************
    706  *
    707  * FUNCTION:    AcpiDbMethodThread
    708  *
    709  * PARAMETERS:  Context             - Execution info segment
    710  *
    711  * RETURN:      None
    712  *
    713  * DESCRIPTION: Debugger execute thread. Waits for a command line, then
    714  *              simply dispatches it.
    715  *
    716  ******************************************************************************/
    717 
    718 static void ACPI_SYSTEM_XFACE
    719 AcpiDbMethodThread (
    720     void                    *Context)
    721 {
    722     ACPI_STATUS             Status;
    723     ACPI_DB_METHOD_INFO     *Info = Context;
    724     ACPI_DB_METHOD_INFO     LocalInfo;
    725     UINT32                  i;
    726     UINT8                   Allow;
    727     ACPI_BUFFER             ReturnObj;
    728 
    729 
    730     /*
    731      * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments.
    732      * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads
    733      * concurrently.
    734      *
    735      * Note: The arguments we are passing are used by the ASL test suite
    736      * (aslts). Do not change them without updating the tests.
    737      */
    738     (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER);
    739 
    740     if (Info->InitArgs)
    741     {
    742         AcpiDbUint32ToHexString (Info->NumCreated,
    743             Info->IndexOfThreadStr);
    744         AcpiDbUint32ToHexString ((UINT32) AcpiOsGetThreadId (),
    745             Info->IdOfThreadStr);
    746     }
    747 
    748     if (Info->Threads && (Info->NumCreated < Info->NumThreads))
    749     {
    750         Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId();
    751     }
    752 
    753     LocalInfo = *Info;
    754     LocalInfo.Args = LocalInfo.Arguments;
    755     LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr;
    756     LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr;
    757     LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr;
    758     LocalInfo.Arguments[3] = NULL;
    759 
    760     LocalInfo.Types = LocalInfo.ArgTypes;
    761 
    762     (void) AcpiOsSignalSemaphore (Info->InfoGate, 1);
    763 
    764     for (i = 0; i < Info->NumLoops; i++)
    765     {
    766         Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj);
    767         if (ACPI_FAILURE (Status))
    768         {
    769             AcpiOsPrintf ("%s During evaluation of %s at iteration %X\n",
    770                 AcpiFormatException (Status), Info->Pathname, i);
    771             if (Status == AE_ABORT_METHOD)
    772             {
    773                 break;
    774             }
    775         }
    776 
    777 #if 0
    778         if ((i % 100) == 0)
    779         {
    780             AcpiOsPrintf ("%u loops, Thread 0x%x\n",
    781                 i, AcpiOsGetThreadId ());
    782         }
    783 
    784         if (ReturnObj.Length)
    785         {
    786             AcpiOsPrintf ("Evaluation of %s returned object %p Buflen %X\n",
    787                 Info->Pathname, ReturnObj.Pointer,
    788                 (UINT32) ReturnObj.Length);
    789             AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);
    790         }
    791 #endif
    792     }
    793 
    794     /* Signal our completion */
    795 
    796     Allow = 0;
    797     (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate,
    798         1, ACPI_WAIT_FOREVER);
    799     Info->NumCompleted++;
    800 
    801     if (Info->NumCompleted == Info->NumThreads)
    802     {
    803         /* Do signal for main thread once only */
    804         Allow = 1;
    805     }
    806 
    807     (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1);
    808 
    809     if (Allow)
    810     {
    811         Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1);
    812         if (ACPI_FAILURE (Status))
    813         {
    814             AcpiOsPrintf (
    815                 "Could not signal debugger thread sync semaphore, %s\n",
    816                 AcpiFormatException (Status));
    817         }
    818     }
    819 }
    820 
    821 
    822 /*******************************************************************************
    823  *
    824  * FUNCTION:    AcpiDbSingleExecutionThread
    825  *
    826  * PARAMETERS:  Context                 - Method info struct
    827  *
    828  * RETURN:      None
    829  *
    830  * DESCRIPTION: Create one thread and execute a method
    831  *
    832  ******************************************************************************/
    833 
    834 static void ACPI_SYSTEM_XFACE
    835 AcpiDbSingleExecutionThread (
    836     void                    *Context)
    837 {
    838     ACPI_DB_METHOD_INFO     *Info = Context;
    839     ACPI_STATUS             Status;
    840     ACPI_BUFFER             ReturnObj;
    841 
    842 
    843     AcpiOsPrintf ("\n");
    844 
    845     Status = AcpiDbExecuteMethod (Info, &ReturnObj);
    846     if (ACPI_FAILURE (Status))
    847     {
    848         AcpiOsPrintf ("%s During evaluation of %s\n",
    849             AcpiFormatException (Status), Info->Pathname);
    850         return;
    851     }
    852 
    853     /* Display a return object, if any */
    854 
    855     if (ReturnObj.Length)
    856     {
    857         AcpiOsPrintf ("Evaluation of %s returned object %p, "
    858             "external buffer length %X\n",
    859             AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer,
    860             (UINT32) ReturnObj.Length);
    861 
    862         AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);
    863     }
    864 
    865     AcpiOsPrintf ("\nBackground thread completed\n%c ",
    866         ACPI_DEBUGGER_COMMAND_PROMPT);
    867 }
    868 
    869 
    870 /*******************************************************************************
    871  *
    872  * FUNCTION:    AcpiDbCreateExecutionThread
    873  *
    874  * PARAMETERS:  MethodNameArg           - Control method to execute
    875  *              Arguments               - Array of arguments to the method
    876  *              Types                   - Corresponding array of object types
    877  *
    878  * RETURN:      None
    879  *
    880  * DESCRIPTION: Create a single thread to evaluate a namespace object. Handles
    881  *              arguments passed on command line for control methods.
    882  *
    883  ******************************************************************************/
    884 
    885 void
    886 AcpiDbCreateExecutionThread (
    887     char                    *MethodNameArg,
    888     char                    **Arguments,
    889     ACPI_OBJECT_TYPE        *Types)
    890 {
    891     ACPI_STATUS             Status;
    892     UINT32                  i;
    893 
    894 
    895     memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));
    896     AcpiGbl_DbMethodInfo.Name = MethodNameArg;
    897     AcpiGbl_DbMethodInfo.InitArgs = 1;
    898     AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments;
    899     AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes;
    900 
    901     /* Setup method arguments, up to 7 (0-6) */
    902 
    903     for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *Arguments; i++)
    904     {
    905         AcpiGbl_DbMethodInfo.Arguments[i] = *Arguments;
    906         Arguments++;
    907 
    908         AcpiGbl_DbMethodInfo.ArgTypes[i] = *Types;
    909         Types++;
    910     }
    911 
    912     Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
    913     if (ACPI_FAILURE (Status))
    914     {
    915         return;
    916     }
    917 
    918     /* Get the NS node, determines existence also */
    919 
    920     Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,
    921         &AcpiGbl_DbMethodInfo.Method);
    922     if (ACPI_FAILURE (Status))
    923     {
    924         AcpiOsPrintf ("%s Could not get handle for %s\n",
    925             AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname);
    926         return;
    927     }
    928 
    929     Status = AcpiOsExecute (OSL_DEBUGGER_EXEC_THREAD,
    930         AcpiDbSingleExecutionThread, &AcpiGbl_DbMethodInfo);
    931     if (ACPI_FAILURE (Status))
    932     {
    933         return;
    934     }
    935 
    936     AcpiOsPrintf ("\nBackground thread started\n");
    937 }
    938 
    939 
    940 /*******************************************************************************
    941  *
    942  * FUNCTION:    AcpiDbCreateExecutionThreads
    943  *
    944  * PARAMETERS:  NumThreadsArg           - Number of threads to create
    945  *              NumLoopsArg             - Loop count for the thread(s)
    946  *              MethodNameArg           - Control method to execute
    947  *
    948  * RETURN:      None
    949  *
    950  * DESCRIPTION: Create threads to execute method(s)
    951  *
    952  ******************************************************************************/
    953 
    954 void
    955 AcpiDbCreateExecutionThreads (
    956     char                    *NumThreadsArg,
    957     char                    *NumLoopsArg,
    958     char                    *MethodNameArg)
    959 {
    960     ACPI_STATUS             Status;
    961     UINT32                  NumThreads;
    962     UINT32                  NumLoops;
    963     UINT32                  i;
    964     UINT32                  Size;
    965     ACPI_MUTEX              MainThreadGate;
    966     ACPI_MUTEX              ThreadCompleteGate;
    967     ACPI_MUTEX              InfoGate;
    968 
    969 
    970     /* Get the arguments */
    971 
    972     NumThreads = strtoul (NumThreadsArg, NULL, 0);
    973     NumLoops = strtoul (NumLoopsArg, NULL, 0);
    974 
    975     if (!NumThreads || !NumLoops)
    976     {
    977         AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n",
    978             NumThreads, NumLoops);
    979         return;
    980     }
    981 
    982     /*
    983      * Create the semaphore for synchronization of
    984      * the created threads with the main thread.
    985      */
    986     Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate);
    987     if (ACPI_FAILURE (Status))
    988     {
    989         AcpiOsPrintf ("Could not create semaphore for "
    990             "synchronization with the main thread, %s\n",
    991             AcpiFormatException (Status));
    992         return;
    993     }
    994 
    995     /*
    996      * Create the semaphore for synchronization
    997      * between the created threads.
    998      */
    999     Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate);
   1000     if (ACPI_FAILURE (Status))
   1001     {
   1002         AcpiOsPrintf ("Could not create semaphore for "
   1003             "synchronization between the created threads, %s\n",
   1004             AcpiFormatException (Status));
   1005 
   1006         (void) AcpiOsDeleteSemaphore (MainThreadGate);
   1007         return;
   1008     }
   1009 
   1010     Status = AcpiOsCreateSemaphore (1, 1, &InfoGate);
   1011     if (ACPI_FAILURE (Status))
   1012     {
   1013         AcpiOsPrintf ("Could not create semaphore for "
   1014             "synchronization of AcpiGbl_DbMethodInfo, %s\n",
   1015             AcpiFormatException (Status));
   1016 
   1017         (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
   1018         (void) AcpiOsDeleteSemaphore (MainThreadGate);
   1019         return;
   1020     }
   1021 
   1022     memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));
   1023 
   1024     /* Array to store IDs of threads */
   1025 
   1026     AcpiGbl_DbMethodInfo.NumThreads = NumThreads;
   1027     Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads;
   1028 
   1029     AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size);
   1030     if (AcpiGbl_DbMethodInfo.Threads == NULL)
   1031     {
   1032         AcpiOsPrintf ("No memory for thread IDs array\n");
   1033         (void) AcpiOsDeleteSemaphore (MainThreadGate);
   1034         (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
   1035         (void) AcpiOsDeleteSemaphore (InfoGate);
   1036         return;
   1037     }
   1038     memset (AcpiGbl_DbMethodInfo.Threads, 0, Size);
   1039 
   1040     /* Setup the context to be passed to each thread */
   1041 
   1042     AcpiGbl_DbMethodInfo.Name = MethodNameArg;
   1043     AcpiGbl_DbMethodInfo.Flags = 0;
   1044     AcpiGbl_DbMethodInfo.NumLoops = NumLoops;
   1045     AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate;
   1046     AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate;
   1047     AcpiGbl_DbMethodInfo.InfoGate = InfoGate;
   1048 
   1049     /* Init arguments to be passed to method */
   1050 
   1051     AcpiGbl_DbMethodInfo.InitArgs = 1;
   1052     AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments;
   1053     AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr;
   1054     AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr;
   1055     AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr;
   1056     AcpiGbl_DbMethodInfo.Arguments[3] = NULL;
   1057 
   1058     AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes;
   1059     AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER;
   1060     AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER;
   1061     AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER;
   1062 
   1063     AcpiDbUint32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr);
   1064 
   1065     Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
   1066     if (ACPI_FAILURE (Status))
   1067     {
   1068         goto CleanupAndExit;
   1069     }
   1070 
   1071     /* Get the NS node, determines existence also */
   1072 
   1073     Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname,
   1074         &AcpiGbl_DbMethodInfo.Method);
   1075     if (ACPI_FAILURE (Status))
   1076     {
   1077         AcpiOsPrintf ("%s Could not get handle for %s\n",
   1078             AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname);
   1079         goto CleanupAndExit;
   1080     }
   1081 
   1082     /* Create the threads */
   1083 
   1084     AcpiOsPrintf ("Creating %X threads to execute %X times each\n",
   1085         NumThreads, NumLoops);
   1086 
   1087     for (i = 0; i < (NumThreads); i++)
   1088     {
   1089         Status = AcpiOsExecute (OSL_DEBUGGER_EXEC_THREAD, AcpiDbMethodThread,
   1090             &AcpiGbl_DbMethodInfo);
   1091         if (ACPI_FAILURE (Status))
   1092         {
   1093             break;
   1094         }
   1095     }
   1096 
   1097     /* Wait for all threads to complete */
   1098 
   1099     (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER);
   1100 
   1101     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
   1102     AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads);
   1103     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
   1104 
   1105 CleanupAndExit:
   1106 
   1107     /* Cleanup and exit */
   1108 
   1109     (void) AcpiOsDeleteSemaphore (MainThreadGate);
   1110     (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
   1111     (void) AcpiOsDeleteSemaphore (InfoGate);
   1112 
   1113     AcpiOsFree (AcpiGbl_DbMethodInfo.Threads);
   1114     AcpiGbl_DbMethodInfo.Threads = NULL;
   1115 }
   1116