1 /****************************************************************************** 2 * 3 * Module Name: utosi - Support for the _OSI predefined control method 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2016, 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 "acpi.h" 45 #include "accommon.h" 46 47 48 #define _COMPONENT ACPI_UTILITIES 49 ACPI_MODULE_NAME ("utosi") 50 51 52 /****************************************************************************** 53 * 54 * ACPICA policy for new _OSI strings: 55 * 56 * It is the stated policy of ACPICA that new _OSI strings will be integrated 57 * into this module as soon as possible after they are defined. It is strongly 58 * recommended that all ACPICA hosts mirror this policy and integrate any 59 * changes to this module as soon as possible. There are several historical 60 * reasons behind this policy: 61 * 62 * 1) New BIOSs tend to test only the case where the host responds TRUE to 63 * the latest version of Windows, which would respond to the latest/newest 64 * _OSI string. Not responding TRUE to the latest version of Windows will 65 * risk executing untested code paths throughout the DSDT and SSDTs. 66 * 67 * 2) If a new _OSI string is recognized only after a significant delay, this 68 * has the potential to cause problems on existing working machines because 69 * of the possibility that a new and different path through the ASL code 70 * will be executed. 71 * 72 * 3) New _OSI strings are tending to come out about once per year. A delay 73 * in recognizing a new string for a significant amount of time risks the 74 * release of another string which only compounds the initial problem. 75 * 76 *****************************************************************************/ 77 78 79 /* 80 * Strings supported by the _OSI predefined control method (which is 81 * implemented internally within this module.) 82 * 83 * March 2009: Removed "Linux" as this host no longer wants to respond true 84 * for this string. Basically, the only safe OS strings are windows-related 85 * and in many or most cases represent the only test path within the 86 * BIOS-provided ASL code. 87 * 88 * The last element of each entry is used to track the newest version of 89 * Windows that the BIOS has requested. 90 */ 91 static ACPI_INTERFACE_INFO AcpiDefaultSupportedInterfaces[] = 92 { 93 /* Operating System Vendor Strings */ 94 95 {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */ 96 {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */ 97 {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ 98 {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ 99 {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ 100 {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ 101 {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ 102 {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ 103 {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ 104 {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ 105 {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ 106 /* 107 * XXX 108 * The following OSes are temporarily disabled. Windows introduced 109 * support for xhci (USB 3.0) in Windows 8. When we advertise Windows 8 110 * and newer support, some vendors use that as a key to automatically 111 * transition all USB ports to the xhci controller. Until we have 112 * support for the xhci controller, we should not advertise these 113 * operating systems. From a brief survey, there isn't too much other 114 * AML that this impacts at this time. 115 */ 116 /* {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8},*/ /* Windows 8 and Server 2012 - Added 08/2012 */ 117 /* {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8},*/ /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */ 118 /* {"Windows 2015", NULL, 0, ACPI_OSI_WIN_10},*/ /* Windows 10 - Added 03/2015 */ 119 120 /* Feature Group Strings */ 121 122 {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0}, 123 124 /* 125 * All "optional" feature group strings (features that are implemented 126 * by the host) should be dynamically modified to VALID by the host via 127 * AcpiInstallInterface or AcpiUpdateInterfaces. Such optional feature 128 * group strings are set as INVALID by default here. 129 */ 130 131 {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 132 {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 133 {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 134 {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 135 {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0} 136 }; 137 138 139 /******************************************************************************* 140 * 141 * FUNCTION: AcpiUtInitializeInterfaces 142 * 143 * PARAMETERS: None 144 * 145 * RETURN: Status 146 * 147 * DESCRIPTION: Initialize the global _OSI supported interfaces list 148 * 149 ******************************************************************************/ 150 151 ACPI_STATUS 152 AcpiUtInitializeInterfaces ( 153 void) 154 { 155 ACPI_STATUS Status; 156 UINT32 i; 157 158 159 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 160 if (ACPI_FAILURE (Status)) 161 { 162 return (Status); 163 } 164 165 AcpiGbl_SupportedInterfaces = AcpiDefaultSupportedInterfaces; 166 167 /* Link the static list of supported interfaces */ 168 169 for (i = 0; 170 i < (ACPI_ARRAY_LENGTH (AcpiDefaultSupportedInterfaces) - 1); 171 i++) 172 { 173 AcpiDefaultSupportedInterfaces[i].Next = 174 &AcpiDefaultSupportedInterfaces[(ACPI_SIZE) i + 1]; 175 } 176 177 AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 178 return (AE_OK); 179 } 180 181 182 /******************************************************************************* 183 * 184 * FUNCTION: AcpiUtInterfaceTerminate 185 * 186 * PARAMETERS: None 187 * 188 * RETURN: Status 189 * 190 * DESCRIPTION: Delete all interfaces in the global list. Sets 191 * AcpiGbl_SupportedInterfaces to NULL. 192 * 193 ******************************************************************************/ 194 195 ACPI_STATUS 196 AcpiUtInterfaceTerminate ( 197 void) 198 { 199 ACPI_STATUS Status; 200 ACPI_INTERFACE_INFO *NextInterface; 201 202 203 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 204 if (ACPI_FAILURE (Status)) 205 { 206 return (Status); 207 } 208 209 NextInterface = AcpiGbl_SupportedInterfaces; 210 while (NextInterface) 211 { 212 AcpiGbl_SupportedInterfaces = NextInterface->Next; 213 214 if (NextInterface->Flags & ACPI_OSI_DYNAMIC) 215 { 216 /* Only interfaces added at runtime can be freed */ 217 218 ACPI_FREE (NextInterface->Name); 219 ACPI_FREE (NextInterface); 220 } 221 else 222 { 223 /* Interface is in static list. Reset it to invalid or valid. */ 224 225 if (NextInterface->Flags & ACPI_OSI_DEFAULT_INVALID) 226 { 227 NextInterface->Flags |= ACPI_OSI_INVALID; 228 } 229 else 230 { 231 NextInterface->Flags &= ~ACPI_OSI_INVALID; 232 } 233 } 234 235 NextInterface = AcpiGbl_SupportedInterfaces; 236 } 237 238 AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 239 return (AE_OK); 240 } 241 242 243 /******************************************************************************* 244 * 245 * FUNCTION: AcpiUtInstallInterface 246 * 247 * PARAMETERS: InterfaceName - The interface to install 248 * 249 * RETURN: Status 250 * 251 * DESCRIPTION: Install the interface into the global interface list. 252 * Caller MUST hold AcpiGbl_OsiMutex 253 * 254 ******************************************************************************/ 255 256 ACPI_STATUS 257 AcpiUtInstallInterface ( 258 ACPI_STRING InterfaceName) 259 { 260 ACPI_INTERFACE_INFO *InterfaceInfo; 261 262 263 /* Allocate info block and space for the name string */ 264 265 InterfaceInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_INTERFACE_INFO)); 266 if (!InterfaceInfo) 267 { 268 return (AE_NO_MEMORY); 269 } 270 271 InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (strlen (InterfaceName) + 1); 272 if (!InterfaceInfo->Name) 273 { 274 ACPI_FREE (InterfaceInfo); 275 return (AE_NO_MEMORY); 276 } 277 278 /* Initialize new info and insert at the head of the global list */ 279 280 strcpy (InterfaceInfo->Name, InterfaceName); 281 InterfaceInfo->Flags = ACPI_OSI_DYNAMIC; 282 InterfaceInfo->Next = AcpiGbl_SupportedInterfaces; 283 284 AcpiGbl_SupportedInterfaces = InterfaceInfo; 285 return (AE_OK); 286 } 287 288 289 /******************************************************************************* 290 * 291 * FUNCTION: AcpiUtRemoveInterface 292 * 293 * PARAMETERS: InterfaceName - The interface to remove 294 * 295 * RETURN: Status 296 * 297 * DESCRIPTION: Remove the interface from the global interface list. 298 * Caller MUST hold AcpiGbl_OsiMutex 299 * 300 ******************************************************************************/ 301 302 ACPI_STATUS 303 AcpiUtRemoveInterface ( 304 ACPI_STRING InterfaceName) 305 { 306 ACPI_INTERFACE_INFO *PreviousInterface; 307 ACPI_INTERFACE_INFO *NextInterface; 308 309 310 PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces; 311 while (NextInterface) 312 { 313 if (!strcmp (InterfaceName, NextInterface->Name)) 314 { 315 /* 316 * Found: name is in either the static list 317 * or was added at runtime 318 */ 319 if (NextInterface->Flags & ACPI_OSI_DYNAMIC) 320 { 321 /* Interface was added dynamically, remove and free it */ 322 323 if (PreviousInterface == NextInterface) 324 { 325 AcpiGbl_SupportedInterfaces = NextInterface->Next; 326 } 327 else 328 { 329 PreviousInterface->Next = NextInterface->Next; 330 } 331 332 ACPI_FREE (NextInterface->Name); 333 ACPI_FREE (NextInterface); 334 } 335 else 336 { 337 /* 338 * Interface is in static list. If marked invalid, then 339 * it does not actually exist. Else, mark it invalid. 340 */ 341 if (NextInterface->Flags & ACPI_OSI_INVALID) 342 { 343 return (AE_NOT_EXIST); 344 } 345 346 NextInterface->Flags |= ACPI_OSI_INVALID; 347 } 348 349 return (AE_OK); 350 } 351 352 PreviousInterface = NextInterface; 353 NextInterface = NextInterface->Next; 354 } 355 356 /* Interface was not found */ 357 358 return (AE_NOT_EXIST); 359 } 360 361 362 /******************************************************************************* 363 * 364 * FUNCTION: AcpiUtUpdateInterfaces 365 * 366 * PARAMETERS: Action - Actions to be performed during the 367 * update 368 * 369 * RETURN: Status 370 * 371 * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor 372 * strings or/and feature group strings. 373 * Caller MUST hold AcpiGbl_OsiMutex 374 * 375 ******************************************************************************/ 376 377 ACPI_STATUS 378 AcpiUtUpdateInterfaces ( 379 UINT8 Action) 380 { 381 ACPI_INTERFACE_INFO *NextInterface; 382 383 384 NextInterface = AcpiGbl_SupportedInterfaces; 385 while (NextInterface) 386 { 387 if (((NextInterface->Flags & ACPI_OSI_FEATURE) && 388 (Action & ACPI_FEATURE_STRINGS)) || 389 (!(NextInterface->Flags & ACPI_OSI_FEATURE) && 390 (Action & ACPI_VENDOR_STRINGS))) 391 { 392 if (Action & ACPI_DISABLE_INTERFACES) 393 { 394 /* Mark the interfaces as invalid */ 395 396 NextInterface->Flags |= ACPI_OSI_INVALID; 397 } 398 else 399 { 400 /* Mark the interfaces as valid */ 401 402 NextInterface->Flags &= ~ACPI_OSI_INVALID; 403 } 404 } 405 406 NextInterface = NextInterface->Next; 407 } 408 409 return (AE_OK); 410 } 411 412 413 /******************************************************************************* 414 * 415 * FUNCTION: AcpiUtGetInterface 416 * 417 * PARAMETERS: InterfaceName - The interface to find 418 * 419 * RETURN: ACPI_INTERFACE_INFO if found. NULL if not found. 420 * 421 * DESCRIPTION: Search for the specified interface name in the global list. 422 * Caller MUST hold AcpiGbl_OsiMutex 423 * 424 ******************************************************************************/ 425 426 ACPI_INTERFACE_INFO * 427 AcpiUtGetInterface ( 428 ACPI_STRING InterfaceName) 429 { 430 ACPI_INTERFACE_INFO *NextInterface; 431 432 433 NextInterface = AcpiGbl_SupportedInterfaces; 434 while (NextInterface) 435 { 436 if (!strcmp (InterfaceName, NextInterface->Name)) 437 { 438 return (NextInterface); 439 } 440 441 NextInterface = NextInterface->Next; 442 } 443 444 return (NULL); 445 } 446 447 448 /******************************************************************************* 449 * 450 * FUNCTION: AcpiUtOsiImplementation 451 * 452 * PARAMETERS: WalkState - Current walk state 453 * 454 * RETURN: Status 455 * 456 * DESCRIPTION: Implementation of the _OSI predefined control method. When 457 * an invocation of _OSI is encountered in the system AML, 458 * control is transferred to this function. 459 * 460 ******************************************************************************/ 461 462 ACPI_STATUS 463 AcpiUtOsiImplementation ( 464 ACPI_WALK_STATE *WalkState) 465 { 466 ACPI_OPERAND_OBJECT *StringDesc; 467 ACPI_OPERAND_OBJECT *ReturnDesc; 468 ACPI_INTERFACE_INFO *InterfaceInfo; 469 ACPI_INTERFACE_HANDLER InterfaceHandler; 470 ACPI_STATUS Status; 471 UINT32 ReturnValue; 472 473 474 ACPI_FUNCTION_TRACE (UtOsiImplementation); 475 476 477 /* Validate the string input argument (from the AML caller) */ 478 479 StringDesc = WalkState->Arguments[0].Object; 480 if (!StringDesc || 481 (StringDesc->Common.Type != ACPI_TYPE_STRING)) 482 { 483 return_ACPI_STATUS (AE_TYPE); 484 } 485 486 /* Create a return object */ 487 488 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 489 if (!ReturnDesc) 490 { 491 return_ACPI_STATUS (AE_NO_MEMORY); 492 } 493 494 /* Default return value is 0, NOT SUPPORTED */ 495 496 ReturnValue = 0; 497 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 498 if (ACPI_FAILURE (Status)) 499 { 500 AcpiUtRemoveReference (ReturnDesc); 501 return_ACPI_STATUS (Status); 502 } 503 504 /* Lookup the interface in the global _OSI list */ 505 506 InterfaceInfo = AcpiUtGetInterface (StringDesc->String.Pointer); 507 if (InterfaceInfo && 508 !(InterfaceInfo->Flags & ACPI_OSI_INVALID)) 509 { 510 /* 511 * The interface is supported. 512 * Update the OsiData if necessary. We keep track of the latest 513 * version of Windows that has been requested by the BIOS. 514 */ 515 if (InterfaceInfo->Value > AcpiGbl_OsiData) 516 { 517 AcpiGbl_OsiData = InterfaceInfo->Value; 518 } 519 520 ReturnValue = ACPI_UINT32_MAX; 521 } 522 523 AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 524 525 /* 526 * Invoke an optional _OSI interface handler. The host OS may wish 527 * to do some interface-specific handling. For example, warn about 528 * certain interfaces or override the true/false support value. 529 */ 530 InterfaceHandler = AcpiGbl_InterfaceHandler; 531 if (InterfaceHandler) 532 { 533 ReturnValue = InterfaceHandler ( 534 StringDesc->String.Pointer, ReturnValue); 535 } 536 537 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, 538 "ACPI: BIOS _OSI(\"%s\") is %ssupported\n", 539 StringDesc->String.Pointer, ReturnValue == 0 ? "not " : "")); 540 541 /* Complete the return object */ 542 543 ReturnDesc->Integer.Value = ReturnValue; 544 WalkState->ReturnDesc = ReturnDesc; 545 return_ACPI_STATUS (AE_OK); 546 } 547