1 /****************************************************************************** 2 * 3 * Module Name: aehandlers - Various handlers for acpiexec 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2011, 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 "aecommon.h" 45 46 #define _COMPONENT ACPI_TOOLS 47 ACPI_MODULE_NAME ("aehandlers") 48 49 /* Local prototypes */ 50 51 static void 52 AeNotifyHandler ( 53 ACPI_HANDLE Device, 54 UINT32 Value, 55 void *Context); 56 57 static void 58 AeDeviceNotifyHandler ( 59 ACPI_HANDLE Device, 60 UINT32 Value, 61 void *Context); 62 63 static ACPI_STATUS 64 AeExceptionHandler ( 65 ACPI_STATUS AmlStatus, 66 ACPI_NAME Name, 67 UINT16 Opcode, 68 UINT32 AmlOffset, 69 void *Context); 70 71 static ACPI_STATUS 72 AeTableHandler ( 73 UINT32 Event, 74 void *Table, 75 void *Context); 76 77 static ACPI_STATUS 78 AeRegionInit ( 79 ACPI_HANDLE RegionHandle, 80 UINT32 Function, 81 void *HandlerContext, 82 void **RegionContext); 83 84 static void 85 AeAttachedDataHandler ( 86 ACPI_HANDLE Object, 87 void *Data); 88 89 static UINT32 90 AeInterfaceHandler ( 91 ACPI_STRING InterfaceName, 92 UINT32 Supported); 93 94 static UINT32 95 AeEventHandler ( 96 void *Context); 97 98 static UINT32 SigintCount = 0; 99 static AE_DEBUG_REGIONS AeRegions; 100 101 102 /* 103 * We will override some of the default region handlers, especially the 104 * SystemMemory handler, which must be implemented locally. Do not override 105 * the PCI_Config handler since we would like to exercise the default handler 106 * code. These handlers are installed "early" - before any _REG methods 107 * are executed - since they are special in the sense that tha ACPI spec 108 * declares that they must "always be available". Cannot override the 109 * DataTable region handler either -- needed for test execution. 110 */ 111 static ACPI_ADR_SPACE_TYPE DefaultSpaceIdList[] = { 112 ACPI_ADR_SPACE_SYSTEM_MEMORY, 113 ACPI_ADR_SPACE_SYSTEM_IO 114 }; 115 116 /* 117 * We will install handlers for some of the various address space IDs 118 * Test one user-defined address space (used by aslts.) 119 */ 120 #define ACPI_ADR_SPACE_USER_DEFINED 0x80 121 122 static ACPI_ADR_SPACE_TYPE SpaceIdList[] = { 123 ACPI_ADR_SPACE_EC, 124 ACPI_ADR_SPACE_SMBUS, 125 ACPI_ADR_SPACE_PCI_BAR_TARGET, 126 ACPI_ADR_SPACE_IPMI, 127 ACPI_ADR_SPACE_FIXED_HARDWARE, 128 ACPI_ADR_SPACE_USER_DEFINED 129 }; 130 131 132 /****************************************************************************** 133 * 134 * FUNCTION: AeCtrlCHandler 135 * 136 * PARAMETERS: Sig 137 * 138 * RETURN: none 139 * 140 * DESCRIPTION: Control-C handler. Abort running control method if any. 141 * 142 *****************************************************************************/ 143 144 void ACPI_SYSTEM_XFACE 145 AeCtrlCHandler ( 146 int Sig) 147 { 148 149 signal (SIGINT, SIG_IGN); 150 SigintCount++; 151 152 AcpiOsPrintf ("Caught a ctrl-c (#%u)\n\n", SigintCount); 153 154 if (AcpiGbl_MethodExecuting) 155 { 156 AcpiGbl_AbortMethod = TRUE; 157 signal (SIGINT, AeCtrlCHandler); 158 159 if (SigintCount < 10) 160 { 161 return; 162 } 163 } 164 165 exit (0); 166 } 167 168 169 /****************************************************************************** 170 * 171 * FUNCTION: AeNotifyHandler 172 * 173 * PARAMETERS: Standard notify handler parameters 174 * 175 * RETURN: Status 176 * 177 * DESCRIPTION: System notify handler for AcpiExec utility. Used by the ASL 178 * test suite(s) to communicate errors and other information to 179 * this utility via the Notify() operator. 180 * 181 *****************************************************************************/ 182 183 static void 184 AeNotifyHandler ( 185 ACPI_HANDLE Device, 186 UINT32 Value, 187 void *Context) 188 { 189 190 switch (Value) 191 { 192 #if 0 193 case 0: 194 printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value); 195 if (AcpiGbl_DebugFile) 196 { 197 AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n"); 198 } 199 break; 200 201 202 case 1: 203 printf ("[AcpiExec] Method Error: Incorrect numeric result\n"); 204 if (AcpiGbl_DebugFile) 205 { 206 AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n"); 207 } 208 break; 209 210 211 case 2: 212 printf ("[AcpiExec] Method Error: An operand was overwritten\n"); 213 if (AcpiGbl_DebugFile) 214 { 215 AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n"); 216 } 217 break; 218 219 #endif 220 221 default: 222 printf ("[AcpiExec] Received a System Notify on [%4.4s] %p Value 0x%2.2X (%s)\n", 223 AcpiUtGetNodeName (Device), Device, Value, 224 AcpiUtGetNotifyName (Value)); 225 if (AcpiGbl_DebugFile) 226 { 227 AcpiOsPrintf ("[AcpiExec] Received a system notify, Value 0x%2.2X\n", Value); 228 } 229 230 (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL); 231 break; 232 } 233 } 234 235 236 /****************************************************************************** 237 * 238 * FUNCTION: AeDeviceNotifyHandler 239 * 240 * PARAMETERS: Standard notify handler parameters 241 * 242 * RETURN: Status 243 * 244 * DESCRIPTION: Device notify handler for AcpiExec utility. Used by the ASL 245 * test suite(s) to communicate errors and other information to 246 * this utility via the Notify() operator. 247 * 248 *****************************************************************************/ 249 250 static void 251 AeDeviceNotifyHandler ( 252 ACPI_HANDLE Device, 253 UINT32 Value, 254 void *Context) 255 { 256 257 printf ("[AcpiExec] Received a Device Notify on [%4.4s] %p Value 0x%2.2X (%s)\n", 258 AcpiUtGetNodeName (Device), Device, Value, 259 AcpiUtGetNotifyName (Value)); 260 if (AcpiGbl_DebugFile) 261 { 262 AcpiOsPrintf ("[AcpiExec] Received a device notify, Value 0x%2.2X\n", Value); 263 } 264 265 (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL); 266 } 267 268 269 /****************************************************************************** 270 * 271 * FUNCTION: AeExceptionHandler 272 * 273 * PARAMETERS: Standard exception handler parameters 274 * 275 * RETURN: Status 276 * 277 * DESCRIPTION: System exception handler for AcpiExec utility. 278 * 279 *****************************************************************************/ 280 281 static ACPI_STATUS 282 AeExceptionHandler ( 283 ACPI_STATUS AmlStatus, 284 ACPI_NAME Name, 285 UINT16 Opcode, 286 UINT32 AmlOffset, 287 void *Context) 288 { 289 ACPI_STATUS NewAmlStatus = AmlStatus; 290 ACPI_STATUS Status; 291 ACPI_BUFFER ReturnObj; 292 ACPI_OBJECT_LIST ArgList; 293 ACPI_OBJECT Arg[3]; 294 const char *Exception; 295 296 297 Exception = AcpiFormatException (AmlStatus); 298 AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception); 299 if (Name) 300 { 301 AcpiOsPrintf ("of method [%4.4s]", (char *) &Name); 302 } 303 else 304 { 305 AcpiOsPrintf ("at module level (table load)"); 306 } 307 AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset); 308 309 /* 310 * Invoke the _ERR method if present 311 * 312 * Setup parameter object 313 */ 314 ArgList.Count = 3; 315 ArgList.Pointer = Arg; 316 317 Arg[0].Type = ACPI_TYPE_INTEGER; 318 Arg[0].Integer.Value = AmlStatus; 319 320 Arg[1].Type = ACPI_TYPE_STRING; 321 Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception); 322 Arg[1].String.Length = ACPI_STRLEN (Exception); 323 324 Arg[2].Type = ACPI_TYPE_INTEGER; 325 Arg[2].Integer.Value = AcpiOsGetThreadId(); 326 327 /* Setup return buffer */ 328 329 ReturnObj.Pointer = NULL; 330 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 331 332 Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj); 333 if (ACPI_SUCCESS (Status)) 334 { 335 if (ReturnObj.Pointer) 336 { 337 /* Override original status */ 338 339 NewAmlStatus = (ACPI_STATUS) 340 ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value; 341 342 AcpiOsFree (ReturnObj.Pointer); 343 } 344 } 345 else if (Status != AE_NOT_FOUND) 346 { 347 AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n", 348 AcpiFormatException (Status)); 349 } 350 351 /* Global override */ 352 353 if (AcpiGbl_IgnoreErrors) 354 { 355 NewAmlStatus = AE_OK; 356 } 357 358 if (NewAmlStatus != AmlStatus) 359 { 360 AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n", 361 AcpiFormatException (NewAmlStatus)); 362 } 363 364 return (NewAmlStatus); 365 } 366 367 368 /****************************************************************************** 369 * 370 * FUNCTION: AeTableHandler 371 * 372 * PARAMETERS: Table handler 373 * 374 * RETURN: Status 375 * 376 * DESCRIPTION: System table handler for AcpiExec utility. 377 * 378 *****************************************************************************/ 379 380 static char *TableEvents[] = 381 { 382 "LOAD", 383 "UNLOAD", 384 "UNKNOWN" 385 }; 386 387 static ACPI_STATUS 388 AeTableHandler ( 389 UINT32 Event, 390 void *Table, 391 void *Context) 392 { 393 ACPI_STATUS Status; 394 395 396 if (Event > ACPI_NUM_TABLE_EVENTS) 397 { 398 Event = ACPI_NUM_TABLE_EVENTS; 399 } 400 401 /* Enable any GPEs associated with newly-loaded GPE methods */ 402 403 Status = AcpiUpdateAllGpes (); 404 AE_CHECK_OK (AcpiUpdateAllGpes, Status); 405 406 printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n", 407 TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table); 408 return (AE_OK); 409 } 410 411 412 /****************************************************************************** 413 * 414 * FUNCTION: AeGpeHandler 415 * 416 * DESCRIPTION: Common GPE handler for acpiexec 417 * 418 *****************************************************************************/ 419 420 UINT32 421 AeGpeHandler ( 422 ACPI_HANDLE GpeDevice, 423 UINT32 GpeNumber, 424 void *Context) 425 { 426 ACPI_NAMESPACE_NODE *DeviceNode = (ACPI_NAMESPACE_NODE *) GpeDevice; 427 428 429 AcpiOsPrintf ("[AcpiExec] GPE Handler received GPE%02X (GPE block %4.4s)\n", 430 GpeNumber, GpeDevice ? DeviceNode->Name.Ascii : "FADT"); 431 432 return (ACPI_REENABLE_GPE); 433 } 434 435 436 /****************************************************************************** 437 * 438 * FUNCTION: AeGlobalEventHandler 439 * 440 * DESCRIPTION: Global GPE/Fixed event handler 441 * 442 *****************************************************************************/ 443 444 void 445 AeGlobalEventHandler ( 446 UINT32 Type, 447 ACPI_HANDLE Device, 448 UINT32 EventNumber, 449 void *Context) 450 { 451 char *TypeName; 452 453 454 switch (Type) 455 { 456 case ACPI_EVENT_TYPE_GPE: 457 TypeName = "GPE"; 458 break; 459 460 case ACPI_EVENT_TYPE_FIXED: 461 TypeName = "FixedEvent"; 462 break; 463 464 default: 465 TypeName = "UNKNOWN"; 466 break; 467 } 468 469 AcpiOsPrintf ("[AcpiExec] Global Event Handler received: Type %s Number %.2X Dev %p\n", 470 TypeName, EventNumber, Device); 471 } 472 473 474 /****************************************************************************** 475 * 476 * FUNCTION: AeAttachedDataHandler 477 * 478 * DESCRIPTION: Handler for deletion of nodes with attached data (attached via 479 * AcpiAttachData) 480 * 481 *****************************************************************************/ 482 483 static void 484 AeAttachedDataHandler ( 485 ACPI_HANDLE Object, 486 void *Data) 487 { 488 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data); 489 490 491 AcpiOsPrintf ("Received an attached data deletion on %4.4s\n", 492 Node->Name.Ascii); 493 } 494 495 496 /****************************************************************************** 497 * 498 * FUNCTION: AeInterfaceHandler 499 * 500 * DESCRIPTION: Handler for _OSI invocations 501 * 502 *****************************************************************************/ 503 504 static UINT32 505 AeInterfaceHandler ( 506 ACPI_STRING InterfaceName, 507 UINT32 Supported) 508 { 509 ACPI_FUNCTION_NAME (AeInterfaceHandler); 510 511 512 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 513 "Received _OSI (\"%s\"), is %ssupported\n", 514 InterfaceName, Supported == 0 ? "not " : "")); 515 516 return (Supported); 517 } 518 519 520 /****************************************************************************** 521 * 522 * FUNCTION: AeEventHandler 523 * 524 * DESCRIPTION: Handler for Fixed Events 525 * 526 *****************************************************************************/ 527 528 static UINT32 529 AeEventHandler ( 530 void *Context) 531 { 532 return (0); 533 } 534 535 536 /****************************************************************************** 537 * 538 * FUNCTION: AeRegionInit 539 * 540 * PARAMETERS: None 541 * 542 * RETURN: Status 543 * 544 * DESCRIPTION: Opregion init function. 545 * 546 *****************************************************************************/ 547 548 static ACPI_STATUS 549 AeRegionInit ( 550 ACPI_HANDLE RegionHandle, 551 UINT32 Function, 552 void *HandlerContext, 553 void **RegionContext) 554 { 555 /* 556 * Real simple, set the RegionContext to the RegionHandle 557 */ 558 *RegionContext = RegionHandle; 559 560 return (AE_OK); 561 } 562 563 564 /****************************************************************************** 565 * 566 * FUNCTION: AeInstallLateHandlers 567 * 568 * PARAMETERS: None 569 * 570 * RETURN: Status 571 * 572 * DESCRIPTION: Install handlers for the AcpiExec utility. 573 * 574 *****************************************************************************/ 575 576 ACPI_STATUS 577 AeInstallLateHandlers ( 578 void) 579 { 580 ACPI_STATUS Status; 581 UINT32 i; 582 583 584 /* Install some fixed event handlers */ 585 586 Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, AeEventHandler, NULL); 587 AE_CHECK_OK (AcpiInstallFixedEventHandler, Status); 588 589 Status = AcpiInstallFixedEventHandler (ACPI_EVENT_RTC, AeEventHandler, NULL); 590 AE_CHECK_OK (AcpiInstallFixedEventHandler, Status); 591 592 /* 593 * Install handlers for some of the "device driver" address spaces 594 * such as EC, SMBus, etc. 595 */ 596 for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++) 597 { 598 /* Install handler at the root object */ 599 600 Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode, 601 SpaceIdList[i], AeRegionHandler, AeRegionInit, NULL); 602 if (ACPI_FAILURE (Status)) 603 { 604 ACPI_EXCEPTION ((AE_INFO, Status, 605 "Could not install an OpRegion handler for %s space(%u)", 606 AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i])); 607 return (Status); 608 } 609 } 610 611 return (AE_OK); 612 } 613 614 615 /****************************************************************************** 616 * 617 * FUNCTION: AeInstallEarlyHandlers 618 * 619 * PARAMETERS: None 620 * 621 * RETURN: Status 622 * 623 * DESCRIPTION: Install handlers for the AcpiExec utility. 624 * 625 * Notes: Don't install handler for PCI_Config, we want to use the 626 * default handler to exercise that code. 627 * 628 *****************************************************************************/ 629 630 ACPI_STATUS 631 AeInstallEarlyHandlers ( 632 void) 633 { 634 ACPI_STATUS Status; 635 UINT32 i; 636 ACPI_HANDLE Handle; 637 638 639 ACPI_FUNCTION_ENTRY (); 640 641 642 Status = AcpiInstallInterfaceHandler (AeInterfaceHandler); 643 if (ACPI_FAILURE (Status)) 644 { 645 printf ("Could not install interface handler, %s\n", 646 AcpiFormatException (Status)); 647 } 648 649 Status = AcpiInstallTableHandler (AeTableHandler, NULL); 650 if (ACPI_FAILURE (Status)) 651 { 652 printf ("Could not install table handler, %s\n", 653 AcpiFormatException (Status)); 654 } 655 656 Status = AcpiInstallExceptionHandler (AeExceptionHandler); 657 if (ACPI_FAILURE (Status)) 658 { 659 printf ("Could not install exception handler, %s\n", 660 AcpiFormatException (Status)); 661 } 662 663 /* Install global notify handler */ 664 665 Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, 666 AeNotifyHandler, NULL); 667 if (ACPI_FAILURE (Status)) 668 { 669 printf ("Could not install a global notify handler, %s\n", 670 AcpiFormatException (Status)); 671 } 672 673 Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY, 674 AeDeviceNotifyHandler, NULL); 675 if (ACPI_FAILURE (Status)) 676 { 677 printf ("Could not install a global notify handler, %s\n", 678 AcpiFormatException (Status)); 679 } 680 681 Status = AcpiGetHandle (NULL, "\\_SB", &Handle); 682 if (ACPI_SUCCESS (Status)) 683 { 684 Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, 685 AeNotifyHandler, NULL); 686 if (ACPI_FAILURE (Status)) 687 { 688 printf ("Could not install a notify handler, %s\n", 689 AcpiFormatException (Status)); 690 } 691 692 Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, 693 AeNotifyHandler); 694 if (ACPI_FAILURE (Status)) 695 { 696 printf ("Could not remove a notify handler, %s\n", 697 AcpiFormatException (Status)); 698 } 699 700 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 701 AeNotifyHandler, NULL); 702 AE_CHECK_OK (AcpiInstallNotifyHandler, Status); 703 704 Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY, 705 AeNotifyHandler); 706 AE_CHECK_OK (AcpiRemoveNotifyHandler, Status); 707 708 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 709 AeNotifyHandler, NULL); 710 if (ACPI_FAILURE (Status)) 711 { 712 printf ("Could not install a notify handler, %s\n", 713 AcpiFormatException (Status)); 714 } 715 716 Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle); 717 AE_CHECK_OK (AcpiAttachData, Status); 718 719 Status = AcpiDetachData (Handle, AeAttachedDataHandler); 720 AE_CHECK_OK (AcpiDetachData, Status); 721 722 Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle); 723 AE_CHECK_OK (AcpiAttachData, Status); 724 } 725 else 726 { 727 printf ("No _SB_ found, %s\n", AcpiFormatException (Status)); 728 } 729 730 731 /* 732 * Install handlers that will override the default handlers for some of 733 * the space IDs. 734 */ 735 for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++) 736 { 737 /* Install handler at the root object */ 738 739 Status = AcpiInstallAddressSpaceHandler (AcpiGbl_RootNode, 740 DefaultSpaceIdList[i], AeRegionHandler, 741 AeRegionInit, NULL); 742 if (ACPI_FAILURE (Status)) 743 { 744 ACPI_EXCEPTION ((AE_INFO, Status, 745 "Could not install a default OpRegion handler for %s space(%u)", 746 AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]), 747 DefaultSpaceIdList[i])); 748 return (Status); 749 } 750 } 751 752 /* 753 * Initialize the global Region Handler space 754 * MCW 3/23/00 755 */ 756 AeRegions.NumberOfRegions = 0; 757 AeRegions.RegionList = NULL; 758 return (Status); 759 } 760 761 762 /****************************************************************************** 763 * 764 * FUNCTION: AeRegionHandler 765 * 766 * PARAMETERS: Standard region handler parameters 767 * 768 * RETURN: Status 769 * 770 * DESCRIPTION: Test handler - Handles some dummy regions via memory that can 771 * be manipulated in Ring 3. Simulates actual reads and writes. 772 * 773 *****************************************************************************/ 774 775 ACPI_STATUS 776 AeRegionHandler ( 777 UINT32 Function, 778 ACPI_PHYSICAL_ADDRESS Address, 779 UINT32 BitWidth, 780 UINT64 *Value, 781 void *HandlerContext, 782 void *RegionContext) 783 { 784 785 ACPI_OPERAND_OBJECT *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext); 786 UINT8 *Buffer = ACPI_CAST_PTR (UINT8, Value); 787 ACPI_PHYSICAL_ADDRESS BaseAddress; 788 ACPI_SIZE Length; 789 BOOLEAN BufferExists; 790 AE_REGION *RegionElement; 791 void *BufferValue; 792 ACPI_STATUS Status; 793 UINT32 ByteWidth; 794 UINT32 i; 795 UINT8 SpaceId; 796 797 798 ACPI_FUNCTION_NAME (AeRegionHandler); 799 800 /* 801 * If the object is not a region, simply return 802 */ 803 if (RegionObject->Region.Type != ACPI_TYPE_REGION) 804 { 805 return (AE_OK); 806 } 807 808 /* 809 * Region support can be disabled with the -r option. 810 * We use this to support dynamically loaded tables where we pass a valid 811 * address to the AML. 812 */ 813 if (AcpiGbl_DbOpt_NoRegionSupport) 814 { 815 BufferValue = ACPI_TO_POINTER (Address); 816 ByteWidth = (BitWidth / 8); 817 818 if (BitWidth % 8) 819 { 820 ByteWidth += 1; 821 } 822 goto DoFunction; 823 } 824 825 /* 826 * Find the region's address space and length before searching 827 * the linked list. 828 */ 829 BaseAddress = RegionObject->Region.Address; 830 Length = (ACPI_SIZE) RegionObject->Region.Length; 831 SpaceId = RegionObject->Region.SpaceId; 832 833 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n", 834 AcpiUtGetRegionName (RegionObject->Region.SpaceId), 835 (UINT32) Address)); 836 837 switch (SpaceId) 838 { 839 case ACPI_ADR_SPACE_SYSTEM_IO: 840 /* 841 * For I/O space, exercise the port validation 842 */ 843 switch (Function & ACPI_IO_MASK) 844 { 845 case ACPI_READ: 846 Status = AcpiHwReadPort (Address, (UINT32 *) Value, BitWidth); 847 AE_CHECK_OK (AcpiHwReadPort, Status); 848 break; 849 850 case ACPI_WRITE: 851 Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth); 852 AE_CHECK_OK (AcpiHwWritePort, Status); 853 break; 854 855 default: 856 Status = AE_BAD_PARAMETER; 857 break; 858 } 859 860 if (ACPI_FAILURE (Status)) 861 { 862 return (Status); 863 } 864 865 /* Now go ahead and simulate the hardware */ 866 break; 867 868 869 case ACPI_ADR_SPACE_SMBUS: 870 871 Length = 0; 872 873 switch (Function & ACPI_IO_MASK) 874 { 875 case ACPI_READ: 876 switch (Function >> 16) 877 { 878 case AML_FIELD_ATTRIB_SMB_QUICK: 879 case AML_FIELD_ATTRIB_SMB_SEND_RCV: 880 case AML_FIELD_ATTRIB_SMB_BYTE: 881 Length = 1; 882 break; 883 884 case AML_FIELD_ATTRIB_SMB_WORD: 885 case AML_FIELD_ATTRIB_SMB_WORD_CALL: 886 Length = 2; 887 break; 888 889 case AML_FIELD_ATTRIB_SMB_BLOCK: 890 case AML_FIELD_ATTRIB_SMB_BLOCK_CALL: 891 Length = 32; 892 break; 893 894 default: 895 break; 896 } 897 break; 898 899 case ACPI_WRITE: 900 switch (Function >> 16) 901 { 902 case AML_FIELD_ATTRIB_SMB_QUICK: 903 case AML_FIELD_ATTRIB_SMB_SEND_RCV: 904 case AML_FIELD_ATTRIB_SMB_BYTE: 905 case AML_FIELD_ATTRIB_SMB_WORD: 906 case AML_FIELD_ATTRIB_SMB_BLOCK: 907 Length = 0; 908 break; 909 910 case AML_FIELD_ATTRIB_SMB_WORD_CALL: 911 Length = 2; 912 break; 913 914 case AML_FIELD_ATTRIB_SMB_BLOCK_CALL: 915 Length = 32; 916 break; 917 918 default: 919 break; 920 } 921 break; 922 923 default: 924 break; 925 } 926 927 for (i = 0; i < Length; i++) 928 { 929 Buffer[i+2] = (UINT8) (0xA0 + i); 930 } 931 932 Buffer[0] = 0x7A; 933 Buffer[1] = (UINT8) Length; 934 return (AE_OK); 935 936 937 case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */ 938 939 AcpiOsPrintf ("AcpiExec: Received IPMI request: " 940 "Address %X BaseAddress %X Length %X Width %X BufferLength %u\n", 941 (UINT32) Address, (UINT32) BaseAddress, 942 Length, BitWidth, Buffer[1]); 943 944 /* 945 * Regardless of a READ or WRITE, this handler is passed a 66-byte 946 * buffer in which to return the IPMI status/length/data. 947 * 948 * Return some example data to show use of the bidirectional buffer 949 */ 950 Buffer[0] = 0; /* Status byte */ 951 Buffer[1] = 64; /* Return buffer data length */ 952 Buffer[2] = 0; /* Completion code */ 953 Buffer[3] = 0x34; /* Power measurement */ 954 Buffer[4] = 0x12; /* Power measurement */ 955 Buffer[65] = 0xEE; /* last buffer byte */ 956 return (AE_OK); 957 958 default: 959 break; 960 } 961 962 /* 963 * Search through the linked list for this region's buffer 964 */ 965 BufferExists = FALSE; 966 RegionElement = AeRegions.RegionList; 967 968 if (AeRegions.NumberOfRegions) 969 { 970 while (!BufferExists && RegionElement) 971 { 972 if (RegionElement->Address == BaseAddress && 973 RegionElement->Length == Length && 974 RegionElement->SpaceId == SpaceId) 975 { 976 BufferExists = TRUE; 977 } 978 else 979 { 980 RegionElement = RegionElement->NextRegion; 981 } 982 } 983 } 984 985 /* 986 * If the Region buffer does not exist, create it now 987 */ 988 if (!BufferExists) 989 { 990 /* 991 * Do the memory allocations first 992 */ 993 RegionElement = AcpiOsAllocate (sizeof (AE_REGION)); 994 if (!RegionElement) 995 { 996 return (AE_NO_MEMORY); 997 } 998 999 RegionElement->Buffer = AcpiOsAllocate (Length); 1000 if (!RegionElement->Buffer) 1001 { 1002 AcpiOsFree (RegionElement); 1003 return (AE_NO_MEMORY); 1004 } 1005 1006 /* Initialize the region with the default fill value */ 1007 1008 ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length); 1009 1010 RegionElement->Address = BaseAddress; 1011 RegionElement->Length = Length; 1012 RegionElement->SpaceId = SpaceId; 1013 RegionElement->NextRegion = NULL; 1014 1015 /* 1016 * Increment the number of regions and put this one 1017 * at the head of the list as it will probably get accessed 1018 * more often anyway. 1019 */ 1020 AeRegions.NumberOfRegions += 1; 1021 1022 if (AeRegions.RegionList) 1023 { 1024 RegionElement->NextRegion = AeRegions.RegionList; 1025 } 1026 1027 AeRegions.RegionList = RegionElement; 1028 } 1029 1030 /* 1031 * Calculate the size of the memory copy 1032 */ 1033 ByteWidth = (BitWidth / 8); 1034 1035 if (BitWidth % 8) 1036 { 1037 ByteWidth += 1; 1038 } 1039 1040 /* 1041 * The buffer exists and is pointed to by RegionElement. 1042 * We now need to verify the request is valid and perform the operation. 1043 * 1044 * NOTE: RegionElement->Length is in bytes, therefore it we compare against 1045 * ByteWidth (see above) 1046 */ 1047 if (((UINT64) Address + ByteWidth) > 1048 ((UINT64)(RegionElement->Address) + RegionElement->Length)) 1049 { 1050 ACPI_WARNING ((AE_INFO, 1051 "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X", 1052 (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address, 1053 ByteWidth, (UINT32)(RegionElement->Address), 1054 RegionElement->Length)); 1055 1056 return (AE_AML_REGION_LIMIT); 1057 } 1058 1059 /* 1060 * Get BufferValue to point to the "address" in the buffer 1061 */ 1062 BufferValue = ((UINT8 *) RegionElement->Buffer + 1063 ((UINT64) Address - (UINT64) RegionElement->Address)); 1064 1065 DoFunction: 1066 1067 /* 1068 * Perform a read or write to the buffer space 1069 */ 1070 switch (Function) 1071 { 1072 case ACPI_READ: 1073 /* 1074 * Set the pointer Value to whatever is in the buffer 1075 */ 1076 ACPI_MEMCPY (Value, BufferValue, ByteWidth); 1077 break; 1078 1079 case ACPI_WRITE: 1080 /* 1081 * Write the contents of Value to the buffer 1082 */ 1083 ACPI_MEMCPY (BufferValue, Value, ByteWidth); 1084 break; 1085 1086 default: 1087 return (AE_BAD_PARAMETER); 1088 } 1089 1090 return (AE_OK); 1091 } 1092 1093 1094