diff options
author | Len Brown <len.brown@intel.com> | 2009-01-09 00:13:17 -0500 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-01-09 03:30:47 -0500 |
commit | 95b482a8d31116f3f5c2a5089569393234d06385 (patch) | |
tree | f32aec8673a285a9d188948be97af3034ee06e93 /drivers/acpi/dispatcher | |
parent | 6620e0c49f577454b772fb381543d60ae53eb885 (diff) |
ACPICA: create acpica/ directory
also, delete sleep/ and delete ACPI_CFLAGS from Makefile
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/dispatcher')
-rw-r--r-- | drivers/acpi/dispatcher/Makefile | 9 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsfield.c | 650 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsinit.c | 205 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsmethod.c | 629 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsmthdat.c | 718 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsobject.c | 813 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsopcode.c | 1469 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dsutils.c | 869 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dswexec.c | 746 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dswload.c | 1203 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dswscope.c | 214 | ||||
-rw-r--r-- | drivers/acpi/dispatcher/dswstate.c | 753 |
12 files changed, 0 insertions, 8278 deletions
diff --git a/drivers/acpi/dispatcher/Makefile b/drivers/acpi/dispatcher/Makefile deleted file mode 100644 index eb7e602a83cd..000000000000 --- a/drivers/acpi/dispatcher/Makefile +++ /dev/null | |||
@@ -1,9 +0,0 @@ | |||
1 | # | ||
2 | # Makefile for all Linux ACPI interpreter subdirectories | ||
3 | # | ||
4 | |||
5 | obj-y := dsfield.o dsmthdat.o dsopcode.o dswexec.o dswscope.o \ | ||
6 | dsmethod.o dsobject.o dsutils.o dswload.o dswstate.o \ | ||
7 | dsinit.o | ||
8 | |||
9 | EXTRA_CFLAGS += $(ACPI_CFLAGS) | ||
diff --git a/drivers/acpi/dispatcher/dsfield.c b/drivers/acpi/dispatcher/dsfield.c deleted file mode 100644 index 5fbc24075b44..000000000000 --- a/drivers/acpi/dispatcher/dsfield.c +++ /dev/null | |||
@@ -1,650 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dsfield - Dispatcher field routines | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/amlcode.h> | ||
47 | #include <acpi/acdispat.h> | ||
48 | #include <acpi/acinterp.h> | ||
49 | #include <acpi/acnamesp.h> | ||
50 | #include <acpi/acparser.h> | ||
51 | |||
52 | #define _COMPONENT ACPI_DISPATCHER | ||
53 | ACPI_MODULE_NAME("dsfield") | ||
54 | |||
55 | /* Local prototypes */ | ||
56 | static acpi_status | ||
57 | acpi_ds_get_field_names(struct acpi_create_field_info *info, | ||
58 | struct acpi_walk_state *walk_state, | ||
59 | union acpi_parse_object *arg); | ||
60 | |||
61 | /******************************************************************************* | ||
62 | * | ||
63 | * FUNCTION: acpi_ds_create_buffer_field | ||
64 | * | ||
65 | * PARAMETERS: Op - Current parse op (create_xXField) | ||
66 | * walk_state - Current state | ||
67 | * | ||
68 | * RETURN: Status | ||
69 | * | ||
70 | * DESCRIPTION: Execute the create_field operators: | ||
71 | * create_bit_field_op, | ||
72 | * create_byte_field_op, | ||
73 | * create_word_field_op, | ||
74 | * create_dword_field_op, | ||
75 | * create_qword_field_op, | ||
76 | * create_field_op (all of which define a field in a buffer) | ||
77 | * | ||
78 | ******************************************************************************/ | ||
79 | |||
80 | acpi_status | ||
81 | acpi_ds_create_buffer_field(union acpi_parse_object *op, | ||
82 | struct acpi_walk_state *walk_state) | ||
83 | { | ||
84 | union acpi_parse_object *arg; | ||
85 | struct acpi_namespace_node *node; | ||
86 | acpi_status status; | ||
87 | union acpi_operand_object *obj_desc; | ||
88 | union acpi_operand_object *second_desc = NULL; | ||
89 | u32 flags; | ||
90 | |||
91 | ACPI_FUNCTION_TRACE(ds_create_buffer_field); | ||
92 | |||
93 | /* | ||
94 | * Get the name_string argument (name of the new buffer_field) | ||
95 | */ | ||
96 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { | ||
97 | |||
98 | /* For create_field, name is the 4th argument */ | ||
99 | |||
100 | arg = acpi_ps_get_arg(op, 3); | ||
101 | } else { | ||
102 | /* For all other create_xXXField operators, name is the 3rd argument */ | ||
103 | |||
104 | arg = acpi_ps_get_arg(op, 2); | ||
105 | } | ||
106 | |||
107 | if (!arg) { | ||
108 | return_ACPI_STATUS(AE_AML_NO_OPERAND); | ||
109 | } | ||
110 | |||
111 | if (walk_state->deferred_node) { | ||
112 | node = walk_state->deferred_node; | ||
113 | status = AE_OK; | ||
114 | } else { | ||
115 | /* Execute flag should always be set when this function is entered */ | ||
116 | |||
117 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | ||
118 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
119 | } | ||
120 | |||
121 | /* Creating new namespace node, should not already exist */ | ||
122 | |||
123 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | ||
124 | ACPI_NS_ERROR_IF_FOUND; | ||
125 | |||
126 | /* Mark node temporary if we are executing a method */ | ||
127 | |||
128 | if (walk_state->method_node) { | ||
129 | flags |= ACPI_NS_TEMPORARY; | ||
130 | } | ||
131 | |||
132 | /* Enter the name_string into the namespace */ | ||
133 | |||
134 | status = | ||
135 | acpi_ns_lookup(walk_state->scope_info, | ||
136 | arg->common.value.string, ACPI_TYPE_ANY, | ||
137 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, | ||
138 | &node); | ||
139 | if (ACPI_FAILURE(status)) { | ||
140 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | ||
141 | return_ACPI_STATUS(status); | ||
142 | } | ||
143 | } | ||
144 | |||
145 | /* | ||
146 | * We could put the returned object (Node) on the object stack for later, | ||
147 | * but for now, we will put it in the "op" object that the parser uses, | ||
148 | * so we can get it again at the end of this scope. | ||
149 | */ | ||
150 | op->common.node = node; | ||
151 | |||
152 | /* | ||
153 | * If there is no object attached to the node, this node was just created | ||
154 | * and we need to create the field object. Otherwise, this was a lookup | ||
155 | * of an existing node and we don't want to create the field object again. | ||
156 | */ | ||
157 | obj_desc = acpi_ns_get_attached_object(node); | ||
158 | if (obj_desc) { | ||
159 | return_ACPI_STATUS(AE_OK); | ||
160 | } | ||
161 | |||
162 | /* | ||
163 | * The Field definition is not fully parsed at this time. | ||
164 | * (We must save the address of the AML for the buffer and index operands) | ||
165 | */ | ||
166 | |||
167 | /* Create the buffer field object */ | ||
168 | |||
169 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER_FIELD); | ||
170 | if (!obj_desc) { | ||
171 | status = AE_NO_MEMORY; | ||
172 | goto cleanup; | ||
173 | } | ||
174 | |||
175 | /* | ||
176 | * Remember location in AML stream of the field unit opcode and operands -- | ||
177 | * since the buffer and index operands must be evaluated. | ||
178 | */ | ||
179 | second_desc = obj_desc->common.next_object; | ||
180 | second_desc->extra.aml_start = op->named.data; | ||
181 | second_desc->extra.aml_length = op->named.length; | ||
182 | obj_desc->buffer_field.node = node; | ||
183 | |||
184 | /* Attach constructed field descriptors to parent node */ | ||
185 | |||
186 | status = acpi_ns_attach_object(node, obj_desc, ACPI_TYPE_BUFFER_FIELD); | ||
187 | if (ACPI_FAILURE(status)) { | ||
188 | goto cleanup; | ||
189 | } | ||
190 | |||
191 | cleanup: | ||
192 | |||
193 | /* Remove local reference to the object */ | ||
194 | |||
195 | acpi_ut_remove_reference(obj_desc); | ||
196 | return_ACPI_STATUS(status); | ||
197 | } | ||
198 | |||
199 | /******************************************************************************* | ||
200 | * | ||
201 | * FUNCTION: acpi_ds_get_field_names | ||
202 | * | ||
203 | * PARAMETERS: Info - create_field info structure | ||
204 | * ` walk_state - Current method state | ||
205 | * Arg - First parser arg for the field name list | ||
206 | * | ||
207 | * RETURN: Status | ||
208 | * | ||
209 | * DESCRIPTION: Process all named fields in a field declaration. Names are | ||
210 | * entered into the namespace. | ||
211 | * | ||
212 | ******************************************************************************/ | ||
213 | |||
214 | static acpi_status | ||
215 | acpi_ds_get_field_names(struct acpi_create_field_info *info, | ||
216 | struct acpi_walk_state *walk_state, | ||
217 | union acpi_parse_object *arg) | ||
218 | { | ||
219 | acpi_status status; | ||
220 | acpi_integer position; | ||
221 | |||
222 | ACPI_FUNCTION_TRACE_PTR(ds_get_field_names, info); | ||
223 | |||
224 | /* First field starts at bit zero */ | ||
225 | |||
226 | info->field_bit_position = 0; | ||
227 | |||
228 | /* Process all elements in the field list (of parse nodes) */ | ||
229 | |||
230 | while (arg) { | ||
231 | /* | ||
232 | * Three types of field elements are handled: | ||
233 | * 1) Offset - specifies a bit offset | ||
234 | * 2) access_as - changes the access mode | ||
235 | * 3) Name - Enters a new named field into the namespace | ||
236 | */ | ||
237 | switch (arg->common.aml_opcode) { | ||
238 | case AML_INT_RESERVEDFIELD_OP: | ||
239 | |||
240 | position = (acpi_integer) info->field_bit_position | ||
241 | + (acpi_integer) arg->common.value.size; | ||
242 | |||
243 | if (position > ACPI_UINT32_MAX) { | ||
244 | ACPI_ERROR((AE_INFO, | ||
245 | "Bit offset within field too large (> 0xFFFFFFFF)")); | ||
246 | return_ACPI_STATUS(AE_SUPPORT); | ||
247 | } | ||
248 | |||
249 | info->field_bit_position = (u32) position; | ||
250 | break; | ||
251 | |||
252 | case AML_INT_ACCESSFIELD_OP: | ||
253 | |||
254 | /* | ||
255 | * Get a new access_type and access_attribute -- to be used for all | ||
256 | * field units that follow, until field end or another access_as | ||
257 | * keyword. | ||
258 | * | ||
259 | * In field_flags, preserve the flag bits other than the | ||
260 | * ACCESS_TYPE bits | ||
261 | */ | ||
262 | info->field_flags = (u8) | ||
263 | ((info-> | ||
264 | field_flags & ~(AML_FIELD_ACCESS_TYPE_MASK)) | | ||
265 | ((u8) ((u32) arg->common.value.integer >> 8))); | ||
266 | |||
267 | info->attribute = (u8) (arg->common.value.integer); | ||
268 | break; | ||
269 | |||
270 | case AML_INT_NAMEDFIELD_OP: | ||
271 | |||
272 | /* Lookup the name, it should already exist */ | ||
273 | |||
274 | status = acpi_ns_lookup(walk_state->scope_info, | ||
275 | (char *)&arg->named.name, | ||
276 | info->field_type, | ||
277 | ACPI_IMODE_EXECUTE, | ||
278 | ACPI_NS_DONT_OPEN_SCOPE, | ||
279 | walk_state, &info->field_node); | ||
280 | if (ACPI_FAILURE(status)) { | ||
281 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | ||
282 | status); | ||
283 | return_ACPI_STATUS(status); | ||
284 | } else { | ||
285 | arg->common.node = info->field_node; | ||
286 | info->field_bit_length = arg->common.value.size; | ||
287 | |||
288 | /* | ||
289 | * If there is no object attached to the node, this node was | ||
290 | * just created and we need to create the field object. | ||
291 | * Otherwise, this was a lookup of an existing node and we | ||
292 | * don't want to create the field object again. | ||
293 | */ | ||
294 | if (!acpi_ns_get_attached_object | ||
295 | (info->field_node)) { | ||
296 | status = acpi_ex_prep_field_value(info); | ||
297 | if (ACPI_FAILURE(status)) { | ||
298 | return_ACPI_STATUS(status); | ||
299 | } | ||
300 | } | ||
301 | } | ||
302 | |||
303 | /* Keep track of bit position for the next field */ | ||
304 | |||
305 | position = (acpi_integer) info->field_bit_position | ||
306 | + (acpi_integer) arg->common.value.size; | ||
307 | |||
308 | if (position > ACPI_UINT32_MAX) { | ||
309 | ACPI_ERROR((AE_INFO, | ||
310 | "Field [%4.4s] bit offset too large (> 0xFFFFFFFF)", | ||
311 | ACPI_CAST_PTR(char, | ||
312 | &info->field_node-> | ||
313 | name))); | ||
314 | return_ACPI_STATUS(AE_SUPPORT); | ||
315 | } | ||
316 | |||
317 | info->field_bit_position += info->field_bit_length; | ||
318 | break; | ||
319 | |||
320 | default: | ||
321 | |||
322 | ACPI_ERROR((AE_INFO, | ||
323 | "Invalid opcode in field list: %X", | ||
324 | arg->common.aml_opcode)); | ||
325 | return_ACPI_STATUS(AE_AML_BAD_OPCODE); | ||
326 | } | ||
327 | |||
328 | arg = arg->common.next; | ||
329 | } | ||
330 | |||
331 | return_ACPI_STATUS(AE_OK); | ||
332 | } | ||
333 | |||
334 | /******************************************************************************* | ||
335 | * | ||
336 | * FUNCTION: acpi_ds_create_field | ||
337 | * | ||
338 | * PARAMETERS: Op - Op containing the Field definition and args | ||
339 | * region_node - Object for the containing Operation Region | ||
340 | * ` walk_state - Current method state | ||
341 | * | ||
342 | * RETURN: Status | ||
343 | * | ||
344 | * DESCRIPTION: Create a new field in the specified operation region | ||
345 | * | ||
346 | ******************************************************************************/ | ||
347 | |||
348 | acpi_status | ||
349 | acpi_ds_create_field(union acpi_parse_object *op, | ||
350 | struct acpi_namespace_node *region_node, | ||
351 | struct acpi_walk_state *walk_state) | ||
352 | { | ||
353 | acpi_status status; | ||
354 | union acpi_parse_object *arg; | ||
355 | struct acpi_create_field_info info; | ||
356 | |||
357 | ACPI_FUNCTION_TRACE_PTR(ds_create_field, op); | ||
358 | |||
359 | /* First arg is the name of the parent op_region (must already exist) */ | ||
360 | |||
361 | arg = op->common.value.arg; | ||
362 | if (!region_node) { | ||
363 | status = | ||
364 | acpi_ns_lookup(walk_state->scope_info, | ||
365 | arg->common.value.name, ACPI_TYPE_REGION, | ||
366 | ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | ||
367 | walk_state, ®ion_node); | ||
368 | if (ACPI_FAILURE(status)) { | ||
369 | ACPI_ERROR_NAMESPACE(arg->common.value.name, status); | ||
370 | return_ACPI_STATUS(status); | ||
371 | } | ||
372 | } | ||
373 | |||
374 | /* Second arg is the field flags */ | ||
375 | |||
376 | arg = arg->common.next; | ||
377 | info.field_flags = (u8) arg->common.value.integer; | ||
378 | info.attribute = 0; | ||
379 | |||
380 | /* Each remaining arg is a Named Field */ | ||
381 | |||
382 | info.field_type = ACPI_TYPE_LOCAL_REGION_FIELD; | ||
383 | info.region_node = region_node; | ||
384 | |||
385 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | ||
386 | |||
387 | return_ACPI_STATUS(status); | ||
388 | } | ||
389 | |||
390 | /******************************************************************************* | ||
391 | * | ||
392 | * FUNCTION: acpi_ds_init_field_objects | ||
393 | * | ||
394 | * PARAMETERS: Op - Op containing the Field definition and args | ||
395 | * ` walk_state - Current method state | ||
396 | * | ||
397 | * RETURN: Status | ||
398 | * | ||
399 | * DESCRIPTION: For each "Field Unit" name in the argument list that is | ||
400 | * part of the field declaration, enter the name into the | ||
401 | * namespace. | ||
402 | * | ||
403 | ******************************************************************************/ | ||
404 | |||
405 | acpi_status | ||
406 | acpi_ds_init_field_objects(union acpi_parse_object *op, | ||
407 | struct acpi_walk_state *walk_state) | ||
408 | { | ||
409 | acpi_status status; | ||
410 | union acpi_parse_object *arg = NULL; | ||
411 | struct acpi_namespace_node *node; | ||
412 | u8 type = 0; | ||
413 | u32 flags; | ||
414 | |||
415 | ACPI_FUNCTION_TRACE_PTR(ds_init_field_objects, op); | ||
416 | |||
417 | /* Execute flag should always be set when this function is entered */ | ||
418 | |||
419 | if (!(walk_state->parse_flags & ACPI_PARSE_EXECUTE)) { | ||
420 | if (walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP) { | ||
421 | |||
422 | /* bank_field Op is deferred, just return OK */ | ||
423 | |||
424 | return_ACPI_STATUS(AE_OK); | ||
425 | } | ||
426 | |||
427 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
428 | } | ||
429 | |||
430 | /* | ||
431 | * Get the field_list argument for this opcode. This is the start of the | ||
432 | * list of field elements. | ||
433 | */ | ||
434 | switch (walk_state->opcode) { | ||
435 | case AML_FIELD_OP: | ||
436 | arg = acpi_ps_get_arg(op, 2); | ||
437 | type = ACPI_TYPE_LOCAL_REGION_FIELD; | ||
438 | break; | ||
439 | |||
440 | case AML_BANK_FIELD_OP: | ||
441 | arg = acpi_ps_get_arg(op, 4); | ||
442 | type = ACPI_TYPE_LOCAL_BANK_FIELD; | ||
443 | break; | ||
444 | |||
445 | case AML_INDEX_FIELD_OP: | ||
446 | arg = acpi_ps_get_arg(op, 3); | ||
447 | type = ACPI_TYPE_LOCAL_INDEX_FIELD; | ||
448 | break; | ||
449 | |||
450 | default: | ||
451 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
452 | } | ||
453 | |||
454 | /* Creating new namespace node(s), should not already exist */ | ||
455 | |||
456 | flags = ACPI_NS_NO_UPSEARCH | ACPI_NS_DONT_OPEN_SCOPE | | ||
457 | ACPI_NS_ERROR_IF_FOUND; | ||
458 | |||
459 | /* Mark node(s) temporary if we are executing a method */ | ||
460 | |||
461 | if (walk_state->method_node) { | ||
462 | flags |= ACPI_NS_TEMPORARY; | ||
463 | } | ||
464 | |||
465 | /* | ||
466 | * Walk the list of entries in the field_list | ||
467 | * Note: field_list can be of zero length. In this case, Arg will be NULL. | ||
468 | */ | ||
469 | while (arg) { | ||
470 | /* | ||
471 | * Ignore OFFSET and ACCESSAS terms here; we are only interested in the | ||
472 | * field names in order to enter them into the namespace. | ||
473 | */ | ||
474 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | ||
475 | status = acpi_ns_lookup(walk_state->scope_info, | ||
476 | (char *)&arg->named.name, type, | ||
477 | ACPI_IMODE_LOAD_PASS1, flags, | ||
478 | walk_state, &node); | ||
479 | if (ACPI_FAILURE(status)) { | ||
480 | ACPI_ERROR_NAMESPACE((char *)&arg->named.name, | ||
481 | status); | ||
482 | if (status != AE_ALREADY_EXISTS) { | ||
483 | return_ACPI_STATUS(status); | ||
484 | } | ||
485 | |||
486 | /* Name already exists, just ignore this error */ | ||
487 | |||
488 | status = AE_OK; | ||
489 | } | ||
490 | |||
491 | arg->common.node = node; | ||
492 | } | ||
493 | |||
494 | /* Get the next field element in the list */ | ||
495 | |||
496 | arg = arg->common.next; | ||
497 | } | ||
498 | |||
499 | return_ACPI_STATUS(AE_OK); | ||
500 | } | ||
501 | |||
502 | /******************************************************************************* | ||
503 | * | ||
504 | * FUNCTION: acpi_ds_create_bank_field | ||
505 | * | ||
506 | * PARAMETERS: Op - Op containing the Field definition and args | ||
507 | * region_node - Object for the containing Operation Region | ||
508 | * walk_state - Current method state | ||
509 | * | ||
510 | * RETURN: Status | ||
511 | * | ||
512 | * DESCRIPTION: Create a new bank field in the specified operation region | ||
513 | * | ||
514 | ******************************************************************************/ | ||
515 | |||
516 | acpi_status | ||
517 | acpi_ds_create_bank_field(union acpi_parse_object *op, | ||
518 | struct acpi_namespace_node *region_node, | ||
519 | struct acpi_walk_state *walk_state) | ||
520 | { | ||
521 | acpi_status status; | ||
522 | union acpi_parse_object *arg; | ||
523 | struct acpi_create_field_info info; | ||
524 | |||
525 | ACPI_FUNCTION_TRACE_PTR(ds_create_bank_field, op); | ||
526 | |||
527 | /* First arg is the name of the parent op_region (must already exist) */ | ||
528 | |||
529 | arg = op->common.value.arg; | ||
530 | if (!region_node) { | ||
531 | status = | ||
532 | acpi_ns_lookup(walk_state->scope_info, | ||
533 | arg->common.value.name, ACPI_TYPE_REGION, | ||
534 | ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | ||
535 | walk_state, ®ion_node); | ||
536 | if (ACPI_FAILURE(status)) { | ||
537 | ACPI_ERROR_NAMESPACE(arg->common.value.name, status); | ||
538 | return_ACPI_STATUS(status); | ||
539 | } | ||
540 | } | ||
541 | |||
542 | /* Second arg is the Bank Register (Field) (must already exist) */ | ||
543 | |||
544 | arg = arg->common.next; | ||
545 | status = | ||
546 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | ||
547 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | ||
548 | ACPI_NS_SEARCH_PARENT, walk_state, | ||
549 | &info.register_node); | ||
550 | if (ACPI_FAILURE(status)) { | ||
551 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | ||
552 | return_ACPI_STATUS(status); | ||
553 | } | ||
554 | |||
555 | /* | ||
556 | * Third arg is the bank_value | ||
557 | * This arg is a term_arg, not a constant | ||
558 | * It will be evaluated later, by acpi_ds_eval_bank_field_operands | ||
559 | */ | ||
560 | arg = arg->common.next; | ||
561 | |||
562 | /* Fourth arg is the field flags */ | ||
563 | |||
564 | arg = arg->common.next; | ||
565 | info.field_flags = (u8) arg->common.value.integer; | ||
566 | |||
567 | /* Each remaining arg is a Named Field */ | ||
568 | |||
569 | info.field_type = ACPI_TYPE_LOCAL_BANK_FIELD; | ||
570 | info.region_node = region_node; | ||
571 | |||
572 | /* | ||
573 | * Use Info.data_register_node to store bank_field Op | ||
574 | * It's safe because data_register_node will never be used when create bank field | ||
575 | * We store aml_start and aml_length in the bank_field Op for late evaluation | ||
576 | * Used in acpi_ex_prep_field_value(Info) | ||
577 | * | ||
578 | * TBD: Or, should we add a field in struct acpi_create_field_info, like "void *ParentOp"? | ||
579 | */ | ||
580 | info.data_register_node = (struct acpi_namespace_node *)op; | ||
581 | |||
582 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | ||
583 | return_ACPI_STATUS(status); | ||
584 | } | ||
585 | |||
586 | /******************************************************************************* | ||
587 | * | ||
588 | * FUNCTION: acpi_ds_create_index_field | ||
589 | * | ||
590 | * PARAMETERS: Op - Op containing the Field definition and args | ||
591 | * region_node - Object for the containing Operation Region | ||
592 | * ` walk_state - Current method state | ||
593 | * | ||
594 | * RETURN: Status | ||
595 | * | ||
596 | * DESCRIPTION: Create a new index field in the specified operation region | ||
597 | * | ||
598 | ******************************************************************************/ | ||
599 | |||
600 | acpi_status | ||
601 | acpi_ds_create_index_field(union acpi_parse_object *op, | ||
602 | struct acpi_namespace_node *region_node, | ||
603 | struct acpi_walk_state *walk_state) | ||
604 | { | ||
605 | acpi_status status; | ||
606 | union acpi_parse_object *arg; | ||
607 | struct acpi_create_field_info info; | ||
608 | |||
609 | ACPI_FUNCTION_TRACE_PTR(ds_create_index_field, op); | ||
610 | |||
611 | /* First arg is the name of the Index register (must already exist) */ | ||
612 | |||
613 | arg = op->common.value.arg; | ||
614 | status = | ||
615 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | ||
616 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | ||
617 | ACPI_NS_SEARCH_PARENT, walk_state, | ||
618 | &info.register_node); | ||
619 | if (ACPI_FAILURE(status)) { | ||
620 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | ||
621 | return_ACPI_STATUS(status); | ||
622 | } | ||
623 | |||
624 | /* Second arg is the data register (must already exist) */ | ||
625 | |||
626 | arg = arg->common.next; | ||
627 | status = | ||
628 | acpi_ns_lookup(walk_state->scope_info, arg->common.value.string, | ||
629 | ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, | ||
630 | ACPI_NS_SEARCH_PARENT, walk_state, | ||
631 | &info.data_register_node); | ||
632 | if (ACPI_FAILURE(status)) { | ||
633 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | ||
634 | return_ACPI_STATUS(status); | ||
635 | } | ||
636 | |||
637 | /* Next arg is the field flags */ | ||
638 | |||
639 | arg = arg->common.next; | ||
640 | info.field_flags = (u8) arg->common.value.integer; | ||
641 | |||
642 | /* Each remaining arg is a Named Field */ | ||
643 | |||
644 | info.field_type = ACPI_TYPE_LOCAL_INDEX_FIELD; | ||
645 | info.region_node = region_node; | ||
646 | |||
647 | status = acpi_ds_get_field_names(&info, walk_state, arg->common.next); | ||
648 | |||
649 | return_ACPI_STATUS(status); | ||
650 | } | ||
diff --git a/drivers/acpi/dispatcher/dsinit.c b/drivers/acpi/dispatcher/dsinit.c deleted file mode 100644 index 4f1cdd823fcc..000000000000 --- a/drivers/acpi/dispatcher/dsinit.c +++ /dev/null | |||
@@ -1,205 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dsinit - Object initialization namespace walk | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/acdispat.h> | ||
47 | #include <acpi/acnamesp.h> | ||
48 | #include <acpi/actables.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_DISPATCHER | ||
51 | ACPI_MODULE_NAME("dsinit") | ||
52 | |||
53 | /* Local prototypes */ | ||
54 | static acpi_status | ||
55 | acpi_ds_init_one_object(acpi_handle obj_handle, | ||
56 | u32 level, void *context, void **return_value); | ||
57 | |||
58 | /******************************************************************************* | ||
59 | * | ||
60 | * FUNCTION: acpi_ds_init_one_object | ||
61 | * | ||
62 | * PARAMETERS: obj_handle - Node for the object | ||
63 | * Level - Current nesting level | ||
64 | * Context - Points to a init info struct | ||
65 | * return_value - Not used | ||
66 | * | ||
67 | * RETURN: Status | ||
68 | * | ||
69 | * DESCRIPTION: Callback from acpi_walk_namespace. Invoked for every object | ||
70 | * within the namespace. | ||
71 | * | ||
72 | * Currently, the only objects that require initialization are: | ||
73 | * 1) Methods | ||
74 | * 2) Operation Regions | ||
75 | * | ||
76 | ******************************************************************************/ | ||
77 | |||
78 | static acpi_status | ||
79 | acpi_ds_init_one_object(acpi_handle obj_handle, | ||
80 | u32 level, void *context, void **return_value) | ||
81 | { | ||
82 | struct acpi_init_walk_info *info = | ||
83 | (struct acpi_init_walk_info *)context; | ||
84 | struct acpi_namespace_node *node = | ||
85 | (struct acpi_namespace_node *)obj_handle; | ||
86 | acpi_object_type type; | ||
87 | acpi_status status; | ||
88 | |||
89 | ACPI_FUNCTION_ENTRY(); | ||
90 | |||
91 | /* | ||
92 | * We are only interested in NS nodes owned by the table that | ||
93 | * was just loaded | ||
94 | */ | ||
95 | if (node->owner_id != info->owner_id) { | ||
96 | return (AE_OK); | ||
97 | } | ||
98 | |||
99 | info->object_count++; | ||
100 | |||
101 | /* And even then, we are only interested in a few object types */ | ||
102 | |||
103 | type = acpi_ns_get_type(obj_handle); | ||
104 | |||
105 | switch (type) { | ||
106 | case ACPI_TYPE_REGION: | ||
107 | |||
108 | status = acpi_ds_initialize_region(obj_handle); | ||
109 | if (ACPI_FAILURE(status)) { | ||
110 | ACPI_EXCEPTION((AE_INFO, status, | ||
111 | "During Region initialization %p [%4.4s]", | ||
112 | obj_handle, | ||
113 | acpi_ut_get_node_name(obj_handle))); | ||
114 | } | ||
115 | |||
116 | info->op_region_count++; | ||
117 | break; | ||
118 | |||
119 | case ACPI_TYPE_METHOD: | ||
120 | |||
121 | info->method_count++; | ||
122 | break; | ||
123 | |||
124 | case ACPI_TYPE_DEVICE: | ||
125 | |||
126 | info->device_count++; | ||
127 | break; | ||
128 | |||
129 | default: | ||
130 | break; | ||
131 | } | ||
132 | |||
133 | /* | ||
134 | * We ignore errors from above, and always return OK, since | ||
135 | * we don't want to abort the walk on a single error. | ||
136 | */ | ||
137 | return (AE_OK); | ||
138 | } | ||
139 | |||
140 | /******************************************************************************* | ||
141 | * | ||
142 | * FUNCTION: acpi_ds_initialize_objects | ||
143 | * | ||
144 | * PARAMETERS: table_desc - Descriptor for parent ACPI table | ||
145 | * start_node - Root of subtree to be initialized. | ||
146 | * | ||
147 | * RETURN: Status | ||
148 | * | ||
149 | * DESCRIPTION: Walk the namespace starting at "StartNode" and perform any | ||
150 | * necessary initialization on the objects found therein | ||
151 | * | ||
152 | ******************************************************************************/ | ||
153 | |||
154 | acpi_status | ||
155 | acpi_ds_initialize_objects(u32 table_index, | ||
156 | struct acpi_namespace_node * start_node) | ||
157 | { | ||
158 | acpi_status status; | ||
159 | struct acpi_init_walk_info info; | ||
160 | struct acpi_table_header *table; | ||
161 | acpi_owner_id owner_id; | ||
162 | |||
163 | ACPI_FUNCTION_TRACE(ds_initialize_objects); | ||
164 | |||
165 | status = acpi_tb_get_owner_id(table_index, &owner_id); | ||
166 | if (ACPI_FAILURE(status)) { | ||
167 | return_ACPI_STATUS(status); | ||
168 | } | ||
169 | |||
170 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
171 | "**** Starting initialization of namespace objects ****\n")); | ||
172 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, "Parsing all Control Methods:")); | ||
173 | |||
174 | info.method_count = 0; | ||
175 | info.op_region_count = 0; | ||
176 | info.object_count = 0; | ||
177 | info.device_count = 0; | ||
178 | info.table_index = table_index; | ||
179 | info.owner_id = owner_id; | ||
180 | |||
181 | /* Walk entire namespace from the supplied root */ | ||
182 | |||
183 | status = acpi_walk_namespace(ACPI_TYPE_ANY, start_node, ACPI_UINT32_MAX, | ||
184 | acpi_ds_init_one_object, &info, NULL); | ||
185 | if (ACPI_FAILURE(status)) { | ||
186 | ACPI_EXCEPTION((AE_INFO, status, "During WalkNamespace")); | ||
187 | } | ||
188 | |||
189 | status = acpi_get_table_by_index(table_index, &table); | ||
190 | if (ACPI_FAILURE(status)) { | ||
191 | return_ACPI_STATUS(status); | ||
192 | } | ||
193 | |||
194 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_INIT, | ||
195 | "\nTable [%4.4s](id %4.4X) - %hd Objects with %hd Devices %hd Methods %hd Regions\n", | ||
196 | table->signature, owner_id, info.object_count, | ||
197 | info.device_count, info.method_count, | ||
198 | info.op_region_count)); | ||
199 | |||
200 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
201 | "%hd Methods, %hd Regions\n", info.method_count, | ||
202 | info.op_region_count)); | ||
203 | |||
204 | return_ACPI_STATUS(AE_OK); | ||
205 | } | ||
diff --git a/drivers/acpi/dispatcher/dsmethod.c b/drivers/acpi/dispatcher/dsmethod.c deleted file mode 100644 index 333c8560d9f8..000000000000 --- a/drivers/acpi/dispatcher/dsmethod.c +++ /dev/null | |||
@@ -1,629 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dsmethod - Parser/Interpreter interface - control method parsing | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/amlcode.h> | ||
47 | #include <acpi/acdispat.h> | ||
48 | #include <acpi/acinterp.h> | ||
49 | #include <acpi/acnamesp.h> | ||
50 | #ifdef ACPI_DISASSEMBLER | ||
51 | #include <acpi/acdisasm.h> | ||
52 | #endif | ||
53 | |||
54 | #define _COMPONENT ACPI_DISPATCHER | ||
55 | ACPI_MODULE_NAME("dsmethod") | ||
56 | |||
57 | /* Local prototypes */ | ||
58 | static acpi_status | ||
59 | acpi_ds_create_method_mutex(union acpi_operand_object *method_desc); | ||
60 | |||
61 | /******************************************************************************* | ||
62 | * | ||
63 | * FUNCTION: acpi_ds_method_error | ||
64 | * | ||
65 | * PARAMETERS: Status - Execution status | ||
66 | * walk_state - Current state | ||
67 | * | ||
68 | * RETURN: Status | ||
69 | * | ||
70 | * DESCRIPTION: Called on method error. Invoke the global exception handler if | ||
71 | * present, dump the method data if the disassembler is configured | ||
72 | * | ||
73 | * Note: Allows the exception handler to change the status code | ||
74 | * | ||
75 | ******************************************************************************/ | ||
76 | |||
77 | acpi_status | ||
78 | acpi_ds_method_error(acpi_status status, struct acpi_walk_state *walk_state) | ||
79 | { | ||
80 | ACPI_FUNCTION_ENTRY(); | ||
81 | |||
82 | /* Ignore AE_OK and control exception codes */ | ||
83 | |||
84 | if (ACPI_SUCCESS(status) || (status & AE_CODE_CONTROL)) { | ||
85 | return (status); | ||
86 | } | ||
87 | |||
88 | /* Invoke the global exception handler */ | ||
89 | |||
90 | if (acpi_gbl_exception_handler) { | ||
91 | |||
92 | /* Exit the interpreter, allow handler to execute methods */ | ||
93 | |||
94 | acpi_ex_exit_interpreter(); | ||
95 | |||
96 | /* | ||
97 | * Handler can map the exception code to anything it wants, including | ||
98 | * AE_OK, in which case the executing method will not be aborted. | ||
99 | */ | ||
100 | status = acpi_gbl_exception_handler(status, | ||
101 | walk_state->method_node ? | ||
102 | walk_state->method_node-> | ||
103 | name.integer : 0, | ||
104 | walk_state->opcode, | ||
105 | walk_state->aml_offset, | ||
106 | NULL); | ||
107 | acpi_ex_enter_interpreter(); | ||
108 | } | ||
109 | |||
110 | acpi_ds_clear_implicit_return(walk_state); | ||
111 | |||
112 | #ifdef ACPI_DISASSEMBLER | ||
113 | if (ACPI_FAILURE(status)) { | ||
114 | |||
115 | /* Display method locals/args if disassembler is present */ | ||
116 | |||
117 | acpi_dm_dump_method_info(status, walk_state, walk_state->op); | ||
118 | } | ||
119 | #endif | ||
120 | |||
121 | return (status); | ||
122 | } | ||
123 | |||
124 | /******************************************************************************* | ||
125 | * | ||
126 | * FUNCTION: acpi_ds_create_method_mutex | ||
127 | * | ||
128 | * PARAMETERS: obj_desc - The method object | ||
129 | * | ||
130 | * RETURN: Status | ||
131 | * | ||
132 | * DESCRIPTION: Create a mutex object for a serialized control method | ||
133 | * | ||
134 | ******************************************************************************/ | ||
135 | |||
136 | static acpi_status | ||
137 | acpi_ds_create_method_mutex(union acpi_operand_object *method_desc) | ||
138 | { | ||
139 | union acpi_operand_object *mutex_desc; | ||
140 | acpi_status status; | ||
141 | |||
142 | ACPI_FUNCTION_TRACE(ds_create_method_mutex); | ||
143 | |||
144 | /* Create the new mutex object */ | ||
145 | |||
146 | mutex_desc = acpi_ut_create_internal_object(ACPI_TYPE_MUTEX); | ||
147 | if (!mutex_desc) { | ||
148 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
149 | } | ||
150 | |||
151 | /* Create the actual OS Mutex */ | ||
152 | |||
153 | status = acpi_os_create_mutex(&mutex_desc->mutex.os_mutex); | ||
154 | if (ACPI_FAILURE(status)) { | ||
155 | return_ACPI_STATUS(status); | ||
156 | } | ||
157 | |||
158 | mutex_desc->mutex.sync_level = method_desc->method.sync_level; | ||
159 | method_desc->method.mutex = mutex_desc; | ||
160 | return_ACPI_STATUS(AE_OK); | ||
161 | } | ||
162 | |||
163 | /******************************************************************************* | ||
164 | * | ||
165 | * FUNCTION: acpi_ds_begin_method_execution | ||
166 | * | ||
167 | * PARAMETERS: method_node - Node of the method | ||
168 | * obj_desc - The method object | ||
169 | * walk_state - current state, NULL if not yet executing | ||
170 | * a method. | ||
171 | * | ||
172 | * RETURN: Status | ||
173 | * | ||
174 | * DESCRIPTION: Prepare a method for execution. Parses the method if necessary, | ||
175 | * increments the thread count, and waits at the method semaphore | ||
176 | * for clearance to execute. | ||
177 | * | ||
178 | ******************************************************************************/ | ||
179 | |||
180 | acpi_status | ||
181 | acpi_ds_begin_method_execution(struct acpi_namespace_node *method_node, | ||
182 | union acpi_operand_object *obj_desc, | ||
183 | struct acpi_walk_state *walk_state) | ||
184 | { | ||
185 | acpi_status status = AE_OK; | ||
186 | |||
187 | ACPI_FUNCTION_TRACE_PTR(ds_begin_method_execution, method_node); | ||
188 | |||
189 | if (!method_node) { | ||
190 | return_ACPI_STATUS(AE_NULL_ENTRY); | ||
191 | } | ||
192 | |||
193 | /* Prevent wraparound of thread count */ | ||
194 | |||
195 | if (obj_desc->method.thread_count == ACPI_UINT8_MAX) { | ||
196 | ACPI_ERROR((AE_INFO, | ||
197 | "Method reached maximum reentrancy limit (255)")); | ||
198 | return_ACPI_STATUS(AE_AML_METHOD_LIMIT); | ||
199 | } | ||
200 | |||
201 | /* | ||
202 | * If this method is serialized, we need to acquire the method mutex. | ||
203 | */ | ||
204 | if (obj_desc->method.method_flags & AML_METHOD_SERIALIZED) { | ||
205 | /* | ||
206 | * Create a mutex for the method if it is defined to be Serialized | ||
207 | * and a mutex has not already been created. We defer the mutex creation | ||
208 | * until a method is actually executed, to minimize the object count | ||
209 | */ | ||
210 | if (!obj_desc->method.mutex) { | ||
211 | status = acpi_ds_create_method_mutex(obj_desc); | ||
212 | if (ACPI_FAILURE(status)) { | ||
213 | return_ACPI_STATUS(status); | ||
214 | } | ||
215 | } | ||
216 | |||
217 | /* | ||
218 | * The current_sync_level (per-thread) must be less than or equal to | ||
219 | * the sync level of the method. This mechanism provides some | ||
220 | * deadlock prevention | ||
221 | * | ||
222 | * Top-level method invocation has no walk state at this point | ||
223 | */ | ||
224 | if (walk_state && | ||
225 | (walk_state->thread->current_sync_level > | ||
226 | obj_desc->method.mutex->mutex.sync_level)) { | ||
227 | ACPI_ERROR((AE_INFO, | ||
228 | "Cannot acquire Mutex for method [%4.4s], current SyncLevel is too large (%d)", | ||
229 | acpi_ut_get_node_name(method_node), | ||
230 | walk_state->thread->current_sync_level)); | ||
231 | |||
232 | return_ACPI_STATUS(AE_AML_MUTEX_ORDER); | ||
233 | } | ||
234 | |||
235 | /* | ||
236 | * Obtain the method mutex if necessary. Do not acquire mutex for a | ||
237 | * recursive call. | ||
238 | */ | ||
239 | if (!walk_state || | ||
240 | !obj_desc->method.mutex->mutex.thread_id || | ||
241 | (walk_state->thread->thread_id != | ||
242 | obj_desc->method.mutex->mutex.thread_id)) { | ||
243 | /* | ||
244 | * Acquire the method mutex. This releases the interpreter if we | ||
245 | * block (and reacquires it before it returns) | ||
246 | */ | ||
247 | status = | ||
248 | acpi_ex_system_wait_mutex(obj_desc->method.mutex-> | ||
249 | mutex.os_mutex, | ||
250 | ACPI_WAIT_FOREVER); | ||
251 | if (ACPI_FAILURE(status)) { | ||
252 | return_ACPI_STATUS(status); | ||
253 | } | ||
254 | |||
255 | /* Update the mutex and walk info and save the original sync_level */ | ||
256 | |||
257 | if (walk_state) { | ||
258 | obj_desc->method.mutex->mutex. | ||
259 | original_sync_level = | ||
260 | walk_state->thread->current_sync_level; | ||
261 | |||
262 | obj_desc->method.mutex->mutex.thread_id = | ||
263 | walk_state->thread->thread_id; | ||
264 | walk_state->thread->current_sync_level = | ||
265 | obj_desc->method.sync_level; | ||
266 | } else { | ||
267 | obj_desc->method.mutex->mutex. | ||
268 | original_sync_level = | ||
269 | obj_desc->method.mutex->mutex.sync_level; | ||
270 | } | ||
271 | } | ||
272 | |||
273 | /* Always increase acquisition depth */ | ||
274 | |||
275 | obj_desc->method.mutex->mutex.acquisition_depth++; | ||
276 | } | ||
277 | |||
278 | /* | ||
279 | * Allocate an Owner ID for this method, only if this is the first thread | ||
280 | * to begin concurrent execution. We only need one owner_id, even if the | ||
281 | * method is invoked recursively. | ||
282 | */ | ||
283 | if (!obj_desc->method.owner_id) { | ||
284 | status = acpi_ut_allocate_owner_id(&obj_desc->method.owner_id); | ||
285 | if (ACPI_FAILURE(status)) { | ||
286 | goto cleanup; | ||
287 | } | ||
288 | } | ||
289 | |||
290 | /* | ||
291 | * Increment the method parse tree thread count since it has been | ||
292 | * reentered one more time (even if it is the same thread) | ||
293 | */ | ||
294 | obj_desc->method.thread_count++; | ||
295 | return_ACPI_STATUS(status); | ||
296 | |||
297 | cleanup: | ||
298 | /* On error, must release the method mutex (if present) */ | ||
299 | |||
300 | if (obj_desc->method.mutex) { | ||
301 | acpi_os_release_mutex(obj_desc->method.mutex->mutex.os_mutex); | ||
302 | } | ||
303 | return_ACPI_STATUS(status); | ||
304 | } | ||
305 | |||
306 | /******************************************************************************* | ||
307 | * | ||
308 | * FUNCTION: acpi_ds_call_control_method | ||
309 | * | ||
310 | * PARAMETERS: Thread - Info for this thread | ||
311 | * this_walk_state - Current walk state | ||
312 | * Op - Current Op to be walked | ||
313 | * | ||
314 | * RETURN: Status | ||
315 | * | ||
316 | * DESCRIPTION: Transfer execution to a called control method | ||
317 | * | ||
318 | ******************************************************************************/ | ||
319 | |||
320 | acpi_status | ||
321 | acpi_ds_call_control_method(struct acpi_thread_state *thread, | ||
322 | struct acpi_walk_state *this_walk_state, | ||
323 | union acpi_parse_object *op) | ||
324 | { | ||
325 | acpi_status status; | ||
326 | struct acpi_namespace_node *method_node; | ||
327 | struct acpi_walk_state *next_walk_state = NULL; | ||
328 | union acpi_operand_object *obj_desc; | ||
329 | struct acpi_evaluate_info *info; | ||
330 | u32 i; | ||
331 | |||
332 | ACPI_FUNCTION_TRACE_PTR(ds_call_control_method, this_walk_state); | ||
333 | |||
334 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
335 | "Calling method %p, currentstate=%p\n", | ||
336 | this_walk_state->prev_op, this_walk_state)); | ||
337 | |||
338 | /* | ||
339 | * Get the namespace entry for the control method we are about to call | ||
340 | */ | ||
341 | method_node = this_walk_state->method_call_node; | ||
342 | if (!method_node) { | ||
343 | return_ACPI_STATUS(AE_NULL_ENTRY); | ||
344 | } | ||
345 | |||
346 | obj_desc = acpi_ns_get_attached_object(method_node); | ||
347 | if (!obj_desc) { | ||
348 | return_ACPI_STATUS(AE_NULL_OBJECT); | ||
349 | } | ||
350 | |||
351 | /* Init for new method, possibly wait on method mutex */ | ||
352 | |||
353 | status = acpi_ds_begin_method_execution(method_node, obj_desc, | ||
354 | this_walk_state); | ||
355 | if (ACPI_FAILURE(status)) { | ||
356 | return_ACPI_STATUS(status); | ||
357 | } | ||
358 | |||
359 | /* Begin method parse/execution. Create a new walk state */ | ||
360 | |||
361 | next_walk_state = acpi_ds_create_walk_state(obj_desc->method.owner_id, | ||
362 | NULL, obj_desc, thread); | ||
363 | if (!next_walk_state) { | ||
364 | status = AE_NO_MEMORY; | ||
365 | goto cleanup; | ||
366 | } | ||
367 | |||
368 | /* | ||
369 | * The resolved arguments were put on the previous walk state's operand | ||
370 | * stack. Operands on the previous walk state stack always | ||
371 | * start at index 0. Also, null terminate the list of arguments | ||
372 | */ | ||
373 | this_walk_state->operands[this_walk_state->num_operands] = NULL; | ||
374 | |||
375 | /* | ||
376 | * Allocate and initialize the evaluation information block | ||
377 | * TBD: this is somewhat inefficient, should change interface to | ||
378 | * ds_init_aml_walk. For now, keeps this struct off the CPU stack | ||
379 | */ | ||
380 | info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info)); | ||
381 | if (!info) { | ||
382 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
383 | } | ||
384 | |||
385 | info->parameters = &this_walk_state->operands[0]; | ||
386 | |||
387 | status = acpi_ds_init_aml_walk(next_walk_state, NULL, method_node, | ||
388 | obj_desc->method.aml_start, | ||
389 | obj_desc->method.aml_length, info, | ||
390 | ACPI_IMODE_EXECUTE); | ||
391 | |||
392 | ACPI_FREE(info); | ||
393 | if (ACPI_FAILURE(status)) { | ||
394 | goto cleanup; | ||
395 | } | ||
396 | |||
397 | /* | ||
398 | * Delete the operands on the previous walkstate operand stack | ||
399 | * (they were copied to new objects) | ||
400 | */ | ||
401 | for (i = 0; i < obj_desc->method.param_count; i++) { | ||
402 | acpi_ut_remove_reference(this_walk_state->operands[i]); | ||
403 | this_walk_state->operands[i] = NULL; | ||
404 | } | ||
405 | |||
406 | /* Clear the operand stack */ | ||
407 | |||
408 | this_walk_state->num_operands = 0; | ||
409 | |||
410 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
411 | "**** Begin nested execution of [%4.4s] **** WalkState=%p\n", | ||
412 | method_node->name.ascii, next_walk_state)); | ||
413 | |||
414 | /* Invoke an internal method if necessary */ | ||
415 | |||
416 | if (obj_desc->method.method_flags & AML_METHOD_INTERNAL_ONLY) { | ||
417 | status = obj_desc->method.implementation(next_walk_state); | ||
418 | if (status == AE_OK) { | ||
419 | status = AE_CTRL_TERMINATE; | ||
420 | } | ||
421 | } | ||
422 | |||
423 | return_ACPI_STATUS(status); | ||
424 | |||
425 | cleanup: | ||
426 | |||
427 | /* On error, we must terminate the method properly */ | ||
428 | |||
429 | acpi_ds_terminate_control_method(obj_desc, next_walk_state); | ||
430 | if (next_walk_state) { | ||
431 | acpi_ds_delete_walk_state(next_walk_state); | ||
432 | } | ||
433 | |||
434 | return_ACPI_STATUS(status); | ||
435 | } | ||
436 | |||
437 | /******************************************************************************* | ||
438 | * | ||
439 | * FUNCTION: acpi_ds_restart_control_method | ||
440 | * | ||
441 | * PARAMETERS: walk_state - State for preempted method (caller) | ||
442 | * return_desc - Return value from the called method | ||
443 | * | ||
444 | * RETURN: Status | ||
445 | * | ||
446 | * DESCRIPTION: Restart a method that was preempted by another (nested) method | ||
447 | * invocation. Handle the return value (if any) from the callee. | ||
448 | * | ||
449 | ******************************************************************************/ | ||
450 | |||
451 | acpi_status | ||
452 | acpi_ds_restart_control_method(struct acpi_walk_state *walk_state, | ||
453 | union acpi_operand_object *return_desc) | ||
454 | { | ||
455 | acpi_status status; | ||
456 | int same_as_implicit_return; | ||
457 | |||
458 | ACPI_FUNCTION_TRACE_PTR(ds_restart_control_method, walk_state); | ||
459 | |||
460 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
461 | "****Restart [%4.4s] Op %p ReturnValueFromCallee %p\n", | ||
462 | acpi_ut_get_node_name(walk_state->method_node), | ||
463 | walk_state->method_call_op, return_desc)); | ||
464 | |||
465 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
466 | " ReturnFromThisMethodUsed?=%X ResStack %p Walk %p\n", | ||
467 | walk_state->return_used, | ||
468 | walk_state->results, walk_state)); | ||
469 | |||
470 | /* Did the called method return a value? */ | ||
471 | |||
472 | if (return_desc) { | ||
473 | |||
474 | /* Is the implicit return object the same as the return desc? */ | ||
475 | |||
476 | same_as_implicit_return = | ||
477 | (walk_state->implicit_return_obj == return_desc); | ||
478 | |||
479 | /* Are we actually going to use the return value? */ | ||
480 | |||
481 | if (walk_state->return_used) { | ||
482 | |||
483 | /* Save the return value from the previous method */ | ||
484 | |||
485 | status = acpi_ds_result_push(return_desc, walk_state); | ||
486 | if (ACPI_FAILURE(status)) { | ||
487 | acpi_ut_remove_reference(return_desc); | ||
488 | return_ACPI_STATUS(status); | ||
489 | } | ||
490 | |||
491 | /* | ||
492 | * Save as THIS method's return value in case it is returned | ||
493 | * immediately to yet another method | ||
494 | */ | ||
495 | walk_state->return_desc = return_desc; | ||
496 | } | ||
497 | |||
498 | /* | ||
499 | * The following code is the optional support for the so-called | ||
500 | * "implicit return". Some AML code assumes that the last value of the | ||
501 | * method is "implicitly" returned to the caller, in the absence of an | ||
502 | * explicit return value. | ||
503 | * | ||
504 | * Just save the last result of the method as the return value. | ||
505 | * | ||
506 | * NOTE: this is optional because the ASL language does not actually | ||
507 | * support this behavior. | ||
508 | */ | ||
509 | else if (!acpi_ds_do_implicit_return | ||
510 | (return_desc, walk_state, FALSE) | ||
511 | || same_as_implicit_return) { | ||
512 | /* | ||
513 | * Delete the return value if it will not be used by the | ||
514 | * calling method or remove one reference if the explicit return | ||
515 | * is the same as the implicit return value. | ||
516 | */ | ||
517 | acpi_ut_remove_reference(return_desc); | ||
518 | } | ||
519 | } | ||
520 | |||
521 | return_ACPI_STATUS(AE_OK); | ||
522 | } | ||
523 | |||
524 | /******************************************************************************* | ||
525 | * | ||
526 | * FUNCTION: acpi_ds_terminate_control_method | ||
527 | * | ||
528 | * PARAMETERS: method_desc - Method object | ||
529 | * walk_state - State associated with the method | ||
530 | * | ||
531 | * RETURN: None | ||
532 | * | ||
533 | * DESCRIPTION: Terminate a control method. Delete everything that the method | ||
534 | * created, delete all locals and arguments, and delete the parse | ||
535 | * tree if requested. | ||
536 | * | ||
537 | * MUTEX: Interpreter is locked | ||
538 | * | ||
539 | ******************************************************************************/ | ||
540 | |||
541 | void | ||
542 | acpi_ds_terminate_control_method(union acpi_operand_object *method_desc, | ||
543 | struct acpi_walk_state *walk_state) | ||
544 | { | ||
545 | |||
546 | ACPI_FUNCTION_TRACE_PTR(ds_terminate_control_method, walk_state); | ||
547 | |||
548 | /* method_desc is required, walk_state is optional */ | ||
549 | |||
550 | if (!method_desc) { | ||
551 | return_VOID; | ||
552 | } | ||
553 | |||
554 | if (walk_state) { | ||
555 | |||
556 | /* Delete all arguments and locals */ | ||
557 | |||
558 | acpi_ds_method_data_delete_all(walk_state); | ||
559 | |||
560 | /* | ||
561 | * If method is serialized, release the mutex and restore the | ||
562 | * current sync level for this thread | ||
563 | */ | ||
564 | if (method_desc->method.mutex) { | ||
565 | |||
566 | /* Acquisition Depth handles recursive calls */ | ||
567 | |||
568 | method_desc->method.mutex->mutex.acquisition_depth--; | ||
569 | if (!method_desc->method.mutex->mutex.acquisition_depth) { | ||
570 | walk_state->thread->current_sync_level = | ||
571 | method_desc->method.mutex->mutex. | ||
572 | original_sync_level; | ||
573 | |||
574 | acpi_os_release_mutex(method_desc->method. | ||
575 | mutex->mutex.os_mutex); | ||
576 | method_desc->method.mutex->mutex.thread_id = NULL; | ||
577 | } | ||
578 | } | ||
579 | |||
580 | /* | ||
581 | * Delete any namespace objects created anywhere within | ||
582 | * the namespace by the execution of this method | ||
583 | */ | ||
584 | acpi_ns_delete_namespace_by_owner(method_desc->method.owner_id); | ||
585 | } | ||
586 | |||
587 | /* Decrement the thread count on the method */ | ||
588 | |||
589 | if (method_desc->method.thread_count) { | ||
590 | method_desc->method.thread_count--; | ||
591 | } else { | ||
592 | ACPI_ERROR((AE_INFO, "Invalid zero thread count in method")); | ||
593 | } | ||
594 | |||
595 | /* Are there any other threads currently executing this method? */ | ||
596 | |||
597 | if (method_desc->method.thread_count) { | ||
598 | /* | ||
599 | * Additional threads. Do not release the owner_id in this case, | ||
600 | * we immediately reuse it for the next thread executing this method | ||
601 | */ | ||
602 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
603 | "*** Completed execution of one thread, %d threads remaining\n", | ||
604 | method_desc->method.thread_count)); | ||
605 | } else { | ||
606 | /* This is the only executing thread for this method */ | ||
607 | |||
608 | /* | ||
609 | * Support to dynamically change a method from not_serialized to | ||
610 | * Serialized if it appears that the method is incorrectly written and | ||
611 | * does not support multiple thread execution. The best example of this | ||
612 | * is if such a method creates namespace objects and blocks. A second | ||
613 | * thread will fail with an AE_ALREADY_EXISTS exception | ||
614 | * | ||
615 | * This code is here because we must wait until the last thread exits | ||
616 | * before creating the synchronization semaphore. | ||
617 | */ | ||
618 | if ((method_desc->method.method_flags & AML_METHOD_SERIALIZED) | ||
619 | && (!method_desc->method.mutex)) { | ||
620 | (void)acpi_ds_create_method_mutex(method_desc); | ||
621 | } | ||
622 | |||
623 | /* No more threads, we can free the owner_id */ | ||
624 | |||
625 | acpi_ut_release_owner_id(&method_desc->method.owner_id); | ||
626 | } | ||
627 | |||
628 | return_VOID; | ||
629 | } | ||
diff --git a/drivers/acpi/dispatcher/dsmthdat.c b/drivers/acpi/dispatcher/dsmthdat.c deleted file mode 100644 index a1a11996a651..000000000000 --- a/drivers/acpi/dispatcher/dsmthdat.c +++ /dev/null | |||
@@ -1,718 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Module Name: dsmthdat - control method arguments and local variables | ||
4 | * | ||
5 | ******************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/acdispat.h> | ||
47 | #include <acpi/acnamesp.h> | ||
48 | #include <acpi/acinterp.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_DISPATCHER | ||
51 | ACPI_MODULE_NAME("dsmthdat") | ||
52 | |||
53 | /* Local prototypes */ | ||
54 | static void | ||
55 | acpi_ds_method_data_delete_value(u8 type, | ||
56 | u32 index, struct acpi_walk_state *walk_state); | ||
57 | |||
58 | static acpi_status | ||
59 | acpi_ds_method_data_set_value(u8 type, | ||
60 | u32 index, | ||
61 | union acpi_operand_object *object, | ||
62 | struct acpi_walk_state *walk_state); | ||
63 | |||
64 | #ifdef ACPI_OBSOLETE_FUNCTIONS | ||
65 | acpi_object_type | ||
66 | acpi_ds_method_data_get_type(u16 opcode, | ||
67 | u32 index, struct acpi_walk_state *walk_state); | ||
68 | #endif | ||
69 | |||
70 | /******************************************************************************* | ||
71 | * | ||
72 | * FUNCTION: acpi_ds_method_data_init | ||
73 | * | ||
74 | * PARAMETERS: walk_state - Current walk state object | ||
75 | * | ||
76 | * RETURN: Status | ||
77 | * | ||
78 | * DESCRIPTION: Initialize the data structures that hold the method's arguments | ||
79 | * and locals. The data struct is an array of namespace nodes for | ||
80 | * each - this allows ref_of and de_ref_of to work properly for these | ||
81 | * special data types. | ||
82 | * | ||
83 | * NOTES: walk_state fields are initialized to zero by the | ||
84 | * ACPI_ALLOCATE_ZEROED(). | ||
85 | * | ||
86 | * A pseudo-Namespace Node is assigned to each argument and local | ||
87 | * so that ref_of() can return a pointer to the Node. | ||
88 | * | ||
89 | ******************************************************************************/ | ||
90 | |||
91 | void acpi_ds_method_data_init(struct acpi_walk_state *walk_state) | ||
92 | { | ||
93 | u32 i; | ||
94 | |||
95 | ACPI_FUNCTION_TRACE(ds_method_data_init); | ||
96 | |||
97 | /* Init the method arguments */ | ||
98 | |||
99 | for (i = 0; i < ACPI_METHOD_NUM_ARGS; i++) { | ||
100 | ACPI_MOVE_32_TO_32(&walk_state->arguments[i].name, | ||
101 | NAMEOF_ARG_NTE); | ||
102 | walk_state->arguments[i].name.integer |= (i << 24); | ||
103 | walk_state->arguments[i].descriptor_type = ACPI_DESC_TYPE_NAMED; | ||
104 | walk_state->arguments[i].type = ACPI_TYPE_ANY; | ||
105 | walk_state->arguments[i].flags = | ||
106 | ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_ARG; | ||
107 | } | ||
108 | |||
109 | /* Init the method locals */ | ||
110 | |||
111 | for (i = 0; i < ACPI_METHOD_NUM_LOCALS; i++) { | ||
112 | ACPI_MOVE_32_TO_32(&walk_state->local_variables[i].name, | ||
113 | NAMEOF_LOCAL_NTE); | ||
114 | |||
115 | walk_state->local_variables[i].name.integer |= (i << 24); | ||
116 | walk_state->local_variables[i].descriptor_type = | ||
117 | ACPI_DESC_TYPE_NAMED; | ||
118 | walk_state->local_variables[i].type = ACPI_TYPE_ANY; | ||
119 | walk_state->local_variables[i].flags = | ||
120 | ANOBJ_END_OF_PEER_LIST | ANOBJ_METHOD_LOCAL; | ||
121 | } | ||
122 | |||
123 | return_VOID; | ||
124 | } | ||
125 | |||
126 | /******************************************************************************* | ||
127 | * | ||
128 | * FUNCTION: acpi_ds_method_data_delete_all | ||
129 | * | ||
130 | * PARAMETERS: walk_state - Current walk state object | ||
131 | * | ||
132 | * RETURN: None | ||
133 | * | ||
134 | * DESCRIPTION: Delete method locals and arguments. Arguments are only | ||
135 | * deleted if this method was called from another method. | ||
136 | * | ||
137 | ******************************************************************************/ | ||
138 | |||
139 | void acpi_ds_method_data_delete_all(struct acpi_walk_state *walk_state) | ||
140 | { | ||
141 | u32 index; | ||
142 | |||
143 | ACPI_FUNCTION_TRACE(ds_method_data_delete_all); | ||
144 | |||
145 | /* Detach the locals */ | ||
146 | |||
147 | for (index = 0; index < ACPI_METHOD_NUM_LOCALS; index++) { | ||
148 | if (walk_state->local_variables[index].object) { | ||
149 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Local%d=%p\n", | ||
150 | index, | ||
151 | walk_state->local_variables[index]. | ||
152 | object)); | ||
153 | |||
154 | /* Detach object (if present) and remove a reference */ | ||
155 | |||
156 | acpi_ns_detach_object(&walk_state-> | ||
157 | local_variables[index]); | ||
158 | } | ||
159 | } | ||
160 | |||
161 | /* Detach the arguments */ | ||
162 | |||
163 | for (index = 0; index < ACPI_METHOD_NUM_ARGS; index++) { | ||
164 | if (walk_state->arguments[index].object) { | ||
165 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Deleting Arg%d=%p\n", | ||
166 | index, | ||
167 | walk_state->arguments[index].object)); | ||
168 | |||
169 | /* Detach object (if present) and remove a reference */ | ||
170 | |||
171 | acpi_ns_detach_object(&walk_state->arguments[index]); | ||
172 | } | ||
173 | } | ||
174 | |||
175 | return_VOID; | ||
176 | } | ||
177 | |||
178 | /******************************************************************************* | ||
179 | * | ||
180 | * FUNCTION: acpi_ds_method_data_init_args | ||
181 | * | ||
182 | * PARAMETERS: *Params - Pointer to a parameter list for the method | ||
183 | * max_param_count - The arg count for this method | ||
184 | * walk_state - Current walk state object | ||
185 | * | ||
186 | * RETURN: Status | ||
187 | * | ||
188 | * DESCRIPTION: Initialize arguments for a method. The parameter list is a list | ||
189 | * of ACPI operand objects, either null terminated or whose length | ||
190 | * is defined by max_param_count. | ||
191 | * | ||
192 | ******************************************************************************/ | ||
193 | |||
194 | acpi_status | ||
195 | acpi_ds_method_data_init_args(union acpi_operand_object **params, | ||
196 | u32 max_param_count, | ||
197 | struct acpi_walk_state *walk_state) | ||
198 | { | ||
199 | acpi_status status; | ||
200 | u32 index = 0; | ||
201 | |||
202 | ACPI_FUNCTION_TRACE_PTR(ds_method_data_init_args, params); | ||
203 | |||
204 | if (!params) { | ||
205 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
206 | "No param list passed to method\n")); | ||
207 | return_ACPI_STATUS(AE_OK); | ||
208 | } | ||
209 | |||
210 | /* Copy passed parameters into the new method stack frame */ | ||
211 | |||
212 | while ((index < ACPI_METHOD_NUM_ARGS) && | ||
213 | (index < max_param_count) && params[index]) { | ||
214 | /* | ||
215 | * A valid parameter. | ||
216 | * Store the argument in the method/walk descriptor. | ||
217 | * Do not copy the arg in order to implement call by reference | ||
218 | */ | ||
219 | status = acpi_ds_method_data_set_value(ACPI_REFCLASS_ARG, index, | ||
220 | params[index], | ||
221 | walk_state); | ||
222 | if (ACPI_FAILURE(status)) { | ||
223 | return_ACPI_STATUS(status); | ||
224 | } | ||
225 | |||
226 | index++; | ||
227 | } | ||
228 | |||
229 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "%d args passed to method\n", index)); | ||
230 | return_ACPI_STATUS(AE_OK); | ||
231 | } | ||
232 | |||
233 | /******************************************************************************* | ||
234 | * | ||
235 | * FUNCTION: acpi_ds_method_data_get_node | ||
236 | * | ||
237 | * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or | ||
238 | * ACPI_REFCLASS_ARG | ||
239 | * Index - Which Local or Arg whose type to get | ||
240 | * walk_state - Current walk state object | ||
241 | * Node - Where the node is returned. | ||
242 | * | ||
243 | * RETURN: Status and node | ||
244 | * | ||
245 | * DESCRIPTION: Get the Node associated with a local or arg. | ||
246 | * | ||
247 | ******************************************************************************/ | ||
248 | |||
249 | acpi_status | ||
250 | acpi_ds_method_data_get_node(u8 type, | ||
251 | u32 index, | ||
252 | struct acpi_walk_state *walk_state, | ||
253 | struct acpi_namespace_node **node) | ||
254 | { | ||
255 | ACPI_FUNCTION_TRACE(ds_method_data_get_node); | ||
256 | |||
257 | /* | ||
258 | * Method Locals and Arguments are supported | ||
259 | */ | ||
260 | switch (type) { | ||
261 | case ACPI_REFCLASS_LOCAL: | ||
262 | |||
263 | if (index > ACPI_METHOD_MAX_LOCAL) { | ||
264 | ACPI_ERROR((AE_INFO, | ||
265 | "Local index %d is invalid (max %d)", | ||
266 | index, ACPI_METHOD_MAX_LOCAL)); | ||
267 | return_ACPI_STATUS(AE_AML_INVALID_INDEX); | ||
268 | } | ||
269 | |||
270 | /* Return a pointer to the pseudo-node */ | ||
271 | |||
272 | *node = &walk_state->local_variables[index]; | ||
273 | break; | ||
274 | |||
275 | case ACPI_REFCLASS_ARG: | ||
276 | |||
277 | if (index > ACPI_METHOD_MAX_ARG) { | ||
278 | ACPI_ERROR((AE_INFO, | ||
279 | "Arg index %d is invalid (max %d)", | ||
280 | index, ACPI_METHOD_MAX_ARG)); | ||
281 | return_ACPI_STATUS(AE_AML_INVALID_INDEX); | ||
282 | } | ||
283 | |||
284 | /* Return a pointer to the pseudo-node */ | ||
285 | |||
286 | *node = &walk_state->arguments[index]; | ||
287 | break; | ||
288 | |||
289 | default: | ||
290 | ACPI_ERROR((AE_INFO, "Type %d is invalid", type)); | ||
291 | return_ACPI_STATUS(AE_TYPE); | ||
292 | } | ||
293 | |||
294 | return_ACPI_STATUS(AE_OK); | ||
295 | } | ||
296 | |||
297 | /******************************************************************************* | ||
298 | * | ||
299 | * FUNCTION: acpi_ds_method_data_set_value | ||
300 | * | ||
301 | * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or | ||
302 | * ACPI_REFCLASS_ARG | ||
303 | * Index - Which Local or Arg to get | ||
304 | * Object - Object to be inserted into the stack entry | ||
305 | * walk_state - Current walk state object | ||
306 | * | ||
307 | * RETURN: Status | ||
308 | * | ||
309 | * DESCRIPTION: Insert an object onto the method stack at entry Opcode:Index. | ||
310 | * Note: There is no "implicit conversion" for locals. | ||
311 | * | ||
312 | ******************************************************************************/ | ||
313 | |||
314 | static acpi_status | ||
315 | acpi_ds_method_data_set_value(u8 type, | ||
316 | u32 index, | ||
317 | union acpi_operand_object *object, | ||
318 | struct acpi_walk_state *walk_state) | ||
319 | { | ||
320 | acpi_status status; | ||
321 | struct acpi_namespace_node *node; | ||
322 | |||
323 | ACPI_FUNCTION_TRACE(ds_method_data_set_value); | ||
324 | |||
325 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
326 | "NewObj %p Type %2.2X, Refs=%d [%s]\n", object, | ||
327 | type, object->common.reference_count, | ||
328 | acpi_ut_get_type_name(object->common.type))); | ||
329 | |||
330 | /* Get the namespace node for the arg/local */ | ||
331 | |||
332 | status = acpi_ds_method_data_get_node(type, index, walk_state, &node); | ||
333 | if (ACPI_FAILURE(status)) { | ||
334 | return_ACPI_STATUS(status); | ||
335 | } | ||
336 | |||
337 | /* | ||
338 | * Increment ref count so object can't be deleted while installed. | ||
339 | * NOTE: We do not copy the object in order to preserve the call by | ||
340 | * reference semantics of ACPI Control Method invocation. | ||
341 | * (See ACPI Specification 2.0_c) | ||
342 | */ | ||
343 | acpi_ut_add_reference(object); | ||
344 | |||
345 | /* Install the object */ | ||
346 | |||
347 | node->object = object; | ||
348 | return_ACPI_STATUS(status); | ||
349 | } | ||
350 | |||
351 | /******************************************************************************* | ||
352 | * | ||
353 | * FUNCTION: acpi_ds_method_data_get_value | ||
354 | * | ||
355 | * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or | ||
356 | * ACPI_REFCLASS_ARG | ||
357 | * Index - Which local_var or argument to get | ||
358 | * walk_state - Current walk state object | ||
359 | * dest_desc - Where Arg or Local value is returned | ||
360 | * | ||
361 | * RETURN: Status | ||
362 | * | ||
363 | * DESCRIPTION: Retrieve value of selected Arg or Local for this method | ||
364 | * Used only in acpi_ex_resolve_to_value(). | ||
365 | * | ||
366 | ******************************************************************************/ | ||
367 | |||
368 | acpi_status | ||
369 | acpi_ds_method_data_get_value(u8 type, | ||
370 | u32 index, | ||
371 | struct acpi_walk_state *walk_state, | ||
372 | union acpi_operand_object **dest_desc) | ||
373 | { | ||
374 | acpi_status status; | ||
375 | struct acpi_namespace_node *node; | ||
376 | union acpi_operand_object *object; | ||
377 | |||
378 | ACPI_FUNCTION_TRACE(ds_method_data_get_value); | ||
379 | |||
380 | /* Validate the object descriptor */ | ||
381 | |||
382 | if (!dest_desc) { | ||
383 | ACPI_ERROR((AE_INFO, "Null object descriptor pointer")); | ||
384 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
385 | } | ||
386 | |||
387 | /* Get the namespace node for the arg/local */ | ||
388 | |||
389 | status = acpi_ds_method_data_get_node(type, index, walk_state, &node); | ||
390 | if (ACPI_FAILURE(status)) { | ||
391 | return_ACPI_STATUS(status); | ||
392 | } | ||
393 | |||
394 | /* Get the object from the node */ | ||
395 | |||
396 | object = node->object; | ||
397 | |||
398 | /* Examine the returned object, it must be valid. */ | ||
399 | |||
400 | if (!object) { | ||
401 | /* | ||
402 | * Index points to uninitialized object. | ||
403 | * This means that either 1) The expected argument was | ||
404 | * not passed to the method, or 2) A local variable | ||
405 | * was referenced by the method (via the ASL) | ||
406 | * before it was initialized. Either case is an error. | ||
407 | */ | ||
408 | |||
409 | /* If slack enabled, init the local_x/arg_x to an Integer of value zero */ | ||
410 | |||
411 | if (acpi_gbl_enable_interpreter_slack) { | ||
412 | object = | ||
413 | acpi_ut_create_internal_object(ACPI_TYPE_INTEGER); | ||
414 | if (!object) { | ||
415 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
416 | } | ||
417 | |||
418 | object->integer.value = 0; | ||
419 | node->object = object; | ||
420 | } | ||
421 | |||
422 | /* Otherwise, return the error */ | ||
423 | |||
424 | else | ||
425 | switch (type) { | ||
426 | case ACPI_REFCLASS_ARG: | ||
427 | |||
428 | ACPI_ERROR((AE_INFO, | ||
429 | "Uninitialized Arg[%d] at node %p", | ||
430 | index, node)); | ||
431 | |||
432 | return_ACPI_STATUS(AE_AML_UNINITIALIZED_ARG); | ||
433 | |||
434 | case ACPI_REFCLASS_LOCAL: | ||
435 | |||
436 | ACPI_ERROR((AE_INFO, | ||
437 | "Uninitialized Local[%d] at node %p", | ||
438 | index, node)); | ||
439 | |||
440 | return_ACPI_STATUS(AE_AML_UNINITIALIZED_LOCAL); | ||
441 | |||
442 | default: | ||
443 | |||
444 | ACPI_ERROR((AE_INFO, | ||
445 | "Not a Arg/Local opcode: %X", | ||
446 | type)); | ||
447 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
448 | } | ||
449 | } | ||
450 | |||
451 | /* | ||
452 | * The Index points to an initialized and valid object. | ||
453 | * Return an additional reference to the object | ||
454 | */ | ||
455 | *dest_desc = object; | ||
456 | acpi_ut_add_reference(object); | ||
457 | |||
458 | return_ACPI_STATUS(AE_OK); | ||
459 | } | ||
460 | |||
461 | /******************************************************************************* | ||
462 | * | ||
463 | * FUNCTION: acpi_ds_method_data_delete_value | ||
464 | * | ||
465 | * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or | ||
466 | * ACPI_REFCLASS_ARG | ||
467 | * Index - Which local_var or argument to delete | ||
468 | * walk_state - Current walk state object | ||
469 | * | ||
470 | * RETURN: None | ||
471 | * | ||
472 | * DESCRIPTION: Delete the entry at Opcode:Index. Inserts | ||
473 | * a null into the stack slot after the object is deleted. | ||
474 | * | ||
475 | ******************************************************************************/ | ||
476 | |||
477 | static void | ||
478 | acpi_ds_method_data_delete_value(u8 type, | ||
479 | u32 index, struct acpi_walk_state *walk_state) | ||
480 | { | ||
481 | acpi_status status; | ||
482 | struct acpi_namespace_node *node; | ||
483 | union acpi_operand_object *object; | ||
484 | |||
485 | ACPI_FUNCTION_TRACE(ds_method_data_delete_value); | ||
486 | |||
487 | /* Get the namespace node for the arg/local */ | ||
488 | |||
489 | status = acpi_ds_method_data_get_node(type, index, walk_state, &node); | ||
490 | if (ACPI_FAILURE(status)) { | ||
491 | return_VOID; | ||
492 | } | ||
493 | |||
494 | /* Get the associated object */ | ||
495 | |||
496 | object = acpi_ns_get_attached_object(node); | ||
497 | |||
498 | /* | ||
499 | * Undefine the Arg or Local by setting its descriptor | ||
500 | * pointer to NULL. Locals/Args can contain both | ||
501 | * ACPI_OPERAND_OBJECTS and ACPI_NAMESPACE_NODEs | ||
502 | */ | ||
503 | node->object = NULL; | ||
504 | |||
505 | if ((object) && | ||
506 | (ACPI_GET_DESCRIPTOR_TYPE(object) == ACPI_DESC_TYPE_OPERAND)) { | ||
507 | /* | ||
508 | * There is a valid object. | ||
509 | * Decrement the reference count by one to balance the | ||
510 | * increment when the object was stored. | ||
511 | */ | ||
512 | acpi_ut_remove_reference(object); | ||
513 | } | ||
514 | |||
515 | return_VOID; | ||
516 | } | ||
517 | |||
518 | /******************************************************************************* | ||
519 | * | ||
520 | * FUNCTION: acpi_ds_store_object_to_local | ||
521 | * | ||
522 | * PARAMETERS: Type - Either ACPI_REFCLASS_LOCAL or | ||
523 | * ACPI_REFCLASS_ARG | ||
524 | * Index - Which Local or Arg to set | ||
525 | * obj_desc - Value to be stored | ||
526 | * walk_state - Current walk state | ||
527 | * | ||
528 | * RETURN: Status | ||
529 | * | ||
530 | * DESCRIPTION: Store a value in an Arg or Local. The obj_desc is installed | ||
531 | * as the new value for the Arg or Local and the reference count | ||
532 | * for obj_desc is incremented. | ||
533 | * | ||
534 | ******************************************************************************/ | ||
535 | |||
536 | acpi_status | ||
537 | acpi_ds_store_object_to_local(u8 type, | ||
538 | u32 index, | ||
539 | union acpi_operand_object *obj_desc, | ||
540 | struct acpi_walk_state *walk_state) | ||
541 | { | ||
542 | acpi_status status; | ||
543 | struct acpi_namespace_node *node; | ||
544 | union acpi_operand_object *current_obj_desc; | ||
545 | union acpi_operand_object *new_obj_desc; | ||
546 | |||
547 | ACPI_FUNCTION_TRACE(ds_store_object_to_local); | ||
548 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Type=%2.2X Index=%d Obj=%p\n", | ||
549 | type, index, obj_desc)); | ||
550 | |||
551 | /* Parameter validation */ | ||
552 | |||
553 | if (!obj_desc) { | ||
554 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
555 | } | ||
556 | |||
557 | /* Get the namespace node for the arg/local */ | ||
558 | |||
559 | status = acpi_ds_method_data_get_node(type, index, walk_state, &node); | ||
560 | if (ACPI_FAILURE(status)) { | ||
561 | return_ACPI_STATUS(status); | ||
562 | } | ||
563 | |||
564 | current_obj_desc = acpi_ns_get_attached_object(node); | ||
565 | if (current_obj_desc == obj_desc) { | ||
566 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p already installed!\n", | ||
567 | obj_desc)); | ||
568 | return_ACPI_STATUS(status); | ||
569 | } | ||
570 | |||
571 | /* | ||
572 | * If the reference count on the object is more than one, we must | ||
573 | * take a copy of the object before we store. A reference count | ||
574 | * of exactly 1 means that the object was just created during the | ||
575 | * evaluation of an expression, and we can safely use it since it | ||
576 | * is not used anywhere else. | ||
577 | */ | ||
578 | new_obj_desc = obj_desc; | ||
579 | if (obj_desc->common.reference_count > 1) { | ||
580 | status = | ||
581 | acpi_ut_copy_iobject_to_iobject(obj_desc, &new_obj_desc, | ||
582 | walk_state); | ||
583 | if (ACPI_FAILURE(status)) { | ||
584 | return_ACPI_STATUS(status); | ||
585 | } | ||
586 | } | ||
587 | |||
588 | /* | ||
589 | * If there is an object already in this slot, we either | ||
590 | * have to delete it, or if this is an argument and there | ||
591 | * is an object reference stored there, we have to do | ||
592 | * an indirect store! | ||
593 | */ | ||
594 | if (current_obj_desc) { | ||
595 | /* | ||
596 | * Check for an indirect store if an argument | ||
597 | * contains an object reference (stored as an Node). | ||
598 | * We don't allow this automatic dereferencing for | ||
599 | * locals, since a store to a local should overwrite | ||
600 | * anything there, including an object reference. | ||
601 | * | ||
602 | * If both Arg0 and Local0 contain ref_of (Local4): | ||
603 | * | ||
604 | * Store (1, Arg0) - Causes indirect store to local4 | ||
605 | * Store (1, Local0) - Stores 1 in local0, overwriting | ||
606 | * the reference to local4 | ||
607 | * Store (1, de_refof (Local0)) - Causes indirect store to local4 | ||
608 | * | ||
609 | * Weird, but true. | ||
610 | */ | ||
611 | if (type == ACPI_REFCLASS_ARG) { | ||
612 | /* | ||
613 | * If we have a valid reference object that came from ref_of(), | ||
614 | * do the indirect store | ||
615 | */ | ||
616 | if ((ACPI_GET_DESCRIPTOR_TYPE(current_obj_desc) == | ||
617 | ACPI_DESC_TYPE_OPERAND) | ||
618 | && (current_obj_desc->common.type == | ||
619 | ACPI_TYPE_LOCAL_REFERENCE) | ||
620 | && (current_obj_desc->reference.class == | ||
621 | ACPI_REFCLASS_REFOF)) { | ||
622 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
623 | "Arg (%p) is an ObjRef(Node), storing in node %p\n", | ||
624 | new_obj_desc, | ||
625 | current_obj_desc)); | ||
626 | |||
627 | /* | ||
628 | * Store this object to the Node (perform the indirect store) | ||
629 | * NOTE: No implicit conversion is performed, as per the ACPI | ||
630 | * specification rules on storing to Locals/Args. | ||
631 | */ | ||
632 | status = | ||
633 | acpi_ex_store_object_to_node(new_obj_desc, | ||
634 | current_obj_desc-> | ||
635 | reference. | ||
636 | object, | ||
637 | walk_state, | ||
638 | ACPI_NO_IMPLICIT_CONVERSION); | ||
639 | |||
640 | /* Remove local reference if we copied the object above */ | ||
641 | |||
642 | if (new_obj_desc != obj_desc) { | ||
643 | acpi_ut_remove_reference(new_obj_desc); | ||
644 | } | ||
645 | return_ACPI_STATUS(status); | ||
646 | } | ||
647 | } | ||
648 | |||
649 | /* Delete the existing object before storing the new one */ | ||
650 | |||
651 | acpi_ds_method_data_delete_value(type, index, walk_state); | ||
652 | } | ||
653 | |||
654 | /* | ||
655 | * Install the Obj descriptor (*new_obj_desc) into | ||
656 | * the descriptor for the Arg or Local. | ||
657 | * (increments the object reference count by one) | ||
658 | */ | ||
659 | status = | ||
660 | acpi_ds_method_data_set_value(type, index, new_obj_desc, | ||
661 | walk_state); | ||
662 | |||
663 | /* Remove local reference if we copied the object above */ | ||
664 | |||
665 | if (new_obj_desc != obj_desc) { | ||
666 | acpi_ut_remove_reference(new_obj_desc); | ||
667 | } | ||
668 | |||
669 | return_ACPI_STATUS(status); | ||
670 | } | ||
671 | |||
672 | #ifdef ACPI_OBSOLETE_FUNCTIONS | ||
673 | /******************************************************************************* | ||
674 | * | ||
675 | * FUNCTION: acpi_ds_method_data_get_type | ||
676 | * | ||
677 | * PARAMETERS: Opcode - Either AML_LOCAL_OP or AML_ARG_OP | ||
678 | * Index - Which Local or Arg whose type to get | ||
679 | * walk_state - Current walk state object | ||
680 | * | ||
681 | * RETURN: Data type of current value of the selected Arg or Local | ||
682 | * | ||
683 | * DESCRIPTION: Get the type of the object stored in the Local or Arg | ||
684 | * | ||
685 | ******************************************************************************/ | ||
686 | |||
687 | acpi_object_type | ||
688 | acpi_ds_method_data_get_type(u16 opcode, | ||
689 | u32 index, struct acpi_walk_state *walk_state) | ||
690 | { | ||
691 | acpi_status status; | ||
692 | struct acpi_namespace_node *node; | ||
693 | union acpi_operand_object *object; | ||
694 | |||
695 | ACPI_FUNCTION_TRACE(ds_method_data_get_type); | ||
696 | |||
697 | /* Get the namespace node for the arg/local */ | ||
698 | |||
699 | status = acpi_ds_method_data_get_node(opcode, index, walk_state, &node); | ||
700 | if (ACPI_FAILURE(status)) { | ||
701 | return_VALUE((ACPI_TYPE_NOT_FOUND)); | ||
702 | } | ||
703 | |||
704 | /* Get the object */ | ||
705 | |||
706 | object = acpi_ns_get_attached_object(node); | ||
707 | if (!object) { | ||
708 | |||
709 | /* Uninitialized local/arg, return TYPE_ANY */ | ||
710 | |||
711 | return_VALUE(ACPI_TYPE_ANY); | ||
712 | } | ||
713 | |||
714 | /* Get the object type */ | ||
715 | |||
716 | return_VALUE(ACPI_GET_OBJECT_TYPE(object)); | ||
717 | } | ||
718 | #endif | ||
diff --git a/drivers/acpi/dispatcher/dsobject.c b/drivers/acpi/dispatcher/dsobject.c deleted file mode 100644 index 6e6c73cc39ff..000000000000 --- a/drivers/acpi/dispatcher/dsobject.c +++ /dev/null | |||
@@ -1,813 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dsobject - Dispatcher object management routines | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/acparser.h> | ||
47 | #include <acpi/amlcode.h> | ||
48 | #include <acpi/acdispat.h> | ||
49 | #include <acpi/acnamesp.h> | ||
50 | #include <acpi/acinterp.h> | ||
51 | |||
52 | #define _COMPONENT ACPI_DISPATCHER | ||
53 | ACPI_MODULE_NAME("dsobject") | ||
54 | |||
55 | /* Local prototypes */ | ||
56 | static acpi_status | ||
57 | acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | ||
58 | union acpi_parse_object *op, | ||
59 | union acpi_operand_object **obj_desc_ptr); | ||
60 | |||
61 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
62 | /******************************************************************************* | ||
63 | * | ||
64 | * FUNCTION: acpi_ds_build_internal_object | ||
65 | * | ||
66 | * PARAMETERS: walk_state - Current walk state | ||
67 | * Op - Parser object to be translated | ||
68 | * obj_desc_ptr - Where the ACPI internal object is returned | ||
69 | * | ||
70 | * RETURN: Status | ||
71 | * | ||
72 | * DESCRIPTION: Translate a parser Op object to the equivalent namespace object | ||
73 | * Simple objects are any objects other than a package object! | ||
74 | * | ||
75 | ******************************************************************************/ | ||
76 | |||
77 | static acpi_status | ||
78 | acpi_ds_build_internal_object(struct acpi_walk_state *walk_state, | ||
79 | union acpi_parse_object *op, | ||
80 | union acpi_operand_object **obj_desc_ptr) | ||
81 | { | ||
82 | union acpi_operand_object *obj_desc; | ||
83 | acpi_status status; | ||
84 | |||
85 | ACPI_FUNCTION_TRACE(ds_build_internal_object); | ||
86 | |||
87 | *obj_desc_ptr = NULL; | ||
88 | if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { | ||
89 | /* | ||
90 | * This is a named object reference. If this name was | ||
91 | * previously looked up in the namespace, it was stored in this op. | ||
92 | * Otherwise, go ahead and look it up now | ||
93 | */ | ||
94 | if (!op->common.node) { | ||
95 | status = acpi_ns_lookup(walk_state->scope_info, | ||
96 | op->common.value.string, | ||
97 | ACPI_TYPE_ANY, | ||
98 | ACPI_IMODE_EXECUTE, | ||
99 | ACPI_NS_SEARCH_PARENT | | ||
100 | ACPI_NS_DONT_OPEN_SCOPE, NULL, | ||
101 | ACPI_CAST_INDIRECT_PTR(struct | ||
102 | acpi_namespace_node, | ||
103 | &(op-> | ||
104 | common. | ||
105 | node))); | ||
106 | if (ACPI_FAILURE(status)) { | ||
107 | |||
108 | /* Check if we are resolving a named reference within a package */ | ||
109 | |||
110 | if ((status == AE_NOT_FOUND) | ||
111 | && (acpi_gbl_enable_interpreter_slack) | ||
112 | && | ||
113 | ((op->common.parent->common.aml_opcode == | ||
114 | AML_PACKAGE_OP) | ||
115 | || (op->common.parent->common.aml_opcode == | ||
116 | AML_VAR_PACKAGE_OP))) { | ||
117 | /* | ||
118 | * We didn't find the target and we are populating elements | ||
119 | * of a package - ignore if slack enabled. Some ASL code | ||
120 | * contains dangling invalid references in packages and | ||
121 | * expects that no exception will be issued. Leave the | ||
122 | * element as a null element. It cannot be used, but it | ||
123 | * can be overwritten by subsequent ASL code - this is | ||
124 | * typically the case. | ||
125 | */ | ||
126 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
127 | "Ignoring unresolved reference in package [%4.4s]\n", | ||
128 | walk_state-> | ||
129 | scope_info->scope. | ||
130 | node->name.ascii)); | ||
131 | |||
132 | return_ACPI_STATUS(AE_OK); | ||
133 | } else { | ||
134 | ACPI_ERROR_NAMESPACE(op->common.value. | ||
135 | string, status); | ||
136 | } | ||
137 | |||
138 | return_ACPI_STATUS(status); | ||
139 | } | ||
140 | } | ||
141 | |||
142 | /* Special object resolution for elements of a package */ | ||
143 | |||
144 | if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || | ||
145 | (op->common.parent->common.aml_opcode == | ||
146 | AML_VAR_PACKAGE_OP)) { | ||
147 | /* | ||
148 | * Attempt to resolve the node to a value before we insert it into | ||
149 | * the package. If this is a reference to a common data type, | ||
150 | * resolve it immediately. According to the ACPI spec, package | ||
151 | * elements can only be "data objects" or method references. | ||
152 | * Attempt to resolve to an Integer, Buffer, String or Package. | ||
153 | * If cannot, return the named reference (for things like Devices, | ||
154 | * Methods, etc.) Buffer Fields and Fields will resolve to simple | ||
155 | * objects (int/buf/str/pkg). | ||
156 | * | ||
157 | * NOTE: References to things like Devices, Methods, Mutexes, etc. | ||
158 | * will remain as named references. This behavior is not described | ||
159 | * in the ACPI spec, but it appears to be an oversight. | ||
160 | */ | ||
161 | obj_desc = | ||
162 | ACPI_CAST_PTR(union acpi_operand_object, | ||
163 | op->common.node); | ||
164 | |||
165 | status = | ||
166 | acpi_ex_resolve_node_to_value(ACPI_CAST_INDIRECT_PTR | ||
167 | (struct | ||
168 | acpi_namespace_node, | ||
169 | &obj_desc), | ||
170 | walk_state); | ||
171 | if (ACPI_FAILURE(status)) { | ||
172 | return_ACPI_STATUS(status); | ||
173 | } | ||
174 | |||
175 | switch (op->common.node->type) { | ||
176 | /* | ||
177 | * For these types, we need the actual node, not the subobject. | ||
178 | * However, the subobject did not get an extra reference count above. | ||
179 | * | ||
180 | * TBD: should ex_resolve_node_to_value be changed to fix this? | ||
181 | */ | ||
182 | case ACPI_TYPE_DEVICE: | ||
183 | case ACPI_TYPE_THERMAL: | ||
184 | |||
185 | acpi_ut_add_reference(op->common.node->object); | ||
186 | |||
187 | /*lint -fallthrough */ | ||
188 | /* | ||
189 | * For these types, we need the actual node, not the subobject. | ||
190 | * The subobject got an extra reference count in ex_resolve_node_to_value. | ||
191 | */ | ||
192 | case ACPI_TYPE_MUTEX: | ||
193 | case ACPI_TYPE_METHOD: | ||
194 | case ACPI_TYPE_POWER: | ||
195 | case ACPI_TYPE_PROCESSOR: | ||
196 | case ACPI_TYPE_EVENT: | ||
197 | case ACPI_TYPE_REGION: | ||
198 | |||
199 | /* We will create a reference object for these types below */ | ||
200 | break; | ||
201 | |||
202 | default: | ||
203 | /* | ||
204 | * All other types - the node was resolved to an actual | ||
205 | * object, we are done. | ||
206 | */ | ||
207 | goto exit; | ||
208 | } | ||
209 | } | ||
210 | } | ||
211 | |||
212 | /* Create and init a new internal ACPI object */ | ||
213 | |||
214 | obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info | ||
215 | (op->common.aml_opcode))-> | ||
216 | object_type); | ||
217 | if (!obj_desc) { | ||
218 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
219 | } | ||
220 | |||
221 | status = | ||
222 | acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode, | ||
223 | &obj_desc); | ||
224 | if (ACPI_FAILURE(status)) { | ||
225 | acpi_ut_remove_reference(obj_desc); | ||
226 | return_ACPI_STATUS(status); | ||
227 | } | ||
228 | |||
229 | exit: | ||
230 | *obj_desc_ptr = obj_desc; | ||
231 | return_ACPI_STATUS(status); | ||
232 | } | ||
233 | |||
234 | /******************************************************************************* | ||
235 | * | ||
236 | * FUNCTION: acpi_ds_build_internal_buffer_obj | ||
237 | * | ||
238 | * PARAMETERS: walk_state - Current walk state | ||
239 | * Op - Parser object to be translated | ||
240 | * buffer_length - Length of the buffer | ||
241 | * obj_desc_ptr - Where the ACPI internal object is returned | ||
242 | * | ||
243 | * RETURN: Status | ||
244 | * | ||
245 | * DESCRIPTION: Translate a parser Op package object to the equivalent | ||
246 | * namespace object | ||
247 | * | ||
248 | ******************************************************************************/ | ||
249 | |||
250 | acpi_status | ||
251 | acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state, | ||
252 | union acpi_parse_object *op, | ||
253 | u32 buffer_length, | ||
254 | union acpi_operand_object **obj_desc_ptr) | ||
255 | { | ||
256 | union acpi_parse_object *arg; | ||
257 | union acpi_operand_object *obj_desc; | ||
258 | union acpi_parse_object *byte_list; | ||
259 | u32 byte_list_length = 0; | ||
260 | |||
261 | ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj); | ||
262 | |||
263 | /* | ||
264 | * If we are evaluating a Named buffer object "Name (xxxx, Buffer)". | ||
265 | * The buffer object already exists (from the NS node), otherwise it must | ||
266 | * be created. | ||
267 | */ | ||
268 | obj_desc = *obj_desc_ptr; | ||
269 | if (!obj_desc) { | ||
270 | |||
271 | /* Create a new buffer object */ | ||
272 | |||
273 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER); | ||
274 | *obj_desc_ptr = obj_desc; | ||
275 | if (!obj_desc) { | ||
276 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
277 | } | ||
278 | } | ||
279 | |||
280 | /* | ||
281 | * Second arg is the buffer data (optional) byte_list can be either | ||
282 | * individual bytes or a string initializer. In either case, a | ||
283 | * byte_list appears in the AML. | ||
284 | */ | ||
285 | arg = op->common.value.arg; /* skip first arg */ | ||
286 | |||
287 | byte_list = arg->named.next; | ||
288 | if (byte_list) { | ||
289 | if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) { | ||
290 | ACPI_ERROR((AE_INFO, | ||
291 | "Expecting bytelist, got AML opcode %X in op %p", | ||
292 | byte_list->common.aml_opcode, byte_list)); | ||
293 | |||
294 | acpi_ut_remove_reference(obj_desc); | ||
295 | return (AE_TYPE); | ||
296 | } | ||
297 | |||
298 | byte_list_length = (u32) byte_list->common.value.integer; | ||
299 | } | ||
300 | |||
301 | /* | ||
302 | * The buffer length (number of bytes) will be the larger of: | ||
303 | * 1) The specified buffer length and | ||
304 | * 2) The length of the initializer byte list | ||
305 | */ | ||
306 | obj_desc->buffer.length = buffer_length; | ||
307 | if (byte_list_length > buffer_length) { | ||
308 | obj_desc->buffer.length = byte_list_length; | ||
309 | } | ||
310 | |||
311 | /* Allocate the buffer */ | ||
312 | |||
313 | if (obj_desc->buffer.length == 0) { | ||
314 | obj_desc->buffer.pointer = NULL; | ||
315 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
316 | "Buffer defined with zero length in AML, creating\n")); | ||
317 | } else { | ||
318 | obj_desc->buffer.pointer = | ||
319 | ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length); | ||
320 | if (!obj_desc->buffer.pointer) { | ||
321 | acpi_ut_delete_object_desc(obj_desc); | ||
322 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
323 | } | ||
324 | |||
325 | /* Initialize buffer from the byte_list (if present) */ | ||
326 | |||
327 | if (byte_list) { | ||
328 | ACPI_MEMCPY(obj_desc->buffer.pointer, | ||
329 | byte_list->named.data, byte_list_length); | ||
330 | } | ||
331 | } | ||
332 | |||
333 | obj_desc->buffer.flags |= AOPOBJ_DATA_VALID; | ||
334 | op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); | ||
335 | return_ACPI_STATUS(AE_OK); | ||
336 | } | ||
337 | |||
338 | /******************************************************************************* | ||
339 | * | ||
340 | * FUNCTION: acpi_ds_build_internal_package_obj | ||
341 | * | ||
342 | * PARAMETERS: walk_state - Current walk state | ||
343 | * Op - Parser object to be translated | ||
344 | * element_count - Number of elements in the package - this is | ||
345 | * the num_elements argument to Package() | ||
346 | * obj_desc_ptr - Where the ACPI internal object is returned | ||
347 | * | ||
348 | * RETURN: Status | ||
349 | * | ||
350 | * DESCRIPTION: Translate a parser Op package object to the equivalent | ||
351 | * namespace object | ||
352 | * | ||
353 | * NOTE: The number of elements in the package will be always be the num_elements | ||
354 | * count, regardless of the number of elements in the package list. If | ||
355 | * num_elements is smaller, only that many package list elements are used. | ||
356 | * if num_elements is larger, the Package object is padded out with | ||
357 | * objects of type Uninitialized (as per ACPI spec.) | ||
358 | * | ||
359 | * Even though the ASL compilers do not allow num_elements to be smaller | ||
360 | * than the Package list length (for the fixed length package opcode), some | ||
361 | * BIOS code modifies the AML on the fly to adjust the num_elements, and | ||
362 | * this code compensates for that. This also provides compatibility with | ||
363 | * other AML interpreters. | ||
364 | * | ||
365 | ******************************************************************************/ | ||
366 | |||
367 | acpi_status | ||
368 | acpi_ds_build_internal_package_obj(struct acpi_walk_state *walk_state, | ||
369 | union acpi_parse_object *op, | ||
370 | u32 element_count, | ||
371 | union acpi_operand_object **obj_desc_ptr) | ||
372 | { | ||
373 | union acpi_parse_object *arg; | ||
374 | union acpi_parse_object *parent; | ||
375 | union acpi_operand_object *obj_desc = NULL; | ||
376 | acpi_status status = AE_OK; | ||
377 | unsigned i; | ||
378 | u16 index; | ||
379 | u16 reference_count; | ||
380 | |||
381 | ACPI_FUNCTION_TRACE(ds_build_internal_package_obj); | ||
382 | |||
383 | /* Find the parent of a possibly nested package */ | ||
384 | |||
385 | parent = op->common.parent; | ||
386 | while ((parent->common.aml_opcode == AML_PACKAGE_OP) || | ||
387 | (parent->common.aml_opcode == AML_VAR_PACKAGE_OP)) { | ||
388 | parent = parent->common.parent; | ||
389 | } | ||
390 | |||
391 | /* | ||
392 | * If we are evaluating a Named package object "Name (xxxx, Package)", | ||
393 | * the package object already exists, otherwise it must be created. | ||
394 | */ | ||
395 | obj_desc = *obj_desc_ptr; | ||
396 | if (!obj_desc) { | ||
397 | obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_PACKAGE); | ||
398 | *obj_desc_ptr = obj_desc; | ||
399 | if (!obj_desc) { | ||
400 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
401 | } | ||
402 | |||
403 | obj_desc->package.node = parent->common.node; | ||
404 | } | ||
405 | |||
406 | /* | ||
407 | * Allocate the element array (array of pointers to the individual | ||
408 | * objects) based on the num_elements parameter. Add an extra pointer slot | ||
409 | * so that the list is always null terminated. | ||
410 | */ | ||
411 | obj_desc->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size) | ||
412 | element_count + | ||
413 | 1) * sizeof(void *)); | ||
414 | |||
415 | if (!obj_desc->package.elements) { | ||
416 | acpi_ut_delete_object_desc(obj_desc); | ||
417 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
418 | } | ||
419 | |||
420 | obj_desc->package.count = element_count; | ||
421 | |||
422 | /* | ||
423 | * Initialize the elements of the package, up to the num_elements count. | ||
424 | * Package is automatically padded with uninitialized (NULL) elements | ||
425 | * if num_elements is greater than the package list length. Likewise, | ||
426 | * Package is truncated if num_elements is less than the list length. | ||
427 | */ | ||
428 | arg = op->common.value.arg; | ||
429 | arg = arg->common.next; | ||
430 | for (i = 0; arg && (i < element_count); i++) { | ||
431 | if (arg->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { | ||
432 | if (arg->common.node->type == ACPI_TYPE_METHOD) { | ||
433 | /* | ||
434 | * A method reference "looks" to the parser to be a method | ||
435 | * invocation, so we special case it here | ||
436 | */ | ||
437 | arg->common.aml_opcode = AML_INT_NAMEPATH_OP; | ||
438 | status = | ||
439 | acpi_ds_build_internal_object(walk_state, | ||
440 | arg, | ||
441 | &obj_desc-> | ||
442 | package. | ||
443 | elements[i]); | ||
444 | } else { | ||
445 | /* This package element is already built, just get it */ | ||
446 | |||
447 | obj_desc->package.elements[i] = | ||
448 | ACPI_CAST_PTR(union acpi_operand_object, | ||
449 | arg->common.node); | ||
450 | } | ||
451 | } else { | ||
452 | status = acpi_ds_build_internal_object(walk_state, arg, | ||
453 | &obj_desc-> | ||
454 | package. | ||
455 | elements[i]); | ||
456 | } | ||
457 | |||
458 | if (*obj_desc_ptr) { | ||
459 | |||
460 | /* Existing package, get existing reference count */ | ||
461 | |||
462 | reference_count = | ||
463 | (*obj_desc_ptr)->common.reference_count; | ||
464 | if (reference_count > 1) { | ||
465 | |||
466 | /* Make new element ref count match original ref count */ | ||
467 | |||
468 | for (index = 0; index < (reference_count - 1); | ||
469 | index++) { | ||
470 | acpi_ut_add_reference((obj_desc-> | ||
471 | package. | ||
472 | elements[i])); | ||
473 | } | ||
474 | } | ||
475 | } | ||
476 | |||
477 | arg = arg->common.next; | ||
478 | } | ||
479 | |||
480 | /* Check for match between num_elements and actual length of package_list */ | ||
481 | |||
482 | if (arg) { | ||
483 | /* | ||
484 | * num_elements was exhausted, but there are remaining elements in the | ||
485 | * package_list. | ||
486 | * | ||
487 | * Note: technically, this is an error, from ACPI spec: "It is an error | ||
488 | * for NumElements to be less than the number of elements in the | ||
489 | * PackageList". However, for now, we just print an error message and | ||
490 | * no exception is returned. | ||
491 | */ | ||
492 | while (arg) { | ||
493 | |||
494 | /* Find out how many elements there really are */ | ||
495 | |||
496 | i++; | ||
497 | arg = arg->common.next; | ||
498 | } | ||
499 | |||
500 | ACPI_WARNING((AE_INFO, | ||
501 | "Package List length (%X) larger than NumElements count (%X), truncated\n", | ||
502 | i, element_count)); | ||
503 | } else if (i < element_count) { | ||
504 | /* | ||
505 | * Arg list (elements) was exhausted, but we did not reach num_elements count. | ||
506 | * Note: this is not an error, the package is padded out with NULLs. | ||
507 | */ | ||
508 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
509 | "Package List length (%X) smaller than NumElements count (%X), padded with null elements\n", | ||
510 | i, element_count)); | ||
511 | } | ||
512 | |||
513 | obj_desc->package.flags |= AOPOBJ_DATA_VALID; | ||
514 | op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc); | ||
515 | return_ACPI_STATUS(status); | ||
516 | } | ||
517 | |||
518 | /******************************************************************************* | ||
519 | * | ||
520 | * FUNCTION: acpi_ds_create_node | ||
521 | * | ||
522 | * PARAMETERS: walk_state - Current walk state | ||
523 | * Node - NS Node to be initialized | ||
524 | * Op - Parser object to be translated | ||
525 | * | ||
526 | * RETURN: Status | ||
527 | * | ||
528 | * DESCRIPTION: Create the object to be associated with a namespace node | ||
529 | * | ||
530 | ******************************************************************************/ | ||
531 | |||
532 | acpi_status | ||
533 | acpi_ds_create_node(struct acpi_walk_state *walk_state, | ||
534 | struct acpi_namespace_node *node, | ||
535 | union acpi_parse_object *op) | ||
536 | { | ||
537 | acpi_status status; | ||
538 | union acpi_operand_object *obj_desc; | ||
539 | |||
540 | ACPI_FUNCTION_TRACE_PTR(ds_create_node, op); | ||
541 | |||
542 | /* | ||
543 | * Because of the execution pass through the non-control-method | ||
544 | * parts of the table, we can arrive here twice. Only init | ||
545 | * the named object node the first time through | ||
546 | */ | ||
547 | if (acpi_ns_get_attached_object(node)) { | ||
548 | return_ACPI_STATUS(AE_OK); | ||
549 | } | ||
550 | |||
551 | if (!op->common.value.arg) { | ||
552 | |||
553 | /* No arguments, there is nothing to do */ | ||
554 | |||
555 | return_ACPI_STATUS(AE_OK); | ||
556 | } | ||
557 | |||
558 | /* Build an internal object for the argument(s) */ | ||
559 | |||
560 | status = acpi_ds_build_internal_object(walk_state, op->common.value.arg, | ||
561 | &obj_desc); | ||
562 | if (ACPI_FAILURE(status)) { | ||
563 | return_ACPI_STATUS(status); | ||
564 | } | ||
565 | |||
566 | /* Re-type the object according to its argument */ | ||
567 | |||
568 | node->type = ACPI_GET_OBJECT_TYPE(obj_desc); | ||
569 | |||
570 | /* Attach obj to node */ | ||
571 | |||
572 | status = acpi_ns_attach_object(node, obj_desc, node->type); | ||
573 | |||
574 | /* Remove local reference to the object */ | ||
575 | |||
576 | acpi_ut_remove_reference(obj_desc); | ||
577 | return_ACPI_STATUS(status); | ||
578 | } | ||
579 | |||
580 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
581 | |||
582 | /******************************************************************************* | ||
583 | * | ||
584 | * FUNCTION: acpi_ds_init_object_from_op | ||
585 | * | ||
586 | * PARAMETERS: walk_state - Current walk state | ||
587 | * Op - Parser op used to init the internal object | ||
588 | * Opcode - AML opcode associated with the object | ||
589 | * ret_obj_desc - Namespace object to be initialized | ||
590 | * | ||
591 | * RETURN: Status | ||
592 | * | ||
593 | * DESCRIPTION: Initialize a namespace object from a parser Op and its | ||
594 | * associated arguments. The namespace object is a more compact | ||
595 | * representation of the Op and its arguments. | ||
596 | * | ||
597 | ******************************************************************************/ | ||
598 | |||
599 | acpi_status | ||
600 | acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state, | ||
601 | union acpi_parse_object *op, | ||
602 | u16 opcode, | ||
603 | union acpi_operand_object **ret_obj_desc) | ||
604 | { | ||
605 | const struct acpi_opcode_info *op_info; | ||
606 | union acpi_operand_object *obj_desc; | ||
607 | acpi_status status = AE_OK; | ||
608 | |||
609 | ACPI_FUNCTION_TRACE(ds_init_object_from_op); | ||
610 | |||
611 | obj_desc = *ret_obj_desc; | ||
612 | op_info = acpi_ps_get_opcode_info(opcode); | ||
613 | if (op_info->class == AML_CLASS_UNKNOWN) { | ||
614 | |||
615 | /* Unknown opcode */ | ||
616 | |||
617 | return_ACPI_STATUS(AE_TYPE); | ||
618 | } | ||
619 | |||
620 | /* Perform per-object initialization */ | ||
621 | |||
622 | switch (ACPI_GET_OBJECT_TYPE(obj_desc)) { | ||
623 | case ACPI_TYPE_BUFFER: | ||
624 | |||
625 | /* | ||
626 | * Defer evaluation of Buffer term_arg operand | ||
627 | */ | ||
628 | obj_desc->buffer.node = | ||
629 | ACPI_CAST_PTR(struct acpi_namespace_node, | ||
630 | walk_state->operands[0]); | ||
631 | obj_desc->buffer.aml_start = op->named.data; | ||
632 | obj_desc->buffer.aml_length = op->named.length; | ||
633 | break; | ||
634 | |||
635 | case ACPI_TYPE_PACKAGE: | ||
636 | |||
637 | /* | ||
638 | * Defer evaluation of Package term_arg operand | ||
639 | */ | ||
640 | obj_desc->package.node = | ||
641 | ACPI_CAST_PTR(struct acpi_namespace_node, | ||
642 | walk_state->operands[0]); | ||
643 | obj_desc->package.aml_start = op->named.data; | ||
644 | obj_desc->package.aml_length = op->named.length; | ||
645 | break; | ||
646 | |||
647 | case ACPI_TYPE_INTEGER: | ||
648 | |||
649 | switch (op_info->type) { | ||
650 | case AML_TYPE_CONSTANT: | ||
651 | /* | ||
652 | * Resolve AML Constants here - AND ONLY HERE! | ||
653 | * All constants are integers. | ||
654 | * We mark the integer with a flag that indicates that it started | ||
655 | * life as a constant -- so that stores to constants will perform | ||
656 | * as expected (noop). zero_op is used as a placeholder for optional | ||
657 | * target operands. | ||
658 | */ | ||
659 | obj_desc->common.flags = AOPOBJ_AML_CONSTANT; | ||
660 | |||
661 | switch (opcode) { | ||
662 | case AML_ZERO_OP: | ||
663 | |||
664 | obj_desc->integer.value = 0; | ||
665 | break; | ||
666 | |||
667 | case AML_ONE_OP: | ||
668 | |||
669 | obj_desc->integer.value = 1; | ||
670 | break; | ||
671 | |||
672 | case AML_ONES_OP: | ||
673 | |||
674 | obj_desc->integer.value = ACPI_INTEGER_MAX; | ||
675 | |||
676 | /* Truncate value if we are executing from a 32-bit ACPI table */ | ||
677 | |||
678 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
679 | acpi_ex_truncate_for32bit_table(obj_desc); | ||
680 | #endif | ||
681 | break; | ||
682 | |||
683 | case AML_REVISION_OP: | ||
684 | |||
685 | obj_desc->integer.value = ACPI_CA_VERSION; | ||
686 | break; | ||
687 | |||
688 | default: | ||
689 | |||
690 | ACPI_ERROR((AE_INFO, | ||
691 | "Unknown constant opcode %X", | ||
692 | opcode)); | ||
693 | status = AE_AML_OPERAND_TYPE; | ||
694 | break; | ||
695 | } | ||
696 | break; | ||
697 | |||
698 | case AML_TYPE_LITERAL: | ||
699 | |||
700 | obj_desc->integer.value = op->common.value.integer; | ||
701 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
702 | acpi_ex_truncate_for32bit_table(obj_desc); | ||
703 | #endif | ||
704 | break; | ||
705 | |||
706 | default: | ||
707 | ACPI_ERROR((AE_INFO, "Unknown Integer type %X", | ||
708 | op_info->type)); | ||
709 | status = AE_AML_OPERAND_TYPE; | ||
710 | break; | ||
711 | } | ||
712 | break; | ||
713 | |||
714 | case ACPI_TYPE_STRING: | ||
715 | |||
716 | obj_desc->string.pointer = op->common.value.string; | ||
717 | obj_desc->string.length = | ||
718 | (u32) ACPI_STRLEN(op->common.value.string); | ||
719 | |||
720 | /* | ||
721 | * The string is contained in the ACPI table, don't ever try | ||
722 | * to delete it | ||
723 | */ | ||
724 | obj_desc->common.flags |= AOPOBJ_STATIC_POINTER; | ||
725 | break; | ||
726 | |||
727 | case ACPI_TYPE_METHOD: | ||
728 | break; | ||
729 | |||
730 | case ACPI_TYPE_LOCAL_REFERENCE: | ||
731 | |||
732 | switch (op_info->type) { | ||
733 | case AML_TYPE_LOCAL_VARIABLE: | ||
734 | |||
735 | /* Local ID (0-7) is (AML opcode - base AML_LOCAL_OP) */ | ||
736 | |||
737 | obj_desc->reference.value = opcode - AML_LOCAL_OP; | ||
738 | obj_desc->reference.class = ACPI_REFCLASS_LOCAL; | ||
739 | |||
740 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
741 | status = | ||
742 | acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL, | ||
743 | obj_desc->reference. | ||
744 | value, walk_state, | ||
745 | ACPI_CAST_INDIRECT_PTR | ||
746 | (struct | ||
747 | acpi_namespace_node, | ||
748 | &obj_desc->reference. | ||
749 | object)); | ||
750 | #endif | ||
751 | break; | ||
752 | |||
753 | case AML_TYPE_METHOD_ARGUMENT: | ||
754 | |||
755 | /* Arg ID (0-6) is (AML opcode - base AML_ARG_OP) */ | ||
756 | |||
757 | obj_desc->reference.value = opcode - AML_ARG_OP; | ||
758 | obj_desc->reference.class = ACPI_REFCLASS_ARG; | ||
759 | |||
760 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
761 | status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG, | ||
762 | obj_desc-> | ||
763 | reference.value, | ||
764 | walk_state, | ||
765 | ACPI_CAST_INDIRECT_PTR | ||
766 | (struct | ||
767 | acpi_namespace_node, | ||
768 | &obj_desc-> | ||
769 | reference. | ||
770 | object)); | ||
771 | #endif | ||
772 | break; | ||
773 | |||
774 | default: /* Object name or Debug object */ | ||
775 | |||
776 | switch (op->common.aml_opcode) { | ||
777 | case AML_INT_NAMEPATH_OP: | ||
778 | |||
779 | /* Node was saved in Op */ | ||
780 | |||
781 | obj_desc->reference.node = op->common.node; | ||
782 | obj_desc->reference.object = | ||
783 | op->common.node->object; | ||
784 | obj_desc->reference.class = ACPI_REFCLASS_NAME; | ||
785 | break; | ||
786 | |||
787 | case AML_DEBUG_OP: | ||
788 | |||
789 | obj_desc->reference.class = ACPI_REFCLASS_DEBUG; | ||
790 | break; | ||
791 | |||
792 | default: | ||
793 | |||
794 | ACPI_ERROR((AE_INFO, | ||
795 | "Unimplemented reference type for AML opcode: %4.4X", | ||
796 | opcode)); | ||
797 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | ||
798 | } | ||
799 | break; | ||
800 | } | ||
801 | break; | ||
802 | |||
803 | default: | ||
804 | |||
805 | ACPI_ERROR((AE_INFO, "Unimplemented data type: %X", | ||
806 | ACPI_GET_OBJECT_TYPE(obj_desc))); | ||
807 | |||
808 | status = AE_AML_OPERAND_TYPE; | ||
809 | break; | ||
810 | } | ||
811 | |||
812 | return_ACPI_STATUS(status); | ||
813 | } | ||
diff --git a/drivers/acpi/dispatcher/dsopcode.c b/drivers/acpi/dispatcher/dsopcode.c deleted file mode 100644 index cb8a0d3109f0..000000000000 --- a/drivers/acpi/dispatcher/dsopcode.c +++ /dev/null | |||
@@ -1,1469 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dsopcode - Dispatcher Op Region support and handling of | ||
4 | * "control" opcodes | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2008, Intel Corp. | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/accommon.h> | ||
47 | #include <acpi/acparser.h> | ||
48 | #include <acpi/amlcode.h> | ||
49 | #include <acpi/acdispat.h> | ||
50 | #include <acpi/acinterp.h> | ||
51 | #include <acpi/acnamesp.h> | ||
52 | #include <acpi/acevents.h> | ||
53 | #include <acpi/actables.h> | ||
54 | |||
55 | #define _COMPONENT ACPI_DISPATCHER | ||
56 | ACPI_MODULE_NAME("dsopcode") | ||
57 | |||
58 | /* Local prototypes */ | ||
59 | static acpi_status | ||
60 | acpi_ds_execute_arguments(struct acpi_namespace_node *node, | ||
61 | struct acpi_namespace_node *scope_node, | ||
62 | u32 aml_length, u8 * aml_start); | ||
63 | |||
64 | static acpi_status | ||
65 | acpi_ds_init_buffer_field(u16 aml_opcode, | ||
66 | union acpi_operand_object *obj_desc, | ||
67 | union acpi_operand_object *buffer_desc, | ||
68 | union acpi_operand_object *offset_desc, | ||
69 | union acpi_operand_object *length_desc, | ||
70 | union acpi_operand_object *result_desc); | ||
71 | |||
72 | /******************************************************************************* | ||
73 | * | ||
74 | * FUNCTION: acpi_ds_execute_arguments | ||
75 | * | ||
76 | * PARAMETERS: Node - Object NS node | ||
77 | * scope_node - Parent NS node | ||
78 | * aml_length - Length of executable AML | ||
79 | * aml_start - Pointer to the AML | ||
80 | * | ||
81 | * RETURN: Status. | ||
82 | * | ||
83 | * DESCRIPTION: Late (deferred) execution of region or field arguments | ||
84 | * | ||
85 | ******************************************************************************/ | ||
86 | |||
87 | static acpi_status | ||
88 | acpi_ds_execute_arguments(struct acpi_namespace_node *node, | ||
89 | struct acpi_namespace_node *scope_node, | ||
90 | u32 aml_length, u8 * aml_start) | ||
91 | { | ||
92 | acpi_status status; | ||
93 | union acpi_parse_object *op; | ||
94 | struct acpi_walk_state *walk_state; | ||
95 | |||
96 | ACPI_FUNCTION_TRACE(ds_execute_arguments); | ||
97 | |||
98 | /* | ||
99 | * Allocate a new parser op to be the root of the parsed tree | ||
100 | */ | ||
101 | op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); | ||
102 | if (!op) { | ||
103 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
104 | } | ||
105 | |||
106 | /* Save the Node for use in acpi_ps_parse_aml */ | ||
107 | |||
108 | op->common.node = scope_node; | ||
109 | |||
110 | /* Create and initialize a new parser state */ | ||
111 | |||
112 | walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); | ||
113 | if (!walk_state) { | ||
114 | status = AE_NO_MEMORY; | ||
115 | goto cleanup; | ||
116 | } | ||
117 | |||
118 | status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, | ||
119 | aml_length, NULL, ACPI_IMODE_LOAD_PASS1); | ||
120 | if (ACPI_FAILURE(status)) { | ||
121 | acpi_ds_delete_walk_state(walk_state); | ||
122 | goto cleanup; | ||
123 | } | ||
124 | |||
125 | /* Mark this parse as a deferred opcode */ | ||
126 | |||
127 | walk_state->parse_flags = ACPI_PARSE_DEFERRED_OP; | ||
128 | walk_state->deferred_node = node; | ||
129 | |||
130 | /* Pass1: Parse the entire declaration */ | ||
131 | |||
132 | status = acpi_ps_parse_aml(walk_state); | ||
133 | if (ACPI_FAILURE(status)) { | ||
134 | goto cleanup; | ||
135 | } | ||
136 | |||
137 | /* Get and init the Op created above */ | ||
138 | |||
139 | op->common.node = node; | ||
140 | acpi_ps_delete_parse_tree(op); | ||
141 | |||
142 | /* Evaluate the deferred arguments */ | ||
143 | |||
144 | op = acpi_ps_alloc_op(AML_INT_EVAL_SUBTREE_OP); | ||
145 | if (!op) { | ||
146 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
147 | } | ||
148 | |||
149 | op->common.node = scope_node; | ||
150 | |||
151 | /* Create and initialize a new parser state */ | ||
152 | |||
153 | walk_state = acpi_ds_create_walk_state(0, NULL, NULL, NULL); | ||
154 | if (!walk_state) { | ||
155 | status = AE_NO_MEMORY; | ||
156 | goto cleanup; | ||
157 | } | ||
158 | |||
159 | /* Execute the opcode and arguments */ | ||
160 | |||
161 | status = acpi_ds_init_aml_walk(walk_state, op, NULL, aml_start, | ||
162 | aml_length, NULL, ACPI_IMODE_EXECUTE); | ||
163 | if (ACPI_FAILURE(status)) { | ||
164 | acpi_ds_delete_walk_state(walk_state); | ||
165 | goto cleanup; | ||
166 | } | ||
167 | |||
168 | /* Mark this execution as a deferred opcode */ | ||
169 | |||
170 | walk_state->deferred_node = node; | ||
171 | status = acpi_ps_parse_aml(walk_state); | ||
172 | |||
173 | cleanup: | ||
174 | acpi_ps_delete_parse_tree(op); | ||
175 | return_ACPI_STATUS(status); | ||
176 | } | ||
177 | |||
178 | /******************************************************************************* | ||
179 | * | ||
180 | * FUNCTION: acpi_ds_get_buffer_field_arguments | ||
181 | * | ||
182 | * PARAMETERS: obj_desc - A valid buffer_field object | ||
183 | * | ||
184 | * RETURN: Status. | ||
185 | * | ||
186 | * DESCRIPTION: Get buffer_field Buffer and Index. This implements the late | ||
187 | * evaluation of these field attributes. | ||
188 | * | ||
189 | ******************************************************************************/ | ||
190 | |||
191 | acpi_status | ||
192 | acpi_ds_get_buffer_field_arguments(union acpi_operand_object *obj_desc) | ||
193 | { | ||
194 | union acpi_operand_object *extra_desc; | ||
195 | struct acpi_namespace_node *node; | ||
196 | acpi_status status; | ||
197 | |||
198 | ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_field_arguments, obj_desc); | ||
199 | |||
200 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
201 | return_ACPI_STATUS(AE_OK); | ||
202 | } | ||
203 | |||
204 | /* Get the AML pointer (method object) and buffer_field node */ | ||
205 | |||
206 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
207 | node = obj_desc->buffer_field.node; | ||
208 | |||
209 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
210 | (ACPI_TYPE_BUFFER_FIELD, node, NULL)); | ||
211 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BufferField Arg Init\n", | ||
212 | acpi_ut_get_node_name(node))); | ||
213 | |||
214 | /* Execute the AML code for the term_arg arguments */ | ||
215 | |||
216 | status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), | ||
217 | extra_desc->extra.aml_length, | ||
218 | extra_desc->extra.aml_start); | ||
219 | return_ACPI_STATUS(status); | ||
220 | } | ||
221 | |||
222 | /******************************************************************************* | ||
223 | * | ||
224 | * FUNCTION: acpi_ds_get_bank_field_arguments | ||
225 | * | ||
226 | * PARAMETERS: obj_desc - A valid bank_field object | ||
227 | * | ||
228 | * RETURN: Status. | ||
229 | * | ||
230 | * DESCRIPTION: Get bank_field bank_value. This implements the late | ||
231 | * evaluation of these field attributes. | ||
232 | * | ||
233 | ******************************************************************************/ | ||
234 | |||
235 | acpi_status | ||
236 | acpi_ds_get_bank_field_arguments(union acpi_operand_object *obj_desc) | ||
237 | { | ||
238 | union acpi_operand_object *extra_desc; | ||
239 | struct acpi_namespace_node *node; | ||
240 | acpi_status status; | ||
241 | |||
242 | ACPI_FUNCTION_TRACE_PTR(ds_get_bank_field_arguments, obj_desc); | ||
243 | |||
244 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
245 | return_ACPI_STATUS(AE_OK); | ||
246 | } | ||
247 | |||
248 | /* Get the AML pointer (method object) and bank_field node */ | ||
249 | |||
250 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
251 | node = obj_desc->bank_field.node; | ||
252 | |||
253 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
254 | (ACPI_TYPE_LOCAL_BANK_FIELD, node, NULL)); | ||
255 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] BankField Arg Init\n", | ||
256 | acpi_ut_get_node_name(node))); | ||
257 | |||
258 | /* Execute the AML code for the term_arg arguments */ | ||
259 | |||
260 | status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), | ||
261 | extra_desc->extra.aml_length, | ||
262 | extra_desc->extra.aml_start); | ||
263 | return_ACPI_STATUS(status); | ||
264 | } | ||
265 | |||
266 | /******************************************************************************* | ||
267 | * | ||
268 | * FUNCTION: acpi_ds_get_buffer_arguments | ||
269 | * | ||
270 | * PARAMETERS: obj_desc - A valid Buffer object | ||
271 | * | ||
272 | * RETURN: Status. | ||
273 | * | ||
274 | * DESCRIPTION: Get Buffer length and initializer byte list. This implements | ||
275 | * the late evaluation of these attributes. | ||
276 | * | ||
277 | ******************************************************************************/ | ||
278 | |||
279 | acpi_status acpi_ds_get_buffer_arguments(union acpi_operand_object *obj_desc) | ||
280 | { | ||
281 | struct acpi_namespace_node *node; | ||
282 | acpi_status status; | ||
283 | |||
284 | ACPI_FUNCTION_TRACE_PTR(ds_get_buffer_arguments, obj_desc); | ||
285 | |||
286 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
287 | return_ACPI_STATUS(AE_OK); | ||
288 | } | ||
289 | |||
290 | /* Get the Buffer node */ | ||
291 | |||
292 | node = obj_desc->buffer.node; | ||
293 | if (!node) { | ||
294 | ACPI_ERROR((AE_INFO, | ||
295 | "No pointer back to NS node in buffer obj %p", | ||
296 | obj_desc)); | ||
297 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
298 | } | ||
299 | |||
300 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Buffer Arg Init\n")); | ||
301 | |||
302 | /* Execute the AML code for the term_arg arguments */ | ||
303 | |||
304 | status = acpi_ds_execute_arguments(node, node, | ||
305 | obj_desc->buffer.aml_length, | ||
306 | obj_desc->buffer.aml_start); | ||
307 | return_ACPI_STATUS(status); | ||
308 | } | ||
309 | |||
310 | /******************************************************************************* | ||
311 | * | ||
312 | * FUNCTION: acpi_ds_get_package_arguments | ||
313 | * | ||
314 | * PARAMETERS: obj_desc - A valid Package object | ||
315 | * | ||
316 | * RETURN: Status. | ||
317 | * | ||
318 | * DESCRIPTION: Get Package length and initializer byte list. This implements | ||
319 | * the late evaluation of these attributes. | ||
320 | * | ||
321 | ******************************************************************************/ | ||
322 | |||
323 | acpi_status acpi_ds_get_package_arguments(union acpi_operand_object *obj_desc) | ||
324 | { | ||
325 | struct acpi_namespace_node *node; | ||
326 | acpi_status status; | ||
327 | |||
328 | ACPI_FUNCTION_TRACE_PTR(ds_get_package_arguments, obj_desc); | ||
329 | |||
330 | if (obj_desc->common.flags & AOPOBJ_DATA_VALID) { | ||
331 | return_ACPI_STATUS(AE_OK); | ||
332 | } | ||
333 | |||
334 | /* Get the Package node */ | ||
335 | |||
336 | node = obj_desc->package.node; | ||
337 | if (!node) { | ||
338 | ACPI_ERROR((AE_INFO, | ||
339 | "No pointer back to NS node in package %p", | ||
340 | obj_desc)); | ||
341 | return_ACPI_STATUS(AE_AML_INTERNAL); | ||
342 | } | ||
343 | |||
344 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Package Arg Init\n")); | ||
345 | |||
346 | /* Execute the AML code for the term_arg arguments */ | ||
347 | |||
348 | status = acpi_ds_execute_arguments(node, node, | ||
349 | obj_desc->package.aml_length, | ||
350 | obj_desc->package.aml_start); | ||
351 | return_ACPI_STATUS(status); | ||
352 | } | ||
353 | |||
354 | /***************************************************************************** | ||
355 | * | ||
356 | * FUNCTION: acpi_ds_get_region_arguments | ||
357 | * | ||
358 | * PARAMETERS: obj_desc - A valid region object | ||
359 | * | ||
360 | * RETURN: Status. | ||
361 | * | ||
362 | * DESCRIPTION: Get region address and length. This implements the late | ||
363 | * evaluation of these region attributes. | ||
364 | * | ||
365 | ****************************************************************************/ | ||
366 | |||
367 | acpi_status acpi_ds_get_region_arguments(union acpi_operand_object *obj_desc) | ||
368 | { | ||
369 | struct acpi_namespace_node *node; | ||
370 | acpi_status status; | ||
371 | union acpi_operand_object *extra_desc; | ||
372 | |||
373 | ACPI_FUNCTION_TRACE_PTR(ds_get_region_arguments, obj_desc); | ||
374 | |||
375 | if (obj_desc->region.flags & AOPOBJ_DATA_VALID) { | ||
376 | return_ACPI_STATUS(AE_OK); | ||
377 | } | ||
378 | |||
379 | extra_desc = acpi_ns_get_secondary_object(obj_desc); | ||
380 | if (!extra_desc) { | ||
381 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
382 | } | ||
383 | |||
384 | /* Get the Region node */ | ||
385 | |||
386 | node = obj_desc->region.node; | ||
387 | |||
388 | ACPI_DEBUG_EXEC(acpi_ut_display_init_pathname | ||
389 | (ACPI_TYPE_REGION, node, NULL)); | ||
390 | |||
391 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "[%4.4s] OpRegion Arg Init at AML %p\n", | ||
392 | acpi_ut_get_node_name(node), | ||
393 | extra_desc->extra.aml_start)); | ||
394 | |||
395 | /* Execute the argument AML */ | ||
396 | |||
397 | status = acpi_ds_execute_arguments(node, acpi_ns_get_parent_node(node), | ||
398 | extra_desc->extra.aml_length, | ||
399 | extra_desc->extra.aml_start); | ||
400 | if (ACPI_FAILURE(status)) { | ||
401 | return_ACPI_STATUS(status); | ||
402 | } | ||
403 | |||
404 | /* Validate the region address/length via the host OS */ | ||
405 | |||
406 | status = acpi_os_validate_address(obj_desc->region.space_id, | ||
407 | obj_desc->region.address, | ||
408 | (acpi_size) obj_desc->region.length, | ||
409 | acpi_ut_get_node_name(node)); | ||
410 | |||
411 | if (ACPI_FAILURE(status)) { | ||
412 | /* | ||
413 | * Invalid address/length. We will emit an error message and mark | ||
414 | * the region as invalid, so that it will cause an additional error if | ||
415 | * it is ever used. Then return AE_OK. | ||
416 | */ | ||
417 | ACPI_EXCEPTION((AE_INFO, status, | ||
418 | "During address validation of OpRegion [%4.4s]", | ||
419 | node->name.ascii)); | ||
420 | obj_desc->common.flags |= AOPOBJ_INVALID; | ||
421 | status = AE_OK; | ||
422 | } | ||
423 | |||
424 | return_ACPI_STATUS(status); | ||
425 | } | ||
426 | |||
427 | /******************************************************************************* | ||
428 | * | ||
429 | * FUNCTION: acpi_ds_initialize_region | ||
430 | * | ||
431 | * PARAMETERS: obj_handle - Region namespace node | ||
432 | * | ||
433 | * RETURN: Status | ||
434 | * | ||
435 | * DESCRIPTION: Front end to ev_initialize_region | ||
436 | * | ||
437 | ******************************************************************************/ | ||
438 | |||
439 | acpi_status acpi_ds_initialize_region(acpi_handle obj_handle) | ||
440 | { | ||
441 | union acpi_operand_object *obj_desc; | ||
442 | acpi_status status; | ||
443 | |||
444 | obj_desc = acpi_ns_get_attached_object(obj_handle); | ||
445 | |||
446 | /* Namespace is NOT locked */ | ||
447 | |||
448 | status = acpi_ev_initialize_region(obj_desc, FALSE); | ||
449 | return (status); | ||
450 | } | ||
451 | |||
452 | /******************************************************************************* | ||
453 | * | ||
454 | * FUNCTION: acpi_ds_init_buffer_field | ||
455 | * | ||
456 | * PARAMETERS: aml_opcode - create_xxx_field | ||
457 | * obj_desc - buffer_field object | ||
458 | * buffer_desc - Host Buffer | ||
459 | * offset_desc - Offset into buffer | ||
460 | * length_desc - Length of field (CREATE_FIELD_OP only) | ||
461 | * result_desc - Where to store the result | ||
462 | * | ||
463 | * RETURN: Status | ||
464 | * | ||
465 | * DESCRIPTION: Perform actual initialization of a buffer field | ||
466 | * | ||
467 | ******************************************************************************/ | ||
468 | |||
469 | static acpi_status | ||
470 | acpi_ds_init_buffer_field(u16 aml_opcode, | ||
471 | union acpi_operand_object *obj_desc, | ||
472 | union acpi_operand_object *buffer_desc, | ||
473 | union acpi_operand_object *offset_desc, | ||
474 | union acpi_operand_object *length_desc, | ||
475 | union acpi_operand_object *result_desc) | ||
476 | { | ||
477 | u32 offset; | ||
478 | u32 bit_offset; | ||
479 | u32 bit_count; | ||
480 | u8 field_flags; | ||
481 | acpi_status status; | ||
482 | |||
483 | ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); | ||
484 | |||
485 | /* Host object must be a Buffer */ | ||
486 | |||
487 | if (ACPI_GET_OBJECT_TYPE(buffer_desc) != ACPI_TYPE_BUFFER) { | ||
488 | ACPI_ERROR((AE_INFO, | ||
489 | "Target of Create Field is not a Buffer object - %s", | ||
490 | acpi_ut_get_object_type_name(buffer_desc))); | ||
491 | |||
492 | status = AE_AML_OPERAND_TYPE; | ||
493 | goto cleanup; | ||
494 | } | ||
495 | |||
496 | /* | ||
497 | * The last parameter to all of these opcodes (result_desc) started | ||
498 | * out as a name_string, and should therefore now be a NS node | ||
499 | * after resolution in acpi_ex_resolve_operands(). | ||
500 | */ | ||
501 | if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) { | ||
502 | ACPI_ERROR((AE_INFO, | ||
503 | "(%s) destination not a NS Node [%s]", | ||
504 | acpi_ps_get_opcode_name(aml_opcode), | ||
505 | acpi_ut_get_descriptor_name(result_desc))); | ||
506 | |||
507 | status = AE_AML_OPERAND_TYPE; | ||
508 | goto cleanup; | ||
509 | } | ||
510 | |||
511 | offset = (u32) offset_desc->integer.value; | ||
512 | |||
513 | /* | ||
514 | * Setup the Bit offsets and counts, according to the opcode | ||
515 | */ | ||
516 | switch (aml_opcode) { | ||
517 | case AML_CREATE_FIELD_OP: | ||
518 | |||
519 | /* Offset is in bits, count is in bits */ | ||
520 | |||
521 | field_flags = AML_FIELD_ACCESS_BYTE; | ||
522 | bit_offset = offset; | ||
523 | bit_count = (u32) length_desc->integer.value; | ||
524 | |||
525 | /* Must have a valid (>0) bit count */ | ||
526 | |||
527 | if (bit_count == 0) { | ||
528 | ACPI_ERROR((AE_INFO, | ||
529 | "Attempt to CreateField of length zero")); | ||
530 | status = AE_AML_OPERAND_VALUE; | ||
531 | goto cleanup; | ||
532 | } | ||
533 | break; | ||
534 | |||
535 | case AML_CREATE_BIT_FIELD_OP: | ||
536 | |||
537 | /* Offset is in bits, Field is one bit */ | ||
538 | |||
539 | bit_offset = offset; | ||
540 | bit_count = 1; | ||
541 | field_flags = AML_FIELD_ACCESS_BYTE; | ||
542 | break; | ||
543 | |||
544 | case AML_CREATE_BYTE_FIELD_OP: | ||
545 | |||
546 | /* Offset is in bytes, field is one byte */ | ||
547 | |||
548 | bit_offset = 8 * offset; | ||
549 | bit_count = 8; | ||
550 | field_flags = AML_FIELD_ACCESS_BYTE; | ||
551 | break; | ||
552 | |||
553 | case AML_CREATE_WORD_FIELD_OP: | ||
554 | |||
555 | /* Offset is in bytes, field is one word */ | ||
556 | |||
557 | bit_offset = 8 * offset; | ||
558 | bit_count = 16; | ||
559 | field_flags = AML_FIELD_ACCESS_WORD; | ||
560 | break; | ||
561 | |||
562 | case AML_CREATE_DWORD_FIELD_OP: | ||
563 | |||
564 | /* Offset is in bytes, field is one dword */ | ||
565 | |||
566 | bit_offset = 8 * offset; | ||
567 | bit_count = 32; | ||
568 | field_flags = AML_FIELD_ACCESS_DWORD; | ||
569 | break; | ||
570 | |||
571 | case AML_CREATE_QWORD_FIELD_OP: | ||
572 | |||
573 | /* Offset is in bytes, field is one qword */ | ||
574 | |||
575 | bit_offset = 8 * offset; | ||
576 | bit_count = 64; | ||
577 | field_flags = AML_FIELD_ACCESS_QWORD; | ||
578 | break; | ||
579 | |||
580 | default: | ||
581 | |||
582 | ACPI_ERROR((AE_INFO, | ||
583 | "Unknown field creation opcode %02x", aml_opcode)); | ||
584 | status = AE_AML_BAD_OPCODE; | ||
585 | goto cleanup; | ||
586 | } | ||
587 | |||
588 | /* Entire field must fit within the current length of the buffer */ | ||
589 | |||
590 | if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { | ||
591 | ACPI_ERROR((AE_INFO, | ||
592 | "Field [%4.4s] at %d exceeds Buffer [%4.4s] size %d (bits)", | ||
593 | acpi_ut_get_node_name(result_desc), | ||
594 | bit_offset + bit_count, | ||
595 | acpi_ut_get_node_name(buffer_desc->buffer.node), | ||
596 | 8 * (u32) buffer_desc->buffer.length)); | ||
597 | status = AE_AML_BUFFER_LIMIT; | ||
598 | goto cleanup; | ||
599 | } | ||
600 | |||
601 | /* | ||
602 | * Initialize areas of the field object that are common to all fields | ||
603 | * For field_flags, use LOCK_RULE = 0 (NO_LOCK), | ||
604 | * UPDATE_RULE = 0 (UPDATE_PRESERVE) | ||
605 | */ | ||
606 | status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, | ||
607 | bit_offset, bit_count); | ||
608 | if (ACPI_FAILURE(status)) { | ||
609 | goto cleanup; | ||
610 | } | ||
611 | |||
612 | obj_desc->buffer_field.buffer_obj = buffer_desc; | ||
613 | |||
614 | /* Reference count for buffer_desc inherits obj_desc count */ | ||
615 | |||
616 | buffer_desc->common.reference_count = (u16) | ||
617 | (buffer_desc->common.reference_count + | ||
618 | obj_desc->common.reference_count); | ||
619 | |||
620 | cleanup: | ||
621 | |||
622 | /* Always delete the operands */ | ||
623 | |||
624 | acpi_ut_remove_reference(offset_desc); | ||
625 | acpi_ut_remove_reference(buffer_desc); | ||
626 | |||
627 | if (aml_opcode == AML_CREATE_FIELD_OP) { | ||
628 | acpi_ut_remove_reference(length_desc); | ||
629 | } | ||
630 | |||
631 | /* On failure, delete the result descriptor */ | ||
632 | |||
633 | if (ACPI_FAILURE(status)) { | ||
634 | acpi_ut_remove_reference(result_desc); /* Result descriptor */ | ||
635 | } else { | ||
636 | /* Now the address and length are valid for this buffer_field */ | ||
637 | |||
638 | obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; | ||
639 | } | ||
640 | |||
641 | return_ACPI_STATUS(status); | ||
642 | } | ||
643 | |||
644 | /******************************************************************************* | ||
645 | * | ||
646 | * FUNCTION: acpi_ds_eval_buffer_field_operands | ||
647 | * | ||
648 | * PARAMETERS: walk_state - Current walk | ||
649 | * Op - A valid buffer_field Op object | ||
650 | * | ||
651 | * RETURN: Status | ||
652 | * | ||
653 | * DESCRIPTION: Get buffer_field Buffer and Index | ||
654 | * Called from acpi_ds_exec_end_op during buffer_field parse tree walk | ||
655 | * | ||
656 | ******************************************************************************/ | ||
657 | |||
658 | acpi_status | ||
659 | acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, | ||
660 | union acpi_parse_object *op) | ||
661 | { | ||
662 | acpi_status status; | ||
663 | union acpi_operand_object *obj_desc; | ||
664 | struct acpi_namespace_node *node; | ||
665 | union acpi_parse_object *next_op; | ||
666 | |||
667 | ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); | ||
668 | |||
669 | /* | ||
670 | * This is where we evaluate the address and length fields of the | ||
671 | * create_xxx_field declaration | ||
672 | */ | ||
673 | node = op->common.node; | ||
674 | |||
675 | /* next_op points to the op that holds the Buffer */ | ||
676 | |||
677 | next_op = op->common.value.arg; | ||
678 | |||
679 | /* Evaluate/create the address and length operands */ | ||
680 | |||
681 | status = acpi_ds_create_operands(walk_state, next_op); | ||
682 | if (ACPI_FAILURE(status)) { | ||
683 | return_ACPI_STATUS(status); | ||
684 | } | ||
685 | |||
686 | obj_desc = acpi_ns_get_attached_object(node); | ||
687 | if (!obj_desc) { | ||
688 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
689 | } | ||
690 | |||
691 | /* Resolve the operands */ | ||
692 | |||
693 | status = acpi_ex_resolve_operands(op->common.aml_opcode, | ||
694 | ACPI_WALK_OPERANDS, walk_state); | ||
695 | if (ACPI_FAILURE(status)) { | ||
696 | ACPI_ERROR((AE_INFO, "(%s) bad operand(s) (%X)", | ||
697 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
698 | status)); | ||
699 | |||
700 | return_ACPI_STATUS(status); | ||
701 | } | ||
702 | |||
703 | /* Initialize the Buffer Field */ | ||
704 | |||
705 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { | ||
706 | |||
707 | /* NOTE: Slightly different operands for this opcode */ | ||
708 | |||
709 | status = | ||
710 | acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, | ||
711 | walk_state->operands[0], | ||
712 | walk_state->operands[1], | ||
713 | walk_state->operands[2], | ||
714 | walk_state->operands[3]); | ||
715 | } else { | ||
716 | /* All other, create_xxx_field opcodes */ | ||
717 | |||
718 | status = | ||
719 | acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, | ||
720 | walk_state->operands[0], | ||
721 | walk_state->operands[1], NULL, | ||
722 | walk_state->operands[2]); | ||
723 | } | ||
724 | |||
725 | return_ACPI_STATUS(status); | ||
726 | } | ||
727 | |||
728 | /******************************************************************************* | ||
729 | * | ||
730 | * FUNCTION: acpi_ds_eval_region_operands | ||
731 | * | ||
732 | * PARAMETERS: walk_state - Current walk | ||
733 | * Op - A valid region Op object | ||
734 | * | ||
735 | * RETURN: Status | ||
736 | * | ||
737 | * DESCRIPTION: Get region address and length | ||
738 | * Called from acpi_ds_exec_end_op during op_region parse tree walk | ||
739 | * | ||
740 | ******************************************************************************/ | ||
741 | |||
742 | acpi_status | ||
743 | acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, | ||
744 | union acpi_parse_object *op) | ||
745 | { | ||
746 | acpi_status status; | ||
747 | union acpi_operand_object *obj_desc; | ||
748 | union acpi_operand_object *operand_desc; | ||
749 | struct acpi_namespace_node *node; | ||
750 | union acpi_parse_object *next_op; | ||
751 | |||
752 | ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); | ||
753 | |||
754 | /* | ||
755 | * This is where we evaluate the address and length fields of the | ||
756 | * op_region declaration | ||
757 | */ | ||
758 | node = op->common.node; | ||
759 | |||
760 | /* next_op points to the op that holds the space_iD */ | ||
761 | |||
762 | next_op = op->common.value.arg; | ||
763 | |||
764 | /* next_op points to address op */ | ||
765 | |||
766 | next_op = next_op->common.next; | ||
767 | |||
768 | /* Evaluate/create the address and length operands */ | ||
769 | |||
770 | status = acpi_ds_create_operands(walk_state, next_op); | ||
771 | if (ACPI_FAILURE(status)) { | ||
772 | return_ACPI_STATUS(status); | ||
773 | } | ||
774 | |||
775 | /* Resolve the length and address operands to numbers */ | ||
776 | |||
777 | status = acpi_ex_resolve_operands(op->common.aml_opcode, | ||
778 | ACPI_WALK_OPERANDS, walk_state); | ||
779 | if (ACPI_FAILURE(status)) { | ||
780 | return_ACPI_STATUS(status); | ||
781 | } | ||
782 | |||
783 | obj_desc = acpi_ns_get_attached_object(node); | ||
784 | if (!obj_desc) { | ||
785 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
786 | } | ||
787 | |||
788 | /* | ||
789 | * Get the length operand and save it | ||
790 | * (at Top of stack) | ||
791 | */ | ||
792 | operand_desc = walk_state->operands[walk_state->num_operands - 1]; | ||
793 | |||
794 | obj_desc->region.length = (u32) operand_desc->integer.value; | ||
795 | acpi_ut_remove_reference(operand_desc); | ||
796 | |||
797 | /* | ||
798 | * Get the address and save it | ||
799 | * (at top of stack - 1) | ||
800 | */ | ||
801 | operand_desc = walk_state->operands[walk_state->num_operands - 2]; | ||
802 | |||
803 | obj_desc->region.address = (acpi_physical_address) | ||
804 | operand_desc->integer.value; | ||
805 | acpi_ut_remove_reference(operand_desc); | ||
806 | |||
807 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | ||
808 | obj_desc, | ||
809 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), | ||
810 | obj_desc->region.length)); | ||
811 | |||
812 | /* Now the address and length are valid for this opregion */ | ||
813 | |||
814 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | ||
815 | |||
816 | return_ACPI_STATUS(status); | ||
817 | } | ||
818 | |||
819 | /******************************************************************************* | ||
820 | * | ||
821 | * FUNCTION: acpi_ds_eval_table_region_operands | ||
822 | * | ||
823 | * PARAMETERS: walk_state - Current walk | ||
824 | * Op - A valid region Op object | ||
825 | * | ||
826 | * RETURN: Status | ||
827 | * | ||
828 | * DESCRIPTION: Get region address and length | ||
829 | * Called from acpi_ds_exec_end_op during data_table_region parse tree walk | ||
830 | * | ||
831 | ******************************************************************************/ | ||
832 | |||
833 | acpi_status | ||
834 | acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, | ||
835 | union acpi_parse_object *op) | ||
836 | { | ||
837 | acpi_status status; | ||
838 | union acpi_operand_object *obj_desc; | ||
839 | union acpi_operand_object **operand; | ||
840 | struct acpi_namespace_node *node; | ||
841 | union acpi_parse_object *next_op; | ||
842 | u32 table_index; | ||
843 | struct acpi_table_header *table; | ||
844 | |||
845 | ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); | ||
846 | |||
847 | /* | ||
848 | * This is where we evaluate the signature_string and oem_iDString | ||
849 | * and oem_table_iDString of the data_table_region declaration | ||
850 | */ | ||
851 | node = op->common.node; | ||
852 | |||
853 | /* next_op points to signature_string op */ | ||
854 | |||
855 | next_op = op->common.value.arg; | ||
856 | |||
857 | /* | ||
858 | * Evaluate/create the signature_string and oem_iDString | ||
859 | * and oem_table_iDString operands | ||
860 | */ | ||
861 | status = acpi_ds_create_operands(walk_state, next_op); | ||
862 | if (ACPI_FAILURE(status)) { | ||
863 | return_ACPI_STATUS(status); | ||
864 | } | ||
865 | |||
866 | /* | ||
867 | * Resolve the signature_string and oem_iDString | ||
868 | * and oem_table_iDString operands | ||
869 | */ | ||
870 | status = acpi_ex_resolve_operands(op->common.aml_opcode, | ||
871 | ACPI_WALK_OPERANDS, walk_state); | ||
872 | if (ACPI_FAILURE(status)) { | ||
873 | return_ACPI_STATUS(status); | ||
874 | } | ||
875 | |||
876 | operand = &walk_state->operands[0]; | ||
877 | |||
878 | /* Find the ACPI table */ | ||
879 | |||
880 | status = acpi_tb_find_table(operand[0]->string.pointer, | ||
881 | operand[1]->string.pointer, | ||
882 | operand[2]->string.pointer, &table_index); | ||
883 | if (ACPI_FAILURE(status)) { | ||
884 | return_ACPI_STATUS(status); | ||
885 | } | ||
886 | |||
887 | acpi_ut_remove_reference(operand[0]); | ||
888 | acpi_ut_remove_reference(operand[1]); | ||
889 | acpi_ut_remove_reference(operand[2]); | ||
890 | |||
891 | status = acpi_get_table_by_index(table_index, &table); | ||
892 | if (ACPI_FAILURE(status)) { | ||
893 | return_ACPI_STATUS(status); | ||
894 | } | ||
895 | |||
896 | obj_desc = acpi_ns_get_attached_object(node); | ||
897 | if (!obj_desc) { | ||
898 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
899 | } | ||
900 | |||
901 | obj_desc->region.address = | ||
902 | (acpi_physical_address) ACPI_TO_INTEGER(table); | ||
903 | obj_desc->region.length = table->length; | ||
904 | |||
905 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | ||
906 | obj_desc, | ||
907 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), | ||
908 | obj_desc->region.length)); | ||
909 | |||
910 | /* Now the address and length are valid for this opregion */ | ||
911 | |||
912 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | ||
913 | |||
914 | return_ACPI_STATUS(status); | ||
915 | } | ||
916 | |||
917 | /******************************************************************************* | ||
918 | * | ||
919 | * FUNCTION: acpi_ds_eval_data_object_operands | ||
920 | * | ||
921 | * PARAMETERS: walk_state - Current walk | ||
922 | * Op - A valid data_object Op object | ||
923 | * obj_desc - data_object | ||
924 | * | ||
925 | * RETURN: Status | ||
926 | * | ||
927 | * DESCRIPTION: Get the operands and complete the following data object types: | ||
928 | * Buffer, Package. | ||
929 | * | ||
930 | ******************************************************************************/ | ||
931 | |||
932 | acpi_status | ||
933 | acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, | ||
934 | union acpi_parse_object *op, | ||
935 | union acpi_operand_object *obj_desc) | ||
936 | { | ||
937 | acpi_status status; | ||
938 | union acpi_operand_object *arg_desc; | ||
939 | u32 length; | ||
940 | |||
941 | ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); | ||
942 | |||
943 | /* The first operand (for all of these data objects) is the length */ | ||
944 | |||
945 | /* | ||
946 | * Set proper index into operand stack for acpi_ds_obj_stack_push | ||
947 | * invoked inside acpi_ds_create_operand. | ||
948 | */ | ||
949 | walk_state->operand_index = walk_state->num_operands; | ||
950 | |||
951 | status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); | ||
952 | if (ACPI_FAILURE(status)) { | ||
953 | return_ACPI_STATUS(status); | ||
954 | } | ||
955 | |||
956 | status = acpi_ex_resolve_operands(walk_state->opcode, | ||
957 | &(walk_state-> | ||
958 | operands[walk_state->num_operands - | ||
959 | 1]), walk_state); | ||
960 | if (ACPI_FAILURE(status)) { | ||
961 | return_ACPI_STATUS(status); | ||
962 | } | ||
963 | |||
964 | /* Extract length operand */ | ||
965 | |||
966 | arg_desc = walk_state->operands[walk_state->num_operands - 1]; | ||
967 | length = (u32) arg_desc->integer.value; | ||
968 | |||
969 | /* Cleanup for length operand */ | ||
970 | |||
971 | status = acpi_ds_obj_stack_pop(1, walk_state); | ||
972 | if (ACPI_FAILURE(status)) { | ||
973 | return_ACPI_STATUS(status); | ||
974 | } | ||
975 | |||
976 | acpi_ut_remove_reference(arg_desc); | ||
977 | |||
978 | /* | ||
979 | * Create the actual data object | ||
980 | */ | ||
981 | switch (op->common.aml_opcode) { | ||
982 | case AML_BUFFER_OP: | ||
983 | |||
984 | status = | ||
985 | acpi_ds_build_internal_buffer_obj(walk_state, op, length, | ||
986 | &obj_desc); | ||
987 | break; | ||
988 | |||
989 | case AML_PACKAGE_OP: | ||
990 | case AML_VAR_PACKAGE_OP: | ||
991 | |||
992 | status = | ||
993 | acpi_ds_build_internal_package_obj(walk_state, op, length, | ||
994 | &obj_desc); | ||
995 | break; | ||
996 | |||
997 | default: | ||
998 | return_ACPI_STATUS(AE_AML_BAD_OPCODE); | ||
999 | } | ||
1000 | |||
1001 | if (ACPI_SUCCESS(status)) { | ||
1002 | /* | ||
1003 | * Return the object in the walk_state, unless the parent is a package - | ||
1004 | * in this case, the return object will be stored in the parse tree | ||
1005 | * for the package. | ||
1006 | */ | ||
1007 | if ((!op->common.parent) || | ||
1008 | ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && | ||
1009 | (op->common.parent->common.aml_opcode != | ||
1010 | AML_VAR_PACKAGE_OP) | ||
1011 | && (op->common.parent->common.aml_opcode != AML_NAME_OP))) { | ||
1012 | walk_state->result_obj = obj_desc; | ||
1013 | } | ||
1014 | } | ||
1015 | |||
1016 | return_ACPI_STATUS(status); | ||
1017 | } | ||
1018 | |||
1019 | /******************************************************************************* | ||
1020 | * | ||
1021 | * FUNCTION: acpi_ds_eval_bank_field_operands | ||
1022 | * | ||
1023 | * PARAMETERS: walk_state - Current walk | ||
1024 | * Op - A valid bank_field Op object | ||
1025 | * | ||
1026 | * RETURN: Status | ||
1027 | * | ||
1028 | * DESCRIPTION: Get bank_field bank_value | ||
1029 | * Called from acpi_ds_exec_end_op during bank_field parse tree walk | ||
1030 | * | ||
1031 | ******************************************************************************/ | ||
1032 | |||
1033 | acpi_status | ||
1034 | acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | ||
1035 | union acpi_parse_object *op) | ||
1036 | { | ||
1037 | acpi_status status; | ||
1038 | union acpi_operand_object *obj_desc; | ||
1039 | union acpi_operand_object *operand_desc; | ||
1040 | struct acpi_namespace_node *node; | ||
1041 | union acpi_parse_object *next_op; | ||
1042 | union acpi_parse_object *arg; | ||
1043 | |||
1044 | ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); | ||
1045 | |||
1046 | /* | ||
1047 | * This is where we evaluate the bank_value field of the | ||
1048 | * bank_field declaration | ||
1049 | */ | ||
1050 | |||
1051 | /* next_op points to the op that holds the Region */ | ||
1052 | |||
1053 | next_op = op->common.value.arg; | ||
1054 | |||
1055 | /* next_op points to the op that holds the Bank Register */ | ||
1056 | |||
1057 | next_op = next_op->common.next; | ||
1058 | |||
1059 | /* next_op points to the op that holds the Bank Value */ | ||
1060 | |||
1061 | next_op = next_op->common.next; | ||
1062 | |||
1063 | /* | ||
1064 | * Set proper index into operand stack for acpi_ds_obj_stack_push | ||
1065 | * invoked inside acpi_ds_create_operand. | ||
1066 | * | ||
1067 | * We use walk_state->Operands[0] to store the evaluated bank_value | ||
1068 | */ | ||
1069 | walk_state->operand_index = 0; | ||
1070 | |||
1071 | status = acpi_ds_create_operand(walk_state, next_op, 0); | ||
1072 | if (ACPI_FAILURE(status)) { | ||
1073 | return_ACPI_STATUS(status); | ||
1074 | } | ||
1075 | |||
1076 | status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); | ||
1077 | if (ACPI_FAILURE(status)) { | ||
1078 | return_ACPI_STATUS(status); | ||
1079 | } | ||
1080 | |||
1081 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, | ||
1082 | acpi_ps_get_opcode_name(op->common.aml_opcode), 1); | ||
1083 | /* | ||
1084 | * Get the bank_value operand and save it | ||
1085 | * (at Top of stack) | ||
1086 | */ | ||
1087 | operand_desc = walk_state->operands[0]; | ||
1088 | |||
1089 | /* Arg points to the start Bank Field */ | ||
1090 | |||
1091 | arg = acpi_ps_get_arg(op, 4); | ||
1092 | while (arg) { | ||
1093 | |||
1094 | /* Ignore OFFSET and ACCESSAS terms here */ | ||
1095 | |||
1096 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | ||
1097 | node = arg->common.node; | ||
1098 | |||
1099 | obj_desc = acpi_ns_get_attached_object(node); | ||
1100 | if (!obj_desc) { | ||
1101 | return_ACPI_STATUS(AE_NOT_EXIST); | ||
1102 | } | ||
1103 | |||
1104 | obj_desc->bank_field.value = | ||
1105 | (u32) operand_desc->integer.value; | ||
1106 | } | ||
1107 | |||
1108 | /* Move to next field in the list */ | ||
1109 | |||
1110 | arg = arg->common.next; | ||
1111 | } | ||
1112 | |||
1113 | acpi_ut_remove_reference(operand_desc); | ||
1114 | return_ACPI_STATUS(status); | ||
1115 | } | ||
1116 | |||
1117 | /******************************************************************************* | ||
1118 | * | ||
1119 | * FUNCTION: acpi_ds_exec_begin_control_op | ||
1120 | * | ||
1121 | * PARAMETERS: walk_list - The list that owns the walk stack | ||
1122 | * Op - The control Op | ||
1123 | * | ||
1124 | * RETURN: Status | ||
1125 | * | ||
1126 | * DESCRIPTION: Handles all control ops encountered during control method | ||
1127 | * execution. | ||
1128 | * | ||
1129 | ******************************************************************************/ | ||
1130 | |||
1131 | acpi_status | ||
1132 | acpi_ds_exec_begin_control_op(struct acpi_walk_state *walk_state, | ||
1133 | union acpi_parse_object *op) | ||
1134 | { | ||
1135 | acpi_status status = AE_OK; | ||
1136 | union acpi_generic_state *control_state; | ||
1137 | |||
1138 | ACPI_FUNCTION_NAME(ds_exec_begin_control_op); | ||
1139 | |||
1140 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p Opcode=%2.2X State=%p\n", op, | ||
1141 | op->common.aml_opcode, walk_state)); | ||
1142 | |||
1143 | switch (op->common.aml_opcode) { | ||
1144 | case AML_WHILE_OP: | ||
1145 | |||
1146 | /* | ||
1147 | * If this is an additional iteration of a while loop, continue. | ||
1148 | * There is no need to allocate a new control state. | ||
1149 | */ | ||
1150 | if (walk_state->control_state) { | ||
1151 | if (walk_state->control_state->control.aml_predicate_start | ||
1152 | == (walk_state->parser_state.aml - 1)) { | ||
1153 | |||
1154 | /* Reset the state to start-of-loop */ | ||
1155 | |||
1156 | walk_state->control_state->common.state = | ||
1157 | ACPI_CONTROL_CONDITIONAL_EXECUTING; | ||
1158 | break; | ||
1159 | } | ||
1160 | } | ||
1161 | |||
1162 | /*lint -fallthrough */ | ||
1163 | |||
1164 | case AML_IF_OP: | ||
1165 | |||
1166 | /* | ||
1167 | * IF/WHILE: Create a new control state to manage these | ||
1168 | * constructs. We need to manage these as a stack, in order | ||
1169 | * to handle nesting. | ||
1170 | */ | ||
1171 | control_state = acpi_ut_create_control_state(); | ||
1172 | if (!control_state) { | ||
1173 | status = AE_NO_MEMORY; | ||
1174 | break; | ||
1175 | } | ||
1176 | /* | ||
1177 | * Save a pointer to the predicate for multiple executions | ||
1178 | * of a loop | ||
1179 | */ | ||
1180 | control_state->control.aml_predicate_start = | ||
1181 | walk_state->parser_state.aml - 1; | ||
1182 | control_state->control.package_end = | ||
1183 | walk_state->parser_state.pkg_end; | ||
1184 | control_state->control.opcode = op->common.aml_opcode; | ||
1185 | |||
1186 | /* Push the control state on this walk's control stack */ | ||
1187 | |||
1188 | acpi_ut_push_generic_state(&walk_state->control_state, | ||
1189 | control_state); | ||
1190 | break; | ||
1191 | |||
1192 | case AML_ELSE_OP: | ||
1193 | |||
1194 | /* Predicate is in the state object */ | ||
1195 | /* If predicate is true, the IF was executed, ignore ELSE part */ | ||
1196 | |||
1197 | if (walk_state->last_predicate) { | ||
1198 | status = AE_CTRL_TRUE; | ||
1199 | } | ||
1200 | |||
1201 | break; | ||
1202 | |||
1203 | case AML_RETURN_OP: | ||
1204 | |||
1205 | break; | ||
1206 | |||
1207 | default: | ||
1208 | break; | ||
1209 | } | ||
1210 | |||
1211 | return (status); | ||
1212 | } | ||
1213 | |||
1214 | /******************************************************************************* | ||
1215 | * | ||
1216 | * FUNCTION: acpi_ds_exec_end_control_op | ||
1217 | * | ||
1218 | * PARAMETERS: walk_list - The list that owns the walk stack | ||
1219 | * Op - The control Op | ||
1220 | * | ||
1221 | * RETURN: Status | ||
1222 | * | ||
1223 | * DESCRIPTION: Handles all control ops encountered during control method | ||
1224 | * execution. | ||
1225 | * | ||
1226 | ******************************************************************************/ | ||
1227 | |||
1228 | acpi_status | ||
1229 | acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state, | ||
1230 | union acpi_parse_object * op) | ||
1231 | { | ||
1232 | acpi_status status = AE_OK; | ||
1233 | union acpi_generic_state *control_state; | ||
1234 | |||
1235 | ACPI_FUNCTION_NAME(ds_exec_end_control_op); | ||
1236 | |||
1237 | switch (op->common.aml_opcode) { | ||
1238 | case AML_IF_OP: | ||
1239 | |||
1240 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[IF_OP] Op=%p\n", op)); | ||
1241 | |||
1242 | /* | ||
1243 | * Save the result of the predicate in case there is an | ||
1244 | * ELSE to come | ||
1245 | */ | ||
1246 | walk_state->last_predicate = | ||
1247 | (u8) walk_state->control_state->common.value; | ||
1248 | |||
1249 | /* | ||
1250 | * Pop the control state that was created at the start | ||
1251 | * of the IF and free it | ||
1252 | */ | ||
1253 | control_state = | ||
1254 | acpi_ut_pop_generic_state(&walk_state->control_state); | ||
1255 | acpi_ut_delete_generic_state(control_state); | ||
1256 | break; | ||
1257 | |||
1258 | case AML_ELSE_OP: | ||
1259 | |||
1260 | break; | ||
1261 | |||
1262 | case AML_WHILE_OP: | ||
1263 | |||
1264 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "[WHILE_OP] Op=%p\n", op)); | ||
1265 | |||
1266 | control_state = walk_state->control_state; | ||
1267 | if (control_state->common.value) { | ||
1268 | |||
1269 | /* Predicate was true, the body of the loop was just executed */ | ||
1270 | |||
1271 | /* | ||
1272 | * This loop counter mechanism allows the interpreter to escape | ||
1273 | * possibly infinite loops. This can occur in poorly written AML | ||
1274 | * when the hardware does not respond within a while loop and the | ||
1275 | * loop does not implement a timeout. | ||
1276 | */ | ||
1277 | control_state->control.loop_count++; | ||
1278 | if (control_state->control.loop_count > | ||
1279 | ACPI_MAX_LOOP_ITERATIONS) { | ||
1280 | status = AE_AML_INFINITE_LOOP; | ||
1281 | break; | ||
1282 | } | ||
1283 | |||
1284 | /* | ||
1285 | * Go back and evaluate the predicate and maybe execute the loop | ||
1286 | * another time | ||
1287 | */ | ||
1288 | status = AE_CTRL_PENDING; | ||
1289 | walk_state->aml_last_while = | ||
1290 | control_state->control.aml_predicate_start; | ||
1291 | break; | ||
1292 | } | ||
1293 | |||
1294 | /* Predicate was false, terminate this while loop */ | ||
1295 | |||
1296 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1297 | "[WHILE_OP] termination! Op=%p\n", op)); | ||
1298 | |||
1299 | /* Pop this control state and free it */ | ||
1300 | |||
1301 | control_state = | ||
1302 | acpi_ut_pop_generic_state(&walk_state->control_state); | ||
1303 | acpi_ut_delete_generic_state(control_state); | ||
1304 | break; | ||
1305 | |||
1306 | case AML_RETURN_OP: | ||
1307 | |||
1308 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1309 | "[RETURN_OP] Op=%p Arg=%p\n", op, | ||
1310 | op->common.value.arg)); | ||
1311 | |||
1312 | /* | ||
1313 | * One optional operand -- the return value | ||
1314 | * It can be either an immediate operand or a result that | ||
1315 | * has been bubbled up the tree | ||
1316 | */ | ||
1317 | if (op->common.value.arg) { | ||
1318 | |||
1319 | /* Since we have a real Return(), delete any implicit return */ | ||
1320 | |||
1321 | acpi_ds_clear_implicit_return(walk_state); | ||
1322 | |||
1323 | /* Return statement has an immediate operand */ | ||
1324 | |||
1325 | status = | ||
1326 | acpi_ds_create_operands(walk_state, | ||
1327 | op->common.value.arg); | ||
1328 | if (ACPI_FAILURE(status)) { | ||
1329 | return (status); | ||
1330 | } | ||
1331 | |||
1332 | /* | ||
1333 | * If value being returned is a Reference (such as | ||
1334 | * an arg or local), resolve it now because it may | ||
1335 | * cease to exist at the end of the method. | ||
1336 | */ | ||
1337 | status = | ||
1338 | acpi_ex_resolve_to_value(&walk_state->operands[0], | ||
1339 | walk_state); | ||
1340 | if (ACPI_FAILURE(status)) { | ||
1341 | return (status); | ||
1342 | } | ||
1343 | |||
1344 | /* | ||
1345 | * Get the return value and save as the last result | ||
1346 | * value. This is the only place where walk_state->return_desc | ||
1347 | * is set to anything other than zero! | ||
1348 | */ | ||
1349 | walk_state->return_desc = walk_state->operands[0]; | ||
1350 | } else if (walk_state->result_count) { | ||
1351 | |||
1352 | /* Since we have a real Return(), delete any implicit return */ | ||
1353 | |||
1354 | acpi_ds_clear_implicit_return(walk_state); | ||
1355 | |||
1356 | /* | ||
1357 | * The return value has come from a previous calculation. | ||
1358 | * | ||
1359 | * If value being returned is a Reference (such as | ||
1360 | * an arg or local), resolve it now because it may | ||
1361 | * cease to exist at the end of the method. | ||
1362 | * | ||
1363 | * Allow references created by the Index operator to return unchanged. | ||
1364 | */ | ||
1365 | if ((ACPI_GET_DESCRIPTOR_TYPE | ||
1366 | (walk_state->results->results.obj_desc[0]) == | ||
1367 | ACPI_DESC_TYPE_OPERAND) | ||
1368 | && | ||
1369 | (ACPI_GET_OBJECT_TYPE | ||
1370 | (walk_state->results->results.obj_desc[0]) == | ||
1371 | ACPI_TYPE_LOCAL_REFERENCE) | ||
1372 | && ((walk_state->results->results.obj_desc[0])-> | ||
1373 | reference.class != ACPI_REFCLASS_INDEX)) { | ||
1374 | status = | ||
1375 | acpi_ex_resolve_to_value(&walk_state-> | ||
1376 | results->results. | ||
1377 | obj_desc[0], | ||
1378 | walk_state); | ||
1379 | if (ACPI_FAILURE(status)) { | ||
1380 | return (status); | ||
1381 | } | ||
1382 | } | ||
1383 | |||
1384 | walk_state->return_desc = | ||
1385 | walk_state->results->results.obj_desc[0]; | ||
1386 | } else { | ||
1387 | /* No return operand */ | ||
1388 | |||
1389 | if (walk_state->num_operands) { | ||
1390 | acpi_ut_remove_reference(walk_state-> | ||
1391 | operands[0]); | ||
1392 | } | ||
1393 | |||
1394 | walk_state->operands[0] = NULL; | ||
1395 | walk_state->num_operands = 0; | ||
1396 | walk_state->return_desc = NULL; | ||
1397 | } | ||
1398 | |||
1399 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1400 | "Completed RETURN_OP State=%p, RetVal=%p\n", | ||
1401 | walk_state, walk_state->return_desc)); | ||
1402 | |||
1403 | /* End the control method execution right now */ | ||
1404 | |||
1405 | status = AE_CTRL_TERMINATE; | ||
1406 | break; | ||
1407 | |||
1408 | case AML_NOOP_OP: | ||
1409 | |||
1410 | /* Just do nothing! */ | ||
1411 | break; | ||
1412 | |||
1413 | case AML_BREAK_POINT_OP: | ||
1414 | |||
1415 | /* Call up to the OS service layer to handle this */ | ||
1416 | |||
1417 | status = | ||
1418 | acpi_os_signal(ACPI_SIGNAL_BREAKPOINT, | ||
1419 | "Executed AML Breakpoint opcode"); | ||
1420 | |||
1421 | /* If and when it returns, all done. */ | ||
1422 | |||
1423 | break; | ||
1424 | |||
1425 | case AML_BREAK_OP: | ||
1426 | case AML_CONTINUE_OP: /* ACPI 2.0 */ | ||
1427 | |||
1428 | /* Pop and delete control states until we find a while */ | ||
1429 | |||
1430 | while (walk_state->control_state && | ||
1431 | (walk_state->control_state->control.opcode != | ||
1432 | AML_WHILE_OP)) { | ||
1433 | control_state = | ||
1434 | acpi_ut_pop_generic_state(&walk_state-> | ||
1435 | control_state); | ||
1436 | acpi_ut_delete_generic_state(control_state); | ||
1437 | } | ||
1438 | |||
1439 | /* No while found? */ | ||
1440 | |||
1441 | if (!walk_state->control_state) { | ||
1442 | return (AE_AML_NO_WHILE); | ||
1443 | } | ||
1444 | |||
1445 | /* Was: walk_state->aml_last_while = walk_state->control_state->Control.aml_predicate_start; */ | ||
1446 | |||
1447 | walk_state->aml_last_while = | ||
1448 | walk_state->control_state->control.package_end; | ||
1449 | |||
1450 | /* Return status depending on opcode */ | ||
1451 | |||
1452 | if (op->common.aml_opcode == AML_BREAK_OP) { | ||
1453 | status = AE_CTRL_BREAK; | ||
1454 | } else { | ||
1455 | status = AE_CTRL_CONTINUE; | ||
1456 | } | ||
1457 | break; | ||
1458 | |||
1459 | default: | ||
1460 | |||
1461 | ACPI_ERROR((AE_INFO, "Unknown control opcode=%X Op=%p", | ||
1462 | op->common.aml_opcode, op)); | ||
1463 | |||
1464 | status = AE_AML_BAD_OPCODE; | ||
1465 | break; | ||
1466 | } | ||
1467 | |||
1468 | return (status); | ||
1469 | } | ||
diff --git a/drivers/acpi/dispatcher/dsutils.c b/drivers/acpi/dispatcher/dsutils.c deleted file mode 100644 index 9c88846ca2ce..000000000000 --- a/drivers/acpi/dispatcher/dsutils.c +++ /dev/null | |||
@@ -1,869 +0,0 @@ | |||
1 | /******************************************************************************* | ||
2 | * | ||
3 | * Module Name: dsutils - Dispatcher utilities | ||
4 | * | ||
5 | ******************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/acparser.h> | ||
47 | #include <acpi/amlcode.h> | ||
48 | #include <acpi/acdispat.h> | ||
49 | #include <acpi/acinterp.h> | ||
50 | #include <acpi/acnamesp.h> | ||
51 | #include <acpi/acdebug.h> | ||
52 | |||
53 | #define _COMPONENT ACPI_DISPATCHER | ||
54 | ACPI_MODULE_NAME("dsutils") | ||
55 | |||
56 | /******************************************************************************* | ||
57 | * | ||
58 | * FUNCTION: acpi_ds_clear_implicit_return | ||
59 | * | ||
60 | * PARAMETERS: walk_state - Current State | ||
61 | * | ||
62 | * RETURN: None. | ||
63 | * | ||
64 | * DESCRIPTION: Clear and remove a reference on an implicit return value. Used | ||
65 | * to delete "stale" return values (if enabled, the return value | ||
66 | * from every operator is saved at least momentarily, in case the | ||
67 | * parent method exits.) | ||
68 | * | ||
69 | ******************************************************************************/ | ||
70 | void acpi_ds_clear_implicit_return(struct acpi_walk_state *walk_state) | ||
71 | { | ||
72 | ACPI_FUNCTION_NAME(ds_clear_implicit_return); | ||
73 | |||
74 | /* | ||
75 | * Slack must be enabled for this feature | ||
76 | */ | ||
77 | if (!acpi_gbl_enable_interpreter_slack) { | ||
78 | return; | ||
79 | } | ||
80 | |||
81 | if (walk_state->implicit_return_obj) { | ||
82 | /* | ||
83 | * Delete any "stale" implicit return. However, in | ||
84 | * complex statements, the implicit return value can be | ||
85 | * bubbled up several levels. | ||
86 | */ | ||
87 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
88 | "Removing reference on stale implicit return obj %p\n", | ||
89 | walk_state->implicit_return_obj)); | ||
90 | |||
91 | acpi_ut_remove_reference(walk_state->implicit_return_obj); | ||
92 | walk_state->implicit_return_obj = NULL; | ||
93 | } | ||
94 | } | ||
95 | |||
96 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
97 | /******************************************************************************* | ||
98 | * | ||
99 | * FUNCTION: acpi_ds_do_implicit_return | ||
100 | * | ||
101 | * PARAMETERS: return_desc - The return value | ||
102 | * walk_state - Current State | ||
103 | * add_reference - True if a reference should be added to the | ||
104 | * return object | ||
105 | * | ||
106 | * RETURN: TRUE if implicit return enabled, FALSE otherwise | ||
107 | * | ||
108 | * DESCRIPTION: Implements the optional "implicit return". We save the result | ||
109 | * of every ASL operator and control method invocation in case the | ||
110 | * parent method exit. Before storing a new return value, we | ||
111 | * delete the previous return value. | ||
112 | * | ||
113 | ******************************************************************************/ | ||
114 | |||
115 | u8 | ||
116 | acpi_ds_do_implicit_return(union acpi_operand_object *return_desc, | ||
117 | struct acpi_walk_state *walk_state, u8 add_reference) | ||
118 | { | ||
119 | ACPI_FUNCTION_NAME(ds_do_implicit_return); | ||
120 | |||
121 | /* | ||
122 | * Slack must be enabled for this feature, and we must | ||
123 | * have a valid return object | ||
124 | */ | ||
125 | if ((!acpi_gbl_enable_interpreter_slack) || (!return_desc)) { | ||
126 | return (FALSE); | ||
127 | } | ||
128 | |||
129 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
130 | "Result %p will be implicitly returned; Prev=%p\n", | ||
131 | return_desc, walk_state->implicit_return_obj)); | ||
132 | |||
133 | /* | ||
134 | * Delete any "stale" implicit return value first. However, in | ||
135 | * complex statements, the implicit return value can be | ||
136 | * bubbled up several levels, so we don't clear the value if it | ||
137 | * is the same as the return_desc. | ||
138 | */ | ||
139 | if (walk_state->implicit_return_obj) { | ||
140 | if (walk_state->implicit_return_obj == return_desc) { | ||
141 | return (TRUE); | ||
142 | } | ||
143 | acpi_ds_clear_implicit_return(walk_state); | ||
144 | } | ||
145 | |||
146 | /* Save the implicit return value, add a reference if requested */ | ||
147 | |||
148 | walk_state->implicit_return_obj = return_desc; | ||
149 | if (add_reference) { | ||
150 | acpi_ut_add_reference(return_desc); | ||
151 | } | ||
152 | |||
153 | return (TRUE); | ||
154 | } | ||
155 | |||
156 | /******************************************************************************* | ||
157 | * | ||
158 | * FUNCTION: acpi_ds_is_result_used | ||
159 | * | ||
160 | * PARAMETERS: Op - Current Op | ||
161 | * walk_state - Current State | ||
162 | * | ||
163 | * RETURN: TRUE if result is used, FALSE otherwise | ||
164 | * | ||
165 | * DESCRIPTION: Check if a result object will be used by the parent | ||
166 | * | ||
167 | ******************************************************************************/ | ||
168 | |||
169 | u8 | ||
170 | acpi_ds_is_result_used(union acpi_parse_object * op, | ||
171 | struct acpi_walk_state * walk_state) | ||
172 | { | ||
173 | const struct acpi_opcode_info *parent_info; | ||
174 | |||
175 | ACPI_FUNCTION_TRACE_PTR(ds_is_result_used, op); | ||
176 | |||
177 | /* Must have both an Op and a Result Object */ | ||
178 | |||
179 | if (!op) { | ||
180 | ACPI_ERROR((AE_INFO, "Null Op")); | ||
181 | return_UINT8(TRUE); | ||
182 | } | ||
183 | |||
184 | /* | ||
185 | * We know that this operator is not a | ||
186 | * Return() operator (would not come here.) The following code is the | ||
187 | * optional support for a so-called "implicit return". Some AML code | ||
188 | * assumes that the last value of the method is "implicitly" returned | ||
189 | * to the caller. Just save the last result as the return value. | ||
190 | * NOTE: this is optional because the ASL language does not actually | ||
191 | * support this behavior. | ||
192 | */ | ||
193 | (void)acpi_ds_do_implicit_return(walk_state->result_obj, walk_state, | ||
194 | TRUE); | ||
195 | |||
196 | /* | ||
197 | * Now determine if the parent will use the result | ||
198 | * | ||
199 | * If there is no parent, or the parent is a scope_op, we are executing | ||
200 | * at the method level. An executing method typically has no parent, | ||
201 | * since each method is parsed separately. A method invoked externally | ||
202 | * via execute_control_method has a scope_op as the parent. | ||
203 | */ | ||
204 | if ((!op->common.parent) || | ||
205 | (op->common.parent->common.aml_opcode == AML_SCOPE_OP)) { | ||
206 | |||
207 | /* No parent, the return value cannot possibly be used */ | ||
208 | |||
209 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
210 | "At Method level, result of [%s] not used\n", | ||
211 | acpi_ps_get_opcode_name(op->common. | ||
212 | aml_opcode))); | ||
213 | return_UINT8(FALSE); | ||
214 | } | ||
215 | |||
216 | /* Get info on the parent. The root_op is AML_SCOPE */ | ||
217 | |||
218 | parent_info = | ||
219 | acpi_ps_get_opcode_info(op->common.parent->common.aml_opcode); | ||
220 | if (parent_info->class == AML_CLASS_UNKNOWN) { | ||
221 | ACPI_ERROR((AE_INFO, "Unknown parent opcode Op=%p", op)); | ||
222 | return_UINT8(FALSE); | ||
223 | } | ||
224 | |||
225 | /* | ||
226 | * Decide what to do with the result based on the parent. If | ||
227 | * the parent opcode will not use the result, delete the object. | ||
228 | * Otherwise leave it as is, it will be deleted when it is used | ||
229 | * as an operand later. | ||
230 | */ | ||
231 | switch (parent_info->class) { | ||
232 | case AML_CLASS_CONTROL: | ||
233 | |||
234 | switch (op->common.parent->common.aml_opcode) { | ||
235 | case AML_RETURN_OP: | ||
236 | |||
237 | /* Never delete the return value associated with a return opcode */ | ||
238 | |||
239 | goto result_used; | ||
240 | |||
241 | case AML_IF_OP: | ||
242 | case AML_WHILE_OP: | ||
243 | |||
244 | /* | ||
245 | * If we are executing the predicate AND this is the predicate op, | ||
246 | * we will use the return value | ||
247 | */ | ||
248 | if ((walk_state->control_state->common.state == | ||
249 | ACPI_CONTROL_PREDICATE_EXECUTING) | ||
250 | && (walk_state->control_state->control. | ||
251 | predicate_op == op)) { | ||
252 | goto result_used; | ||
253 | } | ||
254 | break; | ||
255 | |||
256 | default: | ||
257 | /* Ignore other control opcodes */ | ||
258 | break; | ||
259 | } | ||
260 | |||
261 | /* The general control opcode returns no result */ | ||
262 | |||
263 | goto result_not_used; | ||
264 | |||
265 | case AML_CLASS_CREATE: | ||
266 | |||
267 | /* | ||
268 | * These opcodes allow term_arg(s) as operands and therefore | ||
269 | * the operands can be method calls. The result is used. | ||
270 | */ | ||
271 | goto result_used; | ||
272 | |||
273 | case AML_CLASS_NAMED_OBJECT: | ||
274 | |||
275 | if ((op->common.parent->common.aml_opcode == AML_REGION_OP) || | ||
276 | (op->common.parent->common.aml_opcode == AML_DATA_REGION_OP) | ||
277 | || (op->common.parent->common.aml_opcode == AML_PACKAGE_OP) | ||
278 | || (op->common.parent->common.aml_opcode == | ||
279 | AML_VAR_PACKAGE_OP) | ||
280 | || (op->common.parent->common.aml_opcode == AML_BUFFER_OP) | ||
281 | || (op->common.parent->common.aml_opcode == | ||
282 | AML_INT_EVAL_SUBTREE_OP) | ||
283 | || (op->common.parent->common.aml_opcode == | ||
284 | AML_BANK_FIELD_OP)) { | ||
285 | /* | ||
286 | * These opcodes allow term_arg(s) as operands and therefore | ||
287 | * the operands can be method calls. The result is used. | ||
288 | */ | ||
289 | goto result_used; | ||
290 | } | ||
291 | |||
292 | goto result_not_used; | ||
293 | |||
294 | default: | ||
295 | |||
296 | /* | ||
297 | * In all other cases. the parent will actually use the return | ||
298 | * object, so keep it. | ||
299 | */ | ||
300 | goto result_used; | ||
301 | } | ||
302 | |||
303 | result_used: | ||
304 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
305 | "Result of [%s] used by Parent [%s] Op=%p\n", | ||
306 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
307 | acpi_ps_get_opcode_name(op->common.parent->common. | ||
308 | aml_opcode), op)); | ||
309 | |||
310 | return_UINT8(TRUE); | ||
311 | |||
312 | result_not_used: | ||
313 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
314 | "Result of [%s] not used by Parent [%s] Op=%p\n", | ||
315 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
316 | acpi_ps_get_opcode_name(op->common.parent->common. | ||
317 | aml_opcode), op)); | ||
318 | |||
319 | return_UINT8(FALSE); | ||
320 | } | ||
321 | |||
322 | /******************************************************************************* | ||
323 | * | ||
324 | * FUNCTION: acpi_ds_delete_result_if_not_used | ||
325 | * | ||
326 | * PARAMETERS: Op - Current parse Op | ||
327 | * result_obj - Result of the operation | ||
328 | * walk_state - Current state | ||
329 | * | ||
330 | * RETURN: Status | ||
331 | * | ||
332 | * DESCRIPTION: Used after interpretation of an opcode. If there is an internal | ||
333 | * result descriptor, check if the parent opcode will actually use | ||
334 | * this result. If not, delete the result now so that it will | ||
335 | * not become orphaned. | ||
336 | * | ||
337 | ******************************************************************************/ | ||
338 | |||
339 | void | ||
340 | acpi_ds_delete_result_if_not_used(union acpi_parse_object *op, | ||
341 | union acpi_operand_object *result_obj, | ||
342 | struct acpi_walk_state *walk_state) | ||
343 | { | ||
344 | union acpi_operand_object *obj_desc; | ||
345 | acpi_status status; | ||
346 | |||
347 | ACPI_FUNCTION_TRACE_PTR(ds_delete_result_if_not_used, result_obj); | ||
348 | |||
349 | if (!op) { | ||
350 | ACPI_ERROR((AE_INFO, "Null Op")); | ||
351 | return_VOID; | ||
352 | } | ||
353 | |||
354 | if (!result_obj) { | ||
355 | return_VOID; | ||
356 | } | ||
357 | |||
358 | if (!acpi_ds_is_result_used(op, walk_state)) { | ||
359 | |||
360 | /* Must pop the result stack (obj_desc should be equal to result_obj) */ | ||
361 | |||
362 | status = acpi_ds_result_pop(&obj_desc, walk_state); | ||
363 | if (ACPI_SUCCESS(status)) { | ||
364 | acpi_ut_remove_reference(result_obj); | ||
365 | } | ||
366 | } | ||
367 | |||
368 | return_VOID; | ||
369 | } | ||
370 | |||
371 | /******************************************************************************* | ||
372 | * | ||
373 | * FUNCTION: acpi_ds_resolve_operands | ||
374 | * | ||
375 | * PARAMETERS: walk_state - Current walk state with operands on stack | ||
376 | * | ||
377 | * RETURN: Status | ||
378 | * | ||
379 | * DESCRIPTION: Resolve all operands to their values. Used to prepare | ||
380 | * arguments to a control method invocation (a call from one | ||
381 | * method to another.) | ||
382 | * | ||
383 | ******************************************************************************/ | ||
384 | |||
385 | acpi_status acpi_ds_resolve_operands(struct acpi_walk_state *walk_state) | ||
386 | { | ||
387 | u32 i; | ||
388 | acpi_status status = AE_OK; | ||
389 | |||
390 | ACPI_FUNCTION_TRACE_PTR(ds_resolve_operands, walk_state); | ||
391 | |||
392 | /* | ||
393 | * Attempt to resolve each of the valid operands | ||
394 | * Method arguments are passed by reference, not by value. This means | ||
395 | * that the actual objects are passed, not copies of the objects. | ||
396 | */ | ||
397 | for (i = 0; i < walk_state->num_operands; i++) { | ||
398 | status = | ||
399 | acpi_ex_resolve_to_value(&walk_state->operands[i], | ||
400 | walk_state); | ||
401 | if (ACPI_FAILURE(status)) { | ||
402 | break; | ||
403 | } | ||
404 | } | ||
405 | |||
406 | return_ACPI_STATUS(status); | ||
407 | } | ||
408 | |||
409 | /******************************************************************************* | ||
410 | * | ||
411 | * FUNCTION: acpi_ds_clear_operands | ||
412 | * | ||
413 | * PARAMETERS: walk_state - Current walk state with operands on stack | ||
414 | * | ||
415 | * RETURN: None | ||
416 | * | ||
417 | * DESCRIPTION: Clear all operands on the current walk state operand stack. | ||
418 | * | ||
419 | ******************************************************************************/ | ||
420 | |||
421 | void acpi_ds_clear_operands(struct acpi_walk_state *walk_state) | ||
422 | { | ||
423 | u32 i; | ||
424 | |||
425 | ACPI_FUNCTION_TRACE_PTR(ds_clear_operands, walk_state); | ||
426 | |||
427 | /* Remove a reference on each operand on the stack */ | ||
428 | |||
429 | for (i = 0; i < walk_state->num_operands; i++) { | ||
430 | /* | ||
431 | * Remove a reference to all operands, including both | ||
432 | * "Arguments" and "Targets". | ||
433 | */ | ||
434 | acpi_ut_remove_reference(walk_state->operands[i]); | ||
435 | walk_state->operands[i] = NULL; | ||
436 | } | ||
437 | |||
438 | walk_state->num_operands = 0; | ||
439 | return_VOID; | ||
440 | } | ||
441 | #endif | ||
442 | |||
443 | /******************************************************************************* | ||
444 | * | ||
445 | * FUNCTION: acpi_ds_create_operand | ||
446 | * | ||
447 | * PARAMETERS: walk_state - Current walk state | ||
448 | * Arg - Parse object for the argument | ||
449 | * arg_index - Which argument (zero based) | ||
450 | * | ||
451 | * RETURN: Status | ||
452 | * | ||
453 | * DESCRIPTION: Translate a parse tree object that is an argument to an AML | ||
454 | * opcode to the equivalent interpreter object. This may include | ||
455 | * looking up a name or entering a new name into the internal | ||
456 | * namespace. | ||
457 | * | ||
458 | ******************************************************************************/ | ||
459 | |||
460 | acpi_status | ||
461 | acpi_ds_create_operand(struct acpi_walk_state *walk_state, | ||
462 | union acpi_parse_object *arg, u32 arg_index) | ||
463 | { | ||
464 | acpi_status status = AE_OK; | ||
465 | char *name_string; | ||
466 | u32 name_length; | ||
467 | union acpi_operand_object *obj_desc; | ||
468 | union acpi_parse_object *parent_op; | ||
469 | u16 opcode; | ||
470 | acpi_interpreter_mode interpreter_mode; | ||
471 | const struct acpi_opcode_info *op_info; | ||
472 | |||
473 | ACPI_FUNCTION_TRACE_PTR(ds_create_operand, arg); | ||
474 | |||
475 | /* A valid name must be looked up in the namespace */ | ||
476 | |||
477 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && | ||
478 | (arg->common.value.string) && | ||
479 | !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
480 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Getting a name: Arg=%p\n", | ||
481 | arg)); | ||
482 | |||
483 | /* Get the entire name string from the AML stream */ | ||
484 | |||
485 | status = | ||
486 | acpi_ex_get_name_string(ACPI_TYPE_ANY, | ||
487 | arg->common.value.buffer, | ||
488 | &name_string, &name_length); | ||
489 | |||
490 | if (ACPI_FAILURE(status)) { | ||
491 | return_ACPI_STATUS(status); | ||
492 | } | ||
493 | |||
494 | /* All prefixes have been handled, and the name is in name_string */ | ||
495 | |||
496 | /* | ||
497 | * Special handling for buffer_field declarations. This is a deferred | ||
498 | * opcode that unfortunately defines the field name as the last | ||
499 | * parameter instead of the first. We get here when we are performing | ||
500 | * the deferred execution, so the actual name of the field is already | ||
501 | * in the namespace. We don't want to attempt to look it up again | ||
502 | * because we may be executing in a different scope than where the | ||
503 | * actual opcode exists. | ||
504 | */ | ||
505 | if ((walk_state->deferred_node) && | ||
506 | (walk_state->deferred_node->type == ACPI_TYPE_BUFFER_FIELD) | ||
507 | && (arg_index == | ||
508 | (u32) ((walk_state->opcode == | ||
509 | AML_CREATE_FIELD_OP) ? 3 : 2))) { | ||
510 | obj_desc = | ||
511 | ACPI_CAST_PTR(union acpi_operand_object, | ||
512 | walk_state->deferred_node); | ||
513 | status = AE_OK; | ||
514 | } else { /* All other opcodes */ | ||
515 | |||
516 | /* | ||
517 | * Differentiate between a namespace "create" operation | ||
518 | * versus a "lookup" operation (IMODE_LOAD_PASS2 vs. | ||
519 | * IMODE_EXECUTE) in order to support the creation of | ||
520 | * namespace objects during the execution of control methods. | ||
521 | */ | ||
522 | parent_op = arg->common.parent; | ||
523 | op_info = | ||
524 | acpi_ps_get_opcode_info(parent_op->common. | ||
525 | aml_opcode); | ||
526 | if ((op_info->flags & AML_NSNODE) | ||
527 | && (parent_op->common.aml_opcode != | ||
528 | AML_INT_METHODCALL_OP) | ||
529 | && (parent_op->common.aml_opcode != AML_REGION_OP) | ||
530 | && (parent_op->common.aml_opcode != | ||
531 | AML_INT_NAMEPATH_OP)) { | ||
532 | |||
533 | /* Enter name into namespace if not found */ | ||
534 | |||
535 | interpreter_mode = ACPI_IMODE_LOAD_PASS2; | ||
536 | } else { | ||
537 | /* Return a failure if name not found */ | ||
538 | |||
539 | interpreter_mode = ACPI_IMODE_EXECUTE; | ||
540 | } | ||
541 | |||
542 | status = | ||
543 | acpi_ns_lookup(walk_state->scope_info, name_string, | ||
544 | ACPI_TYPE_ANY, interpreter_mode, | ||
545 | ACPI_NS_SEARCH_PARENT | | ||
546 | ACPI_NS_DONT_OPEN_SCOPE, walk_state, | ||
547 | ACPI_CAST_INDIRECT_PTR(struct | ||
548 | acpi_namespace_node, | ||
549 | &obj_desc)); | ||
550 | /* | ||
551 | * The only case where we pass through (ignore) a NOT_FOUND | ||
552 | * error is for the cond_ref_of opcode. | ||
553 | */ | ||
554 | if (status == AE_NOT_FOUND) { | ||
555 | if (parent_op->common.aml_opcode == | ||
556 | AML_COND_REF_OF_OP) { | ||
557 | /* | ||
558 | * For the Conditional Reference op, it's OK if | ||
559 | * the name is not found; We just need a way to | ||
560 | * indicate this to the interpreter, set the | ||
561 | * object to the root | ||
562 | */ | ||
563 | obj_desc = ACPI_CAST_PTR(union | ||
564 | acpi_operand_object, | ||
565 | acpi_gbl_root_node); | ||
566 | status = AE_OK; | ||
567 | } else { | ||
568 | /* | ||
569 | * We just plain didn't find it -- which is a | ||
570 | * very serious error at this point | ||
571 | */ | ||
572 | status = AE_AML_NAME_NOT_FOUND; | ||
573 | } | ||
574 | } | ||
575 | |||
576 | if (ACPI_FAILURE(status)) { | ||
577 | ACPI_ERROR_NAMESPACE(name_string, status); | ||
578 | } | ||
579 | } | ||
580 | |||
581 | /* Free the namestring created above */ | ||
582 | |||
583 | ACPI_FREE(name_string); | ||
584 | |||
585 | /* Check status from the lookup */ | ||
586 | |||
587 | if (ACPI_FAILURE(status)) { | ||
588 | return_ACPI_STATUS(status); | ||
589 | } | ||
590 | |||
591 | /* Put the resulting object onto the current object stack */ | ||
592 | |||
593 | status = acpi_ds_obj_stack_push(obj_desc, walk_state); | ||
594 | if (ACPI_FAILURE(status)) { | ||
595 | return_ACPI_STATUS(status); | ||
596 | } | ||
597 | ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object | ||
598 | (obj_desc, walk_state)); | ||
599 | } else { | ||
600 | /* Check for null name case */ | ||
601 | |||
602 | if ((arg->common.aml_opcode == AML_INT_NAMEPATH_OP) && | ||
603 | !(arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
604 | /* | ||
605 | * If the name is null, this means that this is an | ||
606 | * optional result parameter that was not specified | ||
607 | * in the original ASL. Create a Zero Constant for a | ||
608 | * placeholder. (Store to a constant is a Noop.) | ||
609 | */ | ||
610 | opcode = AML_ZERO_OP; /* Has no arguments! */ | ||
611 | |||
612 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
613 | "Null namepath: Arg=%p\n", arg)); | ||
614 | } else { | ||
615 | opcode = arg->common.aml_opcode; | ||
616 | } | ||
617 | |||
618 | /* Get the object type of the argument */ | ||
619 | |||
620 | op_info = acpi_ps_get_opcode_info(opcode); | ||
621 | if (op_info->object_type == ACPI_TYPE_INVALID) { | ||
622 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); | ||
623 | } | ||
624 | |||
625 | if ((op_info->flags & AML_HAS_RETVAL) | ||
626 | || (arg->common.flags & ACPI_PARSEOP_IN_STACK)) { | ||
627 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
628 | "Argument previously created, already stacked\n")); | ||
629 | |||
630 | ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object | ||
631 | (walk_state-> | ||
632 | operands[walk_state->num_operands - | ||
633 | 1], walk_state)); | ||
634 | |||
635 | /* | ||
636 | * Use value that was already previously returned | ||
637 | * by the evaluation of this argument | ||
638 | */ | ||
639 | status = acpi_ds_result_pop(&obj_desc, walk_state); | ||
640 | if (ACPI_FAILURE(status)) { | ||
641 | /* | ||
642 | * Only error is underflow, and this indicates | ||
643 | * a missing or null operand! | ||
644 | */ | ||
645 | ACPI_EXCEPTION((AE_INFO, status, | ||
646 | "Missing or null operand")); | ||
647 | return_ACPI_STATUS(status); | ||
648 | } | ||
649 | } else { | ||
650 | /* Create an ACPI_INTERNAL_OBJECT for the argument */ | ||
651 | |||
652 | obj_desc = | ||
653 | acpi_ut_create_internal_object(op_info-> | ||
654 | object_type); | ||
655 | if (!obj_desc) { | ||
656 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
657 | } | ||
658 | |||
659 | /* Initialize the new object */ | ||
660 | |||
661 | status = | ||
662 | acpi_ds_init_object_from_op(walk_state, arg, opcode, | ||
663 | &obj_desc); | ||
664 | if (ACPI_FAILURE(status)) { | ||
665 | acpi_ut_delete_object_desc(obj_desc); | ||
666 | return_ACPI_STATUS(status); | ||
667 | } | ||
668 | } | ||
669 | |||
670 | /* Put the operand object on the object stack */ | ||
671 | |||
672 | status = acpi_ds_obj_stack_push(obj_desc, walk_state); | ||
673 | if (ACPI_FAILURE(status)) { | ||
674 | return_ACPI_STATUS(status); | ||
675 | } | ||
676 | |||
677 | ACPI_DEBUGGER_EXEC(acpi_db_display_argument_object | ||
678 | (obj_desc, walk_state)); | ||
679 | } | ||
680 | |||
681 | return_ACPI_STATUS(AE_OK); | ||
682 | } | ||
683 | |||
684 | /******************************************************************************* | ||
685 | * | ||
686 | * FUNCTION: acpi_ds_create_operands | ||
687 | * | ||
688 | * PARAMETERS: walk_state - Current state | ||
689 | * first_arg - First argument of a parser argument tree | ||
690 | * | ||
691 | * RETURN: Status | ||
692 | * | ||
693 | * DESCRIPTION: Convert an operator's arguments from a parse tree format to | ||
694 | * namespace objects and place those argument object on the object | ||
695 | * stack in preparation for evaluation by the interpreter. | ||
696 | * | ||
697 | ******************************************************************************/ | ||
698 | |||
699 | acpi_status | ||
700 | acpi_ds_create_operands(struct acpi_walk_state *walk_state, | ||
701 | union acpi_parse_object *first_arg) | ||
702 | { | ||
703 | acpi_status status = AE_OK; | ||
704 | union acpi_parse_object *arg; | ||
705 | union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS]; | ||
706 | u32 arg_count = 0; | ||
707 | u32 index = walk_state->num_operands; | ||
708 | u32 i; | ||
709 | |||
710 | ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg); | ||
711 | |||
712 | /* Get all arguments in the list */ | ||
713 | |||
714 | arg = first_arg; | ||
715 | while (arg) { | ||
716 | if (index >= ACPI_OBJ_NUM_OPERANDS) { | ||
717 | return_ACPI_STATUS(AE_BAD_DATA); | ||
718 | } | ||
719 | |||
720 | arguments[index] = arg; | ||
721 | walk_state->operands[index] = NULL; | ||
722 | |||
723 | /* Move on to next argument, if any */ | ||
724 | |||
725 | arg = arg->common.next; | ||
726 | arg_count++; | ||
727 | index++; | ||
728 | } | ||
729 | |||
730 | index--; | ||
731 | |||
732 | /* It is the appropriate order to get objects from the Result stack */ | ||
733 | |||
734 | for (i = 0; i < arg_count; i++) { | ||
735 | arg = arguments[index]; | ||
736 | |||
737 | /* Force the filling of the operand stack in inverse order */ | ||
738 | |||
739 | walk_state->operand_index = (u8) index; | ||
740 | |||
741 | status = acpi_ds_create_operand(walk_state, arg, index); | ||
742 | if (ACPI_FAILURE(status)) { | ||
743 | goto cleanup; | ||
744 | } | ||
745 | |||
746 | index--; | ||
747 | |||
748 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
749 | "Arg #%d (%p) done, Arg1=%p\n", index, arg, | ||
750 | first_arg)); | ||
751 | } | ||
752 | |||
753 | return_ACPI_STATUS(status); | ||
754 | |||
755 | cleanup: | ||
756 | /* | ||
757 | * We must undo everything done above; meaning that we must | ||
758 | * pop everything off of the operand stack and delete those | ||
759 | * objects | ||
760 | */ | ||
761 | acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state); | ||
762 | |||
763 | ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index)); | ||
764 | return_ACPI_STATUS(status); | ||
765 | } | ||
766 | |||
767 | /***************************************************************************** | ||
768 | * | ||
769 | * FUNCTION: acpi_ds_evaluate_name_path | ||
770 | * | ||
771 | * PARAMETERS: walk_state - Current state of the parse tree walk, | ||
772 | * the opcode of current operation should be | ||
773 | * AML_INT_NAMEPATH_OP | ||
774 | * | ||
775 | * RETURN: Status | ||
776 | * | ||
777 | * DESCRIPTION: Translate the -name_path- parse tree object to the equivalent | ||
778 | * interpreter object, convert it to value, if needed, duplicate | ||
779 | * it, if needed, and push it onto the current result stack. | ||
780 | * | ||
781 | ****************************************************************************/ | ||
782 | |||
783 | acpi_status acpi_ds_evaluate_name_path(struct acpi_walk_state *walk_state) | ||
784 | { | ||
785 | acpi_status status = AE_OK; | ||
786 | union acpi_parse_object *op = walk_state->op; | ||
787 | union acpi_operand_object **operand = &walk_state->operands[0]; | ||
788 | union acpi_operand_object *new_obj_desc; | ||
789 | u8 type; | ||
790 | |||
791 | ACPI_FUNCTION_TRACE_PTR(ds_evaluate_name_path, walk_state); | ||
792 | |||
793 | if (!op->common.parent) { | ||
794 | |||
795 | /* This happens after certain exception processing */ | ||
796 | |||
797 | goto exit; | ||
798 | } | ||
799 | |||
800 | if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) || | ||
801 | (op->common.parent->common.aml_opcode == AML_VAR_PACKAGE_OP) || | ||
802 | (op->common.parent->common.aml_opcode == AML_REF_OF_OP)) { | ||
803 | |||
804 | /* TBD: Should we specify this feature as a bit of op_info->Flags of these opcodes? */ | ||
805 | |||
806 | goto exit; | ||
807 | } | ||
808 | |||
809 | status = acpi_ds_create_operand(walk_state, op, 0); | ||
810 | if (ACPI_FAILURE(status)) { | ||
811 | goto exit; | ||
812 | } | ||
813 | |||
814 | if (op->common.flags & ACPI_PARSEOP_TARGET) { | ||
815 | new_obj_desc = *operand; | ||
816 | goto push_result; | ||
817 | } | ||
818 | |||
819 | type = ACPI_GET_OBJECT_TYPE(*operand); | ||
820 | |||
821 | status = acpi_ex_resolve_to_value(operand, walk_state); | ||
822 | if (ACPI_FAILURE(status)) { | ||
823 | goto exit; | ||
824 | } | ||
825 | |||
826 | if (type == ACPI_TYPE_INTEGER) { | ||
827 | |||
828 | /* It was incremented by acpi_ex_resolve_to_value */ | ||
829 | |||
830 | acpi_ut_remove_reference(*operand); | ||
831 | |||
832 | status = | ||
833 | acpi_ut_copy_iobject_to_iobject(*operand, &new_obj_desc, | ||
834 | walk_state); | ||
835 | if (ACPI_FAILURE(status)) { | ||
836 | goto exit; | ||
837 | } | ||
838 | } else { | ||
839 | /* | ||
840 | * The object either was anew created or is | ||
841 | * a Namespace node - don't decrement it. | ||
842 | */ | ||
843 | new_obj_desc = *operand; | ||
844 | } | ||
845 | |||
846 | /* Cleanup for name-path operand */ | ||
847 | |||
848 | status = acpi_ds_obj_stack_pop(1, walk_state); | ||
849 | if (ACPI_FAILURE(status)) { | ||
850 | walk_state->result_obj = new_obj_desc; | ||
851 | goto exit; | ||
852 | } | ||
853 | |||
854 | push_result: | ||
855 | |||
856 | walk_state->result_obj = new_obj_desc; | ||
857 | |||
858 | status = acpi_ds_result_push(walk_state->result_obj, walk_state); | ||
859 | if (ACPI_SUCCESS(status)) { | ||
860 | |||
861 | /* Force to take it from stack */ | ||
862 | |||
863 | op->common.flags |= ACPI_PARSEOP_IN_STACK; | ||
864 | } | ||
865 | |||
866 | exit: | ||
867 | |||
868 | return_ACPI_STATUS(status); | ||
869 | } | ||
diff --git a/drivers/acpi/dispatcher/dswexec.c b/drivers/acpi/dispatcher/dswexec.c deleted file mode 100644 index 2482cbd37f25..000000000000 --- a/drivers/acpi/dispatcher/dswexec.c +++ /dev/null | |||
@@ -1,746 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dswexec - Dispatcher method execution callbacks; | ||
4 | * dispatch to interpreter. | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2008, Intel Corp. | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include <acpi/accommon.h> | ||
47 | #include <acpi/acparser.h> | ||
48 | #include <acpi/amlcode.h> | ||
49 | #include <acpi/acdispat.h> | ||
50 | #include <acpi/acinterp.h> | ||
51 | #include <acpi/acnamesp.h> | ||
52 | #include <acpi/acdebug.h> | ||
53 | |||
54 | #define _COMPONENT ACPI_DISPATCHER | ||
55 | ACPI_MODULE_NAME("dswexec") | ||
56 | |||
57 | /* | ||
58 | * Dispatch table for opcode classes | ||
59 | */ | ||
60 | static ACPI_EXECUTE_OP acpi_gbl_op_type_dispatch[] = { | ||
61 | acpi_ex_opcode_0A_0T_1R, | ||
62 | acpi_ex_opcode_1A_0T_0R, | ||
63 | acpi_ex_opcode_1A_0T_1R, | ||
64 | acpi_ex_opcode_1A_1T_0R, | ||
65 | acpi_ex_opcode_1A_1T_1R, | ||
66 | acpi_ex_opcode_2A_0T_0R, | ||
67 | acpi_ex_opcode_2A_0T_1R, | ||
68 | acpi_ex_opcode_2A_1T_1R, | ||
69 | acpi_ex_opcode_2A_2T_1R, | ||
70 | acpi_ex_opcode_3A_0T_0R, | ||
71 | acpi_ex_opcode_3A_1T_1R, | ||
72 | acpi_ex_opcode_6A_0T_1R | ||
73 | }; | ||
74 | |||
75 | /***************************************************************************** | ||
76 | * | ||
77 | * FUNCTION: acpi_ds_get_predicate_value | ||
78 | * | ||
79 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
80 | * result_obj - if non-zero, pop result from result stack | ||
81 | * | ||
82 | * RETURN: Status | ||
83 | * | ||
84 | * DESCRIPTION: Get the result of a predicate evaluation | ||
85 | * | ||
86 | ****************************************************************************/ | ||
87 | |||
88 | acpi_status | ||
89 | acpi_ds_get_predicate_value(struct acpi_walk_state *walk_state, | ||
90 | union acpi_operand_object *result_obj) | ||
91 | { | ||
92 | acpi_status status = AE_OK; | ||
93 | union acpi_operand_object *obj_desc; | ||
94 | union acpi_operand_object *local_obj_desc = NULL; | ||
95 | |||
96 | ACPI_FUNCTION_TRACE_PTR(ds_get_predicate_value, walk_state); | ||
97 | |||
98 | walk_state->control_state->common.state = 0; | ||
99 | |||
100 | if (result_obj) { | ||
101 | status = acpi_ds_result_pop(&obj_desc, walk_state); | ||
102 | if (ACPI_FAILURE(status)) { | ||
103 | ACPI_EXCEPTION((AE_INFO, status, | ||
104 | "Could not get result from predicate evaluation")); | ||
105 | |||
106 | return_ACPI_STATUS(status); | ||
107 | } | ||
108 | } else { | ||
109 | status = acpi_ds_create_operand(walk_state, walk_state->op, 0); | ||
110 | if (ACPI_FAILURE(status)) { | ||
111 | return_ACPI_STATUS(status); | ||
112 | } | ||
113 | |||
114 | status = | ||
115 | acpi_ex_resolve_to_value(&walk_state->operands[0], | ||
116 | walk_state); | ||
117 | if (ACPI_FAILURE(status)) { | ||
118 | return_ACPI_STATUS(status); | ||
119 | } | ||
120 | |||
121 | obj_desc = walk_state->operands[0]; | ||
122 | } | ||
123 | |||
124 | if (!obj_desc) { | ||
125 | ACPI_ERROR((AE_INFO, | ||
126 | "No predicate ObjDesc=%p State=%p", | ||
127 | obj_desc, walk_state)); | ||
128 | |||
129 | return_ACPI_STATUS(AE_AML_NO_OPERAND); | ||
130 | } | ||
131 | |||
132 | /* | ||
133 | * Result of predicate evaluation must be an Integer | ||
134 | * object. Implicitly convert the argument if necessary. | ||
135 | */ | ||
136 | status = acpi_ex_convert_to_integer(obj_desc, &local_obj_desc, 16); | ||
137 | if (ACPI_FAILURE(status)) { | ||
138 | goto cleanup; | ||
139 | } | ||
140 | |||
141 | if (ACPI_GET_OBJECT_TYPE(local_obj_desc) != ACPI_TYPE_INTEGER) { | ||
142 | ACPI_ERROR((AE_INFO, | ||
143 | "Bad predicate (not an integer) ObjDesc=%p State=%p Type=%X", | ||
144 | obj_desc, walk_state, | ||
145 | ACPI_GET_OBJECT_TYPE(obj_desc))); | ||
146 | |||
147 | status = AE_AML_OPERAND_TYPE; | ||
148 | goto cleanup; | ||
149 | } | ||
150 | |||
151 | /* Truncate the predicate to 32-bits if necessary */ | ||
152 | |||
153 | acpi_ex_truncate_for32bit_table(local_obj_desc); | ||
154 | |||
155 | /* | ||
156 | * Save the result of the predicate evaluation on | ||
157 | * the control stack | ||
158 | */ | ||
159 | if (local_obj_desc->integer.value) { | ||
160 | walk_state->control_state->common.value = TRUE; | ||
161 | } else { | ||
162 | /* | ||
163 | * Predicate is FALSE, we will just toss the | ||
164 | * rest of the package | ||
165 | */ | ||
166 | walk_state->control_state->common.value = FALSE; | ||
167 | status = AE_CTRL_FALSE; | ||
168 | } | ||
169 | |||
170 | /* Predicate can be used for an implicit return value */ | ||
171 | |||
172 | (void)acpi_ds_do_implicit_return(local_obj_desc, walk_state, TRUE); | ||
173 | |||
174 | cleanup: | ||
175 | |||
176 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Completed a predicate eval=%X Op=%p\n", | ||
177 | walk_state->control_state->common.value, | ||
178 | walk_state->op)); | ||
179 | |||
180 | /* Break to debugger to display result */ | ||
181 | |||
182 | ACPI_DEBUGGER_EXEC(acpi_db_display_result_object | ||
183 | (local_obj_desc, walk_state)); | ||
184 | |||
185 | /* | ||
186 | * Delete the predicate result object (we know that | ||
187 | * we don't need it anymore) | ||
188 | */ | ||
189 | if (local_obj_desc != obj_desc) { | ||
190 | acpi_ut_remove_reference(local_obj_desc); | ||
191 | } | ||
192 | acpi_ut_remove_reference(obj_desc); | ||
193 | |||
194 | walk_state->control_state->common.state = ACPI_CONTROL_NORMAL; | ||
195 | return_ACPI_STATUS(status); | ||
196 | } | ||
197 | |||
198 | /***************************************************************************** | ||
199 | * | ||
200 | * FUNCTION: acpi_ds_exec_begin_op | ||
201 | * | ||
202 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
203 | * out_op - Where to return op if a new one is created | ||
204 | * | ||
205 | * RETURN: Status | ||
206 | * | ||
207 | * DESCRIPTION: Descending callback used during the execution of control | ||
208 | * methods. This is where most operators and operands are | ||
209 | * dispatched to the interpreter. | ||
210 | * | ||
211 | ****************************************************************************/ | ||
212 | |||
213 | acpi_status | ||
214 | acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state, | ||
215 | union acpi_parse_object **out_op) | ||
216 | { | ||
217 | union acpi_parse_object *op; | ||
218 | acpi_status status = AE_OK; | ||
219 | u32 opcode_class; | ||
220 | |||
221 | ACPI_FUNCTION_TRACE_PTR(ds_exec_begin_op, walk_state); | ||
222 | |||
223 | op = walk_state->op; | ||
224 | if (!op) { | ||
225 | status = acpi_ds_load2_begin_op(walk_state, out_op); | ||
226 | if (ACPI_FAILURE(status)) { | ||
227 | goto error_exit; | ||
228 | } | ||
229 | |||
230 | op = *out_op; | ||
231 | walk_state->op = op; | ||
232 | walk_state->opcode = op->common.aml_opcode; | ||
233 | walk_state->op_info = | ||
234 | acpi_ps_get_opcode_info(op->common.aml_opcode); | ||
235 | |||
236 | if (acpi_ns_opens_scope(walk_state->op_info->object_type)) { | ||
237 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
238 | "(%s) Popping scope for Op %p\n", | ||
239 | acpi_ut_get_type_name(walk_state-> | ||
240 | op_info-> | ||
241 | object_type), | ||
242 | op)); | ||
243 | |||
244 | status = acpi_ds_scope_stack_pop(walk_state); | ||
245 | if (ACPI_FAILURE(status)) { | ||
246 | goto error_exit; | ||
247 | } | ||
248 | } | ||
249 | } | ||
250 | |||
251 | if (op == walk_state->origin) { | ||
252 | if (out_op) { | ||
253 | *out_op = op; | ||
254 | } | ||
255 | |||
256 | return_ACPI_STATUS(AE_OK); | ||
257 | } | ||
258 | |||
259 | /* | ||
260 | * If the previous opcode was a conditional, this opcode | ||
261 | * must be the beginning of the associated predicate. | ||
262 | * Save this knowledge in the current scope descriptor | ||
263 | */ | ||
264 | if ((walk_state->control_state) && | ||
265 | (walk_state->control_state->common.state == | ||
266 | ACPI_CONTROL_CONDITIONAL_EXECUTING)) { | ||
267 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
268 | "Exec predicate Op=%p State=%p\n", op, | ||
269 | walk_state)); | ||
270 | |||
271 | walk_state->control_state->common.state = | ||
272 | ACPI_CONTROL_PREDICATE_EXECUTING; | ||
273 | |||
274 | /* Save start of predicate */ | ||
275 | |||
276 | walk_state->control_state->control.predicate_op = op; | ||
277 | } | ||
278 | |||
279 | opcode_class = walk_state->op_info->class; | ||
280 | |||
281 | /* We want to send namepaths to the load code */ | ||
282 | |||
283 | if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { | ||
284 | opcode_class = AML_CLASS_NAMED_OBJECT; | ||
285 | } | ||
286 | |||
287 | /* | ||
288 | * Handle the opcode based upon the opcode type | ||
289 | */ | ||
290 | switch (opcode_class) { | ||
291 | case AML_CLASS_CONTROL: | ||
292 | |||
293 | status = acpi_ds_exec_begin_control_op(walk_state, op); | ||
294 | break; | ||
295 | |||
296 | case AML_CLASS_NAMED_OBJECT: | ||
297 | |||
298 | if (walk_state->walk_type & ACPI_WALK_METHOD) { | ||
299 | /* | ||
300 | * Found a named object declaration during method execution; | ||
301 | * we must enter this object into the namespace. The created | ||
302 | * object is temporary and will be deleted upon completion of | ||
303 | * the execution of this method. | ||
304 | */ | ||
305 | status = acpi_ds_load2_begin_op(walk_state, NULL); | ||
306 | } | ||
307 | |||
308 | break; | ||
309 | |||
310 | case AML_CLASS_EXECUTE: | ||
311 | case AML_CLASS_CREATE: | ||
312 | |||
313 | break; | ||
314 | |||
315 | default: | ||
316 | break; | ||
317 | } | ||
318 | |||
319 | /* Nothing to do here during method execution */ | ||
320 | |||
321 | return_ACPI_STATUS(status); | ||
322 | |||
323 | error_exit: | ||
324 | status = acpi_ds_method_error(status, walk_state); | ||
325 | return_ACPI_STATUS(status); | ||
326 | } | ||
327 | |||
328 | /***************************************************************************** | ||
329 | * | ||
330 | * FUNCTION: acpi_ds_exec_end_op | ||
331 | * | ||
332 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
333 | * | ||
334 | * RETURN: Status | ||
335 | * | ||
336 | * DESCRIPTION: Ascending callback used during the execution of control | ||
337 | * methods. The only thing we really need to do here is to | ||
338 | * notice the beginning of IF, ELSE, and WHILE blocks. | ||
339 | * | ||
340 | ****************************************************************************/ | ||
341 | |||
342 | acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state) | ||
343 | { | ||
344 | union acpi_parse_object *op; | ||
345 | acpi_status status = AE_OK; | ||
346 | u32 op_type; | ||
347 | u32 op_class; | ||
348 | union acpi_parse_object *next_op; | ||
349 | union acpi_parse_object *first_arg; | ||
350 | |||
351 | ACPI_FUNCTION_TRACE_PTR(ds_exec_end_op, walk_state); | ||
352 | |||
353 | op = walk_state->op; | ||
354 | op_type = walk_state->op_info->type; | ||
355 | op_class = walk_state->op_info->class; | ||
356 | |||
357 | if (op_class == AML_CLASS_UNKNOWN) { | ||
358 | ACPI_ERROR((AE_INFO, "Unknown opcode %X", | ||
359 | op->common.aml_opcode)); | ||
360 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); | ||
361 | } | ||
362 | |||
363 | first_arg = op->common.value.arg; | ||
364 | |||
365 | /* Init the walk state */ | ||
366 | |||
367 | walk_state->num_operands = 0; | ||
368 | walk_state->operand_index = 0; | ||
369 | walk_state->return_desc = NULL; | ||
370 | walk_state->result_obj = NULL; | ||
371 | |||
372 | /* Call debugger for single step support (DEBUG build only) */ | ||
373 | |||
374 | ACPI_DEBUGGER_EXEC(status = | ||
375 | acpi_db_single_step(walk_state, op, op_class)); | ||
376 | ACPI_DEBUGGER_EXEC(if (ACPI_FAILURE(status)) { | ||
377 | return_ACPI_STATUS(status);} | ||
378 | ) ; | ||
379 | |||
380 | /* Decode the Opcode Class */ | ||
381 | |||
382 | switch (op_class) { | ||
383 | case AML_CLASS_ARGUMENT: /* Constants, literals, etc. */ | ||
384 | |||
385 | if (walk_state->opcode == AML_INT_NAMEPATH_OP) { | ||
386 | status = acpi_ds_evaluate_name_path(walk_state); | ||
387 | if (ACPI_FAILURE(status)) { | ||
388 | goto cleanup; | ||
389 | } | ||
390 | } | ||
391 | break; | ||
392 | |||
393 | case AML_CLASS_EXECUTE: /* Most operators with arguments */ | ||
394 | |||
395 | /* Build resolved operand stack */ | ||
396 | |||
397 | status = acpi_ds_create_operands(walk_state, first_arg); | ||
398 | if (ACPI_FAILURE(status)) { | ||
399 | goto cleanup; | ||
400 | } | ||
401 | |||
402 | /* | ||
403 | * All opcodes require operand resolution, with the only exceptions | ||
404 | * being the object_type and size_of operators. | ||
405 | */ | ||
406 | if (!(walk_state->op_info->flags & AML_NO_OPERAND_RESOLVE)) { | ||
407 | |||
408 | /* Resolve all operands */ | ||
409 | |||
410 | status = acpi_ex_resolve_operands(walk_state->opcode, | ||
411 | &(walk_state-> | ||
412 | operands | ||
413 | [walk_state-> | ||
414 | num_operands - 1]), | ||
415 | walk_state); | ||
416 | } | ||
417 | |||
418 | if (ACPI_SUCCESS(status)) { | ||
419 | /* | ||
420 | * Dispatch the request to the appropriate interpreter handler | ||
421 | * routine. There is one routine per opcode "type" based upon the | ||
422 | * number of opcode arguments and return type. | ||
423 | */ | ||
424 | status = | ||
425 | acpi_gbl_op_type_dispatch[op_type] (walk_state); | ||
426 | } else { | ||
427 | /* | ||
428 | * Treat constructs of the form "Store(LocalX,LocalX)" as noops when the | ||
429 | * Local is uninitialized. | ||
430 | */ | ||
431 | if ((status == AE_AML_UNINITIALIZED_LOCAL) && | ||
432 | (walk_state->opcode == AML_STORE_OP) && | ||
433 | (walk_state->operands[0]->common.type == | ||
434 | ACPI_TYPE_LOCAL_REFERENCE) | ||
435 | && (walk_state->operands[1]->common.type == | ||
436 | ACPI_TYPE_LOCAL_REFERENCE) | ||
437 | && (walk_state->operands[0]->reference.class == | ||
438 | walk_state->operands[1]->reference.class) | ||
439 | && (walk_state->operands[0]->reference.value == | ||
440 | walk_state->operands[1]->reference.value)) { | ||
441 | status = AE_OK; | ||
442 | } else { | ||
443 | ACPI_EXCEPTION((AE_INFO, status, | ||
444 | "While resolving operands for [%s]", | ||
445 | acpi_ps_get_opcode_name | ||
446 | (walk_state->opcode))); | ||
447 | } | ||
448 | } | ||
449 | |||
450 | /* Always delete the argument objects and clear the operand stack */ | ||
451 | |||
452 | acpi_ds_clear_operands(walk_state); | ||
453 | |||
454 | /* | ||
455 | * If a result object was returned from above, push it on the | ||
456 | * current result stack | ||
457 | */ | ||
458 | if (ACPI_SUCCESS(status) && walk_state->result_obj) { | ||
459 | status = | ||
460 | acpi_ds_result_push(walk_state->result_obj, | ||
461 | walk_state); | ||
462 | } | ||
463 | break; | ||
464 | |||
465 | default: | ||
466 | |||
467 | switch (op_type) { | ||
468 | case AML_TYPE_CONTROL: /* Type 1 opcode, IF/ELSE/WHILE/NOOP */ | ||
469 | |||
470 | /* 1 Operand, 0 external_result, 0 internal_result */ | ||
471 | |||
472 | status = acpi_ds_exec_end_control_op(walk_state, op); | ||
473 | |||
474 | break; | ||
475 | |||
476 | case AML_TYPE_METHOD_CALL: | ||
477 | |||
478 | /* | ||
479 | * If the method is referenced from within a package | ||
480 | * declaration, it is not a invocation of the method, just | ||
481 | * a reference to it. | ||
482 | */ | ||
483 | if ((op->asl.parent) && | ||
484 | ((op->asl.parent->asl.aml_opcode == AML_PACKAGE_OP) | ||
485 | || (op->asl.parent->asl.aml_opcode == | ||
486 | AML_VAR_PACKAGE_OP))) { | ||
487 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
488 | "Method Reference in a Package, Op=%p\n", | ||
489 | op)); | ||
490 | |||
491 | op->common.node = | ||
492 | (struct acpi_namespace_node *)op->asl.value. | ||
493 | arg->asl.node; | ||
494 | acpi_ut_add_reference(op->asl.value.arg->asl. | ||
495 | node->object); | ||
496 | return_ACPI_STATUS(AE_OK); | ||
497 | } | ||
498 | |||
499 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
500 | "Method invocation, Op=%p\n", op)); | ||
501 | |||
502 | /* | ||
503 | * (AML_METHODCALL) Op->Asl.Value.Arg->Asl.Node contains | ||
504 | * the method Node pointer | ||
505 | */ | ||
506 | /* next_op points to the op that holds the method name */ | ||
507 | |||
508 | next_op = first_arg; | ||
509 | |||
510 | /* next_op points to first argument op */ | ||
511 | |||
512 | next_op = next_op->common.next; | ||
513 | |||
514 | /* | ||
515 | * Get the method's arguments and put them on the operand stack | ||
516 | */ | ||
517 | status = acpi_ds_create_operands(walk_state, next_op); | ||
518 | if (ACPI_FAILURE(status)) { | ||
519 | break; | ||
520 | } | ||
521 | |||
522 | /* | ||
523 | * Since the operands will be passed to another control method, | ||
524 | * we must resolve all local references here (Local variables, | ||
525 | * arguments to *this* method, etc.) | ||
526 | */ | ||
527 | status = acpi_ds_resolve_operands(walk_state); | ||
528 | if (ACPI_FAILURE(status)) { | ||
529 | |||
530 | /* On error, clear all resolved operands */ | ||
531 | |||
532 | acpi_ds_clear_operands(walk_state); | ||
533 | break; | ||
534 | } | ||
535 | |||
536 | /* | ||
537 | * Tell the walk loop to preempt this running method and | ||
538 | * execute the new method | ||
539 | */ | ||
540 | status = AE_CTRL_TRANSFER; | ||
541 | |||
542 | /* | ||
543 | * Return now; we don't want to disturb anything, | ||
544 | * especially the operand count! | ||
545 | */ | ||
546 | return_ACPI_STATUS(status); | ||
547 | |||
548 | case AML_TYPE_CREATE_FIELD: | ||
549 | |||
550 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
551 | "Executing CreateField Buffer/Index Op=%p\n", | ||
552 | op)); | ||
553 | |||
554 | status = acpi_ds_load2_end_op(walk_state); | ||
555 | if (ACPI_FAILURE(status)) { | ||
556 | break; | ||
557 | } | ||
558 | |||
559 | status = | ||
560 | acpi_ds_eval_buffer_field_operands(walk_state, op); | ||
561 | break; | ||
562 | |||
563 | case AML_TYPE_CREATE_OBJECT: | ||
564 | |||
565 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
566 | "Executing CreateObject (Buffer/Package) Op=%p\n", | ||
567 | op)); | ||
568 | |||
569 | switch (op->common.parent->common.aml_opcode) { | ||
570 | case AML_NAME_OP: | ||
571 | |||
572 | /* | ||
573 | * Put the Node on the object stack (Contains the ACPI Name | ||
574 | * of this object) | ||
575 | */ | ||
576 | walk_state->operands[0] = | ||
577 | (void *)op->common.parent->common.node; | ||
578 | walk_state->num_operands = 1; | ||
579 | |||
580 | status = acpi_ds_create_node(walk_state, | ||
581 | op->common.parent-> | ||
582 | common.node, | ||
583 | op->common.parent); | ||
584 | if (ACPI_FAILURE(status)) { | ||
585 | break; | ||
586 | } | ||
587 | |||
588 | /* Fall through */ | ||
589 | /*lint -fallthrough */ | ||
590 | |||
591 | case AML_INT_EVAL_SUBTREE_OP: | ||
592 | |||
593 | status = | ||
594 | acpi_ds_eval_data_object_operands | ||
595 | (walk_state, op, | ||
596 | acpi_ns_get_attached_object(op->common. | ||
597 | parent->common. | ||
598 | node)); | ||
599 | break; | ||
600 | |||
601 | default: | ||
602 | |||
603 | status = | ||
604 | acpi_ds_eval_data_object_operands | ||
605 | (walk_state, op, NULL); | ||
606 | break; | ||
607 | } | ||
608 | |||
609 | /* | ||
610 | * If a result object was returned from above, push it on the | ||
611 | * current result stack | ||
612 | */ | ||
613 | if (walk_state->result_obj) { | ||
614 | status = | ||
615 | acpi_ds_result_push(walk_state->result_obj, | ||
616 | walk_state); | ||
617 | } | ||
618 | break; | ||
619 | |||
620 | case AML_TYPE_NAMED_FIELD: | ||
621 | case AML_TYPE_NAMED_COMPLEX: | ||
622 | case AML_TYPE_NAMED_SIMPLE: | ||
623 | case AML_TYPE_NAMED_NO_OBJ: | ||
624 | |||
625 | status = acpi_ds_load2_end_op(walk_state); | ||
626 | if (ACPI_FAILURE(status)) { | ||
627 | break; | ||
628 | } | ||
629 | |||
630 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
631 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
632 | "Executing OpRegion Address/Length Op=%p\n", | ||
633 | op)); | ||
634 | |||
635 | status = | ||
636 | acpi_ds_eval_region_operands(walk_state, | ||
637 | op); | ||
638 | if (ACPI_FAILURE(status)) { | ||
639 | break; | ||
640 | } | ||
641 | } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { | ||
642 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
643 | "Executing DataTableRegion Strings Op=%p\n", | ||
644 | op)); | ||
645 | |||
646 | status = | ||
647 | acpi_ds_eval_table_region_operands | ||
648 | (walk_state, op); | ||
649 | if (ACPI_FAILURE(status)) { | ||
650 | break; | ||
651 | } | ||
652 | } else if (op->common.aml_opcode == AML_BANK_FIELD_OP) { | ||
653 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
654 | "Executing BankField Op=%p\n", | ||
655 | op)); | ||
656 | |||
657 | status = | ||
658 | acpi_ds_eval_bank_field_operands(walk_state, | ||
659 | op); | ||
660 | if (ACPI_FAILURE(status)) { | ||
661 | break; | ||
662 | } | ||
663 | } | ||
664 | break; | ||
665 | |||
666 | case AML_TYPE_UNDEFINED: | ||
667 | |||
668 | ACPI_ERROR((AE_INFO, | ||
669 | "Undefined opcode type Op=%p", op)); | ||
670 | return_ACPI_STATUS(AE_NOT_IMPLEMENTED); | ||
671 | |||
672 | case AML_TYPE_BOGUS: | ||
673 | |||
674 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
675 | "Internal opcode=%X type Op=%p\n", | ||
676 | walk_state->opcode, op)); | ||
677 | break; | ||
678 | |||
679 | default: | ||
680 | |||
681 | ACPI_ERROR((AE_INFO, | ||
682 | "Unimplemented opcode, class=%X type=%X Opcode=%X Op=%p", | ||
683 | op_class, op_type, op->common.aml_opcode, | ||
684 | op)); | ||
685 | |||
686 | status = AE_NOT_IMPLEMENTED; | ||
687 | break; | ||
688 | } | ||
689 | } | ||
690 | |||
691 | /* | ||
692 | * ACPI 2.0 support for 64-bit integers: Truncate numeric | ||
693 | * result value if we are executing from a 32-bit ACPI table | ||
694 | */ | ||
695 | acpi_ex_truncate_for32bit_table(walk_state->result_obj); | ||
696 | |||
697 | /* | ||
698 | * Check if we just completed the evaluation of a | ||
699 | * conditional predicate | ||
700 | */ | ||
701 | if ((ACPI_SUCCESS(status)) && | ||
702 | (walk_state->control_state) && | ||
703 | (walk_state->control_state->common.state == | ||
704 | ACPI_CONTROL_PREDICATE_EXECUTING) && | ||
705 | (walk_state->control_state->control.predicate_op == op)) { | ||
706 | status = | ||
707 | acpi_ds_get_predicate_value(walk_state, | ||
708 | walk_state->result_obj); | ||
709 | walk_state->result_obj = NULL; | ||
710 | } | ||
711 | |||
712 | cleanup: | ||
713 | |||
714 | if (walk_state->result_obj) { | ||
715 | |||
716 | /* Break to debugger to display result */ | ||
717 | |||
718 | ACPI_DEBUGGER_EXEC(acpi_db_display_result_object | ||
719 | (walk_state->result_obj, walk_state)); | ||
720 | |||
721 | /* | ||
722 | * Delete the result op if and only if: | ||
723 | * Parent will not use the result -- such as any | ||
724 | * non-nested type2 op in a method (parent will be method) | ||
725 | */ | ||
726 | acpi_ds_delete_result_if_not_used(op, walk_state->result_obj, | ||
727 | walk_state); | ||
728 | } | ||
729 | #ifdef _UNDER_DEVELOPMENT | ||
730 | |||
731 | if (walk_state->parser_state.aml == walk_state->parser_state.aml_end) { | ||
732 | acpi_db_method_end(walk_state); | ||
733 | } | ||
734 | #endif | ||
735 | |||
736 | /* Invoke exception handler on error */ | ||
737 | |||
738 | if (ACPI_FAILURE(status)) { | ||
739 | status = acpi_ds_method_error(status, walk_state); | ||
740 | } | ||
741 | |||
742 | /* Always clear the object stack */ | ||
743 | |||
744 | walk_state->num_operands = 0; | ||
745 | return_ACPI_STATUS(status); | ||
746 | } | ||
diff --git a/drivers/acpi/dispatcher/dswload.c b/drivers/acpi/dispatcher/dswload.c deleted file mode 100644 index 2d71ceda3d56..000000000000 --- a/drivers/acpi/dispatcher/dswload.c +++ /dev/null | |||
@@ -1,1203 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dswload - Dispatcher namespace load callbacks | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/acparser.h> | ||
47 | #include <acpi/amlcode.h> | ||
48 | #include <acpi/acdispat.h> | ||
49 | #include <acpi/acinterp.h> | ||
50 | #include <acpi/acnamesp.h> | ||
51 | #include <acpi/acevents.h> | ||
52 | |||
53 | #ifdef ACPI_ASL_COMPILER | ||
54 | #include <acpi/acdisasm.h> | ||
55 | #endif | ||
56 | |||
57 | #define _COMPONENT ACPI_DISPATCHER | ||
58 | ACPI_MODULE_NAME("dswload") | ||
59 | |||
60 | /******************************************************************************* | ||
61 | * | ||
62 | * FUNCTION: acpi_ds_init_callbacks | ||
63 | * | ||
64 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
65 | * pass_number - 1, 2, or 3 | ||
66 | * | ||
67 | * RETURN: Status | ||
68 | * | ||
69 | * DESCRIPTION: Init walk state callbacks | ||
70 | * | ||
71 | ******************************************************************************/ | ||
72 | acpi_status | ||
73 | acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number) | ||
74 | { | ||
75 | |||
76 | switch (pass_number) { | ||
77 | case 1: | ||
78 | walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | | ||
79 | ACPI_PARSE_DELETE_TREE; | ||
80 | walk_state->descending_callback = acpi_ds_load1_begin_op; | ||
81 | walk_state->ascending_callback = acpi_ds_load1_end_op; | ||
82 | break; | ||
83 | |||
84 | case 2: | ||
85 | walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 | | ||
86 | ACPI_PARSE_DELETE_TREE; | ||
87 | walk_state->descending_callback = acpi_ds_load2_begin_op; | ||
88 | walk_state->ascending_callback = acpi_ds_load2_end_op; | ||
89 | break; | ||
90 | |||
91 | case 3: | ||
92 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
93 | walk_state->parse_flags |= ACPI_PARSE_EXECUTE | | ||
94 | ACPI_PARSE_DELETE_TREE; | ||
95 | walk_state->descending_callback = acpi_ds_exec_begin_op; | ||
96 | walk_state->ascending_callback = acpi_ds_exec_end_op; | ||
97 | #endif | ||
98 | break; | ||
99 | |||
100 | default: | ||
101 | return (AE_BAD_PARAMETER); | ||
102 | } | ||
103 | |||
104 | return (AE_OK); | ||
105 | } | ||
106 | |||
107 | /******************************************************************************* | ||
108 | * | ||
109 | * FUNCTION: acpi_ds_load1_begin_op | ||
110 | * | ||
111 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
112 | * out_op - Where to return op if a new one is created | ||
113 | * | ||
114 | * RETURN: Status | ||
115 | * | ||
116 | * DESCRIPTION: Descending callback used during the loading of ACPI tables. | ||
117 | * | ||
118 | ******************************************************************************/ | ||
119 | |||
120 | acpi_status | ||
121 | acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state, | ||
122 | union acpi_parse_object ** out_op) | ||
123 | { | ||
124 | union acpi_parse_object *op; | ||
125 | struct acpi_namespace_node *node; | ||
126 | acpi_status status; | ||
127 | acpi_object_type object_type; | ||
128 | char *path; | ||
129 | u32 flags; | ||
130 | |||
131 | ACPI_FUNCTION_TRACE(ds_load1_begin_op); | ||
132 | |||
133 | op = walk_state->op; | ||
134 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, | ||
135 | walk_state)); | ||
136 | |||
137 | /* We are only interested in opcodes that have an associated name */ | ||
138 | |||
139 | if (op) { | ||
140 | if (!(walk_state->op_info->flags & AML_NAMED)) { | ||
141 | *out_op = op; | ||
142 | return_ACPI_STATUS(AE_OK); | ||
143 | } | ||
144 | |||
145 | /* Check if this object has already been installed in the namespace */ | ||
146 | |||
147 | if (op->common.node) { | ||
148 | *out_op = op; | ||
149 | return_ACPI_STATUS(AE_OK); | ||
150 | } | ||
151 | } | ||
152 | |||
153 | path = acpi_ps_get_next_namestring(&walk_state->parser_state); | ||
154 | |||
155 | /* Map the raw opcode into an internal object type */ | ||
156 | |||
157 | object_type = walk_state->op_info->object_type; | ||
158 | |||
159 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
160 | "State=%p Op=%p [%s]\n", walk_state, op, | ||
161 | acpi_ut_get_type_name(object_type))); | ||
162 | |||
163 | switch (walk_state->opcode) { | ||
164 | case AML_SCOPE_OP: | ||
165 | |||
166 | /* | ||
167 | * The target name of the Scope() operator must exist at this point so | ||
168 | * that we can actually open the scope to enter new names underneath it. | ||
169 | * Allow search-to-root for single namesegs. | ||
170 | */ | ||
171 | status = | ||
172 | acpi_ns_lookup(walk_state->scope_info, path, object_type, | ||
173 | ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT, | ||
174 | walk_state, &(node)); | ||
175 | #ifdef ACPI_ASL_COMPILER | ||
176 | if (status == AE_NOT_FOUND) { | ||
177 | /* | ||
178 | * Table disassembly: | ||
179 | * Target of Scope() not found. Generate an External for it, and | ||
180 | * insert the name into the namespace. | ||
181 | */ | ||
182 | acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0); | ||
183 | status = | ||
184 | acpi_ns_lookup(walk_state->scope_info, path, | ||
185 | object_type, ACPI_IMODE_LOAD_PASS1, | ||
186 | ACPI_NS_SEARCH_PARENT, walk_state, | ||
187 | &node); | ||
188 | } | ||
189 | #endif | ||
190 | if (ACPI_FAILURE(status)) { | ||
191 | ACPI_ERROR_NAMESPACE(path, status); | ||
192 | return_ACPI_STATUS(status); | ||
193 | } | ||
194 | |||
195 | /* | ||
196 | * Check to make sure that the target is | ||
197 | * one of the opcodes that actually opens a scope | ||
198 | */ | ||
199 | switch (node->type) { | ||
200 | case ACPI_TYPE_ANY: | ||
201 | case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ | ||
202 | case ACPI_TYPE_DEVICE: | ||
203 | case ACPI_TYPE_POWER: | ||
204 | case ACPI_TYPE_PROCESSOR: | ||
205 | case ACPI_TYPE_THERMAL: | ||
206 | |||
207 | /* These are acceptable types */ | ||
208 | break; | ||
209 | |||
210 | case ACPI_TYPE_INTEGER: | ||
211 | case ACPI_TYPE_STRING: | ||
212 | case ACPI_TYPE_BUFFER: | ||
213 | |||
214 | /* | ||
215 | * These types we will allow, but we will change the type. This | ||
216 | * enables some existing code of the form: | ||
217 | * | ||
218 | * Name (DEB, 0) | ||
219 | * Scope (DEB) { ... } | ||
220 | * | ||
221 | * Note: silently change the type here. On the second pass, we will report | ||
222 | * a warning | ||
223 | */ | ||
224 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | ||
225 | "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)\n", | ||
226 | path, | ||
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 Scope operator [%4.4s] (Cannot override)", | ||
239 | acpi_ut_get_type_name(node->type), path)); | ||
240 | |||
241 | return_ACPI_STATUS(AE_AML_OPERAND_TYPE); | ||
242 | } | ||
243 | break; | ||
244 | |||
245 | default: | ||
246 | /* | ||
247 | * For all other named opcodes, we will enter the name into | ||
248 | * the namespace. | ||
249 | * | ||
250 | * Setup the search flags. | ||
251 | * Since we are entering a name into the namespace, we do not want to | ||
252 | * enable the search-to-root upsearch. | ||
253 | * | ||
254 | * There are only two conditions where it is acceptable that the name | ||
255 | * already exists: | ||
256 | * 1) the Scope() operator can reopen a scoping object that was | ||
257 | * previously defined (Scope, Method, Device, etc.) | ||
258 | * 2) Whenever we are parsing a deferred opcode (op_region, Buffer, | ||
259 | * buffer_field, or Package), the name of the object is already | ||
260 | * in the namespace. | ||
261 | */ | ||
262 | if (walk_state->deferred_node) { | ||
263 | |||
264 | /* This name is already in the namespace, get the node */ | ||
265 | |||
266 | node = walk_state->deferred_node; | ||
267 | status = AE_OK; | ||
268 | break; | ||
269 | } | ||
270 | |||
271 | /* | ||
272 | * If we are executing a method, do not create any namespace objects | ||
273 | * during the load phase, only during execution. | ||
274 | */ | ||
275 | if (walk_state->method_node) { | ||
276 | node = NULL; | ||
277 | status = AE_OK; | ||
278 | break; | ||
279 | } | ||
280 | |||
281 | flags = ACPI_NS_NO_UPSEARCH; | ||
282 | if ((walk_state->opcode != AML_SCOPE_OP) && | ||
283 | (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) { | ||
284 | flags |= ACPI_NS_ERROR_IF_FOUND; | ||
285 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
286 | "[%s] Cannot already exist\n", | ||
287 | acpi_ut_get_type_name(object_type))); | ||
288 | } else { | ||
289 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
290 | "[%s] Both Find or Create allowed\n", | ||
291 | acpi_ut_get_type_name(object_type))); | ||
292 | } | ||
293 | |||
294 | /* | ||
295 | * Enter the named type into the internal namespace. We enter the name | ||
296 | * as we go downward in the parse tree. Any necessary subobjects that | ||
297 | * involve arguments to the opcode must be created as we go back up the | ||
298 | * parse tree later. | ||
299 | */ | ||
300 | status = | ||
301 | acpi_ns_lookup(walk_state->scope_info, path, object_type, | ||
302 | ACPI_IMODE_LOAD_PASS1, flags, walk_state, | ||
303 | &node); | ||
304 | if (ACPI_FAILURE(status)) { | ||
305 | if (status == AE_ALREADY_EXISTS) { | ||
306 | |||
307 | /* The name already exists in this scope */ | ||
308 | |||
309 | if (node->flags & ANOBJ_IS_EXTERNAL) { | ||
310 | /* | ||
311 | * Allow one create on an object or segment that was | ||
312 | * previously declared External | ||
313 | */ | ||
314 | node->flags &= ~ANOBJ_IS_EXTERNAL; | ||
315 | node->type = (u8) object_type; | ||
316 | |||
317 | /* Just retyped a node, probably will need to open a scope */ | ||
318 | |||
319 | if (acpi_ns_opens_scope(object_type)) { | ||
320 | status = | ||
321 | acpi_ds_scope_stack_push | ||
322 | (node, object_type, | ||
323 | walk_state); | ||
324 | if (ACPI_FAILURE(status)) { | ||
325 | return_ACPI_STATUS | ||
326 | (status); | ||
327 | } | ||
328 | } | ||
329 | |||
330 | status = AE_OK; | ||
331 | } | ||
332 | } | ||
333 | |||
334 | if (ACPI_FAILURE(status)) { | ||
335 | ACPI_ERROR_NAMESPACE(path, status); | ||
336 | return_ACPI_STATUS(status); | ||
337 | } | ||
338 | } | ||
339 | break; | ||
340 | } | ||
341 | |||
342 | /* Common exit */ | ||
343 | |||
344 | if (!op) { | ||
345 | |||
346 | /* Create a new op */ | ||
347 | |||
348 | op = acpi_ps_alloc_op(walk_state->opcode); | ||
349 | if (!op) { | ||
350 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
351 | } | ||
352 | } | ||
353 | |||
354 | /* Initialize the op */ | ||
355 | |||
356 | #if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY)) | ||
357 | op->named.path = ACPI_CAST_PTR(u8, path); | ||
358 | #endif | ||
359 | |||
360 | if (node) { | ||
361 | /* | ||
362 | * Put the Node in the "op" object that the parser uses, so we | ||
363 | * can get it again quickly when this scope is closed | ||
364 | */ | ||
365 | op->common.node = node; | ||
366 | op->named.name = node->name.integer; | ||
367 | } | ||
368 | |||
369 | acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state), | ||
370 | op); | ||
371 | *out_op = op; | ||
372 | return_ACPI_STATUS(status); | ||
373 | } | ||
374 | |||
375 | /******************************************************************************* | ||
376 | * | ||
377 | * FUNCTION: acpi_ds_load1_end_op | ||
378 | * | ||
379 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
380 | * | ||
381 | * RETURN: Status | ||
382 | * | ||
383 | * DESCRIPTION: Ascending callback used during the loading of the namespace, | ||
384 | * both control methods and everything else. | ||
385 | * | ||
386 | ******************************************************************************/ | ||
387 | |||
388 | acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) | ||
389 | { | ||
390 | union acpi_parse_object *op; | ||
391 | acpi_object_type object_type; | ||
392 | acpi_status status = AE_OK; | ||
393 | |||
394 | ACPI_FUNCTION_TRACE(ds_load1_end_op); | ||
395 | |||
396 | op = walk_state->op; | ||
397 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, | ||
398 | walk_state)); | ||
399 | |||
400 | /* We are only interested in opcodes that have an associated name */ | ||
401 | |||
402 | if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { | ||
403 | return_ACPI_STATUS(AE_OK); | ||
404 | } | ||
405 | |||
406 | /* Get the object type to determine if we should pop the scope */ | ||
407 | |||
408 | object_type = walk_state->op_info->object_type; | ||
409 | |||
410 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
411 | if (walk_state->op_info->flags & AML_FIELD) { | ||
412 | /* | ||
413 | * If we are executing a method, do not create any namespace objects | ||
414 | * during the load phase, only during execution. | ||
415 | */ | ||
416 | if (!walk_state->method_node) { | ||
417 | if (walk_state->opcode == AML_FIELD_OP || | ||
418 | walk_state->opcode == AML_BANK_FIELD_OP || | ||
419 | walk_state->opcode == AML_INDEX_FIELD_OP) { | ||
420 | status = | ||
421 | acpi_ds_init_field_objects(op, walk_state); | ||
422 | } | ||
423 | } | ||
424 | return_ACPI_STATUS(status); | ||
425 | } | ||
426 | |||
427 | /* | ||
428 | * If we are executing a method, do not create any namespace objects | ||
429 | * during the load phase, only during execution. | ||
430 | */ | ||
431 | if (!walk_state->method_node) { | ||
432 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
433 | status = | ||
434 | acpi_ex_create_region(op->named.data, | ||
435 | op->named.length, | ||
436 | (acpi_adr_space_type) ((op-> | ||
437 | common. | ||
438 | value. | ||
439 | arg)-> | ||
440 | common. | ||
441 | value. | ||
442 | integer), | ||
443 | walk_state); | ||
444 | if (ACPI_FAILURE(status)) { | ||
445 | return_ACPI_STATUS(status); | ||
446 | } | ||
447 | } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { | ||
448 | status = | ||
449 | acpi_ex_create_region(op->named.data, | ||
450 | op->named.length, | ||
451 | REGION_DATA_TABLE, | ||
452 | walk_state); | ||
453 | if (ACPI_FAILURE(status)) { | ||
454 | return_ACPI_STATUS(status); | ||
455 | } | ||
456 | } | ||
457 | } | ||
458 | #endif | ||
459 | |||
460 | if (op->common.aml_opcode == AML_NAME_OP) { | ||
461 | |||
462 | /* For Name opcode, get the object type from the argument */ | ||
463 | |||
464 | if (op->common.value.arg) { | ||
465 | object_type = (acpi_ps_get_opcode_info((op->common. | ||
466 | value.arg)-> | ||
467 | common. | ||
468 | aml_opcode))-> | ||
469 | object_type; | ||
470 | |||
471 | /* Set node type if we have a namespace node */ | ||
472 | |||
473 | if (op->common.node) { | ||
474 | op->common.node->type = (u8) object_type; | ||
475 | } | ||
476 | } | ||
477 | } | ||
478 | |||
479 | /* | ||
480 | * If we are executing a method, do not create any namespace objects | ||
481 | * during the load phase, only during execution. | ||
482 | */ | ||
483 | if (!walk_state->method_node) { | ||
484 | if (op->common.aml_opcode == AML_METHOD_OP) { | ||
485 | /* | ||
486 | * method_op pkg_length name_string method_flags term_list | ||
487 | * | ||
488 | * Note: We must create the method node/object pair as soon as we | ||
489 | * see the method declaration. This allows later pass1 parsing | ||
490 | * of invocations of the method (need to know the number of | ||
491 | * arguments.) | ||
492 | */ | ||
493 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
494 | "LOADING-Method: State=%p Op=%p NamedObj=%p\n", | ||
495 | walk_state, op, op->named.node)); | ||
496 | |||
497 | if (!acpi_ns_get_attached_object(op->named.node)) { | ||
498 | walk_state->operands[0] = | ||
499 | ACPI_CAST_PTR(void, op->named.node); | ||
500 | walk_state->num_operands = 1; | ||
501 | |||
502 | status = | ||
503 | acpi_ds_create_operands(walk_state, | ||
504 | op->common.value. | ||
505 | arg); | ||
506 | if (ACPI_SUCCESS(status)) { | ||
507 | status = | ||
508 | acpi_ex_create_method(op->named. | ||
509 | data, | ||
510 | op->named. | ||
511 | length, | ||
512 | walk_state); | ||
513 | } | ||
514 | |||
515 | walk_state->operands[0] = NULL; | ||
516 | walk_state->num_operands = 0; | ||
517 | |||
518 | if (ACPI_FAILURE(status)) { | ||
519 | return_ACPI_STATUS(status); | ||
520 | } | ||
521 | } | ||
522 | } | ||
523 | } | ||
524 | |||
525 | /* Pop the scope stack (only if loading a table) */ | ||
526 | |||
527 | if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) { | ||
528 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
529 | "(%s): Popping scope for Op %p\n", | ||
530 | acpi_ut_get_type_name(object_type), op)); | ||
531 | |||
532 | status = acpi_ds_scope_stack_pop(walk_state); | ||
533 | } | ||
534 | |||
535 | return_ACPI_STATUS(status); | ||
536 | } | ||
537 | |||
538 | /******************************************************************************* | ||
539 | * | ||
540 | * FUNCTION: acpi_ds_load2_begin_op | ||
541 | * | ||
542 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
543 | * out_op - Wher to return op if a new one is created | ||
544 | * | ||
545 | * RETURN: Status | ||
546 | * | ||
547 | * DESCRIPTION: Descending callback used during the loading of ACPI tables. | ||
548 | * | ||
549 | ******************************************************************************/ | ||
550 | |||
551 | acpi_status | ||
552 | acpi_ds_load2_begin_op(struct acpi_walk_state *walk_state, | ||
553 | union acpi_parse_object **out_op) | ||
554 | { | ||
555 | union acpi_parse_object *op; | ||
556 | struct acpi_namespace_node *node; | ||
557 | acpi_status status; | ||
558 | acpi_object_type object_type; | ||
559 | char *buffer_ptr; | ||
560 | u32 flags; | ||
561 | |||
562 | ACPI_FUNCTION_TRACE(ds_load2_begin_op); | ||
563 | |||
564 | op = walk_state->op; | ||
565 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, | ||
566 | walk_state)); | ||
567 | |||
568 | if (op) { | ||
569 | if ((walk_state->control_state) && | ||
570 | (walk_state->control_state->common.state == | ||
571 | ACPI_CONTROL_CONDITIONAL_EXECUTING)) { | ||
572 | |||
573 | /* We are executing a while loop outside of a method */ | ||
574 | |||
575 | status = acpi_ds_exec_begin_op(walk_state, out_op); | ||
576 | return_ACPI_STATUS(status); | ||
577 | } | ||
578 | |||
579 | /* We only care about Namespace opcodes here */ | ||
580 | |||
581 | if ((!(walk_state->op_info->flags & AML_NSOPCODE) && | ||
582 | (walk_state->opcode != AML_INT_NAMEPATH_OP)) || | ||
583 | (!(walk_state->op_info->flags & AML_NAMED))) { | ||
584 | #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE | ||
585 | if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || | ||
586 | (walk_state->op_info->class == AML_CLASS_CONTROL)) { | ||
587 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
588 | "Begin/EXEC: %s (fl %8.8X)\n", | ||
589 | walk_state->op_info->name, | ||
590 | walk_state->op_info->flags)); | ||
591 | |||
592 | /* Executing a type1 or type2 opcode outside of a method */ | ||
593 | |||
594 | status = | ||
595 | acpi_ds_exec_begin_op(walk_state, out_op); | ||
596 | return_ACPI_STATUS(status); | ||
597 | } | ||
598 | #endif | ||
599 | return_ACPI_STATUS(AE_OK); | ||
600 | } | ||
601 | |||
602 | /* Get the name we are going to enter or lookup in the namespace */ | ||
603 | |||
604 | if (walk_state->opcode == AML_INT_NAMEPATH_OP) { | ||
605 | |||
606 | /* For Namepath op, get the path string */ | ||
607 | |||
608 | buffer_ptr = op->common.value.string; | ||
609 | if (!buffer_ptr) { | ||
610 | |||
611 | /* No name, just exit */ | ||
612 | |||
613 | return_ACPI_STATUS(AE_OK); | ||
614 | } | ||
615 | } else { | ||
616 | /* Get name from the op */ | ||
617 | |||
618 | buffer_ptr = ACPI_CAST_PTR(char, &op->named.name); | ||
619 | } | ||
620 | } else { | ||
621 | /* Get the namestring from the raw AML */ | ||
622 | |||
623 | buffer_ptr = | ||
624 | acpi_ps_get_next_namestring(&walk_state->parser_state); | ||
625 | } | ||
626 | |||
627 | /* Map the opcode into an internal object type */ | ||
628 | |||
629 | object_type = walk_state->op_info->object_type; | ||
630 | |||
631 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
632 | "State=%p Op=%p Type=%X\n", walk_state, op, | ||
633 | object_type)); | ||
634 | |||
635 | switch (walk_state->opcode) { | ||
636 | case AML_FIELD_OP: | ||
637 | case AML_BANK_FIELD_OP: | ||
638 | case AML_INDEX_FIELD_OP: | ||
639 | |||
640 | node = NULL; | ||
641 | status = AE_OK; | ||
642 | break; | ||
643 | |||
644 | case AML_INT_NAMEPATH_OP: | ||
645 | /* | ||
646 | * The name_path is an object reference to an existing object. | ||
647 | * Don't enter the name into the namespace, but look it up | ||
648 | * for use later. | ||
649 | */ | ||
650 | status = | ||
651 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
652 | object_type, ACPI_IMODE_EXECUTE, | ||
653 | ACPI_NS_SEARCH_PARENT, walk_state, &(node)); | ||
654 | break; | ||
655 | |||
656 | case AML_SCOPE_OP: | ||
657 | /* | ||
658 | * The Path is an object reference to an existing object. | ||
659 | * Don't enter the name into the namespace, but look it up | ||
660 | * for use later. | ||
661 | */ | ||
662 | status = | ||
663 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
664 | object_type, ACPI_IMODE_EXECUTE, | ||
665 | ACPI_NS_SEARCH_PARENT, walk_state, &(node)); | ||
666 | if (ACPI_FAILURE(status)) { | ||
667 | #ifdef ACPI_ASL_COMPILER | ||
668 | if (status == AE_NOT_FOUND) { | ||
669 | status = AE_OK; | ||
670 | } else { | ||
671 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
672 | } | ||
673 | #else | ||
674 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
675 | #endif | ||
676 | return_ACPI_STATUS(status); | ||
677 | } | ||
678 | |||
679 | /* | ||
680 | * We must check to make sure that the target is | ||
681 | * one of the opcodes that actually opens a scope | ||
682 | */ | ||
683 | switch (node->type) { | ||
684 | case ACPI_TYPE_ANY: | ||
685 | case ACPI_TYPE_LOCAL_SCOPE: /* Scope */ | ||
686 | case ACPI_TYPE_DEVICE: | ||
687 | case ACPI_TYPE_POWER: | ||
688 | case ACPI_TYPE_PROCESSOR: | ||
689 | case ACPI_TYPE_THERMAL: | ||
690 | |||
691 | /* These are acceptable types */ | ||
692 | break; | ||
693 | |||
694 | case ACPI_TYPE_INTEGER: | ||
695 | case ACPI_TYPE_STRING: | ||
696 | case ACPI_TYPE_BUFFER: | ||
697 | |||
698 | /* | ||
699 | * These types we will allow, but we will change the type. This | ||
700 | * enables some existing code of the form: | ||
701 | * | ||
702 | * Name (DEB, 0) | ||
703 | * Scope (DEB) { ... } | ||
704 | */ | ||
705 | ACPI_WARNING((AE_INFO, | ||
706 | "Type override - [%4.4s] had invalid type (%s) for Scope operator, changed to (Scope)", | ||
707 | buffer_ptr, | ||
708 | acpi_ut_get_type_name(node->type))); | ||
709 | |||
710 | node->type = ACPI_TYPE_ANY; | ||
711 | walk_state->scope_info->common.value = ACPI_TYPE_ANY; | ||
712 | break; | ||
713 | |||
714 | default: | ||
715 | |||
716 | /* All other types are an error */ | ||
717 | |||
718 | ACPI_ERROR((AE_INFO, | ||
719 | "Invalid type (%s) for target of Scope operator [%4.4s]", | ||
720 | acpi_ut_get_type_name(node->type), | ||
721 | buffer_ptr)); | ||
722 | |||
723 | return (AE_AML_OPERAND_TYPE); | ||
724 | } | ||
725 | break; | ||
726 | |||
727 | default: | ||
728 | |||
729 | /* All other opcodes */ | ||
730 | |||
731 | if (op && op->common.node) { | ||
732 | |||
733 | /* This op/node was previously entered into the namespace */ | ||
734 | |||
735 | node = op->common.node; | ||
736 | |||
737 | if (acpi_ns_opens_scope(object_type)) { | ||
738 | status = | ||
739 | acpi_ds_scope_stack_push(node, object_type, | ||
740 | walk_state); | ||
741 | if (ACPI_FAILURE(status)) { | ||
742 | return_ACPI_STATUS(status); | ||
743 | } | ||
744 | } | ||
745 | |||
746 | return_ACPI_STATUS(AE_OK); | ||
747 | } | ||
748 | |||
749 | /* | ||
750 | * Enter the named type into the internal namespace. We enter the name | ||
751 | * as we go downward in the parse tree. Any necessary subobjects that | ||
752 | * involve arguments to the opcode must be created as we go back up the | ||
753 | * parse tree later. | ||
754 | * | ||
755 | * Note: Name may already exist if we are executing a deferred opcode. | ||
756 | */ | ||
757 | if (walk_state->deferred_node) { | ||
758 | |||
759 | /* This name is already in the namespace, get the node */ | ||
760 | |||
761 | node = walk_state->deferred_node; | ||
762 | status = AE_OK; | ||
763 | break; | ||
764 | } | ||
765 | |||
766 | flags = ACPI_NS_NO_UPSEARCH; | ||
767 | if (walk_state->pass_number == ACPI_IMODE_EXECUTE) { | ||
768 | |||
769 | /* Execution mode, node cannot already exist, node is temporary */ | ||
770 | |||
771 | flags |= (ACPI_NS_ERROR_IF_FOUND | ACPI_NS_TEMPORARY); | ||
772 | } | ||
773 | |||
774 | /* Add new entry or lookup existing entry */ | ||
775 | |||
776 | status = | ||
777 | acpi_ns_lookup(walk_state->scope_info, buffer_ptr, | ||
778 | object_type, ACPI_IMODE_LOAD_PASS2, flags, | ||
779 | walk_state, &node); | ||
780 | |||
781 | if (ACPI_SUCCESS(status) && (flags & ACPI_NS_TEMPORARY)) { | ||
782 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
783 | "***New Node [%4.4s] %p is temporary\n", | ||
784 | acpi_ut_get_node_name(node), node)); | ||
785 | } | ||
786 | break; | ||
787 | } | ||
788 | |||
789 | if (ACPI_FAILURE(status)) { | ||
790 | ACPI_ERROR_NAMESPACE(buffer_ptr, status); | ||
791 | return_ACPI_STATUS(status); | ||
792 | } | ||
793 | |||
794 | if (!op) { | ||
795 | |||
796 | /* Create a new op */ | ||
797 | |||
798 | op = acpi_ps_alloc_op(walk_state->opcode); | ||
799 | if (!op) { | ||
800 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
801 | } | ||
802 | |||
803 | /* Initialize the new op */ | ||
804 | |||
805 | if (node) { | ||
806 | op->named.name = node->name.integer; | ||
807 | } | ||
808 | *out_op = op; | ||
809 | } | ||
810 | |||
811 | /* | ||
812 | * Put the Node in the "op" object that the parser uses, so we | ||
813 | * can get it again quickly when this scope is closed | ||
814 | */ | ||
815 | op->common.node = node; | ||
816 | return_ACPI_STATUS(status); | ||
817 | } | ||
818 | |||
819 | /******************************************************************************* | ||
820 | * | ||
821 | * FUNCTION: acpi_ds_load2_end_op | ||
822 | * | ||
823 | * PARAMETERS: walk_state - Current state of the parse tree walk | ||
824 | * | ||
825 | * RETURN: Status | ||
826 | * | ||
827 | * DESCRIPTION: Ascending callback used during the loading of the namespace, | ||
828 | * both control methods and everything else. | ||
829 | * | ||
830 | ******************************************************************************/ | ||
831 | |||
832 | acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state) | ||
833 | { | ||
834 | union acpi_parse_object *op; | ||
835 | acpi_status status = AE_OK; | ||
836 | acpi_object_type object_type; | ||
837 | struct acpi_namespace_node *node; | ||
838 | union acpi_parse_object *arg; | ||
839 | struct acpi_namespace_node *new_node; | ||
840 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
841 | u32 i; | ||
842 | u8 region_space; | ||
843 | #endif | ||
844 | |||
845 | ACPI_FUNCTION_TRACE(ds_load2_end_op); | ||
846 | |||
847 | op = walk_state->op; | ||
848 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n", | ||
849 | walk_state->op_info->name, op, walk_state)); | ||
850 | |||
851 | /* Check if opcode had an associated namespace object */ | ||
852 | |||
853 | if (!(walk_state->op_info->flags & AML_NSOBJECT)) { | ||
854 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
855 | #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE | ||
856 | /* No namespace object. Executable opcode? */ | ||
857 | |||
858 | if ((walk_state->op_info->class == AML_CLASS_EXECUTE) || | ||
859 | (walk_state->op_info->class == AML_CLASS_CONTROL)) { | ||
860 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
861 | "End/EXEC: %s (fl %8.8X)\n", | ||
862 | walk_state->op_info->name, | ||
863 | walk_state->op_info->flags)); | ||
864 | |||
865 | /* Executing a type1 or type2 opcode outside of a method */ | ||
866 | |||
867 | status = acpi_ds_exec_end_op(walk_state); | ||
868 | return_ACPI_STATUS(status); | ||
869 | } | ||
870 | #endif | ||
871 | #endif | ||
872 | return_ACPI_STATUS(AE_OK); | ||
873 | } | ||
874 | |||
875 | if (op->common.aml_opcode == AML_SCOPE_OP) { | ||
876 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
877 | "Ending scope Op=%p State=%p\n", op, | ||
878 | walk_state)); | ||
879 | } | ||
880 | |||
881 | object_type = walk_state->op_info->object_type; | ||
882 | |||
883 | /* | ||
884 | * Get the Node/name from the earlier lookup | ||
885 | * (It was saved in the *op structure) | ||
886 | */ | ||
887 | node = op->common.node; | ||
888 | |||
889 | /* | ||
890 | * Put the Node on the object stack (Contains the ACPI Name of | ||
891 | * this object) | ||
892 | */ | ||
893 | walk_state->operands[0] = (void *)node; | ||
894 | walk_state->num_operands = 1; | ||
895 | |||
896 | /* Pop the scope stack */ | ||
897 | |||
898 | if (acpi_ns_opens_scope(object_type) && | ||
899 | (op->common.aml_opcode != AML_INT_METHODCALL_OP)) { | ||
900 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
901 | "(%s) Popping scope for Op %p\n", | ||
902 | acpi_ut_get_type_name(object_type), op)); | ||
903 | |||
904 | status = acpi_ds_scope_stack_pop(walk_state); | ||
905 | if (ACPI_FAILURE(status)) { | ||
906 | goto cleanup; | ||
907 | } | ||
908 | } | ||
909 | |||
910 | /* | ||
911 | * Named operations are as follows: | ||
912 | * | ||
913 | * AML_ALIAS | ||
914 | * AML_BANKFIELD | ||
915 | * AML_CREATEBITFIELD | ||
916 | * AML_CREATEBYTEFIELD | ||
917 | * AML_CREATEDWORDFIELD | ||
918 | * AML_CREATEFIELD | ||
919 | * AML_CREATEQWORDFIELD | ||
920 | * AML_CREATEWORDFIELD | ||
921 | * AML_DATA_REGION | ||
922 | * AML_DEVICE | ||
923 | * AML_EVENT | ||
924 | * AML_FIELD | ||
925 | * AML_INDEXFIELD | ||
926 | * AML_METHOD | ||
927 | * AML_METHODCALL | ||
928 | * AML_MUTEX | ||
929 | * AML_NAME | ||
930 | * AML_NAMEDFIELD | ||
931 | * AML_OPREGION | ||
932 | * AML_POWERRES | ||
933 | * AML_PROCESSOR | ||
934 | * AML_SCOPE | ||
935 | * AML_THERMALZONE | ||
936 | */ | ||
937 | |||
938 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
939 | "Create-Load [%s] State=%p Op=%p NamedObj=%p\n", | ||
940 | acpi_ps_get_opcode_name(op->common.aml_opcode), | ||
941 | walk_state, op, node)); | ||
942 | |||
943 | /* Decode the opcode */ | ||
944 | |||
945 | arg = op->common.value.arg; | ||
946 | |||
947 | switch (walk_state->op_info->type) { | ||
948 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
949 | |||
950 | case AML_TYPE_CREATE_FIELD: | ||
951 | /* | ||
952 | * Create the field object, but the field buffer and index must | ||
953 | * be evaluated later during the execution phase | ||
954 | */ | ||
955 | status = acpi_ds_create_buffer_field(op, walk_state); | ||
956 | break; | ||
957 | |||
958 | case AML_TYPE_NAMED_FIELD: | ||
959 | /* | ||
960 | * If we are executing a method, initialize the field | ||
961 | */ | ||
962 | if (walk_state->method_node) { | ||
963 | status = acpi_ds_init_field_objects(op, walk_state); | ||
964 | } | ||
965 | |||
966 | switch (op->common.aml_opcode) { | ||
967 | case AML_INDEX_FIELD_OP: | ||
968 | |||
969 | status = | ||
970 | acpi_ds_create_index_field(op, | ||
971 | (acpi_handle) arg-> | ||
972 | common.node, walk_state); | ||
973 | break; | ||
974 | |||
975 | case AML_BANK_FIELD_OP: | ||
976 | |||
977 | status = | ||
978 | acpi_ds_create_bank_field(op, arg->common.node, | ||
979 | walk_state); | ||
980 | break; | ||
981 | |||
982 | case AML_FIELD_OP: | ||
983 | |||
984 | status = | ||
985 | acpi_ds_create_field(op, arg->common.node, | ||
986 | walk_state); | ||
987 | break; | ||
988 | |||
989 | default: | ||
990 | /* All NAMED_FIELD opcodes must be handled above */ | ||
991 | break; | ||
992 | } | ||
993 | break; | ||
994 | |||
995 | case AML_TYPE_NAMED_SIMPLE: | ||
996 | |||
997 | status = acpi_ds_create_operands(walk_state, arg); | ||
998 | if (ACPI_FAILURE(status)) { | ||
999 | goto cleanup; | ||
1000 | } | ||
1001 | |||
1002 | switch (op->common.aml_opcode) { | ||
1003 | case AML_PROCESSOR_OP: | ||
1004 | |||
1005 | status = acpi_ex_create_processor(walk_state); | ||
1006 | break; | ||
1007 | |||
1008 | case AML_POWER_RES_OP: | ||
1009 | |||
1010 | status = acpi_ex_create_power_resource(walk_state); | ||
1011 | break; | ||
1012 | |||
1013 | case AML_MUTEX_OP: | ||
1014 | |||
1015 | status = acpi_ex_create_mutex(walk_state); | ||
1016 | break; | ||
1017 | |||
1018 | case AML_EVENT_OP: | ||
1019 | |||
1020 | status = acpi_ex_create_event(walk_state); | ||
1021 | break; | ||
1022 | |||
1023 | case AML_ALIAS_OP: | ||
1024 | |||
1025 | status = acpi_ex_create_alias(walk_state); | ||
1026 | break; | ||
1027 | |||
1028 | default: | ||
1029 | /* Unknown opcode */ | ||
1030 | |||
1031 | status = AE_OK; | ||
1032 | goto cleanup; | ||
1033 | } | ||
1034 | |||
1035 | /* Delete operands */ | ||
1036 | |||
1037 | for (i = 1; i < walk_state->num_operands; i++) { | ||
1038 | acpi_ut_remove_reference(walk_state->operands[i]); | ||
1039 | walk_state->operands[i] = NULL; | ||
1040 | } | ||
1041 | |||
1042 | break; | ||
1043 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
1044 | |||
1045 | case AML_TYPE_NAMED_COMPLEX: | ||
1046 | |||
1047 | switch (op->common.aml_opcode) { | ||
1048 | #ifndef ACPI_NO_METHOD_EXECUTION | ||
1049 | case AML_REGION_OP: | ||
1050 | case AML_DATA_REGION_OP: | ||
1051 | |||
1052 | if (op->common.aml_opcode == AML_REGION_OP) { | ||
1053 | region_space = (acpi_adr_space_type) | ||
1054 | ((op->common.value.arg)->common.value. | ||
1055 | integer); | ||
1056 | } else { | ||
1057 | region_space = REGION_DATA_TABLE; | ||
1058 | } | ||
1059 | |||
1060 | /* | ||
1061 | * If we are executing a method, initialize the region | ||
1062 | */ | ||
1063 | if (walk_state->method_node) { | ||
1064 | status = | ||
1065 | acpi_ex_create_region(op->named.data, | ||
1066 | op->named.length, | ||
1067 | region_space, | ||
1068 | walk_state); | ||
1069 | if (ACPI_FAILURE(status)) { | ||
1070 | return (status); | ||
1071 | } | ||
1072 | } | ||
1073 | |||
1074 | /* | ||
1075 | * The op_region is not fully parsed at this time. Only valid | ||
1076 | * argument is the space_id. (We must save the address of the | ||
1077 | * AML of the address and length operands) | ||
1078 | */ | ||
1079 | |||
1080 | /* | ||
1081 | * If we have a valid region, initialize it | ||
1082 | * Namespace is NOT locked at this point. | ||
1083 | */ | ||
1084 | status = | ||
1085 | acpi_ev_initialize_region | ||
1086 | (acpi_ns_get_attached_object(node), FALSE); | ||
1087 | if (ACPI_FAILURE(status)) { | ||
1088 | /* | ||
1089 | * If AE_NOT_EXIST is returned, it is not fatal | ||
1090 | * because many regions get created before a handler | ||
1091 | * is installed for said region. | ||
1092 | */ | ||
1093 | if (AE_NOT_EXIST == status) { | ||
1094 | status = AE_OK; | ||
1095 | } | ||
1096 | } | ||
1097 | break; | ||
1098 | |||
1099 | case AML_NAME_OP: | ||
1100 | |||
1101 | status = acpi_ds_create_node(walk_state, node, op); | ||
1102 | break; | ||
1103 | |||
1104 | case AML_METHOD_OP: | ||
1105 | /* | ||
1106 | * method_op pkg_length name_string method_flags term_list | ||
1107 | * | ||
1108 | * Note: We must create the method node/object pair as soon as we | ||
1109 | * see the method declaration. This allows later pass1 parsing | ||
1110 | * of invocations of the method (need to know the number of | ||
1111 | * arguments.) | ||
1112 | */ | ||
1113 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1114 | "LOADING-Method: State=%p Op=%p NamedObj=%p\n", | ||
1115 | walk_state, op, op->named.node)); | ||
1116 | |||
1117 | if (!acpi_ns_get_attached_object(op->named.node)) { | ||
1118 | walk_state->operands[0] = | ||
1119 | ACPI_CAST_PTR(void, op->named.node); | ||
1120 | walk_state->num_operands = 1; | ||
1121 | |||
1122 | status = | ||
1123 | acpi_ds_create_operands(walk_state, | ||
1124 | op->common.value. | ||
1125 | arg); | ||
1126 | if (ACPI_SUCCESS(status)) { | ||
1127 | status = | ||
1128 | acpi_ex_create_method(op->named. | ||
1129 | data, | ||
1130 | op->named. | ||
1131 | length, | ||
1132 | walk_state); | ||
1133 | } | ||
1134 | walk_state->operands[0] = NULL; | ||
1135 | walk_state->num_operands = 0; | ||
1136 | |||
1137 | if (ACPI_FAILURE(status)) { | ||
1138 | return_ACPI_STATUS(status); | ||
1139 | } | ||
1140 | } | ||
1141 | break; | ||
1142 | |||
1143 | #endif /* ACPI_NO_METHOD_EXECUTION */ | ||
1144 | |||
1145 | default: | ||
1146 | /* All NAMED_COMPLEX opcodes must be handled above */ | ||
1147 | break; | ||
1148 | } | ||
1149 | break; | ||
1150 | |||
1151 | case AML_CLASS_INTERNAL: | ||
1152 | |||
1153 | /* case AML_INT_NAMEPATH_OP: */ | ||
1154 | break; | ||
1155 | |||
1156 | case AML_CLASS_METHOD_CALL: | ||
1157 | |||
1158 | ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, | ||
1159 | "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n", | ||
1160 | walk_state, op, node)); | ||
1161 | |||
1162 | /* | ||
1163 | * Lookup the method name and save the Node | ||
1164 | */ | ||
1165 | status = | ||
1166 | acpi_ns_lookup(walk_state->scope_info, | ||
1167 | arg->common.value.string, ACPI_TYPE_ANY, | ||
1168 | ACPI_IMODE_LOAD_PASS2, | ||
1169 | ACPI_NS_SEARCH_PARENT | | ||
1170 | ACPI_NS_DONT_OPEN_SCOPE, walk_state, | ||
1171 | &(new_node)); | ||
1172 | if (ACPI_SUCCESS(status)) { | ||
1173 | /* | ||
1174 | * Make sure that what we found is indeed a method | ||
1175 | * We didn't search for a method on purpose, to see if the name | ||
1176 | * would resolve | ||
1177 | */ | ||
1178 | if (new_node->type != ACPI_TYPE_METHOD) { | ||
1179 | status = AE_AML_OPERAND_TYPE; | ||
1180 | } | ||
1181 | |||
1182 | /* We could put the returned object (Node) on the object stack for | ||
1183 | * later, but for now, we will put it in the "op" object that the | ||
1184 | * parser uses, so we can get it again at the end of this scope | ||
1185 | */ | ||
1186 | op->common.node = new_node; | ||
1187 | } else { | ||
1188 | ACPI_ERROR_NAMESPACE(arg->common.value.string, status); | ||
1189 | } | ||
1190 | break; | ||
1191 | |||
1192 | default: | ||
1193 | break; | ||
1194 | } | ||
1195 | |||
1196 | cleanup: | ||
1197 | |||
1198 | /* Remove the Node pushed at the very beginning */ | ||
1199 | |||
1200 | walk_state->operands[0] = NULL; | ||
1201 | walk_state->num_operands = 0; | ||
1202 | return_ACPI_STATUS(status); | ||
1203 | } | ||
diff --git a/drivers/acpi/dispatcher/dswscope.c b/drivers/acpi/dispatcher/dswscope.c deleted file mode 100644 index 8030541a49f7..000000000000 --- a/drivers/acpi/dispatcher/dswscope.c +++ /dev/null | |||
@@ -1,214 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dswscope - Scope stack manipulation | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/acdispat.h> | ||
47 | |||
48 | #define _COMPONENT ACPI_DISPATCHER | ||
49 | ACPI_MODULE_NAME("dswscope") | ||
50 | |||
51 | /**************************************************************************** | ||
52 | * | ||
53 | * FUNCTION: acpi_ds_scope_stack_clear | ||
54 | * | ||
55 | * PARAMETERS: walk_state - Current state | ||
56 | * | ||
57 | * RETURN: None | ||
58 | * | ||
59 | * DESCRIPTION: Pop (and free) everything on the scope stack except the | ||
60 | * root scope object (which remains at the stack top.) | ||
61 | * | ||
62 | ***************************************************************************/ | ||
63 | void acpi_ds_scope_stack_clear(struct acpi_walk_state *walk_state) | ||
64 | { | ||
65 | union acpi_generic_state *scope_info; | ||
66 | |||
67 | ACPI_FUNCTION_NAME(ds_scope_stack_clear); | ||
68 | |||
69 | while (walk_state->scope_info) { | ||
70 | |||
71 | /* Pop a scope off the stack */ | ||
72 | |||
73 | scope_info = walk_state->scope_info; | ||
74 | walk_state->scope_info = scope_info->scope.next; | ||
75 | |||
76 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
77 | "Popped object type (%s)\n", | ||
78 | acpi_ut_get_type_name(scope_info->common. | ||
79 | value))); | ||
80 | acpi_ut_delete_generic_state(scope_info); | ||
81 | } | ||
82 | } | ||
83 | |||
84 | /**************************************************************************** | ||
85 | * | ||
86 | * FUNCTION: acpi_ds_scope_stack_push | ||
87 | * | ||
88 | * PARAMETERS: Node - Name to be made current | ||
89 | * Type - Type of frame being pushed | ||
90 | * walk_state - Current state | ||
91 | * | ||
92 | * RETURN: Status | ||
93 | * | ||
94 | * DESCRIPTION: Push the current scope on the scope stack, and make the | ||
95 | * passed Node current. | ||
96 | * | ||
97 | ***************************************************************************/ | ||
98 | |||
99 | acpi_status | ||
100 | acpi_ds_scope_stack_push(struct acpi_namespace_node *node, | ||
101 | acpi_object_type type, | ||
102 | struct acpi_walk_state *walk_state) | ||
103 | { | ||
104 | union acpi_generic_state *scope_info; | ||
105 | union acpi_generic_state *old_scope_info; | ||
106 | |||
107 | ACPI_FUNCTION_TRACE(ds_scope_stack_push); | ||
108 | |||
109 | if (!node) { | ||
110 | |||
111 | /* Invalid scope */ | ||
112 | |||
113 | ACPI_ERROR((AE_INFO, "Null scope parameter")); | ||
114 | return_ACPI_STATUS(AE_BAD_PARAMETER); | ||
115 | } | ||
116 | |||
117 | /* Make sure object type is valid */ | ||
118 | |||
119 | if (!acpi_ut_valid_object_type(type)) { | ||
120 | ACPI_WARNING((AE_INFO, "Invalid object type: 0x%X", type)); | ||
121 | } | ||
122 | |||
123 | /* Allocate a new scope object */ | ||
124 | |||
125 | scope_info = acpi_ut_create_generic_state(); | ||
126 | if (!scope_info) { | ||
127 | return_ACPI_STATUS(AE_NO_MEMORY); | ||
128 | } | ||
129 | |||
130 | /* Init new scope object */ | ||
131 | |||
132 | scope_info->common.descriptor_type = ACPI_DESC_TYPE_STATE_WSCOPE; | ||
133 | scope_info->scope.node = node; | ||
134 | scope_info->common.value = (u16) type; | ||
135 | |||
136 | walk_state->scope_depth++; | ||
137 | |||
138 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
139 | "[%.2d] Pushed scope ", | ||
140 | (u32) walk_state->scope_depth)); | ||
141 | |||
142 | old_scope_info = walk_state->scope_info; | ||
143 | if (old_scope_info) { | ||
144 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, | ||
145 | "[%4.4s] (%s)", | ||
146 | acpi_ut_get_node_name(old_scope_info-> | ||
147 | scope.node), | ||
148 | acpi_ut_get_type_name(old_scope_info-> | ||
149 | common.value))); | ||
150 | } else { | ||
151 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (%s)", "ROOT")); | ||
152 | } | ||
153 | |||
154 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, | ||
155 | ", New scope -> [%4.4s] (%s)\n", | ||
156 | acpi_ut_get_node_name(scope_info->scope.node), | ||
157 | acpi_ut_get_type_name(scope_info->common.value))); | ||
158 | |||
159 | /* Push new scope object onto stack */ | ||
160 | |||
161 | acpi_ut_push_generic_state(&walk_state->scope_info, scope_info); | ||
162 | return_ACPI_STATUS(AE_OK); | ||
163 | } | ||
164 | |||
165 | /**************************************************************************** | ||
166 | * | ||
167 | * FUNCTION: acpi_ds_scope_stack_pop | ||
168 | * | ||
169 | * PARAMETERS: walk_state - Current state | ||
170 | * | ||
171 | * RETURN: Status | ||
172 | * | ||
173 | * DESCRIPTION: Pop the scope stack once. | ||
174 | * | ||
175 | ***************************************************************************/ | ||
176 | |||
177 | acpi_status acpi_ds_scope_stack_pop(struct acpi_walk_state *walk_state) | ||
178 | { | ||
179 | union acpi_generic_state *scope_info; | ||
180 | union acpi_generic_state *new_scope_info; | ||
181 | |||
182 | ACPI_FUNCTION_TRACE(ds_scope_stack_pop); | ||
183 | |||
184 | /* | ||
185 | * Pop scope info object off the stack. | ||
186 | */ | ||
187 | scope_info = acpi_ut_pop_generic_state(&walk_state->scope_info); | ||
188 | if (!scope_info) { | ||
189 | return_ACPI_STATUS(AE_STACK_UNDERFLOW); | ||
190 | } | ||
191 | |||
192 | walk_state->scope_depth--; | ||
193 | |||
194 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
195 | "[%.2d] Popped scope [%4.4s] (%s), New scope -> ", | ||
196 | (u32) walk_state->scope_depth, | ||
197 | acpi_ut_get_node_name(scope_info->scope.node), | ||
198 | acpi_ut_get_type_name(scope_info->common.value))); | ||
199 | |||
200 | new_scope_info = walk_state->scope_info; | ||
201 | if (new_scope_info) { | ||
202 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, | ||
203 | "[%4.4s] (%s)\n", | ||
204 | acpi_ut_get_node_name(new_scope_info-> | ||
205 | scope.node), | ||
206 | acpi_ut_get_type_name(new_scope_info-> | ||
207 | common.value))); | ||
208 | } else { | ||
209 | ACPI_DEBUG_PRINT_RAW((ACPI_DB_EXEC, "[\\___] (ROOT)\n")); | ||
210 | } | ||
211 | |||
212 | acpi_ut_delete_generic_state(scope_info); | ||
213 | return_ACPI_STATUS(AE_OK); | ||
214 | } | ||
diff --git a/drivers/acpi/dispatcher/dswstate.c b/drivers/acpi/dispatcher/dswstate.c deleted file mode 100644 index a7543c43c151..000000000000 --- a/drivers/acpi/dispatcher/dswstate.c +++ /dev/null | |||
@@ -1,753 +0,0 @@ | |||
1 | /****************************************************************************** | ||
2 | * | ||
3 | * Module Name: dswstate - Dispatcher parse tree walk management routines | ||
4 | * | ||
5 | *****************************************************************************/ | ||
6 | |||
7 | /* | ||
8 | * Copyright (C) 2000 - 2008, 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 <acpi/accommon.h> | ||
46 | #include <acpi/acparser.h> | ||
47 | #include <acpi/acdispat.h> | ||
48 | #include <acpi/acnamesp.h> | ||
49 | |||
50 | #define _COMPONENT ACPI_DISPATCHER | ||
51 | ACPI_MODULE_NAME("dswstate") | ||
52 | |||
53 | /* Local prototypes */ | ||
54 | static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *ws); | ||
55 | static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *ws); | ||
56 | |||
57 | /******************************************************************************* | ||
58 | * | ||
59 | * FUNCTION: acpi_ds_result_pop | ||
60 | * | ||
61 | * PARAMETERS: Object - Where to return the popped object | ||
62 | * walk_state - Current Walk state | ||
63 | * | ||
64 | * RETURN: Status | ||
65 | * | ||
66 | * DESCRIPTION: Pop an object off the top of this walk's result stack | ||
67 | * | ||
68 | ******************************************************************************/ | ||
69 | |||
70 | acpi_status | ||
71 | acpi_ds_result_pop(union acpi_operand_object **object, | ||
72 | struct acpi_walk_state *walk_state) | ||
73 | { | ||
74 | u32 index; | ||
75 | union acpi_generic_state *state; | ||
76 | acpi_status status; | ||
77 | |||
78 | ACPI_FUNCTION_NAME(ds_result_pop); | ||
79 | |||
80 | state = walk_state->results; | ||
81 | |||
82 | /* Incorrect state of result stack */ | ||
83 | |||
84 | if (state && !walk_state->result_count) { | ||
85 | ACPI_ERROR((AE_INFO, "No results on result stack")); | ||
86 | return (AE_AML_INTERNAL); | ||
87 | } | ||
88 | |||
89 | if (!state && walk_state->result_count) { | ||
90 | ACPI_ERROR((AE_INFO, "No result state for result stack")); | ||
91 | return (AE_AML_INTERNAL); | ||
92 | } | ||
93 | |||
94 | /* Empty result stack */ | ||
95 | |||
96 | if (!state) { | ||
97 | ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", | ||
98 | walk_state)); | ||
99 | return (AE_AML_NO_RETURN_VALUE); | ||
100 | } | ||
101 | |||
102 | /* Return object of the top element and clean that top element result stack */ | ||
103 | |||
104 | walk_state->result_count--; | ||
105 | index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; | ||
106 | |||
107 | *object = state->results.obj_desc[index]; | ||
108 | if (!*object) { | ||
109 | ACPI_ERROR((AE_INFO, | ||
110 | "No result objects on result stack, State=%p", | ||
111 | walk_state)); | ||
112 | return (AE_AML_NO_RETURN_VALUE); | ||
113 | } | ||
114 | |||
115 | state->results.obj_desc[index] = NULL; | ||
116 | if (index == 0) { | ||
117 | status = acpi_ds_result_stack_pop(walk_state); | ||
118 | if (ACPI_FAILURE(status)) { | ||
119 | return (status); | ||
120 | } | ||
121 | } | ||
122 | |||
123 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
124 | "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, | ||
125 | acpi_ut_get_object_type_name(*object), | ||
126 | index, walk_state, walk_state->result_count)); | ||
127 | |||
128 | return (AE_OK); | ||
129 | } | ||
130 | |||
131 | /******************************************************************************* | ||
132 | * | ||
133 | * FUNCTION: acpi_ds_result_push | ||
134 | * | ||
135 | * PARAMETERS: Object - Where to return the popped object | ||
136 | * walk_state - Current Walk state | ||
137 | * | ||
138 | * RETURN: Status | ||
139 | * | ||
140 | * DESCRIPTION: Push an object onto the current result stack | ||
141 | * | ||
142 | ******************************************************************************/ | ||
143 | |||
144 | acpi_status | ||
145 | acpi_ds_result_push(union acpi_operand_object * object, | ||
146 | struct acpi_walk_state * walk_state) | ||
147 | { | ||
148 | union acpi_generic_state *state; | ||
149 | acpi_status status; | ||
150 | u32 index; | ||
151 | |||
152 | ACPI_FUNCTION_NAME(ds_result_push); | ||
153 | |||
154 | if (walk_state->result_count > walk_state->result_size) { | ||
155 | ACPI_ERROR((AE_INFO, "Result stack is full")); | ||
156 | return (AE_AML_INTERNAL); | ||
157 | } else if (walk_state->result_count == walk_state->result_size) { | ||
158 | |||
159 | /* Extend the result stack */ | ||
160 | |||
161 | status = acpi_ds_result_stack_push(walk_state); | ||
162 | if (ACPI_FAILURE(status)) { | ||
163 | ACPI_ERROR((AE_INFO, | ||
164 | "Failed to extend the result stack")); | ||
165 | return (status); | ||
166 | } | ||
167 | } | ||
168 | |||
169 | if (!(walk_state->result_count < walk_state->result_size)) { | ||
170 | ACPI_ERROR((AE_INFO, "No free elements in result stack")); | ||
171 | return (AE_AML_INTERNAL); | ||
172 | } | ||
173 | |||
174 | state = walk_state->results; | ||
175 | if (!state) { | ||
176 | ACPI_ERROR((AE_INFO, "No result stack frame during push")); | ||
177 | return (AE_AML_INTERNAL); | ||
178 | } | ||
179 | |||
180 | if (!object) { | ||
181 | ACPI_ERROR((AE_INFO, | ||
182 | "Null Object! Obj=%p State=%p Num=%X", | ||
183 | object, walk_state, walk_state->result_count)); | ||
184 | return (AE_BAD_PARAMETER); | ||
185 | } | ||
186 | |||
187 | /* Assign the address of object to the top free element of result stack */ | ||
188 | |||
189 | index = walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; | ||
190 | state->results.obj_desc[index] = object; | ||
191 | walk_state->result_count++; | ||
192 | |||
193 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", | ||
194 | object, | ||
195 | acpi_ut_get_object_type_name((union | ||
196 | acpi_operand_object *) | ||
197 | object), walk_state, | ||
198 | walk_state->result_count, | ||
199 | walk_state->current_result)); | ||
200 | |||
201 | return (AE_OK); | ||
202 | } | ||
203 | |||
204 | /******************************************************************************* | ||
205 | * | ||
206 | * FUNCTION: acpi_ds_result_stack_push | ||
207 | * | ||
208 | * PARAMETERS: walk_state - Current Walk state | ||
209 | * | ||
210 | * RETURN: Status | ||
211 | * | ||
212 | * DESCRIPTION: Push an object onto the walk_state result stack | ||
213 | * | ||
214 | ******************************************************************************/ | ||
215 | |||
216 | static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) | ||
217 | { | ||
218 | union acpi_generic_state *state; | ||
219 | |||
220 | ACPI_FUNCTION_NAME(ds_result_stack_push); | ||
221 | |||
222 | /* Check for stack overflow */ | ||
223 | |||
224 | if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > | ||
225 | ACPI_RESULTS_OBJ_NUM_MAX) { | ||
226 | ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%X", | ||
227 | walk_state, walk_state->result_size)); | ||
228 | return (AE_STACK_OVERFLOW); | ||
229 | } | ||
230 | |||
231 | state = acpi_ut_create_generic_state(); | ||
232 | if (!state) { | ||
233 | return (AE_NO_MEMORY); | ||
234 | } | ||
235 | |||
236 | state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; | ||
237 | acpi_ut_push_generic_state(&walk_state->results, state); | ||
238 | |||
239 | /* Increase the length of the result stack by the length of frame */ | ||
240 | |||
241 | walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM; | ||
242 | |||
243 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", | ||
244 | state, walk_state)); | ||
245 | |||
246 | return (AE_OK); | ||
247 | } | ||
248 | |||
249 | /******************************************************************************* | ||
250 | * | ||
251 | * FUNCTION: acpi_ds_result_stack_pop | ||
252 | * | ||
253 | * PARAMETERS: walk_state - Current Walk state | ||
254 | * | ||
255 | * RETURN: Status | ||
256 | * | ||
257 | * DESCRIPTION: Pop an object off of the walk_state result stack | ||
258 | * | ||
259 | ******************************************************************************/ | ||
260 | |||
261 | static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) | ||
262 | { | ||
263 | union acpi_generic_state *state; | ||
264 | |||
265 | ACPI_FUNCTION_NAME(ds_result_stack_pop); | ||
266 | |||
267 | /* Check for stack underflow */ | ||
268 | |||
269 | if (walk_state->results == NULL) { | ||
270 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
271 | "Result stack underflow - State=%p\n", | ||
272 | walk_state)); | ||
273 | return (AE_AML_NO_OPERAND); | ||
274 | } | ||
275 | |||
276 | if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { | ||
277 | ACPI_ERROR((AE_INFO, "Insufficient result stack size")); | ||
278 | return (AE_AML_INTERNAL); | ||
279 | } | ||
280 | |||
281 | state = acpi_ut_pop_generic_state(&walk_state->results); | ||
282 | acpi_ut_delete_generic_state(state); | ||
283 | |||
284 | /* Decrease the length of result stack by the length of frame */ | ||
285 | |||
286 | walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; | ||
287 | |||
288 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, | ||
289 | "Result=%p RemainingResults=%X State=%p\n", | ||
290 | state, walk_state->result_count, walk_state)); | ||
291 | |||
292 | return (AE_OK); | ||
293 | } | ||
294 | |||
295 | /******************************************************************************* | ||
296 | * | ||
297 | * FUNCTION: acpi_ds_obj_stack_push | ||
298 | * | ||
299 | * PARAMETERS: Object - Object to push | ||
300 | * walk_state - Current Walk state | ||
301 | * | ||
302 | * RETURN: Status | ||
303 | * | ||
304 | * DESCRIPTION: Push an object onto this walk's object/operand stack | ||
305 | * | ||
306 | ******************************************************************************/ | ||
307 | |||
308 | acpi_status | ||
309 | acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) | ||
310 | { | ||
311 | ACPI_FUNCTION_NAME(ds_obj_stack_push); | ||
312 | |||
313 | /* Check for stack overflow */ | ||
314 | |||
315 | if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) { | ||
316 | ACPI_ERROR((AE_INFO, | ||
317 | "Object stack overflow! Obj=%p State=%p #Ops=%X", | ||
318 | object, walk_state, walk_state->num_operands)); | ||
319 | return (AE_STACK_OVERFLOW); | ||
320 | } | ||
321 | |||
322 | /* Put the object onto the stack */ | ||
323 | |||
324 | walk_state->operands[walk_state->operand_index] = object; | ||
325 | walk_state->num_operands++; | ||
326 | |||
327 | /* For the usual order of filling the operand stack */ | ||
328 | |||
329 | walk_state->operand_index++; | ||
330 | |||
331 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", | ||
332 | object, | ||
333 | acpi_ut_get_object_type_name((union | ||
334 | acpi_operand_object *) | ||
335 | object), walk_state, | ||
336 | walk_state->num_operands)); | ||
337 | |||
338 | return (AE_OK); | ||
339 | } | ||
340 | |||
341 | /******************************************************************************* | ||
342 | * | ||
343 | * FUNCTION: acpi_ds_obj_stack_pop | ||
344 | * | ||
345 | * PARAMETERS: pop_count - Number of objects/entries to pop | ||
346 | * walk_state - Current Walk state | ||
347 | * | ||
348 | * RETURN: Status | ||
349 | * | ||
350 | * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT | ||
351 | * deleted by this routine. | ||
352 | * | ||
353 | ******************************************************************************/ | ||
354 | |||
355 | acpi_status | ||
356 | acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) | ||
357 | { | ||
358 | u32 i; | ||
359 | |||
360 | ACPI_FUNCTION_NAME(ds_obj_stack_pop); | ||
361 | |||
362 | for (i = 0; i < pop_count; i++) { | ||
363 | |||
364 | /* Check for stack underflow */ | ||
365 | |||
366 | if (walk_state->num_operands == 0) { | ||
367 | ACPI_ERROR((AE_INFO, | ||
368 | "Object stack underflow! Count=%X State=%p #Ops=%X", | ||
369 | pop_count, walk_state, | ||
370 | walk_state->num_operands)); | ||
371 | return (AE_STACK_UNDERFLOW); | ||
372 | } | ||
373 | |||
374 | /* Just set the stack entry to null */ | ||
375 | |||
376 | walk_state->num_operands--; | ||
377 | walk_state->operands[walk_state->num_operands] = NULL; | ||
378 | } | ||
379 | |||
380 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", | ||
381 | pop_count, walk_state, walk_state->num_operands)); | ||
382 | |||
383 | return (AE_OK); | ||
384 | } | ||
385 | |||
386 | /******************************************************************************* | ||
387 | * | ||
388 | * FUNCTION: acpi_ds_obj_stack_pop_and_delete | ||
389 | * | ||
390 | * PARAMETERS: pop_count - Number of objects/entries to pop | ||
391 | * walk_state - Current Walk state | ||
392 | * | ||
393 | * RETURN: Status | ||
394 | * | ||
395 | * DESCRIPTION: Pop this walk's object stack and delete each object that is | ||
396 | * popped off. | ||
397 | * | ||
398 | ******************************************************************************/ | ||
399 | |||
400 | void | ||
401 | acpi_ds_obj_stack_pop_and_delete(u32 pop_count, | ||
402 | struct acpi_walk_state *walk_state) | ||
403 | { | ||
404 | s32 i; | ||
405 | union acpi_operand_object *obj_desc; | ||
406 | |||
407 | ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); | ||
408 | |||
409 | if (pop_count == 0) { | ||
410 | return; | ||
411 | } | ||
412 | |||
413 | for (i = (s32) pop_count - 1; i >= 0; i--) { | ||
414 | if (walk_state->num_operands == 0) { | ||
415 | return; | ||
416 | } | ||
417 | |||
418 | /* Pop the stack and delete an object if present in this stack entry */ | ||
419 | |||
420 | walk_state->num_operands--; | ||
421 | obj_desc = walk_state->operands[i]; | ||
422 | if (obj_desc) { | ||
423 | acpi_ut_remove_reference(walk_state->operands[i]); | ||
424 | walk_state->operands[i] = NULL; | ||
425 | } | ||
426 | } | ||
427 | |||
428 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", | ||
429 | pop_count, walk_state, walk_state->num_operands)); | ||
430 | } | ||
431 | |||
432 | /******************************************************************************* | ||
433 | * | ||
434 | * FUNCTION: acpi_ds_get_current_walk_state | ||
435 | * | ||
436 | * PARAMETERS: Thread - Get current active state for this Thread | ||
437 | * | ||
438 | * RETURN: Pointer to the current walk state | ||
439 | * | ||
440 | * DESCRIPTION: Get the walk state that is at the head of the list (the "current" | ||
441 | * walk state.) | ||
442 | * | ||
443 | ******************************************************************************/ | ||
444 | |||
445 | struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state | ||
446 | *thread) | ||
447 | { | ||
448 | ACPI_FUNCTION_NAME(ds_get_current_walk_state); | ||
449 | |||
450 | if (!thread) { | ||
451 | return (NULL); | ||
452 | } | ||
453 | |||
454 | ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n", | ||
455 | thread->walk_state_list)); | ||
456 | |||
457 | return (thread->walk_state_list); | ||
458 | } | ||
459 | |||
460 | /******************************************************************************* | ||
461 | * | ||
462 | * FUNCTION: acpi_ds_push_walk_state | ||
463 | * | ||
464 | * PARAMETERS: walk_state - State to push | ||
465 | * Thread - Thread state object | ||
466 | * | ||
467 | * RETURN: None | ||
468 | * | ||
469 | * DESCRIPTION: Place the Thread state at the head of the state list | ||
470 | * | ||
471 | ******************************************************************************/ | ||
472 | |||
473 | void | ||
474 | acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, | ||
475 | struct acpi_thread_state *thread) | ||
476 | { | ||
477 | ACPI_FUNCTION_TRACE(ds_push_walk_state); | ||
478 | |||
479 | walk_state->next = thread->walk_state_list; | ||
480 | thread->walk_state_list = walk_state; | ||
481 | |||
482 | return_VOID; | ||
483 | } | ||
484 | |||
485 | /******************************************************************************* | ||
486 | * | ||
487 | * FUNCTION: acpi_ds_pop_walk_state | ||
488 | * | ||
489 | * PARAMETERS: Thread - Current thread state | ||
490 | * | ||
491 | * RETURN: A walk_state object popped from the thread's stack | ||
492 | * | ||
493 | * DESCRIPTION: Remove and return the walkstate object that is at the head of | ||
494 | * the walk stack for the given walk list. NULL indicates that | ||
495 | * the list is empty. | ||
496 | * | ||
497 | ******************************************************************************/ | ||
498 | |||
499 | struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) | ||
500 | { | ||
501 | struct acpi_walk_state *walk_state; | ||
502 | |||
503 | ACPI_FUNCTION_TRACE(ds_pop_walk_state); | ||
504 | |||
505 | walk_state = thread->walk_state_list; | ||
506 | |||
507 | if (walk_state) { | ||
508 | |||
509 | /* Next walk state becomes the current walk state */ | ||
510 | |||
511 | thread->walk_state_list = walk_state->next; | ||
512 | |||
513 | /* | ||
514 | * Don't clear the NEXT field, this serves as an indicator | ||
515 | * that there is a parent WALK STATE | ||
516 | * Do Not: walk_state->Next = NULL; | ||
517 | */ | ||
518 | } | ||
519 | |||
520 | return_PTR(walk_state); | ||
521 | } | ||
522 | |||
523 | /******************************************************************************* | ||
524 | * | ||
525 | * FUNCTION: acpi_ds_create_walk_state | ||
526 | * | ||
527 | * PARAMETERS: owner_id - ID for object creation | ||
528 | * Origin - Starting point for this walk | ||
529 | * method_desc - Method object | ||
530 | * Thread - Current thread state | ||
531 | * | ||
532 | * RETURN: Pointer to the new walk state. | ||
533 | * | ||
534 | * DESCRIPTION: Allocate and initialize a new walk state. The current walk | ||
535 | * state is set to this new state. | ||
536 | * | ||
537 | ******************************************************************************/ | ||
538 | |||
539 | struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, union acpi_parse_object | ||
540 | *origin, union acpi_operand_object | ||
541 | *method_desc, struct acpi_thread_state | ||
542 | *thread) | ||
543 | { | ||
544 | struct acpi_walk_state *walk_state; | ||
545 | |||
546 | ACPI_FUNCTION_TRACE(ds_create_walk_state); | ||
547 | |||
548 | walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state)); | ||
549 | if (!walk_state) { | ||
550 | return_PTR(NULL); | ||
551 | } | ||
552 | |||
553 | walk_state->descriptor_type = ACPI_DESC_TYPE_WALK; | ||
554 | walk_state->method_desc = method_desc; | ||
555 | walk_state->owner_id = owner_id; | ||
556 | walk_state->origin = origin; | ||
557 | walk_state->thread = thread; | ||
558 | |||
559 | walk_state->parser_state.start_op = origin; | ||
560 | |||
561 | /* Init the method args/local */ | ||
562 | |||
563 | #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) | ||
564 | acpi_ds_method_data_init(walk_state); | ||
565 | #endif | ||
566 | |||
567 | /* Put the new state at the head of the walk list */ | ||
568 | |||
569 | if (thread) { | ||
570 | acpi_ds_push_walk_state(walk_state, thread); | ||
571 | } | ||
572 | |||
573 | return_PTR(walk_state); | ||
574 | } | ||
575 | |||
576 | /******************************************************************************* | ||
577 | * | ||
578 | * FUNCTION: acpi_ds_init_aml_walk | ||
579 | * | ||
580 | * PARAMETERS: walk_state - New state to be initialized | ||
581 | * Op - Current parse op | ||
582 | * method_node - Control method NS node, if any | ||
583 | * aml_start - Start of AML | ||
584 | * aml_length - Length of AML | ||
585 | * Info - Method info block (params, etc.) | ||
586 | * pass_number - 1, 2, or 3 | ||
587 | * | ||
588 | * RETURN: Status | ||
589 | * | ||
590 | * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk | ||
591 | * | ||
592 | ******************************************************************************/ | ||
593 | |||
594 | acpi_status | ||
595 | acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, | ||
596 | union acpi_parse_object *op, | ||
597 | struct acpi_namespace_node *method_node, | ||
598 | u8 * aml_start, | ||
599 | u32 aml_length, | ||
600 | struct acpi_evaluate_info *info, u8 pass_number) | ||
601 | { | ||
602 | acpi_status status; | ||
603 | struct acpi_parse_state *parser_state = &walk_state->parser_state; | ||
604 | union acpi_parse_object *extra_op; | ||
605 | |||
606 | ACPI_FUNCTION_TRACE(ds_init_aml_walk); | ||
607 | |||
608 | walk_state->parser_state.aml = | ||
609 | walk_state->parser_state.aml_start = aml_start; | ||
610 | walk_state->parser_state.aml_end = | ||
611 | walk_state->parser_state.pkg_end = aml_start + aml_length; | ||
612 | |||
613 | /* The next_op of the next_walk will be the beginning of the method */ | ||
614 | |||
615 | walk_state->next_op = NULL; | ||
616 | walk_state->pass_number = pass_number; | ||
617 | |||
618 | if (info) { | ||
619 | walk_state->params = info->parameters; | ||
620 | walk_state->caller_return_desc = &info->return_object; | ||
621 | } | ||
622 | |||
623 | status = acpi_ps_init_scope(&walk_state->parser_state, op); | ||
624 | if (ACPI_FAILURE(status)) { | ||
625 | return_ACPI_STATUS(status); | ||
626 | } | ||
627 | |||
628 | if (method_node) { | ||
629 | walk_state->parser_state.start_node = method_node; | ||
630 | walk_state->walk_type = ACPI_WALK_METHOD; | ||
631 | walk_state->method_node = method_node; | ||
632 | walk_state->method_desc = | ||
633 | acpi_ns_get_attached_object(method_node); | ||
634 | |||
635 | /* Push start scope on scope stack and make it current */ | ||
636 | |||
637 | status = | ||
638 | acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD, | ||
639 | walk_state); | ||
640 | if (ACPI_FAILURE(status)) { | ||
641 | return_ACPI_STATUS(status); | ||
642 | } | ||
643 | |||
644 | /* Init the method arguments */ | ||
645 | |||
646 | status = acpi_ds_method_data_init_args(walk_state->params, | ||
647 | ACPI_METHOD_NUM_ARGS, | ||
648 | walk_state); | ||
649 | if (ACPI_FAILURE(status)) { | ||
650 | return_ACPI_STATUS(status); | ||
651 | } | ||
652 | } else { | ||
653 | /* | ||
654 | * Setup the current scope. | ||
655 | * Find a Named Op that has a namespace node associated with it. | ||
656 | * search upwards from this Op. Current scope is the first | ||
657 | * Op with a namespace node. | ||
658 | */ | ||
659 | extra_op = parser_state->start_op; | ||
660 | while (extra_op && !extra_op->common.node) { | ||
661 | extra_op = extra_op->common.parent; | ||
662 | } | ||
663 | |||
664 | if (!extra_op) { | ||
665 | parser_state->start_node = NULL; | ||
666 | } else { | ||
667 | parser_state->start_node = extra_op->common.node; | ||
668 | } | ||
669 | |||
670 | if (parser_state->start_node) { | ||
671 | |||
672 | /* Push start scope on scope stack and make it current */ | ||
673 | |||
674 | status = | ||
675 | acpi_ds_scope_stack_push(parser_state->start_node, | ||
676 | parser_state->start_node-> | ||
677 | type, walk_state); | ||
678 | if (ACPI_FAILURE(status)) { | ||
679 | return_ACPI_STATUS(status); | ||
680 | } | ||
681 | } | ||
682 | } | ||
683 | |||
684 | status = acpi_ds_init_callbacks(walk_state, pass_number); | ||
685 | return_ACPI_STATUS(status); | ||
686 | } | ||
687 | |||
688 | /******************************************************************************* | ||
689 | * | ||
690 | * FUNCTION: acpi_ds_delete_walk_state | ||
691 | * | ||
692 | * PARAMETERS: walk_state - State to delete | ||
693 | * | ||
694 | * RETURN: Status | ||
695 | * | ||
696 | * DESCRIPTION: Delete a walk state including all internal data structures | ||
697 | * | ||
698 | ******************************************************************************/ | ||
699 | |||
700 | void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) | ||
701 | { | ||
702 | union acpi_generic_state *state; | ||
703 | |||
704 | ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); | ||
705 | |||
706 | if (!walk_state) { | ||
707 | return; | ||
708 | } | ||
709 | |||
710 | if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { | ||
711 | ACPI_ERROR((AE_INFO, "%p is not a valid walk state", | ||
712 | walk_state)); | ||
713 | return; | ||
714 | } | ||
715 | |||
716 | /* There should not be any open scopes */ | ||
717 | |||
718 | if (walk_state->parser_state.scope) { | ||
719 | ACPI_ERROR((AE_INFO, "%p walk still has a scope list", | ||
720 | walk_state)); | ||
721 | acpi_ps_cleanup_scope(&walk_state->parser_state); | ||
722 | } | ||
723 | |||
724 | /* Always must free any linked control states */ | ||
725 | |||
726 | while (walk_state->control_state) { | ||
727 | state = walk_state->control_state; | ||
728 | walk_state->control_state = state->common.next; | ||
729 | |||
730 | acpi_ut_delete_generic_state(state); | ||
731 | } | ||
732 | |||
733 | /* Always must free any linked parse states */ | ||
734 | |||
735 | while (walk_state->scope_info) { | ||
736 | state = walk_state->scope_info; | ||
737 | walk_state->scope_info = state->common.next; | ||
738 | |||
739 | acpi_ut_delete_generic_state(state); | ||
740 | } | ||
741 | |||
742 | /* Always must free any stacked result states */ | ||
743 | |||
744 | while (walk_state->results) { | ||
745 | state = walk_state->results; | ||
746 | walk_state->results = state->common.next; | ||
747 | |||
748 | acpi_ut_delete_generic_state(state); | ||
749 | } | ||
750 | |||
751 | ACPI_FREE(walk_state); | ||
752 | return_VOID; | ||
753 | } | ||