0d7cd73cde65a782f4f2627a84a45f9f7d9c083e
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
;