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