acpi_status acpi_ds_load1_end_op()

in acpica/dswload.c [396:596]


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;
#ifdef ACPI_ASL_COMPILER
	u8 param_count;
#endif

	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));

	/*
	 * Disassembler: handle create field operators here.
	 *
	 * create_buffer_field is a deferred op that is typically processed in load
	 * pass 2. However, disassembly of control method contents walk the parse
	 * tree with ACPI_PARSE_LOAD_PASS1 and AML_CREATE operators are processed
	 * in a later walk. This is a problem when there is a control method that
	 * has the same name as the AML_CREATE object. In this case, any use of the
	 * name segment will be detected as a method call rather than a reference
	 * to a buffer field.
	 *
	 * This earlier creation during disassembly solves this issue by inserting
	 * the named object in the ACPI namespace so that references to this name
	 * would be a name string rather than a method call.
	 */
	if ((walk_state->parse_flags & ACPI_PARSE_DISASSEMBLE) &&
	    (walk_state->op_info->flags & AML_CREATE)) {
		status = acpi_ds_create_buffer_field(op, walk_state);
		return_ACPI_STATUS(status);
	}

	/* 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;

	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,
						  ACPI_ADR_SPACE_DATA_TABLE,
						  walk_state);
			if (ACPI_FAILURE(status)) {
				return_ACPI_STATUS(status);
			}
		}
	}

	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;
			}
		}
	}
#ifdef ACPI_ASL_COMPILER
	/*
	 * For external opcode, get the object type from the argument and
	 * get the parameter count from the argument's next.
	 */
	if (acpi_gbl_disasm_flag &&
	    op->common.node && op->common.aml_opcode == AML_EXTERNAL_OP) {
		/*
		 * Note, if this external is not a method
		 * Op->Common.Value.Arg->Common.Next->Common.Value.Integer == 0
		 * Therefore, param_count will be 0.
		 */
		param_count =
		    (u8)op->common.value.arg->common.next->common.value.integer;
		object_type = (u8)op->common.value.arg->common.value.integer;
		op->common.node->flags |= ANOBJ_IS_EXTERNAL;
		op->common.node->type = (u8)object_type;

		acpi_dm_create_subobject_for_external((u8)object_type,
						      &op->common.node,
						      param_count);

		/*
		 * Add the external to the external list because we may be
		 * emitting code based off of the items within the external list.
		 */
		acpi_dm_add_op_to_external_list(op, op->named.path,
						(u8)object_type, param_count,
						ACPI_EXT_ORIGIN_FROM_OPCODE |
						ACPI_EXT_RESOLVED_REFERENCE);
	}
#endif

	/*
	 * 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);
				}
			}
		}
	}

	/* Pop the scope stack (only if loading a table) */

	if (!walk_state->method_node &&
	    op->common.aml_opcode != AML_EXTERNAL_OP &&
	    acpi_ns_opens_scope(object_type)) {
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "(%s): Popping scope for Op %p\n",
				  acpi_ut_get_type_name(object_type), op));

		status = acpi_ds_scope_stack_pop(walk_state);
	}

	return_ACPI_STATUS(status);
}