ACPICA: Abort AML bytecode execution when executing AML_FATAL_OP
The ACPI specification states that when executing AML_FATAL_OP, the OS should log the fatal error event and shutdown in a timely fashion. Windows complies with this requirement by immediatly entering a Bso_d, effectively aborting the execution of the AML bytecode in question. ACPICA however might continue with the AML bytecode execution should acpi_os_signal() simply return AE_OK. This will cause issues because ACPI BIOS implementations might assume that the Fatal() operator does not return. Fix this by aborting the AML bytecode execution in such a case by returning AE_ERROR. Also turn struct acpi_signal_fatal_info into a local variable because of its small size (12 bytes) and to ensure that acpi_os_signal() always receives valid information about the fatal ACPI BIOS error. Link: https://github.com/acpica/acpica/commit/d516c7758ba6 Signed-off-by: Armin Wolf <W_Armin@gmx.de> Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com> Link: https://patch.msgid.link/3325491.5fSG56mABF@rafael.j.wysocki
This commit is contained in:
parent
30c2a333aa
commit
026ad376a6
|
|
@ -10,6 +10,7 @@
|
|||
#include <acpi/acpi.h>
|
||||
#include "accommon.h"
|
||||
#include "acinterp.h"
|
||||
#include <acpi/acoutput.h>
|
||||
#include "acparser.h"
|
||||
#include "amlcode.h"
|
||||
|
||||
|
|
@ -51,8 +52,7 @@ ACPI_MODULE_NAME("exoparg3")
|
|||
acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
|
||||
{
|
||||
union acpi_operand_object **operand = &walk_state->operands[0];
|
||||
struct acpi_signal_fatal_info *fatal;
|
||||
acpi_status status = AE_OK;
|
||||
struct acpi_signal_fatal_info fatal;
|
||||
|
||||
ACPI_FUNCTION_TRACE_STR(ex_opcode_3A_0T_0R,
|
||||
acpi_ps_get_opcode_name(walk_state->opcode));
|
||||
|
|
@ -60,28 +60,23 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
|
|||
switch (walk_state->opcode) {
|
||||
case AML_FATAL_OP: /* Fatal (fatal_type fatal_code fatal_arg) */
|
||||
|
||||
ACPI_DEBUG_PRINT((ACPI_DB_INFO,
|
||||
"FatalOp: Type %X Code %X Arg %X "
|
||||
"<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<<\n",
|
||||
(u32)operand[0]->integer.value,
|
||||
(u32)operand[1]->integer.value,
|
||||
(u32)operand[2]->integer.value));
|
||||
fatal.type = (u32)operand[0]->integer.value;
|
||||
fatal.code = (u32)operand[1]->integer.value;
|
||||
fatal.argument = (u32)operand[2]->integer.value;
|
||||
|
||||
fatal = ACPI_ALLOCATE(sizeof(struct acpi_signal_fatal_info));
|
||||
if (fatal) {
|
||||
fatal->type = (u32) operand[0]->integer.value;
|
||||
fatal->code = (u32) operand[1]->integer.value;
|
||||
fatal->argument = (u32) operand[2]->integer.value;
|
||||
}
|
||||
ACPI_BIOS_ERROR((AE_INFO,
|
||||
"Fatal ACPI BIOS error (Type 0x%X Code 0x%X Arg 0x%X)\n",
|
||||
fatal.type, fatal.code, fatal.argument));
|
||||
|
||||
/* Always signal the OS! */
|
||||
|
||||
status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);
|
||||
acpi_os_signal(ACPI_SIGNAL_FATAL, &fatal);
|
||||
|
||||
/* Might return while OS is shutting down, just continue */
|
||||
|
||||
ACPI_FREE(fatal);
|
||||
goto cleanup;
|
||||
/*
|
||||
* Might return while OS is shutting down, so abort the AML execution
|
||||
* by returning an error.
|
||||
*/
|
||||
return_ACPI_STATUS(AE_ERROR);
|
||||
|
||||
case AML_EXTERNAL_OP:
|
||||
/*
|
||||
|
|
@ -93,21 +88,16 @@ acpi_status acpi_ex_opcode_3A_0T_0R(struct acpi_walk_state *walk_state)
|
|||
* wrong if an external opcode ever gets here.
|
||||
*/
|
||||
ACPI_ERROR((AE_INFO, "Executed External Op"));
|
||||
status = AE_OK;
|
||||
goto cleanup;
|
||||
|
||||
return_ACPI_STATUS(AE_OK);
|
||||
|
||||
default:
|
||||
|
||||
ACPI_ERROR((AE_INFO, "Unknown AML opcode 0x%X",
|
||||
walk_state->opcode));
|
||||
|
||||
status = AE_AML_BAD_OPCODE;
|
||||
goto cleanup;
|
||||
return_ACPI_STATUS(AE_AML_BAD_OPCODE);
|
||||
}
|
||||
|
||||
cleanup:
|
||||
|
||||
return_ACPI_STATUS(status);
|
||||
}
|
||||
|
||||
/*******************************************************************************
|
||||
|
|
|
|||
Loading…
Reference in New Issue