1
1
use super :: {
2
2
AmlError ,
3
- object:: { MethodFlags , Object , WrappedObject } ,
3
+ object:: { Object , ObjectType , WrappedObject } ,
4
4
} ;
5
5
use alloc:: {
6
6
collections:: btree_map:: BTreeMap ,
7
7
string:: { String , ToString } ,
8
- sync:: Arc ,
9
8
vec,
10
9
vec:: Vec ,
11
10
} ;
12
11
use bit_field:: BitField ;
13
12
use core:: { fmt, str, str:: FromStr } ;
14
- use log:: trace;
13
+ use log:: { trace, warn } ;
15
14
16
15
#[ derive( Clone ) ]
17
16
pub struct Namespace {
@@ -29,13 +28,101 @@ impl Namespace {
29
28
namespace. add_level ( AmlName :: from_str ( "\\ _PR" ) . unwrap ( ) , NamespaceLevelKind :: Scope ) . unwrap ( ) ;
30
29
namespace. add_level ( AmlName :: from_str ( "\\ _TZ" ) . unwrap ( ) , NamespaceLevelKind :: Scope ) . unwrap ( ) ;
31
30
32
- // TODO: this is just testing the native methods atm - actually implement it
33
- namespace. insert (
34
- AmlName :: from_str ( "\\ _OSI" ) . unwrap ( ) ,
35
- Object :: NativeMethod { f : Arc :: new ( |args| todo ! ( ) ) , flags : MethodFlags ( 0 ) } . wrap ( ) ,
36
- ) ;
31
+ /*
32
+ * In the dark ages of ACPI 1.0, before `\_OSI`, `\_OS` was used to communicate to the firmware which OS
33
+ * was running. This was predictably not very good, and so was replaced in ACPI 3.0 with `_OSI`, which
34
+ * allows support for individual capabilities to be queried. `_OS` should not be used by modern firmwares;
35
+ * we follow the NT interpreter and ACPICA by calling ourselves `Microsoft Windows NT`.
36
+ *
37
+ * See https://www.kernel.org/doc/html/latest/firmware-guide/acpi/osi.html for more information.
38
+ */
39
+ namespace
40
+ . insert ( AmlName :: from_str ( "\\ _OS" ) . unwrap ( ) , Object :: String ( "Microsoft Windows NT" . to_string ( ) ) . wrap ( ) )
41
+ . unwrap ( ) ;
42
+
43
+ /*
44
+ * `\_OSI` was introduced by ACPI 3.0 to improve the situation created by `\_OS`. Unfortunately, exactly
45
+ * the same problem was immediately repeated by introducing capabilities reflecting that an ACPI
46
+ * implementation is exactly the same as a particular version of Windows' (e.g. firmwares will call
47
+ * `\_OSI("Windows 2001")`).
48
+ *
49
+ * We basically follow suit with whatever Linux does, as this will hopefully minimise breakage:
50
+ * - We always claim `Windows *` compatability
51
+ * - We answer 'yes' to `_OSI("Darwin")
52
+ * - We answer 'no' to `_OSI("Linux")`, and report that the tables are doing the wrong thing
53
+ */
54
+ namespace
55
+ . insert (
56
+ AmlName :: from_str ( "\\ _OSI" ) . unwrap ( ) ,
57
+ Object :: native_method ( 1 , |args| {
58
+ if args. len ( ) != 1 {
59
+ return Err ( AmlError :: MethodArgCountIncorrect ) ;
60
+ }
61
+ let Object :: String ( ref feature) = * args[ 0 ] else {
62
+ return Err ( AmlError :: ObjectNotOfExpectedType {
63
+ expected : ObjectType :: String ,
64
+ got : args[ 0 ] . typ ( ) ,
65
+ } ) ;
66
+ } ;
67
+
68
+ let is_supported = match feature. as_str ( ) {
69
+ "Windows 2000" => true , // 2000
70
+ "Windows 2001" => true , // XP
71
+ "Windows 2001 SP1" => true , // XP SP1
72
+ "Windows 2001 SP2" => true , // XP SP2
73
+ "Windows 2001.1" => true , // Server 2003
74
+ "Windows 2001.1 SP1" => true , // Server 2003 SP1
75
+ "Windows 2006" => true , // Vista
76
+ "Windows 2006 SP1" => true , // Vista SP1
77
+ "Windows 2006 SP2" => true , // Vista SP2
78
+ "Windows 2006.1" => true , // Server 2008
79
+ "Windows 2009" => true , // 7 and Server 2008 R2
80
+ "Windows 2012" => true , // 8 and Server 2012
81
+ "Windows 2013" => true , // 8.1 and Server 2012 R2
82
+ "Windows 2015" => true , // 10
83
+ "Windows 2016" => true , // 10 version 1607
84
+ "Windows 2017" => true , // 10 version 1703
85
+ "Windows 2017.2" => true , // 10 version 1709
86
+ "Windows 2018" => true , // 10 version 1803
87
+ "Windows 2018.2" => true , // 10 version 1809
88
+ "Windows 2019" => true , // 10 version 1903
89
+ "Windows 2020" => true , // 10 version 20H1
90
+ "Windows 2021" => true , // 11
91
+ "Windows 2022" => true , // 11 version 22H2
92
+
93
+ // TODO: Linux answers yes to this, NT answers no. Maybe make configurable
94
+ "Darwin" => false ,
95
+
96
+ "Linux" => {
97
+ // TODO: should we allow users to specify that this should be true? Linux has a
98
+ // command line option for this.
99
+ warn ! ( "ACPI evaluated `_OSI(\" Linux\" )`. This is a bug. Reporting no support." ) ;
100
+ false
101
+ }
102
+
103
+ "Extended Address Space Descriptor" => true ,
104
+ "Module Device" => true ,
105
+ "3.0 Thermal Model" => true ,
106
+ "3.0 _SCP Extensions" => true ,
107
+ "Processor Aggregator Device" => true ,
108
+ _ => false ,
109
+ } ;
110
+
111
+ Ok ( Object :: Integer ( if is_supported { u64:: MAX } else { 0 } ) . wrap ( ) )
112
+ } )
113
+ . wrap ( ) ,
114
+ )
115
+ . unwrap ( ) ;
116
+
117
+ /*
118
+ * `\_REV` evaluates to the version of the ACPI specification supported by this interpreter. Linux did this
119
+ * correctly until 2015, but firmwares misused this to detect Linux (as even modern versions of Windows
120
+ * return `2`), and so they switched to just returning `2` (as we'll also do). `_REV` should be considered
121
+ * useless and deprecated (this is mirrored in newer specs, which claim `2` means "ACPI 2 or greater").
122
+ */
123
+ namespace. insert ( AmlName :: from_str ( "\\ _REV" ) . unwrap ( ) , Object :: Integer ( 2 ) . wrap ( ) ) . unwrap ( ) ;
37
124
38
- // TODO: add pre-defined objects as well - \GL, \OSI, etc.
125
+ // TODO: _GL
39
126
40
127
namespace
41
128
}
0 commit comments