1 /****************************************************************************** 2 * 3 * Module Name: aehandlers - Various handlers for acpiexec 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 "aecommon.h" 45 46 #define _COMPONENT ACPI_TOOLS 47 ACPI_MODULE_NAME ("aehandlers") 48 49 /* Local prototypes */ 50 51 static void 52 AeNotifyHandler1 ( 53 ACPI_HANDLE Device, 54 UINT32 Value, 55 void *Context); 56 57 static void 58 AeNotifyHandler2 ( 59 ACPI_HANDLE Device, 60 UINT32 Value, 61 void *Context); 62 63 static void 64 AeCommonNotifyHandler ( 65 ACPI_HANDLE Device, 66 UINT32 Value, 67 UINT32 HandlerId); 68 69 static void 70 AeDeviceNotifyHandler ( 71 ACPI_HANDLE Device, 72 UINT32 Value, 73 void *Context); 74 75 static ACPI_STATUS 76 AeExceptionHandler ( 77 ACPI_STATUS AmlStatus, 78 ACPI_NAME Name, 79 UINT16 Opcode, 80 UINT32 AmlOffset, 81 void *Context); 82 83 static ACPI_STATUS 84 AeTableHandler ( 85 UINT32 Event, 86 void *Table, 87 void *Context); 88 89 static ACPI_STATUS 90 AeRegionInit ( 91 ACPI_HANDLE RegionHandle, 92 UINT32 Function, 93 void *HandlerContext, 94 void **RegionContext); 95 96 static void 97 AeAttachedDataHandler ( 98 ACPI_HANDLE Object, 99 void *Data); 100 101 static void 102 AeAttachedDataHandler2 ( 103 ACPI_HANDLE Object, 104 void *Data); 105 106 static UINT32 107 AeInterfaceHandler ( 108 ACPI_STRING InterfaceName, 109 UINT32 Supported); 110 111 static ACPI_STATUS 112 AeInstallEcHandler ( 113 ACPI_HANDLE ObjHandle, 114 UINT32 Level, 115 void *Context, 116 void **ReturnValue); 117 118 static ACPI_STATUS 119 AeInstallPciHandler ( 120 ACPI_HANDLE ObjHandle, 121 UINT32 Level, 122 void *Context, 123 void **ReturnValue); 124 125 static ACPI_STATUS 126 AeInstallDeviceHandlers ( 127 void); 128 129 #if (!ACPI_REDUCED_HARDWARE) 130 static UINT32 131 AeEventHandler ( 132 void *Context); 133 134 static UINT32 135 AeSciHandler ( 136 void *Context); 137 138 static char *TableEvents[] = 139 { 140 "LOAD", 141 "UNLOAD", 142 "UNKNOWN" 143 }; 144 #endif /* !ACPI_REDUCED_HARDWARE */ 145 146 147 static UINT32 SigintCount = 0; 148 static AE_DEBUG_REGIONS AeRegions; 149 BOOLEAN AcpiGbl_DisplayRegionAccess = FALSE; 150 151 /* 152 * We will override some of the default region handlers, especially 153 * the SystemMemory handler, which must be implemented locally. 154 * These handlers are installed "early" - before any _REG methods 155 * are executed - since they are special in the sense that the ACPI spec 156 * declares that they must "always be available". Cannot override the 157 * DataTable region handler either -- needed for test execution. 158 * 159 * NOTE: The local region handler will simulate access to these address 160 * spaces by creating a memory buffer behind each operation region. 161 */ 162 static ACPI_ADR_SPACE_TYPE DefaultSpaceIdList[] = 163 { 164 ACPI_ADR_SPACE_SYSTEM_MEMORY, 165 ACPI_ADR_SPACE_SYSTEM_IO, 166 ACPI_ADR_SPACE_PCI_CONFIG, 167 ACPI_ADR_SPACE_EC 168 }; 169 170 /* 171 * We will install handlers for some of the various address space IDs. 172 * Test one user-defined address space (used by aslts). 173 */ 174 #define ACPI_ADR_SPACE_USER_DEFINED1 0x80 175 #define ACPI_ADR_SPACE_USER_DEFINED2 0xE4 176 177 static ACPI_ADR_SPACE_TYPE SpaceIdList[] = 178 { 179 ACPI_ADR_SPACE_SMBUS, 180 ACPI_ADR_SPACE_CMOS, 181 ACPI_ADR_SPACE_PCI_BAR_TARGET, 182 ACPI_ADR_SPACE_IPMI, 183 ACPI_ADR_SPACE_GPIO, 184 ACPI_ADR_SPACE_GSBUS, 185 ACPI_ADR_SPACE_FIXED_HARDWARE, 186 ACPI_ADR_SPACE_USER_DEFINED1, 187 ACPI_ADR_SPACE_USER_DEFINED2 188 }; 189 190 static ACPI_CONNECTION_INFO AeMyContext; 191 192 193 /****************************************************************************** 194 * 195 * FUNCTION: AeCtrlCHandler 196 * 197 * PARAMETERS: Sig 198 * 199 * RETURN: none 200 * 201 * DESCRIPTION: Control-C handler. Abort running control method if any. 202 * 203 *****************************************************************************/ 204 205 void ACPI_SYSTEM_XFACE 206 AeCtrlCHandler ( 207 int Sig) 208 { 209 210 signal (SIGINT, SIG_IGN); 211 SigintCount++; 212 213 AcpiOsPrintf ("Caught a ctrl-c (#%u)\n\n", SigintCount); 214 215 if (AcpiGbl_MethodExecuting) 216 { 217 AcpiGbl_AbortMethod = TRUE; 218 signal (SIGINT, AeCtrlCHandler); 219 220 if (SigintCount < 10) 221 { 222 return; 223 } 224 } 225 226 (void) AcpiOsTerminate (); 227 exit (0); 228 } 229 230 231 /****************************************************************************** 232 * 233 * FUNCTION: AeNotifyHandler(s) 234 * 235 * PARAMETERS: Standard notify handler parameters 236 * 237 * RETURN: Status 238 * 239 * DESCRIPTION: Notify handlers for AcpiExec utility. Used by the ASL 240 * test suite(s) to communicate errors and other information to 241 * this utility via the Notify() operator. Tests notify handling 242 * and multiple notify handler support. 243 * 244 *****************************************************************************/ 245 246 static void 247 AeNotifyHandler1 ( 248 ACPI_HANDLE Device, 249 UINT32 Value, 250 void *Context) 251 { 252 AeCommonNotifyHandler (Device, Value, 1); 253 } 254 255 static void 256 AeNotifyHandler2 ( 257 ACPI_HANDLE Device, 258 UINT32 Value, 259 void *Context) 260 { 261 AeCommonNotifyHandler (Device, Value, 2); 262 } 263 264 static void 265 AeCommonNotifyHandler ( 266 ACPI_HANDLE Device, 267 UINT32 Value, 268 UINT32 HandlerId) 269 { 270 char *Type; 271 272 273 Type = "Device"; 274 if (Value <= ACPI_MAX_SYS_NOTIFY) 275 { 276 Type = "System"; 277 } 278 279 switch (Value) 280 { 281 #if 0 282 case 0: 283 284 printf ("[AcpiExec] Method Error 0x%X: Results not equal\n", Value); 285 if (AcpiGbl_DebugFile) 286 { 287 AcpiOsPrintf ("[AcpiExec] Method Error: Results not equal\n"); 288 } 289 break; 290 291 case 1: 292 293 printf ("[AcpiExec] Method Error: Incorrect numeric result\n"); 294 if (AcpiGbl_DebugFile) 295 { 296 AcpiOsPrintf ("[AcpiExec] Method Error: Incorrect numeric result\n"); 297 } 298 break; 299 300 case 2: 301 302 printf ("[AcpiExec] Method Error: An operand was overwritten\n"); 303 if (AcpiGbl_DebugFile) 304 { 305 AcpiOsPrintf ("[AcpiExec] Method Error: An operand was overwritten\n"); 306 } 307 break; 308 309 #endif 310 311 default: 312 313 printf ("[AcpiExec] Handler %u: Received a %s Notify on [%4.4s] %p Value 0x%2.2X (%s)\n", 314 HandlerId, Type, AcpiUtGetNodeName (Device), Device, Value, 315 AcpiUtGetNotifyName (Value, ACPI_TYPE_ANY)); 316 if (AcpiGbl_DebugFile) 317 { 318 AcpiOsPrintf ("[AcpiExec] Handler %u: Received a %s notify, Value 0x%2.2X\n", 319 HandlerId, Type, Value); 320 } 321 322 (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL); 323 break; 324 } 325 } 326 327 328 /****************************************************************************** 329 * 330 * FUNCTION: AeSystemNotifyHandler 331 * 332 * PARAMETERS: Standard notify handler parameters 333 * 334 * RETURN: Status 335 * 336 * DESCRIPTION: System notify handler for AcpiExec utility. Used by the ASL 337 * test suite(s) to communicate errors and other information to 338 * this utility via the Notify() operator. 339 * 340 *****************************************************************************/ 341 342 static void 343 AeSystemNotifyHandler ( 344 ACPI_HANDLE Device, 345 UINT32 Value, 346 void *Context) 347 { 348 349 printf ("[AcpiExec] Global: Received a System Notify on [%4.4s] %p Value 0x%2.2X (%s)\n", 350 AcpiUtGetNodeName (Device), Device, Value, 351 AcpiUtGetNotifyName (Value, ACPI_TYPE_ANY)); 352 if (AcpiGbl_DebugFile) 353 { 354 AcpiOsPrintf ("[AcpiExec] Global: Received a System Notify, Value 0x%2.2X\n", Value); 355 } 356 357 (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL); 358 } 359 360 361 /****************************************************************************** 362 * 363 * FUNCTION: AeDeviceNotifyHandler 364 * 365 * PARAMETERS: Standard notify handler parameters 366 * 367 * RETURN: Status 368 * 369 * DESCRIPTION: Device notify handler for AcpiExec utility. Used by the ASL 370 * test suite(s) to communicate errors and other information to 371 * this utility via the Notify() operator. 372 * 373 *****************************************************************************/ 374 375 static void 376 AeDeviceNotifyHandler ( 377 ACPI_HANDLE Device, 378 UINT32 Value, 379 void *Context) 380 { 381 382 printf ("[AcpiExec] Global: Received a Device Notify on [%4.4s] %p Value 0x%2.2X (%s)\n", 383 AcpiUtGetNodeName (Device), Device, Value, 384 AcpiUtGetNotifyName (Value, ACPI_TYPE_ANY)); 385 if (AcpiGbl_DebugFile) 386 { 387 AcpiOsPrintf ("[AcpiExec] Global: Received a Device Notify, Value 0x%2.2X\n", Value); 388 } 389 390 (void) AcpiEvaluateObject (Device, "_NOT", NULL, NULL); 391 } 392 393 394 /****************************************************************************** 395 * 396 * FUNCTION: AeExceptionHandler 397 * 398 * PARAMETERS: Standard exception handler parameters 399 * 400 * RETURN: Status 401 * 402 * DESCRIPTION: System exception handler for AcpiExec utility. 403 * 404 *****************************************************************************/ 405 406 static ACPI_STATUS 407 AeExceptionHandler ( 408 ACPI_STATUS AmlStatus, 409 ACPI_NAME Name, 410 UINT16 Opcode, 411 UINT32 AmlOffset, 412 void *Context) 413 { 414 ACPI_STATUS NewAmlStatus = AmlStatus; 415 ACPI_STATUS Status; 416 ACPI_BUFFER ReturnObj; 417 ACPI_OBJECT_LIST ArgList; 418 ACPI_OBJECT Arg[3]; 419 const char *Exception; 420 421 422 Exception = AcpiFormatException (AmlStatus); 423 AcpiOsPrintf ("[AcpiExec] Exception %s during execution ", Exception); 424 if (Name) 425 { 426 AcpiOsPrintf ("of method [%4.4s]", (char *) &Name); 427 } 428 else 429 { 430 AcpiOsPrintf ("at module level (table load)"); 431 } 432 AcpiOsPrintf (" Opcode [%s] @%X\n", AcpiPsGetOpcodeName (Opcode), AmlOffset); 433 434 /* 435 * Invoke the _ERR method if present 436 * 437 * Setup parameter object 438 */ 439 ArgList.Count = 3; 440 ArgList.Pointer = Arg; 441 442 Arg[0].Type = ACPI_TYPE_INTEGER; 443 Arg[0].Integer.Value = AmlStatus; 444 445 Arg[1].Type = ACPI_TYPE_STRING; 446 Arg[1].String.Pointer = ACPI_CAST_PTR (char, Exception); 447 Arg[1].String.Length = ACPI_STRLEN (Exception); 448 449 Arg[2].Type = ACPI_TYPE_INTEGER; 450 Arg[2].Integer.Value = AcpiOsGetThreadId(); 451 452 /* Setup return buffer */ 453 454 ReturnObj.Pointer = NULL; 455 ReturnObj.Length = ACPI_ALLOCATE_BUFFER; 456 457 Status = AcpiEvaluateObject (NULL, "\\_ERR", &ArgList, &ReturnObj); 458 if (ACPI_SUCCESS (Status)) 459 { 460 if (ReturnObj.Pointer) 461 { 462 /* Override original status */ 463 464 NewAmlStatus = (ACPI_STATUS) 465 ((ACPI_OBJECT *) ReturnObj.Pointer)->Integer.Value; 466 467 /* Free a buffer created via ACPI_ALLOCATE_BUFFER */ 468 469 AcpiOsFree (ReturnObj.Pointer); 470 } 471 } 472 else if (Status != AE_NOT_FOUND) 473 { 474 AcpiOsPrintf ("[AcpiExec] Could not execute _ERR method, %s\n", 475 AcpiFormatException (Status)); 476 } 477 478 /* Global override */ 479 480 if (AcpiGbl_IgnoreErrors) 481 { 482 NewAmlStatus = AE_OK; 483 } 484 485 if (NewAmlStatus != AmlStatus) 486 { 487 AcpiOsPrintf ("[AcpiExec] Exception override, new status %s\n", 488 AcpiFormatException (NewAmlStatus)); 489 } 490 491 return (NewAmlStatus); 492 } 493 494 495 /****************************************************************************** 496 * 497 * FUNCTION: AeTableHandler 498 * 499 * PARAMETERS: Table handler 500 * 501 * RETURN: Status 502 * 503 * DESCRIPTION: System table handler for AcpiExec utility. 504 * 505 *****************************************************************************/ 506 507 static ACPI_STATUS 508 AeTableHandler ( 509 UINT32 Event, 510 void *Table, 511 void *Context) 512 { 513 #if (!ACPI_REDUCED_HARDWARE) 514 ACPI_STATUS Status; 515 #endif /* !ACPI_REDUCED_HARDWARE */ 516 517 518 if (Event > ACPI_NUM_TABLE_EVENTS) 519 { 520 Event = ACPI_NUM_TABLE_EVENTS; 521 } 522 523 #if (!ACPI_REDUCED_HARDWARE) 524 /* Enable any GPEs associated with newly-loaded GPE methods */ 525 526 Status = AcpiUpdateAllGpes (); 527 AE_CHECK_OK (AcpiUpdateAllGpes, Status); 528 529 printf ("[AcpiExec] Table Event %s, [%4.4s] %p\n", 530 TableEvents[Event], ((ACPI_TABLE_HEADER *) Table)->Signature, Table); 531 #endif /* !ACPI_REDUCED_HARDWARE */ 532 533 return (AE_OK); 534 } 535 536 537 /****************************************************************************** 538 * 539 * FUNCTION: AeGpeHandler 540 * 541 * DESCRIPTION: Common GPE handler for acpiexec 542 * 543 *****************************************************************************/ 544 545 UINT32 546 AeGpeHandler ( 547 ACPI_HANDLE GpeDevice, 548 UINT32 GpeNumber, 549 void *Context) 550 { 551 ACPI_NAMESPACE_NODE *DeviceNode = (ACPI_NAMESPACE_NODE *) GpeDevice; 552 553 554 AcpiOsPrintf ("[AcpiExec] GPE Handler received GPE %02X (GPE block %4.4s)\n", 555 GpeNumber, GpeDevice ? DeviceNode->Name.Ascii : "FADT"); 556 557 return (ACPI_REENABLE_GPE); 558 } 559 560 561 /****************************************************************************** 562 * 563 * FUNCTION: AeGlobalEventHandler 564 * 565 * DESCRIPTION: Global GPE/Fixed event handler 566 * 567 *****************************************************************************/ 568 569 void 570 AeGlobalEventHandler ( 571 UINT32 Type, 572 ACPI_HANDLE Device, 573 UINT32 EventNumber, 574 void *Context) 575 { 576 char *TypeName; 577 578 579 switch (Type) 580 { 581 case ACPI_EVENT_TYPE_GPE: 582 583 TypeName = "GPE"; 584 break; 585 586 case ACPI_EVENT_TYPE_FIXED: 587 588 TypeName = "FixedEvent"; 589 break; 590 591 default: 592 593 TypeName = "UNKNOWN"; 594 break; 595 } 596 597 AcpiOsPrintf ("[AcpiExec] Global Event Handler received: Type %s Number %.2X Dev %p\n", 598 TypeName, EventNumber, Device); 599 } 600 601 602 /****************************************************************************** 603 * 604 * FUNCTION: AeAttachedDataHandler 605 * 606 * DESCRIPTION: Handler for deletion of nodes with attached data (attached via 607 * AcpiAttachData) 608 * 609 *****************************************************************************/ 610 611 static void 612 AeAttachedDataHandler ( 613 ACPI_HANDLE Object, 614 void *Data) 615 { 616 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data); 617 618 619 AcpiOsPrintf ("Received an attached data deletion (1) on %4.4s\n", 620 Node->Name.Ascii); 621 } 622 623 624 /****************************************************************************** 625 * 626 * FUNCTION: AeAttachedDataHandler2 627 * 628 * DESCRIPTION: Handler for deletion of nodes with attached data (attached via 629 * AcpiAttachData) 630 * 631 *****************************************************************************/ 632 633 static void 634 AeAttachedDataHandler2 ( 635 ACPI_HANDLE Object, 636 void *Data) 637 { 638 ACPI_NAMESPACE_NODE *Node = ACPI_CAST_PTR (ACPI_NAMESPACE_NODE, Data); 639 640 641 AcpiOsPrintf ("Received an attached data deletion (2) on %4.4s\n", 642 Node->Name.Ascii); 643 } 644 645 646 /****************************************************************************** 647 * 648 * FUNCTION: AeInterfaceHandler 649 * 650 * DESCRIPTION: Handler for _OSI invocations 651 * 652 *****************************************************************************/ 653 654 static UINT32 655 AeInterfaceHandler ( 656 ACPI_STRING InterfaceName, 657 UINT32 Supported) 658 { 659 ACPI_FUNCTION_NAME (AeInterfaceHandler); 660 661 662 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 663 "Received _OSI (\"%s\"), is %ssupported\n", 664 InterfaceName, Supported == 0 ? "not " : "")); 665 666 return (Supported); 667 } 668 669 670 #if (!ACPI_REDUCED_HARDWARE) 671 /****************************************************************************** 672 * 673 * FUNCTION: AeEventHandler, AeSciHandler 674 * 675 * DESCRIPTION: Handler for Fixed Events and SCIs 676 * 677 *****************************************************************************/ 678 679 static UINT32 680 AeEventHandler ( 681 void *Context) 682 { 683 return (0); 684 } 685 686 static UINT32 687 AeSciHandler ( 688 void *Context) 689 { 690 691 AcpiOsPrintf ("[AcpiExec] Received an SCI at handler\n"); 692 return (0); 693 } 694 695 #endif /* !ACPI_REDUCED_HARDWARE */ 696 697 698 /****************************************************************************** 699 * 700 * FUNCTION: AeRegionInit 701 * 702 * PARAMETERS: None 703 * 704 * RETURN: Status 705 * 706 * DESCRIPTION: Opregion init function. 707 * 708 *****************************************************************************/ 709 710 static ACPI_STATUS 711 AeRegionInit ( 712 ACPI_HANDLE RegionHandle, 713 UINT32 Function, 714 void *HandlerContext, 715 void **RegionContext) 716 { 717 718 if (Function == ACPI_REGION_DEACTIVATE) 719 { 720 *RegionContext = NULL; 721 } 722 else 723 { 724 *RegionContext = RegionHandle; 725 } 726 727 return (AE_OK); 728 } 729 730 731 /******************************************************************************* 732 * 733 * FUNCTION: AeInstallSciHandler 734 * 735 * PARAMETERS: None 736 * 737 * RETURN: Status 738 * 739 * DESCRIPTION: Install handler for SCIs. Exercise the code by doing an 740 * install/remove/install. 741 * 742 ******************************************************************************/ 743 744 static ACPI_STATUS 745 AeInstallSciHandler ( 746 void) 747 { 748 ACPI_STATUS Status; 749 750 751 Status = AcpiInstallSciHandler (AeSciHandler, &AeMyContext); 752 if (ACPI_FAILURE (Status)) 753 { 754 ACPI_EXCEPTION ((AE_INFO, Status, 755 "Could not install an SCI handler (1)")); 756 } 757 758 Status = AcpiRemoveSciHandler (AeSciHandler); 759 if (ACPI_FAILURE (Status)) 760 { 761 ACPI_EXCEPTION ((AE_INFO, Status, 762 "Could not remove an SCI handler")); 763 } 764 765 Status = AcpiInstallSciHandler (AeSciHandler, &AeMyContext); 766 if (ACPI_FAILURE (Status)) 767 { 768 ACPI_EXCEPTION ((AE_INFO, Status, 769 "Could not install an SCI handler (2)")); 770 } 771 772 return (Status); 773 } 774 775 776 /******************************************************************************* 777 * 778 * FUNCTION: AeInstallDeviceHandlers, AeInstallEcHandler, 779 * AeInstallPciHandler 780 * 781 * PARAMETERS: ACPI_WALK_NAMESPACE callback 782 * 783 * RETURN: Status 784 * 785 * DESCRIPTION: Walk entire namespace, install a handler for every EC 786 * and PCI device found. 787 * 788 ******************************************************************************/ 789 790 static ACPI_STATUS 791 AeInstallEcHandler ( 792 ACPI_HANDLE ObjHandle, 793 UINT32 Level, 794 void *Context, 795 void **ReturnValue) 796 { 797 ACPI_STATUS Status; 798 799 800 /* Install the handler for this EC device */ 801 802 Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_EC, 803 AeRegionHandler, AeRegionInit, &AeMyContext); 804 if (ACPI_FAILURE (Status)) 805 { 806 ACPI_EXCEPTION ((AE_INFO, Status, 807 "Could not install an OpRegion handler for EC device (%p)", 808 ObjHandle)); 809 } 810 811 return (Status); 812 } 813 814 static ACPI_STATUS 815 AeInstallPciHandler ( 816 ACPI_HANDLE ObjHandle, 817 UINT32 Level, 818 void *Context, 819 void **ReturnValue) 820 { 821 ACPI_STATUS Status; 822 823 824 /* Install memory and I/O handlers for the PCI device */ 825 826 Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_IO, 827 AeRegionHandler, AeRegionInit, &AeMyContext); 828 if (ACPI_FAILURE (Status)) 829 { 830 ACPI_EXCEPTION ((AE_INFO, Status, 831 "Could not install an OpRegion handler for PCI device (%p)", 832 ObjHandle)); 833 } 834 835 Status = AcpiInstallAddressSpaceHandler (ObjHandle, ACPI_ADR_SPACE_SYSTEM_MEMORY, 836 AeRegionHandler, AeRegionInit, &AeMyContext); 837 if (ACPI_FAILURE (Status)) 838 { 839 ACPI_EXCEPTION ((AE_INFO, Status, 840 "Could not install an OpRegion handler for PCI device (%p)", 841 ObjHandle)); 842 } 843 844 return (AE_CTRL_TERMINATE); 845 } 846 847 static ACPI_STATUS 848 AeInstallDeviceHandlers ( 849 void) 850 { 851 852 /* Find all Embedded Controller devices */ 853 854 AcpiGetDevices ("PNP0C09", AeInstallEcHandler, NULL, NULL); 855 856 /* Install a PCI handler */ 857 858 AcpiGetDevices ("PNP0A08", AeInstallPciHandler, NULL, NULL); 859 return (AE_OK); 860 } 861 862 863 /****************************************************************************** 864 * 865 * FUNCTION: AeInstallLateHandlers 866 * 867 * PARAMETERS: None 868 * 869 * RETURN: Status 870 * 871 * DESCRIPTION: Install handlers for the AcpiExec utility. 872 * 873 *****************************************************************************/ 874 875 ACPI_STATUS 876 AeInstallLateHandlers ( 877 void) 878 { 879 ACPI_STATUS Status; 880 UINT32 i; 881 882 883 #if (!ACPI_REDUCED_HARDWARE) 884 if (!AcpiGbl_ReducedHardware) 885 { 886 /* Install a user SCI handler */ 887 888 Status = AeInstallSciHandler (); 889 AE_CHECK_OK (AeInstallSciHandler, Status); 890 891 /* Install some fixed event handlers */ 892 893 Status = AcpiInstallFixedEventHandler (ACPI_EVENT_GLOBAL, AeEventHandler, NULL); 894 AE_CHECK_OK (AcpiInstallFixedEventHandler, Status); 895 896 Status = AcpiInstallFixedEventHandler (ACPI_EVENT_RTC, AeEventHandler, NULL); 897 AE_CHECK_OK (AcpiInstallFixedEventHandler, Status); 898 } 899 #endif /* !ACPI_REDUCED_HARDWARE */ 900 901 AeMyContext.Connection = NULL; 902 AeMyContext.AccessLength = 0xA5; 903 904 /* 905 * We will install a handler for each EC device, directly under the EC 906 * device definition. This is unlike the other handlers which we install 907 * at the root node. Also install memory and I/O handlers at any PCI 908 * devices. 909 */ 910 AeInstallDeviceHandlers (); 911 912 /* 913 * Install handlers for some of the "device driver" address spaces 914 * such as SMBus, etc. 915 */ 916 for (i = 0; i < ACPI_ARRAY_LENGTH (SpaceIdList); i++) 917 { 918 /* Install handler at the root object */ 919 920 Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT, 921 SpaceIdList[i], AeRegionHandler, 922 AeRegionInit, &AeMyContext); 923 if (ACPI_FAILURE (Status)) 924 { 925 ACPI_EXCEPTION ((AE_INFO, Status, 926 "Could not install an OpRegion handler for %s space(%u)", 927 AcpiUtGetRegionName((UINT8) SpaceIdList[i]), SpaceIdList[i])); 928 return (Status); 929 } 930 } 931 932 return (AE_OK); 933 } 934 935 936 /****************************************************************************** 937 * 938 * FUNCTION: AeInstallEarlyHandlers 939 * 940 * PARAMETERS: None 941 * 942 * RETURN: Status 943 * 944 * DESCRIPTION: Install handlers for the AcpiExec utility. 945 * 946 * Notes: Don't install handler for PCI_Config, we want to use the 947 * default handler to exercise that code. 948 * 949 *****************************************************************************/ 950 951 ACPI_STATUS 952 AeInstallEarlyHandlers ( 953 void) 954 { 955 ACPI_STATUS Status; 956 UINT32 i; 957 ACPI_HANDLE Handle; 958 959 960 ACPI_FUNCTION_ENTRY (); 961 962 963 Status = AcpiInstallInterfaceHandler (AeInterfaceHandler); 964 if (ACPI_FAILURE (Status)) 965 { 966 printf ("Could not install interface handler, %s\n", 967 AcpiFormatException (Status)); 968 } 969 970 Status = AcpiInstallTableHandler (AeTableHandler, NULL); 971 if (ACPI_FAILURE (Status)) 972 { 973 printf ("Could not install table handler, %s\n", 974 AcpiFormatException (Status)); 975 } 976 977 Status = AcpiInstallExceptionHandler (AeExceptionHandler); 978 if (ACPI_FAILURE (Status)) 979 { 980 printf ("Could not install exception handler, %s\n", 981 AcpiFormatException (Status)); 982 } 983 984 /* Install global notify handlers */ 985 986 Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_SYSTEM_NOTIFY, 987 AeSystemNotifyHandler, NULL); 988 if (ACPI_FAILURE (Status)) 989 { 990 printf ("Could not install a global system notify handler, %s\n", 991 AcpiFormatException (Status)); 992 } 993 994 Status = AcpiInstallNotifyHandler (ACPI_ROOT_OBJECT, ACPI_DEVICE_NOTIFY, 995 AeDeviceNotifyHandler, NULL); 996 if (ACPI_FAILURE (Status)) 997 { 998 printf ("Could not install a global notify handler, %s\n", 999 AcpiFormatException (Status)); 1000 } 1001 1002 Status = AcpiGetHandle (NULL, "\\_SB", &Handle); 1003 if (ACPI_SUCCESS (Status)) 1004 { 1005 Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, 1006 AeNotifyHandler1, NULL); 1007 if (ACPI_FAILURE (Status)) 1008 { 1009 printf ("Could not install a notify handler, %s\n", 1010 AcpiFormatException (Status)); 1011 } 1012 1013 Status = AcpiRemoveNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, 1014 AeNotifyHandler1); 1015 if (ACPI_FAILURE (Status)) 1016 { 1017 printf ("Could not remove a notify handler, %s\n", 1018 AcpiFormatException (Status)); 1019 } 1020 1021 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1022 AeNotifyHandler1, NULL); 1023 AE_CHECK_OK (AcpiInstallNotifyHandler, Status); 1024 1025 Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1026 AeNotifyHandler1); 1027 AE_CHECK_OK (AcpiRemoveNotifyHandler, Status); 1028 1029 #if 0 1030 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1031 AeNotifyHandler1, NULL); 1032 if (ACPI_FAILURE (Status)) 1033 { 1034 printf ("Could not install a notify handler, %s\n", 1035 AcpiFormatException (Status)); 1036 } 1037 #endif 1038 1039 /* Install two handlers for _SB_ */ 1040 1041 Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, 1042 AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567)); 1043 1044 Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, 1045 AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF)); 1046 1047 /* Attempt duplicate handler installation, should fail */ 1048 1049 Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, 1050 AeNotifyHandler1, ACPI_CAST_PTR (void, 0x77777777)); 1051 1052 Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle); 1053 AE_CHECK_OK (AcpiAttachData, Status); 1054 1055 Status = AcpiDetachData (Handle, AeAttachedDataHandler); 1056 AE_CHECK_OK (AcpiDetachData, Status); 1057 1058 /* Test attach data at the root object */ 1059 1060 Status = AcpiAttachData (ACPI_ROOT_OBJECT, AeAttachedDataHandler, 1061 AcpiGbl_RootNode); 1062 AE_CHECK_OK (AcpiAttachData, Status); 1063 1064 Status = AcpiAttachData (ACPI_ROOT_OBJECT, AeAttachedDataHandler2, 1065 AcpiGbl_RootNode); 1066 AE_CHECK_OK (AcpiAttachData, Status); 1067 1068 /* Test support for multiple attaches */ 1069 1070 Status = AcpiAttachData (Handle, AeAttachedDataHandler, Handle); 1071 AE_CHECK_OK (AcpiAttachData, Status); 1072 1073 Status = AcpiAttachData (Handle, AeAttachedDataHandler2, Handle); 1074 AE_CHECK_OK (AcpiAttachData, Status); 1075 } 1076 else 1077 { 1078 printf ("No _SB_ found, %s\n", AcpiFormatException (Status)); 1079 } 1080 1081 1082 Status = AcpiGetHandle (NULL, "\\_TZ.TZ1", &Handle); 1083 if (ACPI_SUCCESS (Status)) 1084 { 1085 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1086 AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567)); 1087 1088 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1089 AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF)); 1090 1091 Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1092 AeNotifyHandler1); 1093 Status = AcpiRemoveNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1094 AeNotifyHandler2); 1095 1096 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1097 AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF)); 1098 1099 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1100 AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567)); 1101 } 1102 1103 Status = AcpiGetHandle (NULL, "\\_PR.CPU0", &Handle); 1104 if (ACPI_SUCCESS (Status)) 1105 { 1106 Status = AcpiInstallNotifyHandler (Handle, ACPI_ALL_NOTIFY, 1107 AeNotifyHandler1, ACPI_CAST_PTR (void, 0x01234567)); 1108 1109 Status = AcpiInstallNotifyHandler (Handle, ACPI_SYSTEM_NOTIFY, 1110 AeNotifyHandler2, ACPI_CAST_PTR (void, 0x89ABCDEF)); 1111 } 1112 1113 /* 1114 * Install handlers that will override the default handlers for some of 1115 * the space IDs. 1116 */ 1117 for (i = 0; i < ACPI_ARRAY_LENGTH (DefaultSpaceIdList); i++) 1118 { 1119 /* Install handler at the root object */ 1120 1121 Status = AcpiInstallAddressSpaceHandler (ACPI_ROOT_OBJECT, 1122 DefaultSpaceIdList[i], AeRegionHandler, 1123 AeRegionInit, &AeMyContext); 1124 if (ACPI_FAILURE (Status)) 1125 { 1126 ACPI_EXCEPTION ((AE_INFO, Status, 1127 "Could not install a default OpRegion handler for %s space(%u)", 1128 AcpiUtGetRegionName ((UINT8) DefaultSpaceIdList[i]), 1129 DefaultSpaceIdList[i])); 1130 return (Status); 1131 } 1132 } 1133 1134 /* 1135 * Initialize the global Region Handler space 1136 * MCW 3/23/00 1137 */ 1138 AeRegions.NumberOfRegions = 0; 1139 AeRegions.RegionList = NULL; 1140 return (Status); 1141 } 1142 1143 1144 /****************************************************************************** 1145 * 1146 * FUNCTION: AeRegionHandler 1147 * 1148 * PARAMETERS: Standard region handler parameters 1149 * 1150 * RETURN: Status 1151 * 1152 * DESCRIPTION: Test handler - Handles some dummy regions via memory that can 1153 * be manipulated in Ring 3. Simulates actual reads and writes. 1154 * 1155 *****************************************************************************/ 1156 1157 ACPI_STATUS 1158 AeRegionHandler ( 1159 UINT32 Function, 1160 ACPI_PHYSICAL_ADDRESS Address, 1161 UINT32 BitWidth, 1162 UINT64 *Value, 1163 void *HandlerContext, 1164 void *RegionContext) 1165 { 1166 1167 ACPI_OPERAND_OBJECT *RegionObject = ACPI_CAST_PTR (ACPI_OPERAND_OBJECT, RegionContext); 1168 UINT8 *Buffer = ACPI_CAST_PTR (UINT8, Value); 1169 UINT8 *OldBuffer; 1170 UINT8 *NewBuffer; 1171 ACPI_PHYSICAL_ADDRESS BaseAddress; 1172 ACPI_PHYSICAL_ADDRESS BaseAddressEnd; 1173 ACPI_PHYSICAL_ADDRESS RegionAddress; 1174 ACPI_PHYSICAL_ADDRESS RegionAddressEnd; 1175 ACPI_SIZE Length; 1176 BOOLEAN BufferExists; 1177 BOOLEAN BufferResize; 1178 AE_REGION *RegionElement; 1179 void *BufferValue; 1180 ACPI_STATUS Status; 1181 UINT32 ByteWidth; 1182 UINT32 RegionLength; 1183 UINT32 i; 1184 UINT8 SpaceId; 1185 ACPI_CONNECTION_INFO *MyContext; 1186 UINT32 Value1; 1187 UINT32 Value2; 1188 ACPI_RESOURCE *Resource; 1189 1190 1191 ACPI_FUNCTION_NAME (AeRegionHandler); 1192 1193 /* 1194 * If the object is not a region, simply return 1195 */ 1196 if (RegionObject->Region.Type != ACPI_TYPE_REGION) 1197 { 1198 return (AE_OK); 1199 } 1200 1201 /* Check that we actually got back our context parameter */ 1202 1203 if (HandlerContext != &AeMyContext) 1204 { 1205 printf ("Region handler received incorrect context %p, should be %p\n", 1206 HandlerContext, &AeMyContext); 1207 } 1208 1209 MyContext = ACPI_CAST_PTR (ACPI_CONNECTION_INFO, HandlerContext); 1210 1211 /* 1212 * Find the region's address space and length before searching 1213 * the linked list. 1214 */ 1215 BaseAddress = RegionObject->Region.Address; 1216 Length = (ACPI_SIZE) RegionObject->Region.Length; 1217 SpaceId = RegionObject->Region.SpaceId; 1218 1219 ACPI_DEBUG_PRINT ((ACPI_DB_OPREGION, "Operation Region request on %s at 0x%X\n", 1220 AcpiUtGetRegionName (RegionObject->Region.SpaceId), 1221 (UINT32) Address)); 1222 1223 /* 1224 * Region support can be disabled with the -do option. 1225 * We use this to support dynamically loaded tables where we pass a valid 1226 * address to the AML. 1227 */ 1228 if (AcpiGbl_DbOpt_NoRegionSupport) 1229 { 1230 BufferValue = ACPI_TO_POINTER (Address); 1231 ByteWidth = (BitWidth / 8); 1232 1233 if (BitWidth % 8) 1234 { 1235 ByteWidth += 1; 1236 } 1237 goto DoFunction; 1238 } 1239 1240 switch (SpaceId) 1241 { 1242 case ACPI_ADR_SPACE_SYSTEM_IO: 1243 /* 1244 * For I/O space, exercise the port validation 1245 * Note: ReadPort currently always returns all ones, length=BitLength 1246 */ 1247 switch (Function & ACPI_IO_MASK) 1248 { 1249 case ACPI_READ: 1250 1251 if (BitWidth == 64) 1252 { 1253 /* Split the 64-bit request into two 32-bit requests */ 1254 1255 Status = AcpiHwReadPort (Address, &Value1, 32); 1256 AE_CHECK_OK (AcpiHwReadPort, Status); 1257 Status = AcpiHwReadPort (Address+4, &Value2, 32); 1258 AE_CHECK_OK (AcpiHwReadPort, Status); 1259 1260 *Value = Value1 | ((UINT64) Value2 << 32); 1261 } 1262 else 1263 { 1264 Status = AcpiHwReadPort (Address, &Value1, BitWidth); 1265 AE_CHECK_OK (AcpiHwReadPort, Status); 1266 *Value = (UINT64) Value1; 1267 } 1268 break; 1269 1270 case ACPI_WRITE: 1271 1272 if (BitWidth == 64) 1273 { 1274 /* Split the 64-bit request into two 32-bit requests */ 1275 1276 Status = AcpiHwWritePort (Address, ACPI_LODWORD (*Value), 32); 1277 AE_CHECK_OK (AcpiHwWritePort, Status); 1278 Status = AcpiHwWritePort (Address+4, ACPI_HIDWORD (*Value), 32); 1279 AE_CHECK_OK (AcpiHwWritePort, Status); 1280 } 1281 else 1282 { 1283 Status = AcpiHwWritePort (Address, (UINT32) *Value, BitWidth); 1284 AE_CHECK_OK (AcpiHwWritePort, Status); 1285 } 1286 break; 1287 1288 default: 1289 1290 Status = AE_BAD_PARAMETER; 1291 break; 1292 } 1293 1294 if (ACPI_FAILURE (Status)) 1295 { 1296 return (Status); 1297 } 1298 1299 /* Now go ahead and simulate the hardware */ 1300 break; 1301 1302 /* 1303 * SMBus and GenericSerialBus support the various bidirectional 1304 * protocols. 1305 */ 1306 case ACPI_ADR_SPACE_SMBUS: 1307 case ACPI_ADR_SPACE_GSBUS: /* ACPI 5.0 */ 1308 1309 Length = 0; 1310 1311 switch (Function & ACPI_IO_MASK) 1312 { 1313 case ACPI_READ: 1314 1315 switch (Function >> 16) 1316 { 1317 case AML_FIELD_ATTRIB_QUICK: 1318 1319 Length = 0; 1320 break; 1321 1322 case AML_FIELD_ATTRIB_SEND_RCV: 1323 case AML_FIELD_ATTRIB_BYTE: 1324 1325 Length = 1; 1326 break; 1327 1328 case AML_FIELD_ATTRIB_WORD: 1329 case AML_FIELD_ATTRIB_WORD_CALL: 1330 1331 Length = 2; 1332 break; 1333 1334 case AML_FIELD_ATTRIB_BLOCK: 1335 case AML_FIELD_ATTRIB_BLOCK_CALL: 1336 1337 Length = 32; 1338 break; 1339 1340 case AML_FIELD_ATTRIB_MULTIBYTE: 1341 case AML_FIELD_ATTRIB_RAW_BYTES: 1342 case AML_FIELD_ATTRIB_RAW_PROCESS: 1343 1344 /* (-2) for status/length */ 1345 Length = MyContext->AccessLength - 2; 1346 break; 1347 1348 default: 1349 1350 break; 1351 } 1352 break; 1353 1354 case ACPI_WRITE: 1355 1356 switch (Function >> 16) 1357 { 1358 case AML_FIELD_ATTRIB_QUICK: 1359 case AML_FIELD_ATTRIB_SEND_RCV: 1360 case AML_FIELD_ATTRIB_BYTE: 1361 case AML_FIELD_ATTRIB_WORD: 1362 case AML_FIELD_ATTRIB_BLOCK: 1363 1364 Length = 0; 1365 break; 1366 1367 case AML_FIELD_ATTRIB_WORD_CALL: 1368 Length = 2; 1369 break; 1370 1371 case AML_FIELD_ATTRIB_BLOCK_CALL: 1372 Length = 32; 1373 break; 1374 1375 case AML_FIELD_ATTRIB_MULTIBYTE: 1376 case AML_FIELD_ATTRIB_RAW_BYTES: 1377 case AML_FIELD_ATTRIB_RAW_PROCESS: 1378 1379 /* (-2) for status/length */ 1380 Length = MyContext->AccessLength - 2; 1381 break; 1382 1383 default: 1384 1385 break; 1386 } 1387 break; 1388 1389 default: 1390 1391 break; 1392 } 1393 1394 if (AcpiGbl_DisplayRegionAccess) 1395 { 1396 AcpiOsPrintf ("AcpiExec: %s " 1397 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X", 1398 AcpiUtGetRegionName (SpaceId), 1399 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 1400 (UINT32) (Function >> 16), 1401 (UINT32) Address, (UINT32) BaseAddress, 1402 Length, BitWidth, Buffer[1]); 1403 1404 /* GenericSerialBus has a Connection() parameter */ 1405 1406 if (SpaceId == ACPI_ADR_SPACE_GSBUS) 1407 { 1408 Status = AcpiBufferToResource (MyContext->Connection, 1409 MyContext->Length, &Resource); 1410 1411 AcpiOsPrintf (" [AccLen %.2X Conn %p]", 1412 MyContext->AccessLength, MyContext->Connection); 1413 } 1414 AcpiOsPrintf ("\n"); 1415 } 1416 1417 /* Setup the return buffer. Note: ASLTS depends on these fill values */ 1418 1419 for (i = 0; i < Length; i++) 1420 { 1421 Buffer[i+2] = (UINT8) (0xA0 + i); 1422 } 1423 1424 Buffer[0] = 0x7A; 1425 Buffer[1] = (UINT8) Length; 1426 return (AE_OK); 1427 1428 1429 case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */ 1430 1431 if (AcpiGbl_DisplayRegionAccess) 1432 { 1433 AcpiOsPrintf ("AcpiExec: IPMI " 1434 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X\n", 1435 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 1436 (UINT32) (Function >> 16), (UINT32) Address, (UINT32) BaseAddress, 1437 Length, BitWidth, Buffer[1]); 1438 } 1439 1440 /* 1441 * Regardless of a READ or WRITE, this handler is passed a 66-byte 1442 * buffer in which to return the IPMI status/length/data. 1443 * 1444 * Return some example data to show use of the bidirectional buffer 1445 */ 1446 Buffer[0] = 0; /* Status byte */ 1447 Buffer[1] = 64; /* Return buffer data length */ 1448 Buffer[2] = 0; /* Completion code */ 1449 Buffer[3] = 0; /* Reserved */ 1450 1451 /* 1452 * Fill the 66-byte buffer with the return data. 1453 * Note: ASLTS depends on these fill values. 1454 */ 1455 for (i = 4; i < 66; i++) 1456 { 1457 Buffer[i] = (UINT8) (i); 1458 } 1459 return (AE_OK); 1460 1461 default: 1462 break; 1463 } 1464 1465 /* 1466 * Search through the linked list for this region's buffer 1467 */ 1468 BufferExists = FALSE; 1469 BufferResize = FALSE; 1470 RegionElement = AeRegions.RegionList; 1471 1472 if (AeRegions.NumberOfRegions) 1473 { 1474 BaseAddressEnd = BaseAddress + Length - 1; 1475 while (!BufferExists && RegionElement) 1476 { 1477 RegionAddress = RegionElement->Address; 1478 RegionAddressEnd = RegionElement->Address + RegionElement->Length - 1; 1479 RegionLength = RegionElement->Length; 1480 1481 /* 1482 * Overlapping Region Support 1483 * 1484 * While searching through the region buffer list, determine if an 1485 * overlap exists between the requested buffer space and the current 1486 * RegionElement space. If there is an overlap then replace the old 1487 * buffer with a new buffer of increased size before continuing to 1488 * do the read or write 1489 */ 1490 if (RegionElement->SpaceId != SpaceId || 1491 BaseAddressEnd < RegionAddress || 1492 BaseAddress > RegionAddressEnd) 1493 { 1494 /* 1495 * Requested buffer is outside of the current RegionElement 1496 * bounds 1497 */ 1498 RegionElement = RegionElement->NextRegion; 1499 } 1500 else 1501 { 1502 /* 1503 * Some amount of buffer space sharing exists. There are 4 cases 1504 * to consider: 1505 * 1506 * 1. Right overlap 1507 * 2. Left overlap 1508 * 3. Left and right overlap 1509 * 4. Fully contained - no resizing required 1510 */ 1511 BufferExists = TRUE; 1512 1513 if ((BaseAddress >= RegionAddress) && 1514 (BaseAddress <= RegionAddressEnd) && 1515 (BaseAddressEnd > RegionAddressEnd)) 1516 { 1517 /* Right overlap */ 1518 1519 RegionElement->Length = BaseAddress - 1520 RegionAddress + Length; 1521 BufferResize = TRUE; 1522 } 1523 1524 else if ((BaseAddressEnd >= RegionAddress) && 1525 (BaseAddressEnd <= RegionAddressEnd) && 1526 (BaseAddress < RegionAddress)) 1527 { 1528 /* Left overlap */ 1529 1530 RegionElement->Address = BaseAddress; 1531 RegionElement->Length = RegionAddress - 1532 BaseAddress + RegionElement->Length; 1533 BufferResize = TRUE; 1534 } 1535 1536 else if ((BaseAddress < RegionAddress) && 1537 (BaseAddressEnd > RegionAddressEnd)) 1538 { 1539 /* Left and right overlap */ 1540 1541 RegionElement->Address = BaseAddress; 1542 RegionElement->Length = Length; 1543 BufferResize = TRUE; 1544 } 1545 1546 /* 1547 * only remaining case is fully contained for which we don't 1548 * need to do anything 1549 */ 1550 if (BufferResize) 1551 { 1552 NewBuffer = AcpiOsAllocate (RegionElement->Length); 1553 if (!NewBuffer) 1554 { 1555 return (AE_NO_MEMORY); 1556 } 1557 1558 OldBuffer = RegionElement->Buffer; 1559 RegionElement->Buffer = NewBuffer; 1560 NewBuffer = NULL; 1561 1562 /* Initialize the region with the default fill value */ 1563 1564 ACPI_MEMSET (RegionElement->Buffer, 1565 AcpiGbl_RegionFillValue, RegionElement->Length); 1566 1567 /* 1568 * Get BufferValue to point (within the new buffer) to the 1569 * base address of the old buffer 1570 */ 1571 BufferValue = (UINT8 *) RegionElement->Buffer + 1572 (UINT64) RegionAddress - 1573 (UINT64) RegionElement->Address; 1574 1575 /* 1576 * Copy the old buffer to its same location within the new 1577 * buffer 1578 */ 1579 ACPI_MEMCPY (BufferValue, OldBuffer, RegionLength); 1580 AcpiOsFree (OldBuffer); 1581 } 1582 } 1583 } 1584 } 1585 1586 /* 1587 * If the Region buffer does not exist, create it now 1588 */ 1589 if (!BufferExists) 1590 { 1591 /* Do the memory allocations first */ 1592 1593 RegionElement = AcpiOsAllocate (sizeof (AE_REGION)); 1594 if (!RegionElement) 1595 { 1596 return (AE_NO_MEMORY); 1597 } 1598 1599 RegionElement->Buffer = AcpiOsAllocate (Length); 1600 if (!RegionElement->Buffer) 1601 { 1602 AcpiOsFree (RegionElement); 1603 return (AE_NO_MEMORY); 1604 } 1605 1606 /* Initialize the region with the default fill value */ 1607 1608 ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length); 1609 1610 RegionElement->Address = BaseAddress; 1611 RegionElement->Length = Length; 1612 RegionElement->SpaceId = SpaceId; 1613 RegionElement->NextRegion = NULL; 1614 1615 /* 1616 * Increment the number of regions and put this one 1617 * at the head of the list as it will probably get accessed 1618 * more often anyway. 1619 */ 1620 AeRegions.NumberOfRegions += 1; 1621 1622 if (AeRegions.RegionList) 1623 { 1624 RegionElement->NextRegion = AeRegions.RegionList; 1625 } 1626 1627 AeRegions.RegionList = RegionElement; 1628 } 1629 1630 /* Calculate the size of the memory copy */ 1631 1632 ByteWidth = (BitWidth / 8); 1633 1634 if (BitWidth % 8) 1635 { 1636 ByteWidth += 1; 1637 } 1638 1639 /* 1640 * The buffer exists and is pointed to by RegionElement. 1641 * We now need to verify the request is valid and perform the operation. 1642 * 1643 * NOTE: RegionElement->Length is in bytes, therefore it we compare against 1644 * ByteWidth (see above) 1645 */ 1646 if (((UINT64) Address + ByteWidth) > 1647 ((UINT64)(RegionElement->Address) + RegionElement->Length)) 1648 { 1649 ACPI_WARNING ((AE_INFO, 1650 "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X", 1651 (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address, 1652 ByteWidth, (UINT32)(RegionElement->Address), 1653 RegionElement->Length)); 1654 1655 return (AE_AML_REGION_LIMIT); 1656 } 1657 1658 /* 1659 * Get BufferValue to point to the "address" in the buffer 1660 */ 1661 BufferValue = ((UINT8 *) RegionElement->Buffer + 1662 ((UINT64) Address - (UINT64) RegionElement->Address)); 1663 1664 DoFunction: 1665 /* 1666 * Perform a read or write to the buffer space 1667 */ 1668 switch (Function) 1669 { 1670 case ACPI_READ: 1671 /* 1672 * Set the pointer Value to whatever is in the buffer 1673 */ 1674 ACPI_MEMCPY (Value, BufferValue, ByteWidth); 1675 break; 1676 1677 case ACPI_WRITE: 1678 /* 1679 * Write the contents of Value to the buffer 1680 */ 1681 ACPI_MEMCPY (BufferValue, Value, ByteWidth); 1682 break; 1683 1684 default: 1685 1686 return (AE_BAD_PARAMETER); 1687 } 1688 1689 if (AcpiGbl_DisplayRegionAccess) 1690 { 1691 switch (SpaceId) 1692 { 1693 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 1694 1695 AcpiOsPrintf ("AcpiExec: SystemMemory " 1696 "%s: Val %.8X Addr %.4X Width %X [REGION: BaseAddr %.4X Len %.2X]\n", 1697 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 1698 (UINT32) *Value, (UINT32) Address, BitWidth, (UINT32) BaseAddress, Length); 1699 break; 1700 1701 case ACPI_ADR_SPACE_GPIO: /* ACPI 5.0 */ 1702 1703 /* This space is required to always be ByteAcc */ 1704 1705 Status = AcpiBufferToResource (MyContext->Connection, 1706 MyContext->Length, &Resource); 1707 1708 AcpiOsPrintf ("AcpiExec: GeneralPurposeIo " 1709 "%s: Val %.8X Addr %.4X BaseAddr %.4X Len %.2X Width %X AccLen %.2X Conn %p\n", 1710 (Function & ACPI_IO_MASK) ? "Write" : "Read ", (UINT32) *Value, 1711 (UINT32) Address, (UINT32) BaseAddress, Length, BitWidth, 1712 MyContext->AccessLength, MyContext->Connection); 1713 break; 1714 1715 default: 1716 1717 break; 1718 } 1719 } 1720 1721 return (AE_OK); 1722 } 1723