utosi.c 15 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455
  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 - 2018, 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}, /* 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. /* Feature Group Strings */
  70. {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0},
  71. /*
  72. * All "optional" feature group strings (features that are implemented
  73. * by the host) should be dynamically modified to VALID by the host via
  74. * acpi_install_interface or acpi_update_interfaces. Such optional feature
  75. * group strings are set as INVALID by default here.
  76. */
  77. {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
  78. {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
  79. {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
  80. {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
  81. {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}
  82. };
  83. /*******************************************************************************
  84. *
  85. * FUNCTION: acpi_ut_initialize_interfaces
  86. *
  87. * PARAMETERS: None
  88. *
  89. * RETURN: Status
  90. *
  91. * DESCRIPTION: Initialize the global _OSI supported interfaces list
  92. *
  93. ******************************************************************************/
  94. acpi_status acpi_ut_initialize_interfaces(void)
  95. {
  96. acpi_status status;
  97. u32 i;
  98. status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
  99. if (ACPI_FAILURE(status)) {
  100. return (status);
  101. }
  102. acpi_gbl_supported_interfaces = acpi_default_supported_interfaces;
  103. /* Link the static list of supported interfaces */
  104. for (i = 0;
  105. i < (ACPI_ARRAY_LENGTH(acpi_default_supported_interfaces) - 1);
  106. i++) {
  107. acpi_default_supported_interfaces[i].next =
  108. &acpi_default_supported_interfaces[(acpi_size)i + 1];
  109. }
  110. acpi_os_release_mutex(acpi_gbl_osi_mutex);
  111. return (AE_OK);
  112. }
  113. /*******************************************************************************
  114. *
  115. * FUNCTION: acpi_ut_interface_terminate
  116. *
  117. * PARAMETERS: None
  118. *
  119. * RETURN: Status
  120. *
  121. * DESCRIPTION: Delete all interfaces in the global list. Sets
  122. * acpi_gbl_supported_interfaces to NULL.
  123. *
  124. ******************************************************************************/
  125. acpi_status acpi_ut_interface_terminate(void)
  126. {
  127. acpi_status status;
  128. struct acpi_interface_info *next_interface;
  129. status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
  130. if (ACPI_FAILURE(status)) {
  131. return (status);
  132. }
  133. next_interface = acpi_gbl_supported_interfaces;
  134. while (next_interface) {
  135. acpi_gbl_supported_interfaces = next_interface->next;
  136. if (next_interface->flags & ACPI_OSI_DYNAMIC) {
  137. /* Only interfaces added at runtime can be freed */
  138. ACPI_FREE(next_interface->name);
  139. ACPI_FREE(next_interface);
  140. } else {
  141. /* Interface is in static list. Reset it to invalid or valid. */
  142. if (next_interface->flags & ACPI_OSI_DEFAULT_INVALID) {
  143. next_interface->flags |= ACPI_OSI_INVALID;
  144. } else {
  145. next_interface->flags &= ~ACPI_OSI_INVALID;
  146. }
  147. }
  148. next_interface = acpi_gbl_supported_interfaces;
  149. }
  150. acpi_os_release_mutex(acpi_gbl_osi_mutex);
  151. return (AE_OK);
  152. }
  153. /*******************************************************************************
  154. *
  155. * FUNCTION: acpi_ut_install_interface
  156. *
  157. * PARAMETERS: interface_name - The interface to install
  158. *
  159. * RETURN: Status
  160. *
  161. * DESCRIPTION: Install the interface into the global interface list.
  162. * Caller MUST hold acpi_gbl_osi_mutex
  163. *
  164. ******************************************************************************/
  165. acpi_status acpi_ut_install_interface(acpi_string interface_name)
  166. {
  167. struct acpi_interface_info *interface_info;
  168. /* Allocate info block and space for the name string */
  169. interface_info =
  170. ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_interface_info));
  171. if (!interface_info) {
  172. return (AE_NO_MEMORY);
  173. }
  174. interface_info->name = ACPI_ALLOCATE_ZEROED(strlen(interface_name) + 1);
  175. if (!interface_info->name) {
  176. ACPI_FREE(interface_info);
  177. return (AE_NO_MEMORY);
  178. }
  179. /* Initialize new info and insert at the head of the global list */
  180. strcpy(interface_info->name, interface_name);
  181. interface_info->flags = ACPI_OSI_DYNAMIC;
  182. interface_info->next = acpi_gbl_supported_interfaces;
  183. acpi_gbl_supported_interfaces = interface_info;
  184. return (AE_OK);
  185. }
  186. /*******************************************************************************
  187. *
  188. * FUNCTION: acpi_ut_remove_interface
  189. *
  190. * PARAMETERS: interface_name - The interface to remove
  191. *
  192. * RETURN: Status
  193. *
  194. * DESCRIPTION: Remove the interface from the global interface list.
  195. * Caller MUST hold acpi_gbl_osi_mutex
  196. *
  197. ******************************************************************************/
  198. acpi_status acpi_ut_remove_interface(acpi_string interface_name)
  199. {
  200. struct acpi_interface_info *previous_interface;
  201. struct acpi_interface_info *next_interface;
  202. previous_interface = next_interface = acpi_gbl_supported_interfaces;
  203. while (next_interface) {
  204. if (!strcmp(interface_name, next_interface->name)) {
  205. /*
  206. * Found: name is in either the static list
  207. * or was added at runtime
  208. */
  209. if (next_interface->flags & ACPI_OSI_DYNAMIC) {
  210. /* Interface was added dynamically, remove and free it */
  211. if (previous_interface == next_interface) {
  212. acpi_gbl_supported_interfaces =
  213. next_interface->next;
  214. } else {
  215. previous_interface->next =
  216. next_interface->next;
  217. }
  218. ACPI_FREE(next_interface->name);
  219. ACPI_FREE(next_interface);
  220. } else {
  221. /*
  222. * Interface is in static list. If marked invalid, then
  223. * it does not actually exist. Else, mark it invalid.
  224. */
  225. if (next_interface->flags & ACPI_OSI_INVALID) {
  226. return (AE_NOT_EXIST);
  227. }
  228. next_interface->flags |= ACPI_OSI_INVALID;
  229. }
  230. return (AE_OK);
  231. }
  232. previous_interface = next_interface;
  233. next_interface = next_interface->next;
  234. }
  235. /* Interface was not found */
  236. return (AE_NOT_EXIST);
  237. }
  238. /*******************************************************************************
  239. *
  240. * FUNCTION: acpi_ut_update_interfaces
  241. *
  242. * PARAMETERS: action - Actions to be performed during the
  243. * update
  244. *
  245. * RETURN: Status
  246. *
  247. * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor
  248. * strings or/and feature group strings.
  249. * Caller MUST hold acpi_gbl_osi_mutex
  250. *
  251. ******************************************************************************/
  252. acpi_status acpi_ut_update_interfaces(u8 action)
  253. {
  254. struct acpi_interface_info *next_interface;
  255. next_interface = acpi_gbl_supported_interfaces;
  256. while (next_interface) {
  257. if (((next_interface->flags & ACPI_OSI_FEATURE) &&
  258. (action & ACPI_FEATURE_STRINGS)) ||
  259. (!(next_interface->flags & ACPI_OSI_FEATURE) &&
  260. (action & ACPI_VENDOR_STRINGS))) {
  261. if (action & ACPI_DISABLE_INTERFACES) {
  262. /* Mark the interfaces as invalid */
  263. next_interface->flags |= ACPI_OSI_INVALID;
  264. } else {
  265. /* Mark the interfaces as valid */
  266. next_interface->flags &= ~ACPI_OSI_INVALID;
  267. }
  268. }
  269. next_interface = next_interface->next;
  270. }
  271. return (AE_OK);
  272. }
  273. /*******************************************************************************
  274. *
  275. * FUNCTION: acpi_ut_get_interface
  276. *
  277. * PARAMETERS: interface_name - The interface to find
  278. *
  279. * RETURN: struct acpi_interface_info if found. NULL if not found.
  280. *
  281. * DESCRIPTION: Search for the specified interface name in the global list.
  282. * Caller MUST hold acpi_gbl_osi_mutex
  283. *
  284. ******************************************************************************/
  285. struct acpi_interface_info *acpi_ut_get_interface(acpi_string interface_name)
  286. {
  287. struct acpi_interface_info *next_interface;
  288. next_interface = acpi_gbl_supported_interfaces;
  289. while (next_interface) {
  290. if (!strcmp(interface_name, next_interface->name)) {
  291. return (next_interface);
  292. }
  293. next_interface = next_interface->next;
  294. }
  295. return (NULL);
  296. }
  297. /*******************************************************************************
  298. *
  299. * FUNCTION: acpi_ut_osi_implementation
  300. *
  301. * PARAMETERS: walk_state - Current walk state
  302. *
  303. * RETURN: Status
  304. * Integer: TRUE (0) if input string is matched
  305. * FALSE (-1) if string is not matched
  306. *
  307. * DESCRIPTION: Implementation of the _OSI predefined control method. When
  308. * an invocation of _OSI is encountered in the system AML,
  309. * control is transferred to this function.
  310. *
  311. * (August 2016)
  312. * Note: _OSI is now defined to return "Ones" to indicate a match, for
  313. * compatibility with other ACPI implementations. On a 32-bit DSDT, Ones
  314. * is 0xFFFFFFFF. On a 64-bit DSDT, Ones is 0xFFFFFFFFFFFFFFFF
  315. * (ACPI_UINT64_MAX).
  316. *
  317. * This function always returns ACPI_UINT64_MAX for TRUE, and later code
  318. * will truncate this to 32 bits if necessary.
  319. *
  320. ******************************************************************************/
  321. acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state)
  322. {
  323. union acpi_operand_object *string_desc;
  324. union acpi_operand_object *return_desc;
  325. struct acpi_interface_info *interface_info;
  326. acpi_interface_handler interface_handler;
  327. acpi_status status;
  328. u64 return_value;
  329. ACPI_FUNCTION_TRACE(ut_osi_implementation);
  330. /* Validate the string input argument (from the AML caller) */
  331. string_desc = walk_state->arguments[0].object;
  332. if (!string_desc || (string_desc->common.type != ACPI_TYPE_STRING)) {
  333. return_ACPI_STATUS(AE_TYPE);
  334. }
  335. /* Create a return object */
  336. return_desc = acpi_ut_create_internal_object(ACPI_TYPE_INTEGER);
  337. if (!return_desc) {
  338. return_ACPI_STATUS(AE_NO_MEMORY);
  339. }
  340. /* Default return value is 0, NOT SUPPORTED */
  341. return_value = 0;
  342. status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);
  343. if (ACPI_FAILURE(status)) {
  344. acpi_ut_remove_reference(return_desc);
  345. return_ACPI_STATUS(status);
  346. }
  347. /* Lookup the interface in the global _OSI list */
  348. interface_info = acpi_ut_get_interface(string_desc->string.pointer);
  349. if (interface_info && !(interface_info->flags & ACPI_OSI_INVALID)) {
  350. /*
  351. * The interface is supported.
  352. * Update the osi_data if necessary. We keep track of the latest
  353. * version of Windows that has been requested by the BIOS.
  354. */
  355. if (interface_info->value > acpi_gbl_osi_data) {
  356. acpi_gbl_osi_data = interface_info->value;
  357. }
  358. return_value = ACPI_UINT64_MAX;
  359. }
  360. acpi_os_release_mutex(acpi_gbl_osi_mutex);
  361. /*
  362. * Invoke an optional _OSI interface handler. The host OS may wish
  363. * to do some interface-specific handling. For example, warn about
  364. * certain interfaces or override the true/false support value.
  365. */
  366. interface_handler = acpi_gbl_interface_handler;
  367. if (interface_handler) {
  368. if (interface_handler
  369. (string_desc->string.pointer, (u32)return_value)) {
  370. return_value = ACPI_UINT64_MAX;
  371. }
  372. }
  373. ACPI_DEBUG_PRINT_RAW((ACPI_DB_INFO,
  374. "ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
  375. string_desc->string.pointer,
  376. return_value == 0 ? "not " : ""));
  377. /* Complete the return object */
  378. return_desc->integer.value = return_value;
  379. walk_state->return_desc = return_desc;
  380. return_ACPI_STATUS(AE_OK);
  381. }