1 | /****************************************************************************** |
2 | * |
3 | * Module Name: dswstate - Dispatcher parse tree walk management routines |
4 | * |
5 | *****************************************************************************/ |
6 | |
7 | /* |
8 | * Copyright (C) 2000 - 2016, Intel Corp. |
9 | * All rights reserved. |
10 | * |
11 | * Redistribution and use in source and binary forms, with or without |
12 | * modification, are permitted provided that the following conditions |
13 | * are met: |
14 | * 1. Redistributions of source code must retain the above copyright |
15 | * notice, this list of conditions, and the following disclaimer, |
16 | * without modification. |
17 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer |
18 | * substantially similar to the "NO WARRANTY" disclaimer below |
19 | * ("Disclaimer") and any redistribution must be conditioned upon |
20 | * including a substantially similar Disclaimer requirement for further |
21 | * binary redistribution. |
22 | * 3. Neither the names of the above-listed copyright holders nor the names |
23 | * of any contributors may be used to endorse or promote products derived |
24 | * from this software without specific prior written permission. |
25 | * |
26 | * Alternatively, this software may be distributed under the terms of the |
27 | * GNU General Public License ("GPL") version 2 as published by the Free |
28 | * Software Foundation. |
29 | * |
30 | * NO WARRANTY |
31 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS |
32 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT |
33 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR |
34 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT |
35 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL |
36 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS |
37 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) |
38 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, |
39 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING |
40 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE |
41 | * POSSIBILITY OF SUCH DAMAGES. |
42 | */ |
43 | |
44 | #include "acpi.h" |
45 | #include "accommon.h" |
46 | #include "acparser.h" |
47 | #include "acdispat.h" |
48 | #include "acnamesp.h" |
49 | |
50 | #define _COMPONENT ACPI_DISPATCHER |
51 | ACPI_MODULE_NAME ("dswstate" ) |
52 | |
53 | /* Local prototypes */ |
54 | |
55 | static ACPI_STATUS |
56 | AcpiDsResultStackPush ( |
57 | ACPI_WALK_STATE *WalkState); |
58 | |
59 | static ACPI_STATUS |
60 | AcpiDsResultStackPop ( |
61 | ACPI_WALK_STATE *WalkState); |
62 | |
63 | |
64 | /******************************************************************************* |
65 | * |
66 | * FUNCTION: AcpiDsResultPop |
67 | * |
68 | * PARAMETERS: Object - Where to return the popped object |
69 | * WalkState - Current Walk state |
70 | * |
71 | * RETURN: Status |
72 | * |
73 | * DESCRIPTION: Pop an object off the top of this walk's result stack |
74 | * |
75 | ******************************************************************************/ |
76 | |
77 | ACPI_STATUS |
78 | AcpiDsResultPop ( |
79 | ACPI_OPERAND_OBJECT **Object, |
80 | ACPI_WALK_STATE *WalkState) |
81 | { |
82 | UINT32 Index; |
83 | ACPI_GENERIC_STATE *State; |
84 | ACPI_STATUS Status; |
85 | |
86 | |
87 | ACPI_FUNCTION_NAME (DsResultPop); |
88 | |
89 | |
90 | State = WalkState->Results; |
91 | |
92 | /* Incorrect state of result stack */ |
93 | |
94 | if (State && !WalkState->ResultCount) |
95 | { |
96 | ACPI_ERROR ((AE_INFO, "No results on result stack" )); |
97 | return (AE_AML_INTERNAL); |
98 | } |
99 | |
100 | if (!State && WalkState->ResultCount) |
101 | { |
102 | ACPI_ERROR ((AE_INFO, "No result state for result stack" )); |
103 | return (AE_AML_INTERNAL); |
104 | } |
105 | |
106 | /* Empty result stack */ |
107 | |
108 | if (!State) |
109 | { |
110 | ACPI_ERROR ((AE_INFO, "Result stack is empty! State=%p" , WalkState)); |
111 | return (AE_AML_NO_RETURN_VALUE); |
112 | } |
113 | |
114 | /* Return object of the top element and clean that top element result stack */ |
115 | |
116 | WalkState->ResultCount--; |
117 | Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM; |
118 | |
119 | *Object = State->Results.ObjDesc [Index]; |
120 | if (!*Object) |
121 | { |
122 | ACPI_ERROR ((AE_INFO, "No result objects on result stack, State=%p" , |
123 | WalkState)); |
124 | return (AE_AML_NO_RETURN_VALUE); |
125 | } |
126 | |
127 | State->Results.ObjDesc [Index] = NULL; |
128 | if (Index == 0) |
129 | { |
130 | Status = AcpiDsResultStackPop (WalkState); |
131 | if (ACPI_FAILURE (Status)) |
132 | { |
133 | return (Status); |
134 | } |
135 | } |
136 | |
137 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
138 | "Obj=%p [%s] Index=%X State=%p Num=%X\n" , *Object, |
139 | AcpiUtGetObjectTypeName (*Object), |
140 | Index, WalkState, WalkState->ResultCount)); |
141 | |
142 | return (AE_OK); |
143 | } |
144 | |
145 | |
146 | /******************************************************************************* |
147 | * |
148 | * FUNCTION: AcpiDsResultPush |
149 | * |
150 | * PARAMETERS: Object - Where to return the popped object |
151 | * WalkState - Current Walk state |
152 | * |
153 | * RETURN: Status |
154 | * |
155 | * DESCRIPTION: Push an object onto the current result stack |
156 | * |
157 | ******************************************************************************/ |
158 | |
159 | ACPI_STATUS |
160 | AcpiDsResultPush ( |
161 | ACPI_OPERAND_OBJECT *Object, |
162 | ACPI_WALK_STATE *WalkState) |
163 | { |
164 | ACPI_GENERIC_STATE *State; |
165 | ACPI_STATUS Status; |
166 | UINT32 Index; |
167 | |
168 | |
169 | ACPI_FUNCTION_NAME (DsResultPush); |
170 | |
171 | |
172 | if (WalkState->ResultCount > WalkState->ResultSize) |
173 | { |
174 | ACPI_ERROR ((AE_INFO, "Result stack is full" )); |
175 | return (AE_AML_INTERNAL); |
176 | } |
177 | else if (WalkState->ResultCount == WalkState->ResultSize) |
178 | { |
179 | /* Extend the result stack */ |
180 | |
181 | Status = AcpiDsResultStackPush (WalkState); |
182 | if (ACPI_FAILURE (Status)) |
183 | { |
184 | ACPI_ERROR ((AE_INFO, "Failed to extend the result stack" )); |
185 | return (Status); |
186 | } |
187 | } |
188 | |
189 | if (!(WalkState->ResultCount < WalkState->ResultSize)) |
190 | { |
191 | ACPI_ERROR ((AE_INFO, "No free elements in result stack" )); |
192 | return (AE_AML_INTERNAL); |
193 | } |
194 | |
195 | State = WalkState->Results; |
196 | if (!State) |
197 | { |
198 | ACPI_ERROR ((AE_INFO, "No result stack frame during push" )); |
199 | return (AE_AML_INTERNAL); |
200 | } |
201 | |
202 | if (!Object) |
203 | { |
204 | ACPI_ERROR ((AE_INFO, |
205 | "Null Object! Obj=%p State=%p Num=%u" , |
206 | Object, WalkState, WalkState->ResultCount)); |
207 | return (AE_BAD_PARAMETER); |
208 | } |
209 | |
210 | /* Assign the address of object to the top free element of result stack */ |
211 | |
212 | Index = (UINT32) WalkState->ResultCount % ACPI_RESULTS_FRAME_OBJ_NUM; |
213 | State->Results.ObjDesc [Index] = Object; |
214 | WalkState->ResultCount++; |
215 | |
216 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n" , |
217 | Object, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT *) Object), |
218 | WalkState, WalkState->ResultCount, WalkState->CurrentResult)); |
219 | |
220 | return (AE_OK); |
221 | } |
222 | |
223 | |
224 | /******************************************************************************* |
225 | * |
226 | * FUNCTION: AcpiDsResultStackPush |
227 | * |
228 | * PARAMETERS: WalkState - Current Walk state |
229 | * |
230 | * RETURN: Status |
231 | * |
232 | * DESCRIPTION: Push an object onto the WalkState result stack |
233 | * |
234 | ******************************************************************************/ |
235 | |
236 | static ACPI_STATUS |
237 | AcpiDsResultStackPush ( |
238 | ACPI_WALK_STATE *WalkState) |
239 | { |
240 | ACPI_GENERIC_STATE *State; |
241 | |
242 | |
243 | ACPI_FUNCTION_NAME (DsResultStackPush); |
244 | |
245 | |
246 | /* Check for stack overflow */ |
247 | |
248 | if (((UINT32) WalkState->ResultSize + ACPI_RESULTS_FRAME_OBJ_NUM) > |
249 | ACPI_RESULTS_OBJ_NUM_MAX) |
250 | { |
251 | ACPI_ERROR ((AE_INFO, "Result stack overflow: State=%p Num=%u" , |
252 | WalkState, WalkState->ResultSize)); |
253 | return (AE_STACK_OVERFLOW); |
254 | } |
255 | |
256 | State = AcpiUtCreateGenericState (); |
257 | if (!State) |
258 | { |
259 | return (AE_NO_MEMORY); |
260 | } |
261 | |
262 | State->Common.DescriptorType = ACPI_DESC_TYPE_STATE_RESULT; |
263 | AcpiUtPushGenericState (&WalkState->Results, State); |
264 | |
265 | /* Increase the length of the result stack by the length of frame */ |
266 | |
267 | WalkState->ResultSize += ACPI_RESULTS_FRAME_OBJ_NUM; |
268 | |
269 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Results=%p State=%p\n" , |
270 | State, WalkState)); |
271 | |
272 | return (AE_OK); |
273 | } |
274 | |
275 | |
276 | /******************************************************************************* |
277 | * |
278 | * FUNCTION: AcpiDsResultStackPop |
279 | * |
280 | * PARAMETERS: WalkState - Current Walk state |
281 | * |
282 | * RETURN: Status |
283 | * |
284 | * DESCRIPTION: Pop an object off of the WalkState result stack |
285 | * |
286 | ******************************************************************************/ |
287 | |
288 | static ACPI_STATUS |
289 | AcpiDsResultStackPop ( |
290 | ACPI_WALK_STATE *WalkState) |
291 | { |
292 | ACPI_GENERIC_STATE *State; |
293 | |
294 | |
295 | ACPI_FUNCTION_NAME (DsResultStackPop); |
296 | |
297 | |
298 | /* Check for stack underflow */ |
299 | |
300 | if (WalkState->Results == NULL) |
301 | { |
302 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
303 | "Result stack underflow - State=%p\n" , WalkState)); |
304 | return (AE_AML_NO_OPERAND); |
305 | } |
306 | |
307 | if (WalkState->ResultSize < ACPI_RESULTS_FRAME_OBJ_NUM) |
308 | { |
309 | ACPI_ERROR ((AE_INFO, "Insufficient result stack size" )); |
310 | return (AE_AML_INTERNAL); |
311 | } |
312 | |
313 | State = AcpiUtPopGenericState (&WalkState->Results); |
314 | AcpiUtDeleteGenericState (State); |
315 | |
316 | /* Decrease the length of result stack by the length of frame */ |
317 | |
318 | WalkState->ResultSize -= ACPI_RESULTS_FRAME_OBJ_NUM; |
319 | |
320 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, |
321 | "Result=%p RemainingResults=%X State=%p\n" , |
322 | State, WalkState->ResultCount, WalkState)); |
323 | |
324 | return (AE_OK); |
325 | } |
326 | |
327 | |
328 | /******************************************************************************* |
329 | * |
330 | * FUNCTION: AcpiDsObjStackPush |
331 | * |
332 | * PARAMETERS: Object - Object to push |
333 | * WalkState - Current Walk state |
334 | * |
335 | * RETURN: Status |
336 | * |
337 | * DESCRIPTION: Push an object onto this walk's object/operand stack |
338 | * |
339 | ******************************************************************************/ |
340 | |
341 | ACPI_STATUS |
342 | AcpiDsObjStackPush ( |
343 | void *Object, |
344 | ACPI_WALK_STATE *WalkState) |
345 | { |
346 | ACPI_FUNCTION_NAME (DsObjStackPush); |
347 | |
348 | |
349 | /* Check for stack overflow */ |
350 | |
351 | if (WalkState->NumOperands >= ACPI_OBJ_NUM_OPERANDS) |
352 | { |
353 | ACPI_ERROR ((AE_INFO, |
354 | "Object stack overflow! Obj=%p State=%p #Ops=%u" , |
355 | Object, WalkState, WalkState->NumOperands)); |
356 | return (AE_STACK_OVERFLOW); |
357 | } |
358 | |
359 | /* Put the object onto the stack */ |
360 | |
361 | WalkState->Operands [WalkState->OperandIndex] = Object; |
362 | WalkState->NumOperands++; |
363 | |
364 | /* For the usual order of filling the operand stack */ |
365 | |
366 | WalkState->OperandIndex++; |
367 | |
368 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n" , |
369 | Object, AcpiUtGetObjectTypeName ((ACPI_OPERAND_OBJECT *) Object), |
370 | WalkState, WalkState->NumOperands)); |
371 | |
372 | return (AE_OK); |
373 | } |
374 | |
375 | |
376 | /******************************************************************************* |
377 | * |
378 | * FUNCTION: AcpiDsObjStackPop |
379 | * |
380 | * PARAMETERS: PopCount - Number of objects/entries to pop |
381 | * WalkState - Current Walk state |
382 | * |
383 | * RETURN: Status |
384 | * |
385 | * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT |
386 | * deleted by this routine. |
387 | * |
388 | ******************************************************************************/ |
389 | |
390 | ACPI_STATUS |
391 | AcpiDsObjStackPop ( |
392 | UINT32 PopCount, |
393 | ACPI_WALK_STATE *WalkState) |
394 | { |
395 | UINT32 i; |
396 | |
397 | |
398 | ACPI_FUNCTION_NAME (DsObjStackPop); |
399 | |
400 | |
401 | for (i = 0; i < PopCount; i++) |
402 | { |
403 | /* Check for stack underflow */ |
404 | |
405 | if (WalkState->NumOperands == 0) |
406 | { |
407 | ACPI_ERROR ((AE_INFO, |
408 | "Object stack underflow! Count=%X State=%p #Ops=%u" , |
409 | PopCount, WalkState, WalkState->NumOperands)); |
410 | return (AE_STACK_UNDERFLOW); |
411 | } |
412 | |
413 | /* Just set the stack entry to null */ |
414 | |
415 | WalkState->NumOperands--; |
416 | WalkState->Operands [WalkState->NumOperands] = NULL; |
417 | } |
418 | |
419 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%u\n" , |
420 | PopCount, WalkState, WalkState->NumOperands)); |
421 | |
422 | return (AE_OK); |
423 | } |
424 | |
425 | |
426 | /******************************************************************************* |
427 | * |
428 | * FUNCTION: AcpiDsObjStackPopAndDelete |
429 | * |
430 | * PARAMETERS: PopCount - Number of objects/entries to pop |
431 | * WalkState - Current Walk state |
432 | * |
433 | * RETURN: Status |
434 | * |
435 | * DESCRIPTION: Pop this walk's object stack and delete each object that is |
436 | * popped off. |
437 | * |
438 | ******************************************************************************/ |
439 | |
440 | void |
441 | AcpiDsObjStackPopAndDelete ( |
442 | UINT32 PopCount, |
443 | ACPI_WALK_STATE *WalkState) |
444 | { |
445 | INT32 i; |
446 | ACPI_OPERAND_OBJECT *ObjDesc; |
447 | |
448 | |
449 | ACPI_FUNCTION_NAME (DsObjStackPopAndDelete); |
450 | |
451 | |
452 | if (PopCount == 0) |
453 | { |
454 | return; |
455 | } |
456 | |
457 | for (i = (INT32) PopCount - 1; i >= 0; i--) |
458 | { |
459 | if (WalkState->NumOperands == 0) |
460 | { |
461 | return; |
462 | } |
463 | |
464 | /* Pop the stack and delete an object if present in this stack entry */ |
465 | |
466 | WalkState->NumOperands--; |
467 | ObjDesc = WalkState->Operands [i]; |
468 | if (ObjDesc) |
469 | { |
470 | AcpiUtRemoveReference (WalkState->Operands [i]); |
471 | WalkState->Operands [i] = NULL; |
472 | } |
473 | } |
474 | |
475 | ACPI_DEBUG_PRINT ((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n" , |
476 | PopCount, WalkState, WalkState->NumOperands)); |
477 | } |
478 | |
479 | |
480 | /******************************************************************************* |
481 | * |
482 | * FUNCTION: AcpiDsGetCurrentWalkState |
483 | * |
484 | * PARAMETERS: Thread - Get current active state for this Thread |
485 | * |
486 | * RETURN: Pointer to the current walk state |
487 | * |
488 | * DESCRIPTION: Get the walk state that is at the head of the list (the "current" |
489 | * walk state.) |
490 | * |
491 | ******************************************************************************/ |
492 | |
493 | ACPI_WALK_STATE * |
494 | AcpiDsGetCurrentWalkState ( |
495 | ACPI_THREAD_STATE *Thread) |
496 | { |
497 | ACPI_FUNCTION_NAME (DsGetCurrentWalkState); |
498 | |
499 | |
500 | if (!Thread) |
501 | { |
502 | return (NULL); |
503 | } |
504 | |
505 | ACPI_DEBUG_PRINT ((ACPI_DB_PARSE, "Current WalkState %p\n" , |
506 | Thread->WalkStateList)); |
507 | |
508 | return (Thread->WalkStateList); |
509 | } |
510 | |
511 | |
512 | /******************************************************************************* |
513 | * |
514 | * FUNCTION: AcpiDsPushWalkState |
515 | * |
516 | * PARAMETERS: WalkState - State to push |
517 | * Thread - Thread state object |
518 | * |
519 | * RETURN: None |
520 | * |
521 | * DESCRIPTION: Place the Thread state at the head of the state list |
522 | * |
523 | ******************************************************************************/ |
524 | |
525 | void |
526 | AcpiDsPushWalkState ( |
527 | ACPI_WALK_STATE *WalkState, |
528 | ACPI_THREAD_STATE *Thread) |
529 | { |
530 | ACPI_FUNCTION_TRACE (DsPushWalkState); |
531 | |
532 | |
533 | WalkState->Next = Thread->WalkStateList; |
534 | Thread->WalkStateList = WalkState; |
535 | |
536 | return_VOID; |
537 | } |
538 | |
539 | |
540 | /******************************************************************************* |
541 | * |
542 | * FUNCTION: AcpiDsPopWalkState |
543 | * |
544 | * PARAMETERS: Thread - Current thread state |
545 | * |
546 | * RETURN: A WalkState object popped from the thread's stack |
547 | * |
548 | * DESCRIPTION: Remove and return the walkstate object that is at the head of |
549 | * the walk stack for the given walk list. NULL indicates that |
550 | * the list is empty. |
551 | * |
552 | ******************************************************************************/ |
553 | |
554 | ACPI_WALK_STATE * |
555 | AcpiDsPopWalkState ( |
556 | ACPI_THREAD_STATE *Thread) |
557 | { |
558 | ACPI_WALK_STATE *WalkState; |
559 | |
560 | |
561 | ACPI_FUNCTION_TRACE (DsPopWalkState); |
562 | |
563 | |
564 | WalkState = Thread->WalkStateList; |
565 | |
566 | if (WalkState) |
567 | { |
568 | /* Next walk state becomes the current walk state */ |
569 | |
570 | Thread->WalkStateList = WalkState->Next; |
571 | |
572 | /* |
573 | * Don't clear the NEXT field, this serves as an indicator |
574 | * that there is a parent WALK STATE |
575 | * Do Not: WalkState->Next = NULL; |
576 | */ |
577 | } |
578 | |
579 | return_PTR (WalkState); |
580 | } |
581 | |
582 | |
583 | /******************************************************************************* |
584 | * |
585 | * FUNCTION: AcpiDsCreateWalkState |
586 | * |
587 | * PARAMETERS: OwnerId - ID for object creation |
588 | * Origin - Starting point for this walk |
589 | * MethodDesc - Method object |
590 | * Thread - Current thread state |
591 | * |
592 | * RETURN: Pointer to the new walk state. |
593 | * |
594 | * DESCRIPTION: Allocate and initialize a new walk state. The current walk |
595 | * state is set to this new state. |
596 | * |
597 | ******************************************************************************/ |
598 | |
599 | ACPI_WALK_STATE * |
600 | AcpiDsCreateWalkState ( |
601 | ACPI_OWNER_ID OwnerId, |
602 | ACPI_PARSE_OBJECT *Origin, |
603 | ACPI_OPERAND_OBJECT *MethodDesc, |
604 | ACPI_THREAD_STATE *Thread) |
605 | { |
606 | ACPI_WALK_STATE *WalkState; |
607 | |
608 | |
609 | ACPI_FUNCTION_TRACE (DsCreateWalkState); |
610 | |
611 | |
612 | WalkState = ACPI_ALLOCATE_ZEROED (sizeof (ACPI_WALK_STATE)); |
613 | if (!WalkState) |
614 | { |
615 | return_PTR (NULL); |
616 | } |
617 | |
618 | WalkState->DescriptorType = ACPI_DESC_TYPE_WALK; |
619 | WalkState->MethodDesc = MethodDesc; |
620 | WalkState->OwnerId = OwnerId; |
621 | WalkState->Origin = Origin; |
622 | WalkState->Thread = Thread; |
623 | |
624 | WalkState->ParserState.StartOp = Origin; |
625 | |
626 | /* Init the method args/local */ |
627 | |
628 | #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) |
629 | AcpiDsMethodDataInit (WalkState); |
630 | #endif |
631 | |
632 | /* Put the new state at the head of the walk list */ |
633 | |
634 | if (Thread) |
635 | { |
636 | AcpiDsPushWalkState (WalkState, Thread); |
637 | } |
638 | |
639 | return_PTR (WalkState); |
640 | } |
641 | |
642 | |
643 | /******************************************************************************* |
644 | * |
645 | * FUNCTION: AcpiDsInitAmlWalk |
646 | * |
647 | * PARAMETERS: WalkState - New state to be initialized |
648 | * Op - Current parse op |
649 | * MethodNode - Control method NS node, if any |
650 | * AmlStart - Start of AML |
651 | * AmlLength - Length of AML |
652 | * Info - Method info block (params, etc.) |
653 | * PassNumber - 1, 2, or 3 |
654 | * |
655 | * RETURN: Status |
656 | * |
657 | * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk |
658 | * |
659 | ******************************************************************************/ |
660 | |
661 | ACPI_STATUS |
662 | AcpiDsInitAmlWalk ( |
663 | ACPI_WALK_STATE *WalkState, |
664 | ACPI_PARSE_OBJECT *Op, |
665 | ACPI_NAMESPACE_NODE *MethodNode, |
666 | UINT8 *AmlStart, |
667 | UINT32 AmlLength, |
668 | ACPI_EVALUATE_INFO *Info, |
669 | UINT8 PassNumber) |
670 | { |
671 | ACPI_STATUS Status; |
672 | ACPI_PARSE_STATE *ParserState = &WalkState->ParserState; |
673 | ACPI_PARSE_OBJECT *; |
674 | |
675 | |
676 | ACPI_FUNCTION_TRACE (DsInitAmlWalk); |
677 | |
678 | |
679 | WalkState->ParserState.Aml = |
680 | WalkState->ParserState.AmlStart = AmlStart; |
681 | WalkState->ParserState.AmlEnd = |
682 | WalkState->ParserState.PkgEnd = AmlStart + AmlLength; |
683 | |
684 | /* The NextOp of the NextWalk will be the beginning of the method */ |
685 | |
686 | WalkState->NextOp = NULL; |
687 | WalkState->PassNumber = PassNumber; |
688 | |
689 | if (Info) |
690 | { |
691 | WalkState->Params = Info->Parameters; |
692 | WalkState->CallerReturnDesc = &Info->ReturnObject; |
693 | } |
694 | |
695 | Status = AcpiPsInitScope (&WalkState->ParserState, Op); |
696 | if (ACPI_FAILURE (Status)) |
697 | { |
698 | return_ACPI_STATUS (Status); |
699 | } |
700 | |
701 | if (MethodNode) |
702 | { |
703 | WalkState->ParserState.StartNode = MethodNode; |
704 | WalkState->WalkType = ACPI_WALK_METHOD; |
705 | WalkState->MethodNode = MethodNode; |
706 | WalkState->MethodDesc = AcpiNsGetAttachedObject (MethodNode); |
707 | |
708 | /* Push start scope on scope stack and make it current */ |
709 | |
710 | Status = AcpiDsScopeStackPush ( |
711 | MethodNode, ACPI_TYPE_METHOD, WalkState); |
712 | if (ACPI_FAILURE (Status)) |
713 | { |
714 | return_ACPI_STATUS (Status); |
715 | } |
716 | |
717 | /* Init the method arguments */ |
718 | |
719 | Status = AcpiDsMethodDataInitArgs (WalkState->Params, |
720 | ACPI_METHOD_NUM_ARGS, WalkState); |
721 | if (ACPI_FAILURE (Status)) |
722 | { |
723 | return_ACPI_STATUS (Status); |
724 | } |
725 | } |
726 | else |
727 | { |
728 | /* |
729 | * Setup the current scope. |
730 | * Find a Named Op that has a namespace node associated with it. |
731 | * search upwards from this Op. Current scope is the first |
732 | * Op with a namespace node. |
733 | */ |
734 | ExtraOp = ParserState->StartOp; |
735 | while (ExtraOp && !ExtraOp->Common.Node) |
736 | { |
737 | ExtraOp = ExtraOp->Common.Parent; |
738 | } |
739 | |
740 | if (!ExtraOp) |
741 | { |
742 | ParserState->StartNode = NULL; |
743 | } |
744 | else |
745 | { |
746 | ParserState->StartNode = ExtraOp->Common.Node; |
747 | } |
748 | |
749 | if (ParserState->StartNode) |
750 | { |
751 | /* Push start scope on scope stack and make it current */ |
752 | |
753 | Status = AcpiDsScopeStackPush (ParserState->StartNode, |
754 | ParserState->StartNode->Type, WalkState); |
755 | if (ACPI_FAILURE (Status)) |
756 | { |
757 | return_ACPI_STATUS (Status); |
758 | } |
759 | } |
760 | } |
761 | |
762 | Status = AcpiDsInitCallbacks (WalkState, PassNumber); |
763 | return_ACPI_STATUS (Status); |
764 | } |
765 | |
766 | |
767 | /******************************************************************************* |
768 | * |
769 | * FUNCTION: AcpiDsDeleteWalkState |
770 | * |
771 | * PARAMETERS: WalkState - State to delete |
772 | * |
773 | * RETURN: Status |
774 | * |
775 | * DESCRIPTION: Delete a walk state including all internal data structures |
776 | * |
777 | ******************************************************************************/ |
778 | |
779 | void |
780 | AcpiDsDeleteWalkState ( |
781 | ACPI_WALK_STATE *WalkState) |
782 | { |
783 | ACPI_GENERIC_STATE *State; |
784 | |
785 | |
786 | ACPI_FUNCTION_TRACE_PTR (DsDeleteWalkState, WalkState); |
787 | |
788 | |
789 | if (!WalkState) |
790 | { |
791 | return_VOID; |
792 | } |
793 | |
794 | if (WalkState->DescriptorType != ACPI_DESC_TYPE_WALK) |
795 | { |
796 | ACPI_ERROR ((AE_INFO, "%p is not a valid walk state" , |
797 | WalkState)); |
798 | return_VOID; |
799 | } |
800 | |
801 | /* There should not be any open scopes */ |
802 | |
803 | if (WalkState->ParserState.Scope) |
804 | { |
805 | ACPI_ERROR ((AE_INFO, "%p walk still has a scope list" , |
806 | WalkState)); |
807 | AcpiPsCleanupScope (&WalkState->ParserState); |
808 | } |
809 | |
810 | /* Always must free any linked control states */ |
811 | |
812 | while (WalkState->ControlState) |
813 | { |
814 | State = WalkState->ControlState; |
815 | WalkState->ControlState = State->Common.Next; |
816 | |
817 | AcpiUtDeleteGenericState (State); |
818 | } |
819 | |
820 | /* Always must free any linked parse states */ |
821 | |
822 | while (WalkState->ScopeInfo) |
823 | { |
824 | State = WalkState->ScopeInfo; |
825 | WalkState->ScopeInfo = State->Common.Next; |
826 | |
827 | AcpiUtDeleteGenericState (State); |
828 | } |
829 | |
830 | /* Always must free any stacked result states */ |
831 | |
832 | while (WalkState->Results) |
833 | { |
834 | State = WalkState->Results; |
835 | WalkState->Results = State->Common.Next; |
836 | |
837 | AcpiUtDeleteGenericState (State); |
838 | } |
839 | |
840 | ACPI_FREE (WalkState); |
841 | return_VOID; |
842 | } |
843 | |