195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 295b482a8SLen Brown /****************************************************************************** 395b482a8SLen Brown * 495b482a8SLen Brown * Module Name: dswstate - Dispatcher parse tree walk management routines 595b482a8SLen Brown * 6da6f8320SBob Moore * Copyright (C) 2000 - 2018, Intel Corp. 795b482a8SLen Brown * 895857638SErik Schmauss *****************************************************************************/ 995b482a8SLen Brown 1095b482a8SLen Brown #include <acpi/acpi.h> 11e2f7a777SLen Brown #include "accommon.h" 12e2f7a777SLen Brown #include "acparser.h" 13e2f7a777SLen Brown #include "acdispat.h" 14e2f7a777SLen Brown #include "acnamesp.h" 1595b482a8SLen Brown 1695b482a8SLen Brown #define _COMPONENT ACPI_DISPATCHER 1795b482a8SLen Brown ACPI_MODULE_NAME("dswstate") 1895b482a8SLen Brown 1995b482a8SLen Brown /* Local prototypes */ 201f86e8c1SLv Zheng static acpi_status 211f86e8c1SLv Zheng acpi_ds_result_stack_push(struct acpi_walk_state *walk_state); 221f86e8c1SLv Zheng static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state); 2395b482a8SLen Brown 2495b482a8SLen Brown /******************************************************************************* 2595b482a8SLen Brown * 2695b482a8SLen Brown * FUNCTION: acpi_ds_result_pop 2795b482a8SLen Brown * 28ba494beeSBob Moore * PARAMETERS: object - Where to return the popped object 2995b482a8SLen Brown * walk_state - Current Walk state 3095b482a8SLen Brown * 3195b482a8SLen Brown * RETURN: Status 3295b482a8SLen Brown * 3395b482a8SLen Brown * DESCRIPTION: Pop an object off the top of this walk's result stack 3495b482a8SLen Brown * 3595b482a8SLen Brown ******************************************************************************/ 3695b482a8SLen Brown 3795b482a8SLen Brown acpi_status 3895b482a8SLen Brown acpi_ds_result_pop(union acpi_operand_object **object, 3995b482a8SLen Brown struct acpi_walk_state *walk_state) 4095b482a8SLen Brown { 4195b482a8SLen Brown u32 index; 4295b482a8SLen Brown union acpi_generic_state *state; 4395b482a8SLen Brown acpi_status status; 4495b482a8SLen Brown 4595b482a8SLen Brown ACPI_FUNCTION_NAME(ds_result_pop); 4695b482a8SLen Brown 4795b482a8SLen Brown state = walk_state->results; 4895b482a8SLen Brown 4995b482a8SLen Brown /* Incorrect state of result stack */ 5095b482a8SLen Brown 5195b482a8SLen Brown if (state && !walk_state->result_count) { 5295b482a8SLen Brown ACPI_ERROR((AE_INFO, "No results on result stack")); 5395b482a8SLen Brown return (AE_AML_INTERNAL); 5495b482a8SLen Brown } 5595b482a8SLen Brown 5695b482a8SLen Brown if (!state && walk_state->result_count) { 5795b482a8SLen Brown ACPI_ERROR((AE_INFO, "No result state for result stack")); 5895b482a8SLen Brown return (AE_AML_INTERNAL); 5995b482a8SLen Brown } 6095b482a8SLen Brown 6195b482a8SLen Brown /* Empty result stack */ 6295b482a8SLen Brown 6395b482a8SLen Brown if (!state) { 6495b482a8SLen Brown ACPI_ERROR((AE_INFO, "Result stack is empty! State=%p", 6595b482a8SLen Brown walk_state)); 6695b482a8SLen Brown return (AE_AML_NO_RETURN_VALUE); 6795b482a8SLen Brown } 6895b482a8SLen Brown 6995b482a8SLen Brown /* Return object of the top element and clean that top element result stack */ 7095b482a8SLen Brown 7195b482a8SLen Brown walk_state->result_count--; 72ba9c3f55SBob Moore index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; 7395b482a8SLen Brown 7495b482a8SLen Brown *object = state->results.obj_desc[index]; 7595b482a8SLen Brown if (!*object) { 7695b482a8SLen Brown ACPI_ERROR((AE_INFO, 7795b482a8SLen Brown "No result objects on result stack, State=%p", 7895b482a8SLen Brown walk_state)); 7995b482a8SLen Brown return (AE_AML_NO_RETURN_VALUE); 8095b482a8SLen Brown } 8195b482a8SLen Brown 8295b482a8SLen Brown state->results.obj_desc[index] = NULL; 8395b482a8SLen Brown if (index == 0) { 8495b482a8SLen Brown status = acpi_ds_result_stack_pop(walk_state); 8595b482a8SLen Brown if (ACPI_FAILURE(status)) { 8695b482a8SLen Brown return (status); 8795b482a8SLen Brown } 8895b482a8SLen Brown } 8995b482a8SLen Brown 9095b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 9195b482a8SLen Brown "Obj=%p [%s] Index=%X State=%p Num=%X\n", *object, 9295b482a8SLen Brown acpi_ut_get_object_type_name(*object), 9395b482a8SLen Brown index, walk_state, walk_state->result_count)); 9495b482a8SLen Brown 9595b482a8SLen Brown return (AE_OK); 9695b482a8SLen Brown } 9795b482a8SLen Brown 9895b482a8SLen Brown /******************************************************************************* 9995b482a8SLen Brown * 10095b482a8SLen Brown * FUNCTION: acpi_ds_result_push 10195b482a8SLen Brown * 102ba494beeSBob Moore * PARAMETERS: object - Where to return the popped object 10395b482a8SLen Brown * walk_state - Current Walk state 10495b482a8SLen Brown * 10595b482a8SLen Brown * RETURN: Status 10695b482a8SLen Brown * 10795b482a8SLen Brown * DESCRIPTION: Push an object onto the current result stack 10895b482a8SLen Brown * 10995b482a8SLen Brown ******************************************************************************/ 11095b482a8SLen Brown 11195b482a8SLen Brown acpi_status 11295b482a8SLen Brown acpi_ds_result_push(union acpi_operand_object *object, 11395b482a8SLen Brown struct acpi_walk_state *walk_state) 11495b482a8SLen Brown { 11595b482a8SLen Brown union acpi_generic_state *state; 11695b482a8SLen Brown acpi_status status; 11795b482a8SLen Brown u32 index; 11895b482a8SLen Brown 11995b482a8SLen Brown ACPI_FUNCTION_NAME(ds_result_push); 12095b482a8SLen Brown 12195b482a8SLen Brown if (walk_state->result_count > walk_state->result_size) { 12295b482a8SLen Brown ACPI_ERROR((AE_INFO, "Result stack is full")); 12395b482a8SLen Brown return (AE_AML_INTERNAL); 12495b482a8SLen Brown } else if (walk_state->result_count == walk_state->result_size) { 12595b482a8SLen Brown 12695b482a8SLen Brown /* Extend the result stack */ 12795b482a8SLen Brown 12895b482a8SLen Brown status = acpi_ds_result_stack_push(walk_state); 12995b482a8SLen Brown if (ACPI_FAILURE(status)) { 13095b482a8SLen Brown ACPI_ERROR((AE_INFO, 13195b482a8SLen Brown "Failed to extend the result stack")); 13295b482a8SLen Brown return (status); 13395b482a8SLen Brown } 13495b482a8SLen Brown } 13595b482a8SLen Brown 13695b482a8SLen Brown if (!(walk_state->result_count < walk_state->result_size)) { 13795b482a8SLen Brown ACPI_ERROR((AE_INFO, "No free elements in result stack")); 13895b482a8SLen Brown return (AE_AML_INTERNAL); 13995b482a8SLen Brown } 14095b482a8SLen Brown 14195b482a8SLen Brown state = walk_state->results; 14295b482a8SLen Brown if (!state) { 14395b482a8SLen Brown ACPI_ERROR((AE_INFO, "No result stack frame during push")); 14495b482a8SLen Brown return (AE_AML_INTERNAL); 14595b482a8SLen Brown } 14695b482a8SLen Brown 14795b482a8SLen Brown if (!object) { 14895b482a8SLen Brown ACPI_ERROR((AE_INFO, 149f6a22b0bSBob Moore "Null Object! Obj=%p State=%p Num=%u", 15095b482a8SLen Brown object, walk_state, walk_state->result_count)); 15195b482a8SLen Brown return (AE_BAD_PARAMETER); 15295b482a8SLen Brown } 15395b482a8SLen Brown 15495b482a8SLen Brown /* Assign the address of object to the top free element of result stack */ 15595b482a8SLen Brown 156ba9c3f55SBob Moore index = (u32)walk_state->result_count % ACPI_RESULTS_FRAME_OBJ_NUM; 15795b482a8SLen Brown state->results.obj_desc[index] = object; 15895b482a8SLen Brown walk_state->result_count++; 15995b482a8SLen Brown 16095b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p Num=%X Cur=%X\n", 16195b482a8SLen Brown object, 16295b482a8SLen Brown acpi_ut_get_object_type_name((union 16395b482a8SLen Brown acpi_operand_object *) 16495b482a8SLen Brown object), walk_state, 16595b482a8SLen Brown walk_state->result_count, 16695b482a8SLen Brown walk_state->current_result)); 16795b482a8SLen Brown 16895b482a8SLen Brown return (AE_OK); 16995b482a8SLen Brown } 17095b482a8SLen Brown 17195b482a8SLen Brown /******************************************************************************* 17295b482a8SLen Brown * 17395b482a8SLen Brown * FUNCTION: acpi_ds_result_stack_push 17495b482a8SLen Brown * 17595b482a8SLen Brown * PARAMETERS: walk_state - Current Walk state 17695b482a8SLen Brown * 17795b482a8SLen Brown * RETURN: Status 17895b482a8SLen Brown * 17995b482a8SLen Brown * DESCRIPTION: Push an object onto the walk_state result stack 18095b482a8SLen Brown * 18195b482a8SLen Brown ******************************************************************************/ 18295b482a8SLen Brown 18395b482a8SLen Brown static acpi_status acpi_ds_result_stack_push(struct acpi_walk_state *walk_state) 18495b482a8SLen Brown { 18595b482a8SLen Brown union acpi_generic_state *state; 18695b482a8SLen Brown 18795b482a8SLen Brown ACPI_FUNCTION_NAME(ds_result_stack_push); 18895b482a8SLen Brown 18995b482a8SLen Brown /* Check for stack overflow */ 19095b482a8SLen Brown 19195b482a8SLen Brown if (((u32) walk_state->result_size + ACPI_RESULTS_FRAME_OBJ_NUM) > 19295b482a8SLen Brown ACPI_RESULTS_OBJ_NUM_MAX) { 193f6a22b0bSBob Moore ACPI_ERROR((AE_INFO, "Result stack overflow: State=%p Num=%u", 19495b482a8SLen Brown walk_state, walk_state->result_size)); 19595b482a8SLen Brown return (AE_STACK_OVERFLOW); 19695b482a8SLen Brown } 19795b482a8SLen Brown 19895b482a8SLen Brown state = acpi_ut_create_generic_state(); 19995b482a8SLen Brown if (!state) { 20095b482a8SLen Brown return (AE_NO_MEMORY); 20195b482a8SLen Brown } 20295b482a8SLen Brown 20395b482a8SLen Brown state->common.descriptor_type = ACPI_DESC_TYPE_STATE_RESULT; 20495b482a8SLen Brown acpi_ut_push_generic_state(&walk_state->results, state); 20595b482a8SLen Brown 20695b482a8SLen Brown /* Increase the length of the result stack by the length of frame */ 20795b482a8SLen Brown 20895b482a8SLen Brown walk_state->result_size += ACPI_RESULTS_FRAME_OBJ_NUM; 20995b482a8SLen Brown 21095b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Results=%p State=%p\n", 21195b482a8SLen Brown state, walk_state)); 21295b482a8SLen Brown 21395b482a8SLen Brown return (AE_OK); 21495b482a8SLen Brown } 21595b482a8SLen Brown 21695b482a8SLen Brown /******************************************************************************* 21795b482a8SLen Brown * 21895b482a8SLen Brown * FUNCTION: acpi_ds_result_stack_pop 21995b482a8SLen Brown * 22095b482a8SLen Brown * PARAMETERS: walk_state - Current Walk state 22195b482a8SLen Brown * 22295b482a8SLen Brown * RETURN: Status 22395b482a8SLen Brown * 22495b482a8SLen Brown * DESCRIPTION: Pop an object off of the walk_state result stack 22595b482a8SLen Brown * 22695b482a8SLen Brown ******************************************************************************/ 22795b482a8SLen Brown 22895b482a8SLen Brown static acpi_status acpi_ds_result_stack_pop(struct acpi_walk_state *walk_state) 22995b482a8SLen Brown { 23095b482a8SLen Brown union acpi_generic_state *state; 23195b482a8SLen Brown 23295b482a8SLen Brown ACPI_FUNCTION_NAME(ds_result_stack_pop); 23395b482a8SLen Brown 23495b482a8SLen Brown /* Check for stack underflow */ 23595b482a8SLen Brown 23695b482a8SLen Brown if (walk_state->results == NULL) { 23795b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 23895b482a8SLen Brown "Result stack underflow - State=%p\n", 23995b482a8SLen Brown walk_state)); 24095b482a8SLen Brown return (AE_AML_NO_OPERAND); 24195b482a8SLen Brown } 24295b482a8SLen Brown 24395b482a8SLen Brown if (walk_state->result_size < ACPI_RESULTS_FRAME_OBJ_NUM) { 24495b482a8SLen Brown ACPI_ERROR((AE_INFO, "Insufficient result stack size")); 24595b482a8SLen Brown return (AE_AML_INTERNAL); 24695b482a8SLen Brown } 24795b482a8SLen Brown 24895b482a8SLen Brown state = acpi_ut_pop_generic_state(&walk_state->results); 24995b482a8SLen Brown acpi_ut_delete_generic_state(state); 25095b482a8SLen Brown 25195b482a8SLen Brown /* Decrease the length of result stack by the length of frame */ 25295b482a8SLen Brown 25395b482a8SLen Brown walk_state->result_size -= ACPI_RESULTS_FRAME_OBJ_NUM; 25495b482a8SLen Brown 25595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, 25695b482a8SLen Brown "Result=%p RemainingResults=%X State=%p\n", 25795b482a8SLen Brown state, walk_state->result_count, walk_state)); 25895b482a8SLen Brown 25995b482a8SLen Brown return (AE_OK); 26095b482a8SLen Brown } 26195b482a8SLen Brown 26295b482a8SLen Brown /******************************************************************************* 26395b482a8SLen Brown * 26495b482a8SLen Brown * FUNCTION: acpi_ds_obj_stack_push 26595b482a8SLen Brown * 266ba494beeSBob Moore * PARAMETERS: object - Object to push 26795b482a8SLen Brown * walk_state - Current Walk state 26895b482a8SLen Brown * 26995b482a8SLen Brown * RETURN: Status 27095b482a8SLen Brown * 27195b482a8SLen Brown * DESCRIPTION: Push an object onto this walk's object/operand stack 27295b482a8SLen Brown * 27395b482a8SLen Brown ******************************************************************************/ 27495b482a8SLen Brown 27595b482a8SLen Brown acpi_status 27695b482a8SLen Brown acpi_ds_obj_stack_push(void *object, struct acpi_walk_state *walk_state) 27795b482a8SLen Brown { 27895b482a8SLen Brown ACPI_FUNCTION_NAME(ds_obj_stack_push); 27995b482a8SLen Brown 28095b482a8SLen Brown /* Check for stack overflow */ 28195b482a8SLen Brown 28295b482a8SLen Brown if (walk_state->num_operands >= ACPI_OBJ_NUM_OPERANDS) { 28395b482a8SLen Brown ACPI_ERROR((AE_INFO, 284f6a22b0bSBob Moore "Object stack overflow! Obj=%p State=%p #Ops=%u", 28595b482a8SLen Brown object, walk_state, walk_state->num_operands)); 28695b482a8SLen Brown return (AE_STACK_OVERFLOW); 28795b482a8SLen Brown } 28895b482a8SLen Brown 28995b482a8SLen Brown /* Put the object onto the stack */ 29095b482a8SLen Brown 29195b482a8SLen Brown walk_state->operands[walk_state->operand_index] = object; 29295b482a8SLen Brown walk_state->num_operands++; 29395b482a8SLen Brown 29495b482a8SLen Brown /* For the usual order of filling the operand stack */ 29595b482a8SLen Brown 29695b482a8SLen Brown walk_state->operand_index++; 29795b482a8SLen Brown 29895b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Obj=%p [%s] State=%p #Ops=%X\n", 29995b482a8SLen Brown object, 30095b482a8SLen Brown acpi_ut_get_object_type_name((union 30195b482a8SLen Brown acpi_operand_object *) 30295b482a8SLen Brown object), walk_state, 30395b482a8SLen Brown walk_state->num_operands)); 30495b482a8SLen Brown 30595b482a8SLen Brown return (AE_OK); 30695b482a8SLen Brown } 30795b482a8SLen Brown 30895b482a8SLen Brown /******************************************************************************* 30995b482a8SLen Brown * 31095b482a8SLen Brown * FUNCTION: acpi_ds_obj_stack_pop 31195b482a8SLen Brown * 31295b482a8SLen Brown * PARAMETERS: pop_count - Number of objects/entries to pop 31395b482a8SLen Brown * walk_state - Current Walk state 31495b482a8SLen Brown * 31595b482a8SLen Brown * RETURN: Status 31695b482a8SLen Brown * 31795b482a8SLen Brown * DESCRIPTION: Pop this walk's object stack. Objects on the stack are NOT 31895b482a8SLen Brown * deleted by this routine. 31995b482a8SLen Brown * 32095b482a8SLen Brown ******************************************************************************/ 32195b482a8SLen Brown 32295b482a8SLen Brown acpi_status 32395b482a8SLen Brown acpi_ds_obj_stack_pop(u32 pop_count, struct acpi_walk_state *walk_state) 32495b482a8SLen Brown { 32595b482a8SLen Brown u32 i; 32695b482a8SLen Brown 32795b482a8SLen Brown ACPI_FUNCTION_NAME(ds_obj_stack_pop); 32895b482a8SLen Brown 32995b482a8SLen Brown for (i = 0; i < pop_count; i++) { 33095b482a8SLen Brown 33195b482a8SLen Brown /* Check for stack underflow */ 33295b482a8SLen Brown 33395b482a8SLen Brown if (walk_state->num_operands == 0) { 33495b482a8SLen Brown ACPI_ERROR((AE_INFO, 335f6a22b0bSBob Moore "Object stack underflow! Count=%X State=%p #Ops=%u", 33695b482a8SLen Brown pop_count, walk_state, 33795b482a8SLen Brown walk_state->num_operands)); 33895b482a8SLen Brown return (AE_STACK_UNDERFLOW); 33995b482a8SLen Brown } 34095b482a8SLen Brown 34195b482a8SLen Brown /* Just set the stack entry to null */ 34295b482a8SLen Brown 34395b482a8SLen Brown walk_state->num_operands--; 34495b482a8SLen Brown walk_state->operands[walk_state->num_operands] = NULL; 34595b482a8SLen Brown } 34695b482a8SLen Brown 347f6a22b0bSBob Moore ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%u\n", 34895b482a8SLen Brown pop_count, walk_state, walk_state->num_operands)); 34995b482a8SLen Brown 35095b482a8SLen Brown return (AE_OK); 35195b482a8SLen Brown } 35295b482a8SLen Brown 35395b482a8SLen Brown /******************************************************************************* 35495b482a8SLen Brown * 35595b482a8SLen Brown * FUNCTION: acpi_ds_obj_stack_pop_and_delete 35695b482a8SLen Brown * 35795b482a8SLen Brown * PARAMETERS: pop_count - Number of objects/entries to pop 35895b482a8SLen Brown * walk_state - Current Walk state 35995b482a8SLen Brown * 36095b482a8SLen Brown * RETURN: Status 36195b482a8SLen Brown * 36295b482a8SLen Brown * DESCRIPTION: Pop this walk's object stack and delete each object that is 36395b482a8SLen Brown * popped off. 36495b482a8SLen Brown * 36595b482a8SLen Brown ******************************************************************************/ 36695b482a8SLen Brown 36795b482a8SLen Brown void 36895b482a8SLen Brown acpi_ds_obj_stack_pop_and_delete(u32 pop_count, 36995b482a8SLen Brown struct acpi_walk_state *walk_state) 37095b482a8SLen Brown { 37195b482a8SLen Brown s32 i; 37295b482a8SLen Brown union acpi_operand_object *obj_desc; 37395b482a8SLen Brown 37495b482a8SLen Brown ACPI_FUNCTION_NAME(ds_obj_stack_pop_and_delete); 37595b482a8SLen Brown 37695b482a8SLen Brown if (pop_count == 0) { 37795b482a8SLen Brown return; 37895b482a8SLen Brown } 37995b482a8SLen Brown 38095b482a8SLen Brown for (i = (s32)pop_count - 1; i >= 0; i--) { 38195b482a8SLen Brown if (walk_state->num_operands == 0) { 38295b482a8SLen Brown return; 38395b482a8SLen Brown } 38495b482a8SLen Brown 38595b482a8SLen Brown /* Pop the stack and delete an object if present in this stack entry */ 38695b482a8SLen Brown 38795b482a8SLen Brown walk_state->num_operands--; 38895b482a8SLen Brown obj_desc = walk_state->operands[i]; 38995b482a8SLen Brown if (obj_desc) { 39095b482a8SLen Brown acpi_ut_remove_reference(walk_state->operands[i]); 39195b482a8SLen Brown walk_state->operands[i] = NULL; 39295b482a8SLen Brown } 39395b482a8SLen Brown } 39495b482a8SLen Brown 39595b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Count=%X State=%p #Ops=%X\n", 39695b482a8SLen Brown pop_count, walk_state, walk_state->num_operands)); 39795b482a8SLen Brown } 39895b482a8SLen Brown 39995b482a8SLen Brown /******************************************************************************* 40095b482a8SLen Brown * 40195b482a8SLen Brown * FUNCTION: acpi_ds_get_current_walk_state 40295b482a8SLen Brown * 403ba494beeSBob Moore * PARAMETERS: thread - Get current active state for this Thread 40495b482a8SLen Brown * 40595b482a8SLen Brown * RETURN: Pointer to the current walk state 40695b482a8SLen Brown * 40795b482a8SLen Brown * DESCRIPTION: Get the walk state that is at the head of the list (the "current" 40895b482a8SLen Brown * walk state.) 40995b482a8SLen Brown * 41095b482a8SLen Brown ******************************************************************************/ 41195b482a8SLen Brown 41295b482a8SLen Brown struct acpi_walk_state *acpi_ds_get_current_walk_state(struct acpi_thread_state 41395b482a8SLen Brown *thread) 41495b482a8SLen Brown { 41595b482a8SLen Brown ACPI_FUNCTION_NAME(ds_get_current_walk_state); 41695b482a8SLen Brown 41795b482a8SLen Brown if (!thread) { 41895b482a8SLen Brown return (NULL); 41995b482a8SLen Brown } 42095b482a8SLen Brown 42195b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Current WalkState %p\n", 42295b482a8SLen Brown thread->walk_state_list)); 42395b482a8SLen Brown 42495b482a8SLen Brown return (thread->walk_state_list); 42595b482a8SLen Brown } 42695b482a8SLen Brown 42795b482a8SLen Brown /******************************************************************************* 42895b482a8SLen Brown * 42995b482a8SLen Brown * FUNCTION: acpi_ds_push_walk_state 43095b482a8SLen Brown * 43195b482a8SLen Brown * PARAMETERS: walk_state - State to push 432ba494beeSBob Moore * thread - Thread state object 43395b482a8SLen Brown * 43495b482a8SLen Brown * RETURN: None 43595b482a8SLen Brown * 43695b482a8SLen Brown * DESCRIPTION: Place the Thread state at the head of the state list 43795b482a8SLen Brown * 43895b482a8SLen Brown ******************************************************************************/ 43995b482a8SLen Brown 44095b482a8SLen Brown void 44195b482a8SLen Brown acpi_ds_push_walk_state(struct acpi_walk_state *walk_state, 44295b482a8SLen Brown struct acpi_thread_state *thread) 44395b482a8SLen Brown { 44495b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_push_walk_state); 44595b482a8SLen Brown 44695b482a8SLen Brown walk_state->next = thread->walk_state_list; 44795b482a8SLen Brown thread->walk_state_list = walk_state; 44895b482a8SLen Brown 44995b482a8SLen Brown return_VOID; 45095b482a8SLen Brown } 45195b482a8SLen Brown 45295b482a8SLen Brown /******************************************************************************* 45395b482a8SLen Brown * 45495b482a8SLen Brown * FUNCTION: acpi_ds_pop_walk_state 45595b482a8SLen Brown * 456ba494beeSBob Moore * PARAMETERS: thread - Current thread state 45795b482a8SLen Brown * 45895b482a8SLen Brown * RETURN: A walk_state object popped from the thread's stack 45995b482a8SLen Brown * 46095b482a8SLen Brown * DESCRIPTION: Remove and return the walkstate object that is at the head of 46195b482a8SLen Brown * the walk stack for the given walk list. NULL indicates that 46295b482a8SLen Brown * the list is empty. 46395b482a8SLen Brown * 46495b482a8SLen Brown ******************************************************************************/ 46595b482a8SLen Brown 46695b482a8SLen Brown struct acpi_walk_state *acpi_ds_pop_walk_state(struct acpi_thread_state *thread) 46795b482a8SLen Brown { 46895b482a8SLen Brown struct acpi_walk_state *walk_state; 46995b482a8SLen Brown 47095b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_pop_walk_state); 47195b482a8SLen Brown 47295b482a8SLen Brown walk_state = thread->walk_state_list; 47395b482a8SLen Brown 47495b482a8SLen Brown if (walk_state) { 47595b482a8SLen Brown 47695b482a8SLen Brown /* Next walk state becomes the current walk state */ 47795b482a8SLen Brown 47895b482a8SLen Brown thread->walk_state_list = walk_state->next; 47995b482a8SLen Brown 48095b482a8SLen Brown /* 48195b482a8SLen Brown * Don't clear the NEXT field, this serves as an indicator 48295b482a8SLen Brown * that there is a parent WALK STATE 48395b482a8SLen Brown * Do Not: walk_state->Next = NULL; 48495b482a8SLen Brown */ 48595b482a8SLen Brown } 48695b482a8SLen Brown 48795b482a8SLen Brown return_PTR(walk_state); 48895b482a8SLen Brown } 48995b482a8SLen Brown 49095b482a8SLen Brown /******************************************************************************* 49195b482a8SLen Brown * 49295b482a8SLen Brown * FUNCTION: acpi_ds_create_walk_state 49395b482a8SLen Brown * 49495b482a8SLen Brown * PARAMETERS: owner_id - ID for object creation 495ba494beeSBob Moore * origin - Starting point for this walk 49695b482a8SLen Brown * method_desc - Method object 497ba494beeSBob Moore * thread - Current thread state 49895b482a8SLen Brown * 49995b482a8SLen Brown * RETURN: Pointer to the new walk state. 50095b482a8SLen Brown * 50195b482a8SLen Brown * DESCRIPTION: Allocate and initialize a new walk state. The current walk 50295b482a8SLen Brown * state is set to this new state. 50395b482a8SLen Brown * 50495b482a8SLen Brown ******************************************************************************/ 50595b482a8SLen Brown 5061f86e8c1SLv Zheng struct acpi_walk_state *acpi_ds_create_walk_state(acpi_owner_id owner_id, 5071f86e8c1SLv Zheng union acpi_parse_object 5081f86e8c1SLv Zheng *origin, 5091f86e8c1SLv Zheng union acpi_operand_object 5101f86e8c1SLv Zheng *method_desc, 5111f86e8c1SLv Zheng struct acpi_thread_state 51295b482a8SLen Brown *thread) 51395b482a8SLen Brown { 51495b482a8SLen Brown struct acpi_walk_state *walk_state; 51595b482a8SLen Brown 51695b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_create_walk_state); 51795b482a8SLen Brown 51895b482a8SLen Brown walk_state = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_walk_state)); 51995b482a8SLen Brown if (!walk_state) { 52095b482a8SLen Brown return_PTR(NULL); 52195b482a8SLen Brown } 52295b482a8SLen Brown 52395b482a8SLen Brown walk_state->descriptor_type = ACPI_DESC_TYPE_WALK; 52495b482a8SLen Brown walk_state->method_desc = method_desc; 52595b482a8SLen Brown walk_state->owner_id = owner_id; 52695b482a8SLen Brown walk_state->origin = origin; 52795b482a8SLen Brown walk_state->thread = thread; 52895b482a8SLen Brown 52995b482a8SLen Brown walk_state->parser_state.start_op = origin; 53095b482a8SLen Brown 53195b482a8SLen Brown /* Init the method args/local */ 53295b482a8SLen Brown 533*178a0f63SErik Schmauss #ifndef ACPI_CONSTANT_EVAL_ONLY 53495b482a8SLen Brown acpi_ds_method_data_init(walk_state); 53595b482a8SLen Brown #endif 53695b482a8SLen Brown 53795b482a8SLen Brown /* Put the new state at the head of the walk list */ 53895b482a8SLen Brown 53995b482a8SLen Brown if (thread) { 54095b482a8SLen Brown acpi_ds_push_walk_state(walk_state, thread); 54195b482a8SLen Brown } 54295b482a8SLen Brown 54395b482a8SLen Brown return_PTR(walk_state); 54495b482a8SLen Brown } 54595b482a8SLen Brown 54695b482a8SLen Brown /******************************************************************************* 54795b482a8SLen Brown * 54895b482a8SLen Brown * FUNCTION: acpi_ds_init_aml_walk 54995b482a8SLen Brown * 55095b482a8SLen Brown * PARAMETERS: walk_state - New state to be initialized 551ba494beeSBob Moore * op - Current parse op 55295b482a8SLen Brown * method_node - Control method NS node, if any 55395b482a8SLen Brown * aml_start - Start of AML 55495b482a8SLen Brown * aml_length - Length of AML 555ba494beeSBob Moore * info - Method info block (params, etc.) 55695b482a8SLen Brown * pass_number - 1, 2, or 3 55795b482a8SLen Brown * 55895b482a8SLen Brown * RETURN: Status 55995b482a8SLen Brown * 56095b482a8SLen Brown * DESCRIPTION: Initialize a walk state for a pass 1 or 2 parse tree walk 56195b482a8SLen Brown * 56295b482a8SLen Brown ******************************************************************************/ 56395b482a8SLen Brown 56495b482a8SLen Brown acpi_status 56595b482a8SLen Brown acpi_ds_init_aml_walk(struct acpi_walk_state *walk_state, 56695b482a8SLen Brown union acpi_parse_object *op, 56795b482a8SLen Brown struct acpi_namespace_node *method_node, 56895b482a8SLen Brown u8 * aml_start, 56995b482a8SLen Brown u32 aml_length, 57095b482a8SLen Brown struct acpi_evaluate_info *info, u8 pass_number) 57195b482a8SLen Brown { 57295b482a8SLen Brown acpi_status status; 57395b482a8SLen Brown struct acpi_parse_state *parser_state = &walk_state->parser_state; 57495b482a8SLen Brown union acpi_parse_object *extra_op; 57595b482a8SLen Brown 57695b482a8SLen Brown ACPI_FUNCTION_TRACE(ds_init_aml_walk); 57795b482a8SLen Brown 57895b482a8SLen Brown walk_state->parser_state.aml = 57995b482a8SLen Brown walk_state->parser_state.aml_start = aml_start; 58095b482a8SLen Brown walk_state->parser_state.aml_end = 58195b482a8SLen Brown walk_state->parser_state.pkg_end = aml_start + aml_length; 58295b482a8SLen Brown 58395b482a8SLen Brown /* The next_op of the next_walk will be the beginning of the method */ 58495b482a8SLen Brown 58595b482a8SLen Brown walk_state->next_op = NULL; 58695b482a8SLen Brown walk_state->pass_number = pass_number; 58795b482a8SLen Brown 58895b482a8SLen Brown if (info) { 58995b482a8SLen Brown walk_state->params = info->parameters; 59095b482a8SLen Brown walk_state->caller_return_desc = &info->return_object; 59195b482a8SLen Brown } 59295b482a8SLen Brown 59395b482a8SLen Brown status = acpi_ps_init_scope(&walk_state->parser_state, op); 59495b482a8SLen Brown if (ACPI_FAILURE(status)) { 59595b482a8SLen Brown return_ACPI_STATUS(status); 59695b482a8SLen Brown } 59795b482a8SLen Brown 59895b482a8SLen Brown if (method_node) { 59995b482a8SLen Brown walk_state->parser_state.start_node = method_node; 60095b482a8SLen Brown walk_state->walk_type = ACPI_WALK_METHOD; 60195b482a8SLen Brown walk_state->method_node = method_node; 60295b482a8SLen Brown walk_state->method_desc = 60395b482a8SLen Brown acpi_ns_get_attached_object(method_node); 60495b482a8SLen Brown 60595b482a8SLen Brown /* Push start scope on scope stack and make it current */ 60695b482a8SLen Brown 60795b482a8SLen Brown status = 60895b482a8SLen Brown acpi_ds_scope_stack_push(method_node, ACPI_TYPE_METHOD, 60995b482a8SLen Brown walk_state); 61095b482a8SLen Brown if (ACPI_FAILURE(status)) { 61195b482a8SLen Brown return_ACPI_STATUS(status); 61295b482a8SLen Brown } 61395b482a8SLen Brown 61495b482a8SLen Brown /* Init the method arguments */ 61595b482a8SLen Brown 61695b482a8SLen Brown status = acpi_ds_method_data_init_args(walk_state->params, 61795b482a8SLen Brown ACPI_METHOD_NUM_ARGS, 61895b482a8SLen Brown walk_state); 61995b482a8SLen Brown if (ACPI_FAILURE(status)) { 62095b482a8SLen Brown return_ACPI_STATUS(status); 62195b482a8SLen Brown } 62295b482a8SLen Brown } else { 62395b482a8SLen Brown /* 62495b482a8SLen Brown * Setup the current scope. 62595b482a8SLen Brown * Find a Named Op that has a namespace node associated with it. 62695b482a8SLen Brown * search upwards from this Op. Current scope is the first 62795b482a8SLen Brown * Op with a namespace node. 62895b482a8SLen Brown */ 62995b482a8SLen Brown extra_op = parser_state->start_op; 63095b482a8SLen Brown while (extra_op && !extra_op->common.node) { 63195b482a8SLen Brown extra_op = extra_op->common.parent; 63295b482a8SLen Brown } 63395b482a8SLen Brown 63495b482a8SLen Brown if (!extra_op) { 63595b482a8SLen Brown parser_state->start_node = NULL; 63695b482a8SLen Brown } else { 63795b482a8SLen Brown parser_state->start_node = extra_op->common.node; 63895b482a8SLen Brown } 63995b482a8SLen Brown 64095b482a8SLen Brown if (parser_state->start_node) { 64195b482a8SLen Brown 64295b482a8SLen Brown /* Push start scope on scope stack and make it current */ 64395b482a8SLen Brown 64495b482a8SLen Brown status = 64595b482a8SLen Brown acpi_ds_scope_stack_push(parser_state->start_node, 64695b482a8SLen Brown parser_state->start_node-> 64795b482a8SLen Brown type, walk_state); 64895b482a8SLen Brown if (ACPI_FAILURE(status)) { 64995b482a8SLen Brown return_ACPI_STATUS(status); 65095b482a8SLen Brown } 65195b482a8SLen Brown } 65295b482a8SLen Brown } 65395b482a8SLen Brown 65495b482a8SLen Brown status = acpi_ds_init_callbacks(walk_state, pass_number); 65595b482a8SLen Brown return_ACPI_STATUS(status); 65695b482a8SLen Brown } 65795b482a8SLen Brown 65895b482a8SLen Brown /******************************************************************************* 65995b482a8SLen Brown * 66095b482a8SLen Brown * FUNCTION: acpi_ds_delete_walk_state 66195b482a8SLen Brown * 66295b482a8SLen Brown * PARAMETERS: walk_state - State to delete 66395b482a8SLen Brown * 66495b482a8SLen Brown * RETURN: Status 66595b482a8SLen Brown * 66695b482a8SLen Brown * DESCRIPTION: Delete a walk state including all internal data structures 66795b482a8SLen Brown * 66895b482a8SLen Brown ******************************************************************************/ 66995b482a8SLen Brown 67095b482a8SLen Brown void acpi_ds_delete_walk_state(struct acpi_walk_state *walk_state) 67195b482a8SLen Brown { 67295b482a8SLen Brown union acpi_generic_state *state; 67395b482a8SLen Brown 67495b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ds_delete_walk_state, walk_state); 67595b482a8SLen Brown 67695b482a8SLen Brown if (!walk_state) { 67768aafc35SBob Moore return_VOID; 67895b482a8SLen Brown } 67995b482a8SLen Brown 68095b482a8SLen Brown if (walk_state->descriptor_type != ACPI_DESC_TYPE_WALK) { 68195b482a8SLen Brown ACPI_ERROR((AE_INFO, "%p is not a valid walk state", 68295b482a8SLen Brown walk_state)); 68368aafc35SBob Moore return_VOID; 68495b482a8SLen Brown } 68595b482a8SLen Brown 68695b482a8SLen Brown /* There should not be any open scopes */ 68795b482a8SLen Brown 68895b482a8SLen Brown if (walk_state->parser_state.scope) { 68995b482a8SLen Brown ACPI_ERROR((AE_INFO, "%p walk still has a scope list", 69095b482a8SLen Brown walk_state)); 69195b482a8SLen Brown acpi_ps_cleanup_scope(&walk_state->parser_state); 69295b482a8SLen Brown } 69395b482a8SLen Brown 69495b482a8SLen Brown /* Always must free any linked control states */ 69595b482a8SLen Brown 69695b482a8SLen Brown while (walk_state->control_state) { 69795b482a8SLen Brown state = walk_state->control_state; 69895b482a8SLen Brown walk_state->control_state = state->common.next; 69995b482a8SLen Brown 70095b482a8SLen Brown acpi_ut_delete_generic_state(state); 70195b482a8SLen Brown } 70295b482a8SLen Brown 70395b482a8SLen Brown /* Always must free any linked parse states */ 70495b482a8SLen Brown 70595b482a8SLen Brown while (walk_state->scope_info) { 70695b482a8SLen Brown state = walk_state->scope_info; 70795b482a8SLen Brown walk_state->scope_info = state->common.next; 70895b482a8SLen Brown 70995b482a8SLen Brown acpi_ut_delete_generic_state(state); 71095b482a8SLen Brown } 71195b482a8SLen Brown 71295b482a8SLen Brown /* Always must free any stacked result states */ 71395b482a8SLen Brown 71495b482a8SLen Brown while (walk_state->results) { 71595b482a8SLen Brown state = walk_state->results; 71695b482a8SLen Brown walk_state->results = state->common.next; 71795b482a8SLen Brown 71895b482a8SLen Brown acpi_ut_delete_generic_state(state); 71995b482a8SLen Brown } 72095b482a8SLen Brown 72195b482a8SLen Brown ACPI_FREE(walk_state); 72295b482a8SLen Brown return_VOID; 72395b482a8SLen Brown } 724