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 - 2021, 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 #ifdef ACPI_DEBUGGER 158 159 #define _COMPONENT ACPI_CA_DEBUGGER 160 ACPI_MODULE_NAME ("dbexec") 161 162 163 static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; 164 165 /* Local prototypes */ 166 167 static ACPI_STATUS 168 AcpiDbExecuteMethod ( 169 ACPI_DB_METHOD_INFO *Info, 170 ACPI_BUFFER *ReturnObj); 171 172 static ACPI_STATUS 173 AcpiDbExecuteSetup ( 174 ACPI_DB_METHOD_INFO *Info); 175 176 static UINT32 177 AcpiDbGetOutstandingAllocations ( 178 void); 179 180 static void ACPI_SYSTEM_XFACE 181 AcpiDbMethodThread ( 182 void *Context); 183 184 static ACPI_STATUS 185 AcpiDbExecutionWalk ( 186 ACPI_HANDLE ObjHandle, 187 UINT32 NestingLevel, 188 void *Context, 189 void **ReturnValue); 190 191 static void ACPI_SYSTEM_XFACE 192 AcpiDbSingleExecutionThread ( 193 void *Context); 194 195 196 /******************************************************************************* 197 * 198 * FUNCTION: AcpiDbDeleteObjects 199 * 200 * PARAMETERS: Count - Count of objects in the list 201 * Objects - Array of ACPI_OBJECTs to be deleted 202 * 203 * RETURN: None 204 * 205 * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested 206 * packages via recursion. 207 * 208 ******************************************************************************/ 209 210 void 211 AcpiDbDeleteObjects ( 212 UINT32 Count, 213 ACPI_OBJECT *Objects) 214 { 215 UINT32 i; 216 217 218 for (i = 0; i < Count; i++) 219 { 220 switch (Objects[i].Type) 221 { 222 case ACPI_TYPE_BUFFER: 223 224 ACPI_FREE (Objects[i].Buffer.Pointer); 225 break; 226 227 case ACPI_TYPE_PACKAGE: 228 229 /* Recursive call to delete package elements */ 230 231 AcpiDbDeleteObjects (Objects[i].Package.Count, 232 Objects[i].Package.Elements); 233 234 /* Free the elements array */ 235 236 ACPI_FREE (Objects[i].Package.Elements); 237 break; 238 239 default: 240 241 break; 242 } 243 } 244 } 245 246 247 /******************************************************************************* 248 * 249 * FUNCTION: AcpiDbExecuteMethod 250 * 251 * PARAMETERS: Info - Valid info segment 252 * ReturnObj - Where to put return object 253 * 254 * RETURN: Status 255 * 256 * DESCRIPTION: Execute a control method. Used to evaluate objects via the 257 * "EXECUTE" or "EVALUATE" commands. 258 * 259 ******************************************************************************/ 260 261 static ACPI_STATUS 262 AcpiDbExecuteMethod ( 263 ACPI_DB_METHOD_INFO *Info, 264 ACPI_BUFFER *ReturnObj) 265 { 266 ACPI_STATUS Status; 267 ACPI_OBJECT_LIST ParamObjects; 268 ACPI_OBJECT Params[ACPI_DEBUGGER_MAX_ARGS + 1]; 269 UINT32 i; 270 271 272 ACPI_FUNCTION_TRACE (DbExecuteMethod); 273 274 275 if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) 276 { 277 AcpiOsPrintf ("Warning: debug output is not enabled!\n"); 278 } 279 280 ParamObjects.Count = 0; 281 ParamObjects.Pointer = NULL; 282 283 /* Pass through any command-line arguments */ 284 285 if (Info->Args && Info->Args[0]) 286 { 287 /* Get arguments passed on the command line */ 288 289 for (i = 0; (Info->Args[i] && *(Info->Args[i])); i++) 290 { 291 /* Convert input string (token) to an actual ACPI_OBJECT */ 292 293 Status = AcpiDbConvertToObject (Info->Types[i], 294 Info->Args[i], &Params[i]); 295 if (ACPI_FAILURE (Status)) 296 { 297 ACPI_EXCEPTION ((AE_INFO, Status, 298 "While parsing method arguments")); 299 goto Cleanup; 300 } 301 } 302 303 ParamObjects.Count = i; 304 ParamObjects.Pointer = Params; 305 } 306 307 /* Prepare for a return object of arbitrary size */ 308 309 ReturnObj->Pointer = AcpiGbl_DbBuffer; 310 ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; 311 312 /* Do the actual method execution */ 313 314 AcpiGbl_MethodExecuting = TRUE; 315 Status = AcpiEvaluateObject (NULL, Info->Pathname, 316 &ParamObjects, ReturnObj); 317 318 AcpiGbl_CmSingleStep = FALSE; 319 AcpiGbl_MethodExecuting = FALSE; 320 321 if (ACPI_FAILURE (Status)) 322 { 323 if ((Status == AE_ABORT_METHOD) || AcpiGbl_AbortMethod) 324 { 325 /* Clear the abort and fall back to the debugger prompt */ 326 327 ACPI_EXCEPTION ((AE_INFO, Status, 328 "Aborting top-level method")); 329 330 AcpiGbl_AbortMethod = FALSE; 331 Status = AE_OK; 332 goto Cleanup; 333 } 334 335 ACPI_EXCEPTION ((AE_INFO, Status, 336 "while executing %s from AML Debugger", Info->Pathname)); 337 338 if (Status == AE_BUFFER_OVERFLOW) 339 { 340 ACPI_ERROR ((AE_INFO, 341 "Possible buffer overflow within AML Debugger " 342 "buffer (size 0x%X needed 0x%X)", 343 ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length)); 344 } 345 } 346 347 Cleanup: 348 AcpiDbDeleteObjects (ParamObjects.Count, Params); 349 return_ACPI_STATUS (Status); 350 } 351 352 353 /******************************************************************************* 354 * 355 * FUNCTION: AcpiDbExecuteSetup 356 * 357 * PARAMETERS: Info - Valid method info 358 * 359 * RETURN: None 360 * 361 * DESCRIPTION: Setup info segment prior to method execution 362 * 363 ******************************************************************************/ 364 365 static ACPI_STATUS 366 AcpiDbExecuteSetup ( 367 ACPI_DB_METHOD_INFO *Info) 368 { 369 ACPI_STATUS Status; 370 371 372 ACPI_FUNCTION_NAME (DbExecuteSetup); 373 374 375 /* Concatenate the current scope to the supplied name */ 376 377 Info->Pathname[0] = 0; 378 if ((Info->Name[0] != '\\') && 379 (Info->Name[0] != '/')) 380 { 381 if (AcpiUtSafeStrcat (Info->Pathname, sizeof (Info->Pathname), 382 AcpiGbl_DbScopeBuf)) 383 { 384 Status = AE_BUFFER_OVERFLOW; 385 goto ErrorExit; 386 } 387 } 388 389 if (AcpiUtSafeStrcat (Info->Pathname, sizeof (Info->Pathname), 390 Info->Name)) 391 { 392 Status = AE_BUFFER_OVERFLOW; 393 goto ErrorExit; 394 } 395 396 AcpiDbPrepNamestring (Info->Pathname); 397 398 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 399 AcpiOsPrintf ("Evaluating %s\n", Info->Pathname); 400 401 if (Info->Flags & EX_SINGLE_STEP) 402 { 403 AcpiGbl_CmSingleStep = TRUE; 404 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 405 } 406 407 else 408 { 409 /* No single step, allow redirection to a file */ 410 411 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 412 } 413 414 return (AE_OK); 415 416 ErrorExit: 417 418 ACPI_EXCEPTION ((AE_INFO, Status, "During setup for method execution")); 419 return (Status); 420 } 421 422 423 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 424 UINT32 425 AcpiDbGetCacheInfo ( 426 ACPI_MEMORY_LIST *Cache) 427 { 428 429 return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); 430 } 431 #endif 432 433 /******************************************************************************* 434 * 435 * FUNCTION: AcpiDbGetOutstandingAllocations 436 * 437 * PARAMETERS: None 438 * 439 * RETURN: Current global allocation count minus cache entries 440 * 441 * DESCRIPTION: Determine the current number of "outstanding" allocations -- 442 * those allocations that have not been freed and also are not 443 * in one of the various object caches. 444 * 445 ******************************************************************************/ 446 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 464 465 /******************************************************************************* 466 * 467 * FUNCTION: AcpiDbExecutionWalk 468 * 469 * PARAMETERS: WALK_CALLBACK 470 * 471 * RETURN: Status 472 * 473 * DESCRIPTION: Execute a control method. Name is relative to the current 474 * scope. 475 * 476 ******************************************************************************/ 477 478 static ACPI_STATUS 479 AcpiDbExecutionWalk ( 480 ACPI_HANDLE ObjHandle, 481 UINT32 NestingLevel, 482 void *Context, 483 void **ReturnValue) 484 { 485 ACPI_OPERAND_OBJECT *ObjDesc; 486 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 487 ACPI_BUFFER ReturnObj; 488 ACPI_STATUS Status; 489 490 491 ObjDesc = AcpiNsGetAttachedObject (Node); 492 if (ObjDesc->Method.ParamCount) 493 { 494 return (AE_OK); 495 } 496 497 ReturnObj.Pointer = NULL; 498 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 499 500 AcpiNsPrintNodePathname (Node, "Evaluating"); 501 502 /* Do the actual method execution */ 503 504 AcpiOsPrintf ("\n"); 505 AcpiGbl_MethodExecuting = TRUE; 506 507 Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); 508 509 AcpiGbl_MethodExecuting = FALSE; 510 511 AcpiOsPrintf ("Evaluation of [%4.4s] returned %s\n", 512 AcpiUtGetNodeName (Node), 513 AcpiFormatException (Status)); 514 515 return (AE_OK); 516 } 517 518 519 /******************************************************************************* 520 * 521 * FUNCTION: AcpiDbExecute 522 * 523 * PARAMETERS: Name - Name of method to execute 524 * Args - Parameters to the method 525 * Types - 526 * Flags - single step/no single step 527 * 528 * RETURN: None 529 * 530 * DESCRIPTION: Execute a control method. Name is relative to the current 531 * scope. Function used for the "EXECUTE", "EVALUATE", and 532 * "ALL" commands 533 * 534 ******************************************************************************/ 535 536 void 537 AcpiDbExecute ( 538 char *Name, 539 char **Args, 540 ACPI_OBJECT_TYPE *Types, 541 UINT32 Flags) 542 { 543 ACPI_STATUS Status; 544 ACPI_BUFFER ReturnObj; 545 char *NameString; 546 547 #ifdef ACPI_DEBUG_OUTPUT 548 UINT32 PreviousAllocations; 549 UINT32 Allocations; 550 #endif 551 552 553 /* 554 * Allow one execution to be performed by debugger or single step 555 * execution will be dead locked by the interpreter mutexes. 556 */ 557 if (AcpiGbl_MethodExecuting) 558 { 559 AcpiOsPrintf ("Only one debugger execution is allowed.\n"); 560 return; 561 } 562 563 #ifdef ACPI_DEBUG_OUTPUT 564 /* Memory allocation tracking */ 565 566 PreviousAllocations = AcpiDbGetOutstandingAllocations (); 567 #endif 568 569 if (*Name == '*') 570 { 571 (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 572 ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL); 573 return; 574 } 575 576 if ((Flags & EX_ALL) && (strlen (Name) > 4)) 577 { 578 AcpiOsPrintf ("Input name (%s) must be a 4-char NameSeg\n", Name); 579 return; 580 } 581 582 NameString = ACPI_ALLOCATE (strlen (Name) + 1); 583 if (!NameString) 584 { 585 return; 586 } 587 588 memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 589 strcpy (NameString, Name); 590 AcpiUtStrupr (NameString); 591 592 /* Subcommand to Execute all predefined names in the namespace */ 593 594 if (!strncmp (NameString, "PREDEF", 6)) 595 { 596 AcpiDbEvaluatePredefinedNames (); 597 ACPI_FREE (NameString); 598 return; 599 } 600 601 /* Command (ALL <nameseg>) to execute all methods of a particular name */ 602 603 else if (Flags & EX_ALL) 604 { 605 AcpiGbl_DbMethodInfo.Name = NameString; 606 ReturnObj.Pointer = NULL; 607 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 608 AcpiDbEvaluateAll (NameString); 609 ACPI_FREE (NameString); 610 return; 611 } 612 else 613 { 614 AcpiGbl_DbMethodInfo.Name = NameString; 615 AcpiGbl_DbMethodInfo.Args = Args; 616 AcpiGbl_DbMethodInfo.Types = Types; 617 AcpiGbl_DbMethodInfo.Flags = Flags; 618 619 ReturnObj.Pointer = NULL; 620 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 621 } 622 623 Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 624 if (ACPI_FAILURE (Status)) 625 { 626 ACPI_FREE (NameString); 627 return; 628 } 629 630 /* Get the NS node, determines existence also */ 631 632 Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 633 &AcpiGbl_DbMethodInfo.Method); 634 if (ACPI_SUCCESS (Status)) 635 { 636 Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, 637 &ReturnObj); 638 } 639 ACPI_FREE (NameString); 640 641 /* 642 * Allow any handlers in separate threads to complete. 643 * (Such as Notify handlers invoked from AML executed above). 644 */ 645 AcpiOsSleep ((UINT64) 10); 646 647 #ifdef ACPI_DEBUG_OUTPUT 648 649 /* Memory allocation tracking */ 650 651 Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; 652 653 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 654 655 if (Allocations > 0) 656 { 657 AcpiOsPrintf ( 658 "0x%X Outstanding allocations after evaluation of %s\n", 659 Allocations, AcpiGbl_DbMethodInfo.Pathname); 660 } 661 #endif 662 663 if (ACPI_FAILURE (Status)) 664 { 665 AcpiOsPrintf ("Evaluation of %s failed with status %s\n", 666 AcpiGbl_DbMethodInfo.Pathname, 667 AcpiFormatException (Status)); 668 } 669 else 670 { 671 /* Display a return object, if any */ 672 673 if (ReturnObj.Length) 674 { 675 AcpiOsPrintf ( 676 "Evaluation of %s returned object %p, " 677 "external buffer length %X\n", 678 AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 679 (UINT32) ReturnObj.Length); 680 681 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 682 AcpiOsPrintf ("\n"); 683 684 /* Dump a _PLD buffer if present */ 685 686 if (ACPI_COMPARE_NAMESEG ((ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 687 AcpiGbl_DbMethodInfo.Method)->Name.Ascii), 688 METHOD_NAME__PLD)) 689 { 690 AcpiDbDumpPldBuffer (ReturnObj.Pointer); 691 } 692 } 693 else 694 { 695 AcpiOsPrintf ("No object was returned from evaluation of %s\n", 696 AcpiGbl_DbMethodInfo.Pathname); 697 } 698 } 699 700 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 701 } 702 703 704 /******************************************************************************* 705 * 706 * FUNCTION: AcpiDbMethodThread 707 * 708 * PARAMETERS: Context - Execution info segment 709 * 710 * RETURN: None 711 * 712 * DESCRIPTION: Debugger execute thread. Waits for a command line, then 713 * simply dispatches it. 714 * 715 ******************************************************************************/ 716 717 static void ACPI_SYSTEM_XFACE 718 AcpiDbMethodThread ( 719 void *Context) 720 { 721 ACPI_STATUS Status; 722 ACPI_DB_METHOD_INFO *Info = Context; 723 ACPI_DB_METHOD_INFO LocalInfo; 724 UINT32 i; 725 UINT8 Allow; 726 ACPI_BUFFER ReturnObj; 727 728 729 /* 730 * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. 731 * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads 732 * concurrently. 733 * 734 * Note: The arguments we are passing are used by the ASL test suite 735 * (aslts). Do not change them without updating the tests. 736 */ 737 (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); 738 739 if (Info->InitArgs) 740 { 741 AcpiDbUint32ToHexString (Info->NumCreated, 742 Info->IndexOfThreadStr); 743 AcpiDbUint32ToHexString ((UINT32) AcpiOsGetThreadId (), 744 Info->IdOfThreadStr); 745 } 746 747 if (Info->Threads && (Info->NumCreated < Info->NumThreads)) 748 { 749 Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId(); 750 } 751 752 LocalInfo = *Info; 753 LocalInfo.Args = LocalInfo.Arguments; 754 LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; 755 LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; 756 LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; 757 LocalInfo.Arguments[3] = NULL; 758 759 LocalInfo.Types = LocalInfo.ArgTypes; 760 761 (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); 762 763 for (i = 0; i < Info->NumLoops; i++) 764 { 765 Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); 766 if (ACPI_FAILURE (Status)) 767 { 768 AcpiOsPrintf ("%s During evaluation of %s at iteration %X\n", 769 AcpiFormatException (Status), Info->Pathname, i); 770 if (Status == AE_ABORT_METHOD) 771 { 772 break; 773 } 774 } 775 776 #if 0 777 if ((i % 100) == 0) 778 { 779 AcpiOsPrintf ("%u loops, Thread 0x%x\n", 780 i, AcpiOsGetThreadId ()); 781 } 782 783 if (ReturnObj.Length) 784 { 785 AcpiOsPrintf ("Evaluation of %s returned object %p Buflen %X\n", 786 Info->Pathname, ReturnObj.Pointer, 787 (UINT32) ReturnObj.Length); 788 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 789 } 790 #endif 791 } 792 793 /* Signal our completion */ 794 795 Allow = 0; 796 (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 797 1, ACPI_WAIT_FOREVER); 798 Info->NumCompleted++; 799 800 if (Info->NumCompleted == Info->NumThreads) 801 { 802 /* Do signal for main thread once only */ 803 Allow = 1; 804 } 805 806 (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); 807 808 if (Allow) 809 { 810 Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); 811 if (ACPI_FAILURE (Status)) 812 { 813 AcpiOsPrintf ( 814 "Could not signal debugger thread sync semaphore, %s\n", 815 AcpiFormatException (Status)); 816 } 817 } 818 } 819 820 821 /******************************************************************************* 822 * 823 * FUNCTION: AcpiDbSingleExecutionThread 824 * 825 * PARAMETERS: Context - Method info struct 826 * 827 * RETURN: None 828 * 829 * DESCRIPTION: Create one thread and execute a method 830 * 831 ******************************************************************************/ 832 833 static void ACPI_SYSTEM_XFACE 834 AcpiDbSingleExecutionThread ( 835 void *Context) 836 { 837 ACPI_DB_METHOD_INFO *Info = Context; 838 ACPI_STATUS Status; 839 ACPI_BUFFER ReturnObj; 840 841 842 AcpiOsPrintf ("\n"); 843 844 Status = AcpiDbExecuteMethod (Info, &ReturnObj); 845 if (ACPI_FAILURE (Status)) 846 { 847 AcpiOsPrintf ("%s During evaluation of %s\n", 848 AcpiFormatException (Status), Info->Pathname); 849 return; 850 } 851 852 /* Display a return object, if any */ 853 854 if (ReturnObj.Length) 855 { 856 AcpiOsPrintf ("Evaluation of %s returned object %p, " 857 "external buffer length %X\n", 858 AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 859 (UINT32) ReturnObj.Length); 860 861 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 862 } 863 864 AcpiOsPrintf ("\nBackground thread completed\n%c ", 865 ACPI_DEBUGGER_COMMAND_PROMPT); 866 } 867 868 869 /******************************************************************************* 870 * 871 * FUNCTION: AcpiDbCreateExecutionThread 872 * 873 * PARAMETERS: MethodNameArg - Control method to execute 874 * Arguments - Array of arguments to the method 875 * Types - Corresponding array of object types 876 * 877 * RETURN: None 878 * 879 * DESCRIPTION: Create a single thread to evaluate a namespace object. Handles 880 * arguments passed on command line for control methods. 881 * 882 ******************************************************************************/ 883 884 void 885 AcpiDbCreateExecutionThread ( 886 char *MethodNameArg, 887 char **Arguments, 888 ACPI_OBJECT_TYPE *Types) 889 { 890 ACPI_STATUS Status; 891 UINT32 i; 892 893 894 memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 895 AcpiGbl_DbMethodInfo.Name = MethodNameArg; 896 AcpiGbl_DbMethodInfo.InitArgs = 1; 897 AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 898 AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes; 899 900 /* Setup method arguments, up to 7 (0-6) */ 901 902 for (i = 0; (i < ACPI_METHOD_NUM_ARGS) && *Arguments; i++) 903 { 904 AcpiGbl_DbMethodInfo.Arguments[i] = *Arguments; 905 Arguments++; 906 907 AcpiGbl_DbMethodInfo.ArgTypes[i] = *Types; 908 Types++; 909 } 910 911 Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 912 if (ACPI_FAILURE (Status)) 913 { 914 return; 915 } 916 917 /* Get the NS node, determines existence also */ 918 919 Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 920 &AcpiGbl_DbMethodInfo.Method); 921 if (ACPI_FAILURE (Status)) 922 { 923 AcpiOsPrintf ("%s Could not get handle for %s\n", 924 AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname); 925 return; 926 } 927 928 Status = AcpiOsExecute (OSL_DEBUGGER_EXEC_THREAD, 929 AcpiDbSingleExecutionThread, &AcpiGbl_DbMethodInfo); 930 if (ACPI_FAILURE (Status)) 931 { 932 return; 933 } 934 935 AcpiOsPrintf ("\nBackground thread started\n"); 936 } 937 938 939 /******************************************************************************* 940 * 941 * FUNCTION: AcpiDbCreateExecutionThreads 942 * 943 * PARAMETERS: NumThreadsArg - Number of threads to create 944 * NumLoopsArg - Loop count for the thread(s) 945 * MethodNameArg - Control method to execute 946 * 947 * RETURN: None 948 * 949 * DESCRIPTION: Create threads to execute method(s) 950 * 951 ******************************************************************************/ 952 953 void 954 AcpiDbCreateExecutionThreads ( 955 char *NumThreadsArg, 956 char *NumLoopsArg, 957 char *MethodNameArg) 958 { 959 ACPI_STATUS Status; 960 UINT32 NumThreads; 961 UINT32 NumLoops; 962 UINT32 i; 963 UINT32 Size; 964 ACPI_MUTEX MainThreadGate; 965 ACPI_MUTEX ThreadCompleteGate; 966 ACPI_MUTEX InfoGate; 967 968 969 /* Get the arguments */ 970 971 NumThreads = strtoul (NumThreadsArg, NULL, 0); 972 NumLoops = strtoul (NumLoopsArg, NULL, 0); 973 974 if (!NumThreads || !NumLoops) 975 { 976 AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", 977 NumThreads, NumLoops); 978 return; 979 } 980 981 /* 982 * Create the semaphore for synchronization of 983 * the created threads with the main thread. 984 */ 985 Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); 986 if (ACPI_FAILURE (Status)) 987 { 988 AcpiOsPrintf ("Could not create semaphore for " 989 "synchronization with the main thread, %s\n", 990 AcpiFormatException (Status)); 991 return; 992 } 993 994 /* 995 * Create the semaphore for synchronization 996 * between the created threads. 997 */ 998 Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); 999 if (ACPI_FAILURE (Status)) 1000 { 1001 AcpiOsPrintf ("Could not create semaphore for " 1002 "synchronization between the created threads, %s\n", 1003 AcpiFormatException (Status)); 1004 1005 (void) AcpiOsDeleteSemaphore (MainThreadGate); 1006 return; 1007 } 1008 1009 Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); 1010 if (ACPI_FAILURE (Status)) 1011 { 1012 AcpiOsPrintf ("Could not create semaphore for " 1013 "synchronization of AcpiGbl_DbMethodInfo, %s\n", 1014 AcpiFormatException (Status)); 1015 1016 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 1017 (void) AcpiOsDeleteSemaphore (MainThreadGate); 1018 return; 1019 } 1020 1021 memset (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 1022 1023 /* Array to store IDs of threads */ 1024 1025 AcpiGbl_DbMethodInfo.NumThreads = NumThreads; 1026 Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads; 1027 1028 AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size); 1029 if (AcpiGbl_DbMethodInfo.Threads == NULL) 1030 { 1031 AcpiOsPrintf ("No memory for thread IDs array\n"); 1032 (void) AcpiOsDeleteSemaphore (MainThreadGate); 1033 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 1034 (void) AcpiOsDeleteSemaphore (InfoGate); 1035 return; 1036 } 1037 memset (AcpiGbl_DbMethodInfo.Threads, 0, Size); 1038 1039 /* Setup the context to be passed to each thread */ 1040 1041 AcpiGbl_DbMethodInfo.Name = MethodNameArg; 1042 AcpiGbl_DbMethodInfo.Flags = 0; 1043 AcpiGbl_DbMethodInfo.NumLoops = NumLoops; 1044 AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; 1045 AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; 1046 AcpiGbl_DbMethodInfo.InfoGate = InfoGate; 1047 1048 /* Init arguments to be passed to method */ 1049 1050 AcpiGbl_DbMethodInfo.InitArgs = 1; 1051 AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 1052 AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; 1053 AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; 1054 AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; 1055 AcpiGbl_DbMethodInfo.Arguments[3] = NULL; 1056 1057 AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes; 1058 AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER; 1059 AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER; 1060 AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER; 1061 1062 AcpiDbUint32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); 1063 1064 Status = AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 1065 if (ACPI_FAILURE (Status)) 1066 { 1067 goto CleanupAndExit; 1068 } 1069 1070 /* Get the NS node, determines existence also */ 1071 1072 Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 1073 &AcpiGbl_DbMethodInfo.Method); 1074 if (ACPI_FAILURE (Status)) 1075 { 1076 AcpiOsPrintf ("%s Could not get handle for %s\n", 1077 AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname); 1078 goto CleanupAndExit; 1079 } 1080 1081 /* Create the threads */ 1082 1083 AcpiOsPrintf ("Creating %X threads to execute %X times each\n", 1084 NumThreads, NumLoops); 1085 1086 for (i = 0; i < (NumThreads); i++) 1087 { 1088 Status = AcpiOsExecute (OSL_DEBUGGER_EXEC_THREAD, AcpiDbMethodThread, 1089 &AcpiGbl_DbMethodInfo); 1090 if (ACPI_FAILURE (Status)) 1091 { 1092 break; 1093 } 1094 } 1095 1096 /* Wait for all threads to complete */ 1097 1098 (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); 1099 1100 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 1101 AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); 1102 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 1103 1104 CleanupAndExit: 1105 1106 /* Cleanup and exit */ 1107 1108 (void) AcpiOsDeleteSemaphore (MainThreadGate); 1109 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 1110 (void) AcpiOsDeleteSemaphore (InfoGate); 1111 1112 AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); 1113 AcpiGbl_DbMethodInfo.Threads = NULL; 1114 } 1115 1116 #endif /* ACPI_DEBUGGER */ 1117