1 | #include <uacpi/internal/opcodes.h> |
2 | |
3 | #define UACPI_OP(opname, opcode, ...) \ |
4 | { #opname, .decode_ops = __VA_ARGS__, .code = opcode }, |
5 | |
6 | #define UACPI_OUT_OF_LINE_OP(opname, opcode, out_of_line_buf, props) \ |
7 | { \ |
8 | .name = #opname, \ |
9 | .indirect_decode_ops = out_of_line_buf, \ |
10 | .properties = props, \ |
11 | .code = opcode, \ |
12 | }, |
13 | |
14 | static const struct uacpi_op_spec opcode_table[0x100] = { |
15 | UACPI_ENUMERATE_OPCODES |
16 | }; |
17 | |
18 | static const struct uacpi_op_spec ext_opcode_table[] = { |
19 | UACPI_ENUMERATE_EXT_OPCODES |
20 | }; |
21 | |
22 | #define _(op) (op & 0x00FF) |
23 | |
24 | static const uacpi_u8 ext_op_to_idx[0x100] = { |
25 | [_(UACPI_AML_OP_MutexOp)] = 1, [_(UACPI_AML_OP_EventOp)] = 2, |
26 | [_(UACPI_AML_OP_CondRefOfOp)] = 3, [_(UACPI_AML_OP_CreateFieldOp)] = 4, |
27 | [_(UACPI_AML_OP_LoadTableOp)] = 5, [_(UACPI_AML_OP_LoadOp)] = 6, |
28 | [_(UACPI_AML_OP_StallOp)] = 7, [_(UACPI_AML_OP_SleepOp)] = 8, |
29 | [_(UACPI_AML_OP_AcquireOp)] = 9, [_(UACPI_AML_OP_SignalOp)] = 10, |
30 | [_(UACPI_AML_OP_WaitOp)] = 11, [_(UACPI_AML_OP_ResetOp)] = 12, |
31 | [_(UACPI_AML_OP_ReleaseOp)] = 13, [_(UACPI_AML_OP_FromBCDOp)] = 14, |
32 | [_(UACPI_AML_OP_ToBCDOp)] = 15, [_(UACPI_AML_OP_RevisionOp)] = 16, |
33 | [_(UACPI_AML_OP_DebugOp)] = 17, [_(UACPI_AML_OP_FatalOp)] = 18, |
34 | [_(UACPI_AML_OP_TimerOp)] = 19, [_(UACPI_AML_OP_OpRegionOp)] = 20, |
35 | [_(UACPI_AML_OP_FieldOp)] = 21, [_(UACPI_AML_OP_DeviceOp)] = 22, |
36 | [_(UACPI_AML_OP_ProcessorOp)] = 23, [_(UACPI_AML_OP_PowerResOp)] = 24, |
37 | [_(UACPI_AML_OP_ThermalZoneOp)] = 25, [_(UACPI_AML_OP_IndexFieldOp)] = 26, |
38 | [_(UACPI_AML_OP_BankFieldOp)] = 27, [_(UACPI_AML_OP_DataRegionOp)] = 28, |
39 | }; |
40 | |
41 | const struct uacpi_op_spec *uacpi_get_op_spec(uacpi_aml_op op) |
42 | { |
43 | if (op > 0xFF) |
44 | return &ext_opcode_table[ext_op_to_idx[_(op)]]; |
45 | |
46 | return &opcode_table[op]; |
47 | } |
48 | |
49 | #define PARSE_FIELD_ELEMENTS(parse_loop_pc) \ |
50 | /* Parse every field element found inside */ \ |
51 | UACPI_PARSE_OP_IF_HAS_DATA, 44, \ |
52 | /* Look at the first byte */ \ |
53 | UACPI_PARSE_OP_LOAD_IMM, 1, \ |
54 | \ |
55 | /* ReservedField := 0x00 PkgLength */ \ |
56 | UACPI_PARSE_OP_IF_EQUALS, 0x00, 3, \ |
57 | UACPI_PARSE_OP_PKGLEN, \ |
58 | UACPI_PARSE_OP_JMP, parse_loop_pc, \ |
59 | \ |
60 | /* AccessField := 0x01 AccessType AccessAttrib */ \ |
61 | UACPI_PARSE_OP_IF_EQUALS, 0x01, 6, \ |
62 | UACPI_PARSE_OP_LOAD_IMM, 1, \ |
63 | UACPI_PARSE_OP_LOAD_IMM, 1, \ |
64 | UACPI_PARSE_OP_JMP, parse_loop_pc, \ |
65 | \ |
66 | /* ConnectField := <0x02 NameString> | <0x02 BufferData> */ \ |
67 | UACPI_PARSE_OP_IF_EQUALS, 0x02, 5, \ |
68 | UACPI_PARSE_OP_TERM_ARG_UNWRAP_INTERNAL, \ |
69 | UACPI_PARSE_OP_TYPECHECK, UACPI_OBJECT_BUFFER, \ |
70 | UACPI_PARSE_OP_JMP, parse_loop_pc, \ |
71 | \ |
72 | /* ExtendedAccessField := 0x03 AccessType ExtendedAccessAttrib \ |
73 | * AccessLength */ \ |
74 | UACPI_PARSE_OP_IF_EQUALS, 0x03, 8, \ |
75 | UACPI_PARSE_OP_LOAD_IMM, 1, \ |
76 | UACPI_PARSE_OP_LOAD_IMM, 1, \ |
77 | UACPI_PARSE_OP_LOAD_IMM, 1, \ |
78 | UACPI_PARSE_OP_JMP, parse_loop_pc, \ |
79 | \ |
80 | /* NamedField := NameSeg PkgLength */ \ |
81 | \ |
82 | /* \ |
83 | * Discard the immediate, as it's the first byte of the \ |
84 | * nameseg. We don't need it. \ |
85 | */ \ |
86 | UACPI_PARSE_OP_ITEM_POP, \ |
87 | UACPI_PARSE_OP_AML_PC_DECREMENT, \ |
88 | UACPI_PARSE_OP_CREATE_NAMESTRING, \ |
89 | UACPI_PARSE_OP_PKGLEN, \ |
90 | UACPI_PARSE_OP_OBJECT_ALLOC_TYPED, UACPI_OBJECT_FIELD_UNIT, \ |
91 | UACPI_PARSE_OP_JMP, parse_loop_pc, \ |
92 | \ |
93 | UACPI_PARSE_OP_INVOKE_HANDLER, \ |
94 | UACPI_PARSE_OP_END |
95 | |
96 | uacpi_u8 uacpi_field_op_decode_ops[] = { |
97 | UACPI_PARSE_OP_TRACKED_PKGLEN, |
98 | UACPI_PARSE_OP_EXISTING_NAMESTRING, |
99 | UACPI_PARSE_OP_LOAD_IMM, 1, |
100 | PARSE_FIELD_ELEMENTS(4), |
101 | }; |
102 | |
103 | uacpi_u8 uacpi_bank_field_op_decode_ops[] = { |
104 | UACPI_PARSE_OP_TRACKED_PKGLEN, |
105 | UACPI_PARSE_OP_EXISTING_NAMESTRING, |
106 | UACPI_PARSE_OP_EXISTING_NAMESTRING, |
107 | UACPI_PARSE_OP_OPERAND, |
108 | UACPI_PARSE_OP_LOAD_IMM, 1, |
109 | PARSE_FIELD_ELEMENTS(6), |
110 | }; |
111 | |
112 | uacpi_u8 uacpi_index_field_op_decode_ops[] = { |
113 | UACPI_PARSE_OP_TRACKED_PKGLEN, |
114 | UACPI_PARSE_OP_EXISTING_NAMESTRING, |
115 | UACPI_PARSE_OP_EXISTING_NAMESTRING, |
116 | UACPI_PARSE_OP_LOAD_IMM, 1, |
117 | PARSE_FIELD_ELEMENTS(5), |
118 | }; |
119 | |
120 | uacpi_u8 uacpi_load_op_decode_ops[] = { |
121 | // Storage for the scope pointer, this is left as 0 in case of errors |
122 | UACPI_PARSE_OP_LOAD_ZERO_IMM, |
123 | UACPI_PARSE_OP_OBJECT_ALLOC_TYPED, UACPI_OBJECT_METHOD, |
124 | UACPI_PARSE_OP_TERM_ARG_UNWRAP_INTERNAL, |
125 | UACPI_PARSE_OP_TARGET, |
126 | |
127 | /* |
128 | * Invoke the handler here to initialize the table. If this fails, it's |
129 | * expected to keep the item 0 as NULL, which is checked below to return |
130 | * false to the caller of Load. |
131 | */ |
132 | UACPI_PARSE_OP_INVOKE_HANDLER, |
133 | UACPI_PARSE_OP_IF_NULL, 0, 3, |
134 | UACPI_PARSE_OP_LOAD_FALSE_OBJECT, |
135 | UACPI_PARSE_OP_JMP, 15, |
136 | |
137 | UACPI_PARSE_OP_LOAD_TRUE_OBJECT, |
138 | UACPI_PARSE_OP_DISPATCH_TABLE_LOAD, |
139 | |
140 | /* |
141 | * Invoke the handler a second time to initialize any AML GPE handlers that |
142 | * might've been loaded from this table. |
143 | */ |
144 | UACPI_PARSE_OP_INVOKE_HANDLER, |
145 | UACPI_PARSE_OP_STORE_TO_TARGET, 3, |
146 | UACPI_PARSE_OP_OBJECT_TRANSFER_TO_PREV, |
147 | UACPI_PARSE_OP_END, |
148 | }; |
149 | |
150 | uacpi_u8 uacpi_load_table_op_decode_ops[] = { |
151 | // Storage for the scope pointer, this is left as 0 in case of errors |
152 | UACPI_PARSE_OP_LOAD_ZERO_IMM, |
153 | UACPI_PARSE_OP_OBJECT_ALLOC_TYPED, UACPI_OBJECT_METHOD, |
154 | // Storage for the target pointer, this is left as 0 if none was requested |
155 | UACPI_PARSE_OP_LOAD_ZERO_IMM, |
156 | |
157 | UACPI_PARSE_OP_LOAD_INLINE_IMM, 1, 5, |
158 | UACPI_PARSE_OP_IF_NOT_NULL, 3, 5, |
159 | UACPI_PARSE_OP_STRING, |
160 | UACPI_PARSE_OP_IMM_DECREMENT, 3, |
161 | UACPI_PARSE_OP_JMP, 7, |
162 | UACPI_PARSE_OP_TERM_ARG_UNWRAP_INTERNAL, |
163 | |
164 | /* |
165 | * Invoke the handler here to initialize the table. If this fails, it's |
166 | * expected to keep the item 0 as NULL, which is checked below to return |
167 | * false to the caller of Load. |
168 | */ |
169 | UACPI_PARSE_OP_INVOKE_HANDLER, |
170 | UACPI_PARSE_OP_IF_NULL, 0, 3, |
171 | UACPI_PARSE_OP_LOAD_FALSE_OBJECT, |
172 | UACPI_PARSE_OP_OBJECT_TRANSFER_TO_PREV, |
173 | UACPI_PARSE_OP_END, |
174 | |
175 | UACPI_PARSE_OP_LOAD_TRUE_OBJECT, |
176 | UACPI_PARSE_OP_DISPATCH_TABLE_LOAD, |
177 | |
178 | /* |
179 | * Invoke the handler a second time to block the store to target in case |
180 | * the load above failed, as well as do any AML GPE handler initialization. |
181 | */ |
182 | UACPI_PARSE_OP_INVOKE_HANDLER, |
183 | |
184 | // If we were given a target to store to, do the store |
185 | UACPI_PARSE_OP_IF_NOT_NULL, 2, 3, |
186 | UACPI_PARSE_OP_STORE_TO_TARGET_INDIRECT, 2, 9, |
187 | |
188 | UACPI_PARSE_OP_OBJECT_TRANSFER_TO_PREV, |
189 | UACPI_PARSE_OP_END, |
190 | }; |
191 | |
192 | #define POP(x) UACPI_PARSE_OP_##x |
193 | |
194 | static |
195 | const uacpi_char *const pop_names[UACPI_PARSE_OP_MAX + 1] = { |
196 | [POP(END)] = "<END-OF-OP>" , |
197 | [POP(SKIP_WITH_WARN_IF_NULL)] = "SKIP_WITH_WARN_IF_NULL" , |
198 | [POP(SIMPLE_NAME)] = "SIMPLE_NAME" , |
199 | [POP(SUPERNAME)] = "SUPERNAME" , |
200 | [POP(SUPERNAME_OR_UNRESOLVED)] = "SUPERNAME_OR_UNRESOLVED" , |
201 | [POP(TERM_ARG)] = "TERM_ARG" , |
202 | [POP(TERM_ARG_UNWRAP_INTERNAL)] = "TERM_ARG_UNWRAP_INTERNAL" , |
203 | [POP(TERM_ARG_OR_NAMED_OBJECT)] = "TERM_ARG_OR_NAMED_OBJECT" , |
204 | [POP(TERM_ARG_OR_NAMED_OBJECT_OR_UNRESOLVED)] = "TERM_ARG_OR_NAMED_OBJECT_OR_UNRESOLVED" , |
205 | [POP(OPERAND)] = "OPERAND" , |
206 | [POP(STRING)] = "STRING" , |
207 | [POP(COMPUTATIONAL_DATA)] = "COMPUTATIONAL_DATA" , |
208 | [POP(TARGET)] = "TARGET" , |
209 | [POP(PKGLEN)] = "PKGLEN" , |
210 | [POP(TRACKED_PKGLEN)] = "TRACKED_PKGLEN" , |
211 | [POP(CREATE_NAMESTRING)] = "CREATE_NAMESTRING" , |
212 | [POP(CREATE_NAMESTRING_OR_NULL_IF_LOAD)] = "CREATE_NAMESTRING_OR_NULL_IF_LOAD" , |
213 | [POP(EXISTING_NAMESTRING)] = "EXISTING_NAMESTRING" , |
214 | [POP(EXISTING_NAMESTRING_OR_NULL)] = "EXISTING_NAMESTRING_OR_NULL" , |
215 | [POP(EXISTING_NAMESTRING_OR_NULL_IF_LOAD)] = "EXISTING_NAMESTRING_OR_NULL_IF_LOAD" , |
216 | [POP(INVOKE_HANDLER)] = "INVOKE_HANDLER" , |
217 | [POP(OBJECT_ALLOC)] = "OBJECT_ALLOC" , |
218 | [POP(EMPTY_OBJECT_ALLOC)] = "EMPTY_OBJECT_ALLOC" , |
219 | [POP(OBJECT_CONVERT_TO_SHALLOW_COPY)] = "OBJECT_CONVERT_TO_SHALLOW_COPY" , |
220 | [POP(OBJECT_CONVERT_TO_DEEP_COPY)] = "OBJECT_CONVERT_TO_DEEP_COPY" , |
221 | [POP(OBJECT_ALLOC_TYPED)] = "OBJECT_ALLOC_TYPED" , |
222 | [POP(RECORD_AML_PC)] = "RECORD_AML_PC" , |
223 | [POP(LOAD_INLINE_IMM_AS_OBJECT)] = "LOAD_INLINE_IMM_AS_OBJECT" , |
224 | [POP(LOAD_INLINE_IMM)] = "LOAD_INLINE_IMM" , |
225 | [POP(LOAD_ZERO_IMM)] = "LOAD_ZERO_IMM" , |
226 | [POP(LOAD_IMM)] = "LOAD_IMM" , |
227 | [POP(LOAD_IMM_AS_OBJECT)] = "LOAD_IMM_AS_OBJECT" , |
228 | [POP(LOAD_FALSE_OBJECT)] = "LOAD_FALSE_OBJECT" , |
229 | [POP(LOAD_TRUE_OBJECT)] = "LOAD_TRUE_OBJECT" , |
230 | [POP(TRUNCATE_NUMBER)] = "TRUNCATE_NUMBER" , |
231 | [POP(TYPECHECK)] = "TYPECHECK" , |
232 | [POP(INSTALL_NAMESPACE_NODE)] = "INSTALL_NAMESPACE_NODE" , |
233 | [POP(OBJECT_TRANSFER_TO_PREV)] = "OBJECT_TRANSFER_TO_PREV" , |
234 | [POP(OBJECT_COPY_TO_PREV)] = "OBJECT_COPY_TO_PREV" , |
235 | [POP(STORE_TO_TARGET)] = "STORE_TO_TARGET" , |
236 | [POP(STORE_TO_TARGET_INDIRECT)] = "STORE_TO_TARGET_INDIRECT" , |
237 | [POP(UNREACHABLE)] = "UNREACHABLE" , |
238 | [POP(BAD_OPCODE)] = "BAD_OPCODE" , |
239 | [POP(AML_PC_DECREMENT)] = "AML_PC_DECREMENT" , |
240 | [POP(IMM_DECREMENT)] = "IMM_DECREMENT" , |
241 | [POP(ITEM_POP)] = "ITEM_POP" , |
242 | [POP(DISPATCH_METHOD_CALL)] = "DISPATCH_METHOD_CALL" , |
243 | [POP(DISPATCH_TABLE_LOAD)] = "DISPATCH_TABLE_LOAD" , |
244 | [POP(CONVERT_NAMESTRING)] = "CONVERT_NAMESTRING" , |
245 | [POP(IF_HAS_DATA)] = "IF_HAS_DATA" , |
246 | [POP(IF_NULL)] = "IF_NULL" , |
247 | [POP(IF_NOT_NULL)] = "IF_NOT_NULL" , |
248 | [POP(IF_EQUALS)] = "IF_EQUALS" , |
249 | [POP(JMP)] = "JMP" , |
250 | }; |
251 | |
252 | const uacpi_char *uacpi_parse_op_to_string(enum uacpi_parse_op op) |
253 | { |
254 | if (uacpi_unlikely(op > UACPI_PARSE_OP_MAX)) |
255 | return "<INVALID-OP>" ; |
256 | |
257 | return pop_names[op]; |
258 | } |
259 | |