acpi_parse_object* acpi_ps_alloc_op ( u16 opcode) { acpi_parse_object *op = NULL; u32 size; u8 flags; const acpi_opcode_info *op_info; FUNCTION_ENTRY (); op_info = acpi_ps_get_opcode_info (opcode); /* Allocate the minimum required size object */ if (op_info->flags & AML_DEFER) { size = sizeof (acpi_parse2_object); flags = PARSEOP_DEFERRED; } else if (op_info->flags & AML_NAMED) { size = sizeof (acpi_parse2_object); flags = PARSEOP_NAMED; } else if (opcode == AML_INT_BYTELIST_OP) { size = sizeof (acpi_parse2_object); flags = PARSEOP_BYTELIST; } else { size = sizeof (acpi_parse_object); flags = PARSEOP_GENERIC; } if (size == sizeof (acpi_parse_object)) { /* * The generic op is by far the most common (16 to 1) */ op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE); } else { op = acpi_ut_acquire_from_cache (ACPI_MEM_LIST_PSNODE_EXT); } /* Initialize the Op */ if (op) { acpi_ps_init_op (op, opcode); op->flags = flags; } return (op); }
void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) { ACPI_FUNCTION_ENTRY(); op->common.descriptor_type = ACPI_DESC_TYPE_PARSER; op->common.aml_opcode = opcode; ACPI_DISASM_ONLY_MEMBERS(strncpy(op->common.aml_op_name, (acpi_ps_get_opcode_info(opcode))-> name, sizeof(op->common.aml_op_name))); }
acpi_status acpi_ds_build_internal_object ( struct acpi_walk_state *walk_state, union acpi_parse_object *op, union acpi_operand_object **obj_desc_ptr) { union acpi_operand_object *obj_desc; acpi_status status; ACPI_FUNCTION_TRACE ("ds_build_internal_object"); *obj_desc_ptr = NULL; if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) { /* * This is an named object reference. If this name was * previously looked up in the namespace, it was stored in this op. * Otherwise, go ahead and look it up now */ if (!op->common.node) { status = acpi_ns_lookup (walk_state->scope_info, op->common.value.string, ACPI_TYPE_ANY, ACPI_IMODE_EXECUTE, ACPI_NS_SEARCH_PARENT | ACPI_NS_DONT_OPEN_SCOPE, NULL, (struct acpi_namespace_node **) &(op->common.node)); if (ACPI_FAILURE (status)) { ACPI_REPORT_NSERROR (op->common.value.string, status); return_ACPI_STATUS (status); } } } /* Create and init the internal ACPI object */ obj_desc = acpi_ut_create_internal_object ((acpi_ps_get_opcode_info (op->common.aml_opcode))->object_type); if (!obj_desc) { return_ACPI_STATUS (AE_NO_MEMORY); } status = acpi_ds_init_object_from_op (walk_state, op, op->common.aml_opcode, &obj_desc); if (ACPI_FAILURE (status)) { acpi_ut_remove_reference (obj_desc); return_ACPI_STATUS (status); } *obj_desc_ptr = obj_desc; return_ACPI_STATUS (AE_OK); }
static void acpi_db_dump_parser_descriptor(union acpi_parse_object *op) { const struct acpi_opcode_info *info; info = acpi_ps_get_opcode_info(op->common.aml_opcode); acpi_os_printf("Parser Op Descriptor:\n"); acpi_os_printf("%20.20s : %4.4X\n", "Opcode", op->common.aml_opcode); ACPI_DEBUG_ONLY_MEMBERS(acpi_os_printf("%20.20s : %s\n", "Opcode Name", info->name)); acpi_os_printf("%20.20s : %p\n", "Value/ArgList", op->common.value.arg); acpi_os_printf("%20.20s : %p\n", "Parent", op->common.parent); acpi_os_printf("%20.20s : %p\n", "NextOp", op->common.next); }
char *acpi_ps_get_opcode_name(u16 opcode) { #if defined(ACPI_DISASSEMBLER) || defined (ACPI_DEBUG_OUTPUT) const struct acpi_opcode_info *op; op = acpi_ps_get_opcode_info(opcode); /* Always guaranteed to return a valid pointer */ return (op->name); #else return ("OpcodeName unavailable"); #endif }
union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml) { union acpi_parse_object *op; const struct acpi_opcode_info *op_info; u8 flags = ACPI_PARSEOP_GENERIC; ACPI_FUNCTION_ENTRY(); op_info = acpi_ps_get_opcode_info(opcode); /* Determine type of parse_op required */ if (op_info->flags & AML_DEFER) { flags = ACPI_PARSEOP_DEFERRED; } else if (op_info->flags & AML_NAMED) { flags = ACPI_PARSEOP_NAMED_OBJECT; } else if (opcode == AML_INT_BYTELIST_OP) { flags = ACPI_PARSEOP_BYTELIST; } /* Allocate the minimum required size object */ if (flags == ACPI_PARSEOP_GENERIC) { /* The generic op (default) is by far the most common (16 to 1) */ op = acpi_os_acquire_object(acpi_gbl_ps_node_cache); } else { /* Extended parseop */ op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache); } /* Initialize the Op */ if (op) { acpi_ps_init_op(op, opcode); op->common.aml = aml; op->common.flags = flags; } return (op); }
void acpi_ps_init_op ( acpi_parse_object *op, u16 opcode) { const acpi_opcode_info *aml_op; FUNCTION_ENTRY (); op->data_type = ACPI_DESC_TYPE_PARSER; op->opcode = opcode; aml_op = acpi_ps_get_opcode_info (opcode); DEBUG_ONLY_MEMBERS (STRNCPY (op->op_name, aml_op->name, sizeof (op->op_name))); }
union acpi_parse_object *acpi_ps_alloc_op(u16 opcode) { union acpi_parse_object *op; const struct acpi_opcode_info *op_info; u8 flags = ACPI_PARSEOP_GENERIC; ACPI_FUNCTION_ENTRY(); op_info = acpi_ps_get_opcode_info(opcode); if (op_info->flags & AML_DEFER) { flags = ACPI_PARSEOP_DEFERRED; } else if (op_info->flags & AML_NAMED) { flags = ACPI_PARSEOP_NAMED; } else if (opcode == AML_INT_BYTELIST_OP) { flags = ACPI_PARSEOP_BYTELIST; } if (flags == ACPI_PARSEOP_GENERIC) { op = acpi_os_acquire_object(acpi_gbl_ps_node_cache); } else { op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache); } if (op) { acpi_ps_init_op(op, opcode); op->common.flags = flags; } return (op); }
static acpi_status acpi_ps_get_aml_opcode(struct acpi_walk_state *walk_state) { u32 aml_offset; ACPI_FUNCTION_TRACE_PTR(ps_get_aml_opcode, walk_state); walk_state->aml = walk_state->parser_state.aml; walk_state->opcode = acpi_ps_peek_opcode(&(walk_state->parser_state)); /* * First cut to determine what we have found: * 1) A valid AML opcode * 2) A name string * 3) An unknown/invalid opcode */ walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); switch (walk_state->op_info->class) { case AML_CLASS_ASCII: case AML_CLASS_PREFIX: /* * Starts with a valid prefix or ASCII char, this is a name * string. Convert the bare name string to a namepath. */ walk_state->opcode = AML_INT_NAMEPATH_OP; walk_state->arg_types = ARGP_NAMESTRING; break; case AML_CLASS_UNKNOWN: /* The opcode is unrecognized. Complain and skip unknown opcodes */ if (walk_state->pass_number == 2) { aml_offset = (u32)ACPI_PTR_DIFF(walk_state->aml, walk_state-> parser_state.aml_start); ACPI_ERROR((AE_INFO, "Unknown opcode 0x%.2X at table offset 0x%.4X, ignoring", walk_state->opcode, (u32)(aml_offset + sizeof(struct acpi_table_header)))); ACPI_DUMP_BUFFER((walk_state->parser_state.aml - 16), 48); #ifdef ACPI_ASL_COMPILER /* * This is executed for the disassembler only. Output goes * to the disassembled ASL output file. */ acpi_os_printf ("/*\nError: Unknown opcode 0x%.2X at table offset 0x%.4X, context:\n", walk_state->opcode, (u32)(aml_offset + sizeof(struct acpi_table_header))); ACPI_ERROR((AE_INFO, "Aborting disassembly, AML byte code is corrupt")); /* Dump the context surrounding the invalid opcode */ acpi_ut_dump_buffer(((u8 *)walk_state->parser_state. aml - 16), 48, DB_BYTE_DISPLAY, (aml_offset + sizeof(struct acpi_table_header) - 16)); acpi_os_printf(" */\n"); /* * Just abort the disassembly, cannot continue because the * parser is essentially lost. The disassembler can then * randomly fail because an ill-constructed parse tree * can result. */ return_ACPI_STATUS(AE_AML_BAD_OPCODE); #endif } /* Increment past one-byte or two-byte opcode */ walk_state->parser_state.aml++; if (walk_state->opcode > 0xFF) { /* Can only happen if first byte is 0x5B */ walk_state->parser_state.aml++; } return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); default: /* Found opcode info, this is a normal opcode */ walk_state->parser_state.aml += acpi_ps_get_opcode_size(walk_state->opcode); walk_state->arg_types = walk_state->op_info->parse_args; break; } return_ACPI_STATUS(AE_OK); }
acpi_status acpi_ps_complete_final_op(struct acpi_walk_state *walk_state, union acpi_parse_object *op, acpi_status status) { acpi_status status2; ACPI_FUNCTION_TRACE_PTR(ps_complete_final_op, walk_state); /* * Complete the last Op (if not completed), and clear the scope stack. * It is easily possible to end an AML "package" with an unbounded number * of open scopes (such as when several ASL blocks are closed with * sequential closing braces). We want to terminate each one cleanly. */ ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "AML package complete at Op %p\n", op)); do { if (op) { if (walk_state->ascending_callback != NULL) { walk_state->op = op; walk_state->op_info = acpi_ps_get_opcode_info(op->common. aml_opcode); walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = acpi_ps_complete_op(walk_state, &op, AE_OK); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } if (status == AE_CTRL_TERMINATE) { status = AE_OK; /* Clean up */ do { if (op) { status2 = acpi_ps_complete_this_op (walk_state, op); if (ACPI_FAILURE (status2)) { return_ACPI_STATUS (status2); } } acpi_ps_pop_scope(& (walk_state-> parser_state), &op, &walk_state-> arg_types, &walk_state-> arg_count); } while (op); return_ACPI_STATUS(status); } else if (ACPI_FAILURE(status)) { /* First error is most important */ (void) acpi_ps_complete_this_op(walk_state, op); return_ACPI_STATUS(status); } } status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(&(walk_state->parser_state), &op, &walk_state->arg_types, &walk_state->arg_count); } while (op); return_ACPI_STATUS(status); }
acpi_status acpi_ps_complete_op(struct acpi_walk_state *walk_state, union acpi_parse_object **op, acpi_status status) { acpi_status status2; ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); /* * Finished one argument of the containing scope */ walk_state->parser_state.scope->parse_scope.arg_count--; /* Close this Op (will result in parse subtree deletion) */ status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } *op = NULL; switch (status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method */ walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); case AE_CTRL_END: acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); if (*op) { walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } /* Close this iteration of the While loop */ walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } status = AE_OK; break; case AE_CTRL_TERMINATE: /* Clean up */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } acpi_ut_delete_generic_state (acpi_ut_pop_generic_state (&walk_state->control_state)); } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); return_ACPI_STATUS(AE_OK); default: /* All other non-AE_OK status */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); #if 0 /* * TBD: Cleanup parse ops on error */ if (*op == NULL) { acpi_ps_pop_scope(parser_state, op, &walk_state->arg_types, &walk_state->arg_count); } #endif walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); } /* This scope complete? */ if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); } else { *op = NULL; } return_ACPI_STATUS(AE_OK); }
acpi_status acpi_ps_create_op(struct acpi_walk_state *walk_state, u8 *aml_op_start, union acpi_parse_object **new_op) { acpi_status status = AE_OK; union acpi_parse_object *op; union acpi_parse_object *named_op = NULL; union acpi_parse_object *parent_scope; u8 argument_count; const struct acpi_opcode_info *op_info; ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); status = acpi_ps_get_aml_opcode(walk_state); if (status == AE_CTRL_PARSE_CONTINUE) { return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Create Op structure and append to parent's argument list */ walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); op = acpi_ps_alloc_op(walk_state->opcode, aml_op_start); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } if (walk_state->op_info->flags & AML_NAMED) { status = acpi_ps_build_named_op(walk_state, aml_op_start, op, &named_op); acpi_ps_free_op(op); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } *new_op = named_op; return_ACPI_STATUS(AE_OK); } /* Not a named opcode, just allocate Op and append to parent */ if (walk_state->op_info->flags & AML_CREATE) { /* * Backup to beginning of create_XXXfield declaration * body_length is unknown until we parse the body */ op->named.data = aml_op_start; op->named.length = 0; } if (walk_state->opcode == AML_BANK_FIELD_OP) { /* * Backup to beginning of bank_field declaration * body_length is unknown until we parse the body */ op->named.data = aml_op_start; op->named.length = 0; } parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); acpi_ps_append_arg(parent_scope, op); if (parent_scope) { op_info = acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); if (op_info->flags & AML_HAS_TARGET) { argument_count = acpi_ps_get_argument_count(op_info->type); if (parent_scope->common.arg_list_length > argument_count) { op->common.flags |= ACPI_PARSEOP_TARGET; } } /* * Special case for both Increment() and Decrement(), where * the lone argument is both a source and a target. */ else if ((parent_scope->common.aml_opcode == AML_INCREMENT_OP) || (parent_scope->common.aml_opcode == AML_DECREMENT_OP)) { op->common.flags |= ACPI_PARSEOP_TARGET; } } if (walk_state->descending_callback != NULL) { /* * Find the object. This will either insert the object into * the namespace or simply look it up */ walk_state->op = *new_op = op; status = walk_state->descending_callback(walk_state, &op); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_CTRL_PARSE_PENDING; } } return_ACPI_STATUS(status); }
static void acpi_ex_dump_object(union acpi_operand_object *obj_desc, struct acpi_exdump_info *info) { u8 *target; char *name; u8 count; if (!info) { acpi_os_printf ("ExDumpObject: Display not implemented for object type %s\n", acpi_ut_get_object_type_name(obj_desc)); return; } /* First table entry must contain the table length (# of table entries) */ count = info->offset; while (count) { target = ACPI_ADD_PTR(u8, obj_desc, info->offset); name = info->name; switch (info->opcode) { case ACPI_EXD_INIT: break; case ACPI_EXD_TYPE: acpi_ex_out_string("Type", acpi_ut_get_object_type_name (obj_desc)); break; case ACPI_EXD_UINT8: acpi_os_printf("%20s : %2.2X\n", name, *target); break; case ACPI_EXD_UINT16: acpi_os_printf("%20s : %4.4X\n", name, ACPI_GET16(target)); break; case ACPI_EXD_UINT32: acpi_os_printf("%20s : %8.8X\n", name, ACPI_GET32(target)); break; case ACPI_EXD_UINT64: acpi_os_printf("%20s : %8.8X%8.8X\n", "Value", ACPI_FORMAT_UINT64(ACPI_GET64(target))); break; case ACPI_EXD_POINTER: acpi_ex_out_pointer(name, *ACPI_CAST_PTR(void *, target)); break; case ACPI_EXD_ADDRESS: acpi_ex_out_address(name, *ACPI_CAST_PTR (acpi_physical_address, target)); break; case ACPI_EXD_STRING: acpi_ut_print_string(obj_desc->string.pointer, ACPI_UINT8_MAX); acpi_os_printf("\n"); break; case ACPI_EXD_BUFFER: ACPI_DUMP_BUFFER(obj_desc->buffer.pointer, obj_desc->buffer.length); break; case ACPI_EXD_PACKAGE: /* Dump the package contents */ acpi_os_printf("\nPackage Contents:\n"); acpi_ex_dump_package_obj(obj_desc, 0, 0); break; case ACPI_EXD_FIELD: acpi_ex_dump_object(obj_desc, acpi_ex_dump_field_common); break; case ACPI_EXD_REFERENCE: acpi_ex_out_string("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))-> name); acpi_ex_dump_reference_obj(obj_desc); break; default: acpi_os_printf("**** Invalid table opcode [%X] ****\n", info->opcode); return; } info++; count--; } }
void acpi_db_display_path ( acpi_parse_object *op) { acpi_parse_object *prev; acpi_parse_object *search; u32 name; u8 do_dot = FALSE; acpi_parse_object *name_path; const acpi_opcode_info *op_info; /* We are only interested in named objects */ op_info = acpi_ps_get_opcode_info (op->opcode); if (!(op_info->flags & AML_NSNODE)) { return; } if (op_info->flags & AML_CREATE) { /* Field creation - check for a fully qualified namepath */ if (op->opcode == AML_CREATE_FIELD_OP) { name_path = acpi_ps_get_arg (op, 3); } else { name_path = acpi_ps_get_arg (op, 2); } if ((name_path) && (name_path->value.string) && (name_path->value.string[0] == '\\')) { acpi_db_display_namestring (name_path->value.string); return; } } prev = NULL; /* Start with Root Node */ while (prev != op) { /* Search upwards in the tree to find scope with "prev" as its parent */ search = op; for (; ;) { if (search->parent == prev) { break; } /* Go up one level */ search = search->parent; } if (prev) { op_info = acpi_ps_get_opcode_info (search->opcode); if (!(op_info->flags & AML_FIELD)) { /* below root scope, append scope name */ if (do_dot) { /* append dot */ acpi_os_printf ("."); } if (op_info->flags & AML_CREATE) { if (op->opcode == AML_CREATE_FIELD_OP) { name_path = acpi_ps_get_arg (op, 3); } else { name_path = acpi_ps_get_arg (op, 2); } if ((name_path) && (name_path->value.string)) { acpi_os_printf ("%4.4s", name_path->value.string); } } else { name = acpi_ps_get_name (search); acpi_os_printf ("%4.4s", &name); } do_dot = TRUE; } } prev = search; } }
acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state) { acpi_status status = AE_OK; acpi_status status2; union acpi_parse_object *op = NULL; /* current op */ union acpi_parse_object *arg = NULL; union acpi_parse_object *pre_op = NULL; struct acpi_parse_state *parser_state; u8 *aml_op_start = NULL; ACPI_FUNCTION_TRACE_PTR("ps_parse_loop", walk_state); if (walk_state->descending_callback == NULL) { return_ACPI_STATUS(AE_BAD_PARAMETER); } parser_state = &walk_state->parser_state; walk_state->arg_types = 0; #if (!defined (ACPI_NO_METHOD_EXECUTION) && !defined (ACPI_CONSTANT_EVAL_ONLY)) if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) { /* We are restarting a preempted control method */ if (acpi_ps_has_completed_scope(parser_state)) { /* * We must check if a predicate to an IF or WHILE statement * was just completed */ if ((parser_state->scope->parse_scope.op) && ((parser_state->scope->parse_scope.op->common. aml_opcode == AML_IF_OP) || (parser_state->scope->parse_scope.op->common. aml_opcode == AML_WHILE_OP)) && (walk_state->control_state) && (walk_state->control_state->common.state == ACPI_CONTROL_PREDICATE_EXECUTING)) { /* * A predicate was just completed, get the value of the * predicate and branch based on that value */ walk_state->op = NULL; status = acpi_ds_get_predicate_value(walk_state, ACPI_TO_POINTER (TRUE)); if (ACPI_FAILURE(status) && ((status & AE_CODE_MASK) != AE_CODE_CONTROL)) { if (status == AE_AML_NO_RETURN_VALUE) { ACPI_EXCEPTION((AE_INFO, status, "Invoked method did not return a value")); } ACPI_EXCEPTION((AE_INFO, status, "get_predicate Failed")); return_ACPI_STATUS(status); } status = acpi_ps_next_parse_state(walk_state, op, status); } acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); } else if (walk_state->prev_op) { /* We were in the middle of an op */ op = walk_state->prev_op; walk_state->arg_types = walk_state->prev_arg_types; } } #endif /* Iterative parsing loop, while there is more AML to process: */ while ((parser_state->aml < parser_state->aml_end) || (op)) { aml_op_start = parser_state->aml; if (!op) { /* Get the next opcode from the AML stream */ walk_state->aml_offset = (u32) ACPI_PTR_DIFF(parser_state->aml, parser_state->aml_start); walk_state->opcode = acpi_ps_peek_opcode(parser_state); /* * First cut to determine what we have found: * 1) A valid AML opcode * 2) A name string * 3) An unknown/invalid opcode */ walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); switch (walk_state->op_info->class) { case AML_CLASS_ASCII: case AML_CLASS_PREFIX: /* * Starts with a valid prefix or ASCII char, this is a name * string. Convert the bare name string to a namepath. */ walk_state->opcode = AML_INT_NAMEPATH_OP; walk_state->arg_types = ARGP_NAMESTRING; break; case AML_CLASS_UNKNOWN: /* The opcode is unrecognized. Just skip unknown opcodes */ ACPI_ERROR((AE_INFO, "Found unknown opcode %X at AML address %p offset %X, ignoring", walk_state->opcode, parser_state->aml, walk_state->aml_offset)); ACPI_DUMP_BUFFER(parser_state->aml, 128); /* Assume one-byte bad opcode */ parser_state->aml++; continue; default: /* Found opcode info, this is a normal opcode */ parser_state->aml += acpi_ps_get_opcode_size(walk_state->opcode); walk_state->arg_types = walk_state->op_info->parse_args; break; } /* Create Op structure and append to parent's argument list */ if (walk_state->op_info->flags & AML_NAMED) { /* Allocate a new pre_op if necessary */ if (!pre_op) { pre_op = acpi_ps_alloc_op(walk_state-> opcode); if (!pre_op) { status = AE_NO_MEMORY; goto close_this_op; } } pre_op->common.value.arg = NULL; pre_op->common.aml_opcode = walk_state->opcode; /* * Get and append arguments until we find the node that contains * the name (the type ARGP_NAME). */ while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && (GET_CURRENT_ARG_TYPE (walk_state->arg_types) != ARGP_NAME)) { status = acpi_ps_get_next_arg(walk_state, parser_state, GET_CURRENT_ARG_TYPE (walk_state-> arg_types), &arg); if (ACPI_FAILURE(status)) { goto close_this_op; } acpi_ps_append_arg(pre_op, arg); INCREMENT_ARG_LIST(walk_state-> arg_types); } /* * Make sure that we found a NAME and didn't run out of * arguments */ if (!GET_CURRENT_ARG_TYPE (walk_state->arg_types)) { status = AE_AML_NO_OPERAND; goto close_this_op; } /* We know that this arg is a name, move to next arg */ INCREMENT_ARG_LIST(walk_state->arg_types); /* * Find the object. This will either insert the object into * the namespace or simply look it up */ walk_state->op = NULL; status = walk_state->descending_callback(walk_state, &op); if (ACPI_FAILURE(status)) { ACPI_EXCEPTION((AE_INFO, status, "During name lookup/catalog")); goto close_this_op; } if (!op) { continue; } status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; goto close_this_op; } if (ACPI_FAILURE(status)) { goto close_this_op; } acpi_ps_append_arg(op, pre_op->common.value.arg); acpi_gbl_depth++; if (op->common.aml_opcode == AML_REGION_OP) { /* * Defer final parsing of an operation_region body, * because we don't have enough info in the first pass * to parse it correctly (i.e., there may be method * calls within the term_arg elements of the body.) * * However, we must continue parsing because * the opregion is not a standalone package -- * we don't know where the end is at this point. * * (Length is unknown until parse of the body complete) */ op->named.data = aml_op_start; op->named.length = 0; } } else { /* Not a named opcode, just allocate Op and append to parent */ walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); op = acpi_ps_alloc_op(walk_state->opcode); if (!op) { status = AE_NO_MEMORY; goto close_this_op; } if (walk_state->op_info->flags & AML_CREATE) { /* * Backup to beginning of create_xXXfield declaration * body_length is unknown until we parse the body */ op->named.data = aml_op_start; op->named.length = 0; } acpi_ps_append_arg(acpi_ps_get_parent_scope (parser_state), op); if ((walk_state->descending_callback != NULL)) { /* * Find the object. This will either insert the object into * the namespace or simply look it up */ walk_state->op = op; status = walk_state-> descending_callback(walk_state, &op); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; goto close_this_op; } if (ACPI_FAILURE(status)) { goto close_this_op; } } } op->common.aml_offset = walk_state->aml_offset; if (walk_state->op_info) { ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Opcode %4.4X [%s] Op %p Aml %p aml_offset %5.5X\n", (u32) op->common.aml_opcode, walk_state->op_info->name, op, parser_state->aml, op->common.aml_offset)); } } /* * Start arg_count at zero because we don't know if there are * any args yet */ walk_state->arg_count = 0; /* Are there any arguments that must be processed? */ if (walk_state->arg_types) { /* Get arguments */ switch (op->common.aml_opcode) { case AML_BYTE_OP: /* AML_BYTEDATA_ARG */ case AML_WORD_OP: /* AML_WORDDATA_ARG */ case AML_DWORD_OP: /* AML_DWORDATA_ARG */ case AML_QWORD_OP: /* AML_QWORDATA_ARG */ case AML_STRING_OP: /* AML_ASCIICHARLIST_ARG */ /* Fill in constant or string argument directly */ acpi_ps_get_next_simple_arg(parser_state, GET_CURRENT_ARG_TYPE (walk_state-> arg_types), op); break; case AML_INT_NAMEPATH_OP: /* AML_NAMESTRING_ARG */ status = acpi_ps_get_next_namepath(walk_state, parser_state, op, 1); if (ACPI_FAILURE(status)) { goto close_this_op; } walk_state->arg_types = 0; break; default: /* * Op is not a constant or string, append each argument * to the Op */ while (GET_CURRENT_ARG_TYPE (walk_state->arg_types) && !walk_state->arg_count) { walk_state->aml_offset = (u32) ACPI_PTR_DIFF(parser_state->aml, parser_state-> aml_start); status = acpi_ps_get_next_arg(walk_state, parser_state, GET_CURRENT_ARG_TYPE (walk_state-> arg_types), &arg); if (ACPI_FAILURE(status)) { goto close_this_op; } if (arg) { arg->common.aml_offset = walk_state->aml_offset; acpi_ps_append_arg(op, arg); } INCREMENT_ARG_LIST(walk_state-> arg_types); } /* Special processing for certain opcodes */ /* TBD (remove): Temporary mechanism to disable this code if needed */ #ifdef ACPI_ENABLE_MODULE_LEVEL_CODE if ((walk_state->pass_number <= ACPI_IMODE_LOAD_PASS1) && ((walk_state-> parse_flags & ACPI_PARSE_DISASSEMBLE) == 0)) { /* * We want to skip If/Else/While constructs during Pass1 * because we want to actually conditionally execute the * code during Pass2. * * Except for disassembly, where we always want to * walk the If/Else/While packages */ switch (op->common.aml_opcode) { case AML_IF_OP: case AML_ELSE_OP: case AML_WHILE_OP: ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Pass1: Skipping an If/Else/While body\n")); /* Skip body of if/else/while in pass 1 */ parser_state->aml = parser_state->pkg_end; walk_state->arg_count = 0; break; default: break; } } #endif switch (op->common.aml_opcode) { case AML_METHOD_OP: /* * Skip parsing of control method * because we don't have enough info in the first pass * to parse it correctly. * * Save the length and address of the body */ op->named.data = parser_state->aml; op->named.length = (u32) (parser_state->pkg_end - parser_state->aml); /* Skip body of method */ parser_state->aml = parser_state->pkg_end; walk_state->arg_count = 0; break; case AML_BUFFER_OP: case AML_PACKAGE_OP: case AML_VAR_PACKAGE_OP: if ((op->common.parent) && (op->common.parent->common. aml_opcode == AML_NAME_OP) && (walk_state->pass_number <= ACPI_IMODE_LOAD_PASS2)) { /* * Skip parsing of Buffers and Packages * because we don't have enough info in the first pass * to parse them correctly. */ op->named.data = aml_op_start; op->named.length = (u32) (parser_state-> pkg_end - aml_op_start); /* Skip body */ parser_state->aml = parser_state->pkg_end; walk_state->arg_count = 0; } break; case AML_WHILE_OP: if (walk_state->control_state) { walk_state->control_state-> control.package_end = parser_state->pkg_end; } break; default: /* No action for all other opcodes */ break; } break; } } /* Check for arguments that need to be processed */ if (walk_state->arg_count) { /* * There are arguments (complex ones), push Op and * prepare for argument */ status = acpi_ps_push_scope(parser_state, op, walk_state->arg_types, walk_state->arg_count); if (ACPI_FAILURE(status)) { goto close_this_op; } op = NULL; continue; } /* * All arguments have been processed -- Op is complete, * prepare for next */ walk_state->op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); if (walk_state->op_info->flags & AML_NAMED) { if (acpi_gbl_depth) { acpi_gbl_depth--; } if (op->common.aml_opcode == AML_REGION_OP) { /* * Skip parsing of control method or opregion body, * because we don't have enough info in the first pass * to parse them correctly. * * Completed parsing an op_region declaration, we now * know the length. */ op->named.length = (u32) (parser_state->aml - op->named.data); } } if (walk_state->op_info->flags & AML_CREATE) { /* * Backup to beginning of create_xXXfield declaration (1 for * Opcode) * * body_length is unknown until we parse the body */ op->named.length = (u32) (parser_state->aml - op->named.data); } /* This op complete, notify the dispatcher */ if (walk_state->ascending_callback != NULL) { walk_state->op = op; walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_OK; goto close_this_op; } } close_this_op: /* * Finished one argument of the containing scope */ parser_state->scope->parse_scope.arg_count--; /* Finished with pre_op */ if (pre_op) { acpi_ps_free_op(pre_op); pre_op = NULL; } /* Close this Op (will result in parse subtree deletion) */ status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } op = NULL; switch (status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method. */ walk_state->prev_op = op; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); case AE_CTRL_END: acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); if (op) { walk_state->op = op; walk_state->op_info = acpi_ps_get_opcode_info(op->common. aml_opcode); walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } op = NULL; } status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!op || (op->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); if (op->common.aml_opcode != AML_WHILE_OP) { status2 = acpi_ds_result_stack_pop (walk_state); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } } /* Close this iteration of the While loop */ walk_state->op = op; walk_state->op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); walk_state->opcode = op->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, op, status); status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } op = NULL; status = AE_OK; break; case AE_CTRL_TERMINATE: status = AE_OK; /* Clean up */ do { if (op) { status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); } while (op); return_ACPI_STATUS(status); default: /* All other non-AE_OK status */ do { if (op) { status2 = acpi_ps_complete_this_op(walk_state, op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); } while (op); /* * TBD: Cleanup parse ops on error */ #if 0 if (op == NULL) { acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); } #endif walk_state->prev_op = op; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); } /* This scope complete? */ if (acpi_ps_has_completed_scope(parser_state)) { acpi_ps_pop_scope(parser_state, &op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", op)); } else { op = NULL; } } /* while parser_state->Aml */
acpi_status acpi_ps_complete_op(struct acpi_walk_state *walk_state, union acpi_parse_object **op, acpi_status status) { acpi_status status2; ACPI_FUNCTION_TRACE_PTR(ps_complete_op, walk_state); /* * Finished one argument of the containing scope */ walk_state->parser_state.scope->parse_scope.arg_count--; /* Close this Op (will result in parse subtree deletion) */ status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } *op = NULL; switch (status) { case AE_OK: break; case AE_CTRL_TRANSFER: /* We are about to transfer to a called method */ walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; return_ACPI_STATUS(status); case AE_CTRL_END: acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); if (*op) { walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } status = AE_OK; break; case AE_CTRL_BREAK: case AE_CTRL_CONTINUE: /* Pop off scopes until we find the While */ while (!(*op) || ((*op)->common.aml_opcode != AML_WHILE_OP)) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } /* Close this iteration of the While loop */ walk_state->op = *op; walk_state->op_info = acpi_ps_get_opcode_info((*op)->common.aml_opcode); walk_state->opcode = (*op)->common.aml_opcode; status = walk_state->ascending_callback(walk_state); status = acpi_ps_next_parse_state(walk_state, *op, status); status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } status = AE_OK; break; case AE_CTRL_TERMINATE: /* Clean up */ do { if (*op) { status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } acpi_ut_delete_generic_state (acpi_ut_pop_generic_state (&walk_state->control_state)); } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); return_ACPI_STATUS(AE_OK); default: /* All other non-AE_OK status */ do { if (*op) { /* * These Opcodes need to be removed from the namespace because they * get created even if these opcodes cannot be created due to * errors. */ if (((*op)->common.aml_opcode == AML_REGION_OP) || ((*op)->common.aml_opcode == AML_DATA_REGION_OP)) { acpi_ns_delete_children((*op)->common. node); acpi_ns_remove_node((*op)->common.node); (*op)->common.node = NULL; acpi_ps_delete_parse_tree(*op); } status2 = acpi_ps_complete_this_op(walk_state, *op); if (ACPI_FAILURE(status2)) { return_ACPI_STATUS(status2); } } acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); } while (*op); #if 0 /* * TBD: Cleanup parse ops on error */ if (*op == NULL) { acpi_ps_pop_scope(parser_state, op, &walk_state->arg_types, &walk_state->arg_count); } #endif walk_state->prev_op = NULL; walk_state->prev_arg_types = walk_state->arg_types; if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) { /* * There was something that went wrong while executing code at the * module-level. We need to skip parsing whatever caused the * error and keep going. One runtime error during the table load * should not cause the entire table to not be loaded. This is * because there could be correct AML beyond the parts that caused * the runtime error. */ ACPI_INFO(("Ignoring error and continuing table load")); return_ACPI_STATUS(AE_OK); } return_ACPI_STATUS(status); } /* This scope complete? */ if (acpi_ps_has_completed_scope(&(walk_state->parser_state))) { acpi_ps_pop_scope(&(walk_state->parser_state), op, &walk_state->arg_types, &walk_state->arg_count); ACPI_DEBUG_PRINT((ACPI_DB_PARSE, "Popped scope, Op=%p\n", *op)); } else { *op = NULL; } return_ACPI_STATUS(AE_OK); }
acpi_status acpi_ds_load1_end_op(struct acpi_walk_state *walk_state) { union acpi_parse_object *op; acpi_object_type object_type; acpi_status status = AE_OK; ACPI_FUNCTION_TRACE(ds_load1_end_op); op = walk_state->op; ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Op=%p State=%p\n", op, walk_state)); /* We are only interested in opcodes that have an associated name */ if (!(walk_state->op_info->flags & (AML_NAMED | AML_FIELD))) { return_ACPI_STATUS(AE_OK); } /* Get the object type to determine if we should pop the scope */ object_type = walk_state->op_info->object_type; #ifndef ACPI_NO_METHOD_EXECUTION if (walk_state->op_info->flags & AML_FIELD) { /* * If we are executing a method, do not create any namespace objects * during the load phase, only during execution. */ if (!walk_state->method_node) { if (walk_state->opcode == AML_FIELD_OP || walk_state->opcode == AML_BANK_FIELD_OP || walk_state->opcode == AML_INDEX_FIELD_OP) { status = acpi_ds_init_field_objects(op, walk_state); } } return_ACPI_STATUS(status); } /* * If we are executing a method, do not create any namespace objects * during the load phase, only during execution. */ if (!walk_state->method_node) { if (op->common.aml_opcode == AML_REGION_OP) { status = acpi_ex_create_region(op->named.data, op->named.length, (acpi_adr_space_type) ((op-> common. value. arg)-> common. value. integer), walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } else if (op->common.aml_opcode == AML_DATA_REGION_OP) { status = acpi_ex_create_region(op->named.data, op->named.length, REGION_DATA_TABLE, walk_state); if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } } #endif if (op->common.aml_opcode == AML_NAME_OP) { /* For Name opcode, get the object type from the argument */ if (op->common.value.arg) { object_type = (acpi_ps_get_opcode_info((op->common. value.arg)-> common. aml_opcode))-> object_type; /* Set node type if we have a namespace node */ if (op->common.node) { op->common.node->type = (u8) object_type; } } } /* * If we are executing a method, do not create any namespace objects * during the load phase, only during execution. */ if (!walk_state->method_node) { if (op->common.aml_opcode == AML_METHOD_OP) { /* * method_op pkg_length name_string method_flags term_list * * Note: We must create the method node/object pair as soon as we * see the method declaration. This allows later pass1 parsing * of invocations of the method (need to know the number of * arguments.) */ ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "LOADING-Method: State=%p Op=%p NamedObj=%p\n", walk_state, op, op->named.node)); if (!acpi_ns_get_attached_object(op->named.node)) { walk_state->operands[0] = ACPI_CAST_PTR(void, op->named.node); walk_state->num_operands = 1; status = acpi_ds_create_operands(walk_state, op->common.value. arg); if (ACPI_SUCCESS(status)) { status = acpi_ex_create_method(op->named. data, op->named. length, walk_state); } walk_state->operands[0] = NULL; walk_state->num_operands = 0; if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } } }
void acpi_db_display_method_info(union acpi_parse_object *start_op) { struct acpi_walk_state *walk_state; union acpi_operand_object *obj_desc; struct acpi_namespace_node *node; union acpi_parse_object *root_op; union acpi_parse_object *op; const struct acpi_opcode_info *op_info; u32 num_ops = 0; u32 num_operands = 0; u32 num_operators = 0; u32 num_remaining_ops = 0; u32 num_remaining_operands = 0; u32 num_remaining_operators = 0; u8 count_remaining = FALSE; walk_state = acpi_ds_get_current_walk_state(acpi_gbl_current_walk_list); if (!walk_state) { acpi_os_printf("There is no method currently executing\n"); return; } obj_desc = walk_state->method_desc; node = walk_state->method_node; acpi_os_printf("Currently executing control method is [%4.4s]\n", acpi_ut_get_node_name(node)); acpi_os_printf("%X Arguments, SyncLevel = %X\n", (u32)obj_desc->method.param_count, (u32)obj_desc->method.sync_level); root_op = start_op; while (root_op->common.parent) { root_op = root_op->common.parent; } op = root_op; while (op) { if (op == start_op) { count_remaining = TRUE; } num_ops++; if (count_remaining) { num_remaining_ops++; } /* Decode the opcode */ op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); switch (op_info->class) { case AML_CLASS_ARGUMENT: if (count_remaining) { num_remaining_operands++; } num_operands++; break; case AML_CLASS_UNKNOWN: /* Bad opcode or ASCII character */ continue; default: if (count_remaining) { num_remaining_operators++; } num_operators++; break; } op = acpi_ps_get_depth_next(start_op, op); } acpi_os_printf ("Method contains: %X AML Opcodes - %X Operators, %X Operands\n", num_ops, num_operators, num_operands); acpi_os_printf ("Remaining to execute: %X AML Opcodes - %X Operators, %X Operands\n", num_remaining_ops, num_remaining_operators, num_remaining_operands); }
void acpi_db_display_opcode ( acpi_walk_state *walk_state, acpi_parse_object *op) { u8 *byte_data; u32 byte_count; u32 i; const acpi_opcode_info *op_info = NULL; u32 name; if (!op) { acpi_os_printf ("<NULL OP PTR>"); } /* op and arguments */ switch (op->opcode) { case AML_BYTE_OP: if (acpi_gbl_db_opt_verbose) { acpi_os_printf ("(u8) 0x%2.2X", op->value.integer8); } else { acpi_os_printf ("0x%2.2X", op->value.integer8); } break; case AML_WORD_OP: if (acpi_gbl_db_opt_verbose) { acpi_os_printf ("(u16) 0x%4.4X", op->value.integer16); } else { acpi_os_printf ("0x%4.4X", op->value.integer16); } break; case AML_DWORD_OP: if (acpi_gbl_db_opt_verbose) { acpi_os_printf ("(u32) 0x%8.8X", op->value.integer32); } else { acpi_os_printf ("0x%8.8X", op->value.integer32); } break; case AML_QWORD_OP: if (acpi_gbl_db_opt_verbose) { acpi_os_printf ("(u64) 0x%8.8X%8.8X", op->value.integer64.hi, op->value.integer64.lo); } else { acpi_os_printf ("0x%8.8X%8.8X", op->value.integer64.hi, op->value.integer64.lo); } break; case AML_STRING_OP: if (op->value.string) { acpi_os_printf ("\"%s\"", op->value.string); } else { acpi_os_printf ("<\"NULL STRING PTR\">"); } break; case AML_INT_STATICSTRING_OP: if (op->value.string) { acpi_os_printf ("\"%s\"", op->value.string); } else { acpi_os_printf ("\"<NULL STATIC STRING PTR>\""); } break; case AML_INT_NAMEPATH_OP: acpi_db_display_namestring (op->value.name); break; case AML_INT_NAMEDFIELD_OP: acpi_os_printf ("Named_field (Length 0x%8.8X) ", op->value.integer32); break; case AML_INT_RESERVEDFIELD_OP: acpi_os_printf ("Reserved_field (Length 0x%8.8X) ", op->value.integer32); break; case AML_INT_ACCESSFIELD_OP: acpi_os_printf ("Access_field (Length 0x%8.8X) ", op->value.integer32); break; case AML_INT_BYTELIST_OP: if (acpi_gbl_db_opt_verbose) { acpi_os_printf ("Byte_list (Length 0x%8.8X) ", op->value.integer32); } else { acpi_os_printf ("0x%2.2X", op->value.integer32); byte_count = op->value.integer32; byte_data = ((acpi_parse2_object *) op)->data; for (i = 0; i < byte_count; i++) { acpi_os_printf (", 0x%2.2X", byte_data[i]); } } break; default: /* Just get the opcode name and print it */ op_info = acpi_ps_get_opcode_info (op->opcode); acpi_os_printf ("%s", op_info->name); #ifndef PARSER_ONLY if ((op->opcode == AML_INT_RETURN_VALUE_OP) && (walk_state->results) && (walk_state->results->results.num_results)) { acpi_db_decode_internal_object (walk_state->results->results.obj_desc [walk_state->results->results.num_results-1]); } #endif break; } if (!op_info) { /* If there is another element in the list, add a comma */ if (op->next) { acpi_os_printf (","); } } /* * If this is a named opcode, print the associated name value */ op_info = acpi_ps_get_opcode_info (op->opcode); if (op && (op_info->flags & AML_NAMED)) { name = acpi_ps_get_name (op); acpi_os_printf (" %4.4s", &name); if (acpi_gbl_db_opt_verbose) { acpi_os_printf (" (Path \\"); acpi_db_display_path (op); acpi_os_printf (")"); } } }
ACPI_STATUS acpi_aml_resolve_operands ( u16 opcode, ACPI_OPERAND_OBJECT **stack_ptr, ACPI_WALK_STATE *walk_state) { ACPI_OPERAND_OBJECT *obj_desc; ACPI_STATUS status = AE_OK; u8 object_type; ACPI_HANDLE temp_handle; u32 arg_types; ACPI_OPCODE_INFO *op_info; u32 this_arg_type; ACPI_OBJECT_TYPE type_needed; op_info = acpi_ps_get_opcode_info (opcode); if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { return (AE_AML_BAD_OPCODE); } arg_types = op_info->runtime_args; if (arg_types == ARGI_INVALID_OPCODE) { return (AE_AML_INTERNAL); } /* * Normal exit is with *Types == '\0' at end of string. * Function will return an exception from within the loop upon * finding an entry which is not, and cannot be converted * to, the required type; if stack underflows; or upon * finding a NULL stack entry (which "should never happen"). */ while (GET_CURRENT_ARG_TYPE (arg_types)) { if (!stack_ptr || !*stack_ptr) { return (AE_AML_INTERNAL); } /* Extract useful items */ obj_desc = *stack_ptr; /* Decode the descriptor type */ if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) { /* Node */ object_type = ((ACPI_NAMESPACE_NODE *) obj_desc)->type; } else if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_INTERNAL)) { /* ACPI internal object */ object_type = obj_desc->common.type; /* Check for bad ACPI_OBJECT_TYPE */ if (!acpi_aml_validate_object_type (object_type)) { return (AE_AML_OPERAND_TYPE); } if (object_type == (u8) INTERNAL_TYPE_REFERENCE) { /* * Decode the Reference */ op_info = acpi_ps_get_opcode_info (opcode); if (ACPI_GET_OP_TYPE (op_info) != ACPI_OP_TYPE_OPCODE) { return (AE_AML_BAD_OPCODE); } switch (obj_desc->reference.op_code) { case AML_ZERO_OP: case AML_ONE_OP: case AML_ONES_OP: case AML_DEBUG_OP: case AML_NAME_OP: case AML_INDEX_OP: case AML_ARG_OP: case AML_LOCAL_OP: break; default: return (AE_AML_OPERAND_TYPE); break; } } } else { /* Invalid descriptor */ return (AE_AML_OPERAND_TYPE); } /* * Get one argument type, point to the next */ this_arg_type = GET_CURRENT_ARG_TYPE (arg_types); INCREMENT_ARG_LIST (arg_types); /* * Handle cases where the object does not need to be * resolved to a value */ switch (this_arg_type) { case ARGI_REFERENCE: /* Reference */ case ARGI_TARGETREF: /* Need an operand of type INTERNAL_TYPE_REFERENCE */ if (VALID_DESCRIPTOR_TYPE (obj_desc, ACPI_DESC_TYPE_NAMED)) /* direct name ptr OK as-is */ { goto next_operand; } status = acpi_aml_check_object_type (INTERNAL_TYPE_REFERENCE, object_type, obj_desc); if (ACPI_FAILURE (status)) { return (status); } if (AML_NAME_OP == obj_desc->reference.op_code) { /* * Convert an indirect name ptr to direct name ptr and put * it on the stack */ temp_handle = obj_desc->reference.object; acpi_cm_remove_reference (obj_desc); (*stack_ptr) = temp_handle; } goto next_operand; break; case ARGI_ANYTYPE: /* * We don't want to resolve Index_op reference objects during * a store because this would be an implicit De_ref_of operation. * Instead, we just want to store the reference object. * -- All others must be resolved below. */ if ((opcode == AML_STORE_OP) && ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) && ((*stack_ptr)->reference.op_code == AML_INDEX_OP)) { goto next_operand; } break; } /* * Resolve this object to a value */ status = acpi_aml_resolve_to_value (stack_ptr, walk_state); if (ACPI_FAILURE (status)) { return (status); } /* * Check the resulting object (value) type */ switch (this_arg_type) { /* * For the simple cases, only one type of resolved object * is allowed */ case ARGI_NUMBER: /* Number */ /* Need an operand of type ACPI_TYPE_NUMBER */ type_needed = ACPI_TYPE_NUMBER; break; case ARGI_BUFFER: /* Need an operand of type ACPI_TYPE_BUFFER */ type_needed = ACPI_TYPE_BUFFER; break; case ARGI_MUTEX: /* Need an operand of type ACPI_TYPE_MUTEX */ type_needed = ACPI_TYPE_MUTEX; break; case ARGI_EVENT: /* Need an operand of type ACPI_TYPE_EVENT */ type_needed = ACPI_TYPE_EVENT; break; case ARGI_REGION: /* Need an operand of type ACPI_TYPE_REGION */ type_needed = ACPI_TYPE_REGION; break; case ARGI_IF: /* If */ /* Need an operand of type INTERNAL_TYPE_IF */ type_needed = INTERNAL_TYPE_IF; break; case ARGI_PACKAGE: /* Package */ /* Need an operand of type ACPI_TYPE_PACKAGE */ type_needed = ACPI_TYPE_PACKAGE; break; case ARGI_ANYTYPE: /* Any operand type will do */ type_needed = ACPI_TYPE_ANY; break; /* * The more complex cases allow multiple resolved object types */ case ARGI_STRING: /* Need an operand of type ACPI_TYPE_STRING or ACPI_TYPE_BUFFER */ if ((ACPI_TYPE_STRING != (*stack_ptr)->common.type) && (ACPI_TYPE_BUFFER != (*stack_ptr)->common.type)) { return (AE_AML_OPERAND_TYPE); } goto next_operand; break; case ARGI_DATAOBJECT: /* * ARGI_DATAOBJECT is only used by the Size_of operator. * * The ACPI specification allows Size_of to return the size of * a Buffer, String or Package. However, the MS ACPI.SYS AML * Interpreter also allows an Node reference to return without * error with a size of 4. */ /* Need a buffer, string, package or Node reference */ if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && ((*stack_ptr)->common.type != ACPI_TYPE_STRING) && ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE) && ((*stack_ptr)->common.type != INTERNAL_TYPE_REFERENCE)) { return (AE_AML_OPERAND_TYPE); } /* * If this is a reference, only allow a reference to an Node. */ if ((*stack_ptr)->common.type == INTERNAL_TYPE_REFERENCE) { if (!(*stack_ptr)->reference.node) { return (AE_AML_OPERAND_TYPE); } } goto next_operand; break; case ARGI_COMPLEXOBJ: /* Need a buffer or package */ if (((*stack_ptr)->common.type != ACPI_TYPE_BUFFER) && ((*stack_ptr)->common.type != ACPI_TYPE_PACKAGE)) { return (AE_AML_OPERAND_TYPE); } goto next_operand; break; default: /* Unknown type */ return (AE_BAD_PARAMETER); } /* * Make sure that the original object was resolved to the * required object type (Simple cases only). */ status = acpi_aml_check_object_type (type_needed, (*stack_ptr)->common.type, *stack_ptr); if (ACPI_FAILURE (status)) { return (status); } next_operand: /* * If more operands needed, decrement Stack_ptr to point * to next operand on stack */ if (GET_CURRENT_ARG_TYPE (arg_types)) { stack_ptr--; } } /* while (*Types) */ return (status); }
acpi_status acpi_ps_get_next_walk_op ( struct acpi_walk_state *walk_state, union acpi_parse_object *op, acpi_parse_upwards ascending_callback) { union acpi_parse_object *next; union acpi_parse_object *parent; union acpi_parse_object *grand_parent; acpi_status status; ACPI_FUNCTION_TRACE_PTR ("ps_get_next_walk_op", op); /* Check for a argument only if we are descending in the tree */ if (walk_state->next_op_info != ACPI_NEXT_OP_UPWARD) { /* Look for an argument or child of the current op */ next = acpi_ps_get_arg (op, 0); if (next) { /* Still going downward in tree (Op is not completed yet) */ walk_state->prev_op = op; walk_state->next_op = next; walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; return_ACPI_STATUS (AE_OK); } /* * No more children, this Op is complete. Save Next and Parent * in case the Op object gets deleted by the callback routine */ next = op->common.next; parent = op->common.parent; walk_state->op = op; walk_state->op_info = acpi_ps_get_opcode_info (op->common.aml_opcode); walk_state->opcode = op->common.aml_opcode; status = ascending_callback (walk_state); /* * If we are back to the starting point, the walk is complete. */ if (op == walk_state->origin) { /* Reached the point of origin, the walk is complete */ walk_state->prev_op = op; walk_state->next_op = NULL; return_ACPI_STATUS (status); } /* * Check for a sibling to the current op. A sibling means * we are still going "downward" in the tree. */ if (next) { /* There is a sibling, it will be next */ walk_state->prev_op = op; walk_state->next_op = next; walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; /* Continue downward */ return_ACPI_STATUS (status); } /* * Drop into the loop below because we are moving upwards in * the tree */ } else { /* * We are resuming a walk, and we were (are) going upward in the tree. * So, we want to drop into the parent loop below. */ parent = op; } /* * Look for a sibling of the current Op's parent * Continue moving up the tree until we find a node that has not been * visited, or we get back to where we started. */ while (parent) { /* We are moving up the tree, therefore this parent Op is complete */ grand_parent = parent->common.parent; next = parent->common.next; walk_state->op = parent; walk_state->op_info = acpi_ps_get_opcode_info (parent->common.aml_opcode); walk_state->opcode = parent->common.aml_opcode; status = ascending_callback (walk_state); /* * If we are back to the starting point, the walk is complete. */ if (parent == walk_state->origin) { /* Reached the point of origin, the walk is complete */ walk_state->prev_op = parent; walk_state->next_op = NULL; return_ACPI_STATUS (status); } /* * If there is a sibling to this parent (it is not the starting point * Op), then we will visit it. */ if (next) { /* found sibling of parent */ walk_state->prev_op = parent; walk_state->next_op = next; walk_state->next_op_info = ACPI_NEXT_OP_DOWNWARD; return_ACPI_STATUS (status); } /* No siblings, no errors, just move up one more level in the tree */ op = parent; parent = grand_parent; walk_state->prev_op = op; } /* * Got all the way to the top of the tree, we must be done! * However, the code should have terminated in the loop above */ walk_state->next_op = NULL; return_ACPI_STATUS (AE_OK); }
void acpi_ex_dump_object_descriptor ( union acpi_operand_object *obj_desc, u32 flags) { u32 i; ACPI_FUNCTION_TRACE ("ex_dump_object_descriptor"); if (!flags) { if (!((ACPI_LV_OBJECTS & acpi_dbg_level) && (_COMPONENT & acpi_dbg_layer))) { return_VOID; } } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) == ACPI_DESC_TYPE_NAMED) { acpi_ex_dump_node ((struct acpi_namespace_node *) obj_desc, flags); acpi_os_printf ("\nAttached Object (%p):\n", ((struct acpi_namespace_node *) obj_desc)->object); acpi_ex_dump_object_descriptor ( ((struct acpi_namespace_node *) obj_desc)->object, flags); return_VOID; } if (ACPI_GET_DESCRIPTOR_TYPE (obj_desc) != ACPI_DESC_TYPE_OPERAND) { acpi_os_printf ( "ex_dump_object_descriptor: %p is not an ACPI operand object: [%s]\n", obj_desc, acpi_ut_get_descriptor_name (obj_desc)); return_VOID; } /* Common Fields */ acpi_ex_out_string ("Type", acpi_ut_get_object_type_name (obj_desc)); acpi_ex_out_integer ("Reference Count", obj_desc->common.reference_count); acpi_ex_out_integer ("Flags", obj_desc->common.flags); /* Object-specific Fields */ switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { case ACPI_TYPE_INTEGER: acpi_os_printf ("%20s : %8.8X%8.8X\n", "Value", ACPI_FORMAT_UINT64 (obj_desc->integer.value)); break; case ACPI_TYPE_STRING: acpi_ex_out_integer ("Length", obj_desc->string.length); acpi_os_printf ("%20s : %p ", "Pointer", obj_desc->string.pointer); acpi_ut_print_string (obj_desc->string.pointer, ACPI_UINT8_MAX); acpi_os_printf ("\n"); break; case ACPI_TYPE_BUFFER: acpi_ex_out_integer ("Length", obj_desc->buffer.length); acpi_ex_out_pointer ("Pointer", obj_desc->buffer.pointer); ACPI_DUMP_BUFFER (obj_desc->buffer.pointer, obj_desc->buffer.length); break; case ACPI_TYPE_PACKAGE: acpi_ex_out_integer ("Flags", obj_desc->package.flags); acpi_ex_out_integer ("Count", obj_desc->package.count); acpi_ex_out_pointer ("Elements", obj_desc->package.elements); /* Dump the package contents */ if (obj_desc->package.count > 0) { acpi_os_printf ("\nPackage Contents:\n"); for (i = 0; i < obj_desc->package.count; i++) { acpi_os_printf ("[%.3d] %p", i, obj_desc->package.elements[i]); if (obj_desc->package.elements[i]) { acpi_os_printf (" %s", acpi_ut_get_object_type_name (obj_desc->package.elements[i])); } acpi_os_printf ("\n"); } } break; case ACPI_TYPE_DEVICE: acpi_ex_out_pointer ("Handler", obj_desc->device.handler); acpi_ex_out_pointer ("system_notify", obj_desc->device.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->device.device_notify); break; case ACPI_TYPE_EVENT: acpi_ex_out_pointer ("Semaphore", obj_desc->event.semaphore); break; case ACPI_TYPE_METHOD: acpi_ex_out_integer ("param_count", obj_desc->method.param_count); acpi_ex_out_integer ("Concurrency", obj_desc->method.concurrency); acpi_ex_out_pointer ("Semaphore", obj_desc->method.semaphore); acpi_ex_out_integer ("owning_id", obj_desc->method.owning_id); acpi_ex_out_integer ("aml_length", obj_desc->method.aml_length); acpi_ex_out_pointer ("aml_start", obj_desc->method.aml_start); break; case ACPI_TYPE_MUTEX: acpi_ex_out_integer ("sync_level", obj_desc->mutex.sync_level); acpi_ex_out_pointer ("owner_thread", obj_desc->mutex.owner_thread); acpi_ex_out_integer ("acquire_depth", obj_desc->mutex.acquisition_depth); acpi_ex_out_pointer ("Semaphore", obj_desc->mutex.semaphore); break; case ACPI_TYPE_REGION: acpi_ex_out_integer ("space_id", obj_desc->region.space_id); acpi_ex_out_integer ("Flags", obj_desc->region.flags); acpi_ex_out_address ("Address", obj_desc->region.address); acpi_ex_out_integer ("Length", obj_desc->region.length); acpi_ex_out_pointer ("Handler", obj_desc->region.handler); acpi_ex_out_pointer ("Next", obj_desc->region.next); break; case ACPI_TYPE_POWER: acpi_ex_out_integer ("system_level", obj_desc->power_resource.system_level); acpi_ex_out_integer ("resource_order", obj_desc->power_resource.resource_order); acpi_ex_out_pointer ("system_notify", obj_desc->power_resource.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->power_resource.device_notify); break; case ACPI_TYPE_PROCESSOR: acpi_ex_out_integer ("Processor ID", obj_desc->processor.proc_id); acpi_ex_out_integer ("Length", obj_desc->processor.length); acpi_ex_out_address ("Address", (acpi_physical_address) obj_desc->processor.address); acpi_ex_out_pointer ("system_notify", obj_desc->processor.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->processor.device_notify); acpi_ex_out_pointer ("Handler", obj_desc->processor.handler); break; case ACPI_TYPE_THERMAL: acpi_ex_out_pointer ("system_notify", obj_desc->thermal_zone.system_notify); acpi_ex_out_pointer ("device_notify", obj_desc->thermal_zone.device_notify); acpi_ex_out_pointer ("Handler", obj_desc->thermal_zone.handler); break; case ACPI_TYPE_BUFFER_FIELD: case ACPI_TYPE_LOCAL_REGION_FIELD: case ACPI_TYPE_LOCAL_BANK_FIELD: case ACPI_TYPE_LOCAL_INDEX_FIELD: acpi_ex_out_integer ("field_flags", obj_desc->common_field.field_flags); acpi_ex_out_integer ("access_byte_width",obj_desc->common_field.access_byte_width); acpi_ex_out_integer ("bit_length", obj_desc->common_field.bit_length); acpi_ex_out_integer ("fld_bit_offset", obj_desc->common_field.start_field_bit_offset); acpi_ex_out_integer ("base_byte_offset", obj_desc->common_field.base_byte_offset); acpi_ex_out_integer ("datum_valid_bits", obj_desc->common_field.datum_valid_bits); acpi_ex_out_integer ("end_fld_valid_bits",obj_desc->common_field.end_field_valid_bits); acpi_ex_out_integer ("end_buf_valid_bits",obj_desc->common_field.end_buffer_valid_bits); acpi_ex_out_pointer ("parent_node", obj_desc->common_field.node); switch (ACPI_GET_OBJECT_TYPE (obj_desc)) { case ACPI_TYPE_BUFFER_FIELD: acpi_ex_out_pointer ("buffer_obj", obj_desc->buffer_field.buffer_obj); break; case ACPI_TYPE_LOCAL_REGION_FIELD: acpi_ex_out_pointer ("region_obj", obj_desc->field.region_obj); break; case ACPI_TYPE_LOCAL_BANK_FIELD: acpi_ex_out_integer ("Value", obj_desc->bank_field.value); acpi_ex_out_pointer ("region_obj", obj_desc->bank_field.region_obj); acpi_ex_out_pointer ("bank_obj", obj_desc->bank_field.bank_obj); break; case ACPI_TYPE_LOCAL_INDEX_FIELD: acpi_ex_out_integer ("Value", obj_desc->index_field.value); acpi_ex_out_pointer ("Index", obj_desc->index_field.index_obj); acpi_ex_out_pointer ("Data", obj_desc->index_field.data_obj); break; default: /* All object types covered above */ break; } break; case ACPI_TYPE_LOCAL_REFERENCE: acpi_ex_out_integer ("target_type", obj_desc->reference.target_type); acpi_ex_out_string ("Opcode", (acpi_ps_get_opcode_info (obj_desc->reference.opcode))->name); acpi_ex_out_integer ("Offset", obj_desc->reference.offset); acpi_ex_out_pointer ("obj_desc", obj_desc->reference.object); acpi_ex_out_pointer ("Node", obj_desc->reference.node); acpi_ex_out_pointer ("Where", obj_desc->reference.where); break; case ACPI_TYPE_LOCAL_ADDRESS_HANDLER: acpi_ex_out_integer ("space_id", obj_desc->address_space.space_id); acpi_ex_out_pointer ("Next", obj_desc->address_space.next); acpi_ex_out_pointer ("region_list", obj_desc->address_space.region_list); acpi_ex_out_pointer ("Node", obj_desc->address_space.node); acpi_ex_out_pointer ("Context", obj_desc->address_space.context); break; case ACPI_TYPE_LOCAL_NOTIFY: acpi_ex_out_pointer ("Node", obj_desc->notify.node); acpi_ex_out_pointer ("Context", obj_desc->notify.context); break; case ACPI_TYPE_LOCAL_ALIAS: case ACPI_TYPE_LOCAL_METHOD_ALIAS: case ACPI_TYPE_LOCAL_EXTRA: case ACPI_TYPE_LOCAL_DATA: default: acpi_os_printf ( "ex_dump_object_descriptor: Display not implemented for object type %s\n", acpi_ut_get_object_type_name (obj_desc)); break; } return_VOID; }
acpi_status acpi_ps_create_op(struct acpi_walk_state *walk_state, u8 *aml_op_start, union acpi_parse_object **new_op) { acpi_status status = AE_OK; union acpi_parse_object *op; union acpi_parse_object *named_op = NULL; union acpi_parse_object *parent_scope; u8 argument_count; const struct acpi_opcode_info *op_info; ACPI_FUNCTION_TRACE_PTR(ps_create_op, walk_state); status = acpi_ps_get_aml_opcode(walk_state); if (status == AE_CTRL_PARSE_CONTINUE) { return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); } if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } /* Create Op structure and append to parent's argument list */ walk_state->op_info = acpi_ps_get_opcode_info(walk_state->opcode); op = acpi_ps_alloc_op(walk_state->opcode, aml_op_start); if (!op) { return_ACPI_STATUS(AE_NO_MEMORY); } if (walk_state->op_info->flags & AML_NAMED) { status = acpi_ps_build_named_op(walk_state, aml_op_start, op, &named_op); acpi_ps_free_op(op); #ifdef ACPI_ASL_COMPILER if (acpi_gbl_disasm_flag && walk_state->opcode == AML_EXTERNAL_OP && status == AE_NOT_FOUND) { /* * If parsing of AML_EXTERNAL_OP's name path fails, then skip * past this opcode and keep parsing. This is a much better * alternative than to abort the entire disassembler. At this * point, the parser_state is at the end of the namepath of the * external declaration opcode. Setting walk_state->Aml to * walk_state->parser_state.Aml + 2 moves increments the * walk_state->Aml past the object type and the paramcount of the * external opcode. */ walk_state->aml = walk_state->parser_state.aml + 2; walk_state->parser_state.aml = walk_state->aml; return_ACPI_STATUS(AE_CTRL_PARSE_CONTINUE); } #endif if (ACPI_FAILURE(status)) { return_ACPI_STATUS(status); } *new_op = named_op; return_ACPI_STATUS(AE_OK); } /* Not a named opcode, just allocate Op and append to parent */ if (walk_state->op_info->flags & AML_CREATE) { /* * Backup to beginning of create_XXXfield declaration * body_length is unknown until we parse the body */ op->named.data = aml_op_start; op->named.length = 0; } if (walk_state->opcode == AML_BANK_FIELD_OP) { /* * Backup to beginning of bank_field declaration * body_length is unknown until we parse the body */ op->named.data = aml_op_start; op->named.length = 0; } parent_scope = acpi_ps_get_parent_scope(&(walk_state->parser_state)); acpi_ps_append_arg(parent_scope, op); if (parent_scope) { op_info = acpi_ps_get_opcode_info(parent_scope->common.aml_opcode); if (op_info->flags & AML_HAS_TARGET) { argument_count = acpi_ps_get_argument_count(op_info->type); if (parent_scope->common.arg_list_length > argument_count) { op->common.flags |= ACPI_PARSEOP_TARGET; } } /* * Special case for both Increment() and Decrement(), where * the lone argument is both a source and a target. */ else if ((parent_scope->common.aml_opcode == AML_INCREMENT_OP) || (parent_scope->common.aml_opcode == AML_DECREMENT_OP)) { op->common.flags |= ACPI_PARSEOP_TARGET; } } if (walk_state->descending_callback != NULL) { /* * Find the object. This will either insert the object into * the namespace or simply look it up */ walk_state->op = *new_op = op; status = walk_state->descending_callback(walk_state, &op); status = acpi_ps_next_parse_state(walk_state, op, status); if (status == AE_CTRL_PENDING) { status = AE_CTRL_PARSE_PENDING; } } return_ACPI_STATUS(status); }