utosi.c revision 249663
1210944Sjkim/****************************************************************************** 2210944Sjkim * 3210944Sjkim * Module Name: utosi - Support for the _OSI predefined control method 4210944Sjkim * 5210944Sjkim *****************************************************************************/ 6210944Sjkim 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, Intel Corp. 9210944Sjkim * All rights reserved. 10210944Sjkim * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25210944Sjkim * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29210944Sjkim * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43210944Sjkim 44210944Sjkim#define __UTOSI_C__ 45210944Sjkim 46210976Sjkim#include <contrib/dev/acpica/include/acpi.h> 47210976Sjkim#include <contrib/dev/acpica/include/accommon.h> 48210944Sjkim 49210944Sjkim 50210944Sjkim#define _COMPONENT ACPI_UTILITIES 51210944Sjkim ACPI_MODULE_NAME ("utosi") 52210944Sjkim 53210944Sjkim/* 54210944Sjkim * Strings supported by the _OSI predefined control method (which is 55210944Sjkim * implemented internally within this module.) 56210944Sjkim * 57210944Sjkim * March 2009: Removed "Linux" as this host no longer wants to respond true 58210944Sjkim * for this string. Basically, the only safe OS strings are windows-related 59210944Sjkim * and in many or most cases represent the only test path within the 60210944Sjkim * BIOS-provided ASL code. 61210944Sjkim * 62210944Sjkim * The last element of each entry is used to track the newest version of 63210944Sjkim * Windows that the BIOS has requested. 64210944Sjkim */ 65210944Sjkimstatic ACPI_INTERFACE_INFO AcpiDefaultSupportedInterfaces[] = 66210944Sjkim{ 67210944Sjkim /* Operating System Vendor Strings */ 68210944Sjkim 69210944Sjkim {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */ 70210944Sjkim {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */ 71210944Sjkim {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ 72210944Sjkim {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ 73210944Sjkim {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ 74210944Sjkim {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ 75210944Sjkim {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ 76210944Sjkim {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ 77210944Sjkim {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ 78213806Sjkim {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ 79210944Sjkim {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ 80239340Sjkim {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */ 81210944Sjkim 82210944Sjkim /* Feature Group Strings */ 83210944Sjkim 84210944Sjkim {"Extended Address Space Descriptor", NULL, 0, 0} 85210944Sjkim 86210944Sjkim /* 87210944Sjkim * All "optional" feature group strings (features that are implemented 88210944Sjkim * by the host) should be dynamically added by the host via 89210944Sjkim * AcpiInstallInterface and should not be manually added here. 90210944Sjkim * 91210944Sjkim * Examples of optional feature group strings: 92210944Sjkim * 93210944Sjkim * "Module Device" 94210944Sjkim * "Processor Device" 95210944Sjkim * "3.0 Thermal Model" 96210944Sjkim * "3.0 _SCP Extensions" 97210944Sjkim * "Processor Aggregator Device" 98210944Sjkim */ 99210944Sjkim}; 100210944Sjkim 101210944Sjkim 102210944Sjkim/******************************************************************************* 103210944Sjkim * 104210944Sjkim * FUNCTION: AcpiUtInitializeInterfaces 105210944Sjkim * 106210944Sjkim * PARAMETERS: None 107210944Sjkim * 108210944Sjkim * RETURN: Status 109210944Sjkim * 110210944Sjkim * DESCRIPTION: Initialize the global _OSI supported interfaces list 111210944Sjkim * 112210944Sjkim ******************************************************************************/ 113210944Sjkim 114210944SjkimACPI_STATUS 115210944SjkimAcpiUtInitializeInterfaces ( 116210944Sjkim void) 117210944Sjkim{ 118249112Sjkim ACPI_STATUS Status; 119210944Sjkim UINT32 i; 120210944Sjkim 121210944Sjkim 122249112Sjkim Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 123249112Sjkim if (ACPI_FAILURE (Status)) 124249112Sjkim { 125249112Sjkim return (Status); 126249112Sjkim } 127249112Sjkim 128210944Sjkim AcpiGbl_SupportedInterfaces = AcpiDefaultSupportedInterfaces; 129210944Sjkim 130210944Sjkim /* Link the static list of supported interfaces */ 131210944Sjkim 132210944Sjkim for (i = 0; i < (ACPI_ARRAY_LENGTH (AcpiDefaultSupportedInterfaces) - 1); i++) 133210944Sjkim { 134210944Sjkim AcpiDefaultSupportedInterfaces[i].Next = 135210944Sjkim &AcpiDefaultSupportedInterfaces[(ACPI_SIZE) i + 1]; 136210944Sjkim } 137210944Sjkim 138210944Sjkim AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 139210944Sjkim return (AE_OK); 140210944Sjkim} 141210944Sjkim 142210944Sjkim 143210944Sjkim/******************************************************************************* 144210944Sjkim * 145210944Sjkim * FUNCTION: AcpiUtInterfaceTerminate 146210944Sjkim * 147210944Sjkim * PARAMETERS: None 148210944Sjkim * 149249112Sjkim * RETURN: Status 150210944Sjkim * 151210944Sjkim * DESCRIPTION: Delete all interfaces in the global list. Sets 152210944Sjkim * AcpiGbl_SupportedInterfaces to NULL. 153210944Sjkim * 154210944Sjkim ******************************************************************************/ 155210944Sjkim 156249112SjkimACPI_STATUS 157210944SjkimAcpiUtInterfaceTerminate ( 158210944Sjkim void) 159210944Sjkim{ 160249112Sjkim ACPI_STATUS Status; 161210944Sjkim ACPI_INTERFACE_INFO *NextInterface; 162210944Sjkim 163210944Sjkim 164249112Sjkim Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 165249112Sjkim if (ACPI_FAILURE (Status)) 166249112Sjkim { 167249112Sjkim return (Status); 168249112Sjkim } 169249112Sjkim 170210944Sjkim NextInterface = AcpiGbl_SupportedInterfaces; 171210944Sjkim while (NextInterface) 172210944Sjkim { 173210944Sjkim AcpiGbl_SupportedInterfaces = NextInterface->Next; 174210944Sjkim 175210944Sjkim /* Only interfaces added at runtime can be freed */ 176210944Sjkim 177210944Sjkim if (NextInterface->Flags & ACPI_OSI_DYNAMIC) 178210944Sjkim { 179210944Sjkim ACPI_FREE (NextInterface->Name); 180210944Sjkim ACPI_FREE (NextInterface); 181210944Sjkim } 182210944Sjkim 183210944Sjkim NextInterface = AcpiGbl_SupportedInterfaces; 184210944Sjkim } 185210944Sjkim 186210944Sjkim AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 187249112Sjkim return (AE_OK); 188210944Sjkim} 189210944Sjkim 190210944Sjkim 191210944Sjkim/******************************************************************************* 192210944Sjkim * 193210944Sjkim * FUNCTION: AcpiUtInstallInterface 194210944Sjkim * 195210944Sjkim * PARAMETERS: InterfaceName - The interface to install 196210944Sjkim * 197210944Sjkim * RETURN: Status 198210944Sjkim * 199210944Sjkim * DESCRIPTION: Install the interface into the global interface list. 200210944Sjkim * Caller MUST hold AcpiGbl_OsiMutex 201210944Sjkim * 202210944Sjkim ******************************************************************************/ 203210944Sjkim 204210944SjkimACPI_STATUS 205210944SjkimAcpiUtInstallInterface ( 206210944Sjkim ACPI_STRING InterfaceName) 207210944Sjkim{ 208210944Sjkim ACPI_INTERFACE_INFO *InterfaceInfo; 209210944Sjkim 210210944Sjkim 211210944Sjkim /* Allocate info block and space for the name string */ 212210944Sjkim 213210944Sjkim InterfaceInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_INTERFACE_INFO)); 214210944Sjkim if (!InterfaceInfo) 215210944Sjkim { 216210944Sjkim return (AE_NO_MEMORY); 217210944Sjkim } 218210944Sjkim 219210944Sjkim InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (InterfaceName) + 1); 220210944Sjkim if (!InterfaceInfo->Name) 221210944Sjkim { 222210944Sjkim ACPI_FREE (InterfaceInfo); 223210944Sjkim return (AE_NO_MEMORY); 224210944Sjkim } 225210944Sjkim 226210944Sjkim /* Initialize new info and insert at the head of the global list */ 227210944Sjkim 228210944Sjkim ACPI_STRCPY (InterfaceInfo->Name, InterfaceName); 229210944Sjkim InterfaceInfo->Flags = ACPI_OSI_DYNAMIC; 230210944Sjkim InterfaceInfo->Next = AcpiGbl_SupportedInterfaces; 231210944Sjkim 232210944Sjkim AcpiGbl_SupportedInterfaces = InterfaceInfo; 233210944Sjkim return (AE_OK); 234210944Sjkim} 235210944Sjkim 236210944Sjkim 237210944Sjkim/******************************************************************************* 238210944Sjkim * 239210944Sjkim * FUNCTION: AcpiUtRemoveInterface 240210944Sjkim * 241210944Sjkim * PARAMETERS: InterfaceName - The interface to remove 242210944Sjkim * 243210944Sjkim * RETURN: Status 244210944Sjkim * 245210944Sjkim * DESCRIPTION: Remove the interface from the global interface list. 246210944Sjkim * Caller MUST hold AcpiGbl_OsiMutex 247210944Sjkim * 248210944Sjkim ******************************************************************************/ 249210944Sjkim 250210944SjkimACPI_STATUS 251210944SjkimAcpiUtRemoveInterface ( 252210944Sjkim ACPI_STRING InterfaceName) 253210944Sjkim{ 254210944Sjkim ACPI_INTERFACE_INFO *PreviousInterface; 255210944Sjkim ACPI_INTERFACE_INFO *NextInterface; 256210944Sjkim 257210944Sjkim 258210944Sjkim PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces; 259210944Sjkim while (NextInterface) 260210944Sjkim { 261210944Sjkim if (!ACPI_STRCMP (InterfaceName, NextInterface->Name)) 262210944Sjkim { 263210944Sjkim /* Found: name is in either the static list or was added at runtime */ 264210944Sjkim 265210944Sjkim if (NextInterface->Flags & ACPI_OSI_DYNAMIC) 266210944Sjkim { 267210944Sjkim /* Interface was added dynamically, remove and free it */ 268210944Sjkim 269210944Sjkim if (PreviousInterface == NextInterface) 270210944Sjkim { 271210944Sjkim AcpiGbl_SupportedInterfaces = NextInterface->Next; 272210944Sjkim } 273210944Sjkim else 274210944Sjkim { 275210944Sjkim PreviousInterface->Next = NextInterface->Next; 276210944Sjkim } 277210944Sjkim 278210944Sjkim ACPI_FREE (NextInterface->Name); 279210944Sjkim ACPI_FREE (NextInterface); 280210944Sjkim } 281210944Sjkim else 282210944Sjkim { 283210944Sjkim /* 284210944Sjkim * Interface is in static list. If marked invalid, then it 285210944Sjkim * does not actually exist. Else, mark it invalid. 286210944Sjkim */ 287210944Sjkim if (NextInterface->Flags & ACPI_OSI_INVALID) 288210944Sjkim { 289210944Sjkim return (AE_NOT_EXIST); 290210944Sjkim } 291210944Sjkim 292210944Sjkim NextInterface->Flags |= ACPI_OSI_INVALID; 293210944Sjkim } 294210944Sjkim 295210944Sjkim return (AE_OK); 296210944Sjkim } 297210944Sjkim 298210944Sjkim PreviousInterface = NextInterface; 299210944Sjkim NextInterface = NextInterface->Next; 300210944Sjkim } 301210944Sjkim 302210944Sjkim /* Interface was not found */ 303210944Sjkim 304210944Sjkim return (AE_NOT_EXIST); 305210944Sjkim} 306210944Sjkim 307210944Sjkim 308210944Sjkim/******************************************************************************* 309210944Sjkim * 310210944Sjkim * FUNCTION: AcpiUtGetInterface 311210944Sjkim * 312210944Sjkim * PARAMETERS: InterfaceName - The interface to find 313210944Sjkim * 314210944Sjkim * RETURN: ACPI_INTERFACE_INFO if found. NULL if not found. 315210944Sjkim * 316210944Sjkim * DESCRIPTION: Search for the specified interface name in the global list. 317210944Sjkim * Caller MUST hold AcpiGbl_OsiMutex 318210944Sjkim * 319210944Sjkim ******************************************************************************/ 320210944Sjkim 321210944SjkimACPI_INTERFACE_INFO * 322210944SjkimAcpiUtGetInterface ( 323210944Sjkim ACPI_STRING InterfaceName) 324210944Sjkim{ 325210944Sjkim ACPI_INTERFACE_INFO *NextInterface; 326210944Sjkim 327210944Sjkim 328210944Sjkim NextInterface = AcpiGbl_SupportedInterfaces; 329210944Sjkim while (NextInterface) 330210944Sjkim { 331210944Sjkim if (!ACPI_STRCMP (InterfaceName, NextInterface->Name)) 332210944Sjkim { 333210944Sjkim return (NextInterface); 334210944Sjkim } 335210944Sjkim 336210944Sjkim NextInterface = NextInterface->Next; 337210944Sjkim } 338210944Sjkim 339210944Sjkim return (NULL); 340210944Sjkim} 341210944Sjkim 342210944Sjkim 343210944Sjkim/******************************************************************************* 344210944Sjkim * 345210944Sjkim * FUNCTION: AcpiUtOsiImplementation 346210944Sjkim * 347210944Sjkim * PARAMETERS: WalkState - Current walk state 348210944Sjkim * 349210944Sjkim * RETURN: Status 350210944Sjkim * 351210944Sjkim * DESCRIPTION: Implementation of the _OSI predefined control method. When 352210944Sjkim * an invocation of _OSI is encountered in the system AML, 353210944Sjkim * control is transferred to this function. 354210944Sjkim * 355210944Sjkim ******************************************************************************/ 356210944Sjkim 357210944SjkimACPI_STATUS 358210944SjkimAcpiUtOsiImplementation ( 359210944Sjkim ACPI_WALK_STATE *WalkState) 360210944Sjkim{ 361210944Sjkim ACPI_OPERAND_OBJECT *StringDesc; 362210944Sjkim ACPI_OPERAND_OBJECT *ReturnDesc; 363210944Sjkim ACPI_INTERFACE_INFO *InterfaceInfo; 364210944Sjkim ACPI_INTERFACE_HANDLER InterfaceHandler; 365249112Sjkim ACPI_STATUS Status; 366210944Sjkim UINT32 ReturnValue; 367210944Sjkim 368210944Sjkim 369210944Sjkim ACPI_FUNCTION_TRACE (UtOsiImplementation); 370210944Sjkim 371210944Sjkim 372210944Sjkim /* Validate the string input argument (from the AML caller) */ 373210944Sjkim 374210944Sjkim StringDesc = WalkState->Arguments[0].Object; 375210944Sjkim if (!StringDesc || 376210944Sjkim (StringDesc->Common.Type != ACPI_TYPE_STRING)) 377210944Sjkim { 378210944Sjkim return_ACPI_STATUS (AE_TYPE); 379210944Sjkim } 380210944Sjkim 381210944Sjkim /* Create a return object */ 382210944Sjkim 383210944Sjkim ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 384210944Sjkim if (!ReturnDesc) 385210944Sjkim { 386210944Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 387210944Sjkim } 388210944Sjkim 389210944Sjkim /* Default return value is 0, NOT SUPPORTED */ 390210944Sjkim 391210944Sjkim ReturnValue = 0; 392249112Sjkim Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 393249112Sjkim if (ACPI_FAILURE (Status)) 394249112Sjkim { 395249663Sjkim AcpiUtRemoveReference (ReturnDesc); 396249112Sjkim return_ACPI_STATUS (Status); 397249112Sjkim } 398210944Sjkim 399210944Sjkim /* Lookup the interface in the global _OSI list */ 400210944Sjkim 401210944Sjkim InterfaceInfo = AcpiUtGetInterface (StringDesc->String.Pointer); 402210944Sjkim if (InterfaceInfo && 403210944Sjkim !(InterfaceInfo->Flags & ACPI_OSI_INVALID)) 404210944Sjkim { 405210944Sjkim /* 406210944Sjkim * The interface is supported. 407210944Sjkim * Update the OsiData if necessary. We keep track of the latest 408210944Sjkim * version of Windows that has been requested by the BIOS. 409210944Sjkim */ 410210944Sjkim if (InterfaceInfo->Value > AcpiGbl_OsiData) 411210944Sjkim { 412210944Sjkim AcpiGbl_OsiData = InterfaceInfo->Value; 413210944Sjkim } 414210944Sjkim 415210944Sjkim ReturnValue = ACPI_UINT32_MAX; 416210944Sjkim } 417210944Sjkim 418210944Sjkim AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 419210944Sjkim 420210944Sjkim /* 421210944Sjkim * Invoke an optional _OSI interface handler. The host OS may wish 422210944Sjkim * to do some interface-specific handling. For example, warn about 423210944Sjkim * certain interfaces or override the true/false support value. 424210944Sjkim */ 425210944Sjkim InterfaceHandler = AcpiGbl_InterfaceHandler; 426210944Sjkim if (InterfaceHandler) 427210944Sjkim { 428210944Sjkim ReturnValue = InterfaceHandler ( 429210944Sjkim StringDesc->String.Pointer, ReturnValue); 430210944Sjkim } 431210944Sjkim 432210944Sjkim ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, 433210944Sjkim "ACPI: BIOS _OSI(\"%s\") is %ssupported\n", 434210944Sjkim StringDesc->String.Pointer, ReturnValue == 0 ? "not " : "")); 435210944Sjkim 436210944Sjkim /* Complete the return object */ 437210944Sjkim 438210944Sjkim ReturnDesc->Integer.Value = ReturnValue; 439210944Sjkim WalkState->ReturnDesc = ReturnDesc; 440210944Sjkim return_ACPI_STATUS (AE_OK); 441210944Sjkim} 442