195b482a8SLen Brown /****************************************************************************** 295b482a8SLen Brown * 395b482a8SLen Brown * Module Name: dswstate - Dispatcher parse tree walk management routines 495b482a8SLen Brown * 595b482a8SLen Brown *****************************************************************************/ 695b482a8SLen Brown 795b482a8SLen Brown /* 877848130SBob Moore * Copyright (C) 2000 - 2012, Intel Corp. 995b482a8SLen Brown * All rights reserved. 1095b482a8SLen Brown * 1195b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 1295b482a8SLen Brown * modification, are permitted provided that the following conditions 1395b482a8SLen Brown * are met: 1495b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 1595b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 1695b482a8SLen Brown * without modification. 1795b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1895b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 1995b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 2095b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 2195b482a8SLen Brown * binary redistribution. 2295b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 2395b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 2495b482a8SLen Brown * from this software without specific prior written permission. 2595b482a8SLen Brown * 2695b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 2795b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 2895b482a8SLen Brown * Software Foundation. 2995b482a8SLen Brown * 3095b482a8SLen Brown * NO WARRANTY 3195b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3295b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3395b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3495b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3595b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3695b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3795b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3895b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3995b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4095b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4195b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 4295b482a8SLen Brown */ 4395b482a8SLen Brown 4495b482a8SLen Brown #include <acpi/acpi.h> 45e2f7a777SLen Brown #include "accommon.h" 46e2f7a777SLen Brown #include "acparser.h" 47e2f7a777SLen Brown #include "acdispat.h" 48e2f7a777SLen Brown #include "acnamesp.h" 4995b482a8SLen Brown 5095b482a8SLen Brown #define _COMPONENT ACPI_DISPATCHER 5195b482a8SLen Brown ACPI_MODULE_NAME("dswstate") 5295b482a8SLen Brown 5395b482a8SLen Brown /* Local prototypes */ 541f86e8c1SLv Zheng static acpi_status 551f86e8c1SLv Zheng acpi_ds_result_stack_push(struct acpi_walk_state *walk_state); 561f86e8c1SLv Zheng static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state); 5795b482a8SLen Brown 5895b482a8SLen Brown /******************************************************************************* 5995b482a8SLen Brown * 6095b482a8SLen Brown * FUNCTION: acpi_ds_result_pop 6195b482a8SLen Brown * 62ba494beeSBob Moore * PARAMETERS: object - Where to return the popped object 6395b482a8SLen Brown * walk_state - Current Walk state 6495b482a8SLen Brown * 6595b482a8SLen Brown * RETURN: Status 6695b482a8SLen Brown * 6795b482a8SLen Brown * DESCRIPTION: Pop an object off the top of this walk's result stack 6895b482a8SLen Brown * 6995b482a8SLen Brown ******************************************************************************/ 7095b482a8SLen Brown 7195b482a8SLen Brown acpi_status 7295b482a8SLen Brown acpi_ds_result_pop(union acpi_operand_object **object, 7395b482a8SLen Brown struct acpi_walk_state *walk_state) 7495b482a8SLen Brown { 7595b482a8SLen Brown u32 index; 7695b482a8SLen Brown union acpi_generic_state *state; 7795b482a8SLen Brown acpi_status status; 7895b482a8SLen Brown 7995b482a8SLen Brown ACPI_FUNCTION_NAME(ds_result_pop); 8095b482a8SLen Brown 8195b482a8SLen Brown state = walk_state->results; 8295b482a8SLen Brown 8395b482a8SLen Brown /* Incorrect state of result stack */ 8495b482a8SLen Brown 8595b482a8SLen Brown if (state && !walk_state->result_count) { 8695b482a8SLen Brown ACPI_ERROR((AE_INFO, "No results on result stack")); 8795b482a8SLen Brown return (AE_AML_INTERNAL); 8895b482a8SLen Brown } 8995b482a8SLen Brown 9095b482a8SLen Brown if (!state && walk_state->result_count) { 9195b482a8SLen Brown ACPI_ERROR((AE_INFO, "No result state for result stack")); 9295b482a8SLen Brown return (AE_AML_INTERNAL); 9395b482a8SLen Brown } 9495b482a8SLen Brown 9595b482a8SLen Brown /* Empty result stack */ 9695b482a8SLen Brown 9795b482a8SLen Brown if (!state) { 9895b482a8SLen Brown ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", 9995b482a8SLen Brown walk_state)); 10095b482a8SLen Brown return (AE_AML_NO_RETURN_VALUE); 10195b482a8SLen Brown } 10295b482a8SLen Brown 10395b482a8SLen Brown /* Return object of the top element and clean that top element result stack */ 10495b482a8SLen Brown 10595b482a8SLen Brown walk_state->result_count--; 106ba9c3f55SBob Moore index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; 10795b482a8SLen Brown 10895b482a8SLen Brown *object = state->results.obj_desc[index]; 10995b482a8SLen Brown if (!*object) { 11095b482a8SLen Brown ACPI_ERROR((AE_INFO, 11195b482a8SLen Brown "No result objects on result stack, State=%p", 11295b482a8SLen Brown walk_state)); 11395b482a8SLen Brown return (AE_AML_NO_RETURN_VALUE); 11495b482a8SLen Brown } 11595b482a8SLen Brown 11695b482a8SLen Brown state->results.obj_desc[index] = NULL; 11795b482a8SLen Brown if (index == 0) { 11895b482a8SLen Brown status = acpi_ds_result_stack_pop(walk_state); 11995b482a8SLen Brown if (ACPI_FAILURE(status)) { 12095b482a8SLen Brown return (status); 12195b482a8SLen Brown } 12295b482a8SLen Brown } 12395b482a8SLen Brown 12495b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 12595b482a8SLen Brown "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, 12695b482a8SLen Brown acpi_ut_get_object_type_name(*object), 12795b482a8SLen Brown index, walk_state, walk_state->result_count)); 12895b482a8SLen Brown 12995b482a8SLen Brown return (AE_OK); 13095b482a8SLen Brown } 13195b482a8SLen Brown 13295b482a8SLen Brown /******************************************************************************* 13395b482a8SLen Brown * 13495b482a8SLen Brown * FUNCTION: acpi_ds_result_push 13595b482a8SLen Brown * 136ba494beeSBob Moore * PARAMETERS: object - Where to return the popped object 13795b482a8SLen Brown * walk_state - Current Walk state 13895b482a8SLen Brown * 13995b482a8SLen Brown * RETURN: Status 14095b482a8SLen Brown * 14195b482a8SLen Brown * DESCRIPTION: Push an object onto the current result stack 14295b482a8SLen Brown * 14395b482a8SLen Brown ******************************************************************************/ 14495b482a8SLen Brown 14595b482a8SLen Brown acpi_status 14695b482a8SLen Brown acpi_ds_result_push(union acpi_operand_object * object, 14795b482a8SLen Brown struct acpi_walk_state * walk_state) 14895b482a8SLen Brown { 14995b482a8SLen Brown union acpi_generic_state *state; 15095b482a8SLen Brown acpi_status status; 15195b482a8SLen Brown u32 index; 15295b482a8SLen Brown 15395b482a8SLen Brown ACPI_FUNCTION_NAME(ds_result_push); 15495b482a8SLen Brown 15595b482a8SLen Brown if (walk_state->result_count > walk_state->result_size) { 15695b482a8SLen Brown ACPI_ERROR((AE_INFO, "Result stack is full")); 15795b482a8SLen Brown return (AE_AML_INTERNAL); 15895b482a8SLen Brown } else if (walk_state->result_count == walk_state->result_size) { 15995b482a8SLen Brown 16095b482a8SLen Brown /* Extend the result stack */ 16195b482a8SLen Brown 16295b482a8SLen Brown status = acpi_ds_result_stack_push(walk_state); 16395b482a8SLen Brown if (ACPI_FAILURE(status)) { 16495b482a8SLen Brown ACPI_ERROR((AE_INFO, 16595b482a8SLen Brown "Failed to extend the result stack")); 16695b482a8SLen Brown return (status); 16795b482a8SLen Brown } 16895b482a8SLen Brown } 16995b482a8SLen Brown 17095b482a8SLen Brown if (!(walk_state->result_count < walk_state->result_size)) { 17195b482a8SLen Brown ACPI_ERROR((AE_INFO, "No free elements in result stack")); 17295b482a8SLen Brown return (AE_AML_INTERNAL); 17395b482a8SLen Brown } 17495b482a8SLen Brown 17595b482a8SLen Brown state = walk_state->results; 17695b482a8SLen Brown if (!state) { 17795b482a8SLen Brown ACPI_ERROR((AE_INFO, "No result stack frame during push")); 17895b482a8SLen Brown return (AE_AML_INTERNAL); 17995b482a8SLen Brown } 18095b482a8SLen Brown 18195b482a8SLen Brown if (!object) { 18295b482a8SLen Brown ACPI_ERROR((AE_INFO, 183f6a22b0bSBob Moore "Null Object! Obj=%p State=%p Num=%u", 18495b482a8SLen Brown object, walk_state, walk_state->result_count)); 18595b482a8SLen Brown return (AE_BAD_PARAMETER); 18695b482a8SLen Brown } 18795b482a8SLen Brown 18895b482a8SLen Brown /* Assign the address of object to the top free element of result stack */ 18995b482a8SLen Brown 190ba9c3f55SBob Moore index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; 19195b482a8SLen Brown state->results.obj_desc[index] = object; 19295b482a8SLen Brown walk_state->result_count++; 19395b482a8SLen Brown 19495b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", 19595b482a8SLen Brown object, 19695b482a8SLen Brown acpi_ut_get_object_type_name((union 19795b482a8SLen Brown acpi_operand_object *) 19895b482a8SLen Brown object), walk_state, 19995b482a8SLen Brown walk_state->result_count, 20095b482a8SLen Brown walk_state->current_result)); 20195b482a8SLen Brown 20295b482a8SLen Brown return (AE_OK); 20395b482a8SLen Brown } 20495b482a8SLen Brown 20595b482a8SLen Brown /******************************************************************************* 20695b482a8SLen Brown * 20795b482a8SLen Brown * FUNCTION: acpi_ds_result_stack_push 20895b482a8SLen Brown * 20995b482a8SLen Brown * PARAMETERS: walk_state - Current Walk state 21095b482a8SLen Brown * 21195b482a8SLen Brown * RETURN: Status 21295b482a8SLen Brown * 21395b482a8SLen Brown * DESCRIPTION: Push an object onto the walk_state result stack 21495b482a8SLen Brown * 21595b482a8SLen Brown ******************************************************************************/ 21695b482a8SLen Brown 21795b482a8SLen Brown static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) 21895b482a8SLen Brown { 21995b482a8SLen Brown union acpi_generic_state *state; 22095b482a8SLen Brown 22195b482a8SLen Brown ACPI_FUNCTION_NAME(ds_result_stack_push); 22295b482a8SLen Brown 22395b482a8SLen Brown /* Check for stack overflow */ 22495b482a8SLen Brown 22595b482a8SLen Brown if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > 22695b482a8SLen Brown ACPI_RESULTS_OBJ_NUM_MAX) { 227f6a22b0bSBob Moore ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%u", 22895b482a8SLen Brown walk_state, walk_state->result_size)); 22995b482a8SLen Brown return (AE_STACK_OVERFLOW); 23095b482a8SLen Brown } 23195b482a8SLen Brown 23295b482a8SLen Brown state = acpi_ut_create_generic_state(); 23395b482a8SLen Brown if (!state) { 23495b482a8SLen Brown return (AE_NO_MEMORY); 23595b482a8SLen Brown } 23695b482a8SLen Brown 23795b482a8SLen Brown state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; 23895b482a8SLen Brown acpi_ut_push_generic_state(&walk_state->results, state); 23995b482a8SLen Brown 24095b482a8SLen Brown /* Increase the length of the result stack by the length of frame */ 24195b482a8SLen Brown 24295b482a8SLen Brown walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM; 24395b482a8SLen Brown 24495b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", 24595b482a8SLen Brown state, walk_state)); 24695b482a8SLen Brown 24795b482a8SLen Brown return (AE_OK); 24895b482a8SLen Brown } 24995b482a8SLen Brown 25095b482a8SLen Brown /******************************************************************************* 25195b482a8SLen Brown * 25295b482a8SLen Brown * FUNCTION: acpi_ds_result_stack_pop 25395b482a8SLen Brown * 25495b482a8SLen Brown * PARAMETERS: walk_state - Current Walk state 25595b482a8SLen Brown * 25695b482a8SLen Brown * RETURN: Status 25795b482a8SLen Brown * 25895b482a8SLen Brown * DESCRIPTION: Pop an object off of the walk_state result stack 25995b482a8SLen Brown * 26095b482a8SLen Brown ******************************************************************************/ 26195b482a8SLen Brown 26295b482a8SLen Brown static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) 26395b482a8SLen Brown { 26495b482a8SLen Brown union acpi_generic_state *state; 26595b482a8SLen Brown 26695b482a8SLen Brown ACPI_FUNCTION_NAME(ds_result_stack_pop); 26795b482a8SLen Brown 26895b482a8SLen Brown /* Check for stack underflow */ 26995b482a8SLen Brown 27095b482a8SLen Brown if (walk_state->results == NULL) { 27195b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 27295b482a8SLen Brown "Result stack underflow - State=%p\n", 27395b482a8SLen Brown walk_state)); 27495b482a8SLen Brown return (AE_AML_NO_OPERAND); 27595b482a8SLen Brown } 27695b482a8SLen Brown 27795b482a8SLen Brown if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { 27895b482a8SLen Brown ACPI_ERROR((AE_INFO, "Insufficient result stack size")); 27995b482a8SLen Brown return (AE_AML_INTERNAL); 28095b482a8SLen Brown } 28195b482a8SLen Brown 28295b482a8SLen Brown state = acpi_ut_pop_generic_state(&walk_state->results); 28395b482a8SLen Brown acpi_ut_delete_generic_state(state); 28495b482a8SLen Brown 28595b482a8SLen Brown /* Decrease the length of result stack by the length of frame */ 28695b482a8SLen Brown 28795b482a8SLen Brown walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; 28895b482a8SLen Brown 28995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 29095b482a8SLen Brown "Result=%p RemainingResults=%X State=%p\n", 29195b482a8SLen Brown state, walk_state->result_count, walk_state)); 29295b482a8SLen Brown 29395b482a8SLen Brown return (AE_OK); 29495b482a8SLen Brown } 29595b482a8SLen Brown 29695b482a8SLen Brown /******************************************************************************* 29795b482a8SLen Brown * 29895b482a8SLen Brown * FUNCTION: acpi_ds_obj_stack_push 29995b482a8SLen Brown * 300ba494beeSBob Moore * PARAMETERS: object - Object to push 30195b482a8SLen Brown * walk_state - Current Walk state 30295b482a8SLen Brown * 30395b482a8SLen Brown * RETURN: Status 30495b482a8SLen Brown * 30595b482a8SLen Brown * DESCRIPTION: Push an object onto this walk's object/operand stack 30695b482a8SLen Brown * 30795b482a8SLen Brown ******************************************************************************/ 30895b482a8SLen Brown 30995b482a8SLen Brown acpi_status 31095b482a8SLen Brown acpi_ds_obj_stack_push(void *object, struct acpi_walk_state * walk_state) 31195b482a8SLen Brown { 31295b482a8SLen Brown ACPI_FUNCTION_NAME(ds_obj_stack_push); 31395b482a8SLen Brown 31495b482a8SLen Brown /* Check for stack overflow */ 31595b482a8SLen Brown 31695b482a8SLen Brown if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) { 31795b482a8SLen Brown ACPI_ERROR((AE_INFO, 318f6a22b0bSBob Moore "Object stack overflow! Obj=%p State=%p #Ops=%u", 31995b482a8SLen Brown object, walk_state, walk_state->num_operands)); 32095b482a8SLen Brown return (AE_STACK_OVERFLOW); 32195b482a8SLen Brown } 32295b482a8SLen Brown 32395b482a8SLen Brown /* Put the object onto the stack */ 32495b482a8SLen Brown 32595b482a8SLen Brown walk_state->operands[walk_state->operand_index] = object; 32695b482a8SLen Brown walk_state->num_operands++; 32795b482a8SLen Brown 32895b482a8SLen Brown /* For the usual order of filling the operand stack */ 32995b482a8SLen Brown 33095b482a8SLen Brown walk_state->operand_index++; 33195b482a8SLen Brown 33295b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", 33395b482a8SLen Brown object, 33495b482a8SLen Brown acpi_ut_get_object_type_name((union 33595b482a8SLen Brown acpi_operand_object *) 33695b482a8SLen Brown object), walk_state, 33795b482a8SLen Brown walk_state->num_operands)); 33895b482a8SLen Brown 33995b482a8SLen Brown return (AE_OK); 34095b482a8SLen Brown } 34195b482a8SLen Brown 34295b482a8SLen Brown /******************************************************************************* 34395b482a8SLen Brown * 34495b482a8SLen Brown * FUNCTION: acpi_ds_obj_stack_pop 34595b482a8SLen Brown * 34695b482a8SLen Brown * PARAMETERS: pop_count - Number of objects/entries to pop 34795b482a8SLen Brown * walk_state - Current Walk state 34895b482a8SLen Brown * 34995b482a8SLen Brown * RETURN: Status 35095b482a8SLen Brown * 35195b482a8SLen Brown * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT 35295b482a8SLen Brown * deleted by this routine. 35395b482a8SLen Brown * 35495b482a8SLen Brown ******************************************************************************/ 35595b482a8SLen Brown 35695b482a8SLen Brown acpi_status 35795b482a8SLen Brown acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state * walk_state) 35895b482a8SLen Brown { 35995b482a8SLen Brown u32 i; 36095b482a8SLen Brown 36195b482a8SLen Brown ACPI_FUNCTION_NAME(ds_obj_stack_pop); 36295b482a8SLen Brown 36395b482a8SLen Brown for (i = 0; i < pop_count; i++) { 36495b482a8SLen Brown 36595b482a8SLen Brown /* Check for stack underflow */ 36695b482a8SLen Brown 36795b482a8SLen Brown if (walk_state->num_operands == 0) { 36895b482a8SLen Brown ACPI_ERROR((AE_INFO, 369f6a22b0bSBob Moore "Object stack underflow! Count=%X State=%p #Ops=%u", 37095b482a8SLen Brown pop_count, walk_state, 37195b482a8SLen Brown walk_state->num_operands)); 37295b482a8SLen Brown return (AE_STACK_UNDERFLOW); 37395b482a8SLen Brown } 37495b482a8SLen Brown 37595b482a8SLen Brown /* Just set the stack entry to null */ 37695b482a8SLen Brown 37795b482a8SLen Brown walk_state->num_operands--; 37895b482a8SLen Brown walk_state->operands[walk_state->num_operands] = NULL; 37995b482a8SLen Brown } 38095b482a8SLen Brown 381f6a22b0bSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%u\n", 38295b482a8SLen Brown pop_count, walk_state, walk_state->num_operands)); 38395b482a8SLen Brown 38495b482a8SLen Brown return (AE_OK); 38595b482a8SLen Brown } 38695b482a8SLen Brown 38795b482a8SLen Brown /******************************************************************************* 38895b482a8SLen Brown * 38995b482a8SLen Brown * FUNCTION: acpi_ds_obj_stack_pop_and_delete 39095b482a8SLen Brown * 39195b482a8SLen Brown * PARAMETERS: pop_count - Number of objects/entries to pop 39295b482a8SLen Brown * walk_state - Current Walk state 39395b482a8SLen Brown * 39495b482a8SLen Brown * RETURN: Status 39595b482a8SLen Brown * 39695b482a8SLen Brown * DESCRIPTION: Pop this walk's object stack and delete each object that is 39795b482a8SLen Brown * popped off. 39895b482a8SLen Brown * 39995b482a8SLen Brown ******************************************************************************/ 40095b482a8SLen Brown 40195b482a8SLen Brown void 40295b482a8SLen Brown acpi_ds_obj_stack_pop_and_delete(u32 pop_count, 40395b482a8SLen Brown struct acpi_walk_state *walk_state) 40495b482a8SLen Brown { 40595b482a8SLen Brown s32 i; 40695b482a8SLen Brown union acpi_operand_object *obj_desc; 40795b482a8SLen Brown 40895b482a8SLen Brown ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); 40995b482a8SLen Brown 41095b482a8SLen Brown if (pop_count == 0) { 41195b482a8SLen Brown return; 41295b482a8SLen Brown } 41395b482a8SLen Brown 41495b482a8SLen Brown for (i = (s32) pop_count - 1; i >= 0; i--) { 41595b482a8SLen Brown if (walk_state->num_operands == 0) { 41695b482a8SLen Brown return; 41795b482a8SLen Brown } 41895b482a8SLen Brown 41995b482a8SLen Brown /* Pop the stack and delete an object if present in this stack entry */ 42095b482a8SLen Brown 42195b482a8SLen Brown walk_state->num_operands--; 42295b482a8SLen Brown obj_desc = walk_state->operands[i]; 42395b482a8SLen Brown if (obj_desc) { 42495b482a8SLen Brown acpi_ut_remove_reference(walk_state->operands[i]); 42595b482a8SLen Brown walk_state->operands[i] = NULL; 42695b482a8SLen Brown } 42795b482a8SLen Brown } 42895b482a8SLen Brown 42995b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", 43095b482a8SLen Brown pop_count, walk_state, walk_state->num_operands)); 43195b482a8SLen Brown } 43295b482a8SLen Brown 43395b482a8SLen Brown /******************************************************************************* 43495b482a8SLen Brown * 43595b482a8SLen Brown * FUNCTION: acpi_ds_get_current_walk_state 43695b482a8SLen Brown * 437ba494beeSBob Moore * PARAMETERS: thread - Get current active state for this Thread 43895b482a8SLen Brown * 43995b482a8SLen Brown * RETURN: Pointer to the current walk state 44095b482a8SLen Brown * 44195b482a8SLen Brown * DESCRIPTION: Get the walk state that is at the head of the list (the "current" 44295b482a8SLen Brown * walk state.) 44395b482a8SLen Brown * 44495b482a8SLen Brown ******************************************************************************/ 44595b482a8SLen Brown 44695b482a8SLen Brown struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state 44795b482a8SLen Brown *thread) 44895b482a8SLen Brown { 44995b482a8SLen Brown ACPI_FUNCTION_NAME(ds_get_current_walk_state); 45095b482a8SLen Brown 45195b482a8SLen Brown if (!thread) { 45295b482a8SLen Brown return (NULL); 45395b482a8SLen Brown } 45495b482a8SLen Brown 45595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n", 45695b482a8SLen Brown thread->walk_state_list)); 45795b482a8SLen Brown 45895b482a8SLen Brown return (thread->walk_state_list); 45995b482a8SLen Brown } 46095b482a8SLen Brown 46195b482a8SLen Brown /******************************************************************************* 46295b482a8SLen Brown * 46395b482a8SLen Brown * FUNCTION: acpi_ds_push_walk_state 46495b482a8SLen Brown * 46595b482a8SLen Brown * PARAMETERS: walk_state - State to push 466ba494beeSBob Moore * thread - Thread state object 46795b482a8SLen Brown * 46895b482a8SLen Brown * RETURN: None 46995b482a8SLen Brown * 47095b482a8SLen Brown * DESCRIPTION: Place the Thread state at the head of the state list 47195b482a8SLen Brown * 47295b482a8SLen Brown ******************************************************************************/ 47395b482a8SLen Brown 47495b482a8SLen Brown void 47595b482a8SLen Brown acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, 47695b482a8SLen Brown struct acpi_thread_state *thread) 47795b482a8SLen Brown { 47895b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_push_walk_state); 47995b482a8SLen Brown 48095b482a8SLen Brown walk_state->next = thread->walk_state_list; 48195b482a8SLen Brown thread->walk_state_list = walk_state; 48295b482a8SLen Brown 48395b482a8SLen Brown return_VOID; 48495b482a8SLen Brown } 48595b482a8SLen Brown 48695b482a8SLen Brown /******************************************************************************* 48795b482a8SLen Brown * 48895b482a8SLen Brown * FUNCTION: acpi_ds_pop_walk_state 48995b482a8SLen Brown * 490ba494beeSBob Moore * PARAMETERS: thread - Current thread state 49195b482a8SLen Brown * 49295b482a8SLen Brown * RETURN: A walk_state object popped from the thread's stack 49395b482a8SLen Brown * 49495b482a8SLen Brown * DESCRIPTION: Remove and return the walkstate object that is at the head of 49595b482a8SLen Brown * the walk stack for the given walk list. NULL indicates that 49695b482a8SLen Brown * the list is empty. 49795b482a8SLen Brown * 49895b482a8SLen Brown ******************************************************************************/ 49995b482a8SLen Brown 50095b482a8SLen Brown struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) 50195b482a8SLen Brown { 50295b482a8SLen Brown struct acpi_walk_state *walk_state; 50395b482a8SLen Brown 50495b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_pop_walk_state); 50595b482a8SLen Brown 50695b482a8SLen Brown walk_state = thread->walk_state_list; 50795b482a8SLen Brown 50895b482a8SLen Brown if (walk_state) { 50995b482a8SLen Brown 51095b482a8SLen Brown /* Next walk state becomes the current walk state */ 51195b482a8SLen Brown 51295b482a8SLen Brown thread->walk_state_list = walk_state->next; 51395b482a8SLen Brown 51495b482a8SLen Brown /* 51595b482a8SLen Brown * Don't clear the NEXT field, this serves as an indicator 51695b482a8SLen Brown * that there is a parent WALK STATE 51795b482a8SLen Brown * Do Not: walk_state->Next = NULL; 51895b482a8SLen Brown */ 51995b482a8SLen Brown } 52095b482a8SLen Brown 52195b482a8SLen Brown return_PTR(walk_state); 52295b482a8SLen Brown } 52395b482a8SLen Brown 52495b482a8SLen Brown /******************************************************************************* 52595b482a8SLen Brown * 52695b482a8SLen Brown * FUNCTION: acpi_ds_create_walk_state 52795b482a8SLen Brown * 52895b482a8SLen Brown * PARAMETERS: owner_id - ID for object creation 529ba494beeSBob Moore * origin - Starting point for this walk 53095b482a8SLen Brown * method_desc - Method object 531ba494beeSBob Moore * thread - Current thread state 53295b482a8SLen Brown * 53395b482a8SLen Brown * RETURN: Pointer to the new walk state. 53495b482a8SLen Brown * 53595b482a8SLen Brown * DESCRIPTION: Allocate and initialize a new walk state. The current walk 53695b482a8SLen Brown * state is set to this new state. 53795b482a8SLen Brown * 53895b482a8SLen Brown ******************************************************************************/ 53995b482a8SLen Brown 5401f86e8c1SLv Zheng struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, 5411f86e8c1SLv Zheng union acpi_parse_object 5421f86e8c1SLv Zheng *origin, 5431f86e8c1SLv Zheng union acpi_operand_object 5441f86e8c1SLv Zheng *method_desc, 5451f86e8c1SLv Zheng struct acpi_thread_state 54695b482a8SLen Brown *thread) 54795b482a8SLen Brown { 54895b482a8SLen Brown struct acpi_walk_state *walk_state; 54995b482a8SLen Brown 55095b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_create_walk_state); 55195b482a8SLen Brown 55295b482a8SLen Brown walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state)); 55395b482a8SLen Brown if (!walk_state) { 55495b482a8SLen Brown return_PTR(NULL); 55595b482a8SLen Brown } 55695b482a8SLen Brown 55795b482a8SLen Brown walk_state->descriptor_type = ACPI_DESC_TYPE_WALK; 55895b482a8SLen Brown walk_state->method_desc = method_desc; 55995b482a8SLen Brown walk_state->owner_id = owner_id; 56095b482a8SLen Brown walk_state->origin = origin; 56195b482a8SLen Brown walk_state->thread = thread; 56295b482a8SLen Brown 56395b482a8SLen Brown walk_state->parser_state.start_op = origin; 56495b482a8SLen Brown 56595b482a8SLen Brown /* Init the method args/local */ 56695b482a8SLen Brown 56795b482a8SLen Brown #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) 56895b482a8SLen Brown acpi_ds_method_data_init(walk_state); 56995b482a8SLen Brown #endif 57095b482a8SLen Brown 57195b482a8SLen Brown /* Put the new state at the head of the walk list */ 57295b482a8SLen Brown 57395b482a8SLen Brown if (thread) { 57495b482a8SLen Brown acpi_ds_push_walk_state(walk_state, thread); 57595b482a8SLen Brown } 57695b482a8SLen Brown 57795b482a8SLen Brown return_PTR(walk_state); 57895b482a8SLen Brown } 57995b482a8SLen Brown 58095b482a8SLen Brown /******************************************************************************* 58195b482a8SLen Brown * 58295b482a8SLen Brown * FUNCTION: acpi_ds_init_aml_walk 58395b482a8SLen Brown * 58495b482a8SLen Brown * PARAMETERS: walk_state - New state to be initialized 585ba494beeSBob Moore * op - Current parse op 58695b482a8SLen Brown * method_node - Control method NS node, if any 58795b482a8SLen Brown * aml_start - Start of AML 58895b482a8SLen Brown * aml_length - Length of AML 589ba494beeSBob Moore * info - Method info block (params, etc.) 59095b482a8SLen Brown * pass_number - 1, 2, or 3 59195b482a8SLen Brown * 59295b482a8SLen Brown * RETURN: Status 59395b482a8SLen Brown * 59495b482a8SLen Brown * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk 59595b482a8SLen Brown * 59695b482a8SLen Brown ******************************************************************************/ 59795b482a8SLen Brown 59895b482a8SLen Brown acpi_status 59995b482a8SLen Brown acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, 60095b482a8SLen Brown union acpi_parse_object *op, 60195b482a8SLen Brown struct acpi_namespace_node *method_node, 60295b482a8SLen Brown u8 * aml_start, 60395b482a8SLen Brown u32 aml_length, 60495b482a8SLen Brown struct acpi_evaluate_info *info, u8 pass_number) 60595b482a8SLen Brown { 60695b482a8SLen Brown acpi_status status; 60795b482a8SLen Brown struct acpi_parse_state *parser_state = &walk_state->parser_state; 60895b482a8SLen Brown union acpi_parse_object *extra_op; 60995b482a8SLen Brown 61095b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_init_aml_walk); 61195b482a8SLen Brown 61295b482a8SLen Brown walk_state->parser_state.aml = 61395b482a8SLen Brown walk_state->parser_state.aml_start = aml_start; 61495b482a8SLen Brown walk_state->parser_state.aml_end = 61595b482a8SLen Brown walk_state->parser_state.pkg_end = aml_start + aml_length; 61695b482a8SLen Brown 61795b482a8SLen Brown /* The next_op of the next_walk will be the beginning of the method */ 61895b482a8SLen Brown 61995b482a8SLen Brown walk_state->next_op = NULL; 62095b482a8SLen Brown walk_state->pass_number = pass_number; 62195b482a8SLen Brown 62295b482a8SLen Brown if (info) { 62395b482a8SLen Brown walk_state->params = info->parameters; 62495b482a8SLen Brown walk_state->caller_return_desc = &info->return_object; 62595b482a8SLen Brown } 62695b482a8SLen Brown 62795b482a8SLen Brown status = acpi_ps_init_scope(&walk_state->parser_state, op); 62895b482a8SLen Brown if (ACPI_FAILURE(status)) { 62995b482a8SLen Brown return_ACPI_STATUS(status); 63095b482a8SLen Brown } 63195b482a8SLen Brown 63295b482a8SLen Brown if (method_node) { 63395b482a8SLen Brown walk_state->parser_state.start_node = method_node; 63495b482a8SLen Brown walk_state->walk_type = ACPI_WALK_METHOD; 63595b482a8SLen Brown walk_state->method_node = method_node; 63695b482a8SLen Brown walk_state->method_desc = 63795b482a8SLen Brown acpi_ns_get_attached_object(method_node); 63895b482a8SLen Brown 63995b482a8SLen Brown /* Push start scope on scope stack and make it current */ 64095b482a8SLen Brown 64195b482a8SLen Brown status = 64295b482a8SLen Brown acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD, 64395b482a8SLen Brown walk_state); 64495b482a8SLen Brown if (ACPI_FAILURE(status)) { 64595b482a8SLen Brown return_ACPI_STATUS(status); 64695b482a8SLen Brown } 64795b482a8SLen Brown 64895b482a8SLen Brown /* Init the method arguments */ 64995b482a8SLen Brown 65095b482a8SLen Brown status = acpi_ds_method_data_init_args(walk_state->params, 65195b482a8SLen Brown ACPI_METHOD_NUM_ARGS, 65295b482a8SLen Brown walk_state); 65395b482a8SLen Brown if (ACPI_FAILURE(status)) { 65495b482a8SLen Brown return_ACPI_STATUS(status); 65595b482a8SLen Brown } 65695b482a8SLen Brown } else { 65795b482a8SLen Brown /* 65895b482a8SLen Brown * Setup the current scope. 65995b482a8SLen Brown * Find a Named Op that has a namespace node associated with it. 66095b482a8SLen Brown * search upwards from this Op. Current scope is the first 66195b482a8SLen Brown * Op with a namespace node. 66295b482a8SLen Brown */ 66395b482a8SLen Brown extra_op = parser_state->start_op; 66495b482a8SLen Brown while (extra_op && !extra_op->common.node) { 66595b482a8SLen Brown extra_op = extra_op->common.parent; 66695b482a8SLen Brown } 66795b482a8SLen Brown 66895b482a8SLen Brown if (!extra_op) { 66995b482a8SLen Brown parser_state->start_node = NULL; 67095b482a8SLen Brown } else { 67195b482a8SLen Brown parser_state->start_node = extra_op->common.node; 67295b482a8SLen Brown } 67395b482a8SLen Brown 67495b482a8SLen Brown if (parser_state->start_node) { 67595b482a8SLen Brown 67695b482a8SLen Brown /* Push start scope on scope stack and make it current */ 67795b482a8SLen Brown 67895b482a8SLen Brown status = 67995b482a8SLen Brown acpi_ds_scope_stack_push(parser_state->start_node, 68095b482a8SLen Brown parser_state->start_node-> 68195b482a8SLen Brown type, walk_state); 68295b482a8SLen Brown if (ACPI_FAILURE(status)) { 68395b482a8SLen Brown return_ACPI_STATUS(status); 68495b482a8SLen Brown } 68595b482a8SLen Brown } 68695b482a8SLen Brown } 68795b482a8SLen Brown 68895b482a8SLen Brown status = acpi_ds_init_callbacks(walk_state, pass_number); 68995b482a8SLen Brown return_ACPI_STATUS(status); 69095b482a8SLen Brown } 69195b482a8SLen Brown 69295b482a8SLen Brown /******************************************************************************* 69395b482a8SLen Brown * 69495b482a8SLen Brown * FUNCTION: acpi_ds_delete_walk_state 69595b482a8SLen Brown * 69695b482a8SLen Brown * PARAMETERS: walk_state - State to delete 69795b482a8SLen Brown * 69895b482a8SLen Brown * RETURN: Status 69995b482a8SLen Brown * 70095b482a8SLen Brown * DESCRIPTION: Delete a walk state including all internal data structures 70195b482a8SLen Brown * 70295b482a8SLen Brown ******************************************************************************/ 70395b482a8SLen Brown 70495b482a8SLen Brown void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) 70595b482a8SLen Brown { 70695b482a8SLen Brown union acpi_generic_state *state; 70795b482a8SLen Brown 70895b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); 70995b482a8SLen Brown 71095b482a8SLen Brown if (!walk_state) { 711*68aafc35SBob Moore return_VOID; 71295b482a8SLen Brown } 71395b482a8SLen Brown 71495b482a8SLen Brown if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { 71595b482a8SLen Brown ACPI_ERROR((AE_INFO, "%p is not a valid walk state", 71695b482a8SLen Brown walk_state)); 717*68aafc35SBob Moore return_VOID; 71895b482a8SLen Brown } 71995b482a8SLen Brown 72095b482a8SLen Brown /* There should not be any open scopes */ 72195b482a8SLen Brown 72295b482a8SLen Brown if (walk_state->parser_state.scope) { 72395b482a8SLen Brown ACPI_ERROR((AE_INFO, "%p walk still has a scope list", 72495b482a8SLen Brown walk_state)); 72595b482a8SLen Brown acpi_ps_cleanup_scope(&walk_state->parser_state); 72695b482a8SLen Brown } 72795b482a8SLen Brown 72895b482a8SLen Brown /* Always must free any linked control states */ 72995b482a8SLen Brown 73095b482a8SLen Brown while (walk_state->control_state) { 73195b482a8SLen Brown state = walk_state->control_state; 73295b482a8SLen Brown walk_state->control_state = state->common.next; 73395b482a8SLen Brown 73495b482a8SLen Brown acpi_ut_delete_generic_state(state); 73595b482a8SLen Brown } 73695b482a8SLen Brown 73795b482a8SLen Brown /* Always must free any linked parse states */ 73895b482a8SLen Brown 73995b482a8SLen Brown while (walk_state->scope_info) { 74095b482a8SLen Brown state = walk_state->scope_info; 74195b482a8SLen Brown walk_state->scope_info = state->common.next; 74295b482a8SLen Brown 74395b482a8SLen Brown acpi_ut_delete_generic_state(state); 74495b482a8SLen Brown } 74595b482a8SLen Brown 74695b482a8SLen Brown /* Always must free any stacked result states */ 74795b482a8SLen Brown 74895b482a8SLen Brown while (walk_state->results) { 74995b482a8SLen Brown state = walk_state->results; 75095b482a8SLen Brown walk_state->results = state->common.next; 75195b482a8SLen Brown 75295b482a8SLen Brown acpi_ut_delete_generic_state(state); 75395b482a8SLen Brown } 75495b482a8SLen Brown 75595b482a8SLen Brown ACPI_FREE(walk_state); 75695b482a8SLen Brown return_VOID; 75795b482a8SLen Brown } 758