2 /******************************************************************************
4 * Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes
7 *****************************************************************************/
10 * Copyright (C) 2000 R. Byron Moore
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.
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.
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
35 #define _COMPONENT INTERPRETER
36 MODULE_NAME ("ammisc")
39 /*******************************************************************************
41 * FUNCTION: Acpi_aml_exec_fatal
45 * RETURN: Status. If the OS returns from the OSD call, we just keep
48 * DESCRIPTION: Execute Fatal operator
50 * ACPI SPECIFICATION REFERENCES:
51 * Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg
52 * Fatal_type := Byte_data
53 * Fatal_code := DWord_data
54 * Fatal_arg := Term_arg=>Integer
56 ******************************************************************************/
60 ACPI_WALK_STATE *walk_state)
62 ACPI_OPERAND_OBJECT *type_desc;
63 ACPI_OPERAND_OBJECT *code_desc;
64 ACPI_OPERAND_OBJECT *arg_desc;
68 /* Resolve operands */
70 status = acpi_aml_resolve_operands (AML_FATAL_OP, WALK_OPERANDS, walk_state);
73 status |= acpi_ds_obj_stack_pop_object (&arg_desc, walk_state);
74 status |= acpi_ds_obj_stack_pop_object (&code_desc, walk_state);
75 status |= acpi_ds_obj_stack_pop_object (&type_desc, walk_state);
76 if (ACPI_FAILURE (status)) {
77 /* Invalid parameters on object stack */
83 /* Def_fatal := Fatal_op Fatal_type Fatal_code Fatal_arg */
87 * TBD: [Unhandled] call OSD interface to notify OS of fatal error
94 /* Free the operands */
96 acpi_cm_remove_reference (arg_desc);
97 acpi_cm_remove_reference (code_desc);
98 acpi_cm_remove_reference (type_desc);
101 /* If we get back from the OS call, we might as well keep going. */
103 REPORT_WARNING (("An AML \"fatal\" Opcode (Fatal_op) was executed\n"));
108 /*******************************************************************************
110 * FUNCTION: Acpi_aml_exec_index
116 * DESCRIPTION: Execute Index operator
118 * ALLOCATION: Deletes one operand descriptor -- other remains on stack
120 * ACPI SPECIFICATION REFERENCES:
121 * Def_index := Index_op Buff_pkg_obj Index_value Result
122 * Index_value := Term_arg=>Integer
123 * Name_string := <Root_char Name_path> | <Prefix_path Name_path>
124 * Result := Super_name
125 * Super_name := Name_string | Arg_obj | Local_obj | Debug_obj | Def_index
126 * Local4_op | Local5_op | Local6_op | Local7_op
128 ******************************************************************************/
131 acpi_aml_exec_index (
132 ACPI_WALK_STATE *walk_state,
133 ACPI_OPERAND_OBJECT **return_desc)
135 ACPI_OPERAND_OBJECT *obj_desc;
136 ACPI_OPERAND_OBJECT *idx_desc;
137 ACPI_OPERAND_OBJECT *res_desc;
138 ACPI_OPERAND_OBJECT *ret_desc = NULL;
139 ACPI_OPERAND_OBJECT *tmp_desc;
143 /* Resolve operands */
144 /* First operand can be either a package or a buffer */
146 status = acpi_aml_resolve_operands (AML_INDEX_OP, WALK_OPERANDS, walk_state);
147 /* Get all operands */
149 status |= acpi_ds_obj_stack_pop_object (&res_desc, walk_state);
150 status |= acpi_ds_obj_stack_pop_object (&idx_desc, walk_state);
151 status |= acpi_ds_obj_stack_pop_object (&obj_desc, walk_state);
152 if (ACPI_FAILURE (status)) {
153 /* Invalid parameters on object stack */
159 /* Create the internal return object */
161 ret_desc = acpi_cm_create_internal_object (INTERNAL_TYPE_REFERENCE);
163 status = AE_NO_MEMORY;
169 * At this point, the Obj_desc operand is either a Package or a Buffer
172 if (obj_desc->common.type == ACPI_TYPE_PACKAGE) {
173 /* Object to be indexed is a Package */
175 if (idx_desc->number.value >= obj_desc->package.count) {
176 status = AE_AML_PACKAGE_LIMIT;
180 if ((res_desc->common.type == INTERNAL_TYPE_REFERENCE) &&
181 (res_desc->reference.op_code == AML_ZERO_OP))
184 * There is no actual result descriptor (the Zero_op Result
185 * descriptor is a placeholder), so just delete the placeholder and
186 * return a reference to the package element
189 acpi_cm_remove_reference (res_desc);
194 * Each element of the package is an internal object. Get the one
198 tmp_desc = obj_desc->package.elements[idx_desc->number.value];
199 ret_desc->reference.op_code = AML_INDEX_OP;
200 ret_desc->reference.target_type = tmp_desc->common.type;
201 ret_desc->reference.object = tmp_desc;
203 status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
204 ret_desc->reference.object = NULL;
208 * The local return object must always be a reference to the package element,
209 * not the element itself.
211 ret_desc->reference.op_code = AML_INDEX_OP;
212 ret_desc->reference.target_type = ACPI_TYPE_PACKAGE;
213 ret_desc->reference.where = &obj_desc->package.elements[idx_desc->number.value];
217 /* Object to be indexed is a Buffer */
219 if (idx_desc->number.value >= obj_desc->buffer.length) {
220 status = AE_AML_BUFFER_LIMIT;
224 ret_desc->reference.op_code = AML_INDEX_OP;
225 ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
226 ret_desc->reference.object = obj_desc;
227 ret_desc->reference.offset = (u32) idx_desc->number.value;
229 status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
235 /* Always delete operands */
237 acpi_cm_remove_reference (obj_desc);
238 acpi_cm_remove_reference (idx_desc);
240 /* Delete return object on error */
242 if (ACPI_FAILURE (status)) {
243 acpi_cm_remove_reference (res_desc);
246 acpi_cm_remove_reference (ret_desc);
251 /* Set the return object and exit */
253 *return_desc = ret_desc;
258 /*******************************************************************************
260 * FUNCTION: Acpi_aml_exec_match
266 * DESCRIPTION: Execute Match operator
268 * ACPI SPECIFICATION REFERENCES:
269 * Def_match := Match_op Search_pkg Opcode1 Operand1
270 * Opcode2 Operand2 Start_index
271 * Opcode1 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT
272 * Opcode2 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT
273 * Operand1 := Term_arg=>Integer
274 * Operand2 := Term_arg=>Integer
275 * Search_pkg := Term_arg=>Package_object
276 * Start_index := Term_arg=>Integer
278 ******************************************************************************/
281 acpi_aml_exec_match (
282 ACPI_WALK_STATE *walk_state,
283 ACPI_OPERAND_OBJECT **return_desc)
285 ACPI_OPERAND_OBJECT *pkg_desc;
286 ACPI_OPERAND_OBJECT *op1_desc;
287 ACPI_OPERAND_OBJECT *V1_desc;
288 ACPI_OPERAND_OBJECT *op2_desc;
289 ACPI_OPERAND_OBJECT *V2_desc;
290 ACPI_OPERAND_OBJECT *start_desc;
291 ACPI_OPERAND_OBJECT *ret_desc = NULL;
294 u32 match_value = (u32) -1;
297 /* Resolve all operands */
299 status = acpi_aml_resolve_operands (AML_MATCH_OP, WALK_OPERANDS, walk_state);
300 /* Get all operands */
302 status |= acpi_ds_obj_stack_pop_object (&start_desc, walk_state);
303 status |= acpi_ds_obj_stack_pop_object (&V2_desc, walk_state);
304 status |= acpi_ds_obj_stack_pop_object (&op2_desc, walk_state);
305 status |= acpi_ds_obj_stack_pop_object (&V1_desc, walk_state);
306 status |= acpi_ds_obj_stack_pop_object (&op1_desc, walk_state);
307 status |= acpi_ds_obj_stack_pop_object (&pkg_desc, walk_state);
309 if (ACPI_FAILURE (status)) {
310 /* Invalid parameters on object stack */
315 /* Validate match comparison sub-opcodes */
317 if ((op1_desc->number.value > MAX_MATCH_OPERATOR) ||
318 (op2_desc->number.value > MAX_MATCH_OPERATOR))
320 status = AE_AML_OPERAND_VALUE;
324 index = (u32) start_desc->number.value;
325 if (index >= (u32) pkg_desc->package.count) {
326 status = AE_AML_PACKAGE_LIMIT;
330 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_NUMBER);
332 status = AE_NO_MEMORY;
338 * Examine each element until a match is found. Within the loop,
339 * "continue" signifies that the current element does not match
340 * and the next should be examined.
341 * Upon finding a match, the loop will terminate via "break" at
342 * the bottom. If it terminates "normally", Match_value will be -1
343 * (its initial value) indicating that no match was found. When
344 * returned as a Number, this will produce the Ones value as specified.
347 for ( ; index < pkg_desc->package.count; ++index) {
349 * Treat any NULL or non-numeric elements as non-matching.
350 * TBD [Unhandled] - if an element is a Name,
351 * should we examine its value?
353 if (!pkg_desc->package.elements[index] ||
354 ACPI_TYPE_NUMBER != pkg_desc->package.elements[index]->common.type)
360 * Within these switch statements:
361 * "break" (exit from the switch) signifies a match;
362 * "continue" (proceed to next iteration of enclosing
363 * "for" loop) signifies a non-match.
365 switch (op1_desc->number.value)
368 case MATCH_MTR: /* always true */
373 case MATCH_MEQ: /* true if equal */
375 if (pkg_desc->package.elements[index]->number.value
376 != V1_desc->number.value)
383 case MATCH_MLE: /* true if less than or equal */
385 if (pkg_desc->package.elements[index]->number.value
386 > V1_desc->number.value)
393 case MATCH_MLT: /* true if less than */
395 if (pkg_desc->package.elements[index]->number.value
396 >= V1_desc->number.value)
403 case MATCH_MGE: /* true if greater than or equal */
405 if (pkg_desc->package.elements[index]->number.value
406 < V1_desc->number.value)
413 case MATCH_MGT: /* true if greater than */
415 if (pkg_desc->package.elements[index]->number.value
416 <= V1_desc->number.value)
423 default: /* undefined */
429 switch(op2_desc->number.value)
439 if (pkg_desc->package.elements[index]->number.value
440 != V2_desc->number.value)
449 if (pkg_desc->package.elements[index]->number.value
450 > V2_desc->number.value)
459 if (pkg_desc->package.elements[index]->number.value
460 >= V2_desc->number.value)
469 if (pkg_desc->package.elements[index]->number.value
470 < V2_desc->number.value)
479 if (pkg_desc->package.elements[index]->number.value
480 <= V2_desc->number.value)
492 /* Match found: exit from loop */
498 /* Match_value is the return value */
500 ret_desc->number.value = match_value;
505 /* Free the operands */
507 acpi_cm_remove_reference (start_desc);
508 acpi_cm_remove_reference (V2_desc);
509 acpi_cm_remove_reference (op2_desc);
510 acpi_cm_remove_reference (V1_desc);
511 acpi_cm_remove_reference (op1_desc);
512 acpi_cm_remove_reference (pkg_desc);
515 /* Delete return object on error */
517 if (ACPI_FAILURE (status) &&
520 acpi_cm_remove_reference (ret_desc);
525 /* Set the return object and exit */
527 *return_desc = ret_desc;