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