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