1 /****************************************************************************** 2 * 3 * Module Name: utosi - Support for the _OSI predefined control method 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2022, 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 MERCHANTABILITY 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 {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */ 107 {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8_1}, /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */ 108 {"Windows 2015", NULL, 0, ACPI_OSI_WIN_10}, /* Windows 10 - Added 03/2015 */ 109 {"Windows 2016", NULL, 0, ACPI_OSI_WIN_10_RS1}, /* Windows 10 version 1607 - Added 12/2017 */ 110 {"Windows 2017", NULL, 0, ACPI_OSI_WIN_10_RS2}, /* Windows 10 version 1703 - Added 12/2017 */ 111 {"Windows 2017.2", NULL, 0, ACPI_OSI_WIN_10_RS3}, /* Windows 10 version 1709 - Added 02/2018 */ 112 {"Windows 2018", NULL, 0, ACPI_OSI_WIN_10_RS4}, /* Windows 10 version 1803 - Added 11/2018 */ 113 {"Windows 2018.2", NULL, 0, ACPI_OSI_WIN_10_RS5}, /* Windows 10 version 1809 - Added 11/2018 */ 114 {"Windows 2019", NULL, 0, ACPI_OSI_WIN_10_19H1}, /* Windows 10 version 1903 - Added 08/2019 */ 115 {"Windows 2020", NULL, 0, ACPI_OSI_WIN_10_20H1}, /* Windows 10 version 2004 - Added 08/2021 */ 116 {"Windows 2021", NULL, 0, ACPI_OSI_WIN_11}, /* Windows 11 - Added 01/2022 */ 117 118 /* Feature Group Strings */ 119 120 {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0}, 121 122 /* 123 * All "optional" feature group strings (features that are implemented 124 * by the host) should be dynamically modified to VALID by the host via 125 * AcpiInstallInterface or AcpiUpdateInterfaces. Such optional feature 126 * group strings are set as INVALID by default here. 127 */ 128 129 {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 130 {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 131 {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 132 {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 133 {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0} 134 }; 135 136 137 /******************************************************************************* 138 * 139 * FUNCTION: AcpiUtInitializeInterfaces 140 * 141 * PARAMETERS: None 142 * 143 * RETURN: Status 144 * 145 * DESCRIPTION: Initialize the global _OSI supported interfaces list 146 * 147 ******************************************************************************/ 148 149 ACPI_STATUS 150 AcpiUtInitializeInterfaces ( 151 void) 152 { 153 ACPI_STATUS Status; 154 UINT32 i; 155 156 157 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 158 if (ACPI_FAILURE (Status)) 159 { 160 return (Status); 161 } 162 163 AcpiGbl_SupportedInterfaces = AcpiDefaultSupportedInterfaces; 164 165 /* Link the static list of supported interfaces */ 166 167 for (i = 0; 168 i < (ACPI_ARRAY_LENGTH (AcpiDefaultSupportedInterfaces) - 1); 169 i++) 170 { 171 AcpiDefaultSupportedInterfaces[i].Next = 172 &AcpiDefaultSupportedInterfaces[(ACPI_SIZE) i + 1]; 173 } 174 175 AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 176 return (AE_OK); 177 } 178 179 180 /******************************************************************************* 181 * 182 * FUNCTION: AcpiUtInterfaceTerminate 183 * 184 * PARAMETERS: None 185 * 186 * RETURN: Status 187 * 188 * DESCRIPTION: Delete all interfaces in the global list. Sets 189 * AcpiGbl_SupportedInterfaces to NULL. 190 * 191 ******************************************************************************/ 192 193 ACPI_STATUS 194 AcpiUtInterfaceTerminate ( 195 void) 196 { 197 ACPI_STATUS Status; 198 ACPI_INTERFACE_INFO *NextInterface; 199 200 201 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 202 if (ACPI_FAILURE (Status)) 203 { 204 return (Status); 205 } 206 207 NextInterface = AcpiGbl_SupportedInterfaces; 208 while (NextInterface) 209 { 210 AcpiGbl_SupportedInterfaces = NextInterface->Next; 211 212 if (NextInterface->Flags & ACPI_OSI_DYNAMIC) 213 { 214 /* Only interfaces added at runtime can be freed */ 215 216 ACPI_FREE (NextInterface->Name); 217 ACPI_FREE (NextInterface); 218 } 219 else 220 { 221 /* Interface is in static list. Reset it to invalid or valid. */ 222 223 if (NextInterface->Flags & ACPI_OSI_DEFAULT_INVALID) 224 { 225 NextInterface->Flags |= ACPI_OSI_INVALID; 226 } 227 else 228 { 229 NextInterface->Flags &= ~ACPI_OSI_INVALID; 230 } 231 } 232 233 NextInterface = AcpiGbl_SupportedInterfaces; 234 } 235 236 AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 237 return (AE_OK); 238 } 239 240 241 /******************************************************************************* 242 * 243 * FUNCTION: AcpiUtInstallInterface 244 * 245 * PARAMETERS: InterfaceName - The interface to install 246 * 247 * RETURN: Status 248 * 249 * DESCRIPTION: Install the interface into the global interface list. 250 * Caller MUST hold AcpiGbl_OsiMutex 251 * 252 ******************************************************************************/ 253 254 ACPI_STATUS 255 AcpiUtInstallInterface ( 256 ACPI_STRING InterfaceName) 257 { 258 ACPI_INTERFACE_INFO *InterfaceInfo; 259 260 261 /* Allocate info block and space for the name string */ 262 263 InterfaceInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_INTERFACE_INFO)); 264 if (!InterfaceInfo) 265 { 266 return (AE_NO_MEMORY); 267 } 268 269 InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (strlen (InterfaceName) + 1); 270 if (!InterfaceInfo->Name) 271 { 272 ACPI_FREE (InterfaceInfo); 273 return (AE_NO_MEMORY); 274 } 275 276 /* Initialize new info and insert at the head of the global list */ 277 278 strcpy (InterfaceInfo->Name, InterfaceName); 279 InterfaceInfo->Flags = ACPI_OSI_DYNAMIC; 280 InterfaceInfo->Next = AcpiGbl_SupportedInterfaces; 281 282 AcpiGbl_SupportedInterfaces = InterfaceInfo; 283 return (AE_OK); 284 } 285 286 287 /******************************************************************************* 288 * 289 * FUNCTION: AcpiUtRemoveInterface 290 * 291 * PARAMETERS: InterfaceName - The interface to remove 292 * 293 * RETURN: Status 294 * 295 * DESCRIPTION: Remove the interface from the global interface list. 296 * Caller MUST hold AcpiGbl_OsiMutex 297 * 298 ******************************************************************************/ 299 300 ACPI_STATUS 301 AcpiUtRemoveInterface ( 302 ACPI_STRING InterfaceName) 303 { 304 ACPI_INTERFACE_INFO *PreviousInterface; 305 ACPI_INTERFACE_INFO *NextInterface; 306 307 308 PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces; 309 while (NextInterface) 310 { 311 if (!strcmp (InterfaceName, NextInterface->Name)) 312 { 313 /* 314 * Found: name is in either the static list 315 * or was added at runtime 316 */ 317 if (NextInterface->Flags & ACPI_OSI_DYNAMIC) 318 { 319 /* Interface was added dynamically, remove and free it */ 320 321 if (PreviousInterface == NextInterface) 322 { 323 AcpiGbl_SupportedInterfaces = NextInterface->Next; 324 } 325 else 326 { 327 PreviousInterface->Next = NextInterface->Next; 328 } 329 330 ACPI_FREE (NextInterface->Name); 331 ACPI_FREE (NextInterface); 332 } 333 else 334 { 335 /* 336 * Interface is in static list. If marked invalid, then 337 * it does not actually exist. Else, mark it invalid. 338 */ 339 if (NextInterface->Flags & ACPI_OSI_INVALID) 340 { 341 return (AE_NOT_EXIST); 342 } 343 344 NextInterface->Flags |= ACPI_OSI_INVALID; 345 } 346 347 return (AE_OK); 348 } 349 350 PreviousInterface = NextInterface; 351 NextInterface = NextInterface->Next; 352 } 353 354 /* Interface was not found */ 355 356 return (AE_NOT_EXIST); 357 } 358 359 360 /******************************************************************************* 361 * 362 * FUNCTION: AcpiUtUpdateInterfaces 363 * 364 * PARAMETERS: Action - Actions to be performed during the 365 * update 366 * 367 * RETURN: Status 368 * 369 * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor 370 * strings or/and feature group strings. 371 * Caller MUST hold AcpiGbl_OsiMutex 372 * 373 ******************************************************************************/ 374 375 ACPI_STATUS 376 AcpiUtUpdateInterfaces ( 377 UINT8 Action) 378 { 379 ACPI_INTERFACE_INFO *NextInterface; 380 381 382 NextInterface = AcpiGbl_SupportedInterfaces; 383 while (NextInterface) 384 { 385 if (((NextInterface->Flags & ACPI_OSI_FEATURE) && 386 (Action & ACPI_FEATURE_STRINGS)) || 387 (!(NextInterface->Flags & ACPI_OSI_FEATURE) && 388 (Action & ACPI_VENDOR_STRINGS))) 389 { 390 if (Action & ACPI_DISABLE_INTERFACES) 391 { 392 /* Mark the interfaces as invalid */ 393 394 NextInterface->Flags |= ACPI_OSI_INVALID; 395 } 396 else 397 { 398 /* Mark the interfaces as valid */ 399 400 NextInterface->Flags &= ~ACPI_OSI_INVALID; 401 } 402 } 403 404 NextInterface = NextInterface->Next; 405 } 406 407 return (AE_OK); 408 } 409 410 411 /******************************************************************************* 412 * 413 * FUNCTION: AcpiUtGetInterface 414 * 415 * PARAMETERS: InterfaceName - The interface to find 416 * 417 * RETURN: ACPI_INTERFACE_INFO if found. NULL if not found. 418 * 419 * DESCRIPTION: Search for the specified interface name in the global list. 420 * Caller MUST hold AcpiGbl_OsiMutex 421 * 422 ******************************************************************************/ 423 424 ACPI_INTERFACE_INFO * 425 AcpiUtGetInterface ( 426 ACPI_STRING InterfaceName) 427 { 428 ACPI_INTERFACE_INFO *NextInterface; 429 430 431 NextInterface = AcpiGbl_SupportedInterfaces; 432 while (NextInterface) 433 { 434 if (!strcmp (InterfaceName, NextInterface->Name)) 435 { 436 return (NextInterface); 437 } 438 439 NextInterface = NextInterface->Next; 440 } 441 442 return (NULL); 443 } 444 445 446 /******************************************************************************* 447 * 448 * FUNCTION: AcpiUtOsiImplementation 449 * 450 * PARAMETERS: WalkState - Current walk state 451 * 452 * RETURN: Status 453 * Integer: TRUE (0) if input string is matched 454 * FALSE (-1) if string is not matched 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 * (August 2016) 461 * Note: _OSI is now defined to return "Ones" to indicate a match, for 462 * compatibility with other ACPI implementations. On a 32-bit DSDT, Ones 463 * is 0xFFFFFFFF. On a 64-bit DSDT, Ones is 0xFFFFFFFFFFFFFFFF 464 * (ACPI_UINT64_MAX). 465 * 466 * This function always returns ACPI_UINT64_MAX for TRUE, and later code 467 * will truncate this to 32 bits if necessary. 468 * 469 ******************************************************************************/ 470 471 ACPI_STATUS 472 AcpiUtOsiImplementation ( 473 ACPI_WALK_STATE *WalkState) 474 { 475 ACPI_OPERAND_OBJECT *StringDesc; 476 ACPI_OPERAND_OBJECT *ReturnDesc; 477 ACPI_INTERFACE_INFO *InterfaceInfo; 478 ACPI_INTERFACE_HANDLER InterfaceHandler; 479 ACPI_STATUS Status; 480 UINT64 ReturnValue; 481 482 483 ACPI_FUNCTION_TRACE (UtOsiImplementation); 484 485 486 /* Validate the string input argument (from the AML caller) */ 487 488 StringDesc = WalkState->Arguments[0].Object; 489 if (!StringDesc || 490 (StringDesc->Common.Type != ACPI_TYPE_STRING)) 491 { 492 return_ACPI_STATUS (AE_TYPE); 493 } 494 495 /* Create a return object */ 496 497 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER); 498 if (!ReturnDesc) 499 { 500 return_ACPI_STATUS (AE_NO_MEMORY); 501 } 502 503 /* Default return value is 0, NOT SUPPORTED */ 504 505 ReturnValue = 0; 506 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER); 507 if (ACPI_FAILURE (Status)) 508 { 509 AcpiUtRemoveReference (ReturnDesc); 510 return_ACPI_STATUS (Status); 511 } 512 513 /* Lookup the interface in the global _OSI list */ 514 515 InterfaceInfo = AcpiUtGetInterface (StringDesc->String.Pointer); 516 if (InterfaceInfo && 517 !(InterfaceInfo->Flags & ACPI_OSI_INVALID)) 518 { 519 /* 520 * The interface is supported. 521 * Update the OsiData if necessary. We keep track of the latest 522 * version of Windows that has been requested by the BIOS. 523 */ 524 if (InterfaceInfo->Value > AcpiGbl_OsiData) 525 { 526 AcpiGbl_OsiData = InterfaceInfo->Value; 527 } 528 529 ReturnValue = ACPI_UINT64_MAX; 530 } 531 532 AcpiOsReleaseMutex (AcpiGbl_OsiMutex); 533 534 /* 535 * Invoke an optional _OSI interface handler. The host OS may wish 536 * to do some interface-specific handling. For example, warn about 537 * certain interfaces or override the true/false support value. 538 */ 539 InterfaceHandler = AcpiGbl_InterfaceHandler; 540 if (InterfaceHandler) 541 { 542 if (InterfaceHandler ( 543 StringDesc->String.Pointer, (UINT32) ReturnValue)) 544 { 545 ReturnValue = ACPI_UINT64_MAX; 546 } 547 } 548 549 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO, 550 "ACPI: BIOS _OSI(\"%s\") is %ssupported\n", 551 StringDesc->String.Pointer, ReturnValue == 0 ? "not " : "")); 552 553 /* Complete the return object */ 554 555 ReturnDesc->Integer.Value = ReturnValue; 556 WalkState->ReturnDesc = ReturnDesc; 557 return_ACPI_STATUS (AE_OK); 558 } 559