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