1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: dswstate - Dispatcher parse tree walk management routines
6 * Copyright (C) 2000 - 2020, Intel Corp.
8 *****************************************************************************/
10 #include <acpi/acpi.h>
16 #define _COMPONENT ACPI_DISPATCHER
17 ACPI_MODULE_NAME("dswstate")
19 /* Local prototypes */
21 acpi_ds_result_stack_push(struct acpi_walk_state
*walk_state
);
22 static acpi_status
acpi_ds_result_stack_pop(struct acpi_walk_state
*walk_state
);
24 /*******************************************************************************
26 * FUNCTION: acpi_ds_result_pop
28 * PARAMETERS: object - Where to return the popped object
29 * walk_state - Current Walk state
33 * DESCRIPTION: Pop an object off the top of this walk's result stack
35 ******************************************************************************/
38 acpi_ds_result_pop(union acpi_operand_object
**object
,
39 struct acpi_walk_state
*walk_state
)
42 union acpi_generic_state
*state
;
45 ACPI_FUNCTION_NAME(ds_result_pop
);
47 state
= walk_state
->results
;
49 /* Incorrect state of result stack */
51 if (state
&& !walk_state
->result_count
) {
52 ACPI_ERROR((AE_INFO
, "No results on result stack"));
53 return (AE_AML_INTERNAL
);
56 if (!state
&& walk_state
->result_count
) {
57 ACPI_ERROR((AE_INFO
, "No result state for result stack"));
58 return (AE_AML_INTERNAL
);
61 /* Empty result stack */
64 ACPI_ERROR((AE_INFO
, "Result stack is empty! State=%p",
66 return (AE_AML_NO_RETURN_VALUE
);
69 /* Return object of the top element and clean that top element result stack */
71 walk_state
->result_count
--;
72 index
= (u32
)walk_state
->result_count
% ACPI_RESULTS_FRAME_OBJ_NUM
;
74 *object
= state
->results
.obj_desc
[index
];
77 "No result objects on result stack, State=%p",
79 return (AE_AML_NO_RETURN_VALUE
);
82 state
->results
.obj_desc
[index
] = NULL
;
84 status
= acpi_ds_result_stack_pop(walk_state
);
85 if (ACPI_FAILURE(status
)) {
90 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
,
91 "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object
,
92 acpi_ut_get_object_type_name(*object
),
93 index
, walk_state
, walk_state
->result_count
));
98 /*******************************************************************************
100 * FUNCTION: acpi_ds_result_push
102 * PARAMETERS: object - Where to return the popped object
103 * walk_state - Current Walk state
107 * DESCRIPTION: Push an object onto the current result stack
109 ******************************************************************************/
112 acpi_ds_result_push(union acpi_operand_object
*object
,
113 struct acpi_walk_state
*walk_state
)
115 union acpi_generic_state
*state
;
119 ACPI_FUNCTION_NAME(ds_result_push
);
121 if (walk_state
->result_count
> walk_state
->result_size
) {
122 ACPI_ERROR((AE_INFO
, "Result stack is full"));
123 return (AE_AML_INTERNAL
);
124 } else if (walk_state
->result_count
== walk_state
->result_size
) {
126 /* Extend the result stack */
128 status
= acpi_ds_result_stack_push(walk_state
);
129 if (ACPI_FAILURE(status
)) {
131 "Failed to extend the result stack"));
136 if (!(walk_state
->result_count
< walk_state
->result_size
)) {
137 ACPI_ERROR((AE_INFO
, "No free elements in result stack"));
138 return (AE_AML_INTERNAL
);
141 state
= walk_state
->results
;
143 ACPI_ERROR((AE_INFO
, "No result stack frame during push"));
144 return (AE_AML_INTERNAL
);
149 "Null Object! Obj=%p State=%p Num=%u",
150 object
, walk_state
, walk_state
->result_count
));
151 return (AE_BAD_PARAMETER
);
154 /* Assign the address of object to the top free element of result stack */
156 index
= (u32
)walk_state
->result_count
% ACPI_RESULTS_FRAME_OBJ_NUM
;
157 state
->results
.obj_desc
[index
] = object
;
158 walk_state
->result_count
++;
160 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
162 acpi_ut_get_object_type_name((union
163 acpi_operand_object
*)
165 walk_state
->result_count
,
166 walk_state
->current_result
));
171 /*******************************************************************************
173 * FUNCTION: acpi_ds_result_stack_push
175 * PARAMETERS: walk_state - Current Walk state
179 * DESCRIPTION: Push an object onto the walk_state result stack
181 ******************************************************************************/
183 static acpi_status
acpi_ds_result_stack_push(struct acpi_walk_state
*walk_state
)
185 union acpi_generic_state
*state
;
187 ACPI_FUNCTION_NAME(ds_result_stack_push
);
189 /* Check for stack overflow */
191 if (((u32
) walk_state
->result_size
+ ACPI_RESULTS_FRAME_OBJ_NUM
) >
192 ACPI_RESULTS_OBJ_NUM_MAX
) {
193 ACPI_ERROR((AE_INFO
, "Result stack overflow: State=%p Num=%u",
194 walk_state
, walk_state
->result_size
));
195 return (AE_STACK_OVERFLOW
);
198 state
= acpi_ut_create_generic_state();
200 return (AE_NO_MEMORY
);
203 state
->common
.descriptor_type
= ACPI_DESC_TYPE_STATE_RESULT
;
204 acpi_ut_push_generic_state(&walk_state
->results
, state
);
206 /* Increase the length of the result stack by the length of frame */
208 walk_state
->result_size
+= ACPI_RESULTS_FRAME_OBJ_NUM
;
210 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
, "Results=%p State=%p\n",
216 /*******************************************************************************
218 * FUNCTION: acpi_ds_result_stack_pop
220 * PARAMETERS: walk_state - Current Walk state
224 * DESCRIPTION: Pop an object off of the walk_state result stack
226 ******************************************************************************/
228 static acpi_status
acpi_ds_result_stack_pop(struct acpi_walk_state
*walk_state
)
230 union acpi_generic_state
*state
;
232 ACPI_FUNCTION_NAME(ds_result_stack_pop
);
234 /* Check for stack underflow */
236 if (walk_state
->results
== NULL
) {
237 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
,
238 "Result stack underflow - State=%p\n",
240 return (AE_AML_NO_OPERAND
);
243 if (walk_state
->result_size
< ACPI_RESULTS_FRAME_OBJ_NUM
) {
244 ACPI_ERROR((AE_INFO
, "Insufficient result stack size"));
245 return (AE_AML_INTERNAL
);
248 state
= acpi_ut_pop_generic_state(&walk_state
->results
);
249 acpi_ut_delete_generic_state(state
);
251 /* Decrease the length of result stack by the length of frame */
253 walk_state
->result_size
-= ACPI_RESULTS_FRAME_OBJ_NUM
;
255 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
,
256 "Result=%p RemainingResults=%X State=%p\n",
257 state
, walk_state
->result_count
, walk_state
));
262 /*******************************************************************************
264 * FUNCTION: acpi_ds_obj_stack_push
266 * PARAMETERS: object - Object to push
267 * walk_state - Current Walk state
271 * DESCRIPTION: Push an object onto this walk's object/operand stack
273 ******************************************************************************/
276 acpi_ds_obj_stack_push(void *object
, struct acpi_walk_state
*walk_state
)
278 ACPI_FUNCTION_NAME(ds_obj_stack_push
);
280 /* Check for stack overflow */
282 if (walk_state
->num_operands
>= ACPI_OBJ_NUM_OPERANDS
) {
284 "Object stack overflow! Obj=%p State=%p #Ops=%u",
285 object
, walk_state
, walk_state
->num_operands
));
286 return (AE_STACK_OVERFLOW
);
289 /* Put the object onto the stack */
291 walk_state
->operands
[walk_state
->operand_index
] = object
;
292 walk_state
->num_operands
++;
294 /* For the usual order of filling the operand stack */
296 walk_state
->operand_index
++;
298 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
, "Obj=%p [%s] State=%p #Ops=%X\n",
300 acpi_ut_get_object_type_name((union
301 acpi_operand_object
*)
303 walk_state
->num_operands
));
308 /*******************************************************************************
310 * FUNCTION: acpi_ds_obj_stack_pop
312 * PARAMETERS: pop_count - Number of objects/entries to pop
313 * walk_state - Current Walk state
317 * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
318 * deleted by this routine.
320 ******************************************************************************/
323 acpi_ds_obj_stack_pop(u32 pop_count
, struct acpi_walk_state
*walk_state
)
327 ACPI_FUNCTION_NAME(ds_obj_stack_pop
);
329 for (i
= 0; i
< pop_count
; i
++) {
331 /* Check for stack underflow */
333 if (walk_state
->num_operands
== 0) {
335 "Object stack underflow! Count=%X State=%p #Ops=%u",
336 pop_count
, walk_state
,
337 walk_state
->num_operands
));
338 return (AE_STACK_UNDERFLOW
);
341 /* Just set the stack entry to null */
343 walk_state
->num_operands
--;
344 walk_state
->operands
[walk_state
->num_operands
] = NULL
;
347 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
, "Count=%X State=%p #Ops=%u\n",
348 pop_count
, walk_state
, walk_state
->num_operands
));
353 /*******************************************************************************
355 * FUNCTION: acpi_ds_obj_stack_pop_and_delete
357 * PARAMETERS: pop_count - Number of objects/entries to pop
358 * walk_state - Current Walk state
362 * DESCRIPTION: Pop this walk's object stack and delete each object that is
365 ******************************************************************************/
368 acpi_ds_obj_stack_pop_and_delete(u32 pop_count
,
369 struct acpi_walk_state
*walk_state
)
372 union acpi_operand_object
*obj_desc
;
374 ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete
);
376 if (pop_count
== 0) {
380 for (i
= (s32
)pop_count
- 1; i
>= 0; i
--) {
381 if (walk_state
->num_operands
== 0) {
385 /* Pop the stack and delete an object if present in this stack entry */
387 walk_state
->num_operands
--;
388 obj_desc
= walk_state
->operands
[i
];
390 acpi_ut_remove_reference(walk_state
->operands
[i
]);
391 walk_state
->operands
[i
] = NULL
;
395 ACPI_DEBUG_PRINT((ACPI_DB_EXEC
, "Count=%X State=%p #Ops=%X\n",
396 pop_count
, walk_state
, walk_state
->num_operands
));
399 /*******************************************************************************
401 * FUNCTION: acpi_ds_get_current_walk_state
403 * PARAMETERS: thread - Get current active state for this Thread
405 * RETURN: Pointer to the current walk state
407 * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
410 ******************************************************************************/
412 struct acpi_walk_state
*acpi_ds_get_current_walk_state(struct acpi_thread_state
415 ACPI_FUNCTION_NAME(ds_get_current_walk_state
);
421 ACPI_DEBUG_PRINT((ACPI_DB_PARSE
, "Current WalkState %p\n",
422 thread
->walk_state_list
));
424 return (thread
->walk_state_list
);
427 /*******************************************************************************
429 * FUNCTION: acpi_ds_push_walk_state
431 * PARAMETERS: walk_state - State to push
432 * thread - Thread state object
436 * DESCRIPTION: Place the Thread state at the head of the state list
438 ******************************************************************************/
441 acpi_ds_push_walk_state(struct acpi_walk_state
*walk_state
,
442 struct acpi_thread_state
*thread
)
444 ACPI_FUNCTION_TRACE(ds_push_walk_state
);
446 walk_state
->next
= thread
->walk_state_list
;
447 thread
->walk_state_list
= walk_state
;
452 /*******************************************************************************
454 * FUNCTION: acpi_ds_pop_walk_state
456 * PARAMETERS: thread - Current thread state
458 * RETURN: A walk_state object popped from the thread's stack
460 * DESCRIPTION: Remove and return the walkstate object that is at the head of
461 * the walk stack for the given walk list. NULL indicates that
464 ******************************************************************************/
466 struct acpi_walk_state
*acpi_ds_pop_walk_state(struct acpi_thread_state
*thread
)
468 struct acpi_walk_state
*walk_state
;
470 ACPI_FUNCTION_TRACE(ds_pop_walk_state
);
472 walk_state
= thread
->walk_state_list
;
476 /* Next walk state becomes the current walk state */
478 thread
->walk_state_list
= walk_state
->next
;
481 * Don't clear the NEXT field, this serves as an indicator
482 * that there is a parent WALK STATE
483 * Do Not: walk_state->Next = NULL;
487 return_PTR(walk_state
);
490 /*******************************************************************************
492 * FUNCTION: acpi_ds_create_walk_state
494 * PARAMETERS: owner_id - ID for object creation
495 * origin - Starting point for this walk
496 * method_desc - Method object
497 * thread - Current thread state
499 * RETURN: Pointer to the new walk state.
501 * DESCRIPTION: Allocate and initialize a new walk state. The current walk
502 * state is set to this new state.
504 ******************************************************************************/
506 struct acpi_walk_state
*acpi_ds_create_walk_state(acpi_owner_id owner_id
,
507 union acpi_parse_object
509 union acpi_operand_object
511 struct acpi_thread_state
514 struct acpi_walk_state
*walk_state
;
516 ACPI_FUNCTION_TRACE(ds_create_walk_state
);
518 walk_state
= ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state
));
523 walk_state
->descriptor_type
= ACPI_DESC_TYPE_WALK
;
524 walk_state
->method_desc
= method_desc
;
525 walk_state
->owner_id
= owner_id
;
526 walk_state
->origin
= origin
;
527 walk_state
->thread
= thread
;
529 walk_state
->parser_state
.start_op
= origin
;
531 /* Init the method args/local */
533 #ifndef ACPI_CONSTANT_EVAL_ONLY
534 acpi_ds_method_data_init(walk_state
);
537 /* Put the new state at the head of the walk list */
540 acpi_ds_push_walk_state(walk_state
, thread
);
543 return_PTR(walk_state
);
546 /*******************************************************************************
548 * FUNCTION: acpi_ds_init_aml_walk
550 * PARAMETERS: walk_state - New state to be initialized
551 * op - Current parse op
552 * method_node - Control method NS node, if any
553 * aml_start - Start of AML
554 * aml_length - Length of AML
555 * info - Method info block (params, etc.)
556 * pass_number - 1, 2, or 3
560 * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
562 ******************************************************************************/
565 acpi_ds_init_aml_walk(struct acpi_walk_state
*walk_state
,
566 union acpi_parse_object
*op
,
567 struct acpi_namespace_node
*method_node
,
570 struct acpi_evaluate_info
*info
, u8 pass_number
)
573 struct acpi_parse_state
*parser_state
= &walk_state
->parser_state
;
574 union acpi_parse_object
*extra_op
;
576 ACPI_FUNCTION_TRACE(ds_init_aml_walk
);
578 walk_state
->parser_state
.aml
=
579 walk_state
->parser_state
.aml_start
= aml_start
;
580 walk_state
->parser_state
.aml_end
=
581 walk_state
->parser_state
.pkg_end
= aml_start
+ aml_length
;
583 /* The next_op of the next_walk will be the beginning of the method */
585 walk_state
->next_op
= NULL
;
586 walk_state
->pass_number
= pass_number
;
589 walk_state
->params
= info
->parameters
;
590 walk_state
->caller_return_desc
= &info
->return_object
;
593 status
= acpi_ps_init_scope(&walk_state
->parser_state
, op
);
594 if (ACPI_FAILURE(status
)) {
595 return_ACPI_STATUS(status
);
599 walk_state
->parser_state
.start_node
= method_node
;
600 walk_state
->walk_type
= ACPI_WALK_METHOD
;
601 walk_state
->method_node
= method_node
;
602 walk_state
->method_desc
=
603 acpi_ns_get_attached_object(method_node
);
605 /* Push start scope on scope stack and make it current */
608 acpi_ds_scope_stack_push(method_node
, ACPI_TYPE_METHOD
,
610 if (ACPI_FAILURE(status
)) {
611 return_ACPI_STATUS(status
);
614 /* Init the method arguments */
616 status
= acpi_ds_method_data_init_args(walk_state
->params
,
617 ACPI_METHOD_NUM_ARGS
,
619 if (ACPI_FAILURE(status
)) {
620 return_ACPI_STATUS(status
);
624 * Setup the current scope.
625 * Find a Named Op that has a namespace node associated with it.
626 * search upwards from this Op. Current scope is the first
627 * Op with a namespace node.
629 extra_op
= parser_state
->start_op
;
630 while (extra_op
&& !extra_op
->common
.node
) {
631 extra_op
= extra_op
->common
.parent
;
635 parser_state
->start_node
= NULL
;
637 parser_state
->start_node
= extra_op
->common
.node
;
640 if (parser_state
->start_node
) {
642 /* Push start scope on scope stack and make it current */
645 acpi_ds_scope_stack_push(parser_state
->start_node
,
646 parser_state
->start_node
->
648 if (ACPI_FAILURE(status
)) {
649 return_ACPI_STATUS(status
);
654 status
= acpi_ds_init_callbacks(walk_state
, pass_number
);
655 return_ACPI_STATUS(status
);
658 /*******************************************************************************
660 * FUNCTION: acpi_ds_delete_walk_state
662 * PARAMETERS: walk_state - State to delete
666 * DESCRIPTION: Delete a walk state including all internal data structures
668 ******************************************************************************/
670 void acpi_ds_delete_walk_state(struct acpi_walk_state
*walk_state
)
672 union acpi_generic_state
*state
;
674 ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state
, walk_state
);
680 if (walk_state
->descriptor_type
!= ACPI_DESC_TYPE_WALK
) {
681 ACPI_ERROR((AE_INFO
, "%p is not a valid walk state",
686 /* There should not be any open scopes */
688 if (walk_state
->parser_state
.scope
) {
689 ACPI_ERROR((AE_INFO
, "%p walk still has a scope list",
691 acpi_ps_cleanup_scope(&walk_state
->parser_state
);
694 /* Always must free any linked control states */
696 while (walk_state
->control_state
) {
697 state
= walk_state
->control_state
;
698 walk_state
->control_state
= state
->common
.next
;
700 acpi_ut_delete_generic_state(state
);
703 /* Always must free any linked parse states */
705 while (walk_state
->scope_info
) {
706 state
= walk_state
->scope_info
;
707 walk_state
->scope_info
= state
->common
.next
;
709 acpi_ut_delete_generic_state(state
);
712 /* Always must free any stacked result states */
714 while (walk_state
->results
) {
715 state
= walk_state
->results
;
716 walk_state
->results
= state
->common
.next
;
718 acpi_ut_delete_generic_state(state
);
721 ACPI_FREE(walk_state
);