/******************************************************************************1*2* Module Name: dsopcode - Dispatcher suport for regions and fields3*4*****************************************************************************/56/*7* Copyright (C) 2000 - 2011, Intel Corp.8* All rights reserved.9*10* Redistribution and use in source and binary forms, with or without11* modification, are permitted provided that the following conditions12* are met:13* 1. Redistributions of source code must retain the above copyright14* notice, this list of conditions, and the following disclaimer,15* without modification.16* 2. Redistributions in binary form must reproduce at minimum a disclaimer17* substantially similar to the "NO WARRANTY" disclaimer below18* ("Disclaimer") and any redistribution must be conditioned upon19* including a substantially similar Disclaimer requirement for further20* binary redistribution.21* 3. Neither the names of the above-listed copyright holders nor the names22* of any contributors may be used to endorse or promote products derived23* from this software without specific prior written permission.24*25* Alternatively, this software may be distributed under the terms of the26* GNU General Public License ("GPL") version 2 as published by the Free27* Software Foundation.28*29* NO WARRANTY30* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS31* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT32* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR33* A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT34* HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL35* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS36* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)37* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,38* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING39* IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE40* POSSIBILITY OF SUCH DAMAGES.41*/4243#include <acpi/acpi.h>44#include "accommon.h"45#include "acparser.h"46#include "amlcode.h"47#include "acdispat.h"48#include "acinterp.h"49#include "acnamesp.h"50#include "acevents.h"51#include "actables.h"5253#define _COMPONENT ACPI_DISPATCHER54ACPI_MODULE_NAME("dsopcode")5556/* Local prototypes */57static acpi_status58acpi_ds_init_buffer_field(u16 aml_opcode,59union acpi_operand_object *obj_desc,60union acpi_operand_object *buffer_desc,61union acpi_operand_object *offset_desc,62union acpi_operand_object *length_desc,63union acpi_operand_object *result_desc);6465/*******************************************************************************66*67* FUNCTION: acpi_ds_initialize_region68*69* PARAMETERS: obj_handle - Region namespace node70*71* RETURN: Status72*73* DESCRIPTION: Front end to ev_initialize_region74*75******************************************************************************/7677acpi_status acpi_ds_initialize_region(acpi_handle obj_handle)78{79union acpi_operand_object *obj_desc;80acpi_status status;8182obj_desc = acpi_ns_get_attached_object(obj_handle);8384/* Namespace is NOT locked */8586status = acpi_ev_initialize_region(obj_desc, FALSE);87return (status);88}8990/*******************************************************************************91*92* FUNCTION: acpi_ds_init_buffer_field93*94* PARAMETERS: aml_opcode - create_xxx_field95* obj_desc - buffer_field object96* buffer_desc - Host Buffer97* offset_desc - Offset into buffer98* length_desc - Length of field (CREATE_FIELD_OP only)99* result_desc - Where to store the result100*101* RETURN: Status102*103* DESCRIPTION: Perform actual initialization of a buffer field104*105******************************************************************************/106107static acpi_status108acpi_ds_init_buffer_field(u16 aml_opcode,109union acpi_operand_object *obj_desc,110union acpi_operand_object *buffer_desc,111union acpi_operand_object *offset_desc,112union acpi_operand_object *length_desc,113union acpi_operand_object *result_desc)114{115u32 offset;116u32 bit_offset;117u32 bit_count;118u8 field_flags;119acpi_status status;120121ACPI_FUNCTION_TRACE_PTR(ds_init_buffer_field, obj_desc);122123/* Host object must be a Buffer */124125if (buffer_desc->common.type != ACPI_TYPE_BUFFER) {126ACPI_ERROR((AE_INFO,127"Target of Create Field is not a Buffer object - %s",128acpi_ut_get_object_type_name(buffer_desc)));129130status = AE_AML_OPERAND_TYPE;131goto cleanup;132}133134/*135* The last parameter to all of these opcodes (result_desc) started136* out as a name_string, and should therefore now be a NS node137* after resolution in acpi_ex_resolve_operands().138*/139if (ACPI_GET_DESCRIPTOR_TYPE(result_desc) != ACPI_DESC_TYPE_NAMED) {140ACPI_ERROR((AE_INFO,141"(%s) destination not a NS Node [%s]",142acpi_ps_get_opcode_name(aml_opcode),143acpi_ut_get_descriptor_name(result_desc)));144145status = AE_AML_OPERAND_TYPE;146goto cleanup;147}148149offset = (u32) offset_desc->integer.value;150151/*152* Setup the Bit offsets and counts, according to the opcode153*/154switch (aml_opcode) {155case AML_CREATE_FIELD_OP:156157/* Offset is in bits, count is in bits */158159field_flags = AML_FIELD_ACCESS_BYTE;160bit_offset = offset;161bit_count = (u32) length_desc->integer.value;162163/* Must have a valid (>0) bit count */164165if (bit_count == 0) {166ACPI_ERROR((AE_INFO,167"Attempt to CreateField of length zero"));168status = AE_AML_OPERAND_VALUE;169goto cleanup;170}171break;172173case AML_CREATE_BIT_FIELD_OP:174175/* Offset is in bits, Field is one bit */176177bit_offset = offset;178bit_count = 1;179field_flags = AML_FIELD_ACCESS_BYTE;180break;181182case AML_CREATE_BYTE_FIELD_OP:183184/* Offset is in bytes, field is one byte */185186bit_offset = 8 * offset;187bit_count = 8;188field_flags = AML_FIELD_ACCESS_BYTE;189break;190191case AML_CREATE_WORD_FIELD_OP:192193/* Offset is in bytes, field is one word */194195bit_offset = 8 * offset;196bit_count = 16;197field_flags = AML_FIELD_ACCESS_WORD;198break;199200case AML_CREATE_DWORD_FIELD_OP:201202/* Offset is in bytes, field is one dword */203204bit_offset = 8 * offset;205bit_count = 32;206field_flags = AML_FIELD_ACCESS_DWORD;207break;208209case AML_CREATE_QWORD_FIELD_OP:210211/* Offset is in bytes, field is one qword */212213bit_offset = 8 * offset;214bit_count = 64;215field_flags = AML_FIELD_ACCESS_QWORD;216break;217218default:219220ACPI_ERROR((AE_INFO,221"Unknown field creation opcode 0x%02X",222aml_opcode));223status = AE_AML_BAD_OPCODE;224goto cleanup;225}226227/* Entire field must fit within the current length of the buffer */228229if ((bit_offset + bit_count) > (8 * (u32) buffer_desc->buffer.length)) {230ACPI_ERROR((AE_INFO,231"Field [%4.4s] at %u exceeds Buffer [%4.4s] size %u (bits)",232acpi_ut_get_node_name(result_desc),233bit_offset + bit_count,234acpi_ut_get_node_name(buffer_desc->buffer.node),2358 * (u32) buffer_desc->buffer.length));236status = AE_AML_BUFFER_LIMIT;237goto cleanup;238}239240/*241* Initialize areas of the field object that are common to all fields242* For field_flags, use LOCK_RULE = 0 (NO_LOCK),243* UPDATE_RULE = 0 (UPDATE_PRESERVE)244*/245status = acpi_ex_prep_common_field_object(obj_desc, field_flags, 0,246bit_offset, bit_count);247if (ACPI_FAILURE(status)) {248goto cleanup;249}250251obj_desc->buffer_field.buffer_obj = buffer_desc;252253/* Reference count for buffer_desc inherits obj_desc count */254255buffer_desc->common.reference_count = (u16)256(buffer_desc->common.reference_count +257obj_desc->common.reference_count);258259cleanup:260261/* Always delete the operands */262263acpi_ut_remove_reference(offset_desc);264acpi_ut_remove_reference(buffer_desc);265266if (aml_opcode == AML_CREATE_FIELD_OP) {267acpi_ut_remove_reference(length_desc);268}269270/* On failure, delete the result descriptor */271272if (ACPI_FAILURE(status)) {273acpi_ut_remove_reference(result_desc); /* Result descriptor */274} else {275/* Now the address and length are valid for this buffer_field */276277obj_desc->buffer_field.flags |= AOPOBJ_DATA_VALID;278}279280return_ACPI_STATUS(status);281}282283/*******************************************************************************284*285* FUNCTION: acpi_ds_eval_buffer_field_operands286*287* PARAMETERS: walk_state - Current walk288* Op - A valid buffer_field Op object289*290* RETURN: Status291*292* DESCRIPTION: Get buffer_field Buffer and Index293* Called from acpi_ds_exec_end_op during buffer_field parse tree walk294*295******************************************************************************/296297acpi_status298acpi_ds_eval_buffer_field_operands(struct acpi_walk_state *walk_state,299union acpi_parse_object *op)300{301acpi_status status;302union acpi_operand_object *obj_desc;303struct acpi_namespace_node *node;304union acpi_parse_object *next_op;305306ACPI_FUNCTION_TRACE_PTR(ds_eval_buffer_field_operands, op);307308/*309* This is where we evaluate the address and length fields of the310* create_xxx_field declaration311*/312node = op->common.node;313314/* next_op points to the op that holds the Buffer */315316next_op = op->common.value.arg;317318/* Evaluate/create the address and length operands */319320status = acpi_ds_create_operands(walk_state, next_op);321if (ACPI_FAILURE(status)) {322return_ACPI_STATUS(status);323}324325obj_desc = acpi_ns_get_attached_object(node);326if (!obj_desc) {327return_ACPI_STATUS(AE_NOT_EXIST);328}329330/* Resolve the operands */331332status = acpi_ex_resolve_operands(op->common.aml_opcode,333ACPI_WALK_OPERANDS, walk_state);334if (ACPI_FAILURE(status)) {335ACPI_ERROR((AE_INFO, "(%s) bad operand(s), status 0x%X",336acpi_ps_get_opcode_name(op->common.aml_opcode),337status));338339return_ACPI_STATUS(status);340}341342/* Initialize the Buffer Field */343344if (op->common.aml_opcode == AML_CREATE_FIELD_OP) {345346/* NOTE: Slightly different operands for this opcode */347348status =349acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,350walk_state->operands[0],351walk_state->operands[1],352walk_state->operands[2],353walk_state->operands[3]);354} else {355/* All other, create_xxx_field opcodes */356357status =358acpi_ds_init_buffer_field(op->common.aml_opcode, obj_desc,359walk_state->operands[0],360walk_state->operands[1], NULL,361walk_state->operands[2]);362}363364return_ACPI_STATUS(status);365}366367/*******************************************************************************368*369* FUNCTION: acpi_ds_eval_region_operands370*371* PARAMETERS: walk_state - Current walk372* Op - A valid region Op object373*374* RETURN: Status375*376* DESCRIPTION: Get region address and length377* Called from acpi_ds_exec_end_op during op_region parse tree walk378*379******************************************************************************/380381acpi_status382acpi_ds_eval_region_operands(struct acpi_walk_state *walk_state,383union acpi_parse_object *op)384{385acpi_status status;386union acpi_operand_object *obj_desc;387union acpi_operand_object *operand_desc;388struct acpi_namespace_node *node;389union acpi_parse_object *next_op;390391ACPI_FUNCTION_TRACE_PTR(ds_eval_region_operands, op);392393/*394* This is where we evaluate the address and length fields of the395* op_region declaration396*/397node = op->common.node;398399/* next_op points to the op that holds the space_iD */400401next_op = op->common.value.arg;402403/* next_op points to address op */404405next_op = next_op->common.next;406407/* Evaluate/create the address and length operands */408409status = acpi_ds_create_operands(walk_state, next_op);410if (ACPI_FAILURE(status)) {411return_ACPI_STATUS(status);412}413414/* Resolve the length and address operands to numbers */415416status = acpi_ex_resolve_operands(op->common.aml_opcode,417ACPI_WALK_OPERANDS, walk_state);418if (ACPI_FAILURE(status)) {419return_ACPI_STATUS(status);420}421422obj_desc = acpi_ns_get_attached_object(node);423if (!obj_desc) {424return_ACPI_STATUS(AE_NOT_EXIST);425}426427/*428* Get the length operand and save it429* (at Top of stack)430*/431operand_desc = walk_state->operands[walk_state->num_operands - 1];432433obj_desc->region.length = (u32) operand_desc->integer.value;434acpi_ut_remove_reference(operand_desc);435436/*437* Get the address and save it438* (at top of stack - 1)439*/440operand_desc = walk_state->operands[walk_state->num_operands - 2];441442obj_desc->region.address = (acpi_physical_address)443operand_desc->integer.value;444acpi_ut_remove_reference(operand_desc);445446ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",447obj_desc,448ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),449obj_desc->region.length));450451/* Now the address and length are valid for this opregion */452453obj_desc->region.flags |= AOPOBJ_DATA_VALID;454455return_ACPI_STATUS(status);456}457458/*******************************************************************************459*460* FUNCTION: acpi_ds_eval_table_region_operands461*462* PARAMETERS: walk_state - Current walk463* Op - A valid region Op object464*465* RETURN: Status466*467* DESCRIPTION: Get region address and length.468* Called from acpi_ds_exec_end_op during data_table_region parse469* tree walk.470*471******************************************************************************/472473acpi_status474acpi_ds_eval_table_region_operands(struct acpi_walk_state *walk_state,475union acpi_parse_object *op)476{477acpi_status status;478union acpi_operand_object *obj_desc;479union acpi_operand_object **operand;480struct acpi_namespace_node *node;481union acpi_parse_object *next_op;482u32 table_index;483struct acpi_table_header *table;484485ACPI_FUNCTION_TRACE_PTR(ds_eval_table_region_operands, op);486487/*488* This is where we evaluate the signature_string and oem_iDString489* and oem_table_iDString of the data_table_region declaration490*/491node = op->common.node;492493/* next_op points to signature_string op */494495next_op = op->common.value.arg;496497/*498* Evaluate/create the signature_string and oem_iDString499* and oem_table_iDString operands500*/501status = acpi_ds_create_operands(walk_state, next_op);502if (ACPI_FAILURE(status)) {503return_ACPI_STATUS(status);504}505506/*507* Resolve the signature_string and oem_iDString508* and oem_table_iDString operands509*/510status = acpi_ex_resolve_operands(op->common.aml_opcode,511ACPI_WALK_OPERANDS, walk_state);512if (ACPI_FAILURE(status)) {513return_ACPI_STATUS(status);514}515516operand = &walk_state->operands[0];517518/* Find the ACPI table */519520status = acpi_tb_find_table(operand[0]->string.pointer,521operand[1]->string.pointer,522operand[2]->string.pointer, &table_index);523if (ACPI_FAILURE(status)) {524return_ACPI_STATUS(status);525}526527acpi_ut_remove_reference(operand[0]);528acpi_ut_remove_reference(operand[1]);529acpi_ut_remove_reference(operand[2]);530531status = acpi_get_table_by_index(table_index, &table);532if (ACPI_FAILURE(status)) {533return_ACPI_STATUS(status);534}535536obj_desc = acpi_ns_get_attached_object(node);537if (!obj_desc) {538return_ACPI_STATUS(AE_NOT_EXIST);539}540541obj_desc->region.address =542(acpi_physical_address) ACPI_TO_INTEGER(table);543obj_desc->region.length = table->length;544545ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "RgnObj %p Addr %8.8X%8.8X Len %X\n",546obj_desc,547ACPI_FORMAT_NATIVE_UINT(obj_desc->region.address),548obj_desc->region.length));549550/* Now the address and length are valid for this opregion */551552obj_desc->region.flags |= AOPOBJ_DATA_VALID;553554return_ACPI_STATUS(status);555}556557/*******************************************************************************558*559* FUNCTION: acpi_ds_eval_data_object_operands560*561* PARAMETERS: walk_state - Current walk562* Op - A valid data_object Op object563* obj_desc - data_object564*565* RETURN: Status566*567* DESCRIPTION: Get the operands and complete the following data object types:568* Buffer, Package.569*570******************************************************************************/571572acpi_status573acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,574union acpi_parse_object *op,575union acpi_operand_object *obj_desc)576{577acpi_status status;578union acpi_operand_object *arg_desc;579u32 length;580581ACPI_FUNCTION_TRACE(ds_eval_data_object_operands);582583/* The first operand (for all of these data objects) is the length */584585/*586* Set proper index into operand stack for acpi_ds_obj_stack_push587* invoked inside acpi_ds_create_operand.588*/589walk_state->operand_index = walk_state->num_operands;590591status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);592if (ACPI_FAILURE(status)) {593return_ACPI_STATUS(status);594}595596status = acpi_ex_resolve_operands(walk_state->opcode,597&(walk_state->598operands[walk_state->num_operands -5991]), walk_state);600if (ACPI_FAILURE(status)) {601return_ACPI_STATUS(status);602}603604/* Extract length operand */605606arg_desc = walk_state->operands[walk_state->num_operands - 1];607length = (u32) arg_desc->integer.value;608609/* Cleanup for length operand */610611status = acpi_ds_obj_stack_pop(1, walk_state);612if (ACPI_FAILURE(status)) {613return_ACPI_STATUS(status);614}615616acpi_ut_remove_reference(arg_desc);617618/*619* Create the actual data object620*/621switch (op->common.aml_opcode) {622case AML_BUFFER_OP:623624status =625acpi_ds_build_internal_buffer_obj(walk_state, op, length,626&obj_desc);627break;628629case AML_PACKAGE_OP:630case AML_VAR_PACKAGE_OP:631632status =633acpi_ds_build_internal_package_obj(walk_state, op, length,634&obj_desc);635break;636637default:638return_ACPI_STATUS(AE_AML_BAD_OPCODE);639}640641if (ACPI_SUCCESS(status)) {642/*643* Return the object in the walk_state, unless the parent is a package -644* in this case, the return object will be stored in the parse tree645* for the package.646*/647if ((!op->common.parent) ||648((op->common.parent->common.aml_opcode != AML_PACKAGE_OP) &&649(op->common.parent->common.aml_opcode !=650AML_VAR_PACKAGE_OP)651&& (op->common.parent->common.aml_opcode != AML_NAME_OP))) {652walk_state->result_obj = obj_desc;653}654}655656return_ACPI_STATUS(status);657}658659/*******************************************************************************660*661* FUNCTION: acpi_ds_eval_bank_field_operands662*663* PARAMETERS: walk_state - Current walk664* Op - A valid bank_field Op object665*666* RETURN: Status667*668* DESCRIPTION: Get bank_field bank_value669* Called from acpi_ds_exec_end_op during bank_field parse tree walk670*671******************************************************************************/672673acpi_status674acpi_ds_eval_bank_field_operands(struct acpi_walk_state *walk_state,675union acpi_parse_object *op)676{677acpi_status status;678union acpi_operand_object *obj_desc;679union acpi_operand_object *operand_desc;680struct acpi_namespace_node *node;681union acpi_parse_object *next_op;682union acpi_parse_object *arg;683684ACPI_FUNCTION_TRACE_PTR(ds_eval_bank_field_operands, op);685686/*687* This is where we evaluate the bank_value field of the688* bank_field declaration689*/690691/* next_op points to the op that holds the Region */692693next_op = op->common.value.arg;694695/* next_op points to the op that holds the Bank Register */696697next_op = next_op->common.next;698699/* next_op points to the op that holds the Bank Value */700701next_op = next_op->common.next;702703/*704* Set proper index into operand stack for acpi_ds_obj_stack_push705* invoked inside acpi_ds_create_operand.706*707* We use walk_state->Operands[0] to store the evaluated bank_value708*/709walk_state->operand_index = 0;710711status = acpi_ds_create_operand(walk_state, next_op, 0);712if (ACPI_FAILURE(status)) {713return_ACPI_STATUS(status);714}715716status = acpi_ex_resolve_to_value(&walk_state->operands[0], walk_state);717if (ACPI_FAILURE(status)) {718return_ACPI_STATUS(status);719}720721ACPI_DUMP_OPERANDS(ACPI_WALK_OPERANDS,722acpi_ps_get_opcode_name(op->common.aml_opcode), 1);723/*724* Get the bank_value operand and save it725* (at Top of stack)726*/727operand_desc = walk_state->operands[0];728729/* Arg points to the start Bank Field */730731arg = acpi_ps_get_arg(op, 4);732while (arg) {733734/* Ignore OFFSET and ACCESSAS terms here */735736if (arg->common.aml_opcode == AML_INT_NAMEDFIELD_OP) {737node = arg->common.node;738739obj_desc = acpi_ns_get_attached_object(node);740if (!obj_desc) {741return_ACPI_STATUS(AE_NOT_EXIST);742}743744obj_desc->bank_field.value =745(u32) operand_desc->integer.value;746}747748/* Move to next field in the list */749750arg = arg->common.next;751}752753acpi_ut_remove_reference(operand_desc);754return_ACPI_STATUS(status);755}756757758