162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/****************************************************************************** 362306a36Sopenharmony_ci * 462306a36Sopenharmony_ci * Module Name: utosi - Support for the _OSI predefined control method 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp. 762306a36Sopenharmony_ci * 862306a36Sopenharmony_ci *****************************************************************************/ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci#include <acpi/acpi.h> 1162306a36Sopenharmony_ci#include "accommon.h" 1262306a36Sopenharmony_ci 1362306a36Sopenharmony_ci#define _COMPONENT ACPI_UTILITIES 1462306a36Sopenharmony_ciACPI_MODULE_NAME("utosi") 1562306a36Sopenharmony_ci 1662306a36Sopenharmony_ci/****************************************************************************** 1762306a36Sopenharmony_ci * 1862306a36Sopenharmony_ci * ACPICA policy for new _OSI strings: 1962306a36Sopenharmony_ci * 2062306a36Sopenharmony_ci * It is the stated policy of ACPICA that new _OSI strings will be integrated 2162306a36Sopenharmony_ci * into this module as soon as possible after they are defined. It is strongly 2262306a36Sopenharmony_ci * recommended that all ACPICA hosts mirror this policy and integrate any 2362306a36Sopenharmony_ci * changes to this module as soon as possible. There are several historical 2462306a36Sopenharmony_ci * reasons behind this policy: 2562306a36Sopenharmony_ci * 2662306a36Sopenharmony_ci * 1) New BIOSs tend to test only the case where the host responds TRUE to 2762306a36Sopenharmony_ci * the latest version of Windows, which would respond to the latest/newest 2862306a36Sopenharmony_ci * _OSI string. Not responding TRUE to the latest version of Windows will 2962306a36Sopenharmony_ci * risk executing untested code paths throughout the DSDT and SSDTs. 3062306a36Sopenharmony_ci * 3162306a36Sopenharmony_ci * 2) If a new _OSI string is recognized only after a significant delay, this 3262306a36Sopenharmony_ci * has the potential to cause problems on existing working machines because 3362306a36Sopenharmony_ci * of the possibility that a new and different path through the ASL code 3462306a36Sopenharmony_ci * will be executed. 3562306a36Sopenharmony_ci * 3662306a36Sopenharmony_ci * 3) New _OSI strings are tending to come out about once per year. A delay 3762306a36Sopenharmony_ci * in recognizing a new string for a significant amount of time risks the 3862306a36Sopenharmony_ci * release of another string which only compounds the initial problem. 3962306a36Sopenharmony_ci * 4062306a36Sopenharmony_ci *****************************************************************************/ 4162306a36Sopenharmony_ci/* 4262306a36Sopenharmony_ci * Strings supported by the _OSI predefined control method (which is 4362306a36Sopenharmony_ci * implemented internally within this module.) 4462306a36Sopenharmony_ci * 4562306a36Sopenharmony_ci * March 2009: Removed "Linux" as this host no longer wants to respond true 4662306a36Sopenharmony_ci * for this string. Basically, the only safe OS strings are windows-related 4762306a36Sopenharmony_ci * and in many or most cases represent the only test path within the 4862306a36Sopenharmony_ci * BIOS-provided ASL code. 4962306a36Sopenharmony_ci * 5062306a36Sopenharmony_ci * The last element of each entry is used to track the newest version of 5162306a36Sopenharmony_ci * Windows that the BIOS has requested. 5262306a36Sopenharmony_ci */ 5362306a36Sopenharmony_cistatic struct acpi_interface_info acpi_default_supported_interfaces[] = { 5462306a36Sopenharmony_ci /* Operating System Vendor Strings */ 5562306a36Sopenharmony_ci 5662306a36Sopenharmony_ci {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */ 5762306a36Sopenharmony_ci {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */ 5862306a36Sopenharmony_ci {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ 5962306a36Sopenharmony_ci {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ 6062306a36Sopenharmony_ci {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ 6162306a36Sopenharmony_ci {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ 6262306a36Sopenharmony_ci {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows vista - Added 03/2006 */ 6362306a36Sopenharmony_ci {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */ 6462306a36Sopenharmony_ci {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */ 6562306a36Sopenharmony_ci {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */ 6662306a36Sopenharmony_ci {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */ 6762306a36Sopenharmony_ci {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */ 6862306a36Sopenharmony_ci {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8_1}, /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */ 6962306a36Sopenharmony_ci {"Windows 2015", NULL, 0, ACPI_OSI_WIN_10}, /* Windows 10 - Added 03/2015 */ 7062306a36Sopenharmony_ci {"Windows 2016", NULL, 0, ACPI_OSI_WIN_10_RS1}, /* Windows 10 version 1607 - Added 12/2017 */ 7162306a36Sopenharmony_ci {"Windows 2017", NULL, 0, ACPI_OSI_WIN_10_RS2}, /* Windows 10 version 1703 - Added 12/2017 */ 7262306a36Sopenharmony_ci {"Windows 2017.2", NULL, 0, ACPI_OSI_WIN_10_RS3}, /* Windows 10 version 1709 - Added 02/2018 */ 7362306a36Sopenharmony_ci {"Windows 2018", NULL, 0, ACPI_OSI_WIN_10_RS4}, /* Windows 10 version 1803 - Added 11/2018 */ 7462306a36Sopenharmony_ci {"Windows 2018.2", NULL, 0, ACPI_OSI_WIN_10_RS5}, /* Windows 10 version 1809 - Added 11/2018 */ 7562306a36Sopenharmony_ci {"Windows 2019", NULL, 0, ACPI_OSI_WIN_10_19H1}, /* Windows 10 version 1903 - Added 08/2019 */ 7662306a36Sopenharmony_ci {"Windows 2020", NULL, 0, ACPI_OSI_WIN_10_20H1}, /* Windows 10 version 2004 - Added 08/2021 */ 7762306a36Sopenharmony_ci {"Windows 2021", NULL, 0, ACPI_OSI_WIN_11}, /* Windows 11 - Added 01/2022 */ 7862306a36Sopenharmony_ci 7962306a36Sopenharmony_ci /* Feature Group Strings */ 8062306a36Sopenharmony_ci 8162306a36Sopenharmony_ci {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0}, 8262306a36Sopenharmony_ci 8362306a36Sopenharmony_ci /* 8462306a36Sopenharmony_ci * All "optional" feature group strings (features that are implemented 8562306a36Sopenharmony_ci * by the host) should be dynamically modified to VALID by the host via 8662306a36Sopenharmony_ci * acpi_install_interface or acpi_update_interfaces. Such optional feature 8762306a36Sopenharmony_ci * group strings are set as INVALID by default here. 8862306a36Sopenharmony_ci */ 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 9162306a36Sopenharmony_ci {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 9262306a36Sopenharmony_ci {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 9362306a36Sopenharmony_ci {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}, 9462306a36Sopenharmony_ci {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0} 9562306a36Sopenharmony_ci}; 9662306a36Sopenharmony_ci 9762306a36Sopenharmony_ci/******************************************************************************* 9862306a36Sopenharmony_ci * 9962306a36Sopenharmony_ci * FUNCTION: acpi_ut_initialize_interfaces 10062306a36Sopenharmony_ci * 10162306a36Sopenharmony_ci * PARAMETERS: None 10262306a36Sopenharmony_ci * 10362306a36Sopenharmony_ci * RETURN: Status 10462306a36Sopenharmony_ci * 10562306a36Sopenharmony_ci * DESCRIPTION: Initialize the global _OSI supported interfaces list 10662306a36Sopenharmony_ci * 10762306a36Sopenharmony_ci ******************************************************************************/ 10862306a36Sopenharmony_ci 10962306a36Sopenharmony_ciacpi_status acpi_ut_initialize_interfaces(void) 11062306a36Sopenharmony_ci{ 11162306a36Sopenharmony_ci acpi_status status; 11262306a36Sopenharmony_ci u32 i; 11362306a36Sopenharmony_ci 11462306a36Sopenharmony_ci status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); 11562306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 11662306a36Sopenharmony_ci return (status); 11762306a36Sopenharmony_ci } 11862306a36Sopenharmony_ci 11962306a36Sopenharmony_ci acpi_gbl_supported_interfaces = acpi_default_supported_interfaces; 12062306a36Sopenharmony_ci 12162306a36Sopenharmony_ci /* Link the static list of supported interfaces */ 12262306a36Sopenharmony_ci 12362306a36Sopenharmony_ci for (i = 0; 12462306a36Sopenharmony_ci i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1); 12562306a36Sopenharmony_ci i++) { 12662306a36Sopenharmony_ci acpi_default_supported_interfaces[i].next = 12762306a36Sopenharmony_ci &acpi_default_supported_interfaces[(acpi_size)i + 1]; 12862306a36Sopenharmony_ci } 12962306a36Sopenharmony_ci 13062306a36Sopenharmony_ci acpi_os_release_mutex(acpi_gbl_osi_mutex); 13162306a36Sopenharmony_ci return (AE_OK); 13262306a36Sopenharmony_ci} 13362306a36Sopenharmony_ci 13462306a36Sopenharmony_ci/******************************************************************************* 13562306a36Sopenharmony_ci * 13662306a36Sopenharmony_ci * FUNCTION: acpi_ut_interface_terminate 13762306a36Sopenharmony_ci * 13862306a36Sopenharmony_ci * PARAMETERS: None 13962306a36Sopenharmony_ci * 14062306a36Sopenharmony_ci * RETURN: Status 14162306a36Sopenharmony_ci * 14262306a36Sopenharmony_ci * DESCRIPTION: Delete all interfaces in the global list. Sets 14362306a36Sopenharmony_ci * acpi_gbl_supported_interfaces to NULL. 14462306a36Sopenharmony_ci * 14562306a36Sopenharmony_ci ******************************************************************************/ 14662306a36Sopenharmony_ci 14762306a36Sopenharmony_ciacpi_status acpi_ut_interface_terminate(void) 14862306a36Sopenharmony_ci{ 14962306a36Sopenharmony_ci acpi_status status; 15062306a36Sopenharmony_ci struct acpi_interface_info *next_interface; 15162306a36Sopenharmony_ci 15262306a36Sopenharmony_ci status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); 15362306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 15462306a36Sopenharmony_ci return (status); 15562306a36Sopenharmony_ci } 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci next_interface = acpi_gbl_supported_interfaces; 15862306a36Sopenharmony_ci while (next_interface) { 15962306a36Sopenharmony_ci acpi_gbl_supported_interfaces = next_interface->next; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci if (next_interface->flags & ACPI_OSI_DYNAMIC) { 16262306a36Sopenharmony_ci 16362306a36Sopenharmony_ci /* Only interfaces added at runtime can be freed */ 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci ACPI_FREE(next_interface->name); 16662306a36Sopenharmony_ci ACPI_FREE(next_interface); 16762306a36Sopenharmony_ci } else { 16862306a36Sopenharmony_ci /* Interface is in static list. Reset it to invalid or valid. */ 16962306a36Sopenharmony_ci 17062306a36Sopenharmony_ci if (next_interface->flags & ACPI_OSI_DEFAULT_INVALID) { 17162306a36Sopenharmony_ci next_interface->flags |= ACPI_OSI_INVALID; 17262306a36Sopenharmony_ci } else { 17362306a36Sopenharmony_ci next_interface->flags &= ~ACPI_OSI_INVALID; 17462306a36Sopenharmony_ci } 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci next_interface = acpi_gbl_supported_interfaces; 17862306a36Sopenharmony_ci } 17962306a36Sopenharmony_ci 18062306a36Sopenharmony_ci acpi_os_release_mutex(acpi_gbl_osi_mutex); 18162306a36Sopenharmony_ci return (AE_OK); 18262306a36Sopenharmony_ci} 18362306a36Sopenharmony_ci 18462306a36Sopenharmony_ci/******************************************************************************* 18562306a36Sopenharmony_ci * 18662306a36Sopenharmony_ci * FUNCTION: acpi_ut_install_interface 18762306a36Sopenharmony_ci * 18862306a36Sopenharmony_ci * PARAMETERS: interface_name - The interface to install 18962306a36Sopenharmony_ci * 19062306a36Sopenharmony_ci * RETURN: Status 19162306a36Sopenharmony_ci * 19262306a36Sopenharmony_ci * DESCRIPTION: Install the interface into the global interface list. 19362306a36Sopenharmony_ci * Caller MUST hold acpi_gbl_osi_mutex 19462306a36Sopenharmony_ci * 19562306a36Sopenharmony_ci ******************************************************************************/ 19662306a36Sopenharmony_ci 19762306a36Sopenharmony_ciacpi_status acpi_ut_install_interface(acpi_string interface_name) 19862306a36Sopenharmony_ci{ 19962306a36Sopenharmony_ci struct acpi_interface_info *interface_info; 20062306a36Sopenharmony_ci 20162306a36Sopenharmony_ci /* Allocate info block and space for the name string */ 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci interface_info = 20462306a36Sopenharmony_ci ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_interface_info)); 20562306a36Sopenharmony_ci if (!interface_info) { 20662306a36Sopenharmony_ci return (AE_NO_MEMORY); 20762306a36Sopenharmony_ci } 20862306a36Sopenharmony_ci 20962306a36Sopenharmony_ci interface_info->name = ACPI_ALLOCATE_ZEROED(strlen(interface_name) + 1); 21062306a36Sopenharmony_ci if (!interface_info->name) { 21162306a36Sopenharmony_ci ACPI_FREE(interface_info); 21262306a36Sopenharmony_ci return (AE_NO_MEMORY); 21362306a36Sopenharmony_ci } 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci /* Initialize new info and insert at the head of the global list */ 21662306a36Sopenharmony_ci 21762306a36Sopenharmony_ci strcpy(interface_info->name, interface_name); 21862306a36Sopenharmony_ci interface_info->flags = ACPI_OSI_DYNAMIC; 21962306a36Sopenharmony_ci interface_info->next = acpi_gbl_supported_interfaces; 22062306a36Sopenharmony_ci 22162306a36Sopenharmony_ci acpi_gbl_supported_interfaces = interface_info; 22262306a36Sopenharmony_ci return (AE_OK); 22362306a36Sopenharmony_ci} 22462306a36Sopenharmony_ci 22562306a36Sopenharmony_ci/******************************************************************************* 22662306a36Sopenharmony_ci * 22762306a36Sopenharmony_ci * FUNCTION: acpi_ut_remove_interface 22862306a36Sopenharmony_ci * 22962306a36Sopenharmony_ci * PARAMETERS: interface_name - The interface to remove 23062306a36Sopenharmony_ci * 23162306a36Sopenharmony_ci * RETURN: Status 23262306a36Sopenharmony_ci * 23362306a36Sopenharmony_ci * DESCRIPTION: Remove the interface from the global interface list. 23462306a36Sopenharmony_ci * Caller MUST hold acpi_gbl_osi_mutex 23562306a36Sopenharmony_ci * 23662306a36Sopenharmony_ci ******************************************************************************/ 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ciacpi_status acpi_ut_remove_interface(acpi_string interface_name) 23962306a36Sopenharmony_ci{ 24062306a36Sopenharmony_ci struct acpi_interface_info *previous_interface; 24162306a36Sopenharmony_ci struct acpi_interface_info *next_interface; 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci previous_interface = next_interface = acpi_gbl_supported_interfaces; 24462306a36Sopenharmony_ci while (next_interface) { 24562306a36Sopenharmony_ci if (!strcmp(interface_name, next_interface->name)) { 24662306a36Sopenharmony_ci /* 24762306a36Sopenharmony_ci * Found: name is in either the static list 24862306a36Sopenharmony_ci * or was added at runtime 24962306a36Sopenharmony_ci */ 25062306a36Sopenharmony_ci if (next_interface->flags & ACPI_OSI_DYNAMIC) { 25162306a36Sopenharmony_ci 25262306a36Sopenharmony_ci /* Interface was added dynamically, remove and free it */ 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci if (previous_interface == next_interface) { 25562306a36Sopenharmony_ci acpi_gbl_supported_interfaces = 25662306a36Sopenharmony_ci next_interface->next; 25762306a36Sopenharmony_ci } else { 25862306a36Sopenharmony_ci previous_interface->next = 25962306a36Sopenharmony_ci next_interface->next; 26062306a36Sopenharmony_ci } 26162306a36Sopenharmony_ci 26262306a36Sopenharmony_ci ACPI_FREE(next_interface->name); 26362306a36Sopenharmony_ci ACPI_FREE(next_interface); 26462306a36Sopenharmony_ci } else { 26562306a36Sopenharmony_ci /* 26662306a36Sopenharmony_ci * Interface is in static list. If marked invalid, then 26762306a36Sopenharmony_ci * it does not actually exist. Else, mark it invalid. 26862306a36Sopenharmony_ci */ 26962306a36Sopenharmony_ci if (next_interface->flags & ACPI_OSI_INVALID) { 27062306a36Sopenharmony_ci return (AE_NOT_EXIST); 27162306a36Sopenharmony_ci } 27262306a36Sopenharmony_ci 27362306a36Sopenharmony_ci next_interface->flags |= ACPI_OSI_INVALID; 27462306a36Sopenharmony_ci } 27562306a36Sopenharmony_ci 27662306a36Sopenharmony_ci return (AE_OK); 27762306a36Sopenharmony_ci } 27862306a36Sopenharmony_ci 27962306a36Sopenharmony_ci previous_interface = next_interface; 28062306a36Sopenharmony_ci next_interface = next_interface->next; 28162306a36Sopenharmony_ci } 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci /* Interface was not found */ 28462306a36Sopenharmony_ci 28562306a36Sopenharmony_ci return (AE_NOT_EXIST); 28662306a36Sopenharmony_ci} 28762306a36Sopenharmony_ci 28862306a36Sopenharmony_ci/******************************************************************************* 28962306a36Sopenharmony_ci * 29062306a36Sopenharmony_ci * FUNCTION: acpi_ut_update_interfaces 29162306a36Sopenharmony_ci * 29262306a36Sopenharmony_ci * PARAMETERS: action - Actions to be performed during the 29362306a36Sopenharmony_ci * update 29462306a36Sopenharmony_ci * 29562306a36Sopenharmony_ci * RETURN: Status 29662306a36Sopenharmony_ci * 29762306a36Sopenharmony_ci * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor 29862306a36Sopenharmony_ci * strings or/and feature group strings. 29962306a36Sopenharmony_ci * Caller MUST hold acpi_gbl_osi_mutex 30062306a36Sopenharmony_ci * 30162306a36Sopenharmony_ci ******************************************************************************/ 30262306a36Sopenharmony_ci 30362306a36Sopenharmony_ciacpi_status acpi_ut_update_interfaces(u8 action) 30462306a36Sopenharmony_ci{ 30562306a36Sopenharmony_ci struct acpi_interface_info *next_interface; 30662306a36Sopenharmony_ci 30762306a36Sopenharmony_ci next_interface = acpi_gbl_supported_interfaces; 30862306a36Sopenharmony_ci while (next_interface) { 30962306a36Sopenharmony_ci if (((next_interface->flags & ACPI_OSI_FEATURE) && 31062306a36Sopenharmony_ci (action & ACPI_FEATURE_STRINGS)) || 31162306a36Sopenharmony_ci (!(next_interface->flags & ACPI_OSI_FEATURE) && 31262306a36Sopenharmony_ci (action & ACPI_VENDOR_STRINGS))) { 31362306a36Sopenharmony_ci if (action & ACPI_DISABLE_INTERFACES) { 31462306a36Sopenharmony_ci 31562306a36Sopenharmony_ci /* Mark the interfaces as invalid */ 31662306a36Sopenharmony_ci 31762306a36Sopenharmony_ci next_interface->flags |= ACPI_OSI_INVALID; 31862306a36Sopenharmony_ci } else { 31962306a36Sopenharmony_ci /* Mark the interfaces as valid */ 32062306a36Sopenharmony_ci 32162306a36Sopenharmony_ci next_interface->flags &= ~ACPI_OSI_INVALID; 32262306a36Sopenharmony_ci } 32362306a36Sopenharmony_ci } 32462306a36Sopenharmony_ci 32562306a36Sopenharmony_ci next_interface = next_interface->next; 32662306a36Sopenharmony_ci } 32762306a36Sopenharmony_ci 32862306a36Sopenharmony_ci return (AE_OK); 32962306a36Sopenharmony_ci} 33062306a36Sopenharmony_ci 33162306a36Sopenharmony_ci/******************************************************************************* 33262306a36Sopenharmony_ci * 33362306a36Sopenharmony_ci * FUNCTION: acpi_ut_get_interface 33462306a36Sopenharmony_ci * 33562306a36Sopenharmony_ci * PARAMETERS: interface_name - The interface to find 33662306a36Sopenharmony_ci * 33762306a36Sopenharmony_ci * RETURN: struct acpi_interface_info if found. NULL if not found. 33862306a36Sopenharmony_ci * 33962306a36Sopenharmony_ci * DESCRIPTION: Search for the specified interface name in the global list. 34062306a36Sopenharmony_ci * Caller MUST hold acpi_gbl_osi_mutex 34162306a36Sopenharmony_ci * 34262306a36Sopenharmony_ci ******************************************************************************/ 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_cistruct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name) 34562306a36Sopenharmony_ci{ 34662306a36Sopenharmony_ci struct acpi_interface_info *next_interface; 34762306a36Sopenharmony_ci 34862306a36Sopenharmony_ci next_interface = acpi_gbl_supported_interfaces; 34962306a36Sopenharmony_ci while (next_interface) { 35062306a36Sopenharmony_ci if (!strcmp(interface_name, next_interface->name)) { 35162306a36Sopenharmony_ci return (next_interface); 35262306a36Sopenharmony_ci } 35362306a36Sopenharmony_ci 35462306a36Sopenharmony_ci next_interface = next_interface->next; 35562306a36Sopenharmony_ci } 35662306a36Sopenharmony_ci 35762306a36Sopenharmony_ci return (NULL); 35862306a36Sopenharmony_ci} 35962306a36Sopenharmony_ci 36062306a36Sopenharmony_ci/******************************************************************************* 36162306a36Sopenharmony_ci * 36262306a36Sopenharmony_ci * FUNCTION: acpi_ut_osi_implementation 36362306a36Sopenharmony_ci * 36462306a36Sopenharmony_ci * PARAMETERS: walk_state - Current walk state 36562306a36Sopenharmony_ci * 36662306a36Sopenharmony_ci * RETURN: Status 36762306a36Sopenharmony_ci * Integer: TRUE (0) if input string is matched 36862306a36Sopenharmony_ci * FALSE (-1) if string is not matched 36962306a36Sopenharmony_ci * 37062306a36Sopenharmony_ci * DESCRIPTION: Implementation of the _OSI predefined control method. When 37162306a36Sopenharmony_ci * an invocation of _OSI is encountered in the system AML, 37262306a36Sopenharmony_ci * control is transferred to this function. 37362306a36Sopenharmony_ci * 37462306a36Sopenharmony_ci * (August 2016) 37562306a36Sopenharmony_ci * Note: _OSI is now defined to return "Ones" to indicate a match, for 37662306a36Sopenharmony_ci * compatibility with other ACPI implementations. On a 32-bit DSDT, Ones 37762306a36Sopenharmony_ci * is 0xFFFFFFFF. On a 64-bit DSDT, Ones is 0xFFFFFFFFFFFFFFFF 37862306a36Sopenharmony_ci * (ACPI_UINT64_MAX). 37962306a36Sopenharmony_ci * 38062306a36Sopenharmony_ci * This function always returns ACPI_UINT64_MAX for TRUE, and later code 38162306a36Sopenharmony_ci * will truncate this to 32 bits if necessary. 38262306a36Sopenharmony_ci * 38362306a36Sopenharmony_ci ******************************************************************************/ 38462306a36Sopenharmony_ci 38562306a36Sopenharmony_ciacpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) 38662306a36Sopenharmony_ci{ 38762306a36Sopenharmony_ci union acpi_operand_object *string_desc; 38862306a36Sopenharmony_ci union acpi_operand_object *return_desc; 38962306a36Sopenharmony_ci struct acpi_interface_info *interface_info; 39062306a36Sopenharmony_ci acpi_interface_handler interface_handler; 39162306a36Sopenharmony_ci acpi_status status; 39262306a36Sopenharmony_ci u64 return_value; 39362306a36Sopenharmony_ci 39462306a36Sopenharmony_ci ACPI_FUNCTION_TRACE(ut_osi_implementation); 39562306a36Sopenharmony_ci 39662306a36Sopenharmony_ci /* Validate the string input argument (from the AML caller) */ 39762306a36Sopenharmony_ci 39862306a36Sopenharmony_ci string_desc = walk_state->arguments[0].object; 39962306a36Sopenharmony_ci if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) { 40062306a36Sopenharmony_ci return_ACPI_STATUS(AE_TYPE); 40162306a36Sopenharmony_ci } 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_ci /* Create a return object */ 40462306a36Sopenharmony_ci 40562306a36Sopenharmony_ci return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); 40662306a36Sopenharmony_ci if (!return_desc) { 40762306a36Sopenharmony_ci return_ACPI_STATUS(AE_NO_MEMORY); 40862306a36Sopenharmony_ci } 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci /* Default return value is 0, NOT SUPPORTED */ 41162306a36Sopenharmony_ci 41262306a36Sopenharmony_ci return_value = 0; 41362306a36Sopenharmony_ci status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER); 41462306a36Sopenharmony_ci if (ACPI_FAILURE(status)) { 41562306a36Sopenharmony_ci acpi_ut_remove_reference(return_desc); 41662306a36Sopenharmony_ci return_ACPI_STATUS(status); 41762306a36Sopenharmony_ci } 41862306a36Sopenharmony_ci 41962306a36Sopenharmony_ci /* Lookup the interface in the global _OSI list */ 42062306a36Sopenharmony_ci 42162306a36Sopenharmony_ci interface_info = acpi_ut_get_interface(string_desc->string.pointer); 42262306a36Sopenharmony_ci if (interface_info && !(interface_info->flags & ACPI_OSI_INVALID)) { 42362306a36Sopenharmony_ci /* 42462306a36Sopenharmony_ci * The interface is supported. 42562306a36Sopenharmony_ci * Update the osi_data if necessary. We keep track of the latest 42662306a36Sopenharmony_ci * version of Windows that has been requested by the BIOS. 42762306a36Sopenharmony_ci */ 42862306a36Sopenharmony_ci if (interface_info->value > acpi_gbl_osi_data) { 42962306a36Sopenharmony_ci acpi_gbl_osi_data = interface_info->value; 43062306a36Sopenharmony_ci } 43162306a36Sopenharmony_ci 43262306a36Sopenharmony_ci return_value = ACPI_UINT64_MAX; 43362306a36Sopenharmony_ci } 43462306a36Sopenharmony_ci 43562306a36Sopenharmony_ci acpi_os_release_mutex(acpi_gbl_osi_mutex); 43662306a36Sopenharmony_ci 43762306a36Sopenharmony_ci /* 43862306a36Sopenharmony_ci * Invoke an optional _OSI interface handler. The host OS may wish 43962306a36Sopenharmony_ci * to do some interface-specific handling. For example, warn about 44062306a36Sopenharmony_ci * certain interfaces or override the true/false support value. 44162306a36Sopenharmony_ci */ 44262306a36Sopenharmony_ci interface_handler = acpi_gbl_interface_handler; 44362306a36Sopenharmony_ci if (interface_handler) { 44462306a36Sopenharmony_ci if (interface_handler 44562306a36Sopenharmony_ci (string_desc->string.pointer, (u32)return_value)) { 44662306a36Sopenharmony_ci return_value = ACPI_UINT64_MAX; 44762306a36Sopenharmony_ci } 44862306a36Sopenharmony_ci } 44962306a36Sopenharmony_ci 45062306a36Sopenharmony_ci ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO, 45162306a36Sopenharmony_ci "ACPI: BIOS _OSI(\"%s\") is %ssupported\n", 45262306a36Sopenharmony_ci string_desc->string.pointer, 45362306a36Sopenharmony_ci return_value == 0 ? "not " : "")); 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci /* Complete the return object */ 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci return_desc->integer.value = return_value; 45862306a36Sopenharmony_ci walk_state->return_desc = return_desc; 45962306a36Sopenharmony_ci return_ACPI_STATUS(AE_OK); 46062306a36Sopenharmony_ci} 461