1 /******************************************************************************
3 * Module Name: utosi - Support for the _OSI predefined control method
5 *****************************************************************************/
8 * Copyright (C) 2000 - 2011, Intel Corp.
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
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.
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.
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.
46 #include <contrib/dev/acpica/include/acpi.h>
47 #include <contrib/dev/acpica/include/accommon.h>
50 #define _COMPONENT ACPI_UTILITIES
51 ACPI_MODULE_NAME ("utosi")
54 * Strings supported by the _OSI predefined control method (which is
55 * implemented internally within this module.)
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.
62 * The last element of each entry is used to track the newest version of
63 * Windows that the BIOS has requested.
65 static ACPI_INTERFACE_INFO AcpiDefaultSupportedInterfaces[] =
67 /* Operating System Vendor Strings */
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 */
81 /* Feature Group Strings */
83 {"Extended Address Space Descriptor", NULL, 0, 0}
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.
90 * Examples of optional feature group strings:
95 * "3.0 _SCP Extensions"
96 * "Processor Aggregator Device"
101 /*******************************************************************************
103 * FUNCTION: AcpiUtInitializeInterfaces
109 * DESCRIPTION: Initialize the global _OSI supported interfaces list
111 ******************************************************************************/
114 AcpiUtInitializeInterfaces (
120 (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
121 AcpiGbl_SupportedInterfaces = AcpiDefaultSupportedInterfaces;
123 /* Link the static list of supported interfaces */
125 for (i = 0; i < (ACPI_ARRAY_LENGTH (AcpiDefaultSupportedInterfaces) - 1); i++)
127 AcpiDefaultSupportedInterfaces[i].Next =
128 &AcpiDefaultSupportedInterfaces[(ACPI_SIZE) i + 1];
131 AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
136 /*******************************************************************************
138 * FUNCTION: AcpiUtInterfaceTerminate
144 * DESCRIPTION: Delete all interfaces in the global list. Sets
145 * AcpiGbl_SupportedInterfaces to NULL.
147 ******************************************************************************/
150 AcpiUtInterfaceTerminate (
153 ACPI_INTERFACE_INFO *NextInterface;
156 (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
157 NextInterface = AcpiGbl_SupportedInterfaces;
159 while (NextInterface)
161 AcpiGbl_SupportedInterfaces = NextInterface->Next;
163 /* Only interfaces added at runtime can be freed */
165 if (NextInterface->Flags & ACPI_OSI_DYNAMIC)
167 ACPI_FREE (NextInterface->Name);
168 ACPI_FREE (NextInterface);
171 NextInterface = AcpiGbl_SupportedInterfaces;
174 AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
178 /*******************************************************************************
180 * FUNCTION: AcpiUtInstallInterface
182 * PARAMETERS: InterfaceName - The interface to install
186 * DESCRIPTION: Install the interface into the global interface list.
187 * Caller MUST hold AcpiGbl_OsiMutex
189 ******************************************************************************/
192 AcpiUtInstallInterface (
193 ACPI_STRING InterfaceName)
195 ACPI_INTERFACE_INFO *InterfaceInfo;
198 /* Allocate info block and space for the name string */
200 InterfaceInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_INTERFACE_INFO));
203 return (AE_NO_MEMORY);
206 InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (InterfaceName) + 1);
207 if (!InterfaceInfo->Name)
209 ACPI_FREE (InterfaceInfo);
210 return (AE_NO_MEMORY);
213 /* Initialize new info and insert at the head of the global list */
215 ACPI_STRCPY (InterfaceInfo->Name, InterfaceName);
216 InterfaceInfo->Flags = ACPI_OSI_DYNAMIC;
217 InterfaceInfo->Next = AcpiGbl_SupportedInterfaces;
219 AcpiGbl_SupportedInterfaces = InterfaceInfo;
224 /*******************************************************************************
226 * FUNCTION: AcpiUtRemoveInterface
228 * PARAMETERS: InterfaceName - The interface to remove
232 * DESCRIPTION: Remove the interface from the global interface list.
233 * Caller MUST hold AcpiGbl_OsiMutex
235 ******************************************************************************/
238 AcpiUtRemoveInterface (
239 ACPI_STRING InterfaceName)
241 ACPI_INTERFACE_INFO *PreviousInterface;
242 ACPI_INTERFACE_INFO *NextInterface;
245 PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces;
246 while (NextInterface)
248 if (!ACPI_STRCMP (InterfaceName, NextInterface->Name))
250 /* Found: name is in either the static list or was added at runtime */
252 if (NextInterface->Flags & ACPI_OSI_DYNAMIC)
254 /* Interface was added dynamically, remove and free it */
256 if (PreviousInterface == NextInterface)
258 AcpiGbl_SupportedInterfaces = NextInterface->Next;
262 PreviousInterface->Next = NextInterface->Next;
265 ACPI_FREE (NextInterface->Name);
266 ACPI_FREE (NextInterface);
271 * Interface is in static list. If marked invalid, then it
272 * does not actually exist. Else, mark it invalid.
274 if (NextInterface->Flags & ACPI_OSI_INVALID)
276 return (AE_NOT_EXIST);
279 NextInterface->Flags |= ACPI_OSI_INVALID;
285 PreviousInterface = NextInterface;
286 NextInterface = NextInterface->Next;
289 /* Interface was not found */
291 return (AE_NOT_EXIST);
295 /*******************************************************************************
297 * FUNCTION: AcpiUtGetInterface
299 * PARAMETERS: InterfaceName - The interface to find
301 * RETURN: ACPI_INTERFACE_INFO if found. NULL if not found.
303 * DESCRIPTION: Search for the specified interface name in the global list.
304 * Caller MUST hold AcpiGbl_OsiMutex
306 ******************************************************************************/
308 ACPI_INTERFACE_INFO *
310 ACPI_STRING InterfaceName)
312 ACPI_INTERFACE_INFO *NextInterface;
315 NextInterface = AcpiGbl_SupportedInterfaces;
316 while (NextInterface)
318 if (!ACPI_STRCMP (InterfaceName, NextInterface->Name))
320 return (NextInterface);
323 NextInterface = NextInterface->Next;
330 /*******************************************************************************
332 * FUNCTION: AcpiUtOsiImplementation
334 * PARAMETERS: WalkState - Current walk state
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.
342 ******************************************************************************/
345 AcpiUtOsiImplementation (
346 ACPI_WALK_STATE *WalkState)
348 ACPI_OPERAND_OBJECT *StringDesc;
349 ACPI_OPERAND_OBJECT *ReturnDesc;
350 ACPI_INTERFACE_INFO *InterfaceInfo;
351 ACPI_INTERFACE_HANDLER InterfaceHandler;
355 ACPI_FUNCTION_TRACE (UtOsiImplementation);
358 /* Validate the string input argument (from the AML caller) */
360 StringDesc = WalkState->Arguments[0].Object;
362 (StringDesc->Common.Type != ACPI_TYPE_STRING))
364 return_ACPI_STATUS (AE_TYPE);
367 /* Create a return object */
369 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
372 return_ACPI_STATUS (AE_NO_MEMORY);
375 /* Default return value is 0, NOT SUPPORTED */
378 (void) AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
380 /* Lookup the interface in the global _OSI list */
382 InterfaceInfo = AcpiUtGetInterface (StringDesc->String.Pointer);
384 !(InterfaceInfo->Flags & ACPI_OSI_INVALID))
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.
391 if (InterfaceInfo->Value > AcpiGbl_OsiData)
393 AcpiGbl_OsiData = InterfaceInfo->Value;
396 ReturnValue = ACPI_UINT32_MAX;
399 AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
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.
406 InterfaceHandler = AcpiGbl_InterfaceHandler;
407 if (InterfaceHandler)
409 ReturnValue = InterfaceHandler (
410 StringDesc->String.Pointer, ReturnValue);
413 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
414 "ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
415 StringDesc->String.Pointer, ReturnValue == 0 ? "not " : ""));
417 /* Complete the return object */
419 ReturnDesc->Integer.Value = ReturnValue;
420 WalkState->ReturnDesc = ReturnDesc;
421 return_ACPI_STATUS (AE_OK);