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