Home | History | Annotate | Line # | Download | only in acpiexec
aehandlers.c revision 1.1.1.2
      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