Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: dsobject - Dispatcher object management routines
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 "acnamesp.h"
16 : : #include "acinterp.h"
17 : :
18 : : #define _COMPONENT ACPI_DISPATCHER
19 : : ACPI_MODULE_NAME("dsobject")
20 : :
21 : : /*******************************************************************************
22 : : *
23 : : * FUNCTION: acpi_ds_build_internal_object
24 : : *
25 : : * PARAMETERS: walk_state - Current walk state
26 : : * op - Parser object to be translated
27 : : * obj_desc_ptr - Where the ACPI internal object is returned
28 : : *
29 : : * RETURN: Status
30 : : *
31 : : * DESCRIPTION: Translate a parser Op object to the equivalent namespace object
32 : : * Simple objects are any objects other than a package object!
33 : : *
34 : : ******************************************************************************/
35 : : acpi_status
36 : 20408 : acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
37 : : union acpi_parse_object *op,
38 : : union acpi_operand_object **obj_desc_ptr)
39 : : {
40 : 20408 : union acpi_operand_object *obj_desc;
41 : 20408 : acpi_status status;
42 : :
43 : 20408 : ACPI_FUNCTION_TRACE(ds_build_internal_object);
44 : :
45 : 20408 : *obj_desc_ptr = NULL;
46 [ + + ]: 20408 : if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
47 : : /*
48 : : * This is a named object reference. If this name was
49 : : * previously looked up in the namespace, it was stored in
50 : : * this op. Otherwise, go ahead and look it up now
51 : : */
52 [ - + ]: 3968 : if (!op->common.node) {
53 : :
54 : : /* Check if we are resolving a named reference within a package */
55 : :
56 : 3968 : if ((op->common.parent->common.aml_opcode ==
57 : : AML_PACKAGE_OP)
58 [ + - ]: 3968 : || (op->common.parent->common.aml_opcode ==
59 : : AML_VARIABLE_PACKAGE_OP)) {
60 : : /*
61 : : * We won't resolve package elements here, we will do this
62 : : * after all ACPI tables are loaded into the namespace. This
63 : : * behavior supports both forward references to named objects
64 : : * and external references to objects in other tables.
65 : : */
66 : 3968 : goto create_new_object;
67 : : } else {
68 : 0 : status = acpi_ns_lookup(walk_state->scope_info,
69 : : op->common.value.string,
70 : : ACPI_TYPE_ANY,
71 : : ACPI_IMODE_EXECUTE,
72 : : ACPI_NS_SEARCH_PARENT |
73 : : ACPI_NS_DONT_OPEN_SCOPE,
74 : : NULL,
75 : : ACPI_CAST_INDIRECT_PTR
76 : : (struct
77 : : acpi_namespace_node,
78 : : &(op->common.node)));
79 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
80 : 0 : ACPI_ERROR_NAMESPACE(walk_state->
81 : : scope_info,
82 : : op->common.value.
83 : 0 : string, status);
84 : 0 : return_ACPI_STATUS(status);
85 : : }
86 : : }
87 : : }
88 : : }
89 : :
90 : 16440 : create_new_object:
91 : :
92 : : /* Create and init a new internal ACPI object */
93 : :
94 : 20408 : obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
95 : : (op->common.aml_opcode))->
96 : : object_type);
97 [ + - ]: 20408 : if (!obj_desc) {
98 : : return_ACPI_STATUS(AE_NO_MEMORY);
99 : : }
100 : :
101 : 20408 : status =
102 : 20408 : acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode,
103 : : &obj_desc);
104 [ - + ]: 20408 : if (ACPI_FAILURE(status)) {
105 : 0 : acpi_ut_remove_reference(obj_desc);
106 : 0 : return_ACPI_STATUS(status);
107 : : }
108 : :
109 : : /*
110 : : * Handling for unresolved package reference elements.
111 : : * These are elements that are namepaths.
112 : : */
113 [ + + ]: 20408 : if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
114 : : (op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
115 : 16656 : obj_desc->reference.resolved = TRUE;
116 : :
117 [ + + ]: 16656 : if ((op->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
118 [ + - ]: 3968 : !obj_desc->reference.node) {
119 : : /*
120 : : * Name was unresolved above.
121 : : * Get the prefix node for later lookup
122 : : */
123 : 3968 : obj_desc->reference.node =
124 : 3968 : walk_state->scope_info->scope.node;
125 : 3968 : obj_desc->reference.aml = op->common.aml;
126 : 3968 : obj_desc->reference.resolved = FALSE;
127 : : }
128 : : }
129 : :
130 : 20408 : *obj_desc_ptr = obj_desc;
131 : 20408 : return_ACPI_STATUS(status);
132 : : }
133 : :
134 : : /*******************************************************************************
135 : : *
136 : : * FUNCTION: acpi_ds_build_internal_buffer_obj
137 : : *
138 : : * PARAMETERS: walk_state - Current walk state
139 : : * op - Parser object to be translated
140 : : * buffer_length - Length of the buffer
141 : : * obj_desc_ptr - Where the ACPI internal object is returned
142 : : *
143 : : * RETURN: Status
144 : : *
145 : : * DESCRIPTION: Translate a parser Op package object to the equivalent
146 : : * namespace object
147 : : *
148 : : ******************************************************************************/
149 : :
150 : : acpi_status
151 : 812 : acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
152 : : union acpi_parse_object *op,
153 : : u32 buffer_length,
154 : : union acpi_operand_object **obj_desc_ptr)
155 : : {
156 : 812 : union acpi_parse_object *arg;
157 : 812 : union acpi_operand_object *obj_desc;
158 : 812 : union acpi_parse_object *byte_list;
159 : 812 : u32 byte_list_length = 0;
160 : :
161 : 812 : ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj);
162 : :
163 : : /*
164 : : * If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
165 : : * The buffer object already exists (from the NS node), otherwise it must
166 : : * be created.
167 : : */
168 : 812 : obj_desc = *obj_desc_ptr;
169 [ - + ]: 812 : if (!obj_desc) {
170 : :
171 : : /* Create a new buffer object */
172 : :
173 : 0 : obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
174 : 0 : *obj_desc_ptr = obj_desc;
175 [ # # ]: 0 : if (!obj_desc) {
176 : : return_ACPI_STATUS(AE_NO_MEMORY);
177 : : }
178 : : }
179 : :
180 : : /*
181 : : * Second arg is the buffer data (optional) byte_list can be either
182 : : * individual bytes or a string initializer. In either case, a
183 : : * byte_list appears in the AML.
184 : : */
185 : 812 : arg = op->common.value.arg; /* skip first arg */
186 : :
187 : 812 : byte_list = arg->named.next;
188 [ + - ]: 812 : if (byte_list) {
189 [ - + ]: 812 : if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
190 : 0 : ACPI_ERROR((AE_INFO,
191 : : "Expecting bytelist, found AML opcode 0x%X in op %p",
192 : : byte_list->common.aml_opcode, byte_list));
193 : :
194 : 0 : acpi_ut_remove_reference(obj_desc);
195 : 0 : return (AE_TYPE);
196 : : }
197 : :
198 : 812 : byte_list_length = (u32) byte_list->common.value.integer;
199 : : }
200 : :
201 : : /*
202 : : * The buffer length (number of bytes) will be the larger of:
203 : : * 1) The specified buffer length and
204 : : * 2) The length of the initializer byte list
205 : : */
206 : 812 : obj_desc->buffer.length = buffer_length;
207 [ - + ]: 812 : if (byte_list_length > buffer_length) {
208 : 0 : obj_desc->buffer.length = byte_list_length;
209 : : }
210 : :
211 : : /* Allocate the buffer */
212 : :
213 [ - + ]: 812 : if (obj_desc->buffer.length == 0) {
214 : 0 : obj_desc->buffer.pointer = NULL;
215 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
216 : 0 : "Buffer defined with zero length in AML, creating\n"));
217 : : } else {
218 : 1624 : obj_desc->buffer.pointer =
219 : 812 : ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length);
220 [ - + ]: 812 : if (!obj_desc->buffer.pointer) {
221 : 0 : acpi_ut_delete_object_desc(obj_desc);
222 : 0 : return_ACPI_STATUS(AE_NO_MEMORY);
223 : : }
224 : :
225 : : /* Initialize buffer from the byte_list (if present) */
226 : :
227 [ + - ]: 812 : if (byte_list) {
228 : 812 : memcpy(obj_desc->buffer.pointer, byte_list->named.data,
229 : : byte_list_length);
230 : : }
231 : : }
232 : :
233 : 812 : obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
234 : 812 : op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
235 : 812 : return_ACPI_STATUS(AE_OK);
236 : : }
237 : :
238 : : /*******************************************************************************
239 : : *
240 : : * FUNCTION: acpi_ds_create_node
241 : : *
242 : : * PARAMETERS: walk_state - Current walk state
243 : : * node - NS Node to be initialized
244 : : * op - Parser object to be translated
245 : : *
246 : : * RETURN: Status
247 : : *
248 : : * DESCRIPTION: Create the object to be associated with a namespace node
249 : : *
250 : : ******************************************************************************/
251 : :
252 : : acpi_status
253 : 4676 : acpi_ds_create_node(struct acpi_walk_state *walk_state,
254 : : struct acpi_namespace_node *node,
255 : : union acpi_parse_object *op)
256 : : {
257 : 4676 : acpi_status status;
258 : 4676 : union acpi_operand_object *obj_desc;
259 : :
260 : 4676 : ACPI_FUNCTION_TRACE_PTR(ds_create_node, op);
261 : :
262 : : /*
263 : : * Because of the execution pass through the non-control-method
264 : : * parts of the table, we can arrive here twice. Only init
265 : : * the named object node the first time through
266 : : */
267 [ + + ]: 4676 : if (acpi_ns_get_attached_object(node)) {
268 : : return_ACPI_STATUS(AE_OK);
269 : : }
270 : :
271 [ + - ]: 3752 : if (!op->common.value.arg) {
272 : :
273 : : /* No arguments, there is nothing to do */
274 : :
275 : : return_ACPI_STATUS(AE_OK);
276 : : }
277 : :
278 : : /* Build an internal object for the argument(s) */
279 : :
280 : 3752 : status =
281 : 3752 : acpi_ds_build_internal_object(walk_state, op->common.value.arg,
282 : : &obj_desc);
283 [ + - ]: 3752 : if (ACPI_FAILURE(status)) {
284 : : return_ACPI_STATUS(status);
285 : : }
286 : :
287 : : /* Re-type the object according to its argument */
288 : :
289 : 3752 : node->type = obj_desc->common.type;
290 : :
291 : : /* Attach obj to node */
292 : :
293 : 3752 : status = acpi_ns_attach_object(node, obj_desc, node->type);
294 : :
295 : : /* Remove local reference to the object */
296 : :
297 : 3752 : acpi_ut_remove_reference(obj_desc);
298 : 3752 : return_ACPI_STATUS(status);
299 : : }
300 : :
301 : : /*******************************************************************************
302 : : *
303 : : * FUNCTION: acpi_ds_init_object_from_op
304 : : *
305 : : * PARAMETERS: walk_state - Current walk state
306 : : * op - Parser op used to init the internal object
307 : : * opcode - AML opcode associated with the object
308 : : * ret_obj_desc - Namespace object to be initialized
309 : : *
310 : : * RETURN: Status
311 : : *
312 : : * DESCRIPTION: Initialize a namespace object from a parser Op and its
313 : : * associated arguments. The namespace object is a more compact
314 : : * representation of the Op and its arguments.
315 : : *
316 : : ******************************************************************************/
317 : :
318 : : acpi_status
319 : 195965 : acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
320 : : union acpi_parse_object *op,
321 : : u16 opcode,
322 : : union acpi_operand_object **ret_obj_desc)
323 : : {
324 : 195965 : const struct acpi_opcode_info *op_info;
325 : 195965 : union acpi_operand_object *obj_desc;
326 : 195965 : acpi_status status = AE_OK;
327 : :
328 : 195965 : ACPI_FUNCTION_TRACE(ds_init_object_from_op);
329 : :
330 : 195965 : obj_desc = *ret_obj_desc;
331 : 195965 : op_info = acpi_ps_get_opcode_info(opcode);
332 [ + - ]: 195965 : if (op_info->class == AML_CLASS_UNKNOWN) {
333 : :
334 : : /* Unknown opcode */
335 : :
336 : : return_ACPI_STATUS(AE_TYPE);
337 : : }
338 : :
339 : : /* Perform per-object initialization */
340 : :
341 [ + + + + : 195965 : switch (obj_desc->common.type) {
+ - - ]
342 : 812 : case ACPI_TYPE_BUFFER:
343 : : /*
344 : : * Defer evaluation of Buffer term_arg operand
345 : : */
346 : 812 : obj_desc->buffer.node =
347 : 812 : ACPI_CAST_PTR(struct acpi_namespace_node,
348 : : walk_state->operands[0]);
349 : 812 : obj_desc->buffer.aml_start = op->named.data;
350 : 812 : obj_desc->buffer.aml_length = op->named.length;
351 : 812 : break;
352 : :
353 : 112 : case ACPI_TYPE_PACKAGE:
354 : : /*
355 : : * Defer evaluation of Package term_arg operand and all
356 : : * package elements. (01/2017): We defer the element
357 : : * resolution to allow forward references from the package
358 : : * in order to provide compatibility with other ACPI
359 : : * implementations.
360 : : */
361 : 112 : obj_desc->package.node =
362 : 112 : ACPI_CAST_PTR(struct acpi_namespace_node,
363 : : walk_state->operands[0]);
364 : :
365 [ - + ]: 112 : if (!op->named.data) {
366 : : return_ACPI_STATUS(AE_OK);
367 : : }
368 : :
369 : 0 : obj_desc->package.aml_start = op->named.data;
370 : 0 : obj_desc->package.aml_length = op->named.length;
371 : 0 : break;
372 : :
373 : 111541 : case ACPI_TYPE_INTEGER:
374 : :
375 [ + + - ]: 111541 : switch (op_info->type) {
376 : 65675 : case AML_TYPE_CONSTANT:
377 : : /*
378 : : * Resolve AML Constants here - AND ONLY HERE!
379 : : * All constants are integers.
380 : : * We mark the integer with a flag that indicates that it started
381 : : * life as a constant -- so that stores to constants will perform
382 : : * as expected (noop). zero_op is used as a placeholder for optional
383 : : * target operands.
384 : : */
385 : 65675 : obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
386 : :
387 [ + + - - : 65675 : switch (opcode) {
- ]
388 : 57487 : case AML_ZERO_OP:
389 : :
390 : 57487 : obj_desc->integer.value = 0;
391 : 57487 : break;
392 : :
393 : 8188 : case AML_ONE_OP:
394 : :
395 : 8188 : obj_desc->integer.value = 1;
396 : 8188 : break;
397 : :
398 : 0 : case AML_ONES_OP:
399 : :
400 : 0 : obj_desc->integer.value = ACPI_UINT64_MAX;
401 : :
402 : : /* Truncate value if we are executing from a 32-bit ACPI table */
403 : :
404 : 0 : (void)acpi_ex_truncate_for32bit_table(obj_desc);
405 : 0 : break;
406 : :
407 : 0 : case AML_REVISION_OP:
408 : :
409 : 0 : obj_desc->integer.value = ACPI_CA_VERSION;
410 : 0 : break;
411 : :
412 : 0 : default:
413 : :
414 : 0 : ACPI_ERROR((AE_INFO,
415 : : "Unknown constant opcode 0x%X",
416 : : opcode));
417 : 0 : status = AE_AML_OPERAND_TYPE;
418 : 0 : break;
419 : : }
420 : : break;
421 : :
422 : 45866 : case AML_TYPE_LITERAL:
423 : :
424 : 45866 : obj_desc->integer.value = op->common.value.integer;
425 : :
426 [ - + ]: 45866 : if (acpi_ex_truncate_for32bit_table(obj_desc)) {
427 : :
428 : : /* Warn if we found a 64-bit constant in a 32-bit table */
429 : :
430 : 0 : ACPI_WARNING((AE_INFO,
431 : : "Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
432 : : ACPI_FORMAT_UINT64(op->common.
433 : : value.integer),
434 : : (u32)obj_desc->integer.value));
435 : : }
436 : : break;
437 : :
438 : 0 : default:
439 : :
440 : 0 : ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X",
441 : : op_info->type));
442 : 0 : status = AE_AML_OPERAND_TYPE;
443 : 0 : break;
444 : : }
445 : : break;
446 : :
447 : 224 : case ACPI_TYPE_STRING:
448 : :
449 : 224 : obj_desc->string.pointer = op->common.value.string;
450 : 224 : obj_desc->string.length = (u32)strlen(op->common.value.string);
451 : :
452 : : /*
453 : : * The string is contained in the ACPI table, don't ever try
454 : : * to delete it
455 : : */
456 : 224 : obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
457 : 224 : break;
458 : :
459 : : case ACPI_TYPE_METHOD:
460 : : break;
461 : :
462 : 83276 : case ACPI_TYPE_LOCAL_REFERENCE:
463 : :
464 [ + + + ]: 83276 : switch (op_info->type) {
465 : 78244 : case AML_TYPE_LOCAL_VARIABLE:
466 : :
467 : : /* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
468 : :
469 : 78244 : obj_desc->reference.value =
470 : 78244 : ((u32)opcode) - AML_FIRST_LOCAL_OP;
471 : 78244 : obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
472 : :
473 : 78244 : status =
474 : 78244 : acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL,
475 : : obj_desc->reference.
476 : : value, walk_state,
477 : 78244 : ACPI_CAST_INDIRECT_PTR
478 : : (struct
479 : : acpi_namespace_node,
480 : : &obj_desc->reference.
481 : : object));
482 : 78244 : break;
483 : :
484 : 1064 : case AML_TYPE_METHOD_ARGUMENT:
485 : :
486 : : /* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
487 : :
488 : 1064 : obj_desc->reference.value =
489 : 1064 : ((u32)opcode) - AML_FIRST_ARG_OP;
490 : 1064 : obj_desc->reference.class = ACPI_REFCLASS_ARG;
491 : :
492 : 1064 : status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG,
493 : : obj_desc->
494 : : reference.value,
495 : : walk_state,
496 : 1064 : ACPI_CAST_INDIRECT_PTR
497 : : (struct
498 : : acpi_namespace_node,
499 : : &obj_desc->
500 : : reference.
501 : : object));
502 : 1064 : break;
503 : :
504 : 3968 : default: /* Object name or Debug object */
505 : :
506 [ + - - ]: 3968 : switch (op->common.aml_opcode) {
507 : 3968 : case AML_INT_NAMEPATH_OP:
508 : :
509 : : /* Node was saved in Op */
510 : :
511 : 3968 : obj_desc->reference.node = op->common.node;
512 : 3968 : obj_desc->reference.class = ACPI_REFCLASS_NAME;
513 [ - + ]: 3968 : if (op->common.node) {
514 : 0 : obj_desc->reference.object =
515 : 0 : op->common.node->object;
516 : : }
517 : : break;
518 : :
519 : 0 : case AML_DEBUG_OP:
520 : :
521 : 0 : obj_desc->reference.class = ACPI_REFCLASS_DEBUG;
522 : 0 : break;
523 : :
524 : 0 : default:
525 : :
526 : 0 : ACPI_ERROR((AE_INFO,
527 : : "Unimplemented reference type for AML opcode: 0x%4.4X",
528 : : opcode));
529 : 0 : return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
530 : : }
531 : : break;
532 : : }
533 : : break;
534 : :
535 : 0 : default:
536 : :
537 : 0 : ACPI_ERROR((AE_INFO, "Unimplemented data type: 0x%X",
538 : : obj_desc->common.type));
539 : :
540 : 0 : status = AE_AML_OPERAND_TYPE;
541 : 0 : break;
542 : : }
543 : :
544 : : return_ACPI_STATUS(status);
545 : : }
|