Home | History | Annotate | Line # | Download | only in debugger
dbexec.c revision 1.1.1.3
      1 /*******************************************************************************
      2  *
      3  * Module Name: dbexec - debugger control method execution
      4  *
      5  ******************************************************************************/
      6 
      7 /*
      8  * Copyright (C) 2000 - 2011, 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 
     45 #include "acpi.h"
     46 #include "accommon.h"
     47 #include "acdebug.h"
     48 #include "acnamesp.h"
     49 
     50 #ifdef ACPI_DEBUGGER
     51 
     52 #define _COMPONENT          ACPI_CA_DEBUGGER
     53         ACPI_MODULE_NAME    ("dbexec")
     54 
     55 
     56 static ACPI_DB_METHOD_INFO          AcpiGbl_DbMethodInfo;
     57 #define DB_DEFAULT_PKG_ELEMENTS     33
     58 
     59 /* Local prototypes */
     60 
     61 static ACPI_STATUS
     62 AcpiDbExecuteMethod (
     63     ACPI_DB_METHOD_INFO     *Info,
     64     ACPI_BUFFER             *ReturnObj);
     65 
     66 static void
     67 AcpiDbExecuteSetup (
     68     ACPI_DB_METHOD_INFO     *Info);
     69 
     70 static UINT32
     71 AcpiDbGetOutstandingAllocations (
     72     void);
     73 
     74 static void ACPI_SYSTEM_XFACE
     75 AcpiDbMethodThread (
     76     void                    *Context);
     77 
     78 static ACPI_STATUS
     79 AcpiDbExecutionWalk (
     80     ACPI_HANDLE             ObjHandle,
     81     UINT32                  NestingLevel,
     82     void                    *Context,
     83     void                    **ReturnValue);
     84 
     85 static ACPI_STATUS
     86 AcpiDbHexCharToValue (
     87     int                     HexChar,
     88     UINT8                   *ReturnValue);
     89 
     90 static ACPI_STATUS
     91 AcpiDbConvertToPackage (
     92     char                    *String,
     93     ACPI_OBJECT             *Object);
     94 
     95 static ACPI_STATUS
     96 AcpiDbConvertToObject (
     97     ACPI_OBJECT_TYPE        Type,
     98     char                    *String,
     99     ACPI_OBJECT             *Object);
    100 
    101 static void
    102 AcpiDbDeleteObjects (
    103     UINT32                  Count,
    104     ACPI_OBJECT             *Objects);
    105 
    106 
    107 /*******************************************************************************
    108  *
    109  * FUNCTION:    AcpiDbHexCharToValue
    110  *
    111  * PARAMETERS:  HexChar             - Ascii Hex digit, 0-9|a-f|A-F
    112  *              ReturnValue         - Where the converted value is returned
    113  *
    114  * RETURN:      Status
    115  *
    116  * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16).
    117  *
    118  ******************************************************************************/
    119 
    120 static ACPI_STATUS
    121 AcpiDbHexCharToValue (
    122     int                     HexChar,
    123     UINT8                   *ReturnValue)
    124 {
    125     UINT8                   Value;
    126 
    127 
    128     /* Digit must be ascii [0-9a-fA-F] */
    129 
    130     if (!ACPI_IS_XDIGIT (HexChar))
    131     {
    132         return (AE_BAD_HEX_CONSTANT);
    133     }
    134 
    135     if (HexChar <= 0x39)
    136     {
    137         Value = (UINT8) (HexChar - 0x30);
    138     }
    139     else
    140     {
    141         Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37);
    142     }
    143 
    144     *ReturnValue = Value;
    145     return (AE_OK);
    146 }
    147 
    148 
    149 /*******************************************************************************
    150  *
    151  * FUNCTION:    AcpiDbHexByteToBinary
    152  *
    153  * PARAMETERS:  HexByte             - Double hex digit (0x00 - 0xFF) in format:
    154  *                                    HiByte then LoByte.
    155  *              ReturnValue         - Where the converted value is returned
    156  *
    157  * RETURN:      Status
    158  *
    159  * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255).
    160  *
    161  ******************************************************************************/
    162 
    163 static ACPI_STATUS
    164 AcpiDbHexByteToBinary (
    165     char                    *HexByte,
    166     UINT8                   *ReturnValue)
    167 {
    168     UINT8                   Local0;
    169     UINT8                   Local1;
    170     ACPI_STATUS             Status;
    171 
    172 
    173     /* High byte */
    174 
    175     Status = AcpiDbHexCharToValue (HexByte[0], &Local0);
    176     if (ACPI_FAILURE (Status))
    177     {
    178         return (Status);
    179     }
    180 
    181     /* Low byte */
    182 
    183     Status = AcpiDbHexCharToValue (HexByte[1], &Local1);
    184     if (ACPI_FAILURE (Status))
    185     {
    186         return (Status);
    187     }
    188 
    189     *ReturnValue = (UINT8) ((Local0 << 4) | Local1);
    190     return (AE_OK);
    191 }
    192 
    193 
    194 /*******************************************************************************
    195  *
    196  * FUNCTION:    AcpiDbConvertToBuffer
    197  *
    198  * PARAMETERS:  String              - Input string to be converted
    199  *              Object              - Where the buffer object is returned
    200  *
    201  * RETURN:      Status
    202  *
    203  * DESCRIPTION: Convert a string to a buffer object. String is treated a list
    204  *              of buffer elements, each separated by a space or comma.
    205  *
    206  ******************************************************************************/
    207 
    208 static ACPI_STATUS
    209 AcpiDbConvertToBuffer (
    210     char                    *String,
    211     ACPI_OBJECT             *Object)
    212 {
    213     UINT32                  i;
    214     UINT32                  j;
    215     UINT32                  Length;
    216     UINT8                   *Buffer;
    217     ACPI_STATUS             Status;
    218 
    219 
    220     /* Generate the final buffer length */
    221 
    222     for (i = 0, Length = 0; String[i];)
    223     {
    224         i+=2;
    225         Length++;
    226 
    227         while (String[i] &&
    228               ((String[i] == ',') || (String[i] == ' ')))
    229         {
    230             i++;
    231         }
    232     }
    233 
    234     Buffer = ACPI_ALLOCATE (Length);
    235     if (!Buffer)
    236     {
    237         return (AE_NO_MEMORY);
    238     }
    239 
    240     /* Convert the command line bytes to the buffer */
    241 
    242     for (i = 0, j = 0; String[i];)
    243     {
    244         Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]);
    245         if (ACPI_FAILURE (Status))
    246         {
    247             ACPI_FREE (Buffer);
    248             return (Status);
    249         }
    250 
    251         j++;
    252         i+=2;
    253         while (String[i] &&
    254               ((String[i] == ',') || (String[i] == ' ')))
    255         {
    256             i++;
    257         }
    258     }
    259 
    260     Object->Type = ACPI_TYPE_BUFFER;
    261     Object->Buffer.Pointer = Buffer;
    262     Object->Buffer.Length = Length;
    263     return (AE_OK);
    264 }
    265 
    266 
    267 /*******************************************************************************
    268  *
    269  * FUNCTION:    AcpiDbConvertToPackage
    270  *
    271  * PARAMETERS:  String              - Input string to be converted
    272  *              Object              - Where the package object is returned
    273  *
    274  * RETURN:      Status
    275  *
    276  * DESCRIPTION: Convert a string to a package object. Handles nested packages
    277  *              via recursion with AcpiDbConvertToObject.
    278  *
    279  ******************************************************************************/
    280 
    281 static ACPI_STATUS
    282 AcpiDbConvertToPackage (
    283     char                    *String,
    284     ACPI_OBJECT             *Object)
    285 {
    286     char                    *This;
    287     char                    *Next;
    288     UINT32                  i;
    289     ACPI_OBJECT_TYPE        Type;
    290     ACPI_OBJECT             *Elements;
    291     ACPI_STATUS             Status;
    292 
    293 
    294     Elements = ACPI_ALLOCATE_ZEROED (
    295         DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT));
    296 
    297     This = String;
    298     for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++)
    299     {
    300         This = AcpiDbGetNextToken (This, &Next, &Type);
    301         if (!This)
    302         {
    303             break;
    304         }
    305 
    306         /* Recursive call to convert each package element */
    307 
    308         Status = AcpiDbConvertToObject (Type, This, &Elements[i]);
    309         if (ACPI_FAILURE (Status))
    310         {
    311             AcpiDbDeleteObjects (i + 1, Elements);
    312             ACPI_FREE (Elements);
    313             return (Status);
    314         }
    315 
    316         This = Next;
    317     }
    318 
    319     Object->Type = ACPI_TYPE_PACKAGE;
    320     Object->Package.Count = i;
    321     Object->Package.Elements = Elements;
    322     return (AE_OK);
    323 }
    324 
    325 
    326 /*******************************************************************************
    327  *
    328  * FUNCTION:    AcpiDbConvertToObject
    329  *
    330  * PARAMETERS:  Type                - Object type as determined by parser
    331  *              String              - Input string to be converted
    332  *              Object              - Where the new object is returned
    333  *
    334  * RETURN:      Status
    335  *
    336  * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing:
    337  *              1) String objects were surrounded by quotes.
    338  *              2) Buffer objects were surrounded by parentheses.
    339  *              3) Package objects were surrounded by brackets "[]".
    340  *              4) All standalone tokens are treated as integers.
    341  *
    342  ******************************************************************************/
    343 
    344 static ACPI_STATUS
    345 AcpiDbConvertToObject (
    346     ACPI_OBJECT_TYPE        Type,
    347     char                    *String,
    348     ACPI_OBJECT             *Object)
    349 {
    350     ACPI_STATUS             Status = AE_OK;
    351 
    352 
    353     switch (Type)
    354     {
    355     case ACPI_TYPE_STRING:
    356         Object->Type = ACPI_TYPE_STRING;
    357         Object->String.Pointer = String;
    358         Object->String.Length = (UINT32) ACPI_STRLEN (String);
    359         break;
    360 
    361     case ACPI_TYPE_BUFFER:
    362         Status = AcpiDbConvertToBuffer (String, Object);
    363         break;
    364 
    365     case ACPI_TYPE_PACKAGE:
    366         Status = AcpiDbConvertToPackage (String, Object);
    367         break;
    368 
    369     default:
    370         Object->Type = ACPI_TYPE_INTEGER;
    371         Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value);
    372         break;
    373     }
    374 
    375     return (Status);
    376 }
    377 
    378 
    379 /*******************************************************************************
    380  *
    381  * FUNCTION:    AcpiDbDeleteObjects
    382  *
    383  * PARAMETERS:  Count               - Count of objects in the list
    384  *              Objects             - Array of ACPI_OBJECTs to be deleted
    385  *
    386  * RETURN:      None
    387  *
    388  * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested
    389  *              packages via recursion.
    390  *
    391  ******************************************************************************/
    392 
    393 static void
    394 AcpiDbDeleteObjects (
    395     UINT32                  Count,
    396     ACPI_OBJECT             *Objects)
    397 {
    398     UINT32                  i;
    399 
    400 
    401     for (i = 0; i < Count; i++)
    402     {
    403         switch (Objects[i].Type)
    404         {
    405         case ACPI_TYPE_BUFFER:
    406             ACPI_FREE (Objects[i].Buffer.Pointer);
    407             break;
    408 
    409         case ACPI_TYPE_PACKAGE:
    410 
    411             /* Recursive call to delete package elements */
    412 
    413             AcpiDbDeleteObjects (Objects[i].Package.Count,
    414                 Objects[i].Package.Elements);
    415 
    416             /* Free the elements array */
    417 
    418             ACPI_FREE (Objects[i].Package.Elements);
    419             break;
    420 
    421         default:
    422             break;
    423         }
    424     }
    425 }
    426 
    427 
    428 /*******************************************************************************
    429  *
    430  * FUNCTION:    AcpiDbExecuteMethod
    431  *
    432  * PARAMETERS:  Info            - Valid info segment
    433  *              ReturnObj       - Where to put return object
    434  *
    435  * RETURN:      Status
    436  *
    437  * DESCRIPTION: Execute a control method.
    438  *
    439  ******************************************************************************/
    440 
    441 static ACPI_STATUS
    442 AcpiDbExecuteMethod (
    443     ACPI_DB_METHOD_INFO     *Info,
    444     ACPI_BUFFER             *ReturnObj)
    445 {
    446     ACPI_STATUS             Status;
    447     ACPI_OBJECT_LIST        ParamObjects;
    448     ACPI_OBJECT             Params[ACPI_METHOD_NUM_ARGS];
    449     ACPI_HANDLE             Handle;
    450     ACPI_DEVICE_INFO        *ObjInfo;
    451     UINT32                  i;
    452 
    453 
    454     ACPI_FUNCTION_TRACE (DbExecuteMethod);
    455 
    456 
    457     if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel)
    458     {
    459         AcpiOsPrintf ("Warning: debug output is not enabled!\n");
    460     }
    461 
    462     /* Get the NS node, determines existence also */
    463 
    464     Status = AcpiGetHandle (NULL, Info->Pathname, &Handle);
    465     if (ACPI_FAILURE (Status))
    466     {
    467         return_ACPI_STATUS (Status);
    468     }
    469 
    470     /* Get the object info for number of method parameters */
    471 
    472     Status = AcpiGetObjectInfo (Handle, &ObjInfo);
    473     if (ACPI_FAILURE (Status))
    474     {
    475         return_ACPI_STATUS (Status);
    476     }
    477 
    478     ParamObjects.Pointer = NULL;
    479     ParamObjects.Count   = 0;
    480 
    481     if (ObjInfo->Type == ACPI_TYPE_METHOD)
    482     {
    483         /* Are there arguments to the method? */
    484 
    485         i = 0;
    486         if (Info->Args && Info->Args[0])
    487         {
    488             /* Get arguments passed on the command line */
    489 
    490             for (; Info->Args[i] &&
    491                 (i < ACPI_METHOD_NUM_ARGS) &&
    492                 (i < ObjInfo->ParamCount);
    493                 i++)
    494             {
    495                 /* Convert input string (token) to an actual ACPI_OBJECT */
    496 
    497                 Status = AcpiDbConvertToObject (Info->Types[i],
    498                     Info->Args[i], &Params[i]);
    499                 if (ACPI_FAILURE (Status))
    500                 {
    501                     ACPI_EXCEPTION ((AE_INFO, Status,
    502                         "While parsing method arguments"));
    503                     goto Cleanup;
    504                 }
    505             }
    506         }
    507 
    508         /* Create additional "default" parameters as needed */
    509 
    510         if (i < ObjInfo->ParamCount)
    511         {
    512             AcpiOsPrintf ("Adding %u arguments containing default values\n",
    513                 ObjInfo->ParamCount - i);
    514 
    515             for (; i < ObjInfo->ParamCount; i++)
    516             {
    517                 switch (i)
    518                 {
    519                 case 0:
    520 
    521                     Params[0].Type           = ACPI_TYPE_INTEGER;
    522                     Params[0].Integer.Value  = 0x01020304;
    523                     break;
    524 
    525                 case 1:
    526 
    527                     Params[1].Type           = ACPI_TYPE_STRING;
    528                     Params[1].String.Length  = 12;
    529                     Params[1].String.Pointer = "AML Debugger";
    530                     break;
    531 
    532                 default:
    533 
    534                     Params[i].Type           = ACPI_TYPE_INTEGER;
    535                     Params[i].Integer.Value  = i * (UINT64) 0x1000;
    536                     break;
    537                 }
    538             }
    539         }
    540 
    541         ParamObjects.Count = ObjInfo->ParamCount;
    542         ParamObjects.Pointer = Params;
    543     }
    544 
    545     /* Prepare for a return object of arbitrary size */
    546 
    547     ReturnObj->Pointer = AcpiGbl_DbBuffer;
    548     ReturnObj->Length  = ACPI_DEBUG_BUFFER_SIZE;
    549 
    550     /* Do the actual method execution */
    551 
    552     AcpiGbl_MethodExecuting = TRUE;
    553     Status = AcpiEvaluateObject (NULL,
    554         Info->Pathname, &ParamObjects, ReturnObj);
    555 
    556     AcpiGbl_CmSingleStep = FALSE;
    557     AcpiGbl_MethodExecuting = FALSE;
    558 
    559     if (ACPI_FAILURE (Status))
    560     {
    561         ACPI_EXCEPTION ((AE_INFO, Status,
    562             "while executing %s from debugger", Info->Pathname));
    563 
    564         if (Status == AE_BUFFER_OVERFLOW)
    565         {
    566             ACPI_ERROR ((AE_INFO,
    567                 "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)",
    568                 ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length));
    569         }
    570     }
    571 
    572 Cleanup:
    573     AcpiDbDeleteObjects (ObjInfo->ParamCount, Params);
    574     ACPI_FREE (ObjInfo);
    575 
    576     return_ACPI_STATUS (Status);
    577 }
    578 
    579 
    580 /*******************************************************************************
    581  *
    582  * FUNCTION:    AcpiDbExecuteSetup
    583  *
    584  * PARAMETERS:  Info            - Valid method info
    585  *
    586  * RETURN:      None
    587  *
    588  * DESCRIPTION: Setup info segment prior to method execution
    589  *
    590  ******************************************************************************/
    591 
    592 static void
    593 AcpiDbExecuteSetup (
    594     ACPI_DB_METHOD_INFO     *Info)
    595 {
    596 
    597     /* Catenate the current scope to the supplied name */
    598 
    599     Info->Pathname[0] = 0;
    600     if ((Info->Name[0] != '\\') &&
    601         (Info->Name[0] != '/'))
    602     {
    603         ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf);
    604     }
    605 
    606     ACPI_STRCAT (Info->Pathname, Info->Name);
    607     AcpiDbPrepNamestring (Info->Pathname);
    608 
    609     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
    610     AcpiOsPrintf ("Executing %s\n", Info->Pathname);
    611 
    612     if (Info->Flags & EX_SINGLE_STEP)
    613     {
    614         AcpiGbl_CmSingleStep = TRUE;
    615         AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
    616     }
    617 
    618     else
    619     {
    620         /* No single step, allow redirection to a file */
    621 
    622         AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT);
    623     }
    624 }
    625 
    626 
    627 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
    628 UINT32
    629 AcpiDbGetCacheInfo (
    630     ACPI_MEMORY_LIST        *Cache)
    631 {
    632 
    633     return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth);
    634 }
    635 #endif
    636 
    637 /*******************************************************************************
    638  *
    639  * FUNCTION:    AcpiDbGetOutstandingAllocations
    640  *
    641  * PARAMETERS:  None
    642  *
    643  * RETURN:      Current global allocation count minus cache entries
    644  *
    645  * DESCRIPTION: Determine the current number of "outstanding" allocations --
    646  *              those allocations that have not been freed and also are not
    647  *              in one of the various object caches.
    648  *
    649  ******************************************************************************/
    650 
    651 static UINT32
    652 AcpiDbGetOutstandingAllocations (
    653     void)
    654 {
    655     UINT32                  Outstanding = 0;
    656 
    657 #ifdef ACPI_DBG_TRACK_ALLOCATIONS
    658 
    659     Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache);
    660     Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache);
    661     Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache);
    662     Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache);
    663 #endif
    664 
    665     return (Outstanding);
    666 }
    667 
    668 
    669 /*******************************************************************************
    670  *
    671  * FUNCTION:    AcpiDbExecutionWalk
    672  *
    673  * PARAMETERS:  WALK_CALLBACK
    674  *
    675  * RETURN:      Status
    676  *
    677  * DESCRIPTION: Execute a control method.  Name is relative to the current
    678  *              scope.
    679  *
    680  ******************************************************************************/
    681 
    682 static ACPI_STATUS
    683 AcpiDbExecutionWalk (
    684     ACPI_HANDLE             ObjHandle,
    685     UINT32                  NestingLevel,
    686     void                    *Context,
    687     void                    **ReturnValue)
    688 {
    689     ACPI_OPERAND_OBJECT     *ObjDesc;
    690     ACPI_NAMESPACE_NODE     *Node = (ACPI_NAMESPACE_NODE *) ObjHandle;
    691     ACPI_BUFFER             ReturnObj;
    692     ACPI_STATUS             Status;
    693 
    694 
    695     ObjDesc = AcpiNsGetAttachedObject (Node);
    696     if (ObjDesc->Method.ParamCount)
    697     {
    698         return (AE_OK);
    699     }
    700 
    701     ReturnObj.Pointer = NULL;
    702     ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
    703 
    704     AcpiNsPrintNodePathname (Node, "Execute");
    705 
    706     /* Do the actual method execution */
    707 
    708     AcpiOsPrintf ("\n");
    709     AcpiGbl_MethodExecuting = TRUE;
    710 
    711     Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj);
    712 
    713     AcpiOsPrintf ("[%4.4s] returned %s\n", AcpiUtGetNodeName (Node),
    714             AcpiFormatException (Status));
    715     AcpiGbl_MethodExecuting = FALSE;
    716 
    717     return (AE_OK);
    718 }
    719 
    720 
    721 /*******************************************************************************
    722  *
    723  * FUNCTION:    AcpiDbExecute
    724  *
    725  * PARAMETERS:  Name                - Name of method to execute
    726  *              Args                - Parameters to the method
    727  *              Flags               - single step/no single step
    728  *
    729  * RETURN:      None
    730  *
    731  * DESCRIPTION: Execute a control method.  Name is relative to the current
    732  *              scope.
    733  *
    734  ******************************************************************************/
    735 
    736 void
    737 AcpiDbExecute (
    738     char                    *Name,
    739     char                    **Args,
    740     ACPI_OBJECT_TYPE        *Types,
    741     UINT32                  Flags)
    742 {
    743     ACPI_STATUS             Status;
    744     ACPI_BUFFER             ReturnObj;
    745     char                    *NameString;
    746 
    747 
    748 #ifdef ACPI_DEBUG_OUTPUT
    749     UINT32                  PreviousAllocations;
    750     UINT32                  Allocations;
    751 
    752 
    753     /* Memory allocation tracking */
    754 
    755     PreviousAllocations = AcpiDbGetOutstandingAllocations ();
    756 #endif
    757 
    758     if (*Name == '*')
    759     {
    760         (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT,
    761                     ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL);
    762         return;
    763     }
    764     else
    765     {
    766         NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1);
    767         if (!NameString)
    768         {
    769             return;
    770         }
    771 
    772         ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));
    773 
    774         ACPI_STRCPY (NameString, Name);
    775         AcpiUtStrupr (NameString);
    776         AcpiGbl_DbMethodInfo.Name = NameString;
    777         AcpiGbl_DbMethodInfo.Args = Args;
    778         AcpiGbl_DbMethodInfo.Types = Types;
    779         AcpiGbl_DbMethodInfo.Flags = Flags;
    780 
    781         ReturnObj.Pointer = NULL;
    782         ReturnObj.Length = ACPI_ALLOCATE_BUFFER;
    783 
    784         AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
    785         Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj);
    786         ACPI_FREE (NameString);
    787     }
    788 
    789     /*
    790      * Allow any handlers in separate threads to complete.
    791      * (Such as Notify handlers invoked from AML executed above).
    792      */
    793     AcpiOsSleep ((UINT64) 10);
    794 
    795 
    796 #ifdef ACPI_DEBUG_OUTPUT
    797 
    798     /* Memory allocation tracking */
    799 
    800     Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations;
    801 
    802     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
    803 
    804     if (Allocations > 0)
    805     {
    806         AcpiOsPrintf ("Outstanding: 0x%X allocations after execution\n",
    807                         Allocations);
    808     }
    809 #endif
    810 
    811     if (ACPI_FAILURE (Status))
    812     {
    813         AcpiOsPrintf ("Execution of %s failed with status %s\n",
    814             AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status));
    815     }
    816     else
    817     {
    818         /* Display a return object, if any */
    819 
    820         if (ReturnObj.Length)
    821         {
    822             AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n",
    823                 AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer,
    824                 (UINT32) ReturnObj.Length);
    825             AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);
    826         }
    827         else
    828         {
    829             AcpiOsPrintf ("No return object from execution of %s\n",
    830                 AcpiGbl_DbMethodInfo.Pathname);
    831         }
    832     }
    833 
    834     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
    835 }
    836 
    837 
    838 /*******************************************************************************
    839  *
    840  * FUNCTION:    AcpiDbMethodThread
    841  *
    842  * PARAMETERS:  Context             - Execution info segment
    843  *
    844  * RETURN:      None
    845  *
    846  * DESCRIPTION: Debugger execute thread.  Waits for a command line, then
    847  *              simply dispatches it.
    848  *
    849  ******************************************************************************/
    850 
    851 static void ACPI_SYSTEM_XFACE
    852 AcpiDbMethodThread (
    853     void                    *Context)
    854 {
    855     ACPI_STATUS             Status;
    856     ACPI_DB_METHOD_INFO     *Info = Context;
    857     ACPI_DB_METHOD_INFO     LocalInfo;
    858     UINT32                  i;
    859     UINT8                   Allow;
    860     ACPI_BUFFER             ReturnObj;
    861 
    862 
    863     /*
    864      * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments.
    865      * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads
    866      * concurrently.
    867      *
    868      * Note: The arguments we are passing are used by the ASL test suite
    869      * (aslts). Do not change them without updating the tests.
    870      */
    871     (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER);
    872 
    873     if (Info->InitArgs)
    874     {
    875         AcpiDbUInt32ToHexString (Info->NumCreated, Info->IndexOfThreadStr);
    876         AcpiDbUInt32ToHexString ((UINT32) AcpiOsGetThreadId (), Info->IdOfThreadStr);
    877     }
    878 
    879     if (Info->Threads && (Info->NumCreated < Info->NumThreads))
    880     {
    881         Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId();
    882     }
    883 
    884     LocalInfo = *Info;
    885     LocalInfo.Args = LocalInfo.Arguments;
    886     LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr;
    887     LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr;
    888     LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr;
    889     LocalInfo.Arguments[3] = NULL;
    890 
    891     LocalInfo.Types = LocalInfo.ArgTypes;
    892 
    893     (void) AcpiOsSignalSemaphore (Info->InfoGate, 1);
    894 
    895     for (i = 0; i < Info->NumLoops; i++)
    896     {
    897         Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj);
    898         if (ACPI_FAILURE (Status))
    899         {
    900             AcpiOsPrintf ("%s During execution of %s at iteration %X\n",
    901                 AcpiFormatException (Status), Info->Pathname, i);
    902             if (Status == AE_ABORT_METHOD)
    903             {
    904                 break;
    905             }
    906         }
    907 
    908 #if 0
    909         if ((i % 100) == 0)
    910         {
    911             AcpiOsPrintf ("%u executions, Thread 0x%x\n", i, AcpiOsGetThreadId ());
    912         }
    913 
    914         if (ReturnObj.Length)
    915         {
    916             AcpiOsPrintf ("Execution of %s returned object %p Buflen %X\n",
    917                 Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length);
    918             AcpiDbDumpExternalObject (ReturnObj.Pointer, 1);
    919         }
    920 #endif
    921     }
    922 
    923     /* Signal our completion */
    924 
    925     Allow = 0;
    926     (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER);
    927     Info->NumCompleted++;
    928 
    929     if (Info->NumCompleted == Info->NumThreads)
    930     {
    931         /* Do signal for main thread once only */
    932         Allow = 1;
    933     }
    934 
    935     (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1);
    936 
    937     if (Allow)
    938     {
    939         Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1);
    940         if (ACPI_FAILURE (Status))
    941         {
    942             AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n",
    943                 AcpiFormatException (Status));
    944         }
    945     }
    946 }
    947 
    948 
    949 /*******************************************************************************
    950  *
    951  * FUNCTION:    AcpiDbCreateExecutionThreads
    952  *
    953  * PARAMETERS:  NumThreadsArg           - Number of threads to create
    954  *              NumLoopsArg             - Loop count for the thread(s)
    955  *              MethodNameArg           - Control method to execute
    956  *
    957  * RETURN:      None
    958  *
    959  * DESCRIPTION: Create threads to execute method(s)
    960  *
    961  ******************************************************************************/
    962 
    963 void
    964 AcpiDbCreateExecutionThreads (
    965     char                    *NumThreadsArg,
    966     char                    *NumLoopsArg,
    967     char                    *MethodNameArg)
    968 {
    969     ACPI_STATUS             Status;
    970     UINT32                  NumThreads;
    971     UINT32                  NumLoops;
    972     UINT32                  i;
    973     UINT32                  Size;
    974     ACPI_MUTEX              MainThreadGate;
    975     ACPI_MUTEX              ThreadCompleteGate;
    976     ACPI_MUTEX              InfoGate;
    977 
    978 
    979     /* Get the arguments */
    980 
    981     NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0);
    982     NumLoops   = ACPI_STRTOUL (NumLoopsArg, NULL, 0);
    983 
    984     if (!NumThreads || !NumLoops)
    985     {
    986         AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n",
    987             NumThreads, NumLoops);
    988         return;
    989     }
    990 
    991     /*
    992      * Create the semaphore for synchronization of
    993      * the created threads with the main thread.
    994      */
    995     Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate);
    996     if (ACPI_FAILURE (Status))
    997     {
    998         AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n",
    999             AcpiFormatException (Status));
   1000         return;
   1001     }
   1002 
   1003     /*
   1004      * Create the semaphore for synchronization
   1005      * between the created threads.
   1006      */
   1007     Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate);
   1008     if (ACPI_FAILURE (Status))
   1009     {
   1010         AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n",
   1011             AcpiFormatException (Status));
   1012         (void) AcpiOsDeleteSemaphore (MainThreadGate);
   1013         return;
   1014     }
   1015 
   1016     Status = AcpiOsCreateSemaphore (1, 1, &InfoGate);
   1017     if (ACPI_FAILURE (Status))
   1018     {
   1019         AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n",
   1020             AcpiFormatException (Status));
   1021         (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
   1022         (void) AcpiOsDeleteSemaphore (MainThreadGate);
   1023         return;
   1024     }
   1025 
   1026     ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO));
   1027 
   1028     /* Array to store IDs of threads */
   1029 
   1030     AcpiGbl_DbMethodInfo.NumThreads = NumThreads;
   1031     Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads;
   1032     AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size);
   1033     if (AcpiGbl_DbMethodInfo.Threads == NULL)
   1034     {
   1035         AcpiOsPrintf ("No memory for thread IDs array\n");
   1036         (void) AcpiOsDeleteSemaphore (MainThreadGate);
   1037         (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
   1038         (void) AcpiOsDeleteSemaphore (InfoGate);
   1039         return;
   1040     }
   1041     ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size);
   1042 
   1043     /* Setup the context to be passed to each thread */
   1044 
   1045     AcpiGbl_DbMethodInfo.Name = MethodNameArg;
   1046     AcpiGbl_DbMethodInfo.Flags = 0;
   1047     AcpiGbl_DbMethodInfo.NumLoops = NumLoops;
   1048     AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate;
   1049     AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate;
   1050     AcpiGbl_DbMethodInfo.InfoGate = InfoGate;
   1051 
   1052     /* Init arguments to be passed to method */
   1053 
   1054     AcpiGbl_DbMethodInfo.InitArgs = 1;
   1055     AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments;
   1056     AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr;
   1057     AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr;
   1058     AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr;
   1059     AcpiGbl_DbMethodInfo.Arguments[3] = NULL;
   1060 
   1061     AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes;
   1062     AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER;
   1063     AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER;
   1064     AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER;
   1065 
   1066     AcpiDbUInt32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr);
   1067 
   1068     AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo);
   1069 
   1070     /* Create the threads */
   1071 
   1072     AcpiOsPrintf ("Creating %X threads to execute %X times each\n",
   1073         NumThreads, NumLoops);
   1074 
   1075     for (i = 0; i < (NumThreads); i++)
   1076     {
   1077         Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread,
   1078             &AcpiGbl_DbMethodInfo);
   1079         if (ACPI_FAILURE (Status))
   1080         {
   1081             break;
   1082         }
   1083     }
   1084 
   1085     /* Wait for all threads to complete */
   1086 
   1087     (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER);
   1088 
   1089     AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT);
   1090     AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads);
   1091     AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT);
   1092 
   1093     /* Cleanup and exit */
   1094 
   1095     (void) AcpiOsDeleteSemaphore (MainThreadGate);
   1096     (void) AcpiOsDeleteSemaphore (ThreadCompleteGate);
   1097     (void) AcpiOsDeleteSemaphore (InfoGate);
   1098 
   1099     AcpiOsFree (AcpiGbl_DbMethodInfo.Threads);
   1100     AcpiGbl_DbMethodInfo.Threads = NULL;
   1101 }
   1102 
   1103 #endif /* ACPI_DEBUGGER */
   1104 
   1105 
   1106