utosi.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460
  1. // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
  2. /******************************************************************************
  3. *
  4. * Module Name: utosi - Support for the _OSI predefined control method
  5. *
  6. * Copyright (C) 2000 - 2022, Intel Corp.
  7. *
  8. *****************************************************************************/
  9. #include <acpi/acpi.h>
  10. #include "accommon.h"
  11. #define _COMPONENT ACPI_UTILITIES
  12. ACPI_MODULE_NAME("utosi")
  13. /******************************************************************************
  14. *
  15. * ACPICA policy for new _OSI strings:
  16. *
  17. * It is the stated policy of ACPICA that new _OSI strings will be integrated
  18. * into this module as soon as possible after they are defined. It is strongly
  19. * recommended that all ACPICA hosts mirror this policy and integrate any
  20. * changes to this module as soon as possible. There are several historical
  21. * reasons behind this policy:
  22. *
  23. * 1) New BIOSs tend to test only the case where the host responds TRUE to
  24. * the latest version of Windows, which would respond to the latest/newest
  25. * _OSI string. Not responding TRUE to the latest version of Windows will
  26. * risk executing untested code paths throughout the DSDT and SSDTs.
  27. *
  28. * 2) If a new _OSI string is recognized only after a significant delay, this
  29. * has the potential to cause problems on existing working machines because
  30. * of the possibility that a new and different path through the ASL code
  31. * will be executed.
  32. *
  33. * 3) New _OSI strings are tending to come out about once per year. A delay
  34. * in recognizing a new string for a significant amount of time risks the
  35. * release of another string which only compounds the initial problem.
  36. *
  37. *****************************************************************************/
  38. /*
  39. * Strings supported by the _OSI predefined control method (which is
  40. * implemented internally within this module.)
  41. *
  42. * March 2009: Removed "Linux" as this host no longer wants to respond true
  43. * for this string. Basically, the only safe OS strings are windows-related
  44. * and in many or most cases represent the only test path within the
  45. * BIOS-provided ASL code.
  46. *
  47. * The last element of each entry is used to track the newest version of
  48. * Windows that the BIOS has requested.
  49. */
  50. static struct acpi_interface_info acpi_default_supported_interfaces[] = {
  51. /* Operating System Vendor Strings */
  52. {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */
  53. {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */
  54. {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */
  55. {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */
  56. {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */
  57. {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */
  58. {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows vista - Added 03/2006 */
  59. {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */
  60. {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */
  61. {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */
  62. {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */
  63. {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */
  64. {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8_1}, /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */
  65. {"Windows 2015", NULL, 0, ACPI_OSI_WIN_10}, /* Windows 10 - Added 03/2015 */
  66. {"Windows 2016", NULL, 0, ACPI_OSI_WIN_10_RS1}, /* Windows 10 version 1607 - Added 12/2017 */
  67. {"Windows 2017", NULL, 0, ACPI_OSI_WIN_10_RS2}, /* Windows 10 version 1703 - Added 12/2017 */
  68. {"Windows 2017.2", NULL, 0, ACPI_OSI_WIN_10_RS3}, /* Windows 10 version 1709 - Added 02/2018 */
  69. {"Windows 2018", NULL, 0, ACPI_OSI_WIN_10_RS4}, /* Windows 10 version 1803 - Added 11/2018 */
  70. {"Windows 2018.2", NULL, 0, ACPI_OSI_WIN_10_RS5}, /* Windows 10 version 1809 - Added 11/2018 */
  71. {"Windows 2019", NULL, 0, ACPI_OSI_WIN_10_19H1}, /* Windows 10 version 1903 - Added 08/2019 */
  72. {"Windows 2020", NULL, 0, ACPI_OSI_WIN_10_20H1}, /* Windows 10 version 2004 - Added 08/2021 */
  73. {"Windows 2021", NULL, 0, ACPI_OSI_WIN_11}, /* Windows 11 - Added 01/2022 */
  74. /* Feature Group Strings */
  75. {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0},
  76. /*
  77. * All "optional" feature group strings (features that are implemented
  78. * by the host) should be dynamically modified to VALID by the host via
  79. * acpi_install_interface or acpi_update_interfaces. Such optional feature
  80. * group strings are set as INVALID by default here.
  81. */
  82. {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
  83. {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
  84. {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
  85. {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
  86. {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}
  87. };
  88. /*******************************************************************************
  89. *
  90. * FUNCTION: acpi_ut_initialize_interfaces
  91. *
  92. * PARAMETERS: None
  93. *
  94. * RETURN: Status
  95. *
  96. * DESCRIPTION: Initialize the global _OSI supported interfaces list
  97. *
  98. ******************************************************************************/
  99. acpi_status acpi_ut_initialize_interfaces(void)
  100. {
  101. acpi_status status;
  102. u32 i;
  103. status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
  104. if (ACPI_FAILURE(status)) {
  105. return (status);
  106. }
  107. acpi_gbl_supported_interfaces = acpi_default_supported_interfaces;
  108. /* Link the static list of supported interfaces */
  109. for (i = 0;
  110. i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1);
  111. i++) {
  112. acpi_default_supported_interfaces[i].next =
  113. &acpi_default_supported_interfaces[(acpi_size)i + 1];
  114. }
  115. acpi_os_release_mutex(acpi_gbl_osi_mutex);
  116. return (AE_OK);
  117. }
  118. /*******************************************************************************
  119. *
  120. * FUNCTION: acpi_ut_interface_terminate
  121. *
  122. * PARAMETERS: None
  123. *
  124. * RETURN: Status
  125. *
  126. * DESCRIPTION: Delete all interfaces in the global list. Sets
  127. * acpi_gbl_supported_interfaces to NULL.
  128. *
  129. ******************************************************************************/
  130. acpi_status acpi_ut_interface_terminate(void)
  131. {
  132. acpi_status status;
  133. struct acpi_interface_info *next_interface;
  134. status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
  135. if (ACPI_FAILURE(status)) {
  136. return (status);
  137. }
  138. next_interface = acpi_gbl_supported_interfaces;
  139. while (next_interface) {
  140. acpi_gbl_supported_interfaces = next_interface->next;
  141. if (next_interface->flags & ACPI_OSI_DYNAMIC) {
  142. /* Only interfaces added at runtime can be freed */
  143. ACPI_FREE(next_interface->name);
  144. ACPI_FREE(next_interface);
  145. } else {
  146. /* Interface is in static list. Reset it to invalid or valid. */
  147. if (next_interface->flags & ACPI_OSI_DEFAULT_INVALID) {
  148. next_interface->flags |= ACPI_OSI_INVALID;
  149. } else {
  150. next_interface->flags &= ~ACPI_OSI_INVALID;
  151. }
  152. }
  153. next_interface = acpi_gbl_supported_interfaces;
  154. }
  155. acpi_os_release_mutex(acpi_gbl_osi_mutex);
  156. return (AE_OK);
  157. }
  158. /*******************************************************************************
  159. *
  160. * FUNCTION: acpi_ut_install_interface
  161. *
  162. * PARAMETERS: interface_name - The interface to install
  163. *
  164. * RETURN: Status
  165. *
  166. * DESCRIPTION: Install the interface into the global interface list.
  167. * Caller MUST hold acpi_gbl_osi_mutex
  168. *
  169. ******************************************************************************/
  170. acpi_status acpi_ut_install_interface(acpi_string interface_name)
  171. {
  172. struct acpi_interface_info *interface_info;
  173. /* Allocate info block and space for the name string */
  174. interface_info =
  175. ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_interface_info));
  176. if (!interface_info) {
  177. return (AE_NO_MEMORY);
  178. }
  179. interface_info->name = ACPI_ALLOCATE_ZEROED(strlen(interface_name) + 1);
  180. if (!interface_info->name) {
  181. ACPI_FREE(interface_info);
  182. return (AE_NO_MEMORY);
  183. }
  184. /* Initialize new info and insert at the head of the global list */
  185. strcpy(interface_info->name, interface_name);
  186. interface_info->flags = ACPI_OSI_DYNAMIC;
  187. interface_info->next = acpi_gbl_supported_interfaces;
  188. acpi_gbl_supported_interfaces = interface_info;
  189. return (AE_OK);
  190. }
  191. /*******************************************************************************
  192. *
  193. * FUNCTION: acpi_ut_remove_interface
  194. *
  195. * PARAMETERS: interface_name - The interface to remove
  196. *
  197. * RETURN: Status
  198. *
  199. * DESCRIPTION: Remove the interface from the global interface list.
  200. * Caller MUST hold acpi_gbl_osi_mutex
  201. *
  202. ******************************************************************************/
  203. acpi_status acpi_ut_remove_interface(acpi_string interface_name)
  204. {
  205. struct acpi_interface_info *previous_interface;
  206. struct acpi_interface_info *next_interface;
  207. previous_interface = next_interface = acpi_gbl_supported_interfaces;
  208. while (next_interface) {
  209. if (!strcmp(interface_name, next_interface->name)) {
  210. /*
  211. * Found: name is in either the static list
  212. * or was added at runtime
  213. */
  214. if (next_interface->flags & ACPI_OSI_DYNAMIC) {
  215. /* Interface was added dynamically, remove and free it */
  216. if (previous_interface == next_interface) {
  217. acpi_gbl_supported_interfaces =
  218. next_interface->next;
  219. } else {
  220. previous_interface->next =
  221. next_interface->next;
  222. }
  223. ACPI_FREE(next_interface->name);
  224. ACPI_FREE(next_interface);
  225. } else {
  226. /*
  227. * Interface is in static list. If marked invalid, then
  228. * it does not actually exist. Else, mark it invalid.
  229. */
  230. if (next_interface->flags & ACPI_OSI_INVALID) {
  231. return (AE_NOT_EXIST);
  232. }
  233. next_interface->flags |= ACPI_OSI_INVALID;
  234. }
  235. return (AE_OK);
  236. }
  237. previous_interface = next_interface;
  238. next_interface = next_interface->next;
  239. }
  240. /* Interface was not found */
  241. return (AE_NOT_EXIST);
  242. }
  243. /*******************************************************************************
  244. *
  245. * FUNCTION: acpi_ut_update_interfaces
  246. *
  247. * PARAMETERS: action - Actions to be performed during the
  248. * update
  249. *
  250. * RETURN: Status
  251. *
  252. * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor
  253. * strings or/and feature group strings.
  254. * Caller MUST hold acpi_gbl_osi_mutex
  255. *
  256. ******************************************************************************/
  257. acpi_status acpi_ut_update_interfaces(u8 action)
  258. {
  259. struct acpi_interface_info *next_interface;
  260. next_interface = acpi_gbl_supported_interfaces;
  261. while (next_interface) {
  262. if (((next_interface->flags & ACPI_OSI_FEATURE) &&
  263. (action & ACPI_FEATURE_STRINGS)) ||
  264. (!(next_interface->flags & ACPI_OSI_FEATURE) &&
  265. (action & ACPI_VENDOR_STRINGS))) {
  266. if (action & ACPI_DISABLE_INTERFACES) {
  267. /* Mark the interfaces as invalid */
  268. next_interface->flags |= ACPI_OSI_INVALID;
  269. } else {
  270. /* Mark the interfaces as valid */
  271. next_interface->flags &= ~ACPI_OSI_INVALID;
  272. }
  273. }
  274. next_interface = next_interface->next;
  275. }
  276. return (AE_OK);
  277. }
  278. /*******************************************************************************
  279. *
  280. * FUNCTION: acpi_ut_get_interface
  281. *
  282. * PARAMETERS: interface_name - The interface to find
  283. *
  284. * RETURN: struct acpi_interface_info if found. NULL if not found.
  285. *
  286. * DESCRIPTION: Search for the specified interface name in the global list.
  287. * Caller MUST hold acpi_gbl_osi_mutex
  288. *
  289. ******************************************************************************/
  290. struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name)
  291. {
  292. struct acpi_interface_info *next_interface;
  293. next_interface = acpi_gbl_supported_interfaces;
  294. while (next_interface) {
  295. if (!strcmp(interface_name, next_interface->name)) {
  296. return (next_interface);
  297. }
  298. next_interface = next_interface->next;
  299. }
  300. return (NULL);
  301. }
  302. /*******************************************************************************
  303. *
  304. * FUNCTION: acpi_ut_osi_implementation
  305. *
  306. * PARAMETERS: walk_state - Current walk state
  307. *
  308. * RETURN: Status
  309. * Integer: TRUE (0) if input string is matched
  310. * FALSE (-1) if string is not matched
  311. *
  312. * DESCRIPTION: Implementation of the _OSI predefined control method. When
  313. * an invocation of _OSI is encountered in the system AML,
  314. * control is transferred to this function.
  315. *
  316. * (August 2016)
  317. * Note: _OSI is now defined to return "Ones" to indicate a match, for
  318. * compatibility with other ACPI implementations. On a 32-bit DSDT, Ones
  319. * is 0xFFFFFFFF. On a 64-bit DSDT, Ones is 0xFFFFFFFFFFFFFFFF
  320. * (ACPI_UINT64_MAX).
  321. *
  322. * This function always returns ACPI_UINT64_MAX for TRUE, and later code
  323. * will truncate this to 32 bits if necessary.
  324. *
  325. ******************************************************************************/
  326. acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
  327. {
  328. union acpi_operand_object *string_desc;
  329. union acpi_operand_object *return_desc;
  330. struct acpi_interface_info *interface_info;
  331. acpi_interface_handler interface_handler;
  332. acpi_status status;
  333. u64 return_value;
  334. ACPI_FUNCTION_TRACE(ut_osi_implementation);
  335. /* Validate the string input argument (from the AML caller) */
  336. string_desc = walk_state->arguments[0].object;
  337. if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
  338. return_ACPI_STATUS(AE_TYPE);
  339. }
  340. /* Create a return object */
  341. return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
  342. if (!return_desc) {
  343. return_ACPI_STATUS(AE_NO_MEMORY);
  344. }
  345. /* Default return value is 0, NOT SUPPORTED */
  346. return_value = 0;
  347. status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
  348. if (ACPI_FAILURE(status)) {
  349. acpi_ut_remove_reference(return_desc);
  350. return_ACPI_STATUS(status);
  351. }
  352. /* Lookup the interface in the global _OSI list */
  353. interface_info = acpi_ut_get_interface(string_desc->string.pointer);
  354. if (interface_info && !(interface_info->flags & ACPI_OSI_INVALID)) {
  355. /*
  356. * The interface is supported.
  357. * Update the osi_data if necessary. We keep track of the latest
  358. * version of Windows that has been requested by the BIOS.
  359. */
  360. if (interface_info->value > acpi_gbl_osi_data) {
  361. acpi_gbl_osi_data = interface_info->value;
  362. }
  363. return_value = ACPI_UINT64_MAX;
  364. }
  365. acpi_os_release_mutex(acpi_gbl_osi_mutex);
  366. /*
  367. * Invoke an optional _OSI interface handler. The host OS may wish
  368. * to do some interface-specific handling. For example, warn about
  369. * certain interfaces or override the true/false support value.
  370. */
  371. interface_handler = acpi_gbl_interface_handler;
  372. if (interface_handler) {
  373. if (interface_handler
  374. (string_desc->string.pointer, (u32)return_value)) {
  375. return_value = ACPI_UINT64_MAX;
  376. }
  377. }
  378. ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
  379. "ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
  380. string_desc->string.pointer,
  381. return_value == 0 ? "not " : ""));
  382. /* Complete the return object */
  383. return_desc->integer.value = return_value;
  384. walk_state->return_desc = return_desc;
  385. return_ACPI_STATUS(AE_OK);
  386. }