167754Smsmith/******************************************************************************* 267754Smsmith * 367754Smsmith * Module Name: dbexec - debugger control method execution 467754Smsmith * 567754Smsmith ******************************************************************************/ 667754Smsmith 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/acdebug.h> 47193341Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 4867754Smsmith 4967754Smsmith 50102550Siwasaki#define _COMPONENT ACPI_CA_DEBUGGER 5191116Smsmith ACPI_MODULE_NAME ("dbexec") 5267754Smsmith 5367754Smsmith 54222544Sjkimstatic ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; 5567754Smsmith 56151937Sjkim/* Local prototypes */ 5767754Smsmith 58151937Sjkimstatic ACPI_STATUS 59151937SjkimAcpiDbExecuteMethod ( 60151937Sjkim ACPI_DB_METHOD_INFO *Info, 61151937Sjkim ACPI_BUFFER *ReturnObj); 62151937Sjkim 63281075Sdimstatic ACPI_STATUS 64151937SjkimAcpiDbExecuteSetup ( 65151937Sjkim ACPI_DB_METHOD_INFO *Info); 66151937Sjkim 67151937Sjkimstatic UINT32 68151937SjkimAcpiDbGetOutstandingAllocations ( 69151937Sjkim void); 70151937Sjkim 71151937Sjkimstatic void ACPI_SYSTEM_XFACE 72151937SjkimAcpiDbMethodThread ( 73151937Sjkim void *Context); 74151937Sjkim 75151937Sjkimstatic ACPI_STATUS 76151937SjkimAcpiDbExecutionWalk ( 77151937Sjkim ACPI_HANDLE ObjHandle, 78151937Sjkim UINT32 NestingLevel, 79151937Sjkim void *Context, 80151937Sjkim void **ReturnValue); 81151937Sjkim 82151937Sjkim 8367754Smsmith/******************************************************************************* 8467754Smsmith * 85222544Sjkim * FUNCTION: AcpiDbDeleteObjects 86222544Sjkim * 87222544Sjkim * PARAMETERS: Count - Count of objects in the list 88222544Sjkim * Objects - Array of ACPI_OBJECTs to be deleted 89222544Sjkim * 90222544Sjkim * RETURN: None 91222544Sjkim * 92222544Sjkim * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested 93222544Sjkim * packages via recursion. 94222544Sjkim * 95222544Sjkim ******************************************************************************/ 96222544Sjkim 97245582Sjkimvoid 98222544SjkimAcpiDbDeleteObjects ( 99222544Sjkim UINT32 Count, 100222544Sjkim ACPI_OBJECT *Objects) 101222544Sjkim{ 102222544Sjkim UINT32 i; 103222544Sjkim 104222544Sjkim 105222544Sjkim for (i = 0; i < Count; i++) 106222544Sjkim { 107222544Sjkim switch (Objects[i].Type) 108222544Sjkim { 109222544Sjkim case ACPI_TYPE_BUFFER: 110250838Sjkim 111222544Sjkim ACPI_FREE (Objects[i].Buffer.Pointer); 112222544Sjkim break; 113222544Sjkim 114222544Sjkim case ACPI_TYPE_PACKAGE: 115222544Sjkim 116222544Sjkim /* Recursive call to delete package elements */ 117222544Sjkim 118222544Sjkim AcpiDbDeleteObjects (Objects[i].Package.Count, 119222544Sjkim Objects[i].Package.Elements); 120222544Sjkim 121222544Sjkim /* Free the elements array */ 122222544Sjkim 123222544Sjkim ACPI_FREE (Objects[i].Package.Elements); 124222544Sjkim break; 125222544Sjkim 126222544Sjkim default: 127250838Sjkim 128222544Sjkim break; 129222544Sjkim } 130222544Sjkim } 131222544Sjkim} 132222544Sjkim 133222544Sjkim 134222544Sjkim/******************************************************************************* 135222544Sjkim * 13667754Smsmith * FUNCTION: AcpiDbExecuteMethod 13767754Smsmith * 13867754Smsmith * PARAMETERS: Info - Valid info segment 13967754Smsmith * ReturnObj - Where to put return object 14067754Smsmith * 14167754Smsmith * RETURN: Status 14267754Smsmith * 14367754Smsmith * DESCRIPTION: Execute a control method. 14467754Smsmith * 14567754Smsmith ******************************************************************************/ 14667754Smsmith 147151937Sjkimstatic ACPI_STATUS 14867754SmsmithAcpiDbExecuteMethod ( 14991116Smsmith ACPI_DB_METHOD_INFO *Info, 15067754Smsmith ACPI_BUFFER *ReturnObj) 15167754Smsmith{ 15267754Smsmith ACPI_STATUS Status; 15367754Smsmith ACPI_OBJECT_LIST ParamObjects; 154249663Sjkim ACPI_OBJECT Params[ACPI_DEBUGGER_MAX_ARGS + 1]; 15567754Smsmith UINT32 i; 15667754Smsmith 15767754Smsmith 158216471Sjkim ACPI_FUNCTION_TRACE (DbExecuteMethod); 159216471Sjkim 160216471Sjkim 16183174Smsmith if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) 16267754Smsmith { 16367754Smsmith AcpiOsPrintf ("Warning: debug output is not enabled!\n"); 16467754Smsmith } 16567754Smsmith 166249663Sjkim ParamObjects.Count = 0; 167249663Sjkim ParamObjects.Pointer = NULL; 168193267Sjkim 169249663Sjkim /* Pass through any command-line arguments */ 170193267Sjkim 171249663Sjkim if (Info->Args && Info->Args[0]) 17267754Smsmith { 173249663Sjkim /* Get arguments passed on the command line */ 17467754Smsmith 175249663Sjkim for (i = 0; (Info->Args[i] && *(Info->Args[i])); i++) 176193267Sjkim { 177249663Sjkim /* Convert input string (token) to an actual ACPI_OBJECT */ 178222544Sjkim 179249663Sjkim Status = AcpiDbConvertToObject (Info->Types[i], 180249663Sjkim Info->Args[i], &Params[i]); 181249663Sjkim if (ACPI_FAILURE (Status)) 182193267Sjkim { 183249663Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 184249663Sjkim "While parsing method arguments")); 185249663Sjkim goto Cleanup; 186193267Sjkim } 187222544Sjkim } 18867754Smsmith 189249663Sjkim ParamObjects.Count = i; 190222544Sjkim ParamObjects.Pointer = Params; 19167754Smsmith } 19267754Smsmith 19367754Smsmith /* Prepare for a return object of arbitrary size */ 19467754Smsmith 195151937Sjkim ReturnObj->Pointer = AcpiGbl_DbBuffer; 196151937Sjkim ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; 19767754Smsmith 19867754Smsmith /* Do the actual method execution */ 19967754Smsmith 200114237Snjl AcpiGbl_MethodExecuting = TRUE; 201249663Sjkim Status = AcpiEvaluateObject (NULL, Info->Pathname, 202249663Sjkim &ParamObjects, ReturnObj); 20367754Smsmith 20467754Smsmith AcpiGbl_CmSingleStep = FALSE; 20567754Smsmith AcpiGbl_MethodExecuting = FALSE; 20667754Smsmith 207216471Sjkim if (ACPI_FAILURE (Status)) 208216471Sjkim { 209216471Sjkim ACPI_EXCEPTION ((AE_INFO, Status, 210222544Sjkim "while executing %s from debugger", Info->Pathname)); 211216471Sjkim 212216471Sjkim if (Status == AE_BUFFER_OVERFLOW) 213216471Sjkim { 214216471Sjkim ACPI_ERROR ((AE_INFO, 215306536Sjkim "Possible overflow of internal debugger " 216306536Sjkim "buffer (size 0x%X needed 0x%X)", 217216471Sjkim ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length)); 218216471Sjkim } 219216471Sjkim } 220216471Sjkim 221222544SjkimCleanup: 222249663Sjkim AcpiDbDeleteObjects (ParamObjects.Count, Params); 223216471Sjkim return_ACPI_STATUS (Status); 22467754Smsmith} 22567754Smsmith 22667754Smsmith 22767754Smsmith/******************************************************************************* 22867754Smsmith * 22967754Smsmith * FUNCTION: AcpiDbExecuteSetup 23067754Smsmith * 23167754Smsmith * PARAMETERS: Info - Valid method info 23267754Smsmith * 233151937Sjkim * RETURN: None 23467754Smsmith * 23567754Smsmith * DESCRIPTION: Setup info segment prior to method execution 23667754Smsmith * 23767754Smsmith ******************************************************************************/ 23867754Smsmith 239281075Sdimstatic ACPI_STATUS 24067754SmsmithAcpiDbExecuteSetup ( 24199679Siwasaki ACPI_DB_METHOD_INFO *Info) 24267754Smsmith{ 243281075Sdim ACPI_STATUS Status; 24467754Smsmith 245281075Sdim 246281075Sdim ACPI_FUNCTION_NAME (DbExecuteSetup); 247281075Sdim 248281075Sdim 24967754Smsmith /* Catenate the current scope to the supplied name */ 25067754Smsmith 25167754Smsmith Info->Pathname[0] = 0; 25267754Smsmith if ((Info->Name[0] != '\\') && 25367754Smsmith (Info->Name[0] != '/')) 25467754Smsmith { 255281075Sdim if (AcpiUtSafeStrcat (Info->Pathname, sizeof (Info->Pathname), 256281075Sdim AcpiGbl_DbScopeBuf)) 257281075Sdim { 258281075Sdim Status = AE_BUFFER_OVERFLOW; 259281075Sdim goto ErrorExit; 260281075Sdim } 26167754Smsmith } 26267754Smsmith 263281075Sdim if (AcpiUtSafeStrcat (Info->Pathname, sizeof (Info->Pathname), 264281075Sdim Info->Name)) 265281075Sdim { 266281075Sdim Status = AE_BUFFER_OVERFLOW; 267281075Sdim goto ErrorExit; 268281075Sdim } 269281075Sdim 27067754Smsmith AcpiDbPrepNamestring (Info->Pathname); 27167754Smsmith 27291116Smsmith AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 273240716Sjkim AcpiOsPrintf ("Evaluating %s\n", Info->Pathname); 27467754Smsmith 27567754Smsmith if (Info->Flags & EX_SINGLE_STEP) 27667754Smsmith { 27767754Smsmith AcpiGbl_CmSingleStep = TRUE; 27891116Smsmith AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 27967754Smsmith } 28067754Smsmith 28167754Smsmith else 28267754Smsmith { 28367754Smsmith /* No single step, allow redirection to a file */ 28467754Smsmith 28591116Smsmith AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 28667754Smsmith } 287281075Sdim 288281075Sdim return (AE_OK); 289281075Sdim 290281075SdimErrorExit: 291281075Sdim 292281075Sdim ACPI_EXCEPTION ((AE_INFO, Status, "During setup for method execution")); 293281075Sdim return (Status); 29467754Smsmith} 29567754Smsmith 29667754Smsmith 297151937Sjkim#ifdef ACPI_DBG_TRACK_ALLOCATIONS 298167802SjkimUINT32 299151937SjkimAcpiDbGetCacheInfo ( 300151937Sjkim ACPI_MEMORY_LIST *Cache) 301151937Sjkim{ 302151937Sjkim 303151937Sjkim return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); 304151937Sjkim} 305151937Sjkim#endif 306151937Sjkim 30767754Smsmith/******************************************************************************* 30867754Smsmith * 30982367Smsmith * FUNCTION: AcpiDbGetOutstandingAllocations 31082367Smsmith * 31182367Smsmith * PARAMETERS: None 31282367Smsmith * 31382367Smsmith * RETURN: Current global allocation count minus cache entries 31482367Smsmith * 31582367Smsmith * DESCRIPTION: Determine the current number of "outstanding" allocations -- 31682367Smsmith * those allocations that have not been freed and also are not 31782367Smsmith * in one of the various object caches. 31882367Smsmith * 31982367Smsmith ******************************************************************************/ 32082367Smsmith 321151937Sjkimstatic UINT32 32299679SiwasakiAcpiDbGetOutstandingAllocations ( 32399679Siwasaki void) 32482367Smsmith{ 32582367Smsmith UINT32 Outstanding = 0; 32682367Smsmith 32782367Smsmith#ifdef ACPI_DBG_TRACK_ALLOCATIONS 32882367Smsmith 329151937Sjkim Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache); 330151937Sjkim Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache); 331151937Sjkim Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache); 332151937Sjkim Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache); 33382367Smsmith#endif 33482367Smsmith 33582367Smsmith return (Outstanding); 33682367Smsmith} 33782367Smsmith 33882367Smsmith 33982367Smsmith/******************************************************************************* 34082367Smsmith * 341114237Snjl * FUNCTION: AcpiDbExecutionWalk 342114237Snjl * 343114237Snjl * PARAMETERS: WALK_CALLBACK 344114237Snjl * 345114237Snjl * RETURN: Status 346114237Snjl * 347241973Sjkim * DESCRIPTION: Execute a control method. Name is relative to the current 348114237Snjl * scope. 349114237Snjl * 350114237Snjl ******************************************************************************/ 351114237Snjl 352151937Sjkimstatic ACPI_STATUS 353114237SnjlAcpiDbExecutionWalk ( 354114237Snjl ACPI_HANDLE ObjHandle, 355114237Snjl UINT32 NestingLevel, 356114237Snjl void *Context, 357114237Snjl void **ReturnValue) 358114237Snjl{ 359114237Snjl ACPI_OPERAND_OBJECT *ObjDesc; 360114237Snjl ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 361114237Snjl ACPI_BUFFER ReturnObj; 362114237Snjl ACPI_STATUS Status; 363114237Snjl 364114237Snjl 365114237Snjl ObjDesc = AcpiNsGetAttachedObject (Node); 366114237Snjl if (ObjDesc->Method.ParamCount) 367114237Snjl { 368114237Snjl return (AE_OK); 369114237Snjl } 370114237Snjl 371114237Snjl ReturnObj.Pointer = NULL; 372114237Snjl ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 373114237Snjl 374240716Sjkim AcpiNsPrintNodePathname (Node, "Evaluating"); 375114237Snjl 376114237Snjl /* Do the actual method execution */ 377114237Snjl 378114237Snjl AcpiOsPrintf ("\n"); 379114237Snjl AcpiGbl_MethodExecuting = TRUE; 380114237Snjl 381114237Snjl Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); 382114237Snjl 383306536Sjkim AcpiOsPrintf ("Evaluation of [%4.4s] returned %s\n", 384306536Sjkim AcpiUtGetNodeName (Node), 385306536Sjkim AcpiFormatException (Status)); 386306536Sjkim 387114237Snjl AcpiGbl_MethodExecuting = FALSE; 388114237Snjl return (AE_OK); 389114237Snjl} 390114237Snjl 391114237Snjl 392114237Snjl/******************************************************************************* 393114237Snjl * 39467754Smsmith * FUNCTION: AcpiDbExecute 39567754Smsmith * 39667754Smsmith * PARAMETERS: Name - Name of method to execute 39767754Smsmith * Args - Parameters to the method 398306536Sjkim * Types - 39967754Smsmith * Flags - single step/no single step 40067754Smsmith * 401151937Sjkim * RETURN: None 40267754Smsmith * 403241973Sjkim * DESCRIPTION: Execute a control method. Name is relative to the current 40467754Smsmith * scope. 40567754Smsmith * 40667754Smsmith ******************************************************************************/ 40767754Smsmith 40867754Smsmithvoid 40967754SmsmithAcpiDbExecute ( 410114237Snjl char *Name, 411114237Snjl char **Args, 412222544Sjkim ACPI_OBJECT_TYPE *Types, 41367754Smsmith UINT32 Flags) 41467754Smsmith{ 41567754Smsmith ACPI_STATUS Status; 41669450Smsmith ACPI_BUFFER ReturnObj; 417167802Sjkim char *NameString; 41869450Smsmith 419102550Siwasaki#ifdef ACPI_DEBUG_OUTPUT 42067754Smsmith UINT32 PreviousAllocations; 42167754Smsmith UINT32 Allocations; 422306536Sjkim#endif 42367754Smsmith 42467754Smsmith 425306536Sjkim /* 426306536Sjkim * Allow one execution to be performed by debugger or single step 427306536Sjkim * execution will be dead locked by the interpreter mutexes. 428306536Sjkim */ 429306536Sjkim if (AcpiGbl_MethodExecuting) 430306536Sjkim { 431306536Sjkim AcpiOsPrintf ("Only one debugger execution is allowed.\n"); 432306536Sjkim return; 433306536Sjkim } 434306536Sjkim 435306536Sjkim#ifdef ACPI_DEBUG_OUTPUT 43667754Smsmith /* Memory allocation tracking */ 43767754Smsmith 43882367Smsmith PreviousAllocations = AcpiDbGetOutstandingAllocations (); 43969450Smsmith#endif 44067754Smsmith 441114237Snjl if (*Name == '*') 442114237Snjl { 443151937Sjkim (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 444306536Sjkim ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL); 445114237Snjl return; 446114237Snjl } 447114237Snjl else 448114237Snjl { 449306536Sjkim NameString = ACPI_ALLOCATE (strlen (Name) + 1); 450167802Sjkim if (!NameString) 451167802Sjkim { 452167802Sjkim return; 453167802Sjkim } 454167802Sjkim 455306536Sjkim memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 456167802Sjkim 457306536Sjkim strcpy (NameString, Name); 458167802Sjkim AcpiUtStrupr (NameString); 459167802Sjkim AcpiGbl_DbMethodInfo.Name = NameString; 460114237Snjl AcpiGbl_DbMethodInfo.Args = Args; 461222544Sjkim AcpiGbl_DbMethodInfo.Types = Types; 462114237Snjl AcpiGbl_DbMethodInfo.Flags = Flags; 46367754Smsmith 464114237Snjl ReturnObj.Pointer = NULL; 465114237Snjl ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 466100966Siwasaki 467281075Sdim Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 468281075Sdim if (ACPI_FAILURE (Status)) 469281075Sdim { 470281075Sdim ACPI_FREE (NameString); 471281075Sdim return; 472281075Sdim } 473239340Sjkim 474239340Sjkim /* Get the NS node, determines existence also */ 475239340Sjkim 476239340Sjkim Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 477239340Sjkim &AcpiGbl_DbMethodInfo.Method); 478245582Sjkim if (ACPI_SUCCESS (Status)) 479239340Sjkim { 480306536Sjkim Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, 481306536Sjkim &ReturnObj); 482239340Sjkim } 483167802Sjkim ACPI_FREE (NameString); 484114237Snjl } 48567754Smsmith 48682367Smsmith /* 48782367Smsmith * Allow any handlers in separate threads to complete. 48882367Smsmith * (Such as Notify handlers invoked from AML executed above). 48982367Smsmith */ 490202771Sjkim AcpiOsSleep ((UINT64) 10); 49167754Smsmith 492102550Siwasaki#ifdef ACPI_DEBUG_OUTPUT 49369450Smsmith 49467754Smsmith /* Memory allocation tracking */ 49567754Smsmith 49682367Smsmith Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; 49767754Smsmith 49891116Smsmith AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 49967754Smsmith 50067754Smsmith if (Allocations > 0) 50167754Smsmith { 502306536Sjkim AcpiOsPrintf ( 503306536Sjkim "0x%X Outstanding allocations after evaluation of %s\n", 504306536Sjkim Allocations, AcpiGbl_DbMethodInfo.Pathname); 50567754Smsmith } 50669450Smsmith#endif 50767754Smsmith 50867754Smsmith if (ACPI_FAILURE (Status)) 50967754Smsmith { 510240716Sjkim AcpiOsPrintf ("Evaluation of %s failed with status %s\n", 511306536Sjkim AcpiGbl_DbMethodInfo.Pathname, 512306536Sjkim AcpiFormatException (Status)); 51367754Smsmith } 51467754Smsmith else 51567754Smsmith { 51667754Smsmith /* Display a return object, if any */ 51767754Smsmith 51867754Smsmith if (ReturnObj.Length) 51967754Smsmith { 520240716Sjkim AcpiOsPrintf ( 521306536Sjkim "Evaluation of %s returned object %p, " 522306536Sjkim "external buffer length %X\n", 523114237Snjl AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 524104470Siwasaki (UINT32) ReturnObj.Length); 525306536Sjkim 526151937Sjkim AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 527239340Sjkim 528239340Sjkim /* Dump a _PLD buffer if present */ 529239340Sjkim 530239340Sjkim if (ACPI_COMPARE_NAME ((ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 531306536Sjkim AcpiGbl_DbMethodInfo.Method)->Name.Ascii), 532306536Sjkim METHOD_NAME__PLD)) 533239340Sjkim { 534239340Sjkim AcpiDbDumpPldBuffer (ReturnObj.Pointer); 535239340Sjkim } 53667754Smsmith } 537100966Siwasaki else 538100966Siwasaki { 539240716Sjkim AcpiOsPrintf ("No object was returned from evaluation of %s\n", 540100966Siwasaki AcpiGbl_DbMethodInfo.Pathname); 541100966Siwasaki } 54267754Smsmith } 54367754Smsmith 54491116Smsmith AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 54567754Smsmith} 54667754Smsmith 54767754Smsmith 54867754Smsmith/******************************************************************************* 54967754Smsmith * 55067754Smsmith * FUNCTION: AcpiDbMethodThread 55167754Smsmith * 55267754Smsmith * PARAMETERS: Context - Execution info segment 55367754Smsmith * 55467754Smsmith * RETURN: None 55567754Smsmith * 556241973Sjkim * DESCRIPTION: Debugger execute thread. Waits for a command line, then 55767754Smsmith * simply dispatches it. 55867754Smsmith * 55967754Smsmith ******************************************************************************/ 56067754Smsmith 561151937Sjkimstatic void ACPI_SYSTEM_XFACE 56267754SmsmithAcpiDbMethodThread ( 56367754Smsmith void *Context) 56467754Smsmith{ 56567754Smsmith ACPI_STATUS Status; 56691116Smsmith ACPI_DB_METHOD_INFO *Info = Context; 567193267Sjkim ACPI_DB_METHOD_INFO LocalInfo; 56867754Smsmith UINT32 i; 569167802Sjkim UINT8 Allow; 57067754Smsmith ACPI_BUFFER ReturnObj; 57167754Smsmith 57267754Smsmith 573193267Sjkim /* 574193267Sjkim * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. 575193267Sjkim * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads 576193267Sjkim * concurrently. 577193267Sjkim * 578193267Sjkim * Note: The arguments we are passing are used by the ASL test suite 579193267Sjkim * (aslts). Do not change them without updating the tests. 580193267Sjkim */ 581193267Sjkim (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); 582193267Sjkim 583167802Sjkim if (Info->InitArgs) 584167802Sjkim { 585306536Sjkim AcpiDbUint32ToHexString (Info->NumCreated, 586306536Sjkim Info->IndexOfThreadStr); 587306536Sjkim AcpiDbUint32ToHexString ((UINT32) AcpiOsGetThreadId (), 588306536Sjkim Info->IdOfThreadStr); 589167802Sjkim } 590167802Sjkim 591167802Sjkim if (Info->Threads && (Info->NumCreated < Info->NumThreads)) 592167802Sjkim { 593212761Sjkim Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId(); 594167802Sjkim } 595167802Sjkim 596193267Sjkim LocalInfo = *Info; 597193267Sjkim LocalInfo.Args = LocalInfo.Arguments; 598193267Sjkim LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; 599193267Sjkim LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; 600193267Sjkim LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; 601193267Sjkim LocalInfo.Arguments[3] = NULL; 602193267Sjkim 603222544Sjkim LocalInfo.Types = LocalInfo.ArgTypes; 604222544Sjkim 605193267Sjkim (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); 606193267Sjkim 60767754Smsmith for (i = 0; i < Info->NumLoops; i++) 60867754Smsmith { 609193267Sjkim Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); 610117521Snjl if (ACPI_FAILURE (Status)) 61167754Smsmith { 612240716Sjkim AcpiOsPrintf ("%s During evaluation of %s at iteration %X\n", 613117521Snjl AcpiFormatException (Status), Info->Pathname, i); 614127175Snjl if (Status == AE_ABORT_METHOD) 615127175Snjl { 616127175Snjl break; 617127175Snjl } 61867754Smsmith } 619117521Snjl 620167802Sjkim#if 0 621128212Snjl if ((i % 100) == 0) 622117521Snjl { 623306536Sjkim AcpiOsPrintf ("%u loops, Thread 0x%x\n", 624306536Sjkim i, AcpiOsGetThreadId ()); 625117521Snjl } 626117521Snjl 627117521Snjl if (ReturnObj.Length) 628117521Snjl { 629240716Sjkim AcpiOsPrintf ("Evaluation of %s returned object %p Buflen %X\n", 630306536Sjkim Info->Pathname, ReturnObj.Pointer, 631306536Sjkim (UINT32) ReturnObj.Length); 632151937Sjkim AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 633117521Snjl } 634117521Snjl#endif 63567754Smsmith } 63667754Smsmith 63767754Smsmith /* Signal our completion */ 63867754Smsmith 639167802Sjkim Allow = 0; 640306536Sjkim (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 641306536Sjkim 1, ACPI_WAIT_FOREVER); 642167802Sjkim Info->NumCompleted++; 643167802Sjkim 644167802Sjkim if (Info->NumCompleted == Info->NumThreads) 64599679Siwasaki { 646167802Sjkim /* Do signal for main thread once only */ 647167802Sjkim Allow = 1; 64899679Siwasaki } 649167802Sjkim 650193267Sjkim (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); 651167802Sjkim 652167802Sjkim if (Allow) 653167802Sjkim { 654167802Sjkim Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); 655167802Sjkim if (ACPI_FAILURE (Status)) 656167802Sjkim { 657306536Sjkim AcpiOsPrintf ( 658306536Sjkim "Could not signal debugger thread sync semaphore, %s\n", 659167802Sjkim AcpiFormatException (Status)); 660167802Sjkim } 661167802Sjkim } 66267754Smsmith} 66367754Smsmith 66467754Smsmith 66567754Smsmith/******************************************************************************* 66667754Smsmith * 66767754Smsmith * FUNCTION: AcpiDbCreateExecutionThreads 66867754Smsmith * 66967754Smsmith * PARAMETERS: NumThreadsArg - Number of threads to create 67067754Smsmith * NumLoopsArg - Loop count for the thread(s) 67167754Smsmith * MethodNameArg - Control method to execute 67267754Smsmith * 67367754Smsmith * RETURN: None 67467754Smsmith * 67567754Smsmith * DESCRIPTION: Create threads to execute method(s) 67667754Smsmith * 67767754Smsmith ******************************************************************************/ 67867754Smsmith 67967754Smsmithvoid 68067754SmsmithAcpiDbCreateExecutionThreads ( 681114237Snjl char *NumThreadsArg, 682114237Snjl char *NumLoopsArg, 683114237Snjl char *MethodNameArg) 68467754Smsmith{ 68567754Smsmith ACPI_STATUS Status; 68667754Smsmith UINT32 NumThreads; 68767754Smsmith UINT32 NumLoops; 68867754Smsmith UINT32 i; 689167802Sjkim UINT32 Size; 690167802Sjkim ACPI_MUTEX MainThreadGate; 691167802Sjkim ACPI_MUTEX ThreadCompleteGate; 692193267Sjkim ACPI_MUTEX InfoGate; 69367754Smsmith 694193267Sjkim 69567754Smsmith /* Get the arguments */ 69667754Smsmith 697306536Sjkim NumThreads = strtoul (NumThreadsArg, NULL, 0); 698306536Sjkim NumLoops = strtoul (NumLoopsArg, NULL, 0); 69967754Smsmith 70067754Smsmith if (!NumThreads || !NumLoops) 70167754Smsmith { 702151937Sjkim AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", 703151937Sjkim NumThreads, NumLoops); 70467754Smsmith return; 70567754Smsmith } 70667754Smsmith 707167802Sjkim /* 708167802Sjkim * Create the semaphore for synchronization of 709167802Sjkim * the created threads with the main thread. 710167802Sjkim */ 711167802Sjkim Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); 712167802Sjkim if (ACPI_FAILURE (Status)) 713167802Sjkim { 714306536Sjkim AcpiOsPrintf ("Could not create semaphore for " 715306536Sjkim "synchronization with the main thread, %s\n", 716167802Sjkim AcpiFormatException (Status)); 717167802Sjkim return; 718167802Sjkim } 71967754Smsmith 720167802Sjkim /* 721167802Sjkim * Create the semaphore for synchronization 722167802Sjkim * between the created threads. 723167802Sjkim */ 724167802Sjkim Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); 72567754Smsmith if (ACPI_FAILURE (Status)) 72667754Smsmith { 727306536Sjkim AcpiOsPrintf ("Could not create semaphore for " 728306536Sjkim "synchronization between the created threads, %s\n", 729151937Sjkim AcpiFormatException (Status)); 730306536Sjkim 731167802Sjkim (void) AcpiOsDeleteSemaphore (MainThreadGate); 73267754Smsmith return; 73367754Smsmith } 73467754Smsmith 735193267Sjkim Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); 736193267Sjkim if (ACPI_FAILURE (Status)) 737193267Sjkim { 738306536Sjkim AcpiOsPrintf ("Could not create semaphore for " 739306536Sjkim "synchronization of AcpiGbl_DbMethodInfo, %s\n", 740193267Sjkim AcpiFormatException (Status)); 741306536Sjkim 742193267Sjkim (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 743193267Sjkim (void) AcpiOsDeleteSemaphore (MainThreadGate); 744193267Sjkim return; 745193267Sjkim } 746193267Sjkim 747306536Sjkim memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 748167802Sjkim 749167802Sjkim /* Array to store IDs of threads */ 750167802Sjkim 751167802Sjkim AcpiGbl_DbMethodInfo.NumThreads = NumThreads; 752212761Sjkim Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads; 753306536Sjkim 754212761Sjkim AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size); 755167802Sjkim if (AcpiGbl_DbMethodInfo.Threads == NULL) 756167802Sjkim { 757167802Sjkim AcpiOsPrintf ("No memory for thread IDs array\n"); 758167802Sjkim (void) AcpiOsDeleteSemaphore (MainThreadGate); 759167802Sjkim (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 760193267Sjkim (void) AcpiOsDeleteSemaphore (InfoGate); 761167802Sjkim return; 762167802Sjkim } 763306536Sjkim memset (AcpiGbl_DbMethodInfo.Threads, 0, Size); 764167802Sjkim 76567754Smsmith /* Setup the context to be passed to each thread */ 76667754Smsmith 76783174Smsmith AcpiGbl_DbMethodInfo.Name = MethodNameArg; 76883174Smsmith AcpiGbl_DbMethodInfo.Flags = 0; 76983174Smsmith AcpiGbl_DbMethodInfo.NumLoops = NumLoops; 770167802Sjkim AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; 771167802Sjkim AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; 772193267Sjkim AcpiGbl_DbMethodInfo.InfoGate = InfoGate; 77367754Smsmith 774167802Sjkim /* Init arguments to be passed to method */ 775167802Sjkim 776167802Sjkim AcpiGbl_DbMethodInfo.InitArgs = 1; 777167802Sjkim AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 778167802Sjkim AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; 779167802Sjkim AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; 780167802Sjkim AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; 781167802Sjkim AcpiGbl_DbMethodInfo.Arguments[3] = NULL; 782222544Sjkim 783222544Sjkim AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes; 784222544Sjkim AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER; 785222544Sjkim AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER; 786222544Sjkim AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER; 787222544Sjkim 788237412Sjkim AcpiDbUint32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); 789167802Sjkim 790281075Sdim Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 791281075Sdim if (ACPI_FAILURE (Status)) 792281075Sdim { 793281075Sdim goto CleanupAndExit; 794281075Sdim } 79567754Smsmith 796239340Sjkim /* Get the NS node, determines existence also */ 797239340Sjkim 798239340Sjkim Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 799239340Sjkim &AcpiGbl_DbMethodInfo.Method); 800239340Sjkim if (ACPI_FAILURE (Status)) 801239340Sjkim { 802239340Sjkim AcpiOsPrintf ("%s Could not get handle for %s\n", 803239340Sjkim AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname); 804239340Sjkim goto CleanupAndExit; 805239340Sjkim } 806239340Sjkim 80767754Smsmith /* Create the threads */ 80867754Smsmith 809151937Sjkim AcpiOsPrintf ("Creating %X threads to execute %X times each\n", 810151937Sjkim NumThreads, NumLoops); 81167754Smsmith 81267754Smsmith for (i = 0; i < (NumThreads); i++) 81367754Smsmith { 814306536Sjkim Status = AcpiOsExecute (OSL_DEBUGGER_EXEC_THREAD, AcpiDbMethodThread, 815151937Sjkim &AcpiGbl_DbMethodInfo); 81699679Siwasaki if (ACPI_FAILURE (Status)) 81799679Siwasaki { 81899679Siwasaki break; 81999679Siwasaki } 82067754Smsmith } 82167754Smsmith 82267754Smsmith /* Wait for all threads to complete */ 82367754Smsmith 824193267Sjkim (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); 82567754Smsmith 826167802Sjkim AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 827167802Sjkim AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); 828167802Sjkim AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 829167802Sjkim 830239340SjkimCleanupAndExit: 831239340Sjkim 83267754Smsmith /* Cleanup and exit */ 83367754Smsmith 834167802Sjkim (void) AcpiOsDeleteSemaphore (MainThreadGate); 835167802Sjkim (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 836193267Sjkim (void) AcpiOsDeleteSemaphore (InfoGate); 83767754Smsmith 838167802Sjkim AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); 839167802Sjkim AcpiGbl_DbMethodInfo.Threads = NULL; 84067754Smsmith} 841