utosi.c revision 1.1.1.3 1 /******************************************************************************
2 *
3 * Module Name: utosi - Support for the _OSI predefined control method
4 *
5 *****************************************************************************/
6
7 /*
8 * Copyright (C) 2000 - 2014, 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 /******************************************************************************
55 *
56 * ACPICA policy for new _OSI strings:
57 *
58 * It is the stated policy of ACPICA that new _OSI strings will be integrated
59 * into this module as soon as possible after they are defined. It is strongly
60 * recommended that all ACPICA hosts mirror this policy and integrate any
61 * changes to this module as soon as possible. There are several historical
62 * reasons behind this policy:
63 *
64 * 1) New BIOSs tend to test only the case where the host responds TRUE to
65 * the latest version of Windows, which would respond to the latest/newest
66 * _OSI string. Not responding TRUE to the latest version of Windows will
67 * risk executing untested code paths throughout the DSDT and SSDTs.
68 *
69 * 2) If a new _OSI string is recognized only after a significant delay, this
70 * has the potential to cause problems on existing working machines because
71 * of the possibility that a new and different path through the ASL code
72 * will be executed.
73 *
74 * 3) New _OSI strings are tending to come out about once per year. A delay
75 * in recognizing a new string for a significant amount of time risks the
76 * release of another string which only compounds the initial problem.
77 *
78 *****************************************************************************/
79
80
81 /*
82 * Strings supported by the _OSI predefined control method (which is
83 * implemented internally within this module.)
84 *
85 * March 2009: Removed "Linux" as this host no longer wants to respond true
86 * for this string. Basically, the only safe OS strings are windows-related
87 * and in many or most cases represent the only test path within the
88 * BIOS-provided ASL code.
89 *
90 * The last element of each entry is used to track the newest version of
91 * Windows that the BIOS has requested.
92 */
93 static ACPI_INTERFACE_INFO AcpiDefaultSupportedInterfaces[] =
94 {
95 /* Operating System Vendor Strings */
96
97 {"Windows 2000", NULL, 0, ACPI_OSI_WIN_2000}, /* Windows 2000 */
98 {"Windows 2001", NULL, 0, ACPI_OSI_WIN_XP}, /* Windows XP */
99 {"Windows 2001 SP1", NULL, 0, ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */
100 {"Windows 2001.1", NULL, 0, ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */
101 {"Windows 2001 SP2", NULL, 0, ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */
102 {"Windows 2001.1 SP1", NULL, 0, ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */
103 {"Windows 2006", NULL, 0, ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */
104 {"Windows 2006.1", NULL, 0, ACPI_OSI_WINSRV_2008}, /* Windows Server 2008 - Added 09/2009 */
105 {"Windows 2006 SP1", NULL, 0, ACPI_OSI_WIN_VISTA_SP1}, /* Windows Vista SP1 - Added 09/2009 */
106 {"Windows 2006 SP2", NULL, 0, ACPI_OSI_WIN_VISTA_SP2}, /* Windows Vista SP2 - Added 09/2010 */
107 {"Windows 2009", NULL, 0, ACPI_OSI_WIN_7}, /* Windows 7 and Server 2008 R2 - Added 09/2009 */
108 {"Windows 2012", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8 and Server 2012 - Added 08/2012 */
109 {"Windows 2013", NULL, 0, ACPI_OSI_WIN_8}, /* Windows 8.1 and Server 2012 R2 - Added 01/2014 */
110
111 /* Feature Group Strings */
112
113 {"Extended Address Space Descriptor", NULL, ACPI_OSI_FEATURE, 0},
114
115 /*
116 * All "optional" feature group strings (features that are implemented
117 * by the host) should be dynamically modified to VALID by the host via
118 * AcpiInstallInterface or AcpiUpdateInterfaces. Such optional feature
119 * group strings are set as INVALID by default here.
120 */
121
122 {"Module Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
123 {"Processor Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
124 {"3.0 Thermal Model", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
125 {"3.0 _SCP Extensions", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0},
126 {"Processor Aggregator Device", NULL, ACPI_OSI_OPTIONAL_FEATURE, 0}
127 };
128
129
130 /*******************************************************************************
131 *
132 * FUNCTION: AcpiUtInitializeInterfaces
133 *
134 * PARAMETERS: None
135 *
136 * RETURN: Status
137 *
138 * DESCRIPTION: Initialize the global _OSI supported interfaces list
139 *
140 ******************************************************************************/
141
142 ACPI_STATUS
143 AcpiUtInitializeInterfaces (
144 void)
145 {
146 ACPI_STATUS Status;
147 UINT32 i;
148
149
150 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
151 if (ACPI_FAILURE (Status))
152 {
153 return (Status);
154 }
155
156 AcpiGbl_SupportedInterfaces = AcpiDefaultSupportedInterfaces;
157
158 /* Link the static list of supported interfaces */
159
160 for (i = 0; i < (ACPI_ARRAY_LENGTH (AcpiDefaultSupportedInterfaces) - 1); i++)
161 {
162 AcpiDefaultSupportedInterfaces[i].Next =
163 &AcpiDefaultSupportedInterfaces[(ACPI_SIZE) i + 1];
164 }
165
166 AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
167 return (AE_OK);
168 }
169
170
171 /*******************************************************************************
172 *
173 * FUNCTION: AcpiUtInterfaceTerminate
174 *
175 * PARAMETERS: None
176 *
177 * RETURN: Status
178 *
179 * DESCRIPTION: Delete all interfaces in the global list. Sets
180 * AcpiGbl_SupportedInterfaces to NULL.
181 *
182 ******************************************************************************/
183
184 ACPI_STATUS
185 AcpiUtInterfaceTerminate (
186 void)
187 {
188 ACPI_STATUS Status;
189 ACPI_INTERFACE_INFO *NextInterface;
190
191
192 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
193 if (ACPI_FAILURE (Status))
194 {
195 return (Status);
196 }
197
198 NextInterface = AcpiGbl_SupportedInterfaces;
199 while (NextInterface)
200 {
201 AcpiGbl_SupportedInterfaces = NextInterface->Next;
202
203 if (NextInterface->Flags & ACPI_OSI_DYNAMIC)
204 {
205 /* Only interfaces added at runtime can be freed */
206
207 ACPI_FREE (NextInterface->Name);
208 ACPI_FREE (NextInterface);
209 }
210 else
211 {
212 /* Interface is in static list. Reset it to invalid or valid. */
213
214 if (NextInterface->Flags & ACPI_OSI_DEFAULT_INVALID)
215 {
216 NextInterface->Flags |= ACPI_OSI_INVALID;
217 }
218 else
219 {
220 NextInterface->Flags &= ~ACPI_OSI_INVALID;
221 }
222 }
223
224 NextInterface = AcpiGbl_SupportedInterfaces;
225 }
226
227 AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
228 return (AE_OK);
229 }
230
231
232 /*******************************************************************************
233 *
234 * FUNCTION: AcpiUtInstallInterface
235 *
236 * PARAMETERS: InterfaceName - The interface to install
237 *
238 * RETURN: Status
239 *
240 * DESCRIPTION: Install the interface into the global interface list.
241 * Caller MUST hold AcpiGbl_OsiMutex
242 *
243 ******************************************************************************/
244
245 ACPI_STATUS
246 AcpiUtInstallInterface (
247 ACPI_STRING InterfaceName)
248 {
249 ACPI_INTERFACE_INFO *InterfaceInfo;
250
251
252 /* Allocate info block and space for the name string */
253
254 InterfaceInfo = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_INTERFACE_INFO));
255 if (!InterfaceInfo)
256 {
257 return (AE_NO_MEMORY);
258 }
259
260 InterfaceInfo->Name = ACPI_ALLOCATE_ZEROED (ACPI_STRLEN (InterfaceName) + 1);
261 if (!InterfaceInfo->Name)
262 {
263 ACPI_FREE (InterfaceInfo);
264 return (AE_NO_MEMORY);
265 }
266
267 /* Initialize new info and insert at the head of the global list */
268
269 ACPI_STRCPY (InterfaceInfo->Name, InterfaceName);
270 InterfaceInfo->Flags = ACPI_OSI_DYNAMIC;
271 InterfaceInfo->Next = AcpiGbl_SupportedInterfaces;
272
273 AcpiGbl_SupportedInterfaces = InterfaceInfo;
274 return (AE_OK);
275 }
276
277
278 /*******************************************************************************
279 *
280 * FUNCTION: AcpiUtRemoveInterface
281 *
282 * PARAMETERS: InterfaceName - The interface to remove
283 *
284 * RETURN: Status
285 *
286 * DESCRIPTION: Remove the interface from the global interface list.
287 * Caller MUST hold AcpiGbl_OsiMutex
288 *
289 ******************************************************************************/
290
291 ACPI_STATUS
292 AcpiUtRemoveInterface (
293 ACPI_STRING InterfaceName)
294 {
295 ACPI_INTERFACE_INFO *PreviousInterface;
296 ACPI_INTERFACE_INFO *NextInterface;
297
298
299 PreviousInterface = NextInterface = AcpiGbl_SupportedInterfaces;
300 while (NextInterface)
301 {
302 if (!ACPI_STRCMP (InterfaceName, NextInterface->Name))
303 {
304 /* Found: name is in either the static list or was added at runtime */
305
306 if (NextInterface->Flags & ACPI_OSI_DYNAMIC)
307 {
308 /* Interface was added dynamically, remove and free it */
309
310 if (PreviousInterface == NextInterface)
311 {
312 AcpiGbl_SupportedInterfaces = NextInterface->Next;
313 }
314 else
315 {
316 PreviousInterface->Next = NextInterface->Next;
317 }
318
319 ACPI_FREE (NextInterface->Name);
320 ACPI_FREE (NextInterface);
321 }
322 else
323 {
324 /*
325 * Interface is in static list. If marked invalid, then it
326 * does not actually exist. Else, mark it invalid.
327 */
328 if (NextInterface->Flags & ACPI_OSI_INVALID)
329 {
330 return (AE_NOT_EXIST);
331 }
332
333 NextInterface->Flags |= ACPI_OSI_INVALID;
334 }
335
336 return (AE_OK);
337 }
338
339 PreviousInterface = NextInterface;
340 NextInterface = NextInterface->Next;
341 }
342
343 /* Interface was not found */
344
345 return (AE_NOT_EXIST);
346 }
347
348
349 /*******************************************************************************
350 *
351 * FUNCTION: AcpiUtUpdateInterfaces
352 *
353 * PARAMETERS: Action - Actions to be performed during the
354 * update
355 *
356 * RETURN: Status
357 *
358 * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor
359 * strings or/and feature group strings.
360 * Caller MUST hold AcpiGbl_OsiMutex
361 *
362 ******************************************************************************/
363
364 ACPI_STATUS
365 AcpiUtUpdateInterfaces (
366 UINT8 Action)
367 {
368 ACPI_INTERFACE_INFO *NextInterface;
369
370
371 NextInterface = AcpiGbl_SupportedInterfaces;
372 while (NextInterface)
373 {
374 if (((NextInterface->Flags & ACPI_OSI_FEATURE) &&
375 (Action & ACPI_FEATURE_STRINGS)) ||
376 (!(NextInterface->Flags & ACPI_OSI_FEATURE) &&
377 (Action & ACPI_VENDOR_STRINGS)))
378 {
379 if (Action & ACPI_DISABLE_INTERFACES)
380 {
381 /* Mark the interfaces as invalid */
382
383 NextInterface->Flags |= ACPI_OSI_INVALID;
384 }
385 else
386 {
387 /* Mark the interfaces as valid */
388
389 NextInterface->Flags &= ~ACPI_OSI_INVALID;
390 }
391 }
392
393 NextInterface = NextInterface->Next;
394 }
395
396 return (AE_OK);
397 }
398
399
400 /*******************************************************************************
401 *
402 * FUNCTION: AcpiUtGetInterface
403 *
404 * PARAMETERS: InterfaceName - The interface to find
405 *
406 * RETURN: ACPI_INTERFACE_INFO if found. NULL if not found.
407 *
408 * DESCRIPTION: Search for the specified interface name in the global list.
409 * Caller MUST hold AcpiGbl_OsiMutex
410 *
411 ******************************************************************************/
412
413 ACPI_INTERFACE_INFO *
414 AcpiUtGetInterface (
415 ACPI_STRING InterfaceName)
416 {
417 ACPI_INTERFACE_INFO *NextInterface;
418
419
420 NextInterface = AcpiGbl_SupportedInterfaces;
421 while (NextInterface)
422 {
423 if (!ACPI_STRCMP (InterfaceName, NextInterface->Name))
424 {
425 return (NextInterface);
426 }
427
428 NextInterface = NextInterface->Next;
429 }
430
431 return (NULL);
432 }
433
434
435 /*******************************************************************************
436 *
437 * FUNCTION: AcpiUtOsiImplementation
438 *
439 * PARAMETERS: WalkState - Current walk state
440 *
441 * RETURN: Status
442 *
443 * DESCRIPTION: Implementation of the _OSI predefined control method. When
444 * an invocation of _OSI is encountered in the system AML,
445 * control is transferred to this function.
446 *
447 ******************************************************************************/
448
449 ACPI_STATUS
450 AcpiUtOsiImplementation (
451 ACPI_WALK_STATE *WalkState)
452 {
453 ACPI_OPERAND_OBJECT *StringDesc;
454 ACPI_OPERAND_OBJECT *ReturnDesc;
455 ACPI_INTERFACE_INFO *InterfaceInfo;
456 ACPI_INTERFACE_HANDLER InterfaceHandler;
457 ACPI_STATUS Status;
458 UINT32 ReturnValue;
459
460
461 ACPI_FUNCTION_TRACE (UtOsiImplementation);
462
463
464 /* Validate the string input argument (from the AML caller) */
465
466 StringDesc = WalkState->Arguments[0].Object;
467 if (!StringDesc ||
468 (StringDesc->Common.Type != ACPI_TYPE_STRING))
469 {
470 return_ACPI_STATUS (AE_TYPE);
471 }
472
473 /* Create a return object */
474
475 ReturnDesc = AcpiUtCreateInternalObject (ACPI_TYPE_INTEGER);
476 if (!ReturnDesc)
477 {
478 return_ACPI_STATUS (AE_NO_MEMORY);
479 }
480
481 /* Default return value is 0, NOT SUPPORTED */
482
483 ReturnValue = 0;
484 Status = AcpiOsAcquireMutex (AcpiGbl_OsiMutex, ACPI_WAIT_FOREVER);
485 if (ACPI_FAILURE (Status))
486 {
487 AcpiUtRemoveReference (ReturnDesc);
488 return_ACPI_STATUS (Status);
489 }
490
491 /* Lookup the interface in the global _OSI list */
492
493 InterfaceInfo = AcpiUtGetInterface (StringDesc->String.Pointer);
494 if (InterfaceInfo &&
495 !(InterfaceInfo->Flags & ACPI_OSI_INVALID))
496 {
497 /*
498 * The interface is supported.
499 * Update the OsiData if necessary. We keep track of the latest
500 * version of Windows that has been requested by the BIOS.
501 */
502 if (InterfaceInfo->Value > AcpiGbl_OsiData)
503 {
504 AcpiGbl_OsiData = InterfaceInfo->Value;
505 }
506
507 ReturnValue = ACPI_UINT32_MAX;
508 }
509
510 AcpiOsReleaseMutex (AcpiGbl_OsiMutex);
511
512 /*
513 * Invoke an optional _OSI interface handler. The host OS may wish
514 * to do some interface-specific handling. For example, warn about
515 * certain interfaces or override the true/false support value.
516 */
517 InterfaceHandler = AcpiGbl_InterfaceHandler;
518 if (InterfaceHandler)
519 {
520 ReturnValue = InterfaceHandler (
521 StringDesc->String.Pointer, ReturnValue);
522 }
523
524 ACPI_DEBUG_PRINT_RAW ((ACPI_DB_INFO,
525 "ACPI: BIOS _OSI(\"%s\") is %ssupported\n",
526 StringDesc->String.Pointer, ReturnValue == 0 ? "not " : ""));
527
528 /* Complete the return object */
529
530 ReturnDesc->Integer.Value = ReturnValue;
531 WalkState->ReturnDesc = ReturnDesc;
532 return_ACPI_STATUS (AE_OK);
533 }
534