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 *ExtraOp; 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