1 /******************************************************************************* 2 * 3 * Module Name: dbtest - Various debug-related tests 4 * 5 ******************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 #include <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/acdebug.h> 47 #include <contrib/dev/acpica/include/acnamesp.h> 48 #include <contrib/dev/acpica/include/acpredef.h> 49 50 51 #define _COMPONENT ACPI_CA_DEBUGGER 52 ACPI_MODULE_NAME ("dbtest") 53 54 55 /* Local prototypes */ 56 57 static void 58 AcpiDbTestAllObjects ( 59 void); 60 61 static ACPI_STATUS 62 AcpiDbTestOneObject ( 63 ACPI_HANDLE ObjHandle, 64 UINT32 NestingLevel, 65 void *Context, 66 void **ReturnValue); 67 68 static ACPI_STATUS 69 AcpiDbTestIntegerType ( 70 ACPI_NAMESPACE_NODE *Node, 71 UINT32 BitLength); 72 73 static ACPI_STATUS 74 AcpiDbTestBufferType ( 75 ACPI_NAMESPACE_NODE *Node, 76 UINT32 BitLength); 77 78 static ACPI_STATUS 79 AcpiDbTestStringType ( 80 ACPI_NAMESPACE_NODE *Node, 81 UINT32 ByteLength); 82 83 static ACPI_STATUS 84 AcpiDbReadFromObject ( 85 ACPI_NAMESPACE_NODE *Node, 86 ACPI_OBJECT_TYPE ExpectedType, 87 ACPI_OBJECT **Value); 88 89 static ACPI_STATUS 90 AcpiDbWriteToObject ( 91 ACPI_NAMESPACE_NODE *Node, 92 ACPI_OBJECT *Value); 93 94 static void 95 AcpiDbEvaluateAllPredefinedNames ( 96 char *CountArg); 97 98 static ACPI_STATUS 99 AcpiDbEvaluateOnePredefinedName ( 100 ACPI_HANDLE ObjHandle, 101 UINT32 NestingLevel, 102 void *Context, 103 void **ReturnValue); 104 105 /* 106 * Test subcommands 107 */ 108 static ACPI_DB_ARGUMENT_INFO AcpiDbTestTypes [] = 109 { 110 {"OBJECTS"}, 111 {"PREDEFINED"}, 112 {NULL} /* Must be null terminated */ 113 }; 114 115 #define CMD_TEST_OBJECTS 0 116 #define CMD_TEST_PREDEFINED 1 117 118 #define BUFFER_FILL_VALUE 0xFF 119 120 /* 121 * Support for the special debugger read/write control methods. 122 * These methods are installed into the current namespace and are 123 * used to read and write the various namespace objects. The point 124 * is to force the AML interpreter do all of the work. 125 */ 126 #define ACPI_DB_READ_METHOD "\\_T98" 127 #define ACPI_DB_WRITE_METHOD "\\_T99" 128 129 static ACPI_HANDLE ReadHandle = NULL; 130 static ACPI_HANDLE WriteHandle = NULL; 131 132 /* ASL Definitions of the debugger read/write control methods */ 133 134 #if 0 135 DefinitionBlock ("ssdt.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001) 136 { 137 Method (_T98, 1, NotSerialized) /* Read */ 138 { 139 Return (DeRefOf (Arg0)) 140 } 141 } 142 DefinitionBlock ("ssdt2.aml", "SSDT", 2, "Intel", "DEBUG", 0x00000001) 143 { 144 Method (_T99, 2, NotSerialized) /* Write */ 145 { 146 Store (Arg1, Arg0) 147 } 148 } 149 #endif 150 151 static unsigned char ReadMethodCode[] = 152 { 153 0x53,0x53,0x44,0x54,0x2E,0x00,0x00,0x00, /* 00000000 "SSDT...." */ 154 0x02,0xC9,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */ 155 0x44,0x45,0x42,0x55,0x47,0x00,0x00,0x00, /* 00000010 "DEBUG..." */ 156 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ 157 0x18,0x12,0x13,0x20,0x14,0x09,0x5F,0x54, /* 00000020 "... .._T" */ 158 0x39,0x38,0x01,0xA4,0x83,0x68 /* 00000028 "98...h" */ 159 }; 160 161 static unsigned char WriteMethodCode[] = 162 { 163 0x53,0x53,0x44,0x54,0x2E,0x00,0x00,0x00, /* 00000000 "SSDT...." */ 164 0x02,0x15,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */ 165 0x44,0x45,0x42,0x55,0x47,0x00,0x00,0x00, /* 00000010 "DEBUG..." */ 166 0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */ 167 0x18,0x12,0x13,0x20,0x14,0x09,0x5F,0x54, /* 00000020 "... .._T" */ 168 0x39,0x39,0x02,0x70,0x69,0x68 /* 00000028 "99.pih" */ 169 }; 170 171 172 /******************************************************************************* 173 * 174 * FUNCTION: AcpiDbExecuteTest 175 * 176 * PARAMETERS: TypeArg - Subcommand 177 * 178 * RETURN: None 179 * 180 * DESCRIPTION: Execute various debug tests. 181 * 182 * Note: Code is prepared for future expansion of the TEST command. 183 * 184 ******************************************************************************/ 185 186 void 187 AcpiDbExecuteTest ( 188 char *TypeArg) 189 { 190 UINT32 Temp; 191 192 193 AcpiUtStrupr (TypeArg); 194 Temp = AcpiDbMatchArgument (TypeArg, AcpiDbTestTypes); 195 if (Temp == ACPI_TYPE_NOT_FOUND) 196 { 197 AcpiOsPrintf ("Invalid or unsupported argument\n"); 198 return; 199 } 200 201 switch (Temp) 202 { 203 case CMD_TEST_OBJECTS: 204 205 AcpiDbTestAllObjects (); 206 break; 207 208 case CMD_TEST_PREDEFINED: 209 210 AcpiDbEvaluateAllPredefinedNames (NULL); 211 break; 212 213 default: 214 break; 215 } 216 } 217 218 219 /******************************************************************************* 220 * 221 * FUNCTION: AcpiDbTestAllObjects 222 * 223 * PARAMETERS: None 224 * 225 * RETURN: None 226 * 227 * DESCRIPTION: This test implements the OBJECTS subcommand. It exercises the 228 * namespace by reading/writing/comparing all data objects such 229 * as integers, strings, buffers, fields, buffer fields, etc. 230 * 231 ******************************************************************************/ 232 233 static void 234 AcpiDbTestAllObjects ( 235 void) 236 { 237 ACPI_STATUS Status; 238 239 240 /* Install the debugger read-object control method if necessary */ 241 242 if (!ReadHandle) 243 { 244 Status = AcpiInstallMethod (ReadMethodCode); 245 if (ACPI_FAILURE (Status)) 246 { 247 AcpiOsPrintf ("%s, Could not install debugger read method\n", 248 AcpiFormatException (Status)); 249 return; 250 } 251 252 Status = AcpiGetHandle (NULL, ACPI_DB_READ_METHOD, &ReadHandle); 253 if (ACPI_FAILURE (Status)) 254 { 255 AcpiOsPrintf ("Could not obtain handle for debug method %s\n", 256 ACPI_DB_READ_METHOD); 257 return; 258 } 259 } 260 261 /* Install the debugger write-object control method if necessary */ 262 263 if (!WriteHandle) 264 { 265 Status = AcpiInstallMethod (WriteMethodCode); 266 if (ACPI_FAILURE (Status)) 267 { 268 AcpiOsPrintf ("%s, Could not install debugger write method\n", 269 AcpiFormatException (Status)); 270 return; 271 } 272 273 Status = AcpiGetHandle (NULL, ACPI_DB_WRITE_METHOD, &WriteHandle); 274 if (ACPI_FAILURE (Status)) 275 { 276 AcpiOsPrintf ("Could not obtain handle for debug method %s\n", 277 ACPI_DB_WRITE_METHOD); 278 return; 279 } 280 } 281 282 /* Walk the entire namespace, testing each supported named data object */ 283 284 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 285 ACPI_UINT32_MAX, AcpiDbTestOneObject, NULL, NULL, NULL); 286 } 287 288 289 /******************************************************************************* 290 * 291 * FUNCTION: AcpiDbTestOneObject 292 * 293 * PARAMETERS: ACPI_WALK_CALLBACK 294 * 295 * RETURN: Status 296 * 297 * DESCRIPTION: Test one namespace object. Supported types are Integer, 298 * String, Buffer, BufferField, and FieldUnit. All other object 299 * types are simply ignored. 300 * 301 * Note: Support for Packages is not implemented. 302 * 303 ******************************************************************************/ 304 305 static ACPI_STATUS 306 AcpiDbTestOneObject ( 307 ACPI_HANDLE ObjHandle, 308 UINT32 NestingLevel, 309 void *Context, 310 void **ReturnValue) 311 { 312 ACPI_NAMESPACE_NODE *Node; 313 ACPI_OPERAND_OBJECT *ObjDesc; 314 ACPI_OPERAND_OBJECT *RegionObj; 315 ACPI_OBJECT_TYPE LocalType; 316 UINT32 BitLength = 0; 317 UINT32 ByteLength = 0; 318 ACPI_STATUS Status = AE_OK; 319 320 321 Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, ObjHandle); 322 ObjDesc = Node->Object; 323 324 /* 325 * For the supported types, get the actual bit length or 326 * byte length. Map the type to one of Integer/String/Buffer. 327 */ 328 switch (Node->Type) 329 { 330 case ACPI_TYPE_INTEGER: 331 332 /* Integer width is either 32 or 64 */ 333 334 LocalType = ACPI_TYPE_INTEGER; 335 BitLength = AcpiGbl_IntegerBitWidth; 336 break; 337 338 case ACPI_TYPE_STRING: 339 340 LocalType = ACPI_TYPE_STRING; 341 ByteLength = ObjDesc->String.Length; 342 break; 343 344 case ACPI_TYPE_BUFFER: 345 346 LocalType = ACPI_TYPE_BUFFER; 347 ByteLength = ObjDesc->Buffer.Length; 348 BitLength = ByteLength * 8; 349 break; 350 351 case ACPI_TYPE_FIELD_UNIT: 352 case ACPI_TYPE_BUFFER_FIELD: 353 case ACPI_TYPE_LOCAL_REGION_FIELD: 354 case ACPI_TYPE_LOCAL_INDEX_FIELD: 355 case ACPI_TYPE_LOCAL_BANK_FIELD: 356 357 LocalType = ACPI_TYPE_INTEGER; 358 if (ObjDesc) 359 { 360 /* 361 * Returned object will be a Buffer if the field length 362 * is larger than the size of an Integer (32 or 64 bits 363 * depending on the DSDT version). 364 */ 365 BitLength = ObjDesc->CommonField.BitLength; 366 ByteLength = ACPI_ROUND_BITS_UP_TO_BYTES (BitLength); 367 if (BitLength > AcpiGbl_IntegerBitWidth) 368 { 369 LocalType = ACPI_TYPE_BUFFER; 370 } 371 } 372 break; 373 374 default: 375 376 /* Ignore all other types */ 377 378 return (AE_OK); 379 } 380 381 /* Emit the common prefix: Type:Name */ 382 383 AcpiOsPrintf ("%14s: %4.4s", 384 AcpiUtGetTypeName (Node->Type), Node->Name.Ascii); 385 if (!ObjDesc) 386 { 387 AcpiOsPrintf (" Ignoring, no attached object\n"); 388 return (AE_OK); 389 } 390 391 /* 392 * Check for unsupported region types. Note: AcpiExec simulates 393 * access to SystemMemory, SystemIO, PCI_Config, and EC. 394 */ 395 switch (Node->Type) 396 { 397 case ACPI_TYPE_LOCAL_REGION_FIELD: 398 399 RegionObj = ObjDesc->Field.RegionObj; 400 switch (RegionObj->Region.SpaceId) 401 { 402 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 403 case ACPI_ADR_SPACE_SYSTEM_IO: 404 case ACPI_ADR_SPACE_PCI_CONFIG: 405 case ACPI_ADR_SPACE_EC: 406 407 break; 408 409 default: 410 411 AcpiOsPrintf (" %s space is not supported [%4.4s]\n", 412 AcpiUtGetRegionName (RegionObj->Region.SpaceId), 413 RegionObj->Region.Node->Name.Ascii); 414 return (AE_OK); 415 } 416 break; 417 418 default: 419 break; 420 } 421 422 /* At this point, we have resolved the object to one of the major types */ 423 424 switch (LocalType) 425 { 426 case ACPI_TYPE_INTEGER: 427 428 Status = AcpiDbTestIntegerType (Node, BitLength); 429 break; 430 431 case ACPI_TYPE_STRING: 432 433 Status = AcpiDbTestStringType (Node, ByteLength); 434 break; 435 436 case ACPI_TYPE_BUFFER: 437 438 Status = AcpiDbTestBufferType (Node, BitLength); 439 break; 440 441 default: 442 443 AcpiOsPrintf (" Ignoring, type not implemented (%2.2X)", 444 LocalType); 445 break; 446 } 447 448 switch (Node->Type) 449 { 450 case ACPI_TYPE_LOCAL_REGION_FIELD: 451 452 RegionObj = ObjDesc->Field.RegionObj; 453 AcpiOsPrintf (" (%s)", 454 AcpiUtGetRegionName (RegionObj->Region.SpaceId)); 455 break; 456 457 default: 458 break; 459 } 460 461 AcpiOsPrintf ("\n"); 462 return (Status); 463 } 464 465 466 /******************************************************************************* 467 * 468 * FUNCTION: AcpiDbTestIntegerType 469 * 470 * PARAMETERS: Node - Parent NS node for the object 471 * BitLength - Actual length of the object. Used for 472 * support of arbitrary length FieldUnit 473 * and BufferField objects. 474 * 475 * RETURN: Status 476 * 477 * DESCRIPTION: Test read/write for an Integer-valued object. Performs a 478 * write/read/compare of an arbitrary new value, then performs 479 * a write/read/compare of the original value. 480 * 481 ******************************************************************************/ 482 483 static ACPI_STATUS 484 AcpiDbTestIntegerType ( 485 ACPI_NAMESPACE_NODE *Node, 486 UINT32 BitLength) 487 { 488 ACPI_OBJECT *Temp1 = NULL; 489 ACPI_OBJECT *Temp2 = NULL; 490 ACPI_OBJECT *Temp3 = NULL; 491 ACPI_OBJECT WriteValue; 492 UINT64 ValueToWrite; 493 ACPI_STATUS Status; 494 495 496 if (BitLength > 64) 497 { 498 AcpiOsPrintf (" Invalid length for an Integer: %u", BitLength); 499 return (AE_OK); 500 } 501 502 /* Read the original value */ 503 504 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp1); 505 if (ACPI_FAILURE (Status)) 506 { 507 return (Status); 508 } 509 510 AcpiOsPrintf (" (%4.4X/%3.3X) %8.8X%8.8X", 511 BitLength, ACPI_ROUND_BITS_UP_TO_BYTES (BitLength), 512 ACPI_FORMAT_UINT64 (Temp1->Integer.Value)); 513 514 ValueToWrite = ACPI_UINT64_MAX >> (64 - BitLength); 515 if (Temp1->Integer.Value == ValueToWrite) 516 { 517 ValueToWrite = 0; 518 } 519 520 /* Write a new value */ 521 522 WriteValue.Type = ACPI_TYPE_INTEGER; 523 WriteValue.Integer.Value = ValueToWrite; 524 Status = AcpiDbWriteToObject (Node, &WriteValue); 525 if (ACPI_FAILURE (Status)) 526 { 527 goto Exit; 528 } 529 530 /* Ensure that we can read back the new value */ 531 532 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp2); 533 if (ACPI_FAILURE (Status)) 534 { 535 goto Exit; 536 } 537 538 if (Temp2->Integer.Value != ValueToWrite) 539 { 540 AcpiOsPrintf (" MISMATCH 2: %8.8X%8.8X, expecting %8.8X%8.8X", 541 ACPI_FORMAT_UINT64 (Temp2->Integer.Value), 542 ACPI_FORMAT_UINT64 (ValueToWrite)); 543 } 544 545 /* Write back the original value */ 546 547 WriteValue.Integer.Value = Temp1->Integer.Value; 548 Status = AcpiDbWriteToObject (Node, &WriteValue); 549 if (ACPI_FAILURE (Status)) 550 { 551 goto Exit; 552 } 553 554 /* Ensure that we can read back the original value */ 555 556 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_INTEGER, &Temp3); 557 if (ACPI_FAILURE (Status)) 558 { 559 goto Exit; 560 } 561 562 if (Temp3->Integer.Value != Temp1->Integer.Value) 563 { 564 AcpiOsPrintf (" MISMATCH 3: %8.8X%8.8X, expecting %8.8X%8.8X", 565 ACPI_FORMAT_UINT64 (Temp3->Integer.Value), 566 ACPI_FORMAT_UINT64 (Temp1->Integer.Value)); 567 } 568 569 Exit: 570 if (Temp1) {AcpiOsFree (Temp1);} 571 if (Temp2) {AcpiOsFree (Temp2);} 572 if (Temp3) {AcpiOsFree (Temp3);} 573 return (AE_OK); 574 } 575 576 577 /******************************************************************************* 578 * 579 * FUNCTION: AcpiDbTestBufferType 580 * 581 * PARAMETERS: Node - Parent NS node for the object 582 * BitLength - Actual length of the object. 583 * 584 * RETURN: Status 585 * 586 * DESCRIPTION: Test read/write for an Buffer-valued object. Performs a 587 * write/read/compare of an arbitrary new value, then performs 588 * a write/read/compare of the original value. 589 * 590 ******************************************************************************/ 591 592 static ACPI_STATUS 593 AcpiDbTestBufferType ( 594 ACPI_NAMESPACE_NODE *Node, 595 UINT32 BitLength) 596 { 597 ACPI_OBJECT *Temp1 = NULL; 598 ACPI_OBJECT *Temp2 = NULL; 599 ACPI_OBJECT *Temp3 = NULL; 600 UINT8 *Buffer; 601 ACPI_OBJECT WriteValue; 602 ACPI_STATUS Status; 603 UINT32 ByteLength; 604 UINT32 i; 605 UINT8 ExtraBits; 606 607 608 ByteLength = ACPI_ROUND_BITS_UP_TO_BYTES (BitLength); 609 if (ByteLength == 0) 610 { 611 AcpiOsPrintf (" Ignoring zero length buffer"); 612 return (AE_OK); 613 } 614 615 /* Allocate a local buffer */ 616 617 Buffer = ACPI_ALLOCATE_ZEROED (ByteLength); 618 if (!Buffer) 619 { 620 return (AE_NO_MEMORY); 621 } 622 623 /* Read the original value */ 624 625 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp1); 626 if (ACPI_FAILURE (Status)) 627 { 628 goto Exit; 629 } 630 631 /* Emit a few bytes of the buffer */ 632 633 AcpiOsPrintf (" (%4.4X/%3.3X)", BitLength, Temp1->Buffer.Length); 634 for (i = 0; ((i < 4) && (i < ByteLength)); i++) 635 { 636 AcpiOsPrintf (" %2.2X", Temp1->Buffer.Pointer[i]); 637 } 638 AcpiOsPrintf ("... "); 639 640 /* 641 * Write a new value. 642 * 643 * Handle possible extra bits at the end of the buffer. Can 644 * happen for FieldUnits larger than an integer, but the bit 645 * count is not an integral number of bytes. Zero out the 646 * unused bits. 647 */ 648 memset (Buffer, BUFFER_FILL_VALUE, ByteLength); 649 ExtraBits = BitLength % 8; 650 if (ExtraBits) 651 { 652 Buffer [ByteLength - 1] = ACPI_MASK_BITS_ABOVE (ExtraBits); 653 } 654 655 WriteValue.Type = ACPI_TYPE_BUFFER; 656 WriteValue.Buffer.Length = ByteLength; 657 WriteValue.Buffer.Pointer = Buffer; 658 659 Status = AcpiDbWriteToObject (Node, &WriteValue); 660 if (ACPI_FAILURE (Status)) 661 { 662 goto Exit; 663 } 664 665 /* Ensure that we can read back the new value */ 666 667 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp2); 668 if (ACPI_FAILURE (Status)) 669 { 670 goto Exit; 671 } 672 673 if (memcmp (Temp2->Buffer.Pointer, Buffer, ByteLength)) 674 { 675 AcpiOsPrintf (" MISMATCH 2: New buffer value"); 676 } 677 678 /* Write back the original value */ 679 680 WriteValue.Buffer.Length = ByteLength; 681 WriteValue.Buffer.Pointer = Temp1->Buffer.Pointer; 682 683 Status = AcpiDbWriteToObject (Node, &WriteValue); 684 if (ACPI_FAILURE (Status)) 685 { 686 goto Exit; 687 } 688 689 /* Ensure that we can read back the original value */ 690 691 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_BUFFER, &Temp3); 692 if (ACPI_FAILURE (Status)) 693 { 694 goto Exit; 695 } 696 697 if (memcmp (Temp1->Buffer.Pointer, 698 Temp3->Buffer.Pointer, ByteLength)) 699 { 700 AcpiOsPrintf (" MISMATCH 3: While restoring original buffer"); 701 } 702 703 Exit: 704 ACPI_FREE (Buffer); 705 if (Temp1) {AcpiOsFree (Temp1);} 706 if (Temp2) {AcpiOsFree (Temp2);} 707 if (Temp3) {AcpiOsFree (Temp3);} 708 return (Status); 709 } 710 711 712 /******************************************************************************* 713 * 714 * FUNCTION: AcpiDbTestStringType 715 * 716 * PARAMETERS: Node - Parent NS node for the object 717 * ByteLength - Actual length of the object. 718 * 719 * RETURN: Status 720 * 721 * DESCRIPTION: Test read/write for an String-valued object. Performs a 722 * write/read/compare of an arbitrary new value, then performs 723 * a write/read/compare of the original value. 724 * 725 ******************************************************************************/ 726 727 static ACPI_STATUS 728 AcpiDbTestStringType ( 729 ACPI_NAMESPACE_NODE *Node, 730 UINT32 ByteLength) 731 { 732 ACPI_OBJECT *Temp1 = NULL; 733 ACPI_OBJECT *Temp2 = NULL; 734 ACPI_OBJECT *Temp3 = NULL; 735 char *ValueToWrite = "Test String from AML Debugger"; 736 ACPI_OBJECT WriteValue; 737 ACPI_STATUS Status; 738 739 740 /* Read the original value */ 741 742 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp1); 743 if (ACPI_FAILURE (Status)) 744 { 745 return (Status); 746 } 747 748 AcpiOsPrintf (" (%4.4X/%3.3X) \"%s\"", (Temp1->String.Length * 8), 749 Temp1->String.Length, Temp1->String.Pointer); 750 751 /* Write a new value */ 752 753 WriteValue.Type = ACPI_TYPE_STRING; 754 WriteValue.String.Length = strlen (ValueToWrite); 755 WriteValue.String.Pointer = ValueToWrite; 756 757 Status = AcpiDbWriteToObject (Node, &WriteValue); 758 if (ACPI_FAILURE (Status)) 759 { 760 goto Exit; 761 } 762 763 /* Ensure that we can read back the new value */ 764 765 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp2); 766 if (ACPI_FAILURE (Status)) 767 { 768 goto Exit; 769 } 770 771 if (strcmp (Temp2->String.Pointer, ValueToWrite)) 772 { 773 AcpiOsPrintf (" MISMATCH 2: %s, expecting %s", 774 Temp2->String.Pointer, ValueToWrite); 775 } 776 777 /* Write back the original value */ 778 779 WriteValue.String.Length = strlen (Temp1->String.Pointer); 780 WriteValue.String.Pointer = Temp1->String.Pointer; 781 782 Status = AcpiDbWriteToObject (Node, &WriteValue); 783 if (ACPI_FAILURE (Status)) 784 { 785 goto Exit; 786 } 787 788 /* Ensure that we can read back the original value */ 789 790 Status = AcpiDbReadFromObject (Node, ACPI_TYPE_STRING, &Temp3); 791 if (ACPI_FAILURE (Status)) 792 { 793 goto Exit; 794 } 795 796 if (strcmp (Temp1->String.Pointer, Temp3->String.Pointer)) 797 { 798 AcpiOsPrintf (" MISMATCH 3: %s, expecting %s", 799 Temp3->String.Pointer, Temp1->String.Pointer); 800 } 801 802 Exit: 803 if (Temp1) {AcpiOsFree (Temp1);} 804 if (Temp2) {AcpiOsFree (Temp2);} 805 if (Temp3) {AcpiOsFree (Temp3);} 806 return (Status); 807 } 808 809 810 /******************************************************************************* 811 * 812 * FUNCTION: AcpiDbReadFromObject 813 * 814 * PARAMETERS: Node - Parent NS node for the object 815 * ExpectedType - Object type expected from the read 816 * Value - Where the value read is returned 817 * 818 * RETURN: Status 819 * 820 * DESCRIPTION: Performs a read from the specified object by invoking the 821 * special debugger control method that reads the object. Thus, 822 * the AML interpreter is doing all of the work, increasing the 823 * validity of the test. 824 * 825 ******************************************************************************/ 826 827 static ACPI_STATUS 828 AcpiDbReadFromObject ( 829 ACPI_NAMESPACE_NODE *Node, 830 ACPI_OBJECT_TYPE ExpectedType, 831 ACPI_OBJECT **Value) 832 { 833 ACPI_OBJECT *RetValue; 834 ACPI_OBJECT_LIST ParamObjects; 835 ACPI_OBJECT Params[2]; 836 ACPI_BUFFER ReturnObj; 837 ACPI_STATUS Status; 838 839 840 Params[0].Type = ACPI_TYPE_LOCAL_REFERENCE; 841 Params[0].Reference.ActualType = Node->Type; 842 Params[0].Reference.Handle = ACPI_CAST_PTR (ACPI_HANDLE, Node); 843 844 ParamObjects.Count = 1; 845 ParamObjects.Pointer = Params; 846 847 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 848 849 AcpiGbl_MethodExecuting = TRUE; 850 Status = AcpiEvaluateObject (ReadHandle, NULL, 851 &ParamObjects, &ReturnObj); 852 AcpiGbl_MethodExecuting = FALSE; 853 854 if (ACPI_FAILURE (Status)) 855 { 856 AcpiOsPrintf ("Could not read from object, %s", 857 AcpiFormatException (Status)); 858 return (Status); 859 } 860 861 RetValue = (ACPI_OBJECT *) ReturnObj.Pointer; 862 863 switch (RetValue->Type) 864 { 865 case ACPI_TYPE_INTEGER: 866 case ACPI_TYPE_BUFFER: 867 case ACPI_TYPE_STRING: 868 /* 869 * Did we receive the type we wanted? Most important for the 870 * Integer/Buffer case (when a field is larger than an Integer, 871 * it should return a Buffer). 872 */ 873 if (RetValue->Type != ExpectedType) 874 { 875 AcpiOsPrintf (" Type mismatch: Expected %s, Received %s", 876 AcpiUtGetTypeName (ExpectedType), 877 AcpiUtGetTypeName (RetValue->Type)); 878 879 return (AE_TYPE); 880 } 881 882 *Value = RetValue; 883 break; 884 885 default: 886 887 AcpiOsPrintf (" Unsupported return object type, %s", 888 AcpiUtGetTypeName (RetValue->Type)); 889 890 AcpiOsFree (ReturnObj.Pointer); 891 return (AE_TYPE); 892 } 893 894 return (Status); 895 } 896 897 898 /******************************************************************************* 899 * 900 * FUNCTION: AcpiDbWriteToObject 901 * 902 * PARAMETERS: Node - Parent NS node for the object 903 * Value - Value to be written 904 * 905 * RETURN: Status 906 * 907 * DESCRIPTION: Performs a write to the specified object by invoking the 908 * special debugger control method that writes the object. Thus, 909 * the AML interpreter is doing all of the work, increasing the 910 * validity of the test. 911 * 912 ******************************************************************************/ 913 914 static ACPI_STATUS 915 AcpiDbWriteToObject ( 916 ACPI_NAMESPACE_NODE *Node, 917 ACPI_OBJECT *Value) 918 { 919 ACPI_OBJECT_LIST ParamObjects; 920 ACPI_OBJECT Params[2]; 921 ACPI_STATUS Status; 922 923 924 Params[0].Type = ACPI_TYPE_LOCAL_REFERENCE; 925 Params[0].Reference.ActualType = Node->Type; 926 Params[0].Reference.Handle = ACPI_CAST_PTR (ACPI_HANDLE, Node); 927 928 /* Copy the incoming user parameter */ 929 930 memcpy (&Params[1], Value, sizeof (ACPI_OBJECT)); 931 932 ParamObjects.Count = 2; 933 ParamObjects.Pointer = Params; 934 935 AcpiGbl_MethodExecuting = TRUE; 936 Status = AcpiEvaluateObject (WriteHandle, NULL, &ParamObjects, NULL); 937 AcpiGbl_MethodExecuting = FALSE; 938 939 if (ACPI_FAILURE (Status)) 940 { 941 AcpiOsPrintf ("Could not write to object, %s", 942 AcpiFormatException (Status)); 943 } 944 945 return (Status); 946 } 947 948 949 /******************************************************************************* 950 * 951 * FUNCTION: AcpiDbEvaluateAllPredefinedNames 952 * 953 * PARAMETERS: CountArg - Max number of methods to execute 954 * 955 * RETURN: None 956 * 957 * DESCRIPTION: Namespace batch execution. Execute predefined names in the 958 * namespace, up to the max count, if specified. 959 * 960 ******************************************************************************/ 961 962 static void 963 AcpiDbEvaluateAllPredefinedNames ( 964 char *CountArg) 965 { 966 ACPI_DB_EXECUTE_WALK Info; 967 968 969 Info.Count = 0; 970 Info.MaxCount = ACPI_UINT32_MAX; 971 972 if (CountArg) 973 { 974 Info.MaxCount = strtoul (CountArg, NULL, 0); 975 } 976 977 /* Search all nodes in namespace */ 978 979 (void) AcpiWalkNamespace (ACPI_TYPE_ANY, ACPI_ROOT_OBJECT, 980 ACPI_UINT32_MAX, AcpiDbEvaluateOnePredefinedName, NULL, 981 (void *) &Info, NULL); 982 983 AcpiOsPrintf ( 984 "Evaluated %u predefined names in the namespace\n", Info.Count); 985 } 986 987 988 /******************************************************************************* 989 * 990 * FUNCTION: AcpiDbEvaluateOnePredefinedName 991 * 992 * PARAMETERS: Callback from WalkNamespace 993 * 994 * RETURN: Status 995 * 996 * DESCRIPTION: Batch execution module. Currently only executes predefined 997 * ACPI names. 998 * 999 ******************************************************************************/ 1000 1001 static ACPI_STATUS 1002 AcpiDbEvaluateOnePredefinedName ( 1003 ACPI_HANDLE ObjHandle, 1004 UINT32 NestingLevel, 1005 void *Context, 1006 void **ReturnValue) 1007 { 1008 ACPI_NAMESPACE_NODE *Node = (ACPI_NAMESPACE_NODE *) ObjHandle; 1009 ACPI_DB_EXECUTE_WALK *Info = (ACPI_DB_EXECUTE_WALK *) Context; 1010 char *Pathname; 1011 const ACPI_PREDEFINED_INFO *Predefined; 1012 ACPI_DEVICE_INFO *ObjInfo; 1013 ACPI_OBJECT_LIST ParamObjects; 1014 ACPI_OBJECT Params[ACPI_METHOD_NUM_ARGS]; 1015 ACPI_OBJECT *ThisParam; 1016 ACPI_BUFFER ReturnObj; 1017 ACPI_STATUS Status; 1018 UINT16 ArgTypeList; 1019 UINT8 ArgCount; 1020 UINT8 ArgType; 1021 UINT32 i; 1022 1023 1024 /* The name must be a predefined ACPI name */ 1025 1026 Predefined = AcpiUtMatchPredefinedMethod (Node->Name.Ascii); 1027 if (!Predefined) 1028 { 1029 return (AE_OK); 1030 } 1031 1032 if (Node->Type == ACPI_TYPE_LOCAL_SCOPE) 1033 { 1034 return (AE_OK); 1035 } 1036 1037 Pathname = AcpiNsGetNormalizedPathname (Node, TRUE); 1038 if (!Pathname) 1039 { 1040 return (AE_OK); 1041 } 1042 1043 /* Get the object info for number of method parameters */ 1044 1045 Status = AcpiGetObjectInfo (ObjHandle, &ObjInfo); 1046 if (ACPI_FAILURE (Status)) 1047 { 1048 ACPI_FREE (Pathname); 1049 return (Status); 1050 } 1051 1052 ParamObjects.Count = 0; 1053 ParamObjects.Pointer = NULL; 1054 1055 if (ObjInfo->Type == ACPI_TYPE_METHOD) 1056 { 1057 /* Setup default parameters (with proper types) */ 1058 1059 ArgTypeList = Predefined->Info.ArgumentList; 1060 ArgCount = METHOD_GET_ARG_COUNT (ArgTypeList); 1061 1062 /* 1063 * Setup the ACPI-required number of arguments, regardless of what 1064 * the actual method defines. If there is a difference, then the 1065 * method is wrong and a warning will be issued during execution. 1066 */ 1067 ThisParam = Params; 1068 for (i = 0; i < ArgCount; i++) 1069 { 1070 ArgType = METHOD_GET_NEXT_TYPE (ArgTypeList); 1071 ThisParam->Type = ArgType; 1072 1073 switch (ArgType) 1074 { 1075 case ACPI_TYPE_INTEGER: 1076 1077 ThisParam->Integer.Value = 1; 1078 break; 1079 1080 case ACPI_TYPE_STRING: 1081 1082 ThisParam->String.Pointer = 1083 "This is the default argument string"; 1084 ThisParam->String.Length = 1085 strlen (ThisParam->String.Pointer); 1086 break; 1087 1088 case ACPI_TYPE_BUFFER: 1089 1090 ThisParam->Buffer.Pointer = (UINT8 *) Params; /* just a garbage buffer */ 1091 ThisParam->Buffer.Length = 48; 1092 break; 1093 1094 case ACPI_TYPE_PACKAGE: 1095 1096 ThisParam->Package.Elements = NULL; 1097 ThisParam->Package.Count = 0; 1098 break; 1099 1100 default: 1101 1102 AcpiOsPrintf ("%s: Unsupported argument type: %u\n", 1103 Pathname, ArgType); 1104 break; 1105 } 1106 1107 ThisParam++; 1108 } 1109 1110 ParamObjects.Count = ArgCount; 1111 ParamObjects.Pointer = Params; 1112 } 1113 1114 ACPI_FREE (ObjInfo); 1115 ReturnObj.Pointer = NULL; 1116 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 1117 1118 /* Do the actual method execution */ 1119 1120 AcpiGbl_MethodExecuting = TRUE; 1121 1122 Status = AcpiEvaluateObject (Node, NULL, &ParamObjects, &ReturnObj); 1123 1124 AcpiOsPrintf ("%-32s returned %s\n", 1125 Pathname, AcpiFormatException (Status)); 1126 AcpiGbl_MethodExecuting = FALSE; 1127 ACPI_FREE (Pathname); 1128 1129 /* Ignore status from method execution */ 1130 1131 Status = AE_OK; 1132 1133 /* Update count, check if we have executed enough methods */ 1134 1135 Info->Count++; 1136 if (Info->Count >= Info->MaxCount) 1137 { 1138 Status = AE_CTRL_TERMINATE; 1139 } 1140 1141 return (Status); 1142 } 1143