Skip to content

Commit 5088814

Browse files
Erik Schmaussrafaeljw
authored andcommitted
ACPICA: AML parser: attempt to continue loading table after error
This change alters the parser so that the table load does not abort upon an error. Notable changes: If there is an error while parsing an element of the termlist, we will skip parsing the current termlist element and continue parsing to the next opcode in the termlist. If we get an error while parsing the conditional of If/Else/While or the device name of Scope, we will skip the body of the statement all together and pop the parser_state. If we get an error while parsing the base offset and length of an operation region declaration, we will remove the operation region from the namespace. Signed-off-by: Erik Schmauss <[email protected]> Signed-off-by: Rafael J. Wysocki <[email protected]>
1 parent 3877b2c commit 5088814

File tree

3 files changed

+85
-6
lines changed

3 files changed

+85
-6
lines changed

drivers/acpi/acpica/psloop.c

Lines changed: 50 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -515,6 +515,22 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
515515
if (ACPI_FAILURE(status)) {
516516
return_ACPI_STATUS(status);
517517
}
518+
if (walk_state->opcode == AML_SCOPE_OP) {
519+
/*
520+
* If the scope op fails to parse, skip the body of the
521+
* scope op because the parse failure indicates that the
522+
* device may not exist.
523+
*/
524+
walk_state->parser_state.aml =
525+
walk_state->aml + 1;
526+
walk_state->parser_state.aml =
527+
acpi_ps_get_next_package_end
528+
(&walk_state->parser_state);
529+
walk_state->aml =
530+
walk_state->parser_state.aml;
531+
ACPI_ERROR((AE_INFO,
532+
"Skipping Scope block"));
533+
}
518534

519535
continue;
520536
}
@@ -557,7 +573,40 @@ acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
557573
if (ACPI_FAILURE(status)) {
558574
return_ACPI_STATUS(status);
559575
}
560-
576+
if ((walk_state->control_state) &&
577+
((walk_state->control_state->control.
578+
opcode == AML_IF_OP)
579+
|| (walk_state->control_state->control.
580+
opcode == AML_WHILE_OP))) {
581+
/*
582+
* If the if/while op fails to parse, we will skip parsing
583+
* the body of the op.
584+
*/
585+
parser_state->aml =
586+
walk_state->control_state->control.
587+
aml_predicate_start + 1;
588+
parser_state->aml =
589+
acpi_ps_get_next_package_end
590+
(parser_state);
591+
walk_state->aml = parser_state->aml;
592+
593+
ACPI_ERROR((AE_INFO,
594+
"Skipping While/If block"));
595+
if (*walk_state->aml == AML_ELSE_OP) {
596+
ACPI_ERROR((AE_INFO,
597+
"Skipping Else block"));
598+
walk_state->parser_state.aml =
599+
walk_state->aml + 1;
600+
walk_state->parser_state.aml =
601+
acpi_ps_get_next_package_end
602+
(parser_state);
603+
walk_state->aml =
604+
parser_state->aml;
605+
}
606+
ACPI_FREE(acpi_ut_pop_generic_state
607+
(&walk_state->control_state));
608+
}
609+
op = NULL;
561610
continue;
562611
}
563612
}

drivers/acpi/acpica/psobject.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#include "acparser.h"
1313
#include "amlcode.h"
1414
#include "acconvert.h"
15+
#include "acnamesp.h"
1516

1617
#define _COMPONENT ACPI_PARSER
1718
ACPI_MODULE_NAME("psobject")
@@ -549,6 +550,21 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
549550

550551
do {
551552
if (*op) {
553+
/*
554+
* These Opcodes need to be removed from the namespace because they
555+
* get created even if these opcodes cannot be created due to
556+
* errors.
557+
*/
558+
if (((*op)->common.aml_opcode == AML_REGION_OP)
559+
|| ((*op)->common.aml_opcode ==
560+
AML_DATA_REGION_OP)) {
561+
acpi_ns_delete_children((*op)->common.
562+
node);
563+
acpi_ns_remove_node((*op)->common.node);
564+
(*op)->common.node = NULL;
565+
acpi_ps_delete_parse_tree(*op);
566+
}
567+
552568
status2 =
553569
acpi_ps_complete_this_op(walk_state, *op);
554570
if (ACPI_FAILURE(status2)) {
@@ -574,6 +590,20 @@ acpi_ps_complete_op(struct acpi_walk_state *walk_state,
574590
#endif
575591
walk_state->prev_op = NULL;
576592
walk_state->prev_arg_types = walk_state->arg_types;
593+
594+
if (walk_state->parse_flags & ACPI_PARSE_MODULE_LEVEL) {
595+
/*
596+
* There was something that went wrong while executing code at the
597+
* module-level. We need to skip parsing whatever caused the
598+
* error and keep going. One runtime error during the table load
599+
* should not cause the entire table to not be loaded. This is
600+
* because there could be correct AML beyond the parts that caused
601+
* the runtime error.
602+
*/
603+
ACPI_ERROR((AE_INFO,
604+
"Ignore error and continue table load"));
605+
return_ACPI_STATUS(AE_OK);
606+
}
577607
return_ACPI_STATUS(status);
578608
}
579609

drivers/acpi/acpica/uterror.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -182,20 +182,20 @@ acpi_ut_prefixed_namespace_error(const char *module_name,
182182
switch (lookup_status) {
183183
case AE_ALREADY_EXISTS:
184184

185-
acpi_os_printf(ACPI_MSG_BIOS_ERROR);
185+
acpi_os_printf("\n" ACPI_MSG_BIOS_ERROR);
186186
message = "Failure creating";
187187
break;
188188

189189
case AE_NOT_FOUND:
190190

191-
acpi_os_printf(ACPI_MSG_BIOS_ERROR);
192-
message = "Failure looking up";
191+
acpi_os_printf("\n" ACPI_MSG_BIOS_ERROR);
192+
message = "Could not resolve";
193193
break;
194194

195195
default:
196196

197-
acpi_os_printf(ACPI_MSG_ERROR);
198-
message = "Failure looking up";
197+
acpi_os_printf("\n" ACPI_MSG_ERROR);
198+
message = "Failure resolving";
199199
break;
200200
}
201201

0 commit comments

Comments
 (0)