File: /usr/src/linux/drivers/acpi/executer/exmisc.c
1
2 /******************************************************************************
3 *
4 * Module Name: exmisc - ACPI AML (p-code) execution - specific opcodes
5 * $Revision: 83 $
6 *
7 *****************************************************************************/
8
9 /*
10 * Copyright (C) 2000, 2001 R. Byron Moore
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License as published by
14 * the Free Software Foundation; either version 2 of the License, or
15 * (at your option) any later version.
16 *
17 * This program is distributed in the hope that it will be useful,
18 * but WITHOUT ANY WARRANTY; without even the implied warranty of
19 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
20 * GNU General Public License for more details.
21 *
22 * You should have received a copy of the GNU General Public License
23 * along with this program; if not, write to the Free Software
24 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
25 */
26
27
28 #include "acpi.h"
29 #include "acparser.h"
30 #include "acinterp.h"
31 #include "amlcode.h"
32 #include "acdispat.h"
33
34
35 #define _COMPONENT ACPI_EXECUTER
36 MODULE_NAME ("exmisc")
37
38
39 /*******************************************************************************
40 *
41 * FUNCTION: Acpi_ex_triadic
42 *
43 * PARAMETERS: Opcode - The opcode to be executed
44 * Walk_state - Current walk state
45 * Return_desc - Where to store the return object
46 *
47 * RETURN: Status
48 *
49 * DESCRIPTION: Execute Triadic operator (3 operands)
50 *
51 * ALLOCATION: Deletes one operand descriptor -- other remains on stack
52 *
53 ******************************************************************************/
54
55 acpi_status
56 acpi_ex_triadic (
57 u16 opcode,
58 acpi_walk_state *walk_state,
59 acpi_operand_object **return_desc)
60 {
61 acpi_operand_object **operand = &walk_state->operands[0];
62 acpi_operand_object *ret_desc = NULL;
63 acpi_operand_object *tmp_desc;
64 ACPI_SIGNAL_FATAL_INFO *fatal;
65 acpi_status status = AE_OK;
66
67
68 FUNCTION_TRACE ("Ex_triadic");
69
70
71 #define obj_desc1 operand[0]
72 #define obj_desc2 operand[1]
73 #define res_desc operand[2]
74
75
76 switch (opcode) {
77
78 case AML_FATAL_OP:
79
80 /* Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg */
81
82 ACPI_DEBUG_PRINT ((ACPI_DB_INFO,
83 "Fatal_op: Type %x Code %x Arg %x <<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
84 (u32) obj_desc1->integer.value, (u32) obj_desc2->integer.value,
85 (u32) res_desc->integer.value));
86
87
88 fatal = ACPI_MEM_ALLOCATE (sizeof (ACPI_SIGNAL_FATAL_INFO));
89 if (fatal) {
90 fatal->type = (u32) obj_desc1->integer.value;
91 fatal->code = (u32) obj_desc2->integer.value;
92 fatal->argument = (u32) res_desc->integer.value;
93 }
94
95 /*
96 * Signal the OS
97 */
98 acpi_os_signal (ACPI_SIGNAL_FATAL, fatal);
99
100 /* Might return while OS is shutting down */
101
102 ACPI_MEM_FREE (fatal);
103 break;
104
105
106 case AML_MID_OP:
107
108 /* Def_mid := Mid_op Source Index Length Result */
109
110 /* Create the internal return object (string or buffer) */
111
112 break;
113
114
115 case AML_INDEX_OP:
116
117 /* Def_index := Index_op Source Index Destination */
118
119 /* Create the internal return object */
120
121 ret_desc = acpi_ut_create_internal_object (INTERNAL_TYPE_REFERENCE);
122 if (!ret_desc) {
123 status = AE_NO_MEMORY;
124 goto cleanup;
125 }
126
127 /*
128 * At this point, the Obj_desc1 operand is either a Package or a Buffer
129 */
130 if (obj_desc1->common.type == ACPI_TYPE_PACKAGE) {
131 /* Object to be indexed is a Package */
132
133 if (obj_desc2->integer.value >= obj_desc1->package.count) {
134 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value beyond package end\n"));
135 status = AE_AML_PACKAGE_LIMIT;
136 goto cleanup;
137 }
138
139 if ((res_desc->common.type == INTERNAL_TYPE_REFERENCE) &&
140 (res_desc->reference.opcode == AML_ZERO_OP)) {
141 /*
142 * There is no actual result descriptor (the Zero_op Result
143 * descriptor is a placeholder), so just delete the placeholder and
144 * return a reference to the package element
145 */
146 acpi_ut_remove_reference (res_desc);
147 }
148
149 else {
150 /*
151 * Each element of the package is an internal object. Get the one
152 * we are after.
153 */
154 tmp_desc = obj_desc1->package.elements[obj_desc2->integer.value];
155 ret_desc->reference.opcode = AML_INDEX_OP;
156 ret_desc->reference.target_type = tmp_desc->common.type;
157 ret_desc->reference.object = tmp_desc;
158
159 status = acpi_ex_store (ret_desc, res_desc, walk_state);
160 ret_desc->reference.object = NULL;
161 }
162
163 /*
164 * The local return object must always be a reference to the package element,
165 * not the element itself.
166 */
167 ret_desc->reference.opcode = AML_INDEX_OP;
168 ret_desc->reference.target_type = ACPI_TYPE_PACKAGE;
169 ret_desc->reference.where = &obj_desc1->package.elements[obj_desc2->integer.value];
170 }
171
172 else {
173 /* Object to be indexed is a Buffer */
174
175 if (obj_desc2->integer.value >= obj_desc1->buffer.length) {
176 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Index value beyond end of buffer\n"));
177 status = AE_AML_BUFFER_LIMIT;
178 goto cleanup;
179 }
180
181 ret_desc->reference.opcode = AML_INDEX_OP;
182 ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
183 ret_desc->reference.object = obj_desc1;
184 ret_desc->reference.offset = (u32) obj_desc2->integer.value;
185
186 status = acpi_ex_store (ret_desc, res_desc, walk_state);
187 }
188 break;
189 }
190
191
192 cleanup:
193
194 /* Always delete operands */
195
196 acpi_ut_remove_reference (obj_desc1);
197 acpi_ut_remove_reference (obj_desc2);
198
199 /* Delete return object on error */
200
201 if (ACPI_FAILURE (status)) {
202 acpi_ut_remove_reference (res_desc);
203
204 if (ret_desc) {
205 acpi_ut_remove_reference (ret_desc);
206 ret_desc = NULL;
207 }
208 }
209
210 /* Set the return object and exit */
211
212 *return_desc = ret_desc;
213 return_ACPI_STATUS (status);
214 }
215
216
217 /*******************************************************************************
218 *
219 * FUNCTION: Acpi_ex_hexadic
220 *
221 * PARAMETERS: Opcode - The opcode to be executed
222 * Walk_state - Current walk state
223 * Return_desc - Where to store the return object
224 *
225 * RETURN: Status
226 *
227 * DESCRIPTION: Execute Match operator
228 *
229 ******************************************************************************/
230
231 acpi_status
232 acpi_ex_hexadic (
233 u16 opcode,
234 acpi_walk_state *walk_state,
235 acpi_operand_object **return_desc)
236 {
237 acpi_operand_object **operand = &walk_state->operands[0];
238 acpi_operand_object *ret_desc = NULL;
239 acpi_status status = AE_OK;
240 u32 index;
241 u32 match_value = (u32) -1;
242
243
244 FUNCTION_TRACE ("Ex_hexadic");
245
246 #define pkg_desc operand[0]
247 #define op1_desc operand[1]
248 #define V1_desc operand[2]
249 #define op2_desc operand[3]
250 #define V2_desc operand[4]
251 #define start_desc operand[5]
252
253
254 switch (opcode) {
255
256 case AML_MATCH_OP:
257
258 /* Validate match comparison sub-opcodes */
259
260 if ((op1_desc->integer.value > MAX_MATCH_OPERATOR) ||
261 (op2_desc->integer.value > MAX_MATCH_OPERATOR)) {
262 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "operation encoding out of range\n"));
263 status = AE_AML_OPERAND_VALUE;
264 goto cleanup;
265 }
266
267 index = (u32) start_desc->integer.value;
268 if (index >= (u32) pkg_desc->package.count) {
269 ACPI_DEBUG_PRINT ((ACPI_DB_ERROR, "Start position value out of range\n"));
270 status = AE_AML_PACKAGE_LIMIT;
271 goto cleanup;
272 }
273
274 ret_desc = acpi_ut_create_internal_object (ACPI_TYPE_INTEGER);
275 if (!ret_desc) {
276 status = AE_NO_MEMORY;
277 goto cleanup;
278
279 }
280
281 /*
282 * Examine each element until a match is found. Within the loop,
283 * "continue" signifies that the current element does not match
284 * and the next should be examined.
285 * Upon finding a match, the loop will terminate via "break" at
286 * the bottom. If it terminates "normally", Match_value will be -1
287 * (its initial value) indicating that no match was found. When
288 * returned as a Number, this will produce the Ones value as specified.
289 */
290 for ( ; index < pkg_desc->package.count; ++index) {
291 /*
292 * Treat any NULL or non-numeric elements as non-matching.
293 * TBD [Unhandled] - if an element is a Name,
294 * should we examine its value?
295 */
296 if (!pkg_desc->package.elements[index] ||
297 ACPI_TYPE_INTEGER != pkg_desc->package.elements[index]->common.type) {
298 continue;
299 }
300
301 /*
302 * Within these switch statements:
303 * "break" (exit from the switch) signifies a match;
304 * "continue" (proceed to next iteration of enclosing
305 * "for" loop) signifies a non-match.
306 */
307 switch (op1_desc->integer.value) {
308
309 case MATCH_MTR: /* always true */
310
311 break;
312
313
314 case MATCH_MEQ: /* true if equal */
315
316 if (pkg_desc->package.elements[index]->integer.value
317 != V1_desc->integer.value) {
318 continue;
319 }
320 break;
321
322
323 case MATCH_MLE: /* true if less than or equal */
324
325 if (pkg_desc->package.elements[index]->integer.value
326 > V1_desc->integer.value) {
327 continue;
328 }
329 break;
330
331
332 case MATCH_MLT: /* true if less than */
333
334 if (pkg_desc->package.elements[index]->integer.value
335 >= V1_desc->integer.value) {
336 continue;
337 }
338 break;
339
340
341 case MATCH_MGE: /* true if greater than or equal */
342
343 if (pkg_desc->package.elements[index]->integer.value
344 < V1_desc->integer.value) {
345 continue;
346 }
347 break;
348
349
350 case MATCH_MGT: /* true if greater than */
351
352 if (pkg_desc->package.elements[index]->integer.value
353 <= V1_desc->integer.value) {
354 continue;
355 }
356 break;
357
358
359 default: /* undefined */
360
361 continue;
362 }
363
364
365 switch(op2_desc->integer.value) {
366
367 case MATCH_MTR:
368
369 break;
370
371
372 case MATCH_MEQ:
373
374 if (pkg_desc->package.elements[index]->integer.value
375 != V2_desc->integer.value) {
376 continue;
377 }
378 break;
379
380
381 case MATCH_MLE:
382
383 if (pkg_desc->package.elements[index]->integer.value
384 > V2_desc->integer.value) {
385 continue;
386 }
387 break;
388
389
390 case MATCH_MLT:
391
392 if (pkg_desc->package.elements[index]->integer.value
393 >= V2_desc->integer.value) {
394 continue;
395 }
396 break;
397
398
399 case MATCH_MGE:
400
401 if (pkg_desc->package.elements[index]->integer.value
402 < V2_desc->integer.value) {
403 continue;
404 }
405 break;
406
407
408 case MATCH_MGT:
409
410 if (pkg_desc->package.elements[index]->integer.value
411 <= V2_desc->integer.value) {
412 continue;
413 }
414 break;
415
416
417 default:
418
419 continue;
420 }
421
422 /* Match found: exit from loop */
423
424 match_value = index;
425 break;
426 }
427
428 /* Match_value is the return value */
429
430 ret_desc->integer.value = match_value;
431 break;
432
433 }
434
435
436 cleanup:
437
438 /* Free the operands */
439
440 acpi_ut_remove_reference (start_desc);
441 acpi_ut_remove_reference (V2_desc);
442 acpi_ut_remove_reference (op2_desc);
443 acpi_ut_remove_reference (V1_desc);
444 acpi_ut_remove_reference (op1_desc);
445 acpi_ut_remove_reference (pkg_desc);
446
447
448 /* Delete return object on error */
449
450 if (ACPI_FAILURE (status) &&
451 (ret_desc)) {
452 acpi_ut_remove_reference (ret_desc);
453 ret_desc = NULL;
454 }
455
456
457 /* Set the return object and exit */
458
459 *return_desc = ret_desc;
460 return_ACPI_STATUS (status);
461 }
462