1 /******************************************************************************* 2 * 3 * Module Name: dbexec - debugger control method execution 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2012, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 45 #include <contrib/dev/acpica/include/acpi.h> 46 #include <contrib/dev/acpica/include/accommon.h> 47 #include <contrib/dev/acpica/include/acdebug.h> 48 #include <contrib/dev/acpica/include/acnamesp.h> 49 50 #ifdef ACPI_DEBUGGER 51 52 #define _COMPONENT ACPI_CA_DEBUGGER 53 ACPI_MODULE_NAME ("dbexec") 54 55 56 static ACPI_DB_METHOD_INFO AcpiGbl_DbMethodInfo; 57 #define DB_DEFAULT_PKG_ELEMENTS 33 58 59 /* Local prototypes */ 60 61 static ACPI_STATUS 62 AcpiDbExecuteMethod ( 63 ACPI_DB_METHOD_INFO *Info, 64 ACPI_BUFFER *ReturnObj); 65 66 static void 67 AcpiDbExecuteSetup ( 68 ACPI_DB_METHOD_INFO *Info); 69 70 static UINT32 71 AcpiDbGetOutstandingAllocations ( 72 void); 73 74 static void ACPI_SYSTEM_XFACE 75 AcpiDbMethodThread ( 76 void *Context); 77 78 static ACPI_STATUS 79 AcpiDbExecutionWalk ( 80 ACPI_HANDLE ObjHandle, 81 UINT32 NestingLevel, 82 void *Context, 83 void **ReturnValue); 84 85 static ACPI_STATUS 86 AcpiDbHexCharToValue ( 87 int HexChar, 88 UINT8 *ReturnValue); 89 90 static ACPI_STATUS 91 AcpiDbConvertToPackage ( 92 char *String, 93 ACPI_OBJECT *Object); 94 95 static ACPI_STATUS 96 AcpiDbConvertToObject ( 97 ACPI_OBJECT_TYPE Type, 98 char *String, 99 ACPI_OBJECT *Object); 100 101 static void 102 AcpiDbDeleteObjects ( 103 UINT32 Count, 104 ACPI_OBJECT *Objects); 105 106 107 static UINT8 * 108 AcpiDbEncodePldBuffer ( 109 ACPI_PLD_INFO *PldInfo); 110 111 static void 112 AcpiDbDumpPldBuffer ( 113 ACPI_OBJECT *ObjDesc); 114 115 116 /******************************************************************************* 117 * 118 * FUNCTION: AcpiDbHexCharToValue 119 * 120 * PARAMETERS: HexChar - Ascii Hex digit, 0-9|a-f|A-F 121 * ReturnValue - Where the converted value is returned 122 * 123 * RETURN: Status 124 * 125 * DESCRIPTION: Convert a single hex character to a 4-bit number (0-16). 126 * 127 ******************************************************************************/ 128 129 static ACPI_STATUS 130 AcpiDbHexCharToValue ( 131 int HexChar, 132 UINT8 *ReturnValue) 133 { 134 UINT8 Value; 135 136 137 /* Digit must be ascii [0-9a-fA-F] */ 138 139 if (!ACPI_IS_XDIGIT (HexChar)) 140 { 141 return (AE_BAD_HEX_CONSTANT); 142 } 143 144 if (HexChar <= 0x39) 145 { 146 Value = (UINT8) (HexChar - 0x30); 147 } 148 else 149 { 150 Value = (UINT8) (ACPI_TOUPPER (HexChar) - 0x37); 151 } 152 153 *ReturnValue = Value; 154 return (AE_OK); 155 } 156 157 158 /******************************************************************************* 159 * 160 * FUNCTION: AcpiDbHexByteToBinary 161 * 162 * PARAMETERS: HexByte - Double hex digit (0x00 - 0xFF) in format: 163 * HiByte then LoByte. 164 * ReturnValue - Where the converted value is returned 165 * 166 * RETURN: Status 167 * 168 * DESCRIPTION: Convert two hex characters to an 8 bit number (0 - 255). 169 * 170 ******************************************************************************/ 171 172 static ACPI_STATUS 173 AcpiDbHexByteToBinary ( 174 char *HexByte, 175 UINT8 *ReturnValue) 176 { 177 UINT8 Local0; 178 UINT8 Local1; 179 ACPI_STATUS Status; 180 181 182 /* High byte */ 183 184 Status = AcpiDbHexCharToValue (HexByte[0], &Local0); 185 if (ACPI_FAILURE (Status)) 186 { 187 return (Status); 188 } 189 190 /* Low byte */ 191 192 Status = AcpiDbHexCharToValue (HexByte[1], &Local1); 193 if (ACPI_FAILURE (Status)) 194 { 195 return (Status); 196 } 197 198 *ReturnValue = (UINT8) ((Local0 << 4) | Local1); 199 return (AE_OK); 200 } 201 202 203 /******************************************************************************* 204 * 205 * FUNCTION: AcpiDbConvertToBuffer 206 * 207 * PARAMETERS: String - Input string to be converted 208 * Object - Where the buffer object is returned 209 * 210 * RETURN: Status 211 * 212 * DESCRIPTION: Convert a string to a buffer object. String is treated a list 213 * of buffer elements, each separated by a space or comma. 214 * 215 ******************************************************************************/ 216 217 static ACPI_STATUS 218 AcpiDbConvertToBuffer ( 219 char *String, 220 ACPI_OBJECT *Object) 221 { 222 UINT32 i; 223 UINT32 j; 224 UINT32 Length; 225 UINT8 *Buffer; 226 ACPI_STATUS Status; 227 228 229 /* Generate the final buffer length */ 230 231 for (i = 0, Length = 0; String[i];) 232 { 233 i+=2; 234 Length++; 235 236 while (String[i] && 237 ((String[i] == ',') || (String[i] == ' '))) 238 { 239 i++; 240 } 241 } 242 243 Buffer = ACPI_ALLOCATE (Length); 244 if (!Buffer) 245 { 246 return (AE_NO_MEMORY); 247 } 248 249 /* Convert the command line bytes to the buffer */ 250 251 for (i = 0, j = 0; String[i];) 252 { 253 Status = AcpiDbHexByteToBinary (&String[i], &Buffer[j]); 254 if (ACPI_FAILURE (Status)) 255 { 256 ACPI_FREE (Buffer); 257 return (Status); 258 } 259 260 j++; 261 i+=2; 262 while (String[i] && 263 ((String[i] == ',') || (String[i] == ' '))) 264 { 265 i++; 266 } 267 } 268 269 Object->Type = ACPI_TYPE_BUFFER; 270 Object->Buffer.Pointer = Buffer; 271 Object->Buffer.Length = Length; 272 return (AE_OK); 273 } 274 275 276 /******************************************************************************* 277 * 278 * FUNCTION: AcpiDbConvertToPackage 279 * 280 * PARAMETERS: String - Input string to be converted 281 * Object - Where the package object is returned 282 * 283 * RETURN: Status 284 * 285 * DESCRIPTION: Convert a string to a package object. Handles nested packages 286 * via recursion with AcpiDbConvertToObject. 287 * 288 ******************************************************************************/ 289 290 static ACPI_STATUS 291 AcpiDbConvertToPackage ( 292 char *String, 293 ACPI_OBJECT *Object) 294 { 295 char *This; 296 char *Next; 297 UINT32 i; 298 ACPI_OBJECT_TYPE Type; 299 ACPI_OBJECT *Elements; 300 ACPI_STATUS Status; 301 302 303 Elements = ACPI_ALLOCATE_ZEROED ( 304 DB_DEFAULT_PKG_ELEMENTS * sizeof (ACPI_OBJECT)); 305 306 This = String; 307 for (i = 0; i < (DB_DEFAULT_PKG_ELEMENTS - 1); i++) 308 { 309 This = AcpiDbGetNextToken (This, &Next, &Type); 310 if (!This) 311 { 312 break; 313 } 314 315 /* Recursive call to convert each package element */ 316 317 Status = AcpiDbConvertToObject (Type, This, &Elements[i]); 318 if (ACPI_FAILURE (Status)) 319 { 320 AcpiDbDeleteObjects (i + 1, Elements); 321 ACPI_FREE (Elements); 322 return (Status); 323 } 324 325 This = Next; 326 } 327 328 Object->Type = ACPI_TYPE_PACKAGE; 329 Object->Package.Count = i; 330 Object->Package.Elements = Elements; 331 return (AE_OK); 332 } 333 334 335 /******************************************************************************* 336 * 337 * FUNCTION: AcpiDbConvertToObject 338 * 339 * PARAMETERS: Type - Object type as determined by parser 340 * String - Input string to be converted 341 * Object - Where the new object is returned 342 * 343 * RETURN: Status 344 * 345 * DESCRIPTION: Convert a typed and tokenized string to an ACPI_OBJECT. Typing: 346 * 1) String objects were surrounded by quotes. 347 * 2) Buffer objects were surrounded by parentheses. 348 * 3) Package objects were surrounded by brackets "[]". 349 * 4) All standalone tokens are treated as integers. 350 * 351 ******************************************************************************/ 352 353 static ACPI_STATUS 354 AcpiDbConvertToObject ( 355 ACPI_OBJECT_TYPE Type, 356 char *String, 357 ACPI_OBJECT *Object) 358 { 359 ACPI_STATUS Status = AE_OK; 360 361 362 switch (Type) 363 { 364 case ACPI_TYPE_STRING: 365 Object->Type = ACPI_TYPE_STRING; 366 Object->String.Pointer = String; 367 Object->String.Length = (UINT32) ACPI_STRLEN (String); 368 break; 369 370 case ACPI_TYPE_BUFFER: 371 Status = AcpiDbConvertToBuffer (String, Object); 372 break; 373 374 case ACPI_TYPE_PACKAGE: 375 Status = AcpiDbConvertToPackage (String, Object); 376 break; 377 378 default: 379 Object->Type = ACPI_TYPE_INTEGER; 380 Status = AcpiUtStrtoul64 (String, 16, &Object->Integer.Value); 381 break; 382 } 383 384 return (Status); 385 } 386 387 388 /******************************************************************************* 389 * 390 * FUNCTION: AcpiDbDeleteObjects 391 * 392 * PARAMETERS: Count - Count of objects in the list 393 * Objects - Array of ACPI_OBJECTs to be deleted 394 * 395 * RETURN: None 396 * 397 * DESCRIPTION: Delete a list of ACPI_OBJECTS. Handles packages and nested 398 * packages via recursion. 399 * 400 ******************************************************************************/ 401 402 static void 403 AcpiDbDeleteObjects ( 404 UINT32 Count, 405 ACPI_OBJECT *Objects) 406 { 407 UINT32 i; 408 409 410 for (i = 0; i < Count; i++) 411 { 412 switch (Objects[i].Type) 413 { 414 case ACPI_TYPE_BUFFER: 415 ACPI_FREE (Objects[i].Buffer.Pointer); 416 break; 417 418 case ACPI_TYPE_PACKAGE: 419 420 /* Recursive call to delete package elements */ 421 422 AcpiDbDeleteObjects (Objects[i].Package.Count, 423 Objects[i].Package.Elements); 424 425 /* Free the elements array */ 426 427 ACPI_FREE (Objects[i].Package.Elements); 428 break; 429 430 default: 431 break; 432 } 433 } 434 } 435 436 437 /******************************************************************************* 438 * 439 * FUNCTION: AcpiDbExecuteMethod 440 * 441 * PARAMETERS: Info - Valid info segment 442 * ReturnObj - Where to put return object 443 * 444 * RETURN: Status 445 * 446 * DESCRIPTION: Execute a control method. 447 * 448 ******************************************************************************/ 449 450 static ACPI_STATUS 451 AcpiDbExecuteMethod ( 452 ACPI_DB_METHOD_INFO *Info, 453 ACPI_BUFFER *ReturnObj) 454 { 455 ACPI_STATUS Status; 456 ACPI_OBJECT_LIST ParamObjects; 457 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 458 ACPI_DEVICE_INFO *ObjInfo; 459 UINT32 i; 460 461 462 ACPI_FUNCTION_TRACE (DbExecuteMethod); 463 464 465 if (AcpiGbl_DbOutputToFile && !AcpiDbgLevel) 466 { 467 AcpiOsPrintf ("Warning: debug output is not enabled!\n"); 468 } 469 470 /* Get the object info for number of method parameters */ 471 472 Status = AcpiGetObjectInfo (Info->Method, &ObjInfo); 473 if (ACPI_FAILURE (Status)) 474 { 475 return_ACPI_STATUS (Status); 476 } 477 478 ParamObjects.Pointer = NULL; 479 ParamObjects.Count = 0; 480 481 if (ObjInfo->Type == ACPI_TYPE_METHOD) 482 { 483 /* Are there arguments to the method? */ 484 485 i = 0; 486 if (Info->Args && Info->Args[0]) 487 { 488 /* Get arguments passed on the command line */ 489 490 for (; Info->Args[i] && 491 (i < ACPI_METHOD_NUM_ARGS) && 492 (i < ObjInfo->ParamCount); 493 i++) 494 { 495 /* Convert input string (token) to an actual ACPI_OBJECT */ 496 497 Status = AcpiDbConvertToObject (Info->Types[i], 498 Info->Args[i], &Params[i]); 499 if (ACPI_FAILURE (Status)) 500 { 501 ACPI_EXCEPTION ((AE_INFO, Status, 502 "While parsing method arguments")); 503 goto Cleanup; 504 } 505 } 506 } 507 508 /* Create additional "default" parameters as needed */ 509 510 if (i < ObjInfo->ParamCount) 511 { 512 AcpiOsPrintf ("Adding %u arguments containing default values\n", 513 ObjInfo->ParamCount - i); 514 515 for (; i < ObjInfo->ParamCount; i++) 516 { 517 switch (i) 518 { 519 case 0: 520 521 Params[0].Type = ACPI_TYPE_INTEGER; 522 Params[0].Integer.Value = 0x01020304; 523 break; 524 525 case 1: 526 527 Params[1].Type = ACPI_TYPE_STRING; 528 Params[1].String.Length = 12; 529 Params[1].String.Pointer = "AML Debugger"; 530 break; 531 532 default: 533 534 Params[i].Type = ACPI_TYPE_INTEGER; 535 Params[i].Integer.Value = i * (UINT64) 0x1000; 536 break; 537 } 538 } 539 } 540 541 ParamObjects.Count = ObjInfo->ParamCount; 542 ParamObjects.Pointer = Params; 543 } 544 545 /* Prepare for a return object of arbitrary size */ 546 547 ReturnObj->Pointer = AcpiGbl_DbBuffer; 548 ReturnObj->Length = ACPI_DEBUG_BUFFER_SIZE; 549 550 /* Do the actual method execution */ 551 552 AcpiGbl_MethodExecuting = TRUE; 553 Status = AcpiEvaluateObject (NULL, 554 Info->Pathname, &ParamObjects, ReturnObj); 555 556 AcpiGbl_CmSingleStep = FALSE; 557 AcpiGbl_MethodExecuting = FALSE; 558 559 if (ACPI_FAILURE (Status)) 560 { 561 ACPI_EXCEPTION ((AE_INFO, Status, 562 "while executing %s from debugger", Info->Pathname)); 563 564 if (Status == AE_BUFFER_OVERFLOW) 565 { 566 ACPI_ERROR ((AE_INFO, 567 "Possible overflow of internal debugger buffer (size 0x%X needed 0x%X)", 568 ACPI_DEBUG_BUFFER_SIZE, (UINT32) ReturnObj->Length)); 569 } 570 } 571 572 Cleanup: 573 AcpiDbDeleteObjects (ObjInfo->ParamCount, Params); 574 ACPI_FREE (ObjInfo); 575 576 return_ACPI_STATUS (Status); 577 } 578 579 580 /******************************************************************************* 581 * 582 * FUNCTION: AcpiDbExecuteSetup 583 * 584 * PARAMETERS: Info - Valid method info 585 * 586 * RETURN: None 587 * 588 * DESCRIPTION: Setup info segment prior to method execution 589 * 590 ******************************************************************************/ 591 592 static void 593 AcpiDbExecuteSetup ( 594 ACPI_DB_METHOD_INFO *Info) 595 { 596 597 /* Catenate the current scope to the supplied name */ 598 599 Info->Pathname[0] = 0; 600 if ((Info->Name[0] != '\\') && 601 (Info->Name[0] != '/')) 602 { 603 ACPI_STRCAT (Info->Pathname, AcpiGbl_DbScopeBuf); 604 } 605 606 ACPI_STRCAT (Info->Pathname, Info->Name); 607 AcpiDbPrepNamestring (Info->Pathname); 608 609 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 610 AcpiOsPrintf ("Evaluating %s\n", Info->Pathname); 611 612 if (Info->Flags & EX_SINGLE_STEP) 613 { 614 AcpiGbl_CmSingleStep = TRUE; 615 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 616 } 617 618 else 619 { 620 /* No single step, allow redirection to a file */ 621 622 AcpiDbSetOutputDestination (ACPI_DB_REDIRECTABLE_OUTPUT); 623 } 624 } 625 626 627 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 628 UINT32 629 AcpiDbGetCacheInfo ( 630 ACPI_MEMORY_LIST *Cache) 631 { 632 633 return (Cache->TotalAllocated - Cache->TotalFreed - Cache->CurrentDepth); 634 } 635 #endif 636 637 /******************************************************************************* 638 * 639 * FUNCTION: AcpiDbGetOutstandingAllocations 640 * 641 * PARAMETERS: None 642 * 643 * RETURN: Current global allocation count minus cache entries 644 * 645 * DESCRIPTION: Determine the current number of "outstanding" allocations -- 646 * those allocations that have not been freed and also are not 647 * in one of the various object caches. 648 * 649 ******************************************************************************/ 650 651 static UINT32 652 AcpiDbGetOutstandingAllocations ( 653 void) 654 { 655 UINT32 Outstanding = 0; 656 657 #ifdef ACPI_DBG_TRACK_ALLOCATIONS 658 659 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_StateCache); 660 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeCache); 661 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_PsNodeExtCache); 662 Outstanding += AcpiDbGetCacheInfo (AcpiGbl_OperandCache); 663 #endif 664 665 return (Outstanding); 666 } 667 668 669 /******************************************************************************* 670 * 671 * FUNCTION: AcpiDbExecutionWalk 672 * 673 * PARAMETERS: WALK_CALLBACK 674 * 675 * RETURN: Status 676 * 677 * DESCRIPTION: Execute a control method. Name is relative to the current 678 * scope. 679 * 680 ******************************************************************************/ 681 682 static ACPI_STATUS 683 AcpiDbExecutionWalk ( 684 ACPI_HANDLE ObjHandle, 685 UINT32 NestingLevel, 686 void *Context, 687 void **ReturnValue) 688 { 689 ACPI_OPERAND_OBJECT *ObjDesc; 690 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 691 ACPI_BUFFER ReturnObj; 692 ACPI_STATUS Status; 693 694 695 ObjDesc = AcpiNsGetAttachedObject (Node); 696 if (ObjDesc->Method.ParamCount) 697 { 698 return (AE_OK); 699 } 700 701 ReturnObj.Pointer = NULL; 702 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 703 704 AcpiNsPrintNodePathname (Node, "Evaluating"); 705 706 /* Do the actual method execution */ 707 708 AcpiOsPrintf ("\n"); 709 AcpiGbl_MethodExecuting = TRUE; 710 711 Status = AcpiEvaluateObject (Node, NULL, NULL, &ReturnObj); 712 713 AcpiOsPrintf ("Evaluation of [%4.4s] returned %s\n", AcpiUtGetNodeName (Node), 714 AcpiFormatException (Status)); 715 AcpiGbl_MethodExecuting = FALSE; 716 717 return (AE_OK); 718 } 719 720 721 /******************************************************************************* 722 * 723 * FUNCTION: AcpiDbEncodePldBuffer 724 * 725 * PARAMETERS: PldInfo - _PLD buffer struct (Using local struct) 726 * 727 * RETURN: Encode _PLD buffer suitable for return value from _PLD 728 * 729 * DESCRIPTION: Bit-packs a _PLD buffer struct. Used to test the _PLD macros 730 * 731 ******************************************************************************/ 732 733 static UINT8 * 734 AcpiDbEncodePldBuffer ( 735 ACPI_PLD_INFO *PldInfo) 736 { 737 UINT32 *Buffer; 738 UINT32 Dword; 739 740 741 Buffer = ACPI_ALLOCATE_ZEROED (ACPI_PLD_BUFFER_SIZE); 742 if (!Buffer) 743 { 744 return (NULL); 745 } 746 747 /* First 32 bits */ 748 749 Dword = 0; 750 ACPI_PLD_SET_REVISION (&Dword, PldInfo->Revision); 751 ACPI_PLD_SET_IGNORE_COLOR (&Dword, PldInfo->IgnoreColor); 752 ACPI_PLD_SET_COLOR (&Dword, PldInfo->Color); 753 ACPI_MOVE_32_TO_32 (&Buffer[0], &Dword); 754 755 /* Second 32 bits */ 756 757 Dword = 0; 758 ACPI_PLD_SET_WIDTH (&Dword, PldInfo->Width); 759 ACPI_PLD_SET_HEIGHT (&Dword, PldInfo->Height); 760 ACPI_MOVE_32_TO_32 (&Buffer[1], &Dword); 761 762 /* Third 32 bits */ 763 764 Dword = 0; 765 ACPI_PLD_SET_USER_VISIBLE (&Dword, PldInfo->UserVisible); 766 ACPI_PLD_SET_DOCK (&Dword, PldInfo->Dock); 767 ACPI_PLD_SET_LID (&Dword, PldInfo->Lid); 768 ACPI_PLD_SET_PANEL (&Dword, PldInfo->Panel); 769 ACPI_PLD_SET_VERTICAL (&Dword, PldInfo->VerticalPosition); 770 ACPI_PLD_SET_HORIZONTAL (&Dword, PldInfo->HorizontalPosition); 771 ACPI_PLD_SET_SHAPE (&Dword, PldInfo->Shape); 772 ACPI_PLD_SET_ORIENTATION (&Dword, PldInfo->GroupOrientation); 773 ACPI_PLD_SET_TOKEN (&Dword, PldInfo->GroupToken); 774 ACPI_PLD_SET_POSITION (&Dword, PldInfo->GroupPosition); 775 ACPI_PLD_SET_BAY (&Dword, PldInfo->Bay); 776 ACPI_MOVE_32_TO_32 (&Buffer[2], &Dword); 777 778 /* Fourth 32 bits */ 779 780 Dword = 0; 781 ACPI_PLD_SET_EJECTABLE (&Dword, PldInfo->Ejectable); 782 ACPI_PLD_SET_OSPM_EJECT (&Dword, PldInfo->OspmEjectRequired); 783 ACPI_PLD_SET_CABINET (&Dword, PldInfo->CabinetNumber); 784 ACPI_PLD_SET_CARD_CAGE (&Dword, PldInfo->CardCageNumber); 785 ACPI_PLD_SET_REFERENCE (&Dword, PldInfo->Reference); 786 ACPI_PLD_SET_ROTATION (&Dword, PldInfo->Rotation); 787 ACPI_PLD_SET_ORDER (&Dword, PldInfo->Order); 788 ACPI_MOVE_32_TO_32 (&Buffer[3], &Dword); 789 790 if (PldInfo->Revision >= 2) 791 { 792 /* Fifth 32 bits */ 793 794 Dword = 0; 795 ACPI_PLD_SET_VERT_OFFSET (&Dword, PldInfo->VerticalOffset); 796 ACPI_PLD_SET_HORIZ_OFFSET (&Dword, PldInfo->HorizontalOffset); 797 ACPI_MOVE_32_TO_32 (&Buffer[4], &Dword); 798 } 799 800 return (ACPI_CAST_PTR (UINT8, Buffer)); 801 } 802 803 804 /******************************************************************************* 805 * 806 * FUNCTION: AcpiDbDumpPldBuffer 807 * 808 * PARAMETERS: ObjDesc - Object returned from _PLD method 809 * 810 * RETURN: None. 811 * 812 * DESCRIPTION: Dumps formatted contents of a _PLD return buffer. 813 * 814 ******************************************************************************/ 815 816 #define ACPI_PLD_OUTPUT "%20s : %-6X\n" 817 818 static void 819 AcpiDbDumpPldBuffer ( 820 ACPI_OBJECT *ObjDesc) 821 { 822 ACPI_OBJECT *BufferDesc; 823 ACPI_PLD_INFO *PldInfo; 824 UINT8 *NewBuffer; 825 ACPI_STATUS Status; 826 827 828 /* Object must be of type Package with at least one Buffer element */ 829 830 if (ObjDesc->Type != ACPI_TYPE_PACKAGE) 831 { 832 return; 833 } 834 835 BufferDesc = &ObjDesc->Package.Elements[0]; 836 if (BufferDesc->Type != ACPI_TYPE_BUFFER) 837 { 838 return; 839 } 840 841 /* Convert _PLD buffer to local _PLD struct */ 842 843 Status = AcpiDecodePldBuffer (BufferDesc->Buffer.Pointer, 844 BufferDesc->Buffer.Length, &PldInfo); 845 if (ACPI_FAILURE (Status)) 846 { 847 return; 848 } 849 850 /* Encode local _PLD struct back to a _PLD buffer */ 851 852 NewBuffer = AcpiDbEncodePldBuffer (PldInfo); 853 if (!NewBuffer) 854 { 855 return; 856 } 857 858 /* The two bit-packed buffers should match */ 859 860 if (ACPI_MEMCMP (NewBuffer, BufferDesc->Buffer.Pointer, 861 BufferDesc->Buffer.Length)) 862 { 863 AcpiOsPrintf ("Converted _PLD buffer does not compare. New:\n"); 864 865 AcpiUtDumpBuffer2 (NewBuffer, 866 BufferDesc->Buffer.Length, DB_BYTE_DISPLAY); 867 } 868 869 /* First 32-bit dword */ 870 871 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Revision", PldInfo->Revision); 872 AcpiOsPrintf (ACPI_PLD_OUTPUT, "IgnoreColor", PldInfo->IgnoreColor); 873 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Color", PldInfo->Color); 874 875 /* Second 32-bit dword */ 876 877 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Width", PldInfo->Width); 878 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Height", PldInfo->Height); 879 880 /* Third 32-bit dword */ 881 882 AcpiOsPrintf (ACPI_PLD_OUTPUT, "UserVisible", PldInfo->UserVisible); 883 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Dock", PldInfo->Dock); 884 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Lid", PldInfo->Lid); 885 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Panel", PldInfo->Panel); 886 AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalPosition", PldInfo->VerticalPosition); 887 AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalPosition", PldInfo->HorizontalPosition); 888 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Shape", PldInfo->Shape); 889 AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupOrientation", PldInfo->GroupOrientation); 890 AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupToken", PldInfo->GroupToken); 891 AcpiOsPrintf (ACPI_PLD_OUTPUT, "GroupPosition", PldInfo->GroupPosition); 892 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Bay", PldInfo->Bay); 893 894 /* Fourth 32-bit dword */ 895 896 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Ejectable", PldInfo->Ejectable); 897 AcpiOsPrintf (ACPI_PLD_OUTPUT, "OspmEjectRequired", PldInfo->OspmEjectRequired); 898 AcpiOsPrintf (ACPI_PLD_OUTPUT, "CabinetNumber", PldInfo->CabinetNumber); 899 AcpiOsPrintf (ACPI_PLD_OUTPUT, "CardCageNumber", PldInfo->CardCageNumber); 900 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Reference", PldInfo->Reference); 901 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Rotation", PldInfo->Rotation); 902 AcpiOsPrintf (ACPI_PLD_OUTPUT, "Order", PldInfo->Order); 903 904 /* Fifth 32-bit dword */ 905 906 if (BufferDesc->Buffer.Length > 16) 907 { 908 AcpiOsPrintf (ACPI_PLD_OUTPUT, "VerticalOffset", PldInfo->VerticalOffset); 909 AcpiOsPrintf (ACPI_PLD_OUTPUT, "HorizontalOffset", PldInfo->HorizontalOffset); 910 } 911 912 ACPI_FREE (PldInfo); 913 ACPI_FREE (NewBuffer); 914 } 915 916 917 /******************************************************************************* 918 * 919 * FUNCTION: AcpiDbExecute 920 * 921 * PARAMETERS: Name - Name of method to execute 922 * Args - Parameters to the method 923 * Flags - single step/no single step 924 * 925 * RETURN: None 926 * 927 * DESCRIPTION: Execute a control method. Name is relative to the current 928 * scope. 929 * 930 ******************************************************************************/ 931 932 void 933 AcpiDbExecute ( 934 char *Name, 935 char **Args, 936 ACPI_OBJECT_TYPE *Types, 937 UINT32 Flags) 938 { 939 ACPI_STATUS Status; 940 ACPI_BUFFER ReturnObj; 941 char *NameString; 942 943 944 #ifdef ACPI_DEBUG_OUTPUT 945 UINT32 PreviousAllocations; 946 UINT32 Allocations; 947 948 949 /* Memory allocation tracking */ 950 951 PreviousAllocations = AcpiDbGetOutstandingAllocations (); 952 #endif 953 954 if (*Name == '*') 955 { 956 (void) AcpiWalkNamespace (ACPI_TYPE_METHOD, ACPI_ROOT_OBJECT, 957 ACPI_UINT32_MAX, AcpiDbExecutionWalk, NULL, NULL, NULL); 958 return; 959 } 960 else 961 { 962 NameString = ACPI_ALLOCATE (ACPI_STRLEN (Name) + 1); 963 if (!NameString) 964 { 965 return; 966 } 967 968 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 969 970 ACPI_STRCPY (NameString, Name); 971 AcpiUtStrupr (NameString); 972 AcpiGbl_DbMethodInfo.Name = NameString; 973 AcpiGbl_DbMethodInfo.Args = Args; 974 AcpiGbl_DbMethodInfo.Types = Types; 975 AcpiGbl_DbMethodInfo.Flags = Flags; 976 977 ReturnObj.Pointer = NULL; 978 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 979 980 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 981 982 /* Get the NS node, determines existence also */ 983 984 Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 985 &AcpiGbl_DbMethodInfo.Method); 986 if (ACPI_FAILURE (Status)) 987 { 988 return; 989 } 990 991 Status = AcpiDbExecuteMethod (&AcpiGbl_DbMethodInfo, &ReturnObj); 992 ACPI_FREE (NameString); 993 } 994 995 /* 996 * Allow any handlers in separate threads to complete. 997 * (Such as Notify handlers invoked from AML executed above). 998 */ 999 AcpiOsSleep ((UINT64) 10); 1000 1001 1002 #ifdef ACPI_DEBUG_OUTPUT 1003 1004 /* Memory allocation tracking */ 1005 1006 Allocations = AcpiDbGetOutstandingAllocations () - PreviousAllocations; 1007 1008 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 1009 1010 if (Allocations > 0) 1011 { 1012 AcpiOsPrintf ("0x%X Outstanding allocations after evaluation of %s\n", 1013 Allocations, AcpiGbl_DbMethodInfo.Pathname); 1014 } 1015 #endif 1016 1017 if (ACPI_FAILURE (Status)) 1018 { 1019 AcpiOsPrintf ("Evaluation of %s failed with status %s\n", 1020 AcpiGbl_DbMethodInfo.Pathname, AcpiFormatException (Status)); 1021 } 1022 else 1023 { 1024 /* Display a return object, if any */ 1025 1026 if (ReturnObj.Length) 1027 { 1028 AcpiOsPrintf ( 1029 "Evaluation of %s returned object %p, external buffer length %X\n", 1030 AcpiGbl_DbMethodInfo.Pathname, ReturnObj.Pointer, 1031 (UINT32) ReturnObj.Length); 1032 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 1033 1034 /* Dump a _PLD buffer if present */ 1035 1036 if (ACPI_COMPARE_NAME ((ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, 1037 AcpiGbl_DbMethodInfo.Method)->Name.Ascii), METHOD_NAME__PLD)) 1038 { 1039 AcpiDbDumpPldBuffer (ReturnObj.Pointer); 1040 } 1041 } 1042 else 1043 { 1044 AcpiOsPrintf ("No object was returned from evaluation of %s\n", 1045 AcpiGbl_DbMethodInfo.Pathname); 1046 } 1047 } 1048 1049 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 1050 } 1051 1052 1053 /******************************************************************************* 1054 * 1055 * FUNCTION: AcpiDbMethodThread 1056 * 1057 * PARAMETERS: Context - Execution info segment 1058 * 1059 * RETURN: None 1060 * 1061 * DESCRIPTION: Debugger execute thread. Waits for a command line, then 1062 * simply dispatches it. 1063 * 1064 ******************************************************************************/ 1065 1066 static void ACPI_SYSTEM_XFACE 1067 AcpiDbMethodThread ( 1068 void *Context) 1069 { 1070 ACPI_STATUS Status; 1071 ACPI_DB_METHOD_INFO *Info = Context; 1072 ACPI_DB_METHOD_INFO LocalInfo; 1073 UINT32 i; 1074 UINT8 Allow; 1075 ACPI_BUFFER ReturnObj; 1076 1077 1078 /* 1079 * AcpiGbl_DbMethodInfo.Arguments will be passed as method arguments. 1080 * Prevent AcpiGbl_DbMethodInfo from being modified by multiple threads 1081 * concurrently. 1082 * 1083 * Note: The arguments we are passing are used by the ASL test suite 1084 * (aslts). Do not change them without updating the tests. 1085 */ 1086 (void) AcpiOsWaitSemaphore (Info->InfoGate, 1, ACPI_WAIT_FOREVER); 1087 1088 if (Info->InitArgs) 1089 { 1090 AcpiDbUint32ToHexString (Info->NumCreated, Info->IndexOfThreadStr); 1091 AcpiDbUint32ToHexString ((UINT32) AcpiOsGetThreadId (), Info->IdOfThreadStr); 1092 } 1093 1094 if (Info->Threads && (Info->NumCreated < Info->NumThreads)) 1095 { 1096 Info->Threads[Info->NumCreated++] = AcpiOsGetThreadId(); 1097 } 1098 1099 LocalInfo = *Info; 1100 LocalInfo.Args = LocalInfo.Arguments; 1101 LocalInfo.Arguments[0] = LocalInfo.NumThreadsStr; 1102 LocalInfo.Arguments[1] = LocalInfo.IdOfThreadStr; 1103 LocalInfo.Arguments[2] = LocalInfo.IndexOfThreadStr; 1104 LocalInfo.Arguments[3] = NULL; 1105 1106 LocalInfo.Types = LocalInfo.ArgTypes; 1107 1108 (void) AcpiOsSignalSemaphore (Info->InfoGate, 1); 1109 1110 for (i = 0; i < Info->NumLoops; i++) 1111 { 1112 Status = AcpiDbExecuteMethod (&LocalInfo, &ReturnObj); 1113 if (ACPI_FAILURE (Status)) 1114 { 1115 AcpiOsPrintf ("%s During evaluation of %s at iteration %X\n", 1116 AcpiFormatException (Status), Info->Pathname, i); 1117 if (Status == AE_ABORT_METHOD) 1118 { 1119 break; 1120 } 1121 } 1122 1123 #if 0 1124 if ((i % 100) == 0) 1125 { 1126 AcpiOsPrintf ("%u loops, Thread 0x%x\n", i, AcpiOsGetThreadId ()); 1127 } 1128 1129 if (ReturnObj.Length) 1130 { 1131 AcpiOsPrintf ("Evaluation of %s returned object %p Buflen %X\n", 1132 Info->Pathname, ReturnObj.Pointer, (UINT32) ReturnObj.Length); 1133 AcpiDbDumpExternalObject (ReturnObj.Pointer, 1); 1134 } 1135 #endif 1136 } 1137 1138 /* Signal our completion */ 1139 1140 Allow = 0; 1141 (void) AcpiOsWaitSemaphore (Info->ThreadCompleteGate, 1, ACPI_WAIT_FOREVER); 1142 Info->NumCompleted++; 1143 1144 if (Info->NumCompleted == Info->NumThreads) 1145 { 1146 /* Do signal for main thread once only */ 1147 Allow = 1; 1148 } 1149 1150 (void) AcpiOsSignalSemaphore (Info->ThreadCompleteGate, 1); 1151 1152 if (Allow) 1153 { 1154 Status = AcpiOsSignalSemaphore (Info->MainThreadGate, 1); 1155 if (ACPI_FAILURE (Status)) 1156 { 1157 AcpiOsPrintf ("Could not signal debugger thread sync semaphore, %s\n", 1158 AcpiFormatException (Status)); 1159 } 1160 } 1161 } 1162 1163 1164 /******************************************************************************* 1165 * 1166 * FUNCTION: AcpiDbCreateExecutionThreads 1167 * 1168 * PARAMETERS: NumThreadsArg - Number of threads to create 1169 * NumLoopsArg - Loop count for the thread(s) 1170 * MethodNameArg - Control method to execute 1171 * 1172 * RETURN: None 1173 * 1174 * DESCRIPTION: Create threads to execute method(s) 1175 * 1176 ******************************************************************************/ 1177 1178 void 1179 AcpiDbCreateExecutionThreads ( 1180 char *NumThreadsArg, 1181 char *NumLoopsArg, 1182 char *MethodNameArg) 1183 { 1184 ACPI_STATUS Status; 1185 UINT32 NumThreads; 1186 UINT32 NumLoops; 1187 UINT32 i; 1188 UINT32 Size; 1189 ACPI_MUTEX MainThreadGate; 1190 ACPI_MUTEX ThreadCompleteGate; 1191 ACPI_MUTEX InfoGate; 1192 1193 1194 /* Get the arguments */ 1195 1196 NumThreads = ACPI_STRTOUL (NumThreadsArg, NULL, 0); 1197 NumLoops = ACPI_STRTOUL (NumLoopsArg, NULL, 0); 1198 1199 if (!NumThreads || !NumLoops) 1200 { 1201 AcpiOsPrintf ("Bad argument: Threads %X, Loops %X\n", 1202 NumThreads, NumLoops); 1203 return; 1204 } 1205 1206 /* 1207 * Create the semaphore for synchronization of 1208 * the created threads with the main thread. 1209 */ 1210 Status = AcpiOsCreateSemaphore (1, 0, &MainThreadGate); 1211 if (ACPI_FAILURE (Status)) 1212 { 1213 AcpiOsPrintf ("Could not create semaphore for synchronization with the main thread, %s\n", 1214 AcpiFormatException (Status)); 1215 return; 1216 } 1217 1218 /* 1219 * Create the semaphore for synchronization 1220 * between the created threads. 1221 */ 1222 Status = AcpiOsCreateSemaphore (1, 1, &ThreadCompleteGate); 1223 if (ACPI_FAILURE (Status)) 1224 { 1225 AcpiOsPrintf ("Could not create semaphore for synchronization between the created threads, %s\n", 1226 AcpiFormatException (Status)); 1227 (void) AcpiOsDeleteSemaphore (MainThreadGate); 1228 return; 1229 } 1230 1231 Status = AcpiOsCreateSemaphore (1, 1, &InfoGate); 1232 if (ACPI_FAILURE (Status)) 1233 { 1234 AcpiOsPrintf ("Could not create semaphore for synchronization of AcpiGbl_DbMethodInfo, %s\n", 1235 AcpiFormatException (Status)); 1236 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 1237 (void) AcpiOsDeleteSemaphore (MainThreadGate); 1238 return; 1239 } 1240 1241 ACPI_MEMSET (&AcpiGbl_DbMethodInfo, 0, sizeof (ACPI_DB_METHOD_INFO)); 1242 1243 /* Array to store IDs of threads */ 1244 1245 AcpiGbl_DbMethodInfo.NumThreads = NumThreads; 1246 Size = sizeof (ACPI_THREAD_ID) * AcpiGbl_DbMethodInfo.NumThreads; 1247 AcpiGbl_DbMethodInfo.Threads = AcpiOsAllocate (Size); 1248 if (AcpiGbl_DbMethodInfo.Threads == NULL) 1249 { 1250 AcpiOsPrintf ("No memory for thread IDs array\n"); 1251 (void) AcpiOsDeleteSemaphore (MainThreadGate); 1252 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 1253 (void) AcpiOsDeleteSemaphore (InfoGate); 1254 return; 1255 } 1256 ACPI_MEMSET (AcpiGbl_DbMethodInfo.Threads, 0, Size); 1257 1258 /* Setup the context to be passed to each thread */ 1259 1260 AcpiGbl_DbMethodInfo.Name = MethodNameArg; 1261 AcpiGbl_DbMethodInfo.Flags = 0; 1262 AcpiGbl_DbMethodInfo.NumLoops = NumLoops; 1263 AcpiGbl_DbMethodInfo.MainThreadGate = MainThreadGate; 1264 AcpiGbl_DbMethodInfo.ThreadCompleteGate = ThreadCompleteGate; 1265 AcpiGbl_DbMethodInfo.InfoGate = InfoGate; 1266 1267 /* Init arguments to be passed to method */ 1268 1269 AcpiGbl_DbMethodInfo.InitArgs = 1; 1270 AcpiGbl_DbMethodInfo.Args = AcpiGbl_DbMethodInfo.Arguments; 1271 AcpiGbl_DbMethodInfo.Arguments[0] = AcpiGbl_DbMethodInfo.NumThreadsStr; 1272 AcpiGbl_DbMethodInfo.Arguments[1] = AcpiGbl_DbMethodInfo.IdOfThreadStr; 1273 AcpiGbl_DbMethodInfo.Arguments[2] = AcpiGbl_DbMethodInfo.IndexOfThreadStr; 1274 AcpiGbl_DbMethodInfo.Arguments[3] = NULL; 1275 1276 AcpiGbl_DbMethodInfo.Types = AcpiGbl_DbMethodInfo.ArgTypes; 1277 AcpiGbl_DbMethodInfo.ArgTypes[0] = ACPI_TYPE_INTEGER; 1278 AcpiGbl_DbMethodInfo.ArgTypes[1] = ACPI_TYPE_INTEGER; 1279 AcpiGbl_DbMethodInfo.ArgTypes[2] = ACPI_TYPE_INTEGER; 1280 1281 AcpiDbUint32ToHexString (NumThreads, AcpiGbl_DbMethodInfo.NumThreadsStr); 1282 1283 AcpiDbExecuteSetup (&AcpiGbl_DbMethodInfo); 1284 1285 /* Get the NS node, determines existence also */ 1286 1287 Status = AcpiGetHandle (NULL, AcpiGbl_DbMethodInfo.Pathname, 1288 &AcpiGbl_DbMethodInfo.Method); 1289 if (ACPI_FAILURE (Status)) 1290 { 1291 AcpiOsPrintf ("%s Could not get handle for %s\n", 1292 AcpiFormatException (Status), AcpiGbl_DbMethodInfo.Pathname); 1293 goto CleanupAndExit; 1294 } 1295 1296 /* Create the threads */ 1297 1298 AcpiOsPrintf ("Creating %X threads to execute %X times each\n", 1299 NumThreads, NumLoops); 1300 1301 for (i = 0; i < (NumThreads); i++) 1302 { 1303 Status = AcpiOsExecute (OSL_DEBUGGER_THREAD, AcpiDbMethodThread, 1304 &AcpiGbl_DbMethodInfo); 1305 if (ACPI_FAILURE (Status)) 1306 { 1307 break; 1308 } 1309 } 1310 1311 /* Wait for all threads to complete */ 1312 1313 (void) AcpiOsWaitSemaphore (MainThreadGate, 1, ACPI_WAIT_FOREVER); 1314 1315 AcpiDbSetOutputDestination (ACPI_DB_DUPLICATE_OUTPUT); 1316 AcpiOsPrintf ("All threads (%X) have completed\n", NumThreads); 1317 AcpiDbSetOutputDestination (ACPI_DB_CONSOLE_OUTPUT); 1318 1319 CleanupAndExit: 1320 1321 /* Cleanup and exit */ 1322 1323 (void) AcpiOsDeleteSemaphore (MainThreadGate); 1324 (void) AcpiOsDeleteSemaphore (ThreadCompleteGate); 1325 (void) AcpiOsDeleteSemaphore (InfoGate); 1326 1327 AcpiOsFree (AcpiGbl_DbMethodInfo.Threads); 1328 AcpiGbl_DbMethodInfo.Threads = NULL; 1329 } 1330 1331 #endif /* ACPI_DEBUGGER */ 1332 1333 1334