Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /****************************************************************************** |
2 | * | |
02582e9b | 3 | * Module Name: dsopcode - Dispatcher support for regions and fields |
1da177e4 LT |
4 | * |
5 | *****************************************************************************/ | |
6 | ||
7 | /* | |
77848130 | 8 | * Copyright (C) 2000 - 2012, Intel Corp. |
1da177e4 LT |
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 | ||
1da177e4 | 44 | #include <acpi/acpi.h> |
e2f7a777 LB |
45 | #include "accommon.h" |
46 | #include "acparser.h" | |
47 | #include "amlcode.h" | |
48 | #include "acdispat.h" | |
49 | #include "acinterp.h" | |
50 | #include "acnamesp.h" | |
51 | #include "acevents.h" | |
52 | #include "actables.h" | |
1da177e4 LT |
53 | |
54 | #define _COMPONENT ACPI_DISPATCHER | |
4be44fcd | 55 | ACPI_MODULE_NAME("dsopcode") |
1da177e4 | 56 | |
44f6c012 | 57 | /* Local prototypes */ |
44f6c012 | 58 | static acpi_status |
4be44fcd LB |
59 | acpi_ds_init_buffer_field(u16 aml_opcode, |
60 | union acpi_operand_object *obj_desc, | |
61 | union acpi_operand_object *buffer_desc, | |
62 | union acpi_operand_object *offset_desc, | |
63 | union acpi_operand_object *length_desc, | |
64 | union acpi_operand_object *result_desc); | |
44f6c012 | 65 | |
44f6c012 | 66 | /******************************************************************************* |
1da177e4 LT |
67 | * |
68 | * FUNCTION: acpi_ds_initialize_region | |
69 | * | |
44f6c012 | 70 | * PARAMETERS: obj_handle - Region namespace node |
1da177e4 LT |
71 | * |
72 | * RETURN: Status | |
73 | * | |
74 | * DESCRIPTION: Front end to ev_initialize_region | |
75 | * | |
44f6c012 | 76 | ******************************************************************************/ |
1da177e4 | 77 | |
4be44fcd | 78 | acpi_status acpi_ds_initialize_region(acpi_handle obj_handle) |
1da177e4 | 79 | { |
4be44fcd LB |
80 | union acpi_operand_object *obj_desc; |
81 | acpi_status status; | |
1da177e4 | 82 | |
4be44fcd | 83 | obj_desc = acpi_ns_get_attached_object(obj_handle); |
1da177e4 LT |
84 | |
85 | /* Namespace is NOT locked */ | |
86 | ||
4be44fcd | 87 | status = acpi_ev_initialize_region(obj_desc, FALSE); |
1da177e4 LT |
88 | return (status); |
89 | } | |
90 | ||
44f6c012 | 91 | /******************************************************************************* |
1da177e4 LT |
92 | * |
93 | * FUNCTION: acpi_ds_init_buffer_field | |
94 | * | |
95 | * PARAMETERS: aml_opcode - create_xxx_field | |
96 | * obj_desc - buffer_field object | |
97 | * buffer_desc - Host Buffer | |
98 | * offset_desc - Offset into buffer | |
44f6c012 RM |
99 | * length_desc - Length of field (CREATE_FIELD_OP only) |
100 | * result_desc - Where to store the result | |
1da177e4 LT |
101 | * |
102 | * RETURN: Status | |
103 | * | |
104 | * DESCRIPTION: Perform actual initialization of a buffer field | |
105 | * | |
44f6c012 | 106 | ******************************************************************************/ |
1da177e4 | 107 | |
44f6c012 | 108 | static acpi_status |
4be44fcd LB |
109 | acpi_ds_init_buffer_field(u16 aml_opcode, |
110 | union acpi_operand_object *obj_desc, | |
111 | union acpi_operand_object *buffer_desc, | |
112 | union acpi_operand_object *offset_desc, | |
113 | union acpi_operand_object *length_desc, | |
114 | union acpi_operand_object *result_desc) | |
1da177e4 | 115 | { |
4be44fcd LB |
116 | u32 offset; |
117 | u32 bit_offset; | |
118 | u32 bit_count; | |
119 | u8 field_flags; | |
120 | acpi_status status; | |
1da177e4 | 121 | |
b229cf92 | 122 | ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc); |
1da177e4 LT |
123 | |
124 | /* Host object must be a Buffer */ | |
125 | ||
3371c19c | 126 | if (buffer_desc->common.type != ACPI_TYPE_BUFFER) { |
b8e4d893 BM |
127 | ACPI_ERROR((AE_INFO, |
128 | "Target of Create Field is not a Buffer object - %s", | |
129 | acpi_ut_get_object_type_name(buffer_desc))); | |
1da177e4 LT |
130 | |
131 | status = AE_AML_OPERAND_TYPE; | |
132 | goto cleanup; | |
133 | } | |
134 | ||
135 | /* | |
136 | * The last parameter to all of these opcodes (result_desc) started | |
137 | * out as a name_string, and should therefore now be a NS node | |
138 | * after resolution in acpi_ex_resolve_operands(). | |
139 | */ | |
4be44fcd | 140 | if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) { |
b8e4d893 BM |
141 | ACPI_ERROR((AE_INFO, |
142 | "(%s) destination not a NS Node [%s]", | |
143 | acpi_ps_get_opcode_name(aml_opcode), | |
144 | acpi_ut_get_descriptor_name(result_desc))); | |
1da177e4 LT |
145 | |
146 | status = AE_AML_OPERAND_TYPE; | |
147 | goto cleanup; | |
148 | } | |
149 | ||
150 | offset = (u32) offset_desc->integer.value; | |
151 | ||
152 | /* | |
153 | * Setup the Bit offsets and counts, according to the opcode | |
154 | */ | |
155 | switch (aml_opcode) { | |
156 | case AML_CREATE_FIELD_OP: | |
157 | ||
158 | /* Offset is in bits, count is in bits */ | |
159 | ||
44f6c012 | 160 | field_flags = AML_FIELD_ACCESS_BYTE; |
1da177e4 | 161 | bit_offset = offset; |
4be44fcd | 162 | bit_count = (u32) length_desc->integer.value; |
44f6c012 RM |
163 | |
164 | /* Must have a valid (>0) bit count */ | |
165 | ||
166 | if (bit_count == 0) { | |
b8e4d893 | 167 | ACPI_ERROR((AE_INFO, |
b229cf92 | 168 | "Attempt to CreateField of length zero")); |
44f6c012 RM |
169 | status = AE_AML_OPERAND_VALUE; |
170 | goto cleanup; | |
171 | } | |
1da177e4 LT |
172 | break; |
173 | ||
174 | case AML_CREATE_BIT_FIELD_OP: | |
175 | ||
176 | /* Offset is in bits, Field is one bit */ | |
177 | ||
178 | bit_offset = offset; | |
4be44fcd | 179 | bit_count = 1; |
1da177e4 LT |
180 | field_flags = AML_FIELD_ACCESS_BYTE; |
181 | break; | |
182 | ||
183 | case AML_CREATE_BYTE_FIELD_OP: | |
184 | ||
185 | /* Offset is in bytes, field is one byte */ | |
186 | ||
187 | bit_offset = 8 * offset; | |
4be44fcd | 188 | bit_count = 8; |
1da177e4 LT |
189 | field_flags = AML_FIELD_ACCESS_BYTE; |
190 | break; | |
191 | ||
192 | case AML_CREATE_WORD_FIELD_OP: | |
193 | ||
194 | /* Offset is in bytes, field is one word */ | |
195 | ||
196 | bit_offset = 8 * offset; | |
4be44fcd | 197 | bit_count = 16; |
1da177e4 LT |
198 | field_flags = AML_FIELD_ACCESS_WORD; |
199 | break; | |
200 | ||
201 | case AML_CREATE_DWORD_FIELD_OP: | |
202 | ||
203 | /* Offset is in bytes, field is one dword */ | |
204 | ||
205 | bit_offset = 8 * offset; | |
4be44fcd | 206 | bit_count = 32; |
1da177e4 LT |
207 | field_flags = AML_FIELD_ACCESS_DWORD; |
208 | break; | |
209 | ||
210 | case AML_CREATE_QWORD_FIELD_OP: | |
211 | ||
212 | /* Offset is in bytes, field is one qword */ | |
213 | ||
214 | bit_offset = 8 * offset; | |
4be44fcd | 215 | bit_count = 64; |
1da177e4 LT |
216 | field_flags = AML_FIELD_ACCESS_QWORD; |
217 | break; | |
218 | ||
219 | default: | |
220 | ||
b8e4d893 | 221 | ACPI_ERROR((AE_INFO, |
f6a22b0b BM |
222 | "Unknown field creation opcode 0x%02X", |
223 | aml_opcode)); | |
1da177e4 LT |
224 | status = AE_AML_BAD_OPCODE; |
225 | goto cleanup; | |
226 | } | |
227 | ||
228 | /* Entire field must fit within the current length of the buffer */ | |
229 | ||
4be44fcd | 230 | if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) { |
b8e4d893 | 231 | ACPI_ERROR((AE_INFO, |
f6a22b0b | 232 | "Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)", |
b8e4d893 BM |
233 | acpi_ut_get_node_name(result_desc), |
234 | bit_offset + bit_count, | |
235 | acpi_ut_get_node_name(buffer_desc->buffer.node), | |
236 | 8 * (u32) buffer_desc->buffer.length)); | |
1da177e4 LT |
237 | status = AE_AML_BUFFER_LIMIT; |
238 | goto cleanup; | |
239 | } | |
240 | ||
241 | /* | |
242 | * Initialize areas of the field object that are common to all fields | |
44f6c012 RM |
243 | * For field_flags, use LOCK_RULE = 0 (NO_LOCK), |
244 | * UPDATE_RULE = 0 (UPDATE_PRESERVE) | |
1da177e4 | 245 | */ |
4be44fcd LB |
246 | status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, |
247 | bit_offset, bit_count); | |
248 | if (ACPI_FAILURE(status)) { | |
1da177e4 LT |
249 | goto cleanup; |
250 | } | |
251 | ||
252 | obj_desc->buffer_field.buffer_obj = buffer_desc; | |
253 | ||
254 | /* Reference count for buffer_desc inherits obj_desc count */ | |
255 | ||
44f6c012 | 256 | buffer_desc->common.reference_count = (u16) |
4be44fcd LB |
257 | (buffer_desc->common.reference_count + |
258 | obj_desc->common.reference_count); | |
1da177e4 | 259 | |
4be44fcd | 260 | cleanup: |
1da177e4 LT |
261 | |
262 | /* Always delete the operands */ | |
263 | ||
4be44fcd LB |
264 | acpi_ut_remove_reference(offset_desc); |
265 | acpi_ut_remove_reference(buffer_desc); | |
1da177e4 LT |
266 | |
267 | if (aml_opcode == AML_CREATE_FIELD_OP) { | |
4be44fcd | 268 | acpi_ut_remove_reference(length_desc); |
1da177e4 LT |
269 | } |
270 | ||
271 | /* On failure, delete the result descriptor */ | |
272 | ||
4be44fcd LB |
273 | if (ACPI_FAILURE(status)) { |
274 | acpi_ut_remove_reference(result_desc); /* Result descriptor */ | |
275 | } else { | |
1da177e4 LT |
276 | /* Now the address and length are valid for this buffer_field */ |
277 | ||
278 | obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; | |
279 | } | |
280 | ||
4be44fcd | 281 | return_ACPI_STATUS(status); |
1da177e4 LT |
282 | } |
283 | ||
44f6c012 | 284 | /******************************************************************************* |
1da177e4 LT |
285 | * |
286 | * FUNCTION: acpi_ds_eval_buffer_field_operands | |
287 | * | |
288 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 289 | * op - A valid buffer_field Op object |
1da177e4 LT |
290 | * |
291 | * RETURN: Status | |
292 | * | |
293 | * DESCRIPTION: Get buffer_field Buffer and Index | |
294 | * Called from acpi_ds_exec_end_op during buffer_field parse tree walk | |
295 | * | |
44f6c012 | 296 | ******************************************************************************/ |
1da177e4 LT |
297 | |
298 | acpi_status | |
4be44fcd LB |
299 | acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, |
300 | union acpi_parse_object *op) | |
1da177e4 | 301 | { |
4be44fcd LB |
302 | acpi_status status; |
303 | union acpi_operand_object *obj_desc; | |
304 | struct acpi_namespace_node *node; | |
305 | union acpi_parse_object *next_op; | |
1da177e4 | 306 | |
b229cf92 | 307 | ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); |
1da177e4 LT |
308 | |
309 | /* | |
310 | * This is where we evaluate the address and length fields of the | |
311 | * create_xxx_field declaration | |
312 | */ | |
4be44fcd | 313 | node = op->common.node; |
1da177e4 LT |
314 | |
315 | /* next_op points to the op that holds the Buffer */ | |
316 | ||
317 | next_op = op->common.value.arg; | |
318 | ||
319 | /* Evaluate/create the address and length operands */ | |
320 | ||
4be44fcd LB |
321 | status = acpi_ds_create_operands(walk_state, next_op); |
322 | if (ACPI_FAILURE(status)) { | |
323 | return_ACPI_STATUS(status); | |
1da177e4 LT |
324 | } |
325 | ||
4be44fcd | 326 | obj_desc = acpi_ns_get_attached_object(node); |
1da177e4 | 327 | if (!obj_desc) { |
4be44fcd | 328 | return_ACPI_STATUS(AE_NOT_EXIST); |
1da177e4 LT |
329 | } |
330 | ||
331 | /* Resolve the operands */ | |
332 | ||
4be44fcd LB |
333 | status = acpi_ex_resolve_operands(op->common.aml_opcode, |
334 | ACPI_WALK_OPERANDS, walk_state); | |
4be44fcd | 335 | if (ACPI_FAILURE(status)) { |
f6a22b0b | 336 | ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X", |
b8e4d893 BM |
337 | acpi_ps_get_opcode_name(op->common.aml_opcode), |
338 | status)); | |
1da177e4 | 339 | |
4be44fcd | 340 | return_ACPI_STATUS(status); |
1da177e4 LT |
341 | } |
342 | ||
343 | /* Initialize the Buffer Field */ | |
344 | ||
345 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { | |
52fc0b02 | 346 | |
1da177e4 LT |
347 | /* NOTE: Slightly different operands for this opcode */ |
348 | ||
4be44fcd LB |
349 | status = |
350 | acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, | |
351 | walk_state->operands[0], | |
352 | walk_state->operands[1], | |
353 | walk_state->operands[2], | |
354 | walk_state->operands[3]); | |
355 | } else { | |
1da177e4 LT |
356 | /* All other, create_xxx_field opcodes */ |
357 | ||
4be44fcd LB |
358 | status = |
359 | acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, | |
360 | walk_state->operands[0], | |
361 | walk_state->operands[1], NULL, | |
362 | walk_state->operands[2]); | |
1da177e4 LT |
363 | } |
364 | ||
4be44fcd | 365 | return_ACPI_STATUS(status); |
1da177e4 LT |
366 | } |
367 | ||
44f6c012 | 368 | /******************************************************************************* |
1da177e4 LT |
369 | * |
370 | * FUNCTION: acpi_ds_eval_region_operands | |
371 | * | |
372 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 373 | * op - A valid region Op object |
1da177e4 LT |
374 | * |
375 | * RETURN: Status | |
376 | * | |
377 | * DESCRIPTION: Get region address and length | |
378 | * Called from acpi_ds_exec_end_op during op_region parse tree walk | |
379 | * | |
44f6c012 | 380 | ******************************************************************************/ |
1da177e4 LT |
381 | |
382 | acpi_status | |
4be44fcd LB |
383 | acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, |
384 | union acpi_parse_object *op) | |
1da177e4 | 385 | { |
4be44fcd LB |
386 | acpi_status status; |
387 | union acpi_operand_object *obj_desc; | |
388 | union acpi_operand_object *operand_desc; | |
389 | struct acpi_namespace_node *node; | |
390 | union acpi_parse_object *next_op; | |
1da177e4 | 391 | |
b229cf92 | 392 | ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); |
1da177e4 LT |
393 | |
394 | /* | |
44f6c012 RM |
395 | * This is where we evaluate the address and length fields of the |
396 | * op_region declaration | |
1da177e4 | 397 | */ |
4be44fcd | 398 | node = op->common.node; |
1da177e4 | 399 | |
ba494bee | 400 | /* next_op points to the op that holds the space_ID */ |
1da177e4 LT |
401 | |
402 | next_op = op->common.value.arg; | |
403 | ||
404 | /* next_op points to address op */ | |
405 | ||
406 | next_op = next_op->common.next; | |
407 | ||
408 | /* Evaluate/create the address and length operands */ | |
409 | ||
4be44fcd LB |
410 | status = acpi_ds_create_operands(walk_state, next_op); |
411 | if (ACPI_FAILURE(status)) { | |
412 | return_ACPI_STATUS(status); | |
1da177e4 LT |
413 | } |
414 | ||
415 | /* Resolve the length and address operands to numbers */ | |
416 | ||
4be44fcd LB |
417 | status = acpi_ex_resolve_operands(op->common.aml_opcode, |
418 | ACPI_WALK_OPERANDS, walk_state); | |
419 | if (ACPI_FAILURE(status)) { | |
420 | return_ACPI_STATUS(status); | |
1da177e4 LT |
421 | } |
422 | ||
4be44fcd | 423 | obj_desc = acpi_ns_get_attached_object(node); |
1da177e4 | 424 | if (!obj_desc) { |
4be44fcd | 425 | return_ACPI_STATUS(AE_NOT_EXIST); |
1da177e4 LT |
426 | } |
427 | ||
428 | /* | |
429 | * Get the length operand and save it | |
430 | * (at Top of stack) | |
431 | */ | |
432 | operand_desc = walk_state->operands[walk_state->num_operands - 1]; | |
433 | ||
434 | obj_desc->region.length = (u32) operand_desc->integer.value; | |
4be44fcd | 435 | acpi_ut_remove_reference(operand_desc); |
1da177e4 LT |
436 | |
437 | /* | |
438 | * Get the address and save it | |
439 | * (at top of stack - 1) | |
440 | */ | |
441 | operand_desc = walk_state->operands[walk_state->num_operands - 2]; | |
442 | ||
44f6c012 | 443 | obj_desc->region.address = (acpi_physical_address) |
4be44fcd LB |
444 | operand_desc->integer.value; |
445 | acpi_ut_remove_reference(operand_desc); | |
1da177e4 | 446 | |
b229cf92 | 447 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", |
4be44fcd | 448 | obj_desc, |
b7f9f042 | 449 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), |
4be44fcd | 450 | obj_desc->region.length)); |
1da177e4 LT |
451 | |
452 | /* Now the address and length are valid for this opregion */ | |
453 | ||
454 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | |
455 | ||
4be44fcd | 456 | return_ACPI_STATUS(status); |
1da177e4 LT |
457 | } |
458 | ||
941f48bb LM |
459 | /******************************************************************************* |
460 | * | |
461 | * FUNCTION: acpi_ds_eval_table_region_operands | |
462 | * | |
463 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 464 | * op - A valid region Op object |
941f48bb LM |
465 | * |
466 | * RETURN: Status | |
467 | * | |
9ad19ac4 BM |
468 | * DESCRIPTION: Get region address and length. |
469 | * Called from acpi_ds_exec_end_op during data_table_region parse | |
470 | * tree walk. | |
941f48bb LM |
471 | * |
472 | ******************************************************************************/ | |
473 | ||
474 | acpi_status | |
475 | acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, | |
476 | union acpi_parse_object *op) | |
477 | { | |
478 | acpi_status status; | |
479 | union acpi_operand_object *obj_desc; | |
480 | union acpi_operand_object **operand; | |
481 | struct acpi_namespace_node *node; | |
482 | union acpi_parse_object *next_op; | |
67a119f9 | 483 | u32 table_index; |
941f48bb LM |
484 | struct acpi_table_header *table; |
485 | ||
486 | ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); | |
487 | ||
488 | /* | |
489 | * This is where we evaluate the signature_string and oem_iDString | |
490 | * and oem_table_iDString of the data_table_region declaration | |
491 | */ | |
492 | node = op->common.node; | |
493 | ||
494 | /* next_op points to signature_string op */ | |
495 | ||
496 | next_op = op->common.value.arg; | |
497 | ||
498 | /* | |
499 | * Evaluate/create the signature_string and oem_iDString | |
500 | * and oem_table_iDString operands | |
501 | */ | |
502 | status = acpi_ds_create_operands(walk_state, next_op); | |
503 | if (ACPI_FAILURE(status)) { | |
504 | return_ACPI_STATUS(status); | |
505 | } | |
506 | ||
507 | /* | |
508 | * Resolve the signature_string and oem_iDString | |
509 | * and oem_table_iDString operands | |
510 | */ | |
511 | status = acpi_ex_resolve_operands(op->common.aml_opcode, | |
512 | ACPI_WALK_OPERANDS, walk_state); | |
513 | if (ACPI_FAILURE(status)) { | |
514 | return_ACPI_STATUS(status); | |
515 | } | |
516 | ||
941f48bb LM |
517 | operand = &walk_state->operands[0]; |
518 | ||
519 | /* Find the ACPI table */ | |
520 | ||
521 | status = acpi_tb_find_table(operand[0]->string.pointer, | |
522 | operand[1]->string.pointer, | |
523 | operand[2]->string.pointer, &table_index); | |
524 | if (ACPI_FAILURE(status)) { | |
525 | return_ACPI_STATUS(status); | |
526 | } | |
527 | ||
528 | acpi_ut_remove_reference(operand[0]); | |
529 | acpi_ut_remove_reference(operand[1]); | |
530 | acpi_ut_remove_reference(operand[2]); | |
531 | ||
532 | status = acpi_get_table_by_index(table_index, &table); | |
533 | if (ACPI_FAILURE(status)) { | |
534 | return_ACPI_STATUS(status); | |
535 | } | |
536 | ||
537 | obj_desc = acpi_ns_get_attached_object(node); | |
538 | if (!obj_desc) { | |
539 | return_ACPI_STATUS(AE_NOT_EXIST); | |
540 | } | |
541 | ||
542 | obj_desc->region.address = | |
543 | (acpi_physical_address) ACPI_TO_INTEGER(table); | |
544 | obj_desc->region.length = table->length; | |
545 | ||
546 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | |
547 | obj_desc, | |
548 | ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address), | |
549 | obj_desc->region.length)); | |
550 | ||
551 | /* Now the address and length are valid for this opregion */ | |
552 | ||
553 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | |
554 | ||
555 | return_ACPI_STATUS(status); | |
556 | } | |
557 | ||
44f6c012 | 558 | /******************************************************************************* |
1da177e4 LT |
559 | * |
560 | * FUNCTION: acpi_ds_eval_data_object_operands | |
561 | * | |
562 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 563 | * op - A valid data_object Op object |
1da177e4 LT |
564 | * obj_desc - data_object |
565 | * | |
566 | * RETURN: Status | |
567 | * | |
568 | * DESCRIPTION: Get the operands and complete the following data object types: | |
569 | * Buffer, Package. | |
570 | * | |
44f6c012 | 571 | ******************************************************************************/ |
1da177e4 LT |
572 | |
573 | acpi_status | |
4be44fcd LB |
574 | acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, |
575 | union acpi_parse_object *op, | |
576 | union acpi_operand_object *obj_desc) | |
1da177e4 | 577 | { |
4be44fcd LB |
578 | acpi_status status; |
579 | union acpi_operand_object *arg_desc; | |
580 | u32 length; | |
1da177e4 | 581 | |
b229cf92 | 582 | ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); |
1da177e4 LT |
583 | |
584 | /* The first operand (for all of these data objects) is the length */ | |
585 | ||
773069d4 BM |
586 | /* |
587 | * Set proper index into operand stack for acpi_ds_obj_stack_push | |
588 | * invoked inside acpi_ds_create_operand. | |
589 | */ | |
590 | walk_state->operand_index = walk_state->num_operands; | |
591 | ||
4be44fcd LB |
592 | status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); |
593 | if (ACPI_FAILURE(status)) { | |
594 | return_ACPI_STATUS(status); | |
1da177e4 LT |
595 | } |
596 | ||
4be44fcd LB |
597 | status = acpi_ex_resolve_operands(walk_state->opcode, |
598 | &(walk_state-> | |
599 | operands[walk_state->num_operands - | |
600 | 1]), walk_state); | |
601 | if (ACPI_FAILURE(status)) { | |
602 | return_ACPI_STATUS(status); | |
1da177e4 LT |
603 | } |
604 | ||
605 | /* Extract length operand */ | |
606 | ||
4be44fcd | 607 | arg_desc = walk_state->operands[walk_state->num_operands - 1]; |
1da177e4 LT |
608 | length = (u32) arg_desc->integer.value; |
609 | ||
610 | /* Cleanup for length operand */ | |
611 | ||
4be44fcd LB |
612 | status = acpi_ds_obj_stack_pop(1, walk_state); |
613 | if (ACPI_FAILURE(status)) { | |
614 | return_ACPI_STATUS(status); | |
1da177e4 LT |
615 | } |
616 | ||
4be44fcd | 617 | acpi_ut_remove_reference(arg_desc); |
1da177e4 LT |
618 | |
619 | /* | |
620 | * Create the actual data object | |
621 | */ | |
622 | switch (op->common.aml_opcode) { | |
623 | case AML_BUFFER_OP: | |
624 | ||
4be44fcd LB |
625 | status = |
626 | acpi_ds_build_internal_buffer_obj(walk_state, op, length, | |
627 | &obj_desc); | |
1da177e4 LT |
628 | break; |
629 | ||
630 | case AML_PACKAGE_OP: | |
631 | case AML_VAR_PACKAGE_OP: | |
632 | ||
4be44fcd LB |
633 | status = |
634 | acpi_ds_build_internal_package_obj(walk_state, op, length, | |
635 | &obj_desc); | |
1da177e4 LT |
636 | break; |
637 | ||
638 | default: | |
4be44fcd | 639 | return_ACPI_STATUS(AE_AML_BAD_OPCODE); |
1da177e4 LT |
640 | } |
641 | ||
4be44fcd | 642 | if (ACPI_SUCCESS(status)) { |
1da177e4 | 643 | /* |
44f6c012 | 644 | * Return the object in the walk_state, unless the parent is a package - |
1da177e4 LT |
645 | * in this case, the return object will be stored in the parse tree |
646 | * for the package. | |
647 | */ | |
648 | if ((!op->common.parent) || | |
4be44fcd LB |
649 | ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && |
650 | (op->common.parent->common.aml_opcode != | |
651 | AML_VAR_PACKAGE_OP) | |
1f86e8c1 LZ |
652 | && (op->common.parent->common.aml_opcode != |
653 | AML_NAME_OP))) { | |
1da177e4 LT |
654 | walk_state->result_obj = obj_desc; |
655 | } | |
656 | } | |
657 | ||
4be44fcd | 658 | return_ACPI_STATUS(status); |
1da177e4 LT |
659 | } |
660 | ||
ef805d95 LM |
661 | /******************************************************************************* |
662 | * | |
663 | * FUNCTION: acpi_ds_eval_bank_field_operands | |
664 | * | |
665 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 666 | * op - A valid bank_field Op object |
ef805d95 LM |
667 | * |
668 | * RETURN: Status | |
669 | * | |
670 | * DESCRIPTION: Get bank_field bank_value | |
671 | * Called from acpi_ds_exec_end_op during bank_field parse tree walk | |
672 | * | |
673 | ******************************************************************************/ | |
674 | ||
675 | acpi_status | |
676 | acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | |
677 | union acpi_parse_object *op) | |
678 | { | |
679 | acpi_status status; | |
680 | union acpi_operand_object *obj_desc; | |
681 | union acpi_operand_object *operand_desc; | |
682 | struct acpi_namespace_node *node; | |
683 | union acpi_parse_object *next_op; | |
684 | union acpi_parse_object *arg; | |
685 | ||
686 | ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); | |
687 | ||
688 | /* | |
689 | * This is where we evaluate the bank_value field of the | |
690 | * bank_field declaration | |
691 | */ | |
692 | ||
693 | /* next_op points to the op that holds the Region */ | |
694 | ||
695 | next_op = op->common.value.arg; | |
696 | ||
697 | /* next_op points to the op that holds the Bank Register */ | |
698 | ||
699 | next_op = next_op->common.next; | |
700 | ||
701 | /* next_op points to the op that holds the Bank Value */ | |
702 | ||
703 | next_op = next_op->common.next; | |
704 | ||
705 | /* | |
706 | * Set proper index into operand stack for acpi_ds_obj_stack_push | |
707 | * invoked inside acpi_ds_create_operand. | |
708 | * | |
709 | * We use walk_state->Operands[0] to store the evaluated bank_value | |
710 | */ | |
711 | walk_state->operand_index = 0; | |
712 | ||
713 | status = acpi_ds_create_operand(walk_state, next_op, 0); | |
714 | if (ACPI_FAILURE(status)) { | |
715 | return_ACPI_STATUS(status); | |
716 | } | |
717 | ||
718 | status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); | |
719 | if (ACPI_FAILURE(status)) { | |
720 | return_ACPI_STATUS(status); | |
721 | } | |
722 | ||
71d993e1 BM |
723 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, |
724 | acpi_ps_get_opcode_name(op->common.aml_opcode), 1); | |
ef805d95 LM |
725 | /* |
726 | * Get the bank_value operand and save it | |
727 | * (at Top of stack) | |
728 | */ | |
729 | operand_desc = walk_state->operands[0]; | |
730 | ||
731 | /* Arg points to the start Bank Field */ | |
732 | ||
733 | arg = acpi_ps_get_arg(op, 4); | |
734 | while (arg) { | |
735 | ||
736 | /* Ignore OFFSET and ACCESSAS terms here */ | |
737 | ||
738 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | |
739 | node = arg->common.node; | |
740 | ||
741 | obj_desc = acpi_ns_get_attached_object(node); | |
742 | if (!obj_desc) { | |
743 | return_ACPI_STATUS(AE_NOT_EXIST); | |
744 | } | |
745 | ||
746 | obj_desc->bank_field.value = | |
747 | (u32) operand_desc->integer.value; | |
748 | } | |
749 | ||
750 | /* Move to next field in the list */ | |
751 | ||
752 | arg = arg->common.next; | |
753 | } | |
754 | ||
755 | acpi_ut_remove_reference(operand_desc); | |
756 | return_ACPI_STATUS(status); | |
757 | } |