1*95b482a8SLen Brown /****************************************************************************** 2*95b482a8SLen Brown * 3*95b482a8SLen Brown * Module Name: psloop - Main AML parse loop 4*95b482a8SLen Brown * 5*95b482a8SLen Brown *****************************************************************************/ 6*95b482a8SLen Brown 7*95b482a8SLen Brown /* 8*95b482a8SLen Brown * Copyright (C) 2000 - 2008, Intel Corp. 9*95b482a8SLen Brown * All rights reserved. 10*95b482a8SLen Brown * 11*95b482a8SLen Brown * Redistribution and use in source and binary forms, with or without 12*95b482a8SLen Brown * modification, are permitted provided that the following conditions 13*95b482a8SLen Brown * are met: 14*95b482a8SLen Brown * 1. Redistributions of source code must retain the above copyright 15*95b482a8SLen Brown * notice, this list of conditions, and the following disclaimer, 16*95b482a8SLen Brown * without modification. 17*95b482a8SLen Brown * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18*95b482a8SLen Brown * substantially similar to the "NO WARRANTY" disclaimer below 19*95b482a8SLen Brown * ("Disclaimer") and any redistribution must be conditioned upon 20*95b482a8SLen Brown * including a substantially similar Disclaimer requirement for further 21*95b482a8SLen Brown * binary redistribution. 22*95b482a8SLen Brown * 3. Neither the names of the above-listed copyright holders nor the names 23*95b482a8SLen Brown * of any contributors may be used to endorse or promote products derived 24*95b482a8SLen Brown * from this software without specific prior written permission. 25*95b482a8SLen Brown * 26*95b482a8SLen Brown * Alternatively, this software may be distributed under the terms of the 27*95b482a8SLen Brown * GNU General Public License ("GPL") version 2 as published by the Free 28*95b482a8SLen Brown * Software Foundation. 29*95b482a8SLen Brown * 30*95b482a8SLen Brown * NO WARRANTY 31*95b482a8SLen Brown * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32*95b482a8SLen Brown * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33*95b482a8SLen Brown * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34*95b482a8SLen Brown * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35*95b482a8SLen Brown * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36*95b482a8SLen Brown * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37*95b482a8SLen Brown * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38*95b482a8SLen Brown * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39*95b482a8SLen Brown * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40*95b482a8SLen Brown * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41*95b482a8SLen Brown * POSSIBILITY OF SUCH DAMAGES. 42*95b482a8SLen Brown */ 43*95b482a8SLen Brown 44*95b482a8SLen Brown /* 45*95b482a8SLen Brown * Parse the AML and build an operation tree as most interpreters, (such as 46*95b482a8SLen Brown * Perl) do. Parsing is done by hand rather than with a YACC generated parser 47*95b482a8SLen Brown * to tightly constrain stack and dynamic memory usage. Parsing is kept 48*95b482a8SLen Brown * flexible and the code fairly compact by parsing based on a list of AML 49*95b482a8SLen Brown * opcode templates in aml_op_info[]. 50*95b482a8SLen Brown */ 51*95b482a8SLen Brown 52*95b482a8SLen Brown #include <acpi/acpi.h> 53*95b482a8SLen Brown #include <acpi/accommon.h> 54*95b482a8SLen Brown #include <acpi/acparser.h> 55*95b482a8SLen Brown #include <acpi/acdispat.h> 56*95b482a8SLen Brown #include <acpi/amlcode.h> 57*95b482a8SLen Brown 58*95b482a8SLen Brown #define _COMPONENT ACPI_PARSER 59*95b482a8SLen Brown ACPI_MODULE_NAME("psloop") 60*95b482a8SLen Brown 61*95b482a8SLen Brown static u32 acpi_gbl_depth = 0; 62*95b482a8SLen Brown 63*95b482a8SLen Brown /* Local prototypes */ 64*95b482a8SLen Brown 65*95b482a8SLen Brown static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state); 66*95b482a8SLen Brown 67*95b482a8SLen Brown static acpi_status 68*95b482a8SLen Brown acpi_ps_build_named_op(struct acpi_walk_state *walk_state, 69*95b482a8SLen Brown u8 * aml_op_start, 70*95b482a8SLen Brown union acpi_parse_object *unnamed_op, 71*95b482a8SLen Brown union acpi_parse_object **op); 72*95b482a8SLen Brown 73*95b482a8SLen Brown static acpi_status 74*95b482a8SLen Brown acpi_ps_create_op(struct acpi_walk_state *walk_state, 75*95b482a8SLen Brown u8 * aml_op_start, union acpi_parse_object **new_op); 76*95b482a8SLen Brown 77*95b482a8SLen Brown static acpi_status 78*95b482a8SLen Brown acpi_ps_get_arguments(struct acpi_walk_state *walk_state, 79*95b482a8SLen Brown u8 * aml_op_start, union acpi_parse_object *op); 80*95b482a8SLen Brown 81*95b482a8SLen Brown static acpi_status 82*95b482a8SLen Brown acpi_ps_complete_op(struct acpi_walk_state *walk_state, 83*95b482a8SLen Brown union acpi_parse_object **op, acpi_status status); 84*95b482a8SLen Brown 85*95b482a8SLen Brown static acpi_status 86*95b482a8SLen Brown acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, 87*95b482a8SLen Brown union acpi_parse_object *op, acpi_status status); 88*95b482a8SLen Brown 89*95b482a8SLen Brown /******************************************************************************* 90*95b482a8SLen Brown * 91*95b482a8SLen Brown * FUNCTION: acpi_ps_get_aml_opcode 92*95b482a8SLen Brown * 93*95b482a8SLen Brown * PARAMETERS: walk_state - Current state 94*95b482a8SLen Brown * 95*95b482a8SLen Brown * RETURN: Status 96*95b482a8SLen Brown * 97*95b482a8SLen Brown * DESCRIPTION: Extract the next AML opcode from the input stream. 98*95b482a8SLen Brown * 99*95b482a8SLen Brown ******************************************************************************/ 100*95b482a8SLen Brown 101*95b482a8SLen Brown static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) 102*95b482a8SLen Brown { 103*95b482a8SLen Brown 104*95b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); 105*95b482a8SLen Brown 106*95b482a8SLen Brown walk_state->aml_offset = 107*95b482a8SLen Brown (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, 108*95b482a8SLen Brown walk_state->parser_state.aml_start); 109*95b482a8SLen Brown walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); 110*95b482a8SLen Brown 111*95b482a8SLen Brown /* 112*95b482a8SLen Brown * First cut to determine what we have found: 113*95b482a8SLen Brown * 1) A valid AML opcode 114*95b482a8SLen Brown * 2) A name string 115*95b482a8SLen Brown * 3) An unknown/invalid opcode 116*95b482a8SLen Brown */ 117*95b482a8SLen Brown walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); 118*95b482a8SLen Brown 119*95b482a8SLen Brown switch (walk_state->op_info->class) { 120*95b482a8SLen Brown case AML_CLASS_ASCII: 121*95b482a8SLen Brown case AML_CLASS_PREFIX: 122*95b482a8SLen Brown /* 123*95b482a8SLen Brown * Starts with a valid prefix or ASCII char, this is a name 124*95b482a8SLen Brown * string. Convert the bare name string to a namepath. 125*95b482a8SLen Brown */ 126*95b482a8SLen Brown walk_state->opcode = AML_INT_NAMEPATH_OP; 127*95b482a8SLen Brown walk_state->arg_types = ARGP_NAMESTRING; 128*95b482a8SLen Brown break; 129*95b482a8SLen Brown 130*95b482a8SLen Brown case AML_CLASS_UNKNOWN: 131*95b482a8SLen Brown 132*95b482a8SLen Brown /* The opcode is unrecognized. Just skip unknown opcodes */ 133*95b482a8SLen Brown 134*95b482a8SLen Brown ACPI_ERROR((AE_INFO, 135*95b482a8SLen Brown "Found unknown opcode %X at AML address %p offset %X, ignoring", 136*95b482a8SLen Brown walk_state->opcode, walk_state->parser_state.aml, 137*95b482a8SLen Brown walk_state->aml_offset)); 138*95b482a8SLen Brown 139*95b482a8SLen Brown ACPI_DUMP_BUFFER(walk_state->parser_state.aml, 128); 140*95b482a8SLen Brown 141*95b482a8SLen Brown /* Assume one-byte bad opcode */ 142*95b482a8SLen Brown 143*95b482a8SLen Brown walk_state->parser_state.aml++; 144*95b482a8SLen Brown return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); 145*95b482a8SLen Brown 146*95b482a8SLen Brown default: 147*95b482a8SLen Brown 148*95b482a8SLen Brown /* Found opcode info, this is a normal opcode */ 149*95b482a8SLen Brown 150*95b482a8SLen Brown walk_state->parser_state.aml += 151*95b482a8SLen Brown acpi_ps_get_opcode_size(walk_state->opcode); 152*95b482a8SLen Brown walk_state->arg_types = walk_state->op_info->parse_args; 153*95b482a8SLen Brown break; 154*95b482a8SLen Brown } 155*95b482a8SLen Brown 156*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 157*95b482a8SLen Brown } 158*95b482a8SLen Brown 159*95b482a8SLen Brown /******************************************************************************* 160*95b482a8SLen Brown * 161*95b482a8SLen Brown * FUNCTION: acpi_ps_build_named_op 162*95b482a8SLen Brown * 163*95b482a8SLen Brown * PARAMETERS: walk_state - Current state 164*95b482a8SLen Brown * aml_op_start - Begin of named Op in AML 165*95b482a8SLen Brown * unnamed_op - Early Op (not a named Op) 166*95b482a8SLen Brown * Op - Returned Op 167*95b482a8SLen Brown * 168*95b482a8SLen Brown * RETURN: Status 169*95b482a8SLen Brown * 170*95b482a8SLen Brown * DESCRIPTION: Parse a named Op 171*95b482a8SLen Brown * 172*95b482a8SLen Brown ******************************************************************************/ 173*95b482a8SLen Brown 174*95b482a8SLen Brown static acpi_status 175*95b482a8SLen Brown acpi_ps_build_named_op(struct acpi_walk_state *walk_state, 176*95b482a8SLen Brown u8 * aml_op_start, 177*95b482a8SLen Brown union acpi_parse_object *unnamed_op, 178*95b482a8SLen Brown union acpi_parse_object **op) 179*95b482a8SLen Brown { 180*95b482a8SLen Brown acpi_status status = AE_OK; 181*95b482a8SLen Brown union acpi_parse_object *arg = NULL; 182*95b482a8SLen Brown 183*95b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ps_build_named_op, walk_state); 184*95b482a8SLen Brown 185*95b482a8SLen Brown unnamed_op->common.value.arg = NULL; 186*95b482a8SLen Brown unnamed_op->common.arg_list_length = 0; 187*95b482a8SLen Brown unnamed_op->common.aml_opcode = walk_state->opcode; 188*95b482a8SLen Brown 189*95b482a8SLen Brown /* 190*95b482a8SLen Brown * Get and append arguments until we find the node that contains 191*95b482a8SLen Brown * the name (the type ARGP_NAME). 192*95b482a8SLen Brown */ 193*95b482a8SLen Brown while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) && 194*95b482a8SLen Brown (GET_CURRENT_ARG_TYPE(walk_state->arg_types) != ARGP_NAME)) { 195*95b482a8SLen Brown status = 196*95b482a8SLen Brown acpi_ps_get_next_arg(walk_state, 197*95b482a8SLen Brown &(walk_state->parser_state), 198*95b482a8SLen Brown GET_CURRENT_ARG_TYPE(walk_state-> 199*95b482a8SLen Brown arg_types), &arg); 200*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 201*95b482a8SLen Brown return_ACPI_STATUS(status); 202*95b482a8SLen Brown } 203*95b482a8SLen Brown 204*95b482a8SLen Brown acpi_ps_append_arg(unnamed_op, arg); 205*95b482a8SLen Brown INCREMENT_ARG_LIST(walk_state->arg_types); 206*95b482a8SLen Brown } 207*95b482a8SLen Brown 208*95b482a8SLen Brown /* 209*95b482a8SLen Brown * Make sure that we found a NAME and didn't run out of arguments 210*95b482a8SLen Brown */ 211*95b482a8SLen Brown if (!GET_CURRENT_ARG_TYPE(walk_state->arg_types)) { 212*95b482a8SLen Brown return_ACPI_STATUS(AE_AML_NO_OPERAND); 213*95b482a8SLen Brown } 214*95b482a8SLen Brown 215*95b482a8SLen Brown /* We know that this arg is a name, move to next arg */ 216*95b482a8SLen Brown 217*95b482a8SLen Brown INCREMENT_ARG_LIST(walk_state->arg_types); 218*95b482a8SLen Brown 219*95b482a8SLen Brown /* 220*95b482a8SLen Brown * Find the object. This will either insert the object into 221*95b482a8SLen Brown * the namespace or simply look it up 222*95b482a8SLen Brown */ 223*95b482a8SLen Brown walk_state->op = NULL; 224*95b482a8SLen Brown 225*95b482a8SLen Brown status = walk_state->descending_callback(walk_state, op); 226*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 227*95b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); 228*95b482a8SLen Brown return_ACPI_STATUS(status); 229*95b482a8SLen Brown } 230*95b482a8SLen Brown 231*95b482a8SLen Brown if (!*op) { 232*95b482a8SLen Brown return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); 233*95b482a8SLen Brown } 234*95b482a8SLen Brown 235*95b482a8SLen Brown status = acpi_ps_next_parse_state(walk_state, *op, status); 236*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 237*95b482a8SLen Brown if (status == AE_CTRL_PENDING) { 238*95b482a8SLen Brown return_ACPI_STATUS(AE_CTRL_PARSE_PENDING); 239*95b482a8SLen Brown } 240*95b482a8SLen Brown return_ACPI_STATUS(status); 241*95b482a8SLen Brown } 242*95b482a8SLen Brown 243*95b482a8SLen Brown acpi_ps_append_arg(*op, unnamed_op->common.value.arg); 244*95b482a8SLen Brown acpi_gbl_depth++; 245*95b482a8SLen Brown 246*95b482a8SLen Brown if ((*op)->common.aml_opcode == AML_REGION_OP || 247*95b482a8SLen Brown (*op)->common.aml_opcode == AML_DATA_REGION_OP) { 248*95b482a8SLen Brown /* 249*95b482a8SLen Brown * Defer final parsing of an operation_region body, because we don't 250*95b482a8SLen Brown * have enough info in the first pass to parse it correctly (i.e., 251*95b482a8SLen Brown * there may be method calls within the term_arg elements of the body.) 252*95b482a8SLen Brown * 253*95b482a8SLen Brown * However, we must continue parsing because the opregion is not a 254*95b482a8SLen Brown * standalone package -- we don't know where the end is at this point. 255*95b482a8SLen Brown * 256*95b482a8SLen Brown * (Length is unknown until parse of the body complete) 257*95b482a8SLen Brown */ 258*95b482a8SLen Brown (*op)->named.data = aml_op_start; 259*95b482a8SLen Brown (*op)->named.length = 0; 260*95b482a8SLen Brown } 261*95b482a8SLen Brown 262*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 263*95b482a8SLen Brown } 264*95b482a8SLen Brown 265*95b482a8SLen Brown /******************************************************************************* 266*95b482a8SLen Brown * 267*95b482a8SLen Brown * FUNCTION: acpi_ps_create_op 268*95b482a8SLen Brown * 269*95b482a8SLen Brown * PARAMETERS: walk_state - Current state 270*95b482a8SLen Brown * aml_op_start - Op start in AML 271*95b482a8SLen Brown * new_op - Returned Op 272*95b482a8SLen Brown * 273*95b482a8SLen Brown * RETURN: Status 274*95b482a8SLen Brown * 275*95b482a8SLen Brown * DESCRIPTION: Get Op from AML 276*95b482a8SLen Brown * 277*95b482a8SLen Brown ******************************************************************************/ 278*95b482a8SLen Brown 279*95b482a8SLen Brown static acpi_status 280*95b482a8SLen Brown acpi_ps_create_op(struct acpi_walk_state *walk_state, 281*95b482a8SLen Brown u8 * aml_op_start, union acpi_parse_object **new_op) 282*95b482a8SLen Brown { 283*95b482a8SLen Brown acpi_status status = AE_OK; 284*95b482a8SLen Brown union acpi_parse_object *op; 285*95b482a8SLen Brown union acpi_parse_object *named_op = NULL; 286*95b482a8SLen Brown union acpi_parse_object *parent_scope; 287*95b482a8SLen Brown u8 argument_count; 288*95b482a8SLen Brown const struct acpi_opcode_info *op_info; 289*95b482a8SLen Brown 290*95b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); 291*95b482a8SLen Brown 292*95b482a8SLen Brown status = acpi_ps_get_aml_opcode(walk_state); 293*95b482a8SLen Brown if (status == AE_CTRL_PARSE_CONTINUE) { 294*95b482a8SLen Brown return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); 295*95b482a8SLen Brown } 296*95b482a8SLen Brown 297*95b482a8SLen Brown /* Create Op structure and append to parent's argument list */ 298*95b482a8SLen Brown 299*95b482a8SLen Brown walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); 300*95b482a8SLen Brown op = acpi_ps_alloc_op(walk_state->opcode); 301*95b482a8SLen Brown if (!op) { 302*95b482a8SLen Brown return_ACPI_STATUS(AE_NO_MEMORY); 303*95b482a8SLen Brown } 304*95b482a8SLen Brown 305*95b482a8SLen Brown if (walk_state->op_info->flags & AML_NAMED) { 306*95b482a8SLen Brown status = 307*95b482a8SLen Brown acpi_ps_build_named_op(walk_state, aml_op_start, op, 308*95b482a8SLen Brown &named_op); 309*95b482a8SLen Brown acpi_ps_free_op(op); 310*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 311*95b482a8SLen Brown return_ACPI_STATUS(status); 312*95b482a8SLen Brown } 313*95b482a8SLen Brown 314*95b482a8SLen Brown *new_op = named_op; 315*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 316*95b482a8SLen Brown } 317*95b482a8SLen Brown 318*95b482a8SLen Brown /* Not a named opcode, just allocate Op and append to parent */ 319*95b482a8SLen Brown 320*95b482a8SLen Brown if (walk_state->op_info->flags & AML_CREATE) { 321*95b482a8SLen Brown /* 322*95b482a8SLen Brown * Backup to beginning of create_xXXfield declaration 323*95b482a8SLen Brown * body_length is unknown until we parse the body 324*95b482a8SLen Brown */ 325*95b482a8SLen Brown op->named.data = aml_op_start; 326*95b482a8SLen Brown op->named.length = 0; 327*95b482a8SLen Brown } 328*95b482a8SLen Brown 329*95b482a8SLen Brown if (walk_state->opcode == AML_BANK_FIELD_OP) { 330*95b482a8SLen Brown /* 331*95b482a8SLen Brown * Backup to beginning of bank_field declaration 332*95b482a8SLen Brown * body_length is unknown until we parse the body 333*95b482a8SLen Brown */ 334*95b482a8SLen Brown op->named.data = aml_op_start; 335*95b482a8SLen Brown op->named.length = 0; 336*95b482a8SLen Brown } 337*95b482a8SLen Brown 338*95b482a8SLen Brown parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); 339*95b482a8SLen Brown acpi_ps_append_arg(parent_scope, op); 340*95b482a8SLen Brown 341*95b482a8SLen Brown if (parent_scope) { 342*95b482a8SLen Brown op_info = 343*95b482a8SLen Brown acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); 344*95b482a8SLen Brown if (op_info->flags & AML_HAS_TARGET) { 345*95b482a8SLen Brown argument_count = 346*95b482a8SLen Brown acpi_ps_get_argument_count(op_info->type); 347*95b482a8SLen Brown if (parent_scope->common.arg_list_length > 348*95b482a8SLen Brown argument_count) { 349*95b482a8SLen Brown op->common.flags |= ACPI_PARSEOP_TARGET; 350*95b482a8SLen Brown } 351*95b482a8SLen Brown } else if (parent_scope->common.aml_opcode == AML_INCREMENT_OP) { 352*95b482a8SLen Brown op->common.flags |= ACPI_PARSEOP_TARGET; 353*95b482a8SLen Brown } 354*95b482a8SLen Brown } 355*95b482a8SLen Brown 356*95b482a8SLen Brown if (walk_state->descending_callback != NULL) { 357*95b482a8SLen Brown /* 358*95b482a8SLen Brown * Find the object. This will either insert the object into 359*95b482a8SLen Brown * the namespace or simply look it up 360*95b482a8SLen Brown */ 361*95b482a8SLen Brown walk_state->op = *new_op = op; 362*95b482a8SLen Brown 363*95b482a8SLen Brown status = walk_state->descending_callback(walk_state, &op); 364*95b482a8SLen Brown status = acpi_ps_next_parse_state(walk_state, op, status); 365*95b482a8SLen Brown if (status == AE_CTRL_PENDING) { 366*95b482a8SLen Brown status = AE_CTRL_PARSE_PENDING; 367*95b482a8SLen Brown } 368*95b482a8SLen Brown } 369*95b482a8SLen Brown 370*95b482a8SLen Brown return_ACPI_STATUS(status); 371*95b482a8SLen Brown } 372*95b482a8SLen Brown 373*95b482a8SLen Brown /******************************************************************************* 374*95b482a8SLen Brown * 375*95b482a8SLen Brown * FUNCTION: acpi_ps_get_arguments 376*95b482a8SLen Brown * 377*95b482a8SLen Brown * PARAMETERS: walk_state - Current state 378*95b482a8SLen Brown * aml_op_start - Op start in AML 379*95b482a8SLen Brown * Op - Current Op 380*95b482a8SLen Brown * 381*95b482a8SLen Brown * RETURN: Status 382*95b482a8SLen Brown * 383*95b482a8SLen Brown * DESCRIPTION: Get arguments for passed Op. 384*95b482a8SLen Brown * 385*95b482a8SLen Brown ******************************************************************************/ 386*95b482a8SLen Brown 387*95b482a8SLen Brown static acpi_status 388*95b482a8SLen Brown acpi_ps_get_arguments(struct acpi_walk_state *walk_state, 389*95b482a8SLen Brown u8 * aml_op_start, union acpi_parse_object *op) 390*95b482a8SLen Brown { 391*95b482a8SLen Brown acpi_status status = AE_OK; 392*95b482a8SLen Brown union acpi_parse_object *arg = NULL; 393*95b482a8SLen Brown 394*95b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state); 395*95b482a8SLen Brown 396*95b482a8SLen Brown switch (op->common.aml_opcode) { 397*95b482a8SLen Brown case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ 398*95b482a8SLen Brown case AML_WORD_OP: /* AML_WORDDATA_ARG */ 399*95b482a8SLen Brown case AML_DWORD_OP: /* AML_DWORDATA_ARG */ 400*95b482a8SLen Brown case AML_QWORD_OP: /* AML_QWORDATA_ARG */ 401*95b482a8SLen Brown case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ 402*95b482a8SLen Brown 403*95b482a8SLen Brown /* Fill in constant or string argument directly */ 404*95b482a8SLen Brown 405*95b482a8SLen Brown acpi_ps_get_next_simple_arg(&(walk_state->parser_state), 406*95b482a8SLen Brown GET_CURRENT_ARG_TYPE(walk_state-> 407*95b482a8SLen Brown arg_types), 408*95b482a8SLen Brown op); 409*95b482a8SLen Brown break; 410*95b482a8SLen Brown 411*95b482a8SLen Brown case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ 412*95b482a8SLen Brown 413*95b482a8SLen Brown status = 414*95b482a8SLen Brown acpi_ps_get_next_namepath(walk_state, 415*95b482a8SLen Brown &(walk_state->parser_state), op, 416*95b482a8SLen Brown 1); 417*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 418*95b482a8SLen Brown return_ACPI_STATUS(status); 419*95b482a8SLen Brown } 420*95b482a8SLen Brown 421*95b482a8SLen Brown walk_state->arg_types = 0; 422*95b482a8SLen Brown break; 423*95b482a8SLen Brown 424*95b482a8SLen Brown default: 425*95b482a8SLen Brown /* 426*95b482a8SLen Brown * Op is not a constant or string, append each argument to the Op 427*95b482a8SLen Brown */ 428*95b482a8SLen Brown while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) 429*95b482a8SLen Brown && !walk_state->arg_count) { 430*95b482a8SLen Brown walk_state->aml_offset = 431*95b482a8SLen Brown (u32) ACPI_PTR_DIFF(walk_state->parser_state.aml, 432*95b482a8SLen Brown walk_state->parser_state. 433*95b482a8SLen Brown aml_start); 434*95b482a8SLen Brown 435*95b482a8SLen Brown status = 436*95b482a8SLen Brown acpi_ps_get_next_arg(walk_state, 437*95b482a8SLen Brown &(walk_state->parser_state), 438*95b482a8SLen Brown GET_CURRENT_ARG_TYPE 439*95b482a8SLen Brown (walk_state->arg_types), &arg); 440*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 441*95b482a8SLen Brown return_ACPI_STATUS(status); 442*95b482a8SLen Brown } 443*95b482a8SLen Brown 444*95b482a8SLen Brown if (arg) { 445*95b482a8SLen Brown arg->common.aml_offset = walk_state->aml_offset; 446*95b482a8SLen Brown acpi_ps_append_arg(op, arg); 447*95b482a8SLen Brown } 448*95b482a8SLen Brown 449*95b482a8SLen Brown INCREMENT_ARG_LIST(walk_state->arg_types); 450*95b482a8SLen Brown } 451*95b482a8SLen Brown 452*95b482a8SLen Brown /* Special processing for certain opcodes */ 453*95b482a8SLen Brown 454*95b482a8SLen Brown /* TBD (remove): Temporary mechanism to disable this code if needed */ 455*95b482a8SLen Brown 456*95b482a8SLen Brown #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE 457*95b482a8SLen Brown 458*95b482a8SLen Brown if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && 459*95b482a8SLen Brown ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { 460*95b482a8SLen Brown /* 461*95b482a8SLen Brown * We want to skip If/Else/While constructs during Pass1 because we 462*95b482a8SLen Brown * want to actually conditionally execute the code during Pass2. 463*95b482a8SLen Brown * 464*95b482a8SLen Brown * Except for disassembly, where we always want to walk the 465*95b482a8SLen Brown * If/Else/While packages 466*95b482a8SLen Brown */ 467*95b482a8SLen Brown switch (op->common.aml_opcode) { 468*95b482a8SLen Brown case AML_IF_OP: 469*95b482a8SLen Brown case AML_ELSE_OP: 470*95b482a8SLen Brown case AML_WHILE_OP: 471*95b482a8SLen Brown 472*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 473*95b482a8SLen Brown "Pass1: Skipping an If/Else/While body\n")); 474*95b482a8SLen Brown 475*95b482a8SLen Brown /* Skip body of if/else/while in pass 1 */ 476*95b482a8SLen Brown 477*95b482a8SLen Brown walk_state->parser_state.aml = 478*95b482a8SLen Brown walk_state->parser_state.pkg_end; 479*95b482a8SLen Brown walk_state->arg_count = 0; 480*95b482a8SLen Brown break; 481*95b482a8SLen Brown 482*95b482a8SLen Brown default: 483*95b482a8SLen Brown break; 484*95b482a8SLen Brown } 485*95b482a8SLen Brown } 486*95b482a8SLen Brown #endif 487*95b482a8SLen Brown 488*95b482a8SLen Brown switch (op->common.aml_opcode) { 489*95b482a8SLen Brown case AML_METHOD_OP: 490*95b482a8SLen Brown /* 491*95b482a8SLen Brown * Skip parsing of control method because we don't have enough 492*95b482a8SLen Brown * info in the first pass to parse it correctly. 493*95b482a8SLen Brown * 494*95b482a8SLen Brown * Save the length and address of the body 495*95b482a8SLen Brown */ 496*95b482a8SLen Brown op->named.data = walk_state->parser_state.aml; 497*95b482a8SLen Brown op->named.length = (u32) 498*95b482a8SLen Brown (walk_state->parser_state.pkg_end - 499*95b482a8SLen Brown walk_state->parser_state.aml); 500*95b482a8SLen Brown 501*95b482a8SLen Brown /* Skip body of method */ 502*95b482a8SLen Brown 503*95b482a8SLen Brown walk_state->parser_state.aml = 504*95b482a8SLen Brown walk_state->parser_state.pkg_end; 505*95b482a8SLen Brown walk_state->arg_count = 0; 506*95b482a8SLen Brown break; 507*95b482a8SLen Brown 508*95b482a8SLen Brown case AML_BUFFER_OP: 509*95b482a8SLen Brown case AML_PACKAGE_OP: 510*95b482a8SLen Brown case AML_VAR_PACKAGE_OP: 511*95b482a8SLen Brown 512*95b482a8SLen Brown if ((op->common.parent) && 513*95b482a8SLen Brown (op->common.parent->common.aml_opcode == 514*95b482a8SLen Brown AML_NAME_OP) 515*95b482a8SLen Brown && (walk_state->pass_number <= 516*95b482a8SLen Brown ACPI_IMODE_LOAD_PASS2)) { 517*95b482a8SLen Brown /* 518*95b482a8SLen Brown * Skip parsing of Buffers and Packages because we don't have 519*95b482a8SLen Brown * enough info in the first pass to parse them correctly. 520*95b482a8SLen Brown */ 521*95b482a8SLen Brown op->named.data = aml_op_start; 522*95b482a8SLen Brown op->named.length = (u32) 523*95b482a8SLen Brown (walk_state->parser_state.pkg_end - 524*95b482a8SLen Brown aml_op_start); 525*95b482a8SLen Brown 526*95b482a8SLen Brown /* Skip body */ 527*95b482a8SLen Brown 528*95b482a8SLen Brown walk_state->parser_state.aml = 529*95b482a8SLen Brown walk_state->parser_state.pkg_end; 530*95b482a8SLen Brown walk_state->arg_count = 0; 531*95b482a8SLen Brown } 532*95b482a8SLen Brown break; 533*95b482a8SLen Brown 534*95b482a8SLen Brown case AML_WHILE_OP: 535*95b482a8SLen Brown 536*95b482a8SLen Brown if (walk_state->control_state) { 537*95b482a8SLen Brown walk_state->control_state->control.package_end = 538*95b482a8SLen Brown walk_state->parser_state.pkg_end; 539*95b482a8SLen Brown } 540*95b482a8SLen Brown break; 541*95b482a8SLen Brown 542*95b482a8SLen Brown default: 543*95b482a8SLen Brown 544*95b482a8SLen Brown /* No action for all other opcodes */ 545*95b482a8SLen Brown break; 546*95b482a8SLen Brown } 547*95b482a8SLen Brown 548*95b482a8SLen Brown break; 549*95b482a8SLen Brown } 550*95b482a8SLen Brown 551*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 552*95b482a8SLen Brown } 553*95b482a8SLen Brown 554*95b482a8SLen Brown /******************************************************************************* 555*95b482a8SLen Brown * 556*95b482a8SLen Brown * FUNCTION: acpi_ps_complete_op 557*95b482a8SLen Brown * 558*95b482a8SLen Brown * PARAMETERS: walk_state - Current state 559*95b482a8SLen Brown * Op - Returned Op 560*95b482a8SLen Brown * Status - Parse status before complete Op 561*95b482a8SLen Brown * 562*95b482a8SLen Brown * RETURN: Status 563*95b482a8SLen Brown * 564*95b482a8SLen Brown * DESCRIPTION: Complete Op 565*95b482a8SLen Brown * 566*95b482a8SLen Brown ******************************************************************************/ 567*95b482a8SLen Brown 568*95b482a8SLen Brown static acpi_status 569*95b482a8SLen Brown acpi_ps_complete_op(struct acpi_walk_state *walk_state, 570*95b482a8SLen Brown union acpi_parse_object **op, acpi_status status) 571*95b482a8SLen Brown { 572*95b482a8SLen Brown acpi_status status2; 573*95b482a8SLen Brown 574*95b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); 575*95b482a8SLen Brown 576*95b482a8SLen Brown /* 577*95b482a8SLen Brown * Finished one argument of the containing scope 578*95b482a8SLen Brown */ 579*95b482a8SLen Brown walk_state->parser_state.scope->parse_scope.arg_count--; 580*95b482a8SLen Brown 581*95b482a8SLen Brown /* Close this Op (will result in parse subtree deletion) */ 582*95b482a8SLen Brown 583*95b482a8SLen Brown status2 = acpi_ps_complete_this_op(walk_state, *op); 584*95b482a8SLen Brown if (ACPI_FAILURE(status2)) { 585*95b482a8SLen Brown return_ACPI_STATUS(status2); 586*95b482a8SLen Brown } 587*95b482a8SLen Brown 588*95b482a8SLen Brown *op = NULL; 589*95b482a8SLen Brown 590*95b482a8SLen Brown switch (status) { 591*95b482a8SLen Brown case AE_OK: 592*95b482a8SLen Brown break; 593*95b482a8SLen Brown 594*95b482a8SLen Brown case AE_CTRL_TRANSFER: 595*95b482a8SLen Brown 596*95b482a8SLen Brown /* We are about to transfer to a called method */ 597*95b482a8SLen Brown 598*95b482a8SLen Brown walk_state->prev_op = NULL; 599*95b482a8SLen Brown walk_state->prev_arg_types = walk_state->arg_types; 600*95b482a8SLen Brown return_ACPI_STATUS(status); 601*95b482a8SLen Brown 602*95b482a8SLen Brown case AE_CTRL_END: 603*95b482a8SLen Brown 604*95b482a8SLen Brown acpi_ps_pop_scope(&(walk_state->parser_state), op, 605*95b482a8SLen Brown &walk_state->arg_types, 606*95b482a8SLen Brown &walk_state->arg_count); 607*95b482a8SLen Brown 608*95b482a8SLen Brown if (*op) { 609*95b482a8SLen Brown walk_state->op = *op; 610*95b482a8SLen Brown walk_state->op_info = 611*95b482a8SLen Brown acpi_ps_get_opcode_info((*op)->common.aml_opcode); 612*95b482a8SLen Brown walk_state->opcode = (*op)->common.aml_opcode; 613*95b482a8SLen Brown 614*95b482a8SLen Brown status = walk_state->ascending_callback(walk_state); 615*95b482a8SLen Brown status = 616*95b482a8SLen Brown acpi_ps_next_parse_state(walk_state, *op, status); 617*95b482a8SLen Brown 618*95b482a8SLen Brown status2 = acpi_ps_complete_this_op(walk_state, *op); 619*95b482a8SLen Brown if (ACPI_FAILURE(status2)) { 620*95b482a8SLen Brown return_ACPI_STATUS(status2); 621*95b482a8SLen Brown } 622*95b482a8SLen Brown } 623*95b482a8SLen Brown 624*95b482a8SLen Brown status = AE_OK; 625*95b482a8SLen Brown break; 626*95b482a8SLen Brown 627*95b482a8SLen Brown case AE_CTRL_BREAK: 628*95b482a8SLen Brown case AE_CTRL_CONTINUE: 629*95b482a8SLen Brown 630*95b482a8SLen Brown /* Pop off scopes until we find the While */ 631*95b482a8SLen Brown 632*95b482a8SLen Brown while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { 633*95b482a8SLen Brown acpi_ps_pop_scope(&(walk_state->parser_state), op, 634*95b482a8SLen Brown &walk_state->arg_types, 635*95b482a8SLen Brown &walk_state->arg_count); 636*95b482a8SLen Brown } 637*95b482a8SLen Brown 638*95b482a8SLen Brown /* Close this iteration of the While loop */ 639*95b482a8SLen Brown 640*95b482a8SLen Brown walk_state->op = *op; 641*95b482a8SLen Brown walk_state->op_info = 642*95b482a8SLen Brown acpi_ps_get_opcode_info((*op)->common.aml_opcode); 643*95b482a8SLen Brown walk_state->opcode = (*op)->common.aml_opcode; 644*95b482a8SLen Brown 645*95b482a8SLen Brown status = walk_state->ascending_callback(walk_state); 646*95b482a8SLen Brown status = acpi_ps_next_parse_state(walk_state, *op, status); 647*95b482a8SLen Brown 648*95b482a8SLen Brown status2 = acpi_ps_complete_this_op(walk_state, *op); 649*95b482a8SLen Brown if (ACPI_FAILURE(status2)) { 650*95b482a8SLen Brown return_ACPI_STATUS(status2); 651*95b482a8SLen Brown } 652*95b482a8SLen Brown 653*95b482a8SLen Brown status = AE_OK; 654*95b482a8SLen Brown break; 655*95b482a8SLen Brown 656*95b482a8SLen Brown case AE_CTRL_TERMINATE: 657*95b482a8SLen Brown 658*95b482a8SLen Brown /* Clean up */ 659*95b482a8SLen Brown do { 660*95b482a8SLen Brown if (*op) { 661*95b482a8SLen Brown status2 = 662*95b482a8SLen Brown acpi_ps_complete_this_op(walk_state, *op); 663*95b482a8SLen Brown if (ACPI_FAILURE(status2)) { 664*95b482a8SLen Brown return_ACPI_STATUS(status2); 665*95b482a8SLen Brown } 666*95b482a8SLen Brown 667*95b482a8SLen Brown acpi_ut_delete_generic_state 668*95b482a8SLen Brown (acpi_ut_pop_generic_state 669*95b482a8SLen Brown (&walk_state->control_state)); 670*95b482a8SLen Brown } 671*95b482a8SLen Brown 672*95b482a8SLen Brown acpi_ps_pop_scope(&(walk_state->parser_state), op, 673*95b482a8SLen Brown &walk_state->arg_types, 674*95b482a8SLen Brown &walk_state->arg_count); 675*95b482a8SLen Brown 676*95b482a8SLen Brown } while (*op); 677*95b482a8SLen Brown 678*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 679*95b482a8SLen Brown 680*95b482a8SLen Brown default: /* All other non-AE_OK status */ 681*95b482a8SLen Brown 682*95b482a8SLen Brown do { 683*95b482a8SLen Brown if (*op) { 684*95b482a8SLen Brown status2 = 685*95b482a8SLen Brown acpi_ps_complete_this_op(walk_state, *op); 686*95b482a8SLen Brown if (ACPI_FAILURE(status2)) { 687*95b482a8SLen Brown return_ACPI_STATUS(status2); 688*95b482a8SLen Brown } 689*95b482a8SLen Brown } 690*95b482a8SLen Brown 691*95b482a8SLen Brown acpi_ps_pop_scope(&(walk_state->parser_state), op, 692*95b482a8SLen Brown &walk_state->arg_types, 693*95b482a8SLen Brown &walk_state->arg_count); 694*95b482a8SLen Brown 695*95b482a8SLen Brown } while (*op); 696*95b482a8SLen Brown 697*95b482a8SLen Brown #if 0 698*95b482a8SLen Brown /* 699*95b482a8SLen Brown * TBD: Cleanup parse ops on error 700*95b482a8SLen Brown */ 701*95b482a8SLen Brown if (*op == NULL) { 702*95b482a8SLen Brown acpi_ps_pop_scope(parser_state, op, 703*95b482a8SLen Brown &walk_state->arg_types, 704*95b482a8SLen Brown &walk_state->arg_count); 705*95b482a8SLen Brown } 706*95b482a8SLen Brown #endif 707*95b482a8SLen Brown walk_state->prev_op = NULL; 708*95b482a8SLen Brown walk_state->prev_arg_types = walk_state->arg_types; 709*95b482a8SLen Brown return_ACPI_STATUS(status); 710*95b482a8SLen Brown } 711*95b482a8SLen Brown 712*95b482a8SLen Brown /* This scope complete? */ 713*95b482a8SLen Brown 714*95b482a8SLen Brown if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { 715*95b482a8SLen Brown acpi_ps_pop_scope(&(walk_state->parser_state), op, 716*95b482a8SLen Brown &walk_state->arg_types, 717*95b482a8SLen Brown &walk_state->arg_count); 718*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); 719*95b482a8SLen Brown } else { 720*95b482a8SLen Brown *op = NULL; 721*95b482a8SLen Brown } 722*95b482a8SLen Brown 723*95b482a8SLen Brown ACPI_PREEMPTION_POINT(); 724*95b482a8SLen Brown 725*95b482a8SLen Brown return_ACPI_STATUS(AE_OK); 726*95b482a8SLen Brown } 727*95b482a8SLen Brown 728*95b482a8SLen Brown /******************************************************************************* 729*95b482a8SLen Brown * 730*95b482a8SLen Brown * FUNCTION: acpi_ps_complete_final_op 731*95b482a8SLen Brown * 732*95b482a8SLen Brown * PARAMETERS: walk_state - Current state 733*95b482a8SLen Brown * Op - Current Op 734*95b482a8SLen Brown * Status - Current parse status before complete last 735*95b482a8SLen Brown * Op 736*95b482a8SLen Brown * 737*95b482a8SLen Brown * RETURN: Status 738*95b482a8SLen Brown * 739*95b482a8SLen Brown * DESCRIPTION: Complete last Op. 740*95b482a8SLen Brown * 741*95b482a8SLen Brown ******************************************************************************/ 742*95b482a8SLen Brown 743*95b482a8SLen Brown static acpi_status 744*95b482a8SLen Brown acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, 745*95b482a8SLen Brown union acpi_parse_object *op, acpi_status status) 746*95b482a8SLen Brown { 747*95b482a8SLen Brown acpi_status status2; 748*95b482a8SLen Brown 749*95b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); 750*95b482a8SLen Brown 751*95b482a8SLen Brown /* 752*95b482a8SLen Brown * Complete the last Op (if not completed), and clear the scope stack. 753*95b482a8SLen Brown * It is easily possible to end an AML "package" with an unbounded number 754*95b482a8SLen Brown * of open scopes (such as when several ASL blocks are closed with 755*95b482a8SLen Brown * sequential closing braces). We want to terminate each one cleanly. 756*95b482a8SLen Brown */ 757*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", 758*95b482a8SLen Brown op)); 759*95b482a8SLen Brown do { 760*95b482a8SLen Brown if (op) { 761*95b482a8SLen Brown if (walk_state->ascending_callback != NULL) { 762*95b482a8SLen Brown walk_state->op = op; 763*95b482a8SLen Brown walk_state->op_info = 764*95b482a8SLen Brown acpi_ps_get_opcode_info(op->common. 765*95b482a8SLen Brown aml_opcode); 766*95b482a8SLen Brown walk_state->opcode = op->common.aml_opcode; 767*95b482a8SLen Brown 768*95b482a8SLen Brown status = 769*95b482a8SLen Brown walk_state->ascending_callback(walk_state); 770*95b482a8SLen Brown status = 771*95b482a8SLen Brown acpi_ps_next_parse_state(walk_state, op, 772*95b482a8SLen Brown status); 773*95b482a8SLen Brown if (status == AE_CTRL_PENDING) { 774*95b482a8SLen Brown status = 775*95b482a8SLen Brown acpi_ps_complete_op(walk_state, &op, 776*95b482a8SLen Brown AE_OK); 777*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 778*95b482a8SLen Brown return_ACPI_STATUS(status); 779*95b482a8SLen Brown } 780*95b482a8SLen Brown } 781*95b482a8SLen Brown 782*95b482a8SLen Brown if (status == AE_CTRL_TERMINATE) { 783*95b482a8SLen Brown status = AE_OK; 784*95b482a8SLen Brown 785*95b482a8SLen Brown /* Clean up */ 786*95b482a8SLen Brown do { 787*95b482a8SLen Brown if (op) { 788*95b482a8SLen Brown status2 = 789*95b482a8SLen Brown acpi_ps_complete_this_op 790*95b482a8SLen Brown (walk_state, op); 791*95b482a8SLen Brown if (ACPI_FAILURE 792*95b482a8SLen Brown (status2)) { 793*95b482a8SLen Brown return_ACPI_STATUS 794*95b482a8SLen Brown (status2); 795*95b482a8SLen Brown } 796*95b482a8SLen Brown } 797*95b482a8SLen Brown 798*95b482a8SLen Brown acpi_ps_pop_scope(& 799*95b482a8SLen Brown (walk_state-> 800*95b482a8SLen Brown parser_state), 801*95b482a8SLen Brown &op, 802*95b482a8SLen Brown &walk_state-> 803*95b482a8SLen Brown arg_types, 804*95b482a8SLen Brown &walk_state-> 805*95b482a8SLen Brown arg_count); 806*95b482a8SLen Brown 807*95b482a8SLen Brown } while (op); 808*95b482a8SLen Brown 809*95b482a8SLen Brown return_ACPI_STATUS(status); 810*95b482a8SLen Brown } 811*95b482a8SLen Brown 812*95b482a8SLen Brown else if (ACPI_FAILURE(status)) { 813*95b482a8SLen Brown 814*95b482a8SLen Brown /* First error is most important */ 815*95b482a8SLen Brown 816*95b482a8SLen Brown (void) 817*95b482a8SLen Brown acpi_ps_complete_this_op(walk_state, 818*95b482a8SLen Brown op); 819*95b482a8SLen Brown return_ACPI_STATUS(status); 820*95b482a8SLen Brown } 821*95b482a8SLen Brown } 822*95b482a8SLen Brown 823*95b482a8SLen Brown status2 = acpi_ps_complete_this_op(walk_state, op); 824*95b482a8SLen Brown if (ACPI_FAILURE(status2)) { 825*95b482a8SLen Brown return_ACPI_STATUS(status2); 826*95b482a8SLen Brown } 827*95b482a8SLen Brown } 828*95b482a8SLen Brown 829*95b482a8SLen Brown acpi_ps_pop_scope(&(walk_state->parser_state), &op, 830*95b482a8SLen Brown &walk_state->arg_types, 831*95b482a8SLen Brown &walk_state->arg_count); 832*95b482a8SLen Brown 833*95b482a8SLen Brown } while (op); 834*95b482a8SLen Brown 835*95b482a8SLen Brown return_ACPI_STATUS(status); 836*95b482a8SLen Brown } 837*95b482a8SLen Brown 838*95b482a8SLen Brown /******************************************************************************* 839*95b482a8SLen Brown * 840*95b482a8SLen Brown * FUNCTION: acpi_ps_parse_loop 841*95b482a8SLen Brown * 842*95b482a8SLen Brown * PARAMETERS: walk_state - Current state 843*95b482a8SLen Brown * 844*95b482a8SLen Brown * RETURN: Status 845*95b482a8SLen Brown * 846*95b482a8SLen Brown * DESCRIPTION: Parse AML (pointed to by the current parser state) and return 847*95b482a8SLen Brown * a tree of ops. 848*95b482a8SLen Brown * 849*95b482a8SLen Brown ******************************************************************************/ 850*95b482a8SLen Brown 851*95b482a8SLen Brown acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) 852*95b482a8SLen Brown { 853*95b482a8SLen Brown acpi_status status = AE_OK; 854*95b482a8SLen Brown union acpi_parse_object *op = NULL; /* current op */ 855*95b482a8SLen Brown struct acpi_parse_state *parser_state; 856*95b482a8SLen Brown u8 *aml_op_start = NULL; 857*95b482a8SLen Brown 858*95b482a8SLen Brown ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state); 859*95b482a8SLen Brown 860*95b482a8SLen Brown if (walk_state->descending_callback == NULL) { 861*95b482a8SLen Brown return_ACPI_STATUS(AE_BAD_PARAMETER); 862*95b482a8SLen Brown } 863*95b482a8SLen Brown 864*95b482a8SLen Brown parser_state = &walk_state->parser_state; 865*95b482a8SLen Brown walk_state->arg_types = 0; 866*95b482a8SLen Brown 867*95b482a8SLen Brown #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) 868*95b482a8SLen Brown 869*95b482a8SLen Brown if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { 870*95b482a8SLen Brown 871*95b482a8SLen Brown /* We are restarting a preempted control method */ 872*95b482a8SLen Brown 873*95b482a8SLen Brown if (acpi_ps_has_completed_scope(parser_state)) { 874*95b482a8SLen Brown /* 875*95b482a8SLen Brown * We must check if a predicate to an IF or WHILE statement 876*95b482a8SLen Brown * was just completed 877*95b482a8SLen Brown */ 878*95b482a8SLen Brown if ((parser_state->scope->parse_scope.op) && 879*95b482a8SLen Brown ((parser_state->scope->parse_scope.op->common. 880*95b482a8SLen Brown aml_opcode == AML_IF_OP) 881*95b482a8SLen Brown || (parser_state->scope->parse_scope.op->common. 882*95b482a8SLen Brown aml_opcode == AML_WHILE_OP)) 883*95b482a8SLen Brown && (walk_state->control_state) 884*95b482a8SLen Brown && (walk_state->control_state->common.state == 885*95b482a8SLen Brown ACPI_CONTROL_PREDICATE_EXECUTING)) { 886*95b482a8SLen Brown /* 887*95b482a8SLen Brown * A predicate was just completed, get the value of the 888*95b482a8SLen Brown * predicate and branch based on that value 889*95b482a8SLen Brown */ 890*95b482a8SLen Brown walk_state->op = NULL; 891*95b482a8SLen Brown status = 892*95b482a8SLen Brown acpi_ds_get_predicate_value(walk_state, 893*95b482a8SLen Brown ACPI_TO_POINTER 894*95b482a8SLen Brown (TRUE)); 895*95b482a8SLen Brown if (ACPI_FAILURE(status) 896*95b482a8SLen Brown && ((status & AE_CODE_MASK) != 897*95b482a8SLen Brown AE_CODE_CONTROL)) { 898*95b482a8SLen Brown if (status == AE_AML_NO_RETURN_VALUE) { 899*95b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, 900*95b482a8SLen Brown "Invoked method did not return a value")); 901*95b482a8SLen Brown 902*95b482a8SLen Brown } 903*95b482a8SLen Brown 904*95b482a8SLen Brown ACPI_EXCEPTION((AE_INFO, status, 905*95b482a8SLen Brown "GetPredicate Failed")); 906*95b482a8SLen Brown return_ACPI_STATUS(status); 907*95b482a8SLen Brown } 908*95b482a8SLen Brown 909*95b482a8SLen Brown status = 910*95b482a8SLen Brown acpi_ps_next_parse_state(walk_state, op, 911*95b482a8SLen Brown status); 912*95b482a8SLen Brown } 913*95b482a8SLen Brown 914*95b482a8SLen Brown acpi_ps_pop_scope(parser_state, &op, 915*95b482a8SLen Brown &walk_state->arg_types, 916*95b482a8SLen Brown &walk_state->arg_count); 917*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 918*95b482a8SLen Brown "Popped scope, Op=%p\n", op)); 919*95b482a8SLen Brown } else if (walk_state->prev_op) { 920*95b482a8SLen Brown 921*95b482a8SLen Brown /* We were in the middle of an op */ 922*95b482a8SLen Brown 923*95b482a8SLen Brown op = walk_state->prev_op; 924*95b482a8SLen Brown walk_state->arg_types = walk_state->prev_arg_types; 925*95b482a8SLen Brown } 926*95b482a8SLen Brown } 927*95b482a8SLen Brown #endif 928*95b482a8SLen Brown 929*95b482a8SLen Brown /* Iterative parsing loop, while there is more AML to process: */ 930*95b482a8SLen Brown 931*95b482a8SLen Brown while ((parser_state->aml < parser_state->aml_end) || (op)) { 932*95b482a8SLen Brown aml_op_start = parser_state->aml; 933*95b482a8SLen Brown if (!op) { 934*95b482a8SLen Brown status = 935*95b482a8SLen Brown acpi_ps_create_op(walk_state, aml_op_start, &op); 936*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 937*95b482a8SLen Brown if (status == AE_CTRL_PARSE_CONTINUE) { 938*95b482a8SLen Brown continue; 939*95b482a8SLen Brown } 940*95b482a8SLen Brown 941*95b482a8SLen Brown if (status == AE_CTRL_PARSE_PENDING) { 942*95b482a8SLen Brown status = AE_OK; 943*95b482a8SLen Brown } 944*95b482a8SLen Brown 945*95b482a8SLen Brown status = 946*95b482a8SLen Brown acpi_ps_complete_op(walk_state, &op, 947*95b482a8SLen Brown status); 948*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 949*95b482a8SLen Brown return_ACPI_STATUS(status); 950*95b482a8SLen Brown } 951*95b482a8SLen Brown 952*95b482a8SLen Brown continue; 953*95b482a8SLen Brown } 954*95b482a8SLen Brown 955*95b482a8SLen Brown op->common.aml_offset = walk_state->aml_offset; 956*95b482a8SLen Brown 957*95b482a8SLen Brown if (walk_state->op_info) { 958*95b482a8SLen Brown ACPI_DEBUG_PRINT((ACPI_DB_PARSE, 959*95b482a8SLen Brown "Opcode %4.4X [%s] Op %p Aml %p AmlOffset %5.5X\n", 960*95b482a8SLen Brown (u32) op->common.aml_opcode, 961*95b482a8SLen Brown walk_state->op_info->name, op, 962*95b482a8SLen Brown parser_state->aml, 963*95b482a8SLen Brown op->common.aml_offset)); 964*95b482a8SLen Brown } 965*95b482a8SLen Brown } 966*95b482a8SLen Brown 967*95b482a8SLen Brown /* 968*95b482a8SLen Brown * Start arg_count at zero because we don't know if there are 969*95b482a8SLen Brown * any args yet 970*95b482a8SLen Brown */ 971*95b482a8SLen Brown walk_state->arg_count = 0; 972*95b482a8SLen Brown 973*95b482a8SLen Brown /* Are there any arguments that must be processed? */ 974*95b482a8SLen Brown 975*95b482a8SLen Brown if (walk_state->arg_types) { 976*95b482a8SLen Brown 977*95b482a8SLen Brown /* Get arguments */ 978*95b482a8SLen Brown 979*95b482a8SLen Brown status = 980*95b482a8SLen Brown acpi_ps_get_arguments(walk_state, aml_op_start, op); 981*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 982*95b482a8SLen Brown status = 983*95b482a8SLen Brown acpi_ps_complete_op(walk_state, &op, 984*95b482a8SLen Brown status); 985*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 986*95b482a8SLen Brown return_ACPI_STATUS(status); 987*95b482a8SLen Brown } 988*95b482a8SLen Brown 989*95b482a8SLen Brown continue; 990*95b482a8SLen Brown } 991*95b482a8SLen Brown } 992*95b482a8SLen Brown 993*95b482a8SLen Brown /* Check for arguments that need to be processed */ 994*95b482a8SLen Brown 995*95b482a8SLen Brown if (walk_state->arg_count) { 996*95b482a8SLen Brown /* 997*95b482a8SLen Brown * There are arguments (complex ones), push Op and 998*95b482a8SLen Brown * prepare for argument 999*95b482a8SLen Brown */ 1000*95b482a8SLen Brown status = acpi_ps_push_scope(parser_state, op, 1001*95b482a8SLen Brown walk_state->arg_types, 1002*95b482a8SLen Brown walk_state->arg_count); 1003*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 1004*95b482a8SLen Brown status = 1005*95b482a8SLen Brown acpi_ps_complete_op(walk_state, &op, 1006*95b482a8SLen Brown status); 1007*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 1008*95b482a8SLen Brown return_ACPI_STATUS(status); 1009*95b482a8SLen Brown } 1010*95b482a8SLen Brown 1011*95b482a8SLen Brown continue; 1012*95b482a8SLen Brown } 1013*95b482a8SLen Brown 1014*95b482a8SLen Brown op = NULL; 1015*95b482a8SLen Brown continue; 1016*95b482a8SLen Brown } 1017*95b482a8SLen Brown 1018*95b482a8SLen Brown /* 1019*95b482a8SLen Brown * All arguments have been processed -- Op is complete, 1020*95b482a8SLen Brown * prepare for next 1021*95b482a8SLen Brown */ 1022*95b482a8SLen Brown walk_state->op_info = 1023*95b482a8SLen Brown acpi_ps_get_opcode_info(op->common.aml_opcode); 1024*95b482a8SLen Brown if (walk_state->op_info->flags & AML_NAMED) { 1025*95b482a8SLen Brown if (acpi_gbl_depth) { 1026*95b482a8SLen Brown acpi_gbl_depth--; 1027*95b482a8SLen Brown } 1028*95b482a8SLen Brown 1029*95b482a8SLen Brown if (op->common.aml_opcode == AML_REGION_OP || 1030*95b482a8SLen Brown op->common.aml_opcode == AML_DATA_REGION_OP) { 1031*95b482a8SLen Brown /* 1032*95b482a8SLen Brown * Skip parsing of control method or opregion body, 1033*95b482a8SLen Brown * because we don't have enough info in the first pass 1034*95b482a8SLen Brown * to parse them correctly. 1035*95b482a8SLen Brown * 1036*95b482a8SLen Brown * Completed parsing an op_region declaration, we now 1037*95b482a8SLen Brown * know the length. 1038*95b482a8SLen Brown */ 1039*95b482a8SLen Brown op->named.length = 1040*95b482a8SLen Brown (u32) (parser_state->aml - op->named.data); 1041*95b482a8SLen Brown } 1042*95b482a8SLen Brown } 1043*95b482a8SLen Brown 1044*95b482a8SLen Brown if (walk_state->op_info->flags & AML_CREATE) { 1045*95b482a8SLen Brown /* 1046*95b482a8SLen Brown * Backup to beginning of create_xXXfield declaration (1 for 1047*95b482a8SLen Brown * Opcode) 1048*95b482a8SLen Brown * 1049*95b482a8SLen Brown * body_length is unknown until we parse the body 1050*95b482a8SLen Brown */ 1051*95b482a8SLen Brown op->named.length = 1052*95b482a8SLen Brown (u32) (parser_state->aml - op->named.data); 1053*95b482a8SLen Brown } 1054*95b482a8SLen Brown 1055*95b482a8SLen Brown if (op->common.aml_opcode == AML_BANK_FIELD_OP) { 1056*95b482a8SLen Brown /* 1057*95b482a8SLen Brown * Backup to beginning of bank_field declaration 1058*95b482a8SLen Brown * 1059*95b482a8SLen Brown * body_length is unknown until we parse the body 1060*95b482a8SLen Brown */ 1061*95b482a8SLen Brown op->named.length = 1062*95b482a8SLen Brown (u32) (parser_state->aml - op->named.data); 1063*95b482a8SLen Brown } 1064*95b482a8SLen Brown 1065*95b482a8SLen Brown /* This op complete, notify the dispatcher */ 1066*95b482a8SLen Brown 1067*95b482a8SLen Brown if (walk_state->ascending_callback != NULL) { 1068*95b482a8SLen Brown walk_state->op = op; 1069*95b482a8SLen Brown walk_state->opcode = op->common.aml_opcode; 1070*95b482a8SLen Brown 1071*95b482a8SLen Brown status = walk_state->ascending_callback(walk_state); 1072*95b482a8SLen Brown status = 1073*95b482a8SLen Brown acpi_ps_next_parse_state(walk_state, op, status); 1074*95b482a8SLen Brown if (status == AE_CTRL_PENDING) { 1075*95b482a8SLen Brown status = AE_OK; 1076*95b482a8SLen Brown } 1077*95b482a8SLen Brown } 1078*95b482a8SLen Brown 1079*95b482a8SLen Brown status = acpi_ps_complete_op(walk_state, &op, status); 1080*95b482a8SLen Brown if (ACPI_FAILURE(status)) { 1081*95b482a8SLen Brown return_ACPI_STATUS(status); 1082*95b482a8SLen Brown } 1083*95b482a8SLen Brown 1084*95b482a8SLen Brown } /* while parser_state->Aml */ 1085*95b482a8SLen Brown 1086*95b482a8SLen Brown status = acpi_ps_complete_final_op(walk_state, op, status); 1087*95b482a8SLen Brown return_ACPI_STATUS(status); 1088*95b482a8SLen Brown } 1089