]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
ACPICA: Abort AML bytecode execution when executing AML_FATAL_OP
authorArmin Wolf <W_Armin@gmx.de>
Wed, 14 Jan 2026 12:25:33 +0000 (13:25 +0100)
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>
Thu, 15 Jan 2026 17:17:48 +0000 (18:17 +0100)
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
drivers/acpi/acpica/exoparg3.c

index bf08110ed6d2578a942b032377bf7b8df945add6..c8c8c4e49563ef9fc8a924bb81a2416e293e403d 100644 (file)
@@ -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 = 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;
-               }
+               fatal.type = (u32)operand[0]->integer.value;
+               fatal.code = (u32)operand[1]->integer.value;
+               fatal.argument = (u32)operand[2]->integer.value;
 
-               /* Always signal the OS! */
+               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));
 
-               status = acpi_os_signal(ACPI_SIGNAL_FATAL, fatal);
+               /* Always signal the OS! */
 
-               /* Might return while OS is shutting down, just continue */
+               acpi_os_signal(ACPI_SIGNAL_FATAL, &fatal);
 
-               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);
 }
 
 /*******************************************************************************