diff options
Diffstat (limited to 'drivers/acpi/acpica/dswload2.c')
-rw-r--r-- | drivers/acpi/acpica/dswload2.c | 720 |
1 files changed, 720 insertions, 0 deletions
diff --git a/drivers/acpi/acpica/dswload2.c b/drivers/acpi/acpica/dswload2.c new file mode 100644 index 00000000000..4be4e921dfe --- /dev/null +++ b/drivers/acpi/acpica/dswload2.c | |||
@@ -0,0 +1,720 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dswload2 - Dispatcher second pass namespace load callbacks | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2011, 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/acpi.h> | ||
45 | #include "accommon.h" | ||
46 | #include "acparser.h" | ||
47 | #include "amlcode.h" | ||
48 | #include "acdispat.h" | ||
49 | #include "acinterp.h" | ||
50 | #include "acnamesp.h" | ||
51 | #include "acevents.h" | ||
52 | |||
53 | #define _COMPONENT ACPI_DISPATCHER | ||
54 | ACPI_MODULE_NAME("dswload2") | ||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_ds_load2_begin_op | ||
59 | * | ||
60 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
61 | * out_op - Wher to return op if a new one is created | ||
62 | * | ||
63 | * RETURN: Status | ||
64 | * | ||
65 | * DESCRIPTION: Descending callback used during the loading of ACPI tables. | ||
66 | * | ||
67 | ******************************************************************************/ | ||
68 | acpi_status | ||
69 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | ||
70 | union acpi_parse_object **out_op) | ||
71 | { | ||
72 | union acpi_parse_object *op; | ||
73 | struct acpi_namespace_node *node; | ||
74 | acpi_status status; | ||
75 | acpi_object_type object_type; | ||
76 | char *buffer_ptr; | ||
77 | u32 flags; | ||
78 | |||
79 | ACPI_FUNCTION_TRACE(ds_load2_begin_op); | ||
80 | |||
81 | op = walk_state->op; | ||
82 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, | ||
83 | walk_state)); | ||
84 | |||
85 | if (op) { | ||
86 | if ((walk_state->control_state) && | ||
87 | (walk_state->control_state->common.state == | ||
88 | ACPI_CONTROL_CONDITIONAL_EXECUTING)) { | ||
89 | |||
90 | /* We are executing a while loop outside of a method */ | ||
91 | |||
92 | status = acpi_ds_exec_begin_op(walk_state, out_op); | ||
93 | return_ACPI_STATUS(status); | ||
94 | } | ||
95 | |||
96 | /* We only care about Namespace opcodes here */ | ||
97 | |||
98 | if ((!(walk_state->op_info->flags & AML_NSOPCODE) && | ||
99 | (walk_state->opcode != AML_INT_NAMEPATH_OP)) || | ||
100 | (!(walk_state->op_info->flags & AML_NAMED))) { | ||
101 | return_ACPI_STATUS(AE_OK); | ||
102 | } | ||
103 | |||
104 | /* Get the name we are going to enter or lookup in the namespace */ | ||
105 | |||
106 | if (walk_state->opcode == AML_INT_NAMEPATH_OP) { | ||
107 | |||
108 | /* For Namepath op, get the path string */ | ||
109 | |||
110 | buffer_ptr = op->common.value.string; | ||
111 | if (!buffer_ptr) { | ||
112 | |||
113 | /* No name, just exit */ | ||
114 | |||
115 | return_ACPI_STATUS(AE_OK); | ||
116 | } | ||
117 | } else { | ||
118 | /* Get name from the op */ | ||
119 | |||
120 | buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); | ||
121 | } | ||
122 | } else { | ||
123 | /* Get the namestring from the raw AML */ | ||
124 | |||
125 | buffer_ptr = | ||
126 | acpi_ps_get_next_namestring(&walk_state->parser_state); | ||
127 | } | ||
128 | |||
129 | /* Map the opcode into an internal object type */ | ||
130 | |||
131 | object_type = walk_state->op_info->object_type; | ||
132 | |||
133 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
134 | "State=%p Op=%p Type=%X\n", walk_state, op, | ||
135 | object_type)); | ||
136 | |||
137 | switch (walk_state->opcode) { | ||
138 | case AML_FIELD_OP: | ||
139 | case AML_BANK_FIELD_OP: | ||
140 | case AML_INDEX_FIELD_OP: | ||
141 | |||
142 | node = NULL; | ||
143 | status = AE_OK; | ||
144 | break; | ||
145 | |||
146 | case AML_INT_NAMEPATH_OP: | ||
147 | /* | ||
148 | * The name_path is an object reference to an existing object. | ||
149 | * Don't enter the name into the namespace, but look it up | ||
150 | * for use later. | ||
151 | */ | ||
152 | status = | ||
153 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
154 | object_type, ACPI_IMODE_EXECUTE, | ||
155 | ACPI_NS_SEARCH_PARENT, walk_state, &(node)); | ||
156 | break; | ||
157 | |||
158 | case AML_SCOPE_OP: | ||
159 | |||
160 | /* Special case for Scope(\) -> refers to the Root node */ | ||
161 | |||
162 | if (op && (op->named.node == acpi_gbl_root_node)) { | ||
163 | node = op->named.node; | ||
164 | |||
165 | status = | ||
166 | acpi_ds_scope_stack_push(node, object_type, | ||
167 | walk_state); | ||
168 | if (ACPI_FAILURE(status)) { | ||
169 | return_ACPI_STATUS(status); | ||
170 | } | ||
171 | } else { | ||
172 | /* | ||
173 | * The Path is an object reference to an existing object. | ||
174 | * Don't enter the name into the namespace, but look it up | ||
175 | * for use later. | ||
176 | */ | ||
177 | status = | ||
178 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
179 | object_type, ACPI_IMODE_EXECUTE, | ||
180 | ACPI_NS_SEARCH_PARENT, walk_state, | ||
181 | &(node)); | ||
182 | if (ACPI_FAILURE(status)) { | ||
183 | #ifdef ACPI_ASL_COMPILER | ||
184 | if (status == AE_NOT_FOUND) { | ||
185 | status = AE_OK; | ||
186 | } else { | ||
187 | ACPI_ERROR_NAMESPACE(buffer_ptr, | ||
188 | status); | ||
189 | } | ||
190 | #else | ||
191 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
192 | #endif | ||
193 | return_ACPI_STATUS(status); | ||
194 | } | ||
195 | } | ||
196 | |||
197 | /* | ||
198 | * We must check to make sure that the target is | ||
199 | * one of the opcodes that actually opens a scope | ||
200 | */ | ||
201 | switch (node->type) { | ||
202 | case ACPI_TYPE_ANY: | ||
203 | case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ | ||
204 | case ACPI_TYPE_DEVICE: | ||
205 | case ACPI_TYPE_POWER: | ||
206 | case ACPI_TYPE_PROCESSOR: | ||
207 | case ACPI_TYPE_THERMAL: | ||
208 | |||
209 | /* These are acceptable types */ | ||
210 | break; | ||
211 | |||
212 | case ACPI_TYPE_INTEGER: | ||
213 | case ACPI_TYPE_STRING: | ||
214 | case ACPI_TYPE_BUFFER: | ||
215 | |||
216 | /* | ||
217 | * These types we will allow, but we will change the type. | ||
218 | * This enables some existing code of the form: | ||
219 | * | ||
220 | * Name (DEB, 0) | ||
221 | * Scope (DEB) { ... } | ||
222 | */ | ||
223 | ACPI_WARNING((AE_INFO, | ||
224 | "Type override - [%4.4s] had invalid type (%s) " | ||
225 | "for Scope operator, changed to type ANY\n", | ||
226 | acpi_ut_get_node_name(node), | ||
227 | acpi_ut_get_type_name(node->type))); | ||
228 | |||
229 | node->type = ACPI_TYPE_ANY; | ||
230 | walk_state->scope_info->common.value = ACPI_TYPE_ANY; | ||
231 | break; | ||
232 | |||
233 | default: | ||
234 | |||
235 | /* All other types are an error */ | ||
236 | |||
237 | ACPI_ERROR((AE_INFO, | ||
238 | "Invalid type (%s) for target of " | ||
239 | "Scope operator [%4.4s] (Cannot override)", | ||
240 | acpi_ut_get_type_name(node->type), | ||
241 | acpi_ut_get_node_name(node))); | ||
242 | |||
243 | return (AE_AML_OPERAND_TYPE); | ||
244 | } | ||
245 | break; | ||
246 | |||
247 | default: | ||
248 | |||
249 | /* All other opcodes */ | ||
250 | |||
251 | if (op && op->common.node) { | ||
252 | |||
253 | /* This op/node was previously entered into the namespace */ | ||
254 | |||
255 | node = op->common.node; | ||
256 | |||
257 | if (acpi_ns_opens_scope(object_type)) { | ||
258 | status = | ||
259 | acpi_ds_scope_stack_push(node, object_type, | ||
260 | walk_state); | ||
261 | if (ACPI_FAILURE(status)) { | ||
262 | return_ACPI_STATUS(status); | ||
263 | } | ||
264 | } | ||
265 | |||
266 | return_ACPI_STATUS(AE_OK); | ||
267 | } | ||
268 | |||
269 | /* | ||
270 | * Enter the named type into the internal namespace. We enter the name | ||
271 | * as we go downward in the parse tree. Any necessary subobjects that | ||
272 | * involve arguments to the opcode must be created as we go back up the | ||
273 | * parse tree later. | ||
274 | * | ||
275 | * Note: Name may already exist if we are executing a deferred opcode. | ||
276 | */ | ||
277 | if (walk_state->deferred_node) { | ||
278 | |||
279 | /* This name is already in the namespace, get the node */ | ||
280 | |||
281 | node = walk_state->deferred_node; | ||
282 | status = AE_OK; | ||
283 | break; | ||
284 | } | ||
285 | |||
286 | flags = ACPI_NS_NO_UPSEARCH; | ||
287 | if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { | ||
288 | |||
289 | /* Execution mode, node cannot already exist, node is temporary */ | ||
290 | |||
291 | flags |= ACPI_NS_ERROR_IF_FOUND; | ||
292 | |||
293 | if (! | ||
294 | (walk_state-> | ||
295 | parse_flags & ACPI_PARSE_MODULE_LEVEL)) { | ||
296 | flags |= ACPI_NS_TEMPORARY; | ||
297 | } | ||
298 | } | ||
299 | |||
300 | /* Add new entry or lookup existing entry */ | ||
301 | |||
302 | status = | ||
303 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
304 | object_type, ACPI_IMODE_LOAD_PASS2, flags, | ||
305 | walk_state, &node); | ||
306 | |||
307 | if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { | ||
308 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
309 | "***New Node [%4.4s] %p is temporary\n", | ||
310 | acpi_ut_get_node_name(node), node)); | ||
311 | } | ||
312 | break; | ||
313 | } | ||
314 | |||
315 | if (ACPI_FAILURE(status)) { | ||
316 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
317 | return_ACPI_STATUS(status); | ||
318 | } | ||
319 | |||
320 | if (!op) { | ||
321 | |||
322 | /* Create a new op */ | ||
323 | |||
324 | op = acpi_ps_alloc_op(walk_state->opcode); | ||
325 | if (!op) { | ||
326 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
327 | } | ||
328 | |||
329 | /* Initialize the new op */ | ||
330 | |||
331 | if (node) { | ||
332 | op->named.name = node->name.integer; | ||
333 | } | ||
334 | *out_op = op; | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Put the Node in the "op" object that the parser uses, so we | ||
339 | * can get it again quickly when this scope is closed | ||
340 | */ | ||
341 | op->common.node = node; | ||
342 | return_ACPI_STATUS(status); | ||
343 | } | ||
344 | |||
345 | /******************************************************************************* | ||
346 | * | ||
347 | * FUNCTION: acpi_ds_load2_end_op | ||
348 | * | ||
349 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
350 | * | ||
351 | * RETURN: Status | ||
352 | * | ||
353 | * DESCRIPTION: Ascending callback used during the loading of the namespace, | ||
354 | * both control methods and everything else. | ||
355 | * | ||
356 | ******************************************************************************/ | ||
357 | |||
358 | acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | ||
359 | { | ||
360 | union acpi_parse_object *op; | ||
361 | acpi_status status = AE_OK; | ||
362 | acpi_object_type object_type; | ||
363 | struct acpi_namespace_node *node; | ||
364 | union acpi_parse_object *arg; | ||
365 | struct acpi_namespace_node *new_node; | ||
366 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
367 | u32 i; | ||
368 | u8 region_space; | ||
369 | #endif | ||
370 | |||
371 | ACPI_FUNCTION_TRACE(ds_load2_end_op); | ||
372 | |||
373 | op = walk_state->op; | ||
374 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", | ||
375 | walk_state->op_info->name, op, walk_state)); | ||
376 | |||
377 | /* Check if opcode had an associated namespace object */ | ||
378 | |||
379 | if (!(walk_state->op_info->flags & AML_NSOBJECT)) { | ||
380 | return_ACPI_STATUS(AE_OK); | ||
381 | } | ||
382 | |||
383 | if (op->common.aml_opcode == AML_SCOPE_OP) { | ||
384 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
385 | "Ending scope Op=%p State=%p\n", op, | ||
386 | walk_state)); | ||
387 | } | ||
388 | |||
389 | object_type = walk_state->op_info->object_type; | ||
390 | |||
391 | /* | ||
392 | * Get the Node/name from the earlier lookup | ||
393 | * (It was saved in the *op structure) | ||
394 | */ | ||
395 | node = op->common.node; | ||
396 | |||
397 | /* | ||
398 | * Put the Node on the object stack (Contains the ACPI Name of | ||
399 | * this object) | ||
400 | */ | ||
401 | walk_state->operands[0] = (void *)node; | ||
402 | walk_state->num_operands = 1; | ||
403 | |||
404 | /* Pop the scope stack */ | ||
405 | |||
406 | if (acpi_ns_opens_scope(object_type) && | ||
407 | (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { | ||
408 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
409 | "(%s) Popping scope for Op %p\n", | ||
410 | acpi_ut_get_type_name(object_type), op)); | ||
411 | |||
412 | status = acpi_ds_scope_stack_pop(walk_state); | ||
413 | if (ACPI_FAILURE(status)) { | ||
414 | goto cleanup; | ||
415 | } | ||
416 | } | ||
417 | |||
418 | /* | ||
419 | * Named operations are as follows: | ||
420 | * | ||
421 | * AML_ALIAS | ||
422 | * AML_BANKFIELD | ||
423 | * AML_CREATEBITFIELD | ||
424 | * AML_CREATEBYTEFIELD | ||
425 | * AML_CREATEDWORDFIELD | ||
426 | * AML_CREATEFIELD | ||
427 | * AML_CREATEQWORDFIELD | ||
428 | * AML_CREATEWORDFIELD | ||
429 | * AML_DATA_REGION | ||
430 | * AML_DEVICE | ||
431 | * AML_EVENT | ||
432 | * AML_FIELD | ||
433 | * AML_INDEXFIELD | ||
434 | * AML_METHOD | ||
435 | * AML_METHODCALL | ||
436 | * AML_MUTEX | ||
437 | * AML_NAME | ||
438 | * AML_NAMEDFIELD | ||
439 | * AML_OPREGION | ||
440 | * AML_POWERRES | ||
441 | * AML_PROCESSOR | ||
442 | * AML_SCOPE | ||
443 | * AML_THERMALZONE | ||
444 | */ | ||
445 | |||
446 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
447 | "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", | ||
448 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
449 | walk_state, op, node)); | ||
450 | |||
451 | /* Decode the opcode */ | ||
452 | |||
453 | arg = op->common.value.arg; | ||
454 | |||
455 | switch (walk_state->op_info->type) { | ||
456 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
457 | |||
458 | case AML_TYPE_CREATE_FIELD: | ||
459 | /* | ||
460 | * Create the field object, but the field buffer and index must | ||
461 | * be evaluated later during the execution phase | ||
462 | */ | ||
463 | status = acpi_ds_create_buffer_field(op, walk_state); | ||
464 | break; | ||
465 | |||
466 | case AML_TYPE_NAMED_FIELD: | ||
467 | /* | ||
468 | * If we are executing a method, initialize the field | ||
469 | */ | ||
470 | if (walk_state->method_node) { | ||
471 | status = acpi_ds_init_field_objects(op, walk_state); | ||
472 | } | ||
473 | |||
474 | switch (op->common.aml_opcode) { | ||
475 | case AML_INDEX_FIELD_OP: | ||
476 | |||
477 | status = | ||
478 | acpi_ds_create_index_field(op, | ||
479 | (acpi_handle) arg-> | ||
480 | common.node, walk_state); | ||
481 | break; | ||
482 | |||
483 | case AML_BANK_FIELD_OP: | ||
484 | |||
485 | status = | ||
486 | acpi_ds_create_bank_field(op, arg->common.node, | ||
487 | walk_state); | ||
488 | break; | ||
489 | |||
490 | case AML_FIELD_OP: | ||
491 | |||
492 | status = | ||
493 | acpi_ds_create_field(op, arg->common.node, | ||
494 | walk_state); | ||
495 | break; | ||
496 | |||
497 | default: | ||
498 | /* All NAMED_FIELD opcodes must be handled above */ | ||
499 | break; | ||
500 | } | ||
501 | break; | ||
502 | |||
503 | case AML_TYPE_NAMED_SIMPLE: | ||
504 | |||
505 | status = acpi_ds_create_operands(walk_state, arg); | ||
506 | if (ACPI_FAILURE(status)) { | ||
507 | goto cleanup; | ||
508 | } | ||
509 | |||
510 | switch (op->common.aml_opcode) { | ||
511 | case AML_PROCESSOR_OP: | ||
512 | |||
513 | status = acpi_ex_create_processor(walk_state); | ||
514 | break; | ||
515 | |||
516 | case AML_POWER_RES_OP: | ||
517 | |||
518 | status = acpi_ex_create_power_resource(walk_state); | ||
519 | break; | ||
520 | |||
521 | case AML_MUTEX_OP: | ||
522 | |||
523 | status = acpi_ex_create_mutex(walk_state); | ||
524 | break; | ||
525 | |||
526 | case AML_EVENT_OP: | ||
527 | |||
528 | status = acpi_ex_create_event(walk_state); | ||
529 | break; | ||
530 | |||
531 | case AML_ALIAS_OP: | ||
532 | |||
533 | status = acpi_ex_create_alias(walk_state); | ||
534 | break; | ||
535 | |||
536 | default: | ||
537 | /* Unknown opcode */ | ||
538 | |||
539 | status = AE_OK; | ||
540 | goto cleanup; | ||
541 | } | ||
542 | |||
543 | /* Delete operands */ | ||
544 | |||
545 | for (i = 1; i < walk_state->num_operands; i++) { | ||
546 | acpi_ut_remove_reference(walk_state->operands[i]); | ||
547 | walk_state->operands[i] = NULL; | ||
548 | } | ||
549 | |||
550 | break; | ||
551 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
552 | |||
553 | case AML_TYPE_NAMED_COMPLEX: | ||
554 | |||
555 | switch (op->common.aml_opcode) { | ||
556 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
557 | case AML_REGION_OP: | ||
558 | case AML_DATA_REGION_OP: | ||
559 | |||
560 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
561 | region_space = (acpi_adr_space_type) | ||
562 | ((op->common.value.arg)->common.value. | ||
563 | integer); | ||
564 | } else { | ||
565 | region_space = REGION_DATA_TABLE; | ||
566 | } | ||
567 | |||
568 | /* | ||
569 | * The op_region is not fully parsed at this time. The only valid | ||
570 | * argument is the space_id. (We must save the address of the | ||
571 | * AML of the address and length operands) | ||
572 | * | ||
573 | * If we have a valid region, initialize it. The namespace is | ||
574 | * unlocked at this point. | ||
575 | * | ||
576 | * Need to unlock interpreter if it is locked (if we are running | ||
577 | * a control method), in order to allow _REG methods to be run | ||
578 | * during acpi_ev_initialize_region. | ||
579 | */ | ||
580 | if (walk_state->method_node) { | ||
581 | /* | ||
582 | * Executing a method: initialize the region and unlock | ||
583 | * the interpreter | ||
584 | */ | ||
585 | status = | ||
586 | acpi_ex_create_region(op->named.data, | ||
587 | op->named.length, | ||
588 | region_space, | ||
589 | walk_state); | ||
590 | if (ACPI_FAILURE(status)) { | ||
591 | return (status); | ||
592 | } | ||
593 | |||
594 | acpi_ex_exit_interpreter(); | ||
595 | } | ||
596 | |||
597 | status = | ||
598 | acpi_ev_initialize_region | ||
599 | (acpi_ns_get_attached_object(node), FALSE); | ||
600 | if (walk_state->method_node) { | ||
601 | acpi_ex_enter_interpreter(); | ||
602 | } | ||
603 | |||
604 | if (ACPI_FAILURE(status)) { | ||
605 | /* | ||
606 | * If AE_NOT_EXIST is returned, it is not fatal | ||
607 | * because many regions get created before a handler | ||
608 | * is installed for said region. | ||
609 | */ | ||
610 | if (AE_NOT_EXIST == status) { | ||
611 | status = AE_OK; | ||
612 | } | ||
613 | } | ||
614 | break; | ||
615 | |||
616 | case AML_NAME_OP: | ||
617 | |||
618 | status = acpi_ds_create_node(walk_state, node, op); | ||
619 | break; | ||
620 | |||
621 | case AML_METHOD_OP: | ||
622 | /* | ||
623 | * method_op pkg_length name_string method_flags term_list | ||
624 | * | ||
625 | * Note: We must create the method node/object pair as soon as we | ||
626 | * see the method declaration. This allows later pass1 parsing | ||
627 | * of invocations of the method (need to know the number of | ||
628 | * arguments.) | ||
629 | */ | ||
630 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
631 | "LOADING-Method: State=%p Op=%p NamedObj=%p\n", | ||
632 | walk_state, op, op->named.node)); | ||
633 | |||
634 | if (!acpi_ns_get_attached_object(op->named.node)) { | ||
635 | walk_state->operands[0] = | ||
636 | ACPI_CAST_PTR(void, op->named.node); | ||
637 | walk_state->num_operands = 1; | ||
638 | |||
639 | status = | ||
640 | acpi_ds_create_operands(walk_state, | ||
641 | op->common.value. | ||
642 | arg); | ||
643 | if (ACPI_SUCCESS(status)) { | ||
644 | status = | ||
645 | acpi_ex_create_method(op->named. | ||
646 | data, | ||
647 | op->named. | ||
648 | length, | ||
649 | walk_state); | ||
650 | } | ||
651 | walk_state->operands[0] = NULL; | ||
652 | walk_state->num_operands = 0; | ||
653 | |||
654 | if (ACPI_FAILURE(status)) { | ||
655 | return_ACPI_STATUS(status); | ||
656 | } | ||
657 | } | ||
658 | break; | ||
659 | |||
660 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
661 | |||
662 | default: | ||
663 | /* All NAMED_COMPLEX opcodes must be handled above */ | ||
664 | break; | ||
665 | } | ||
666 | break; | ||
667 | |||
668 | case AML_CLASS_INTERNAL: | ||
669 | |||
670 | /* case AML_INT_NAMEPATH_OP: */ | ||
671 | break; | ||
672 | |||
673 | case AML_CLASS_METHOD_CALL: | ||
674 | |||
675 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
676 | "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", | ||
677 | walk_state, op, node)); | ||
678 | |||
679 | /* | ||
680 | * Lookup the method name and save the Node | ||
681 | */ | ||
682 | status = | ||
683 | acpi_ns_lookup(walk_state->scope_info, | ||
684 | arg->common.value.string, ACPI_TYPE_ANY, | ||
685 | ACPI_IMODE_LOAD_PASS2, | ||
686 | ACPI_NS_SEARCH_PARENT | | ||
687 | ACPI_NS_DONT_OPEN_SCOPE, walk_state, | ||
688 | &(new_node)); | ||
689 | if (ACPI_SUCCESS(status)) { | ||
690 | /* | ||
691 | * Make sure that what we found is indeed a method | ||
692 | * We didn't search for a method on purpose, to see if the name | ||
693 | * would resolve | ||
694 | */ | ||
695 | if (new_node->type != ACPI_TYPE_METHOD) { | ||
696 | status = AE_AML_OPERAND_TYPE; | ||
697 | } | ||
698 | |||
699 | /* We could put the returned object (Node) on the object stack for | ||
700 | * later, but for now, we will put it in the "op" object that the | ||
701 | * parser uses, so we can get it again at the end of this scope | ||
702 | */ | ||
703 | op->common.node = new_node; | ||
704 | } else { | ||
705 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | ||
706 | } | ||
707 | break; | ||
708 | |||
709 | default: | ||
710 | break; | ||
711 | } | ||
712 | |||
713 | cleanup: | ||
714 | |||
715 | /* Remove the Node pushed at the very beginning */ | ||
716 | |||
717 | walk_state->operands[0] = NULL; | ||
718 | walk_state->num_operands = 0; | ||
719 | return_ACPI_STATUS(status); | ||
720 | } | ||