]>
Commit | Line | Data |
---|---|---|
1da177e4 LT |
1 | /****************************************************************************** |
2 | * | |
02582e9b | 3 | * Module Name: dsopcode - Dispatcher support for regions and fields |
1da177e4 LT |
4 | * |
5 | *****************************************************************************/ | |
6 | ||
7 | /* | |
c8100dc4 | 8 | * Copyright (C) 2000 - 2016, 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 | ||
760235cd | 87 | status = acpi_ev_initialize_region(obj_desc); |
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 | */ |
1fad8738 BM |
246 | status = |
247 | acpi_ex_prep_common_field_object(obj_desc, field_flags, 0, | |
248 | bit_offset, bit_count); | |
4be44fcd | 249 | if (ACPI_FAILURE(status)) { |
1da177e4 LT |
250 | goto cleanup; |
251 | } | |
252 | ||
253 | obj_desc->buffer_field.buffer_obj = buffer_desc; | |
254 | ||
255 | /* Reference count for buffer_desc inherits obj_desc count */ | |
256 | ||
44f6c012 | 257 | buffer_desc->common.reference_count = (u16) |
4be44fcd LB |
258 | (buffer_desc->common.reference_count + |
259 | obj_desc->common.reference_count); | |
1da177e4 | 260 | |
10622bf8 | 261 | cleanup: |
1da177e4 LT |
262 | |
263 | /* Always delete the operands */ | |
264 | ||
4be44fcd LB |
265 | acpi_ut_remove_reference(offset_desc); |
266 | acpi_ut_remove_reference(buffer_desc); | |
1da177e4 LT |
267 | |
268 | if (aml_opcode == AML_CREATE_FIELD_OP) { | |
4be44fcd | 269 | acpi_ut_remove_reference(length_desc); |
1da177e4 LT |
270 | } |
271 | ||
272 | /* On failure, delete the result descriptor */ | |
273 | ||
4be44fcd LB |
274 | if (ACPI_FAILURE(status)) { |
275 | acpi_ut_remove_reference(result_desc); /* Result descriptor */ | |
276 | } else { | |
1da177e4 LT |
277 | /* Now the address and length are valid for this buffer_field */ |
278 | ||
279 | obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID; | |
280 | } | |
281 | ||
4be44fcd | 282 | return_ACPI_STATUS(status); |
1da177e4 LT |
283 | } |
284 | ||
44f6c012 | 285 | /******************************************************************************* |
1da177e4 LT |
286 | * |
287 | * FUNCTION: acpi_ds_eval_buffer_field_operands | |
288 | * | |
289 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 290 | * op - A valid buffer_field Op object |
1da177e4 LT |
291 | * |
292 | * RETURN: Status | |
293 | * | |
294 | * DESCRIPTION: Get buffer_field Buffer and Index | |
295 | * Called from acpi_ds_exec_end_op during buffer_field parse tree walk | |
296 | * | |
44f6c012 | 297 | ******************************************************************************/ |
1da177e4 LT |
298 | |
299 | acpi_status | |
4be44fcd LB |
300 | acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state, |
301 | union acpi_parse_object *op) | |
1da177e4 | 302 | { |
4be44fcd LB |
303 | acpi_status status; |
304 | union acpi_operand_object *obj_desc; | |
305 | struct acpi_namespace_node *node; | |
306 | union acpi_parse_object *next_op; | |
1da177e4 | 307 | |
b229cf92 | 308 | ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op); |
1da177e4 LT |
309 | |
310 | /* | |
311 | * This is where we evaluate the address and length fields of the | |
312 | * create_xxx_field declaration | |
313 | */ | |
4be44fcd | 314 | node = op->common.node; |
1da177e4 LT |
315 | |
316 | /* next_op points to the op that holds the Buffer */ | |
317 | ||
318 | next_op = op->common.value.arg; | |
319 | ||
320 | /* Evaluate/create the address and length operands */ | |
321 | ||
4be44fcd LB |
322 | status = acpi_ds_create_operands(walk_state, next_op); |
323 | if (ACPI_FAILURE(status)) { | |
324 | return_ACPI_STATUS(status); | |
1da177e4 LT |
325 | } |
326 | ||
4be44fcd | 327 | obj_desc = acpi_ns_get_attached_object(node); |
1da177e4 | 328 | if (!obj_desc) { |
4be44fcd | 329 | return_ACPI_STATUS(AE_NOT_EXIST); |
1da177e4 LT |
330 | } |
331 | ||
332 | /* Resolve the operands */ | |
333 | ||
1fad8738 BM |
334 | status = |
335 | acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, | |
336 | walk_state); | |
4be44fcd | 337 | if (ACPI_FAILURE(status)) { |
f6a22b0b | 338 | ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X", |
b8e4d893 BM |
339 | acpi_ps_get_opcode_name(op->common.aml_opcode), |
340 | status)); | |
1da177e4 | 341 | |
4be44fcd | 342 | return_ACPI_STATUS(status); |
1da177e4 LT |
343 | } |
344 | ||
345 | /* Initialize the Buffer Field */ | |
346 | ||
347 | if (op->common.aml_opcode == AML_CREATE_FIELD_OP) { | |
52fc0b02 | 348 | |
1da177e4 LT |
349 | /* NOTE: Slightly different operands for this opcode */ |
350 | ||
4be44fcd LB |
351 | status = |
352 | acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, | |
353 | walk_state->operands[0], | |
354 | walk_state->operands[1], | |
355 | walk_state->operands[2], | |
356 | walk_state->operands[3]); | |
357 | } else { | |
1da177e4 LT |
358 | /* All other, create_xxx_field opcodes */ |
359 | ||
4be44fcd LB |
360 | status = |
361 | acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc, | |
362 | walk_state->operands[0], | |
363 | walk_state->operands[1], NULL, | |
364 | walk_state->operands[2]); | |
1da177e4 LT |
365 | } |
366 | ||
4be44fcd | 367 | return_ACPI_STATUS(status); |
1da177e4 LT |
368 | } |
369 | ||
44f6c012 | 370 | /******************************************************************************* |
1da177e4 LT |
371 | * |
372 | * FUNCTION: acpi_ds_eval_region_operands | |
373 | * | |
374 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 375 | * op - A valid region Op object |
1da177e4 LT |
376 | * |
377 | * RETURN: Status | |
378 | * | |
379 | * DESCRIPTION: Get region address and length | |
380 | * Called from acpi_ds_exec_end_op during op_region parse tree walk | |
381 | * | |
44f6c012 | 382 | ******************************************************************************/ |
1da177e4 LT |
383 | |
384 | acpi_status | |
4be44fcd LB |
385 | acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state, |
386 | union acpi_parse_object *op) | |
1da177e4 | 387 | { |
4be44fcd LB |
388 | acpi_status status; |
389 | union acpi_operand_object *obj_desc; | |
390 | union acpi_operand_object *operand_desc; | |
391 | struct acpi_namespace_node *node; | |
392 | union acpi_parse_object *next_op; | |
1da177e4 | 393 | |
b229cf92 | 394 | ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op); |
1da177e4 LT |
395 | |
396 | /* | |
44f6c012 RM |
397 | * This is where we evaluate the address and length fields of the |
398 | * op_region declaration | |
1da177e4 | 399 | */ |
4be44fcd | 400 | node = op->common.node; |
1da177e4 | 401 | |
ba494bee | 402 | /* next_op points to the op that holds the space_ID */ |
1da177e4 LT |
403 | |
404 | next_op = op->common.value.arg; | |
405 | ||
406 | /* next_op points to address op */ | |
407 | ||
408 | next_op = next_op->common.next; | |
409 | ||
410 | /* Evaluate/create the address and length operands */ | |
411 | ||
4be44fcd LB |
412 | status = acpi_ds_create_operands(walk_state, next_op); |
413 | if (ACPI_FAILURE(status)) { | |
414 | return_ACPI_STATUS(status); | |
1da177e4 LT |
415 | } |
416 | ||
417 | /* Resolve the length and address operands to numbers */ | |
418 | ||
1fad8738 BM |
419 | status = |
420 | acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, | |
421 | walk_state); | |
4be44fcd LB |
422 | if (ACPI_FAILURE(status)) { |
423 | return_ACPI_STATUS(status); | |
1da177e4 LT |
424 | } |
425 | ||
4be44fcd | 426 | obj_desc = acpi_ns_get_attached_object(node); |
1da177e4 | 427 | if (!obj_desc) { |
4be44fcd | 428 | return_ACPI_STATUS(AE_NOT_EXIST); |
1da177e4 LT |
429 | } |
430 | ||
431 | /* | |
432 | * Get the length operand and save it | |
433 | * (at Top of stack) | |
434 | */ | |
435 | operand_desc = walk_state->operands[walk_state->num_operands - 1]; | |
436 | ||
437 | obj_desc->region.length = (u32) operand_desc->integer.value; | |
4be44fcd | 438 | acpi_ut_remove_reference(operand_desc); |
1da177e4 LT |
439 | |
440 | /* | |
441 | * Get the address and save it | |
442 | * (at top of stack - 1) | |
443 | */ | |
444 | operand_desc = walk_state->operands[walk_state->num_operands - 2]; | |
445 | ||
44f6c012 | 446 | obj_desc->region.address = (acpi_physical_address) |
4be44fcd LB |
447 | operand_desc->integer.value; |
448 | acpi_ut_remove_reference(operand_desc); | |
1da177e4 | 449 | |
b229cf92 | 450 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", |
4be44fcd | 451 | obj_desc, |
1d0a0b2f | 452 | ACPI_FORMAT_UINT64(obj_desc->region.address), |
4be44fcd | 453 | obj_desc->region.length)); |
1da177e4 LT |
454 | |
455 | /* Now the address and length are valid for this opregion */ | |
456 | ||
457 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | |
4be44fcd | 458 | return_ACPI_STATUS(status); |
1da177e4 LT |
459 | } |
460 | ||
941f48bb LM |
461 | /******************************************************************************* |
462 | * | |
463 | * FUNCTION: acpi_ds_eval_table_region_operands | |
464 | * | |
465 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 466 | * op - A valid region Op object |
941f48bb LM |
467 | * |
468 | * RETURN: Status | |
469 | * | |
9ad19ac4 BM |
470 | * DESCRIPTION: Get region address and length. |
471 | * Called from acpi_ds_exec_end_op during data_table_region parse | |
472 | * tree walk. | |
941f48bb LM |
473 | * |
474 | ******************************************************************************/ | |
475 | ||
476 | acpi_status | |
477 | acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state, | |
478 | union acpi_parse_object *op) | |
479 | { | |
480 | acpi_status status; | |
481 | union acpi_operand_object *obj_desc; | |
482 | union acpi_operand_object **operand; | |
483 | struct acpi_namespace_node *node; | |
484 | union acpi_parse_object *next_op; | |
941f48bb | 485 | struct acpi_table_header *table; |
9f41fd8a | 486 | u32 table_index; |
941f48bb LM |
487 | |
488 | ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op); | |
489 | ||
490 | /* | |
75c8044f LZ |
491 | * This is where we evaluate the Signature string, oem_id string, |
492 | * and oem_table_id string of the Data Table Region declaration | |
941f48bb LM |
493 | */ |
494 | node = op->common.node; | |
495 | ||
75c8044f | 496 | /* next_op points to Signature string op */ |
941f48bb LM |
497 | |
498 | next_op = op->common.value.arg; | |
499 | ||
500 | /* | |
75c8044f LZ |
501 | * Evaluate/create the Signature string, oem_id string, |
502 | * and oem_table_id string operands | |
941f48bb LM |
503 | */ |
504 | status = acpi_ds_create_operands(walk_state, next_op); | |
505 | if (ACPI_FAILURE(status)) { | |
506 | return_ACPI_STATUS(status); | |
507 | } | |
508 | ||
9f41fd8a BM |
509 | operand = &walk_state->operands[0]; |
510 | ||
941f48bb | 511 | /* |
75c8044f LZ |
512 | * Resolve the Signature string, oem_id string, |
513 | * and oem_table_id string operands | |
941f48bb | 514 | */ |
1fad8738 BM |
515 | status = |
516 | acpi_ex_resolve_operands(op->common.aml_opcode, ACPI_WALK_OPERANDS, | |
517 | walk_state); | |
941f48bb | 518 | if (ACPI_FAILURE(status)) { |
9f41fd8a | 519 | goto cleanup; |
941f48bb LM |
520 | } |
521 | ||
941f48bb LM |
522 | /* Find the ACPI table */ |
523 | ||
524 | status = acpi_tb_find_table(operand[0]->string.pointer, | |
525 | operand[1]->string.pointer, | |
526 | operand[2]->string.pointer, &table_index); | |
527 | if (ACPI_FAILURE(status)) { | |
9f41fd8a BM |
528 | if (status == AE_NOT_FOUND) { |
529 | ACPI_ERROR((AE_INFO, | |
530 | "ACPI Table [%4.4s] OEM:(%s, %s) not found in RSDT/XSDT", | |
531 | operand[0]->string.pointer, | |
532 | operand[1]->string.pointer, | |
533 | operand[2]->string.pointer)); | |
534 | } | |
535 | goto cleanup; | |
941f48bb LM |
536 | } |
537 | ||
941f48bb LM |
538 | status = acpi_get_table_by_index(table_index, &table); |
539 | if (ACPI_FAILURE(status)) { | |
9f41fd8a | 540 | goto cleanup; |
941f48bb LM |
541 | } |
542 | ||
543 | obj_desc = acpi_ns_get_attached_object(node); | |
544 | if (!obj_desc) { | |
9f41fd8a BM |
545 | status = AE_NOT_EXIST; |
546 | goto cleanup; | |
941f48bb LM |
547 | } |
548 | ||
6d3fd3cc | 549 | obj_desc->region.address = ACPI_PTR_TO_PHYSADDR(table); |
941f48bb LM |
550 | obj_desc->region.length = table->length; |
551 | ||
552 | ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n", | |
553 | obj_desc, | |
1d0a0b2f | 554 | ACPI_FORMAT_UINT64(obj_desc->region.address), |
941f48bb LM |
555 | obj_desc->region.length)); |
556 | ||
557 | /* Now the address and length are valid for this opregion */ | |
558 | ||
559 | obj_desc->region.flags |= AOPOBJ_DATA_VALID; | |
560 | ||
9f41fd8a BM |
561 | cleanup: |
562 | acpi_ut_remove_reference(operand[0]); | |
563 | acpi_ut_remove_reference(operand[1]); | |
564 | acpi_ut_remove_reference(operand[2]); | |
565 | ||
941f48bb LM |
566 | return_ACPI_STATUS(status); |
567 | } | |
568 | ||
44f6c012 | 569 | /******************************************************************************* |
1da177e4 LT |
570 | * |
571 | * FUNCTION: acpi_ds_eval_data_object_operands | |
572 | * | |
573 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 574 | * op - A valid data_object Op object |
1da177e4 LT |
575 | * obj_desc - data_object |
576 | * | |
577 | * RETURN: Status | |
578 | * | |
579 | * DESCRIPTION: Get the operands and complete the following data object types: | |
580 | * Buffer, Package. | |
581 | * | |
44f6c012 | 582 | ******************************************************************************/ |
1da177e4 LT |
583 | |
584 | acpi_status | |
4be44fcd LB |
585 | acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state, |
586 | union acpi_parse_object *op, | |
587 | union acpi_operand_object *obj_desc) | |
1da177e4 | 588 | { |
4be44fcd LB |
589 | acpi_status status; |
590 | union acpi_operand_object *arg_desc; | |
591 | u32 length; | |
1da177e4 | 592 | |
b229cf92 | 593 | ACPI_FUNCTION_TRACE(ds_eval_data_object_operands); |
1da177e4 LT |
594 | |
595 | /* The first operand (for all of these data objects) is the length */ | |
596 | ||
773069d4 BM |
597 | /* |
598 | * Set proper index into operand stack for acpi_ds_obj_stack_push | |
599 | * invoked inside acpi_ds_create_operand. | |
600 | */ | |
601 | walk_state->operand_index = walk_state->num_operands; | |
602 | ||
4be44fcd LB |
603 | status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1); |
604 | if (ACPI_FAILURE(status)) { | |
605 | return_ACPI_STATUS(status); | |
1da177e4 LT |
606 | } |
607 | ||
4be44fcd LB |
608 | status = acpi_ex_resolve_operands(walk_state->opcode, |
609 | &(walk_state-> | |
610 | operands[walk_state->num_operands - | |
611 | 1]), walk_state); | |
612 | if (ACPI_FAILURE(status)) { | |
613 | return_ACPI_STATUS(status); | |
1da177e4 LT |
614 | } |
615 | ||
616 | /* Extract length operand */ | |
617 | ||
4be44fcd | 618 | arg_desc = walk_state->operands[walk_state->num_operands - 1]; |
1da177e4 LT |
619 | length = (u32) arg_desc->integer.value; |
620 | ||
621 | /* Cleanup for length operand */ | |
622 | ||
4be44fcd LB |
623 | status = acpi_ds_obj_stack_pop(1, walk_state); |
624 | if (ACPI_FAILURE(status)) { | |
625 | return_ACPI_STATUS(status); | |
1da177e4 LT |
626 | } |
627 | ||
4be44fcd | 628 | acpi_ut_remove_reference(arg_desc); |
1da177e4 LT |
629 | |
630 | /* | |
631 | * Create the actual data object | |
632 | */ | |
633 | switch (op->common.aml_opcode) { | |
634 | case AML_BUFFER_OP: | |
635 | ||
4be44fcd LB |
636 | status = |
637 | acpi_ds_build_internal_buffer_obj(walk_state, op, length, | |
638 | &obj_desc); | |
1da177e4 LT |
639 | break; |
640 | ||
641 | case AML_PACKAGE_OP: | |
642 | case AML_VAR_PACKAGE_OP: | |
643 | ||
4be44fcd LB |
644 | status = |
645 | acpi_ds_build_internal_package_obj(walk_state, op, length, | |
646 | &obj_desc); | |
1da177e4 LT |
647 | break; |
648 | ||
649 | default: | |
1d1ea1b7 | 650 | |
4be44fcd | 651 | return_ACPI_STATUS(AE_AML_BAD_OPCODE); |
1da177e4 LT |
652 | } |
653 | ||
4be44fcd | 654 | if (ACPI_SUCCESS(status)) { |
1da177e4 | 655 | /* |
44f6c012 | 656 | * Return the object in the walk_state, unless the parent is a package - |
1da177e4 LT |
657 | * in this case, the return object will be stored in the parse tree |
658 | * for the package. | |
659 | */ | |
660 | if ((!op->common.parent) || | |
4be44fcd LB |
661 | ((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) && |
662 | (op->common.parent->common.aml_opcode != | |
663 | AML_VAR_PACKAGE_OP) | |
1f86e8c1 LZ |
664 | && (op->common.parent->common.aml_opcode != |
665 | AML_NAME_OP))) { | |
1da177e4 LT |
666 | walk_state->result_obj = obj_desc; |
667 | } | |
668 | } | |
669 | ||
4be44fcd | 670 | return_ACPI_STATUS(status); |
1da177e4 LT |
671 | } |
672 | ||
ef805d95 LM |
673 | /******************************************************************************* |
674 | * | |
675 | * FUNCTION: acpi_ds_eval_bank_field_operands | |
676 | * | |
677 | * PARAMETERS: walk_state - Current walk | |
ba494bee | 678 | * op - A valid bank_field Op object |
ef805d95 LM |
679 | * |
680 | * RETURN: Status | |
681 | * | |
682 | * DESCRIPTION: Get bank_field bank_value | |
683 | * Called from acpi_ds_exec_end_op during bank_field parse tree walk | |
684 | * | |
685 | ******************************************************************************/ | |
686 | ||
687 | acpi_status | |
688 | acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state, | |
689 | union acpi_parse_object *op) | |
690 | { | |
691 | acpi_status status; | |
692 | union acpi_operand_object *obj_desc; | |
693 | union acpi_operand_object *operand_desc; | |
694 | struct acpi_namespace_node *node; | |
695 | union acpi_parse_object *next_op; | |
696 | union acpi_parse_object *arg; | |
697 | ||
698 | ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op); | |
699 | ||
700 | /* | |
701 | * This is where we evaluate the bank_value field of the | |
702 | * bank_field declaration | |
703 | */ | |
704 | ||
705 | /* next_op points to the op that holds the Region */ | |
706 | ||
707 | next_op = op->common.value.arg; | |
708 | ||
709 | /* next_op points to the op that holds the Bank Register */ | |
710 | ||
711 | next_op = next_op->common.next; | |
712 | ||
713 | /* next_op points to the op that holds the Bank Value */ | |
714 | ||
715 | next_op = next_op->common.next; | |
716 | ||
717 | /* | |
718 | * Set proper index into operand stack for acpi_ds_obj_stack_push | |
719 | * invoked inside acpi_ds_create_operand. | |
720 | * | |
721 | * We use walk_state->Operands[0] to store the evaluated bank_value | |
722 | */ | |
723 | walk_state->operand_index = 0; | |
724 | ||
725 | status = acpi_ds_create_operand(walk_state, next_op, 0); | |
726 | if (ACPI_FAILURE(status)) { | |
727 | return_ACPI_STATUS(status); | |
728 | } | |
729 | ||
730 | status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state); | |
731 | if (ACPI_FAILURE(status)) { | |
732 | return_ACPI_STATUS(status); | |
733 | } | |
734 | ||
71d993e1 BM |
735 | ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS, |
736 | acpi_ps_get_opcode_name(op->common.aml_opcode), 1); | |
ef805d95 LM |
737 | /* |
738 | * Get the bank_value operand and save it | |
739 | * (at Top of stack) | |
740 | */ | |
741 | operand_desc = walk_state->operands[0]; | |
742 | ||
743 | /* Arg points to the start Bank Field */ | |
744 | ||
745 | arg = acpi_ps_get_arg(op, 4); | |
746 | while (arg) { | |
747 | ||
748 | /* Ignore OFFSET and ACCESSAS terms here */ | |
749 | ||
750 | if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) { | |
751 | node = arg->common.node; | |
752 | ||
753 | obj_desc = acpi_ns_get_attached_object(node); | |
754 | if (!obj_desc) { | |
755 | return_ACPI_STATUS(AE_NOT_EXIST); | |
756 | } | |
757 | ||
758 | obj_desc->bank_field.value = | |
759 | (u32) operand_desc->integer.value; | |
760 | } | |
761 | ||
762 | /* Move to next field in the list */ | |
763 | ||
764 | arg = arg->common.next; | |
765 | } | |
766 | ||
767 | acpi_ut_remove_reference(operand_desc); | |
768 | return_ACPI_STATUS(status); | |
769 | } |