acpi_status acpi_ds_load2_end_op()

in acpica/dswload2.c [369:745]


acpi_status acpi_ds_load2_end_op(struct acpi_walk_state *walk_state)
{
	union acpi_parse_object *op;
	acpi_status status = AE_OK;
	acpi_object_type object_type;
	struct acpi_namespace_node *node;
	union acpi_parse_object *arg;
	struct acpi_namespace_node *new_node;
	u32 i;
	u8 region_space;
#ifdef ACPI_EXEC_APP
	union acpi_operand_object *obj_desc;
	char *namepath;
#endif

	ACPI_FUNCTION_TRACE(ds_load2_end_op);

	op = walk_state->op;
	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH, "Opcode [%s] Op %p State %p\n",
			  walk_state->op_info->name, op, walk_state));

	/* Check if opcode had an associated namespace object */

	if (!(walk_state->op_info->flags & AML_NSOBJECT)) {
		return_ACPI_STATUS(AE_OK);
	}

	if (op->common.aml_opcode == AML_SCOPE_OP) {
		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "Ending scope Op=%p State=%p\n", op,
				  walk_state));
	}

	object_type = walk_state->op_info->object_type;

	/*
	 * Get the Node/name from the earlier lookup
	 * (It was saved in the *op structure)
	 */
	node = op->common.node;

	/*
	 * Put the Node on the object stack (Contains the ACPI Name of
	 * this object)
	 */
	walk_state->operands[0] = (void *)node;
	walk_state->num_operands = 1;

	/* Pop the scope stack */

	if (acpi_ns_opens_scope(object_type) &&
	    (op->common.aml_opcode != AML_INT_METHODCALL_OP)) {
		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);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}
	}

	/*
	 * Named operations are as follows:
	 *
	 * AML_ALIAS
	 * AML_BANKFIELD
	 * AML_CREATEBITFIELD
	 * AML_CREATEBYTEFIELD
	 * AML_CREATEDWORDFIELD
	 * AML_CREATEFIELD
	 * AML_CREATEQWORDFIELD
	 * AML_CREATEWORDFIELD
	 * AML_DATA_REGION
	 * AML_DEVICE
	 * AML_EVENT
	 * AML_FIELD
	 * AML_INDEXFIELD
	 * AML_METHOD
	 * AML_METHODCALL
	 * AML_MUTEX
	 * AML_NAME
	 * AML_NAMEDFIELD
	 * AML_OPREGION
	 * AML_POWERRES
	 * AML_PROCESSOR
	 * AML_SCOPE
	 * AML_THERMALZONE
	 */

	ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
			  "Create-Load [%s] State=%p Op=%p NamedObj=%p\n",
			  acpi_ps_get_opcode_name(op->common.aml_opcode),
			  walk_state, op, node));

	/* Decode the opcode */

	arg = op->common.value.arg;

	switch (walk_state->op_info->type) {

	case AML_TYPE_CREATE_FIELD:
		/*
		 * Create the field object, but the field buffer and index must
		 * be evaluated later during the execution phase
		 */
		status = acpi_ds_create_buffer_field(op, walk_state);
		if (ACPI_FAILURE(status)) {
			ACPI_EXCEPTION((AE_INFO, status,
					"CreateBufferField failure"));
			goto cleanup;
			}
		break;

	case AML_TYPE_NAMED_FIELD:
		/*
		 * If we are executing a method, initialize the field
		 */
		if (walk_state->method_node) {
			status = acpi_ds_init_field_objects(op, walk_state);
		}

		switch (op->common.aml_opcode) {
		case AML_INDEX_FIELD_OP:

			status =
			    acpi_ds_create_index_field(op,
						       (acpi_handle)arg->common.
						       node, walk_state);
			break;

		case AML_BANK_FIELD_OP:

			status =
			    acpi_ds_create_bank_field(op, arg->common.node,
						      walk_state);
			break;

		case AML_FIELD_OP:

			status =
			    acpi_ds_create_field(op, arg->common.node,
						 walk_state);
			break;

		default:

			/* All NAMED_FIELD opcodes must be handled above */
			break;
		}
		break;

	case AML_TYPE_NAMED_SIMPLE:

		status = acpi_ds_create_operands(walk_state, arg);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}

		switch (op->common.aml_opcode) {
		case AML_PROCESSOR_OP:

			status = acpi_ex_create_processor(walk_state);
			break;

		case AML_POWER_RESOURCE_OP:

			status = acpi_ex_create_power_resource(walk_state);
			break;

		case AML_MUTEX_OP:

			status = acpi_ex_create_mutex(walk_state);
			break;

		case AML_EVENT_OP:

			status = acpi_ex_create_event(walk_state);
			break;

		case AML_ALIAS_OP:

			status = acpi_ex_create_alias(walk_state);
			break;

		default:

			/* Unknown opcode */

			status = AE_OK;
			goto cleanup;
		}

		/* Delete operands */

		for (i = 1; i < walk_state->num_operands; i++) {
			acpi_ut_remove_reference(walk_state->operands[i]);
			walk_state->operands[i] = NULL;
		}

		break;

	case AML_TYPE_NAMED_COMPLEX:

		switch (op->common.aml_opcode) {
		case AML_REGION_OP:
		case AML_DATA_REGION_OP:

			if (op->common.aml_opcode == AML_REGION_OP) {
				region_space = (acpi_adr_space_type)
				    ((op->common.value.arg)->common.value.
				     integer);
			} else {
				region_space = ACPI_ADR_SPACE_DATA_TABLE;
			}

			/*
			 * The op_region is not fully parsed at this time. The only valid
			 * argument is the space_id. (We must save the address of the
			 * AML of the address and length operands)
			 *
			 * If we have a valid region, initialize it. The namespace is
			 * unlocked at this point.
			 *
			 * Need to unlock interpreter if it is locked (if we are running
			 * a control method), in order to allow _REG methods to be run
			 * during acpi_ev_initialize_region.
			 */
			if (walk_state->method_node) {
				/*
				 * Executing a method: initialize the region and unlock
				 * the interpreter
				 */
				status = acpi_ex_create_region(op->named.data,
							       op->named.length,
							       region_space,
							       walk_state);
				if (ACPI_FAILURE(status)) {
					return_ACPI_STATUS(status);
				}
			}

			status =
			    acpi_ev_initialize_region
			    (acpi_ns_get_attached_object(node));
			break;

		case AML_NAME_OP:

			status = acpi_ds_create_node(walk_state, node, op);
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}
#ifdef ACPI_EXEC_APP
			/*
			 * acpi_exec support for namespace initialization file (initialize
			 * Name opcodes in this code.)
			 */
			namepath = acpi_ns_get_external_pathname(node);
			status = ae_lookup_init_file_entry(namepath, &obj_desc);
			if (ACPI_SUCCESS(status)) {

				/* Detach any existing object, attach new object */

				if (node->object) {
					acpi_ns_detach_object(node);
				}
				acpi_ns_attach_object(node, obj_desc,
						      obj_desc->common.type);
			}
			ACPI_FREE(namepath);
			status = AE_OK;
