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 Length = MyContext->AccessLength; 1345 break; 1346 1347 default: 1348 1349 break; 1350 } 1351 break; 1352 1353 case ACPI_WRITE: 1354 1355 switch (Function >> 16) 1356 { 1357 case AML_FIELD_ATTRIB_QUICK: 1358 case AML_FIELD_ATTRIB_SEND_RCV: 1359 case AML_FIELD_ATTRIB_BYTE: 1360 case AML_FIELD_ATTRIB_WORD: 1361 case AML_FIELD_ATTRIB_BLOCK: 1362 1363 Length = 0; 1364 break; 1365 1366 case AML_FIELD_ATTRIB_WORD_CALL: 1367 Length = 2; 1368 break; 1369 1370 case AML_FIELD_ATTRIB_BLOCK_CALL: 1371 Length = 32; 1372 break; 1373 1374 case AML_FIELD_ATTRIB_MULTIBYTE: 1375 case AML_FIELD_ATTRIB_RAW_BYTES: 1376 case AML_FIELD_ATTRIB_RAW_PROCESS: 1377 1378 Length = MyContext->AccessLength; 1379 break; 1380 1381 default: 1382 1383 break; 1384 } 1385 break; 1386 1387 default: 1388 1389 break; 1390 } 1391 1392 if (AcpiGbl_DisplayRegionAccess) 1393 { 1394 AcpiOsPrintf ("AcpiExec: %s " 1395 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X", 1396 AcpiUtGetRegionName (SpaceId), 1397 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 1398 (UINT32) (Function >> 16), 1399 (UINT32) Address, (UINT32) BaseAddress, 1400 Length, BitWidth, Buffer[1]); 1401 1402 /* GenericSerialBus has a Connection() parameter */ 1403 1404 if (SpaceId == ACPI_ADR_SPACE_GSBUS) 1405 { 1406 Status = AcpiBufferToResource (MyContext->Connection, 1407 MyContext->Length, &Resource); 1408 1409 AcpiOsPrintf (" [AccLen %.2X Conn %p]", 1410 MyContext->AccessLength, MyContext->Connection); 1411 } 1412 AcpiOsPrintf ("\n"); 1413 } 1414 1415 /* Setup the return buffer. Note: ASLTS depends on these fill values */ 1416 1417 for (i = 0; i < Length; i++) 1418 { 1419 Buffer[i+2] = (UINT8) (0xA0 + i); 1420 } 1421 1422 Buffer[0] = 0x7A; 1423 Buffer[1] = (UINT8) Length; 1424 return (AE_OK); 1425 1426 1427 case ACPI_ADR_SPACE_IPMI: /* ACPI 4.0 */ 1428 1429 if (AcpiGbl_DisplayRegionAccess) 1430 { 1431 AcpiOsPrintf ("AcpiExec: IPMI " 1432 "%s: Attr %X Addr %.4X BaseAddr %.4X Len %.2X Width %X BufLen %X\n", 1433 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 1434 (UINT32) (Function >> 16), (UINT32) Address, (UINT32) BaseAddress, 1435 Length, BitWidth, Buffer[1]); 1436 } 1437 1438 /* 1439 * Regardless of a READ or WRITE, this handler is passed a 66-byte 1440 * buffer in which to return the IPMI status/length/data. 1441 * 1442 * Return some example data to show use of the bidirectional buffer 1443 */ 1444 Buffer[0] = 0; /* Status byte */ 1445 Buffer[1] = 64; /* Return buffer data length */ 1446 Buffer[2] = 0; /* Completion code */ 1447 Buffer[3] = 0; /* Reserved */ 1448 1449 /* 1450 * Fill the 66-byte buffer with the return data. 1451 * Note: ASLTS depends on these fill values. 1452 */ 1453 for (i = 4; i < 66; i++) 1454 { 1455 Buffer[i] = (UINT8) (i); 1456 } 1457 return (AE_OK); 1458 1459 default: 1460 break; 1461 } 1462 1463 /* 1464 * Search through the linked list for this region's buffer 1465 */ 1466 BufferExists = FALSE; 1467 BufferResize = FALSE; 1468 RegionElement = AeRegions.RegionList; 1469 1470 if (AeRegions.NumberOfRegions) 1471 { 1472 BaseAddressEnd = BaseAddress + Length - 1; 1473 while (!BufferExists && RegionElement) 1474 { 1475 RegionAddress = RegionElement->Address; 1476 RegionAddressEnd = RegionElement->Address + RegionElement->Length - 1; 1477 RegionLength = RegionElement->Length; 1478 1479 /* 1480 * Overlapping Region Support 1481 * 1482 * While searching through the region buffer list, determine if an 1483 * overlap exists between the requested buffer space and the current 1484 * RegionElement space. If there is an overlap then replace the old 1485 * buffer with a new buffer of increased size before continuing to 1486 * do the read or write 1487 */ 1488 if (RegionElement->SpaceId != SpaceId || 1489 BaseAddressEnd < RegionAddress || 1490 BaseAddress > RegionAddressEnd) 1491 { 1492 /* 1493 * Requested buffer is outside of the current RegionElement 1494 * bounds 1495 */ 1496 RegionElement = RegionElement->NextRegion; 1497 } 1498 else 1499 { 1500 /* 1501 * Some amount of buffer space sharing exists. There are 4 cases 1502 * to consider: 1503 * 1504 * 1. Right overlap 1505 * 2. Left overlap 1506 * 3. Left and right overlap 1507 * 4. Fully contained - no resizing required 1508 */ 1509 BufferExists = TRUE; 1510 1511 if ((BaseAddress >= RegionAddress) && 1512 (BaseAddress <= RegionAddressEnd) && 1513 (BaseAddressEnd > RegionAddressEnd)) 1514 { 1515 /* Right overlap */ 1516 1517 RegionElement->Length = BaseAddress - 1518 RegionAddress + Length; 1519 BufferResize = TRUE; 1520 } 1521 1522 else if ((BaseAddressEnd >= RegionAddress) && 1523 (BaseAddressEnd <= RegionAddressEnd) && 1524 (BaseAddress < RegionAddress)) 1525 { 1526 /* Left overlap */ 1527 1528 RegionElement->Address = BaseAddress; 1529 RegionElement->Length = RegionAddress - 1530 BaseAddress + RegionElement->Length; 1531 BufferResize = TRUE; 1532 } 1533 1534 else if ((BaseAddress < RegionAddress) && 1535 (BaseAddressEnd > RegionAddressEnd)) 1536 { 1537 /* Left and right overlap */ 1538 1539 RegionElement->Address = BaseAddress; 1540 RegionElement->Length = Length; 1541 BufferResize = TRUE; 1542 } 1543 1544 /* 1545 * only remaining case is fully contained for which we don't 1546 * need to do anything 1547 */ 1548 if (BufferResize) 1549 { 1550 NewBuffer = AcpiOsAllocate (RegionElement->Length); 1551 if (!NewBuffer) 1552 { 1553 return (AE_NO_MEMORY); 1554 } 1555 1556 OldBuffer = RegionElement->Buffer; 1557 RegionElement->Buffer = NewBuffer; 1558 NewBuffer = NULL; 1559 1560 /* Initialize the region with the default fill value */ 1561 1562 ACPI_MEMSET (RegionElement->Buffer, 1563 AcpiGbl_RegionFillValue, RegionElement->Length); 1564 1565 /* 1566 * Get BufferValue to point (within the new buffer) to the 1567 * base address of the old buffer 1568 */ 1569 BufferValue = (UINT8 *) RegionElement->Buffer + 1570 (UINT64) RegionAddress - 1571 (UINT64) RegionElement->Address; 1572 1573 /* 1574 * Copy the old buffer to its same location within the new 1575 * buffer 1576 */ 1577 ACPI_MEMCPY (BufferValue, OldBuffer, RegionLength); 1578 AcpiOsFree (OldBuffer); 1579 } 1580 } 1581 } 1582 } 1583 1584 /* 1585 * If the Region buffer does not exist, create it now 1586 */ 1587 if (!BufferExists) 1588 { 1589 /* Do the memory allocations first */ 1590 1591 RegionElement = AcpiOsAllocate (sizeof (AE_REGION)); 1592 if (!RegionElement) 1593 { 1594 return (AE_NO_MEMORY); 1595 } 1596 1597 RegionElement->Buffer = AcpiOsAllocate (Length); 1598 if (!RegionElement->Buffer) 1599 { 1600 AcpiOsFree (RegionElement); 1601 return (AE_NO_MEMORY); 1602 } 1603 1604 /* Initialize the region with the default fill value */ 1605 1606 ACPI_MEMSET (RegionElement->Buffer, AcpiGbl_RegionFillValue, Length); 1607 1608 RegionElement->Address = BaseAddress; 1609 RegionElement->Length = Length; 1610 RegionElement->SpaceId = SpaceId; 1611 RegionElement->NextRegion = NULL; 1612 1613 /* 1614 * Increment the number of regions and put this one 1615 * at the head of the list as it will probably get accessed 1616 * more often anyway. 1617 */ 1618 AeRegions.NumberOfRegions += 1; 1619 1620 if (AeRegions.RegionList) 1621 { 1622 RegionElement->NextRegion = AeRegions.RegionList; 1623 } 1624 1625 AeRegions.RegionList = RegionElement; 1626 } 1627 1628 /* Calculate the size of the memory copy */ 1629 1630 ByteWidth = (BitWidth / 8); 1631 1632 if (BitWidth % 8) 1633 { 1634 ByteWidth += 1; 1635 } 1636 1637 /* 1638 * The buffer exists and is pointed to by RegionElement. 1639 * We now need to verify the request is valid and perform the operation. 1640 * 1641 * NOTE: RegionElement->Length is in bytes, therefore it we compare against 1642 * ByteWidth (see above) 1643 */ 1644 if (((UINT64) Address + ByteWidth) > 1645 ((UINT64)(RegionElement->Address) + RegionElement->Length)) 1646 { 1647 ACPI_WARNING ((AE_INFO, 1648 "Request on [%4.4s] is beyond region limit Req-0x%X+0x%X, Base=0x%X, Len-0x%X", 1649 (RegionObject->Region.Node)->Name.Ascii, (UINT32) Address, 1650 ByteWidth, (UINT32)(RegionElement->Address), 1651 RegionElement->Length)); 1652 1653 return (AE_AML_REGION_LIMIT); 1654 } 1655 1656 /* 1657 * Get BufferValue to point to the "address" in the buffer 1658 */ 1659 BufferValue = ((UINT8 *) RegionElement->Buffer + 1660 ((UINT64) Address - (UINT64) RegionElement->Address)); 1661 1662 DoFunction: 1663 /* 1664 * Perform a read or write to the buffer space 1665 */ 1666 switch (Function) 1667 { 1668 case ACPI_READ: 1669 /* 1670 * Set the pointer Value to whatever is in the buffer 1671 */ 1672 ACPI_MEMCPY (Value, BufferValue, ByteWidth); 1673 break; 1674 1675 case ACPI_WRITE: 1676 /* 1677 * Write the contents of Value to the buffer 1678 */ 1679 ACPI_MEMCPY (BufferValue, Value, ByteWidth); 1680 break; 1681 1682 default: 1683 1684 return (AE_BAD_PARAMETER); 1685 } 1686 1687 if (AcpiGbl_DisplayRegionAccess) 1688 { 1689 switch (SpaceId) 1690 { 1691 case ACPI_ADR_SPACE_SYSTEM_MEMORY: 1692 1693 AcpiOsPrintf ("AcpiExec: SystemMemory " 1694 "%s: Val %.8X Addr %.4X Width %X [REGION: BaseAddr %.4X Len %.2X]\n", 1695 (Function & ACPI_IO_MASK) ? "Write" : "Read ", 1696 (UINT32) *Value, (UINT32) Address, BitWidth, (UINT32) BaseAddress, Length); 1697 break; 1698 1699 case ACPI_ADR_SPACE_GPIO: /* ACPI 5.0 */ 1700 1701 /* This space is required to always be ByteAcc */ 1702 1703 Status = AcpiBufferToResource (MyContext->Connection, 1704 MyContext->Length, &Resource); 1705 1706 AcpiOsPrintf ("AcpiExec: GeneralPurposeIo " 1707 "%s: Val %.8X Addr %.4X BaseAddr %.4X Len %.2X Width %X AccLen %.2X Conn %p\n", 1708 (Function & ACPI_IO_MASK) ? "Write" : "Read ", (UINT32) *Value, 1709 (UINT32) Address, (UINT32) BaseAddress, Length, BitWidth, 1710 MyContext->AccessLength, MyContext->Connection); 1711 break; 1712 1713 default: 1714 1715 break; 1716 } 1717 } 1718 1719 return (AE_OK); 1720 } 1721