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