#endif
			break;

		case 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);
				}
			}
			break;

		default:

			/* All NAMED_COMPLEX opcodes must be handled above */
			break;
		}
		break;

	case AML_CLASS_INTERNAL:

		/* case AML_INT_NAMEPATH_OP: */
		break;

	case AML_CLASS_METHOD_CALL:

		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "RESOLVING-MethodCall: State=%p Op=%p NamedObj=%p\n",
				  walk_state, op, node));

		/*
		 * Lookup the method name and save the Node
		 */
		status =
		    acpi_ns_lookup(walk_state->scope_info,
				   arg->common.value.string, ACPI_TYPE_ANY,
				   ACPI_IMODE_LOAD_PASS2,
				   ACPI_NS_SEARCH_PARENT |
				   ACPI_NS_DONT_OPEN_SCOPE, walk_state,
				   &(new_node));
		if (ACPI_SUCCESS(status)) {
			/*
			 * Make sure that what we found is indeed a method
			 * We didn't search for a method on purpose, to see if the name
			 * would resolve
			 */
			if (new_node->type != ACPI_TYPE_METHOD) {
				status = AE_AML_OPERAND_TYPE;
			}

			/* We could put the returned object (Node) on the object stack for
			 * later, but for now, we will put it in the "op" object that the
			 * parser uses, so we can get it again at the end of this scope
			 */
			op->common.node = new_node;
		} else {
			ACPI_ERROR_NAMESPACE(walk_state->scope_info,
					     arg->common.value.string, status);
		}
		break;

	default:

		break;
	}

cleanup:

	/* Remove the Node pushed at the very beginning */

	walk_state->operands[0] = NULL;
	walk_state->num_operands = 0;
	return_ACPI_STATUS(status);
}