Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: dswload - Dispatcher first pass namespace load callbacks
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 : :
18 : : #ifdef ACPI_ASL_COMPILER
19 : : #include "acdisasm.h"
20 : : #endif
21 : :
22 : : #define _COMPONENT ACPI_DISPATCHER
23 : : ACPI_MODULE_NAME("dswload")
24 : :
25 : : /*******************************************************************************
26 : : *
27 : : * FUNCTION: acpi_ds_init_callbacks
28 : : *
29 : : * PARAMETERS: walk_state - Current state of the parse tree walk
30 : : * pass_number - 1, 2, or 3
31 : : *
32 : : * RETURN: Status
33 : : *
34 : : * DESCRIPTION: Init walk state callbacks
35 : : *
36 : : ******************************************************************************/
37 : : acpi_status
38 : 3717 : acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)
39 : : {
40 : :
41 [ + + - + : 3717 : switch (pass_number) {
- ]
42 : 1428 : case 0:
43 : :
44 : : /* Parse only - caller will setup callbacks */
45 : :
46 : 1428 : walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
47 : : ACPI_PARSE_DELETE_TREE | ACPI_PARSE_DISASSEMBLE;
48 : 1428 : walk_state->descending_callback = NULL;
49 : 1428 : walk_state->ascending_callback = NULL;
50 : 1428 : break;
51 : :
52 : 84 : case 1:
53 : :
54 : : /* Load pass 1 */
55 : :
56 : 84 : walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
57 : : ACPI_PARSE_DELETE_TREE;
58 : 84 : walk_state->descending_callback = acpi_ds_load1_begin_op;
59 : 84 : walk_state->ascending_callback = acpi_ds_load1_end_op;
60 : 84 : break;
61 : :
62 : 0 : case 2:
63 : :
64 : : /* Load pass 2 */
65 : :
66 : 0 : walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |
67 : : ACPI_PARSE_DELETE_TREE;
68 : 0 : walk_state->descending_callback = acpi_ds_load2_begin_op;
69 : 0 : walk_state->ascending_callback = acpi_ds_load2_end_op;
70 : 0 : break;
71 : :
72 : 2205 : case 3:
73 : :
74 : : /* Execution pass */
75 : :
76 : 2205 : walk_state->parse_flags |= ACPI_PARSE_EXECUTE |
77 : : ACPI_PARSE_DELETE_TREE;
78 : 2205 : walk_state->descending_callback = acpi_ds_exec_begin_op;
79 : 2205 : walk_state->ascending_callback = acpi_ds_exec_end_op;
80 : 2205 : break;
81 : :
82 : : default:
83 : :
84 : : return (AE_BAD_PARAMETER);
85 : : }
86 : :
87 : : return (AE_OK);
88 : : }
89 : :
90 : : /*******************************************************************************
91 : : *
92 : : * FUNCTION: acpi_ds_load1_begin_op
93 : : *
94 : : * PARAMETERS: walk_state - Current state of the parse tree walk
95 : : * out_op - Where to return op if a new one is created
96 : : *
97 : : * RETURN: Status
98 : : *
99 : : * DESCRIPTION: Descending callback used during the loading of ACPI tables.
100 : : *
101 : : ******************************************************************************/
102 : :
103 : : acpi_status
104 : 0 : acpi_ds_load1_begin_op(struct acpi_walk_state *walk_state,
105 : : union acpi_parse_object **out_op)
106 : : {
107 : 0 : union acpi_parse_object *op;
108 : 0 : struct acpi_namespace_node *node;
109 : 0 : acpi_status status;
110 : 0 : acpi_object_type object_type;
111 : 0 : char *path;
112 : 0 : u32 flags;
113 : :
114 : 0 : ACPI_FUNCTION_TRACE_PTR(ds_load1_begin_op, walk_state->op);
115 : :
116 : 0 : op = walk_state->op;
117 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
118 : 0 : walk_state));
119 : :
120 : : /* We are only interested in opcodes that have an associated name */
121 : :
122 [ # # ]: 0 : if (op) {
123 [ # # ]: 0 : if (!(walk_state->op_info->flags & AML_NAMED)) {
124 : 0 : *out_op = op;
125 : 0 : return_ACPI_STATUS(AE_OK);
126 : : }
127 : :
128 : : /* Check if this object has already been installed in the namespace */
129 : :
130 [ # # ]: 0 : if (op->common.node) {
131 : 0 : *out_op = op;
132 : 0 : return_ACPI_STATUS(AE_OK);
133 : : }
134 : : }
135 : :
136 : 0 : path = acpi_ps_get_next_namestring(&walk_state->parser_state);
137 : :
138 : : /* Map the raw opcode into an internal object type */
139 : :
140 : 0 : object_type = walk_state->op_info->object_type;
141 : :
142 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
143 : : "State=%p Op=%p [%s]\n", walk_state, op,
144 : 0 : acpi_ut_get_type_name(object_type)));
145 : :
146 [ # # ]: 0 : switch (walk_state->opcode) {
147 : 0 : case AML_SCOPE_OP:
148 : : /*
149 : : * The target name of the Scope() operator must exist at this point so
150 : : * that we can actually open the scope to enter new names underneath it.
151 : : * Allow search-to-root for single namesegs.
152 : : */
153 : 0 : status =
154 : 0 : acpi_ns_lookup(walk_state->scope_info, path, object_type,
155 : : ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,
156 : : walk_state, &(node));
157 : : #ifdef ACPI_ASL_COMPILER
158 : : if (status == AE_NOT_FOUND) {
159 : : /*
160 : : * Table disassembly:
161 : : * Target of Scope() not found. Generate an External for it, and
162 : : * insert the name into the namespace.
163 : : */
164 : : acpi_dm_add_op_to_external_list(op, path,
165 : : ACPI_TYPE_DEVICE, 0, 0);
166 : : status =
167 : : acpi_ns_lookup(walk_state->scope_info, path,
168 : : object_type, ACPI_IMODE_LOAD_PASS1,
169 : : ACPI_NS_SEARCH_PARENT, walk_state,
170 : : &node);
171 : : }
172 : : #endif
173 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
174 : 0 : ACPI_ERROR_NAMESPACE(walk_state->scope_info, path,
175 : 0 : status);
176 : 0 : return_ACPI_STATUS(status);
177 : : }
178 : :
179 : : /*
180 : : * Check to make sure that the target is
181 : : * one of the opcodes that actually opens a scope
182 : : */
183 [ # # # # ]: 0 : switch (node->type) {
184 : : case ACPI_TYPE_ANY:
185 : : case ACPI_TYPE_LOCAL_SCOPE: /* Scope */
186 : : case ACPI_TYPE_DEVICE:
187 : : case ACPI_TYPE_POWER:
188 : : case ACPI_TYPE_PROCESSOR:
189 : : case ACPI_TYPE_THERMAL:
190 : :
191 : : /* These are acceptable types */
192 : : break;
193 : :
194 : 0 : case ACPI_TYPE_INTEGER:
195 : : case ACPI_TYPE_STRING:
196 : : case ACPI_TYPE_BUFFER:
197 : : /*
198 : : * These types we will allow, but we will change the type.
199 : : * This enables some existing code of the form:
200 : : *
201 : : * Name (DEB, 0)
202 : : * Scope (DEB) { ... }
203 : : *
204 : : * Note: silently change the type here. On the second pass,
205 : : * we will report a warning
206 : : */
207 : : ACPI_DEBUG_PRINT((ACPI_DB_INFO,
208 : : "Type override - [%4.4s] had invalid type (%s) "
209 : : "for Scope operator, changed to type ANY\n",
210 : : acpi_ut_get_node_name(node),
211 : 0 : acpi_ut_get_type_name(node->type)));
212 : :
213 : 0 : node->type = ACPI_TYPE_ANY;
214 : 0 : walk_state->scope_info->common.value = ACPI_TYPE_ANY;
215 : 0 : break;
216 : :
217 : 0 : case ACPI_TYPE_METHOD:
218 : : /*
219 : : * Allow scope change to root during execution of module-level
220 : : * code. Root is typed METHOD during this time.
221 : : */
222 [ # # ]: 0 : if ((node == acpi_gbl_root_node) &&
223 : 0 : (walk_state->
224 [ # # ]: 0 : parse_flags & ACPI_PARSE_MODULE_LEVEL)) {
225 : : break;
226 : : }
227 : :
228 : : /*lint -fallthrough */
229 : :
230 : : default:
231 : :
232 : : /* All other types are an error */
233 : :
234 : 0 : ACPI_ERROR((AE_INFO,
235 : : "Invalid type (%s) for target of "
236 : : "Scope operator [%4.4s] (Cannot override)",
237 : : acpi_ut_get_type_name(node->type),
238 : : acpi_ut_get_node_name(node)));
239 : :
240 : 0 : return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
241 : : }
242 : 0 : break;
243 : :
244 : 0 : default:
245 : : /*
246 : : * For all other named opcodes, we will enter the name into
247 : : * the namespace.
248 : : *
249 : : * Setup the search flags.
250 : : * Since we are entering a name into the namespace, we do not want to
251 : : * enable the search-to-root upsearch.
252 : : *
253 : : * There are only two conditions where it is acceptable that the name
254 : : * already exists:
255 : : * 1) the Scope() operator can reopen a scoping object that was
256 : : * previously defined (Scope, Method, Device, etc.)
257 : : * 2) Whenever we are parsing a deferred opcode (op_region, Buffer,
258 : : * buffer_field, or Package), the name of the object is already
259 : : * in the namespace.
260 : : */
261 [ # # ]: 0 : if (walk_state->deferred_node) {
262 : :
263 : : /* This name is already in the namespace, get the node */
264 : :
265 : 0 : node = walk_state->deferred_node;
266 : 0 : status = AE_OK;
267 : 0 : break;
268 : : }
269 : :
270 : : /*
271 : : * If we are executing a method, do not create any namespace objects
272 : : * during the load phase, only during execution.
273 : : */
274 [ # # ]: 0 : if (walk_state->method_node) {
275 : 0 : node = NULL;
276 : 0 : status = AE_OK;
277 : 0 : break;
278 : : }
279 : :
280 : 0 : flags = ACPI_NS_NO_UPSEARCH;
281 : 0 : if ((walk_state->opcode != AML_SCOPE_OP) &&
282 [ # # ]: 0 : (!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {
283 [ # # ]: 0 : if (walk_state->namespace_override) {
284 : : flags |= ACPI_NS_OVERRIDE_IF_FOUND;
285 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
286 : : "[%s] Override allowed\n",
287 : : acpi_ut_get_type_name
288 : : (object_type)));
289 : : } else {
290 : 0 : flags |= ACPI_NS_ERROR_IF_FOUND;
291 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
292 : : "[%s] Cannot already exist\n",
293 : : acpi_ut_get_type_name
294 : : (object_type)));
295 : : }
296 : : } else {
297 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
298 : : "[%s] Both Find or Create allowed\n",
299 : 0 : acpi_ut_get_type_name(object_type)));
300 : : }
301 : :
302 : : /*
303 : : * Enter the named type into the internal namespace. We enter the name
304 : : * as we go downward in the parse tree. Any necessary subobjects that
305 : : * involve arguments to the opcode must be created as we go back up the
306 : : * parse tree later.
307 : : */
308 : 0 : status =
309 : 0 : acpi_ns_lookup(walk_state->scope_info, path, object_type,
310 : : ACPI_IMODE_LOAD_PASS1, flags, walk_state,
311 : : &node);
312 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
313 [ # # ]: 0 : if (status == AE_ALREADY_EXISTS) {
314 : :
315 : : /* The name already exists in this scope */
316 : :
317 [ # # ]: 0 : if (node->flags & ANOBJ_IS_EXTERNAL) {
318 : : /*
319 : : * Allow one create on an object or segment that was
320 : : * previously declared External
321 : : */
322 : 0 : node->flags &= ~ANOBJ_IS_EXTERNAL;
323 : 0 : node->type = (u8) object_type;
324 : :
325 : : /* Just retyped a node, probably will need to open a scope */
326 : :
327 [ # # ]: 0 : if (acpi_ns_opens_scope(object_type)) {
328 : 0 : status =
329 : 0 : acpi_ds_scope_stack_push
330 : : (node, object_type,
331 : : walk_state);
332 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
333 : : return_ACPI_STATUS
334 : : (status);
335 : : }
336 : : }
337 : :
338 : : status = AE_OK;
339 : : }
340 : : }
341 : :
342 : 0 : if (ACPI_FAILURE(status)) {
343 : 0 : ACPI_ERROR_NAMESPACE(walk_state->scope_info,
344 : 0 : path, status);
345 : 0 : return_ACPI_STATUS(status);
346 : : }
347 : : }
348 : : break;
349 : : }
350 : :
351 : : /* Common exit */
352 : :
353 [ # # ]: 0 : if (!op) {
354 : :
355 : : /* Create a new op */
356 : :
357 : 0 : op = acpi_ps_alloc_op(walk_state->opcode, walk_state->aml);
358 [ # # ]: 0 : if (!op) {
359 : : return_ACPI_STATUS(AE_NO_MEMORY);
360 : : }
361 : : }
362 : :
363 : : /* Initialize the op */
364 : :
365 : : #ifdef ACPI_CONSTANT_EVAL_ONLY
366 : : op->named.path = path;
367 : : #endif
368 : :
369 [ # # ]: 0 : if (node) {
370 : : /*
371 : : * Put the Node in the "op" object that the parser uses, so we
372 : : * can get it again quickly when this scope is closed
373 : : */
374 : 0 : op->common.node = node;
375 : 0 : op->named.name = node->name.integer;
376 : : }
377 : :
378 : 0 : acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),
379 : : op);
380 : 0 : *out_op = op;
381 : 0 : return_ACPI_STATUS(status);
382 : : }
383 : :
384 : : /*******************************************************************************
385 : : *
386 : : * FUNCTION: acpi_ds_load1_end_op
387 : : *
388 : : * PARAMETERS: walk_state - Current state of the parse tree walk
389 : : *
390 : : * RETURN: Status
391 : : *
392 : : * DESCRIPTION: Ascending callback used during the loading of the namespace,
393 : : * both control methods and everything else.
394 : : *
395 : : ******************************************************************************/
396 : :
397 : 0 : acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)
398 : : {
399 : 0 : union acpi_parse_object *op;
400 : 0 : acpi_object_type object_type;
401 : 0 : acpi_status status = AE_OK;
402 : :
403 : : #ifdef ACPI_ASL_COMPILER
404 : : u8 param_count;
405 : : #endif
406 : :
407 : 0 : ACPI_FUNCTION_TRACE(ds_load1_end_op);
408 : :
409 : 0 : op = walk_state->op;
410 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,
411 : 0 : walk_state));
412 : :
413 : : /*
414 : : * Disassembler: handle create field operators here.
415 : : *
416 : : * create_buffer_field is a deferred op that is typically processed in load
417 : : * pass 2. However, disassembly of control method contents walk the parse
418 : : * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed
419 : : * in a later walk. This is a problem when there is a control method that
420 : : * has the same name as the AML_CREATE object. In this case, any use of the
421 : : * name segment will be detected as a method call rather than a reference
422 : : * to a buffer field.
423 : : *
424 : : * This earlier creation during disassembly solves this issue by inserting
425 : : * the named object in the ACPI namespace so that references to this name
426 : : * would be a name string rather than a method call.
427 : : */
428 [ # # ]: 0 : if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) &&
429 [ # # ]: 0 : (walk_state->op_info->flags & AML_CREATE)) {
430 : 0 : status = acpi_ds_create_buffer_field(op, walk_state);
431 : 0 : return_ACPI_STATUS(status);
432 : : }
433 : :
434 : : /* We are only interested in opcodes that have an associated name */
435 : :
436 [ # # ]: 0 : if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {
437 : : return_ACPI_STATUS(AE_OK);
438 : : }
439 : :
440 : : /* Get the object type to determine if we should pop the scope */
441 : :
442 : 0 : object_type = walk_state->op_info->object_type;
443 : :
444 [ # # ]: 0 : if (walk_state->op_info->flags & AML_FIELD) {
445 : : /*
446 : : * If we are executing a method, do not create any namespace objects
447 : : * during the load phase, only during execution.
448 : : */
449 [ # # ]: 0 : if (!walk_state->method_node) {
450 [ # # ]: 0 : if (walk_state->opcode == AML_FIELD_OP ||
451 [ # # ]: 0 : walk_state->opcode == AML_BANK_FIELD_OP ||
452 : : walk_state->opcode == AML_INDEX_FIELD_OP) {
453 : 0 : status =
454 : 0 : acpi_ds_init_field_objects(op, walk_state);
455 : : }
456 : : }
457 : 0 : return_ACPI_STATUS(status);
458 : : }
459 : :
460 : : /*
461 : : * If we are executing a method, do not create any namespace objects
462 : : * during the load phase, only during execution.
463 : : */
464 [ # # ]: 0 : if (!walk_state->method_node) {
465 [ # # ]: 0 : if (op->common.aml_opcode == AML_REGION_OP) {
466 : 0 : status =
467 : 0 : acpi_ex_create_region(op->named.data,
468 : : op->named.length,
469 : 0 : (acpi_adr_space_type)
470 : 0 : ((op->common.value.arg)->
471 : 0 : common.value.integer),
472 : : walk_state);
473 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
474 : : return_ACPI_STATUS(status);
475 : : }
476 [ # # ]: 0 : } else if (op->common.aml_opcode == AML_DATA_REGION_OP) {
477 : 0 : status =
478 : 0 : acpi_ex_create_region(op->named.data,
479 : : op->named.length,
480 : : ACPI_ADR_SPACE_DATA_TABLE,
481 : : walk_state);
482 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
483 : : return_ACPI_STATUS(status);
484 : : }
485 : : }
486 : : }
487 : :
488 [ # # ]: 0 : if (op->common.aml_opcode == AML_NAME_OP) {
489 : :
490 : : /* For Name opcode, get the object type from the argument */
491 : :
492 [ # # ]: 0 : if (op->common.value.arg) {
493 : 0 : object_type = (acpi_ps_get_opcode_info((op->common.
494 : : value.arg)->
495 : 0 : common.
496 : 0 : aml_opcode))->
497 : : object_type;
498 : :
499 : : /* Set node type if we have a namespace node */
500 : :
501 [ # # ]: 0 : if (op->common.node) {
502 : 0 : op->common.node->type = (u8) object_type;
503 : : }
504 : : }
505 : : }
506 : : #ifdef ACPI_ASL_COMPILER
507 : : /*
508 : : * For external opcode, get the object type from the argument and
509 : : * get the parameter count from the argument's next.
510 : : */
511 : : if (acpi_gbl_disasm_flag &&
512 : : op->common.node && op->common.aml_opcode == AML_EXTERNAL_OP) {
513 : : /*
514 : : * Note, if this external is not a method
515 : : * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0
516 : : * Therefore, param_count will be 0.
517 : : */
518 : : param_count =
519 : : (u8)op->common.value.arg->common.next->common.value.integer;
520 : : object_type = (u8)op->common.value.arg->common.value.integer;
521 : : op->common.node->flags |= ANOBJ_IS_EXTERNAL;
522 : : op->common.node->type = (u8)object_type;
523 : :
524 : : acpi_dm_create_subobject_for_external((u8)object_type,
525 : : &op->common.node,
526 : : param_count);
527 : :
528 : : /*
529 : : * Add the external to the external list because we may be
530 : : * emitting code based off of the items within the external list.
531 : : */
532 : : acpi_dm_add_op_to_external_list(op, op->named.path,
533 : : (u8)object_type, param_count,
534 : : ACPI_EXT_ORIGIN_FROM_OPCODE |
535 : : ACPI_EXT_RESOLVED_REFERENCE);
536 : : }
537 : : #endif
538 : :
539 : : /*
540 : : * If we are executing a method, do not create any namespace objects
541 : : * during the load phase, only during execution.
542 : : */
543 [ # # ]: 0 : if (!walk_state->method_node) {
544 [ # # ]: 0 : if (op->common.aml_opcode == AML_METHOD_OP) {
545 : : /*
546 : : * method_op pkg_length name_string method_flags term_list
547 : : *
548 : : * Note: We must create the method node/object pair as soon as we
549 : : * see the method declaration. This allows later pass1 parsing
550 : : * of invocations of the method (need to know the number of
551 : : * arguments.)
552 : : */
553 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
554 : : "LOADING-Method: State=%p Op=%p NamedObj=%p\n",
555 : 0 : walk_state, op, op->named.node));
556 : :
557 [ # # ]: 0 : if (!acpi_ns_get_attached_object(op->named.node)) {
558 : 0 : walk_state->operands[0] =
559 : 0 : ACPI_CAST_PTR(void, op->named.node);
560 : 0 : walk_state->num_operands = 1;
561 : :
562 : 0 : status =
563 : 0 : acpi_ds_create_operands(walk_state,
564 : : op->common.value.
565 : : arg);
566 [ # # ]: 0 : if (ACPI_SUCCESS(status)) {
567 : 0 : status =
568 : 0 : acpi_ex_create_method(op->named.
569 : : data,
570 : : op->named.
571 : : length,
572 : : walk_state);
573 : : }
574 : :
575 : 0 : walk_state->operands[0] = NULL;
576 : 0 : walk_state->num_operands = 0;
577 : :
578 [ # # ]: 0 : if (ACPI_FAILURE(status)) {
579 : : return_ACPI_STATUS(status);
580 : : }
581 : : }
582 : : }
583 : : }
584 : :
585 : : /* Pop the scope stack (only if loading a table) */
586 : :
587 [ # # ]: 0 : if (!walk_state->method_node &&
588 [ # # # # ]: 0 : op->common.aml_opcode != AML_EXTERNAL_OP &&
589 : 0 : acpi_ns_opens_scope(object_type)) {
590 : : ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
591 : : "(%s): Popping scope for Op %p\n",
592 : 0 : acpi_ut_get_type_name(object_type), op));
593 : :
594 : 0 : status = acpi_ds_scope_stack_pop(walk_state);
595 : : }
596 : :
597 : : return_ACPI_STATUS(status);
598 : : }
|