Home | History | Annotate | Line # | Download | only in utilities
utosi.c revision 1.1
      1 /******************************************************************************
      2  *
      3  * Module Name: utosi - Support for the _OSI predefined control method
      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 #define __UTOSI_C__
     45 
     46 #include "acpi.h"
     47 #include "accommon.h"
     48 
     49 
     50 #define _COMPONENT          ACPI_UTILITIES
     51         ACPI_MODULE_NAME    ("utosi")
     52 
     53 /*
     54  * Strings supported by the _OSI predefined control method (which is
     55  * implemented internally within this module.)
     56  *
     57  * March 2009: Removed "Linux" as this host no longer wants to respond true
     58  * for this string. Basically, the only safe OS strings are windows-related
     59  * and in many or most cases represent the only test path within the
     60  * BIOS-provided ASL code.
     61  *
     62  * The last element of each entry is used to track the newest version of
     63  * Windows that the BIOS has requested.
     64  */
     65 static ACPI_INTERFACE_INFO    AcpiDefaultSupportedInterfaces[] =
     66 {
     67     /* Operating System Vendor Strings */
     68 
     69     {"Windows 2000",        NULL, 0, ACPI_OSI_WIN_2000},         /* Windows 2000 */
     70     {"Windows 2001",        NULL, 0, ACPI_OSI_WIN_XP},           /* Windows XP */
     71     {"Windows 2001 SP1",    NULL, 0, ACPI_OSI_WIN_XP_SP1},       /* Windows XP SP1 */
     72     {"Windows 2001.1",      NULL, 0, ACPI_OSI_WINSRV_2003},      /* Windows Server 2003 */
     73     {"Windows 2001 SP2",    NULL, 0, ACPI_OSI_WIN_XP_SP2},       /* Windows XP SP2 */
     74     {"Windows 2001.1 SP1",  NULL, 0, ACPI_OSI_WINSRV_2003_SP1},  /* Windows Server 2003 SP1 - Added 03/2006 */
     75     {"Windows 2006",        NULL, 0, ACPI_OSI_WIN_VISTA},        /* Windows Vista - Added 03/2006 */
     76     {"Windows 2006.1",      NULL, 0, ACPI_OSI_WINSRV_2008},      /* Windows Server 2008 - Added 09/2009 */
     77     {"Windows 2006 SP1",    NULL, 0, ACPI_OSI_WIN_VISTA_SP1},    /* Windows Vista SP1 - Added 09/2009 */
     78     {"Windows 2006 SP2",    NULL, 0, ACPI_OSI_WIN_VISTA_SP2},    /* Windows Vista SP2 - Added 09/2010 */
     79     {"Windows 2009",        NULL, 0, ACPI_OSI_WIN_7},            /* Windows 7 and Server 2008 R2 - Added 09/2009 */
     80 
     81     /* Feature Group Strings */
     82 
     83     {"Extended Address Space Descriptor", NULL, 0, 0}
     84 
     85     /*
     86      * All "optional" feature group strings (features that are implemented
     87      * by the host) should be dynamically added by the host via
     88      * AcpiInstallInterface and should not be manually added here.
     89      *
     90      * Examples of optional feature group strings:
     91      *
     92      * "Module Device"
     93      * "Processor Device"
     94      * "3.0 Thermal Model"
     95      * "3.0 _SCP Extensions"
     96      * "Processor Aggregator Device"
     97      */
     98 };
     99 
    100 
    101 /*******************************************************************************
    102  *
    103  * FUNCTION:    AcpiUtInitializeInterfaces
    104  *
    105  * PARAMETERS:  None
    106  *
    107  * RETURN:      Status
    108  *
    109  * DESCRIPTION: Initialize the global _OSI supported interfaces list
    110  *
    111  ******************************************************************************/
    112 
    113 ACPI_STATUS
    114 AcpiUtInitializeInterfaces (
    115     void)
    116 {
    117     UINT32                  i;
    118 
    119 
    120     (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
    121     AcpiGbl_SupportedInterfaces = AcpiDefaultSupportedInterfaces;
    122 
    123     /* Link the static list of supported interfaces */
    124 
    125     for (i = 0; i < (ACPI_ARRAY_LENGTH (AcpiDefaultSupportedInterfaces) - 1); i++)
    126     {
    127         AcpiDefaultSupportedInterfaces[i].Next =
    128             &AcpiDefaultSupportedInterfaces[(ACPI_SIZE) i + 1];
    129     }
    130 
    131     AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
    132     return (AE_OK);
    133 }
    134 
    135 
    136 /*******************************************************************************
    137  *
    138  * FUNCTION:    AcpiUtInterfaceTerminate
    139  *
    140  * PARAMETERS:  None
    141  *
    142  * RETURN:      None
    143  *
    144  * DESCRIPTION: Delete all interfaces in the global list. Sets
    145  *              AcpiGbl_SupportedInterfaces to NULL.
    146  *
    147  ******************************************************************************/
    148 
    149 void
    150 AcpiUtInterfaceTerminate (
    151     void)
    152 {
    153     ACPI_INTERFACE_INFO     *NextInterface;
    154 
    155 
    156     (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
    157     NextInterface = AcpiGbl_SupportedInterfaces;
    158 
    159     while (NextInterface)
    160     {
    161         AcpiGbl_SupportedInterfaces = NextInterface->Next;
    162 
    163         /* Only interfaces added at runtime can be freed */
    164 
    165         if (NextInterface->Flags & ACPI_OSI_DYNAMIC)
    166         {
    167             ACPI_FREE (NextInterface->Name);
    168             ACPI_FREE (NextInterface);
    169         }
    170 
    171         NextInterface = AcpiGbl_SupportedInterfaces;
    172     }
    173 
    174     AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
    175 }
    176 
    177 
    178 /*******************************************************************************
    179  *
    180  * FUNCTION:    AcpiUtInstallInterface
    181  *
    182  * PARAMETERS:  InterfaceName       - The interface to install
    183  *
    184  * RETURN:      Status
    185  *
    186  * DESCRIPTION: Install the interface into the global interface list.
    187  *              Caller MUST hold AcpiGbl_OsiMutex
    188  *
    189  ******************************************************************************/
    190 
    191 ACPI_STATUS
    192 AcpiUtInstallInterface (
    193     ACPI_STRING             InterfaceName)
    194 {
    195     ACPI_INTERFACE_INFO     *InterfaceInfo;
    196 
    197 
    198     /* Allocate info block and space for the name string */
    199 
    200     InterfaceInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_INTERFACE_INFO));
    201     if (!InterfaceInfo)
    202     {
    203         return (AE_NO_MEMORY);
    204     }
    205 
    206     InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (InterfaceName) + 1);
    207     if (!InterfaceInfo->Name)
    208     {
    209         ACPI_FREE (InterfaceInfo);
    210         return (AE_NO_MEMORY);
    211     }
    212 
    213     /* Initialize new info and insert at the head of the global list */
    214 
    215     ACPI_STRCPY (InterfaceInfo->Name, InterfaceName);
    216     InterfaceInfo->Flags = ACPI_OSI_DYNAMIC;
    217     InterfaceInfo->Next = AcpiGbl_SupportedInterfaces;
    218 
    219     AcpiGbl_SupportedInterfaces = InterfaceInfo;
    220     return (AE_OK);
    221 }
    222 
    223 
    224 /*******************************************************************************
    225  *
    226  * FUNCTION:    AcpiUtRemoveInterface
    227  *
    228  * PARAMETERS:  InterfaceName       - The interface to remove
    229  *
    230  * RETURN:      Status
    231  *
    232  * DESCRIPTION: Remove the interface from the global interface list.
    233  *              Caller MUST hold AcpiGbl_OsiMutex
    234  *
    235  ******************************************************************************/
    236 
    237 ACPI_STATUS
    238 AcpiUtRemoveInterface (
    239     ACPI_STRING             InterfaceName)
    240 {
    241     ACPI_INTERFACE_INFO     *PreviousInterface;
    242     ACPI_INTERFACE_INFO     *NextInterface;
    243 
    244 
    245     PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces;
    246     while (NextInterface)
    247     {
    248         if (!ACPI_STRCMP (InterfaceName, NextInterface->Name))
    249         {
    250             /* Found: name is in either the static list or was added at runtime */
    251 
    252             if (NextInterface->Flags & ACPI_OSI_DYNAMIC)
    253             {
    254                 /* Interface was added dynamically, remove and free it */
    255 
    256                 if (PreviousInterface == NextInterface)
    257                 {
    258                     AcpiGbl_SupportedInterfaces = NextInterface->Next;
    259                 }
    260                 else
    261                 {
    262                     PreviousInterface->Next = NextInterface->Next;
    263                 }
    264 
    265                 ACPI_FREE (NextInterface->Name);
    266                 ACPI_FREE (NextInterface);
    267             }
    268             else
    269             {
    270                 /*
    271                  * Interface is in static list. If marked invalid, then it
    272                  * does not actually exist. Else, mark it invalid.
    273                  */
    274                 if (NextInterface->Flags & ACPI_OSI_INVALID)
    275                 {
    276                     return (AE_NOT_EXIST);
    277                 }
    278 
    279                 NextInterface->Flags |= ACPI_OSI_INVALID;
    280             }
    281 
    282             return (AE_OK);
    283         }
    284 
    285         PreviousInterface = NextInterface;
    286         NextInterface = NextInterface->Next;
    287     }
    288 
    289     /* Interface was not found */
    290 
    291     return (AE_NOT_EXIST);
    292 }
    293 
    294 
    295 /*******************************************************************************
    296  *
    297  * FUNCTION:    AcpiUtGetInterface
    298  *
    299  * PARAMETERS:  InterfaceName       - The interface to find
    300  *
    301  * RETURN:      ACPI_INTERFACE_INFO if found. NULL if not found.
    302  *
    303  * DESCRIPTION: Search for the specified interface name in the global list.
    304  *              Caller MUST hold AcpiGbl_OsiMutex
    305  *
    306  ******************************************************************************/
    307 
    308 ACPI_INTERFACE_INFO *
    309 AcpiUtGetInterface (
    310     ACPI_STRING             InterfaceName)
    311 {
    312     ACPI_INTERFACE_INFO     *NextInterface;
    313 
    314 
    315     NextInterface = AcpiGbl_SupportedInterfaces;
    316     while (NextInterface)
    317     {
    318         if (!ACPI_STRCMP (InterfaceName, NextInterface->Name))
    319         {
    320             return (NextInterface);
    321         }
    322 
    323         NextInterface = NextInterface->Next;
    324     }
    325 
    326     return (NULL);
    327 }
    328 
    329 
    330 /*******************************************************************************
    331  *
    332  * FUNCTION:    AcpiUtOsiImplementation
    333  *
    334  * PARAMETERS:  WalkState           - Current walk state
    335  *
    336  * RETURN:      Status
    337  *
    338  * DESCRIPTION: Implementation of the _OSI predefined control method. When
    339  *              an invocation of _OSI is encountered in the system AML,
    340  *              control is transferred to this function.
    341  *
    342  ******************************************************************************/
    343 
    344 ACPI_STATUS
    345 AcpiUtOsiImplementation (
    346     ACPI_WALK_STATE         *WalkState)
    347 {
    348     ACPI_OPERAND_OBJECT     *StringDesc;
    349     ACPI_OPERAND_OBJECT     *ReturnDesc;
    350     ACPI_INTERFACE_INFO     *InterfaceInfo;
    351     ACPI_INTERFACE_HANDLER  InterfaceHandler;
    352     UINT32                  ReturnValue;
    353 
    354 
    355     ACPI_FUNCTION_TRACE (UtOsiImplementation);
    356 
    357 
    358     /* Validate the string input argument (from the AML caller) */
    359 
    360     StringDesc = WalkState->Arguments[0].Object;
    361     if (!StringDesc ||
    362         (StringDesc->Common.Type != ACPI_TYPE_STRING))
    363     {
    364         return_ACPI_STATUS (AE_TYPE);
    365     }
    366 
    367     /* Create a return object */
    368 
    369     ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
    370     if (!ReturnDesc)
    371     {
    372         return_ACPI_STATUS (AE_NO_MEMORY);
    373     }
    374 
    375     /* Default return value is 0, NOT SUPPORTED */
    376 
    377     ReturnValue = 0;
    378     (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
    379 
    380     /* Lookup the interface in the global _OSI list */
    381 
    382     InterfaceInfo = AcpiUtGetInterface (StringDesc->String.Pointer);
    383     if (InterfaceInfo &&
    384         !(InterfaceInfo->Flags & ACPI_OSI_INVALID))
    385     {
    386         /*
    387          * The interface is supported.
    388          * Update the OsiData if necessary. We keep track of the latest
    389          * version of Windows that has been requested by the BIOS.
    390          */
    391         if (InterfaceInfo->Value > AcpiGbl_OsiData)
    392         {
    393             AcpiGbl_OsiData = InterfaceInfo->Value;
    394         }
    395 
    396         ReturnValue = ACPI_UINT32_MAX;
    397     }
    398 
    399     AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
    400 
    401     /*
    402      * Invoke an optional _OSI interface handler. The host OS may wish
    403      * to do some interface-specific handling. For example, warn about
    404      * certain interfaces or override the true/false support value.
    405      */
    406     InterfaceHandler = AcpiGbl_InterfaceHandler;
    407     if (InterfaceHandler)
    408     {
    409         ReturnValue = InterfaceHandler (
    410             StringDesc->String.Pointer, ReturnValue);
    411     }
    412 
    413     ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
    414         "ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
    415         StringDesc->String.Pointer, ReturnValue == 0 ? "not " : ""));
    416 
    417     /* Complete the return object */
    418 
    419     ReturnDesc->Integer.Value = ReturnValue;
    420     WalkState->ReturnDesc = ReturnDesc;
    421     return_ACPI_STATUS (AE_OK);
    422 }
    423