1 | /****************************************************************************** |
2 | * |
3 | * Module Name: exoparg6 - AML execution - opcodes with 6 arguments |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, 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 | #include "acpi.h" |
45 | #include "accommon.h" |
46 | #include "acinterp.h" |
47 | #include "acparser.h" |
48 | #include "amlcode.h" |
49 | |
50 | |
51 | #define _COMPONENT ACPI_EXECUTER |
52 | ACPI_MODULE_NAME ("exoparg6" ) |
53 | |
54 | |
55 | /*! |
56 | * Naming convention for AML interpreter execution routines. |
57 | * |
58 | * The routines that begin execution of AML opcodes are named with a common |
59 | * convention based upon the number of arguments, the number of target operands, |
60 | * and whether or not a value is returned: |
61 | * |
62 | * AcpiExOpcode_xA_yT_zR |
63 | * |
64 | * Where: |
65 | * |
66 | * xA - ARGUMENTS: The number of arguments (input operands) that are |
67 | * required for this opcode type (1 through 6 args). |
68 | * yT - TARGETS: The number of targets (output operands) that are required |
69 | * for this opcode type (0, 1, or 2 targets). |
70 | * zR - RETURN VALUE: Indicates whether this opcode type returns a value |
71 | * as the function return (0 or 1). |
72 | * |
73 | * The AcpiExOpcode* functions are called via the Dispatcher component with |
74 | * fully resolved operands. |
75 | !*/ |
76 | |
77 | /* Local prototypes */ |
78 | |
79 | static BOOLEAN |
80 | AcpiExDoMatch ( |
81 | UINT32 MatchOp, |
82 | ACPI_OPERAND_OBJECT *PackageObj, |
83 | ACPI_OPERAND_OBJECT *MatchObj); |
84 | |
85 | |
86 | /******************************************************************************* |
87 | * |
88 | * FUNCTION: AcpiExDoMatch |
89 | * |
90 | * PARAMETERS: MatchOp - The AML match operand |
91 | * PackageObj - Object from the target package |
92 | * MatchObj - Object to be matched |
93 | * |
94 | * RETURN: TRUE if the match is successful, FALSE otherwise |
95 | * |
96 | * DESCRIPTION: Implements the low-level match for the ASL Match operator. |
97 | * Package elements will be implicitly converted to the type of |
98 | * the match object (Integer/Buffer/String). |
99 | * |
100 | ******************************************************************************/ |
101 | |
102 | static BOOLEAN |
103 | AcpiExDoMatch ( |
104 | UINT32 MatchOp, |
105 | ACPI_OPERAND_OBJECT *PackageObj, |
106 | ACPI_OPERAND_OBJECT *MatchObj) |
107 | { |
108 | BOOLEAN LogicalResult = TRUE; |
109 | ACPI_STATUS Status; |
110 | |
111 | |
112 | /* |
113 | * Note: Since the PackageObj/MatchObj ordering is opposite to that of |
114 | * the standard logical operators, we have to reverse them when we call |
115 | * DoLogicalOp in order to make the implicit conversion rules work |
116 | * correctly. However, this means we have to flip the entire equation |
117 | * also. A bit ugly perhaps, but overall, better than fussing the |
118 | * parameters around at runtime, over and over again. |
119 | * |
120 | * Below, P[i] refers to the package element, M refers to the Match object. |
121 | */ |
122 | switch (MatchOp) |
123 | { |
124 | case MATCH_MTR: |
125 | |
126 | /* Always true */ |
127 | |
128 | break; |
129 | |
130 | case MATCH_MEQ: |
131 | /* |
132 | * True if equal: (P[i] == M) |
133 | * Change to: (M == P[i]) |
134 | */ |
135 | Status = AcpiExDoLogicalOp ( |
136 | AML_LEQUAL_OP, MatchObj, PackageObj, &LogicalResult); |
137 | if (ACPI_FAILURE (Status)) |
138 | { |
139 | return (FALSE); |
140 | } |
141 | break; |
142 | |
143 | case MATCH_MLE: |
144 | /* |
145 | * True if less than or equal: (P[i] <= M) (P[i] NotGreater than M) |
146 | * Change to: (M >= P[i]) (M NotLess than P[i]) |
147 | */ |
148 | Status = AcpiExDoLogicalOp ( |
149 | AML_LLESS_OP, MatchObj, PackageObj, &LogicalResult); |
150 | if (ACPI_FAILURE (Status)) |
151 | { |
152 | return (FALSE); |
153 | } |
154 | LogicalResult = (BOOLEAN) !LogicalResult; |
155 | break; |
156 | |
157 | case MATCH_MLT: |
158 | /* |
159 | * True if less than: (P[i] < M) |
160 | * Change to: (M > P[i]) |
161 | */ |
162 | Status = AcpiExDoLogicalOp ( |
163 | AML_LGREATER_OP, MatchObj, PackageObj, &LogicalResult); |
164 | if (ACPI_FAILURE (Status)) |
165 | { |
166 | return (FALSE); |
167 | } |
168 | break; |
169 | |
170 | case MATCH_MGE: |
171 | /* |
172 | * True if greater than or equal: (P[i] >= M) (P[i] NotLess than M) |
173 | * Change to: (M <= P[i]) (M NotGreater than P[i]) |
174 | */ |
175 | Status = AcpiExDoLogicalOp ( |
176 | AML_LGREATER_OP, MatchObj, PackageObj, &LogicalResult); |
177 | if (ACPI_FAILURE (Status)) |
178 | { |
179 | return (FALSE); |
180 | } |
181 | LogicalResult = (BOOLEAN)!LogicalResult; |
182 | break; |
183 | |
184 | case MATCH_MGT: |
185 | /* |
186 | * True if greater than: (P[i] > M) |
187 | * Change to: (M < P[i]) |
188 | */ |
189 | Status = AcpiExDoLogicalOp ( |
190 | AML_LLESS_OP, MatchObj, PackageObj, &LogicalResult); |
191 | if (ACPI_FAILURE (Status)) |
192 | { |
193 | return (FALSE); |
194 | } |
195 | break; |
196 | |
197 | default: |
198 | |
199 | /* Undefined */ |
200 | |
201 | return (FALSE); |
202 | } |
203 | |
204 | return (LogicalResult); |
205 | } |
206 | |
207 | |
208 | /******************************************************************************* |
209 | * |
210 | * FUNCTION: AcpiExOpcode_6A_0T_1R |
211 | * |
212 | * PARAMETERS: WalkState - Current walk state |
213 | * |
214 | * RETURN: Status |
215 | * |
216 | * DESCRIPTION: Execute opcode with 6 arguments, no target, and a return value |
217 | * |
218 | ******************************************************************************/ |
219 | |
220 | ACPI_STATUS |
221 | AcpiExOpcode_6A_0T_1R ( |
222 | ACPI_WALK_STATE *WalkState) |
223 | { |
224 | ACPI_OPERAND_OBJECT **Operand = &WalkState->Operands[0]; |
225 | ACPI_OPERAND_OBJECT *ReturnDesc = NULL; |
226 | ACPI_STATUS Status = AE_OK; |
227 | UINT64 Index; |
228 | ACPI_OPERAND_OBJECT *ThisElement; |
229 | |
230 | |
231 | ACPI_FUNCTION_TRACE_STR (ExOpcode_6A_0T_1R, |
232 | AcpiPsGetOpcodeName (WalkState->Opcode)); |
233 | |
234 | |
235 | switch (WalkState->Opcode) |
236 | { |
237 | case AML_MATCH_OP: |
238 | /* |
239 | * Match (SearchPkg[0], MatchOp1[1], MatchObj1[2], |
240 | * MatchOp2[3], MatchObj2[4], StartIndex[5]) |
241 | */ |
242 | |
243 | /* Validate both Match Term Operators (MTR, MEQ, etc.) */ |
244 | |
245 | if ((Operand[1]->Integer.Value > MAX_MATCH_OPERATOR) || |
246 | (Operand[3]->Integer.Value > MAX_MATCH_OPERATOR)) |
247 | { |
248 | ACPI_ERROR ((AE_INFO, "Match operator out of range" )); |
249 | Status = AE_AML_OPERAND_VALUE; |
250 | goto Cleanup; |
251 | } |
252 | |
253 | /* Get the package StartIndex, validate against the package length */ |
254 | |
255 | Index = Operand[5]->Integer.Value; |
256 | if (Index >= Operand[0]->Package.Count) |
257 | { |
258 | ACPI_ERROR ((AE_INFO, |
259 | "Index (0x%8.8X%8.8X) beyond package end (0x%X)" , |
260 | ACPI_FORMAT_UINT64 (Index), Operand[0]->Package.Count)); |
261 | Status = AE_AML_PACKAGE_LIMIT; |
262 | goto Cleanup; |
263 | } |
264 | |
265 | /* Create an integer for the return value */ |
266 | /* Default return value is ACPI_UINT64_MAX if no match found */ |
267 | |
268 | ReturnDesc = AcpiUtCreateIntegerObject (ACPI_UINT64_MAX); |
269 | if (!ReturnDesc) |
270 | { |
271 | Status = AE_NO_MEMORY; |
272 | goto Cleanup; |
273 | |
274 | } |
275 | |
276 | /* |
277 | * Examine each element until a match is found. Both match conditions |
278 | * must be satisfied for a match to occur. Within the loop, |
279 | * "continue" signifies that the current element does not match |
280 | * and the next should be examined. |
281 | * |
282 | * Upon finding a match, the loop will terminate via "break" at |
283 | * the bottom. If it terminates "normally", MatchValue will be |
284 | * ACPI_UINT64_MAX (Ones) (its initial value) indicating that no |
285 | * match was found. |
286 | */ |
287 | for ( ; Index < Operand[0]->Package.Count; Index++) |
288 | { |
289 | /* Get the current package element */ |
290 | |
291 | ThisElement = Operand[0]->Package.Elements[Index]; |
292 | |
293 | /* Treat any uninitialized (NULL) elements as non-matching */ |
294 | |
295 | if (!ThisElement) |
296 | { |
297 | continue; |
298 | } |
299 | |
300 | /* |
301 | * Both match conditions must be satisfied. Execution of a continue |
302 | * (proceed to next iteration of enclosing for loop) signifies a |
303 | * non-match. |
304 | */ |
305 | if (!AcpiExDoMatch ((UINT32) Operand[1]->Integer.Value, |
306 | ThisElement, Operand[2])) |
307 | { |
308 | continue; |
309 | } |
310 | |
311 | if (!AcpiExDoMatch ((UINT32) Operand[3]->Integer.Value, |
312 | ThisElement, Operand[4])) |
313 | { |
314 | continue; |
315 | } |
316 | |
317 | /* Match found: Index is the return value */ |
318 | |
319 | ReturnDesc->Integer.Value = Index; |
320 | break; |
321 | } |
322 | break; |
323 | |
324 | case AML_LOAD_TABLE_OP: |
325 | |
326 | Status = AcpiExLoadTableOp (WalkState, &ReturnDesc); |
327 | break; |
328 | |
329 | default: |
330 | |
331 | ACPI_ERROR ((AE_INFO, "Unknown AML opcode 0x%X" , |
332 | WalkState->Opcode)); |
333 | |
334 | Status = AE_AML_BAD_OPCODE; |
335 | goto Cleanup; |
336 | } |
337 | |
338 | |
339 | Cleanup: |
340 | |
341 | /* Delete return object on error */ |
342 | |
343 | if (ACPI_FAILURE (Status)) |
344 | { |
345 | AcpiUtRemoveReference (ReturnDesc); |
346 | } |
347 | |
348 | /* Save return object on success */ |
349 | |
350 | else |
351 | { |
352 | WalkState->ResultObj = ReturnDesc; |
353 | } |
354 | |
355 | return_ACPI_STATUS (Status); |
356 | } |
357 | |