/******************************************************************************1*2* Module Name: dswload - Dispatcher first pass namespace load callbacks3*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"5051#ifdef ACPI_ASL_COMPILER52#include <acpi/acdisasm.h>53#endif5455#define _COMPONENT ACPI_DISPATCHER56ACPI_MODULE_NAME("dswload")5758/*******************************************************************************59*60* FUNCTION: acpi_ds_init_callbacks61*62* PARAMETERS: walk_state - Current state of the parse tree walk63* pass_number - 1, 2, or 364*65* RETURN: Status66*67* DESCRIPTION: Init walk state callbacks68*69******************************************************************************/70acpi_status71acpi_ds_init_callbacks(struct acpi_walk_state *walk_state, u32 pass_number)72{7374switch (pass_number) {75case 1:76walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |77ACPI_PARSE_DELETE_TREE;78walk_state->descending_callback = acpi_ds_load1_begin_op;79walk_state->ascending_callback = acpi_ds_load1_end_op;80break;8182case 2:83walk_state->parse_flags = ACPI_PARSE_LOAD_PASS1 |84ACPI_PARSE_DELETE_TREE;85walk_state->descending_callback = acpi_ds_load2_begin_op;86walk_state->ascending_callback = acpi_ds_load2_end_op;87break;8889case 3:90#ifndef ACPI_NO_METHOD_EXECUTION91walk_state->parse_flags |= ACPI_PARSE_EXECUTE |92ACPI_PARSE_DELETE_TREE;93walk_state->descending_callback = acpi_ds_exec_begin_op;94walk_state->ascending_callback = acpi_ds_exec_end_op;95#endif96break;9798default:99return (AE_BAD_PARAMETER);100}101102return (AE_OK);103}104105/*******************************************************************************106*107* FUNCTION: acpi_ds_load1_begin_op108*109* PARAMETERS: walk_state - Current state of the parse tree walk110* out_op - Where to return op if a new one is created111*112* RETURN: Status113*114* DESCRIPTION: Descending callback used during the loading of ACPI tables.115*116******************************************************************************/117118acpi_status119acpi_ds_load1_begin_op(struct acpi_walk_state * walk_state,120union acpi_parse_object ** out_op)121{122union acpi_parse_object *op;123struct acpi_namespace_node *node;124acpi_status status;125acpi_object_type object_type;126char *path;127u32 flags;128129ACPI_FUNCTION_TRACE(ds_load1_begin_op);130131op = walk_state->op;132ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,133walk_state));134135/* We are only interested in opcodes that have an associated name */136137if (op) {138if (!(walk_state->op_info->flags & AML_NAMED)) {139*out_op = op;140return_ACPI_STATUS(AE_OK);141}142143/* Check if this object has already been installed in the namespace */144145if (op->common.node) {146*out_op = op;147return_ACPI_STATUS(AE_OK);148}149}150151path = acpi_ps_get_next_namestring(&walk_state->parser_state);152153/* Map the raw opcode into an internal object type */154155object_type = walk_state->op_info->object_type;156157ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,158"State=%p Op=%p [%s]\n", walk_state, op,159acpi_ut_get_type_name(object_type)));160161switch (walk_state->opcode) {162case AML_SCOPE_OP:163164/*165* The target name of the Scope() operator must exist at this point so166* that we can actually open the scope to enter new names underneath it.167* Allow search-to-root for single namesegs.168*/169status =170acpi_ns_lookup(walk_state->scope_info, path, object_type,171ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT,172walk_state, &(node));173#ifdef ACPI_ASL_COMPILER174if (status == AE_NOT_FOUND) {175/*176* Table disassembly:177* Target of Scope() not found. Generate an External for it, and178* insert the name into the namespace.179*/180acpi_dm_add_to_external_list(path, ACPI_TYPE_DEVICE, 0);181status =182acpi_ns_lookup(walk_state->scope_info, path,183object_type, ACPI_IMODE_LOAD_PASS1,184ACPI_NS_SEARCH_PARENT, walk_state,185&node);186}187#endif188if (ACPI_FAILURE(status)) {189ACPI_ERROR_NAMESPACE(path, status);190return_ACPI_STATUS(status);191}192193/*194* Check to make sure that the target is195* one of the opcodes that actually opens a scope196*/197switch (node->type) {198case ACPI_TYPE_ANY:199case ACPI_TYPE_LOCAL_SCOPE: /* Scope */200case ACPI_TYPE_DEVICE:201case ACPI_TYPE_POWER:202case ACPI_TYPE_PROCESSOR:203case ACPI_TYPE_THERMAL:204205/* These are acceptable types */206break;207208case ACPI_TYPE_INTEGER:209case ACPI_TYPE_STRING:210case ACPI_TYPE_BUFFER:211212/*213* These types we will allow, but we will change the type.214* This enables some existing code of the form:215*216* Name (DEB, 0)217* Scope (DEB) { ... }218*219* Note: silently change the type here. On the second pass,220* we will report a warning221*/222ACPI_DEBUG_PRINT((ACPI_DB_INFO,223"Type override - [%4.4s] had invalid type (%s) "224"for Scope operator, changed to type ANY\n",225acpi_ut_get_node_name(node),226acpi_ut_get_type_name(node->type)));227228node->type = ACPI_TYPE_ANY;229walk_state->scope_info->common.value = ACPI_TYPE_ANY;230break;231232default:233234/* All other types are an error */235236ACPI_ERROR((AE_INFO,237"Invalid type (%s) for target of "238"Scope operator [%4.4s] (Cannot override)",239acpi_ut_get_type_name(node->type),240acpi_ut_get_node_name(node)));241242return_ACPI_STATUS(AE_AML_OPERAND_TYPE);243}244break;245246default:247/*248* For all other named opcodes, we will enter the name into249* the namespace.250*251* Setup the search flags.252* Since we are entering a name into the namespace, we do not want to253* enable the search-to-root upsearch.254*255* There are only two conditions where it is acceptable that the name256* already exists:257* 1) the Scope() operator can reopen a scoping object that was258* previously defined (Scope, Method, Device, etc.)259* 2) Whenever we are parsing a deferred opcode (op_region, Buffer,260* buffer_field, or Package), the name of the object is already261* in the namespace.262*/263if (walk_state->deferred_node) {264265/* This name is already in the namespace, get the node */266267node = walk_state->deferred_node;268status = AE_OK;269break;270}271272/*273* If we are executing a method, do not create any namespace objects274* during the load phase, only during execution.275*/276if (walk_state->method_node) {277node = NULL;278status = AE_OK;279break;280}281282flags = ACPI_NS_NO_UPSEARCH;283if ((walk_state->opcode != AML_SCOPE_OP) &&284(!(walk_state->parse_flags & ACPI_PARSE_DEFERRED_OP))) {285flags |= ACPI_NS_ERROR_IF_FOUND;286ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,287"[%s] Cannot already exist\n",288acpi_ut_get_type_name(object_type)));289} else {290ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,291"[%s] Both Find or Create allowed\n",292acpi_ut_get_type_name(object_type)));293}294295/*296* Enter the named type into the internal namespace. We enter the name297* as we go downward in the parse tree. Any necessary subobjects that298* involve arguments to the opcode must be created as we go back up the299* parse tree later.300*/301status =302acpi_ns_lookup(walk_state->scope_info, path, object_type,303ACPI_IMODE_LOAD_PASS1, flags, walk_state,304&node);305if (ACPI_FAILURE(status)) {306if (status == AE_ALREADY_EXISTS) {307308/* The name already exists in this scope */309310if (node->flags & ANOBJ_IS_EXTERNAL) {311/*312* Allow one create on an object or segment that was313* previously declared External314*/315node->flags &= ~ANOBJ_IS_EXTERNAL;316node->type = (u8) object_type;317318/* Just retyped a node, probably will need to open a scope */319320if (acpi_ns_opens_scope(object_type)) {321status =322acpi_ds_scope_stack_push323(node, object_type,324walk_state);325if (ACPI_FAILURE(status)) {326return_ACPI_STATUS327(status);328}329}330331status = AE_OK;332}333}334335if (ACPI_FAILURE(status)) {336ACPI_ERROR_NAMESPACE(path, status);337return_ACPI_STATUS(status);338}339}340break;341}342343/* Common exit */344345if (!op) {346347/* Create a new op */348349op = acpi_ps_alloc_op(walk_state->opcode);350if (!op) {351return_ACPI_STATUS(AE_NO_MEMORY);352}353}354355/* Initialize the op */356357#if (defined (ACPI_NO_METHOD_EXECUTION) || defined (ACPI_CONSTANT_EVAL_ONLY))358op->named.path = ACPI_CAST_PTR(u8, path);359#endif360361if (node) {362/*363* Put the Node in the "op" object that the parser uses, so we364* can get it again quickly when this scope is closed365*/366op->common.node = node;367op->named.name = node->name.integer;368}369370acpi_ps_append_arg(acpi_ps_get_parent_scope(&walk_state->parser_state),371op);372*out_op = op;373return_ACPI_STATUS(status);374}375376/*******************************************************************************377*378* FUNCTION: acpi_ds_load1_end_op379*380* PARAMETERS: walk_state - Current state of the parse tree walk381*382* RETURN: Status383*384* DESCRIPTION: Ascending callback used during the loading of the namespace,385* both control methods and everything else.386*387******************************************************************************/388389acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state)390{391union acpi_parse_object *op;392acpi_object_type object_type;393acpi_status status = AE_OK;394395ACPI_FUNCTION_TRACE(ds_load1_end_op);396397op = walk_state->op;398ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op,399walk_state));400401/* We are only interested in opcodes that have an associated name */402403if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) {404return_ACPI_STATUS(AE_OK);405}406407/* Get the object type to determine if we should pop the scope */408409object_type = walk_state->op_info->object_type;410411#ifndef ACPI_NO_METHOD_EXECUTION412if (walk_state->op_info->flags & AML_FIELD) {413/*414* If we are executing a method, do not create any namespace objects415* during the load phase, only during execution.416*/417if (!walk_state->method_node) {418if (walk_state->opcode == AML_FIELD_OP ||419walk_state->opcode == AML_BANK_FIELD_OP ||420walk_state->opcode == AML_INDEX_FIELD_OP) {421status =422acpi_ds_init_field_objects(op, walk_state);423}424}425return_ACPI_STATUS(status);426}427428/*429* If we are executing a method, do not create any namespace objects430* during the load phase, only during execution.431*/432if (!walk_state->method_node) {433if (op->common.aml_opcode == AML_REGION_OP) {434status =435acpi_ex_create_region(op->named.data,436op->named.length,437(acpi_adr_space_type) ((op->438common.439value.440arg)->441common.442value.443integer),444walk_state);445if (ACPI_FAILURE(status)) {446return_ACPI_STATUS(status);447}448} else if (op->common.aml_opcode == AML_DATA_REGION_OP) {449status =450acpi_ex_create_region(op->named.data,451op->named.length,452ACPI_ADR_SPACE_DATA_TABLE,453walk_state);454if (ACPI_FAILURE(status)) {455return_ACPI_STATUS(status);456}457}458}459#endif460461if (op->common.aml_opcode == AML_NAME_OP) {462463/* For Name opcode, get the object type from the argument */464465if (op->common.value.arg) {466object_type = (acpi_ps_get_opcode_info((op->common.467value.arg)->468common.469aml_opcode))->470object_type;471472/* Set node type if we have a namespace node */473474if (op->common.node) {475op->common.node->type = (u8) object_type;476}477}478}479480/*481* If we are executing a method, do not create any namespace objects482* during the load phase, only during execution.483*/484if (!walk_state->method_node) {485if (op->common.aml_opcode == AML_METHOD_OP) {486/*487* method_op pkg_length name_string method_flags term_list488*489* Note: We must create the method node/object pair as soon as we490* see the method declaration. This allows later pass1 parsing491* of invocations of the method (need to know the number of492* arguments.)493*/494ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,495"LOADING-Method: State=%p Op=%p NamedObj=%p\n",496walk_state, op, op->named.node));497498if (!acpi_ns_get_attached_object(op->named.node)) {499walk_state->operands[0] =500ACPI_CAST_PTR(void, op->named.node);501walk_state->num_operands = 1;502503status =504acpi_ds_create_operands(walk_state,505op->common.value.506arg);507if (ACPI_SUCCESS(status)) {508status =509acpi_ex_create_method(op->named.510data,511op->named.512length,513walk_state);514}515516walk_state->operands[0] = NULL;517walk_state->num_operands = 0;518519if (ACPI_FAILURE(status)) {520return_ACPI_STATUS(status);521}522}523}524}525526/* Pop the scope stack (only if loading a table) */527528if (!walk_state->method_node && acpi_ns_opens_scope(object_type)) {529ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,530"(%s): Popping scope for Op %p\n",531acpi_ut_get_type_name(object_type), op));532533status = acpi_ds_scope_stack_pop(walk_state);534}535536return_ACPI_STATUS(status);537}538539540