Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 773069d4 authored by Bob Moore's avatar Bob Moore Committed by Len Brown
Browse files

ACPICA: Several fixes for internal method result stack



fixes STACK_OVERFLOW exception on nested method calls. internal
bugzilla 262 and 275.

Signed-off-by: default avatarBob Moore <robert.moore@intel.com>
Signed-off-by: default avatarAlexey Starikovskiy <astarikovskiy@suse.de>
Signed-off-by: default avatarLen Brown <len.brown@intel.com>
parent 4b119e21
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -808,6 +808,12 @@ acpi_ds_eval_data_object_operands(struct acpi_walk_state *walk_state,

	/* The first operand (for all of these data objects) is the length */

	/*
	 * Set proper index into operand stack for acpi_ds_obj_stack_push
	 * invoked inside acpi_ds_create_operand.
	 */
	walk_state->operand_index = walk_state->num_operands;

	status = acpi_ds_create_operand(walk_state, op->common.value.arg, 1);
	if (ACPI_FAILURE(status)) {
		return_ACPI_STATUS(status);
@@ -1070,8 +1076,7 @@ acpi_ds_exec_end_control_op(struct acpi_walk_state * walk_state,
			 * is set to anything other than zero!
			 */
			walk_state->return_desc = walk_state->operands[0];
		} else if ((walk_state->results) &&
			   (walk_state->results->results.num_results > 0)) {
		} else if (walk_state->result_count) {

			/* Since we have a real Return(), delete any implicit return */

+38 −14
Original line number Diff line number Diff line
@@ -630,9 +630,7 @@ acpi_ds_create_operand(struct acpi_walk_state *walk_state,
			 * Use value that was already previously returned
			 * by the evaluation of this argument
			 */
			status =
			    acpi_ds_result_pop_from_bottom(&obj_desc,
							   walk_state);
			status = acpi_ds_result_pop(&obj_desc, walk_state);
			if (ACPI_FAILURE(status)) {
				/*
				 * Only error is underflow, and this indicates
@@ -698,27 +696,54 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
{
	acpi_status status = AE_OK;
	union acpi_parse_object *arg;
	u32 arg_count = 0;
	union acpi_parse_object *arguments[ACPI_OBJ_NUM_OPERANDS];
	u8 arg_count = 0;
	u8 count = 0;
	u8 index = walk_state->num_operands;
	u8 i;

	ACPI_FUNCTION_TRACE_PTR(ds_create_operands, first_arg);

	/* For all arguments in the list... */
	/* Get all arguments in the list */

	arg = first_arg;
	while (arg) {
		status = acpi_ds_create_operand(walk_state, arg, arg_count);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		if (index >= ACPI_OBJ_NUM_OPERANDS) {
			return_ACPI_STATUS(AE_BAD_DATA);
		}

		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "Arg #%d (%p) done, Arg1=%p\n", arg_count,
				  arg, first_arg));
		arguments[index] = arg;
		walk_state->operands[index] = NULL;

		/* Move on to next argument, if any */

		arg = arg->common.next;
		arg_count++;
		index++;
	}

	index--;

	/* It is the appropriate order to get objects from the Result stack */

	for (i = 0; i < arg_count; i++) {
		arg = arguments[index];

		/* Force the filling of the operand stack in inverse order */

		walk_state->operand_index = index;

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

		count++;
		index--;

		ACPI_DEBUG_PRINT((ACPI_DB_DISPATCH,
				  "Arg #%d (%p) done, Arg1=%p\n", index, arg,
				  first_arg));
	}

	return_ACPI_STATUS(status);
@@ -729,9 +754,8 @@ acpi_ds_create_operands(struct acpi_walk_state *walk_state,
	 * pop everything off of the operand stack and delete those
	 * objects
	 */
	(void)acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);
	acpi_ds_obj_stack_pop_and_delete(arg_count, walk_state);

	ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d",
			(arg_count + 1)));
	ACPI_EXCEPTION((AE_INFO, status, "While creating Arg %d", index));
	return_ACPI_STATUS(status);
}
+2 −41
Original line number Diff line number Diff line
@@ -285,11 +285,6 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
	switch (opcode_class) {
	case AML_CLASS_CONTROL:

		status = acpi_ds_result_stack_push(walk_state);
		if (ACPI_FAILURE(status)) {
			goto error_exit;
		}

		status = acpi_ds_exec_begin_control_op(walk_state, op);
		break;

@@ -305,20 +300,11 @@ acpi_ds_exec_begin_op(struct acpi_walk_state *walk_state,
			status = acpi_ds_load2_begin_op(walk_state, NULL);
		}

		if (op->common.aml_opcode == AML_REGION_OP) {
			status = acpi_ds_result_stack_push(walk_state);
		}
		break;

	case AML_CLASS_EXECUTE:
	case AML_CLASS_CREATE:
		/*
		 * Most operators with arguments (except create_xxx_field operators)
		 * Start a new result/operand state
		 */
		if (walk_state->op_info->object_type != ACPI_TYPE_BUFFER_FIELD) {
			status = acpi_ds_result_stack_push(walk_state);
		}

		break;

	default:
@@ -374,6 +360,7 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
	/* Init the walk state */

	walk_state->num_operands = 0;
	walk_state->operand_index = 0;
	walk_state->return_desc = NULL;
	walk_state->result_obj = NULL;

@@ -400,13 +387,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
			goto cleanup;
		}

		/* Done with this result state (Now that operand stack is built) */

		status = acpi_ds_result_stack_pop(walk_state);
		if (ACPI_FAILURE(status)) {
			goto cleanup;
		}

		/*
		 * All opcodes require operand resolution, with the only exceptions
		 * being the object_type and size_of operators.
@@ -487,16 +467,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)

			status = acpi_ds_exec_end_control_op(walk_state, op);

			/* Make sure to properly pop the result stack */

			if (ACPI_SUCCESS(status)) {
				status = acpi_ds_result_stack_pop(walk_state);
			} else if (status == AE_CTRL_PENDING) {
				status = acpi_ds_result_stack_pop(walk_state);
				if (ACPI_SUCCESS(status)) {
					status = AE_CTRL_PENDING;
				}
			}
			break;

		case AML_TYPE_METHOD_CALL:
@@ -632,13 +602,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
				break;
			}

			/* Done with result state (Now that operand stack is built) */

			status = acpi_ds_result_stack_pop(walk_state);
			if (ACPI_FAILURE(status)) {
				goto cleanup;
			}

			/*
			 * If a result object was returned from above, push it on the
			 * current result stack
@@ -671,8 +634,6 @@ acpi_status acpi_ds_exec_end_op(struct acpi_walk_state *walk_state)
				if (ACPI_FAILURE(status)) {
					break;
				}

				status = acpi_ds_result_stack_pop(walk_state);
			}
			break;

+111 −402

File changed.

Preview size limit exceeded, changes collapsed.

+0 −11
Original line number Diff line number Diff line
@@ -603,13 +603,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
			acpi_ps_pop_scope(&(walk_state->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 */
@@ -640,10 +633,6 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
				if (ACPI_FAILURE(status2)) {
					return_ACPI_STATUS(status2);
				}
				status2 = acpi_ds_result_stack_pop(walk_state);
				if (ACPI_FAILURE(status2)) {
					return_ACPI_STATUS(status2);
				}

				acpi_ut_delete_generic_state
				    (acpi_ut_pop_generic_state
Loading