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