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