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