Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 : : /******************************************************************************
3 : : *
4 : : * Module Name: dswstate - Dispatcher parse tree walk 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 "acdispat.h"
14 : : #include "acnamesp.h"
15 : :
16 : : #define _COMPONENT ACPI_DISPATCHER
17 : : ACPI_MODULE_NAME("dswstate")
18 : :
19 : : /* Local prototypes */
20 : : static acpi_status
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);
23 : :
24 : : /*******************************************************************************
25 : : *
26 : : * FUNCTION: acpi_ds_result_pop
27 : : *
28 : : * PARAMETERS: object - Where to return the popped object
29 : : * walk_state - Current Walk state
30 : : *
31 : : * RETURN: Status
32 : : *
33 : : * DESCRIPTION: Pop an object off the top of this walk's result stack
34 : : *
35 : : ******************************************************************************/
36 : :
37 : : acpi_status
38 : 9108 : acpi_ds_result_pop(union acpi_operand_object **object,
39 : : struct acpi_walk_state *walk_state)
40 : : {
41 : 9108 : u32 index;
42 : 9108 : union acpi_generic_state *state;
43 : 9108 : acpi_status status;
44 : :
45 : 9108 : ACPI_FUNCTION_NAME(ds_result_pop);
46 : :
47 : 9108 : state = walk_state->results;
48 : :
49 : : /* Incorrect state of result stack */
50 : :
51 [ + - - + ]: 9108 : if (state && !walk_state->result_count) {
52 : 0 : ACPI_ERROR((AE_INFO, "No results on result stack"));
53 : 0 : return (AE_AML_INTERNAL);
54 : : }
55 : :
56 [ - + - - ]: 9108 : if (!state && walk_state->result_count) {
57 : 0 : ACPI_ERROR((AE_INFO, "No result state for result stack"));
58 : 0 : return (AE_AML_INTERNAL);
59 : : }
60 : :
61 : : /* Empty result stack */
62 : :
63 [ - + ]: 9108 : if (!state) {
64 : 0 : ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p",
65 : : walk_state));
66 : 0 : return (AE_AML_NO_RETURN_VALUE);
67 : : }
68 : :
69 : : /* Return object of the top element and clean that top element result stack */
70 : :
71 : 9108 : walk_state->result_count--;
72 : 9108 : index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
73 : :
74 : 9108 : *object = state->results.obj_desc[index];
75 [ - + ]: 9108 : if (!*object) {
76 : 0 : ACPI_ERROR((AE_INFO,
77 : : "No result objects on result stack, State=%p",
78 : : walk_state));
79 : 0 : return (AE_AML_NO_RETURN_VALUE);
80 : : }
81 : :
82 : 9108 : state->results.obj_desc[index] = NULL;
83 [ + + ]: 9108 : if (index == 0) {
84 : 8316 : status = acpi_ds_result_stack_pop(walk_state);
85 : 8316 : if (ACPI_FAILURE(status)) {
86 : : return (status);
87 : : }
88 : : }
89 : :
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));
94 : :
95 : : return (AE_OK);
96 : : }
97 : :
98 : : /*******************************************************************************
99 : : *
100 : : * FUNCTION: acpi_ds_result_push
101 : : *
102 : : * PARAMETERS: object - Where to return the popped object
103 : : * walk_state - Current Walk state
104 : : *
105 : : * RETURN: Status
106 : : *
107 : : * DESCRIPTION: Push an object onto the current result stack
108 : : *
109 : : ******************************************************************************/
110 : :
111 : : acpi_status
112 : 9192 : acpi_ds_result_push(union acpi_operand_object *object,
113 : : struct acpi_walk_state *walk_state)
114 : : {
115 : 9192 : union acpi_generic_state *state;
116 : 9192 : acpi_status status;
117 : 9192 : u32 index;
118 : :
119 : 9192 : ACPI_FUNCTION_NAME(ds_result_push);
120 : :
121 [ - + ]: 9192 : if (walk_state->result_count > walk_state->result_size) {
122 : 0 : ACPI_ERROR((AE_INFO, "Result stack is full"));
123 : 0 : return (AE_AML_INTERNAL);
124 [ + + ]: 9192 : } else if (walk_state->result_count == walk_state->result_size) {
125 : :
126 : : /* Extend the result stack */
127 : :
128 : 8400 : status = acpi_ds_result_stack_push(walk_state);
129 [ - + ]: 8400 : if (ACPI_FAILURE(status)) {
130 : 0 : ACPI_ERROR((AE_INFO,
131 : : "Failed to extend the result stack"));
132 : 0 : return (status);
133 : : }
134 : : }
135 : :
136 [ - + ]: 9192 : if (!(walk_state->result_count < walk_state->result_size)) {
137 : 0 : ACPI_ERROR((AE_INFO, "No free elements in result stack"));
138 : 0 : return (AE_AML_INTERNAL);
139 : : }
140 : :
141 : 9192 : state = walk_state->results;
142 [ - + ]: 9192 : if (!state) {
143 : 0 : ACPI_ERROR((AE_INFO, "No result stack frame during push"));
144 : 0 : return (AE_AML_INTERNAL);
145 : : }
146 : :
147 [ - + ]: 9192 : if (!object) {
148 : 0 : ACPI_ERROR((AE_INFO,
149 : : "Null Object! Obj=%p State=%p Num=%u",
150 : : object, walk_state, walk_state->result_count));
151 : 0 : return (AE_BAD_PARAMETER);
152 : : }
153 : :
154 : : /* Assign the address of object to the top free element of result stack */
155 : :
156 : 9192 : index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM;
157 : 9192 : state->results.obj_desc[index] = object;
158 : 9192 : walk_state->result_count++;
159 : :
160 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n",
161 : : object,
162 : : acpi_ut_get_object_type_name((union
163 : : acpi_operand_object *)
164 : : object), walk_state,
165 : : walk_state->result_count,
166 : 9192 : walk_state->current_result));
167 : :
168 : 9192 : return (AE_OK);
169 : : }
170 : :
171 : : /*******************************************************************************
172 : : *
173 : : * FUNCTION: acpi_ds_result_stack_push
174 : : *
175 : : * PARAMETERS: walk_state - Current Walk state
176 : : *
177 : : * RETURN: Status
178 : : *
179 : : * DESCRIPTION: Push an object onto the walk_state result stack
180 : : *
181 : : ******************************************************************************/
182 : :
183 : 8400 : static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state)
184 : : {
185 : 8400 : union acpi_generic_state *state;
186 : :
187 : 8400 : ACPI_FUNCTION_NAME(ds_result_stack_push);
188 : :
189 : : /* Check for stack overflow */
190 : :
191 [ - + ]: 8400 : if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) >
192 : : ACPI_RESULTS_OBJ_NUM_MAX) {
193 : 0 : ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%u",
194 : : walk_state, walk_state->result_size));
195 : 0 : return (AE_STACK_OVERFLOW);
196 : : }
197 : :
198 : 8400 : state = acpi_ut_create_generic_state();
199 [ + - ]: 8400 : if (!state) {
200 : : return (AE_NO_MEMORY);
201 : : }
202 : :
203 : 8400 : state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT;
204 : 8400 : acpi_ut_push_generic_state(&walk_state->results, state);
205 : :
206 : : /* Increase the length of the result stack by the length of frame */
207 : :
208 : 8400 : walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM;
209 : :
210 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n",
211 : 8400 : state, walk_state));
212 : :
213 : 8400 : return (AE_OK);
214 : : }
215 : :
216 : : /*******************************************************************************
217 : : *
218 : : * FUNCTION: acpi_ds_result_stack_pop
219 : : *
220 : : * PARAMETERS: walk_state - Current Walk state
221 : : *
222 : : * RETURN: Status
223 : : *
224 : : * DESCRIPTION: Pop an object off of the walk_state result stack
225 : : *
226 : : ******************************************************************************/
227 : :
228 : 8316 : static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state)
229 : : {
230 : 8316 : union acpi_generic_state *state;
231 : :
232 : 8316 : ACPI_FUNCTION_NAME(ds_result_stack_pop);
233 : :
234 : : /* Check for stack underflow */
235 : :
236 [ + - ]: 8316 : if (walk_state->results == NULL) {
237 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
238 : : "Result stack underflow - State=%p\n",
239 : : walk_state));
240 : : return (AE_AML_NO_OPERAND);
241 : : }
242 : :
243 [ - + ]: 8316 : if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) {
244 : 0 : ACPI_ERROR((AE_INFO, "Insufficient result stack size"));
245 : 0 : return (AE_AML_INTERNAL);
246 : : }
247 : :
248 : 8316 : state = acpi_ut_pop_generic_state(&walk_state->results);
249 : 8316 : acpi_ut_delete_generic_state(state);
250 : :
251 : : /* Decrease the length of result stack by the length of frame */
252 : :
253 : 8316 : walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM;
254 : :
255 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
256 : : "Result=%p RemainingResults=%X State=%p\n",
257 : 8316 : state, walk_state->result_count, walk_state));
258 : :
259 : 8316 : return (AE_OK);
260 : : }
261 : :
262 : : /*******************************************************************************
263 : : *
264 : : * FUNCTION: acpi_ds_obj_stack_push
265 : : *
266 : : * PARAMETERS: object - Object to push
267 : : * walk_state - Current Walk state
268 : : *
269 : : * RETURN: Status
270 : : *
271 : : * DESCRIPTION: Push an object onto this walk's object/operand stack
272 : : *
273 : : ******************************************************************************/
274 : :
275 : : acpi_status
276 : 21522 : acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state)
277 : : {
278 : 21522 : ACPI_FUNCTION_NAME(ds_obj_stack_push);
279 : :
280 : : /* Check for stack overflow */
281 : :
282 [ - + ]: 21522 : if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) {
283 : 0 : ACPI_ERROR((AE_INFO,
284 : : "Object stack overflow! Obj=%p State=%p #Ops=%u",
285 : : object, walk_state, walk_state->num_operands));
286 : 0 : return (AE_STACK_OVERFLOW);
287 : : }
288 : :
289 : : /* Put the object onto the stack */
290 : :
291 : 21522 : walk_state->operands[walk_state->operand_index] = object;
292 : 21522 : walk_state->num_operands++;
293 : :
294 : : /* For the usual order of filling the operand stack */
295 : :
296 : 21522 : walk_state->operand_index++;
297 : :
298 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n",
299 : : object,
300 : : acpi_ut_get_object_type_name((union
301 : : acpi_operand_object *)
302 : : object), walk_state,
303 : 21522 : walk_state->num_operands));
304 : :
305 : 21522 : return (AE_OK);
306 : : }
307 : :
308 : : /*******************************************************************************
309 : : *
310 : : * FUNCTION: acpi_ds_obj_stack_pop
311 : : *
312 : : * PARAMETERS: pop_count - Number of objects/entries to pop
313 : : * walk_state - Current Walk state
314 : : *
315 : : * RETURN: Status
316 : : *
317 : : * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT
318 : : * deleted by this routine.
319 : : *
320 : : ******************************************************************************/
321 : :
322 : : acpi_status
323 : 705 : acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state)
324 : : {
325 : 705 : u32 i;
326 : :
327 : 705 : ACPI_FUNCTION_NAME(ds_obj_stack_pop);
328 : :
329 [ + + ]: 1410 : for (i = 0; i < pop_count; i++) {
330 : :
331 : : /* Check for stack underflow */
332 : :
333 [ - + ]: 705 : if (walk_state->num_operands == 0) {
334 : 0 : ACPI_ERROR((AE_INFO,
335 : : "Object stack underflow! Count=%X State=%p #Ops=%u",
336 : : pop_count, walk_state,
337 : : walk_state->num_operands));
338 : 0 : return (AE_STACK_UNDERFLOW);
339 : : }
340 : :
341 : : /* Just set the stack entry to null */
342 : :
343 : 705 : walk_state->num_operands--;
344 : 705 : walk_state->operands[walk_state->num_operands] = NULL;
345 : : }
346 : :
347 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%u\n",
348 : : pop_count, walk_state, walk_state->num_operands));
349 : :
350 : : return (AE_OK);
351 : : }
352 : :
353 : : /*******************************************************************************
354 : : *
355 : : * FUNCTION: acpi_ds_obj_stack_pop_and_delete
356 : : *
357 : : * PARAMETERS: pop_count - Number of objects/entries to pop
358 : : * walk_state - Current Walk state
359 : : *
360 : : * RETURN: Status
361 : : *
362 : : * DESCRIPTION: Pop this walk's object stack and delete each object that is
363 : : * popped off.
364 : : *
365 : : ******************************************************************************/
366 : :
367 : : void
368 : 0 : acpi_ds_obj_stack_pop_and_delete(u32 pop_count,
369 : : struct acpi_walk_state *walk_state)
370 : : {
371 : 0 : s32 i;
372 : 0 : union acpi_operand_object *obj_desc;
373 : :
374 : 0 : ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete);
375 : :
376 [ # # ]: 0 : if (pop_count == 0) {
377 : : return;
378 : : }
379 : :
380 [ # # ]: 0 : for (i = (s32)pop_count - 1; i >= 0; i--) {
381 [ # # ]: 0 : if (walk_state->num_operands == 0) {
382 : : return;
383 : : }
384 : :
385 : : /* Pop the stack and delete an object if present in this stack entry */
386 : :
387 : 0 : walk_state->num_operands--;
388 : 0 : obj_desc = walk_state->operands[i];
389 [ # # ]: 0 : if (obj_desc) {
390 : 0 : acpi_ut_remove_reference(walk_state->operands[i]);
391 : 0 : walk_state->operands[i] = NULL;
392 : : }
393 : : }
394 : :
395 : : ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n",
396 : 0 : pop_count, walk_state, walk_state->num_operands));
397 : : }
398 : :
399 : : /*******************************************************************************
400 : : *
401 : : * FUNCTION: acpi_ds_get_current_walk_state
402 : : *
403 : : * PARAMETERS: thread - Get current active state for this Thread
404 : : *
405 : : * RETURN: Pointer to the current walk state
406 : : *
407 : : * DESCRIPTION: Get the walk state that is at the head of the list (the "current"
408 : : * walk state.)
409 : : *
410 : : ******************************************************************************/
411 : :
412 : 615 : struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state
413 : : *thread)
414 : : {
415 : 615 : ACPI_FUNCTION_NAME(ds_get_current_walk_state);
416 : :
417 [ + - ]: 615 : if (!thread) {
418 : : return (NULL);
419 : : }
420 : :
421 : : ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n",
422 : 615 : thread->walk_state_list));
423 : :
424 : 615 : return (thread->walk_state_list);
425 : : }
426 : :
427 : : /*******************************************************************************
428 : : *
429 : : * FUNCTION: acpi_ds_push_walk_state
430 : : *
431 : : * PARAMETERS: walk_state - State to push
432 : : * thread - Thread state object
433 : : *
434 : : * RETURN: None
435 : : *
436 : : * DESCRIPTION: Place the Thread state at the head of the state list
437 : : *
438 : : ******************************************************************************/
439 : :
440 : : void
441 : 531 : acpi_ds_push_walk_state(struct acpi_walk_state *walk_state,
442 : : struct acpi_thread_state *thread)
443 : : {
444 : 531 : ACPI_FUNCTION_TRACE(ds_push_walk_state);
445 : :
446 : 531 : walk_state->next = thread->walk_state_list;
447 : 531 : thread->walk_state_list = walk_state;
448 : :
449 : 531 : return_VOID;
450 : : }
451 : :
452 : : /*******************************************************************************
453 : : *
454 : : * FUNCTION: acpi_ds_pop_walk_state
455 : : *
456 : : * PARAMETERS: thread - Current thread state
457 : : *
458 : : * RETURN: A walk_state object popped from the thread's stack
459 : : *
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
462 : : * the list is empty.
463 : : *
464 : : ******************************************************************************/
465 : :
466 : 531 : struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread)
467 : : {
468 : 531 : struct acpi_walk_state *walk_state;
469 : :
470 : 531 : ACPI_FUNCTION_TRACE(ds_pop_walk_state);
471 : :
472 : 531 : walk_state = thread->walk_state_list;
473 : :
474 [ + - ]: 531 : if (walk_state) {
475 : :
476 : : /* Next walk state becomes the current walk state */
477 : :
478 : 531 : thread->walk_state_list = walk_state->next;
479 : :
480 : : /*
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;
484 : : */
485 : : }
486 : :
487 : 531 : return_PTR(walk_state);
488 : : }
489 : :
490 : : /*******************************************************************************
491 : : *
492 : : * FUNCTION: acpi_ds_create_walk_state
493 : : *
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
498 : : *
499 : : * RETURN: Pointer to the new walk state.
500 : : *
501 : : * DESCRIPTION: Allocate and initialize a new walk state. The current walk
502 : : * state is set to this new state.
503 : : *
504 : : ******************************************************************************/
505 : :
506 : 531 : struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id,
507 : : union acpi_parse_object
508 : : *origin,
509 : : union acpi_operand_object
510 : : *method_desc,
511 : : struct acpi_thread_state
512 : : *thread)
513 : : {
514 : 531 : struct acpi_walk_state *walk_state;
515 : :
516 : 531 : ACPI_FUNCTION_TRACE(ds_create_walk_state);
517 : :
518 : 531 : walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state));
519 [ + - ]: 531 : if (!walk_state) {
520 : : return_PTR(NULL);
521 : : }
522 : :
523 : 531 : walk_state->descriptor_type = ACPI_DESC_TYPE_WALK;
524 : 531 : walk_state->method_desc = method_desc;
525 : 531 : walk_state->owner_id = owner_id;
526 : 531 : walk_state->origin = origin;
527 : 531 : walk_state->thread = thread;
528 : :
529 : 531 : walk_state->parser_state.start_op = origin;
530 : :
531 : : /* Init the method args/local */
532 : :
533 : : #ifndef ACPI_CONSTANT_EVAL_ONLY
534 : 531 : acpi_ds_method_data_init(walk_state);
535 : : #endif
536 : :
537 : : /* Put the new state at the head of the walk list */
538 : :
539 [ + + ]: 531 : if (thread) {
540 : 84 : acpi_ds_push_walk_state(walk_state, thread);
541 : : }
542 : :
543 : : return_PTR(walk_state);
544 : : }
545 : :
546 : : /*******************************************************************************
547 : : *
548 : : * FUNCTION: acpi_ds_init_aml_walk
549 : : *
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
557 : : *
558 : : * RETURN: Status
559 : : *
560 : : * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk
561 : : *
562 : : ******************************************************************************/
563 : :
564 : : acpi_status
565 : 531 : acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state,
566 : : union acpi_parse_object *op,
567 : : struct acpi_namespace_node *method_node,
568 : : u8 * aml_start,
569 : : u32 aml_length,
570 : : struct acpi_evaluate_info *info, u8 pass_number)
571 : : {
572 : 531 : acpi_status status;
573 : 531 : struct acpi_parse_state *parser_state = &walk_state->parser_state;
574 : 531 : union acpi_parse_object *extra_op;
575 : :
576 : 531 : ACPI_FUNCTION_TRACE(ds_init_aml_walk);
577 : :
578 : 531 : walk_state->parser_state.aml =
579 : 531 : walk_state->parser_state.aml_start = aml_start;
580 : 531 : walk_state->parser_state.aml_end =
581 : 531 : walk_state->parser_state.pkg_end = aml_start + aml_length;
582 : :
583 : : /* The next_op of the next_walk will be the beginning of the method */
584 : :
585 : 531 : walk_state->next_op = NULL;
586 : 531 : walk_state->pass_number = pass_number;
587 : :
588 [ + + ]: 531 : if (info) {
589 : 303 : walk_state->params = info->parameters;
590 : 303 : walk_state->caller_return_desc = &info->return_object;
591 : : }
592 : :
593 : 531 : status = acpi_ps_init_scope(&walk_state->parser_state, op);
594 [ + - ]: 531 : if (ACPI_FAILURE(status)) {
595 : : return_ACPI_STATUS(status);
596 : : }
597 : :
598 [ + + ]: 531 : if (method_node) {
599 : 507 : walk_state->parser_state.start_node = method_node;
600 : 507 : walk_state->walk_type = ACPI_WALK_METHOD;
601 : 507 : walk_state->method_node = method_node;
602 : 1014 : walk_state->method_desc =
603 : 507 : acpi_ns_get_attached_object(method_node);
604 : :
605 : : /* Push start scope on scope stack and make it current */
606 : :
607 : 507 : status =
608 : 507 : acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD,
609 : : walk_state);
610 [ + - ]: 507 : if (ACPI_FAILURE(status)) {
611 : : return_ACPI_STATUS(status);
612 : : }
613 : :
614 : : /* Init the method arguments */
615 : :
616 : 507 : status = acpi_ds_method_data_init_args(walk_state->params,
617 : : ACPI_METHOD_NUM_ARGS,
618 : : walk_state);
619 [ + - ]: 507 : if (ACPI_FAILURE(status)) {
620 : : return_ACPI_STATUS(status);
621 : : }
622 : : } else {
623 : : /*
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.
628 : : */
629 : 24 : extra_op = parser_state->start_op;
630 [ + - - + ]: 24 : while (extra_op && !extra_op->common.node) {
631 : 0 : extra_op = extra_op->common.parent;
632 : : }
633 : :
634 [ - + ]: 24 : if (!extra_op) {
635 : 0 : parser_state->start_node = NULL;
636 : : } else {
637 : 24 : parser_state->start_node = extra_op->common.node;
638 : : }
639 : :
640 [ + - ]: 24 : if (parser_state->start_node) {
641 : :
642 : : /* Push start scope on scope stack and make it current */
643 : :
644 : 24 : status =
645 : 24 : acpi_ds_scope_stack_push(parser_state->start_node,
646 : 24 : parser_state->start_node->
647 : : type, walk_state);
648 [ + - ]: 24 : if (ACPI_FAILURE(status)) {
649 : : return_ACPI_STATUS(status);
650 : : }
651 : : }
652 : : }
653 : :
654 : 531 : status = acpi_ds_init_callbacks(walk_state, pass_number);
655 : 531 : return_ACPI_STATUS(status);
656 : : }
657 : :
658 : : /*******************************************************************************
659 : : *
660 : : * FUNCTION: acpi_ds_delete_walk_state
661 : : *
662 : : * PARAMETERS: walk_state - State to delete
663 : : *
664 : : * RETURN: Status
665 : : *
666 : : * DESCRIPTION: Delete a walk state including all internal data structures
667 : : *
668 : : ******************************************************************************/
669 : :
670 : 531 : void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state)
671 : : {
672 : 531 : union acpi_generic_state *state;
673 : :
674 : 531 : ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state);
675 : :
676 [ + - ]: 531 : if (!walk_state) {
677 : : return_VOID;
678 : : }
679 : :
680 [ - + ]: 531 : if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) {
681 : 0 : ACPI_ERROR((AE_INFO, "%p is not a valid walk state",
682 : : walk_state));
683 : 0 : return_VOID;
684 : : }
685 : :
686 : : /* There should not be any open scopes */
687 : :
688 [ - + ]: 531 : if (walk_state->parser_state.scope) {
689 : 0 : ACPI_ERROR((AE_INFO, "%p walk still has a scope list",
690 : : walk_state));
691 : 0 : acpi_ps_cleanup_scope(&walk_state->parser_state);
692 : : }
693 : :
694 : : /* Always must free any linked control states */
695 : :
696 [ - + ]: 531 : while (walk_state->control_state) {
697 : 0 : state = walk_state->control_state;
698 : 0 : walk_state->control_state = state->common.next;
699 : :
700 : 0 : acpi_ut_delete_generic_state(state);
701 : : }
702 : :
703 : : /* Always must free any linked parse states */
704 : :
705 [ - + ]: 531 : while (walk_state->scope_info) {
706 : 0 : state = walk_state->scope_info;
707 : 0 : walk_state->scope_info = state->common.next;
708 : :
709 : 0 : acpi_ut_delete_generic_state(state);
710 : : }
711 : :
712 : : /* Always must free any stacked result states */
713 : :
714 [ + + ]: 615 : while (walk_state->results) {
715 : 84 : state = walk_state->results;
716 : 84 : walk_state->results = state->common.next;
717 : :
718 : 84 : acpi_ut_delete_generic_state(state);
719 : : }
720 : :
721 : 531 : ACPI_FREE(walk_state);
722 : : return_VOID;
723 : : }
|