2 /******************************************************************************
4 * Module Name: ammisc - ACPI AML (p-code) execution - specific opcodes
7 *****************************************************************************/
10 * Copyright (C) 2000, 2001 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 ACPI_EXECUTER
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->integer.value >= obj_desc->package.count) {
176 status = AE_AML_PACKAGE_LIMIT;
180 if ((res_desc->common.type == INTERNAL_TYPE_REFERENCE) &&
181 (res_desc->reference.opcode == AML_ZERO_OP)) {
183 * There is no actual result descriptor (the Zero_op Result
184 * descriptor is a placeholder), so just delete the placeholder and
185 * return a reference to the package element
188 acpi_cm_remove_reference (res_desc);
193 * Each element of the package is an internal object. Get the one
197 tmp_desc = obj_desc->package.elements[idx_desc->integer.value];
198 ret_desc->reference.opcode = AML_INDEX_OP;
199 ret_desc->reference.target_type = tmp_desc->common.type;
200 ret_desc->reference.object = tmp_desc;
202 status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
203 ret_desc->reference.object = NULL;
207 * The local return object must always be a reference to the package element,
208 * not the element itself.
210 ret_desc->reference.opcode = AML_INDEX_OP;
211 ret_desc->reference.target_type = ACPI_TYPE_PACKAGE;
212 ret_desc->reference.where = &obj_desc->package.elements[idx_desc->integer.value];
216 /* Object to be indexed is a Buffer */
218 if (idx_desc->integer.value >= obj_desc->buffer.length) {
219 status = AE_AML_BUFFER_LIMIT;
223 ret_desc->reference.opcode = AML_INDEX_OP;
224 ret_desc->reference.target_type = ACPI_TYPE_BUFFER_FIELD;
225 ret_desc->reference.object = obj_desc;
226 ret_desc->reference.offset = (u32) idx_desc->integer.value;
228 status = acpi_aml_exec_store (ret_desc, res_desc, walk_state);
234 /* Always delete operands */
236 acpi_cm_remove_reference (obj_desc);
237 acpi_cm_remove_reference (idx_desc);
239 /* Delete return object on error */
241 if (ACPI_FAILURE (status)) {
242 acpi_cm_remove_reference (res_desc);
245 acpi_cm_remove_reference (ret_desc);
250 /* Set the return object and exit */
252 *return_desc = ret_desc;
257 /*******************************************************************************
259 * FUNCTION: Acpi_aml_exec_match
265 * DESCRIPTION: Execute Match operator
267 * ACPI SPECIFICATION REFERENCES:
268 * Def_match := Match_op Search_pkg Opcode1 Operand1
269 * Opcode2 Operand2 Start_index
270 * Opcode1 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT
271 * Opcode2 := Byte_data: MTR, MEQ, MLE, MLT, MGE, or MGT
272 * Operand1 := Term_arg=>Integer
273 * Operand2 := Term_arg=>Integer
274 * Search_pkg := Term_arg=>Package_object
275 * Start_index := Term_arg=>Integer
277 ******************************************************************************/
280 acpi_aml_exec_match (
281 ACPI_WALK_STATE *walk_state,
282 ACPI_OPERAND_OBJECT **return_desc)
284 ACPI_OPERAND_OBJECT *pkg_desc;
285 ACPI_OPERAND_OBJECT *op1_desc;
286 ACPI_OPERAND_OBJECT *V1_desc;
287 ACPI_OPERAND_OBJECT *op2_desc;
288 ACPI_OPERAND_OBJECT *V2_desc;
289 ACPI_OPERAND_OBJECT *start_desc;
290 ACPI_OPERAND_OBJECT *ret_desc = NULL;
293 u32 match_value = (u32) -1;
296 /* Resolve all operands */
298 status = acpi_aml_resolve_operands (AML_MATCH_OP, WALK_OPERANDS, walk_state);
299 /* Get all operands */
301 status |= acpi_ds_obj_stack_pop_object (&start_desc, walk_state);
302 status |= acpi_ds_obj_stack_pop_object (&V2_desc, walk_state);
303 status |= acpi_ds_obj_stack_pop_object (&op2_desc, walk_state);
304 status |= acpi_ds_obj_stack_pop_object (&V1_desc, walk_state);
305 status |= acpi_ds_obj_stack_pop_object (&op1_desc, walk_state);
306 status |= acpi_ds_obj_stack_pop_object (&pkg_desc, walk_state);
308 if (ACPI_FAILURE (status)) {
309 /* Invalid parameters on object stack */
314 /* Validate match comparison sub-opcodes */
316 if ((op1_desc->integer.value > MAX_MATCH_OPERATOR) ||
317 (op2_desc->integer.value > MAX_MATCH_OPERATOR)) {
318 status = AE_AML_OPERAND_VALUE;
322 index = (u32) start_desc->integer.value;
323 if (index >= (u32) pkg_desc->package.count) {
324 status = AE_AML_PACKAGE_LIMIT;
328 ret_desc = acpi_cm_create_internal_object (ACPI_TYPE_INTEGER);
330 status = AE_NO_MEMORY;
336 * Examine each element until a match is found. Within the loop,
337 * "continue" signifies that the current element does not match
338 * and the next should be examined.
339 * Upon finding a match, the loop will terminate via "break" at
340 * the bottom. If it terminates "normally", Match_value will be -1
341 * (its initial value) indicating that no match was found. When
342 * returned as a Number, this will produce the Ones value as specified.
345 for ( ; index < pkg_desc->package.count; ++index) {
347 * Treat any NULL or non-numeric elements as non-matching.
348 * TBD [Unhandled] - if an element is a Name,
349 * should we examine its value?
351 if (!pkg_desc->package.elements[index] ||
352 ACPI_TYPE_INTEGER != pkg_desc->package.elements[index]->common.type) {
357 * Within these switch statements:
358 * "break" (exit from the switch) signifies a match;
359 * "continue" (proceed to next iteration of enclosing
360 * "for" loop) signifies a non-match.
362 switch (op1_desc->integer.value) {
364 case MATCH_MTR: /* always true */
369 case MATCH_MEQ: /* true if equal */
371 if (pkg_desc->package.elements[index]->integer.value
372 != V1_desc->integer.value) {
378 case MATCH_MLE: /* true if less than or equal */
380 if (pkg_desc->package.elements[index]->integer.value
381 > V1_desc->integer.value) {
387 case MATCH_MLT: /* true if less than */
389 if (pkg_desc->package.elements[index]->integer.value
390 >= V1_desc->integer.value) {
396 case MATCH_MGE: /* true if greater than or equal */
398 if (pkg_desc->package.elements[index]->integer.value
399 < V1_desc->integer.value) {
405 case MATCH_MGT: /* true if greater than */
407 if (pkg_desc->package.elements[index]->integer.value
408 <= V1_desc->integer.value) {
414 default: /* undefined */
420 switch(op2_desc->integer.value) {
429 if (pkg_desc->package.elements[index]->integer.value
430 != V2_desc->integer.value) {
438 if (pkg_desc->package.elements[index]->integer.value
439 > V2_desc->integer.value) {
447 if (pkg_desc->package.elements[index]->integer.value
448 >= V2_desc->integer.value) {
456 if (pkg_desc->package.elements[index]->integer.value
457 < V2_desc->integer.value) {
465 if (pkg_desc->package.elements[index]->integer.value
466 <= V2_desc->integer.value) {
477 /* Match found: exit from loop */
483 /* Match_value is the return value */
485 ret_desc->integer.value = match_value;
490 /* Free the operands */
492 acpi_cm_remove_reference (start_desc);
493 acpi_cm_remove_reference (V2_desc);
494 acpi_cm_remove_reference (op2_desc);
495 acpi_cm_remove_reference (V1_desc);
496 acpi_cm_remove_reference (op1_desc);
497 acpi_cm_remove_reference (pkg_desc);
500 /* Delete return object on error */
502 if (ACPI_FAILURE (status) &&
504 acpi_cm_remove_reference (ret_desc);
509 /* Set the return object and exit */
511 *return_desc = ret_desc;