Message ID | 1401371962-32375-2-git-send-email-colin.king@canonical.com |
---|---|
State | Rejected |
Headers | show |
On 05/29/2014 09:59 PM, Colin King wrote: > From: Colin Ian King <colin.king@canonical.com> > > Reduce the number of false positives by including in all tables > to help resolve external references. This requires a re-working > of the two iASL interfaces and consumers of the API. > > Signed-off-by: Colin Ian King <colin.king@canonical.com> > --- > src/acpi/osilinux/osilinux.c | 7 + > src/acpi/syntaxcheck/syntaxcheck.c | 46 ++--- > src/acpica/source/compiler/fwts_iasl_interface.c | 31 ++- > src/acpica/source/compiler/fwts_iasl_interface.h | 2 +- > src/hpet/hpet_check/hpet_check.c | 14 +- > src/lib/include/fwts_iasl.h | 8 +- > src/lib/src/fwts_iasl.c | 232 +++++++++++++++++------ > 7 files changed, 241 insertions(+), 99 deletions(-) > > diff --git a/src/acpi/osilinux/osilinux.c b/src/acpi/osilinux/osilinux.c > index 04a731a..857d141 100644 > --- a/src/acpi/osilinux/osilinux.c > +++ b/src/acpi/osilinux/osilinux.c > @@ -36,10 +36,17 @@ static int osilinux_test1(fwts_framework *fw) > int dumpdepth = 0; > int found = 0; > > + if (fwts_iasl_init(fw) != FWTS_OK) { > + fwts_aborted(fw, "Failure to initialise iasl, aborting."); > + fwts_iasl_deinit(); > + return FWTS_ERROR; > + } > if (fwts_iasl_disassemble(fw, "DSDT", 0, &disassembly) != FWTS_OK) { > fwts_aborted(fw, "Cannot disassemble DSDT with iasl."); > + fwts_iasl_deinit(); > return FWTS_ERROR; > } > + fwts_iasl_deinit(); > > if (disassembly == NULL) { > fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoDSDT", > diff --git a/src/acpi/syntaxcheck/syntaxcheck.c b/src/acpi/syntaxcheck/syntaxcheck.c > index 5281031..5e4f7d4 100644 > --- a/src/acpi/syntaxcheck/syntaxcheck.c > +++ b/src/acpi/syntaxcheck/syntaxcheck.c > @@ -28,6 +28,7 @@ > #include <json/json.h> > > #define ASL_EXCEPTIONS /* so we can include AslErrorLevel in aslmessages.h */ > +#define MAX_TABLES 128 > > #include "aslmessages.h" > > @@ -226,6 +227,10 @@ static int syntaxcheck_init(fwts_framework *fw) > { > (void)syntaxcheck_load_advice(fw); > > + if (fwts_iasl_init(fw) != FWTS_OK) { > + fwts_aborted(fw, "Failure to initialise iasl, aborting."); > + return FWTS_ERROR; > + } > return FWTS_OK; > } > > @@ -233,6 +238,7 @@ static int syntaxcheck_deinit(fwts_framework *fw) > { > FWTS_UNUSED(fw); > > + fwts_iasl_deinit(); > syntaxcheck_free_advice(); > > return FWTS_OK; > @@ -456,27 +462,19 @@ static void syntaxcheck_give_advice(fwts_framework *fw, uint32_t error_code) > /* > * syntaxcheck_table() > * disassemble and reassemble a table, check for errors. which indicates the Nth > - * table, for example, SSDT may have tables 1..N > + * table > */ > -static int syntaxcheck_table(fwts_framework *fw, char *tablename, int which) > +static int syntaxcheck_table(fwts_framework *fw, const int which) > { > fwts_list_link *item; > int errors = 0; > int warnings = 0; > int remarks = 0; > - fwts_acpi_table_info *table; > + char *tablename = fwts_iasl_aml_name(which); > fwts_list *iasl_stdout, *iasl_stderr, *iasl_disassembly; > > - if (fwts_acpi_find_table(fw, tablename, which, &table) != FWTS_OK) { > - fwts_aborted(fw, "Cannot load ACPI table %s.", tablename); > - return FWTS_ERROR; > - } > - > - if (table == NULL) > - return FWTS_NO_TABLE; /* Table does not exist */ > - > - if (fwts_iasl_reassemble(fw, table->data, table->length, > - &iasl_disassembly, &iasl_stdout, &iasl_stderr) != FWTS_OK) { > + if (fwts_iasl_reassemble(fw, which, > + &iasl_disassembly, &iasl_stdout, &iasl_stderr) != FWTS_OK) { > fwts_aborted(fw, "Cannot re-assasemble with iasl."); > return FWTS_ERROR; > } > @@ -611,34 +609,24 @@ static int syntaxcheck_table(fwts_framework *fw, char *tablename, int which) > return FWTS_OK; > } > > -static int syntaxcheck_DSDT(fwts_framework *fw) > -{ > - return syntaxcheck_table(fw, "DSDT", 0); > -} > - > -static int syntaxcheck_SSDT(fwts_framework *fw) > +static int syntaxcheck_tables(fwts_framework *fw) > { > int i; > + const int n = fwts_iasl_aml_file_count(); > > - for (i=0; i < 100; i++) { > - int ret = syntaxcheck_table(fw, "SSDT", i); > - if (ret == FWTS_NO_TABLE) > - return FWTS_OK; /* Hit the last table */ > - if (ret != FWTS_OK) > - return FWTS_ERROR; > - } > + for (i = 0; i < n; i++) > + syntaxcheck_table(fw, i); > > return FWTS_OK; > } > > static fwts_framework_minor_test syntaxcheck_tests[] = { > - { syntaxcheck_DSDT, "Disassemble and reassemble DSDT" }, > - { syntaxcheck_SSDT, "Disassemble and reassemble SSDT" }, > + { syntaxcheck_tables, "Disassemble and reassemble DSDT and SSDTs." }, > { NULL, NULL } > }; > > static fwts_framework_ops syntaxcheck_ops = { > - .description = "Re-assemble DSDT and find syntax errors and warnings.", > + .description = "Re-assemble DSDT and SSDTs to find syntax errors and warnings.", > .init = syntaxcheck_init, > .deinit = syntaxcheck_deinit, > .minor_tests = syntaxcheck_tests > diff --git a/src/acpica/source/compiler/fwts_iasl_interface.c b/src/acpica/source/compiler/fwts_iasl_interface.c > index 180dadd..f1498e5 100644 > --- a/src/acpica/source/compiler/fwts_iasl_interface.c > +++ b/src/acpica/source/compiler/fwts_iasl_interface.c > @@ -27,6 +27,7 @@ > #include "fwts_iasl_interface.h" > > #include "aslcompiler.h" > +#include "acdisasm.h" > #include "acapps.h" > > /* > @@ -61,16 +62,21 @@ static void init_asl_core(void) > * fwts_iasl_disassemble_aml() > * invoke iasl to disassemble AML > */ > -int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile) > +int fwts_iasl_disassemble_aml( > + char *tables[], > + const int table_entries, > + const int which, > + const char *outputfile) > { > pid_t pid; > - int status; > + int status, i; > > pid = fork(); > switch (pid) { > case -1: > return -1; > case 0: > + > /* Child */ > init_asl_core(); > > @@ -83,9 +89,28 @@ int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile) > Gbl_UseDefaultAmlFilename = FALSE; > UtConvertBackslashes (Gbl_OutputFilenamePrefix); > > + /* > + * Add in external files and NOT the one we want > + * disassemble > + */ > + for (i = 0; i < table_entries; i++) { > + if (i != which) { > + ACPI_STATUS acpi_status; > + /* > + * Add in external tables that are NOT the table > + * we intent to disassemble > + */ > + acpi_status = AcpiDmAddToExternalFileList(tables[i]); > + if (ACPI_FAILURE(acpi_status)) { > + (void)unlink(outputfile); > + _exit(1); > + } > + } > + } > + > /* Throw away noisy errors */ > if (freopen("/dev/null", "w", stderr) != NULL) > - AslDoOneFile((char *)aml); > + AslDoOneFile((char *)tables[which]); > > _exit(0); > break; > diff --git a/src/acpica/source/compiler/fwts_iasl_interface.h b/src/acpica/source/compiler/fwts_iasl_interface.h > index 71675d3..5e2647b 100644 > --- a/src/acpica/source/compiler/fwts_iasl_interface.h > +++ b/src/acpica/source/compiler/fwts_iasl_interface.h > @@ -20,7 +20,7 @@ > #ifndef __FWTS_IASL_INTERFACE__ > #define __FWTS_IASL_INTERFACE__ > > -int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile); > +int fwts_iasl_disassemble_aml(char *tables[], const int table_entries, const int which, const char *outputfile); > int fwts_iasl_assemble_aml(const char *source, char **stdout_output, char **stderr_output); > > #endif > diff --git a/src/hpet/hpet_check/hpet_check.c b/src/hpet/hpet_check/hpet_check.c > index 553dbc0..1a87a35 100644 > --- a/src/hpet/hpet_check/hpet_check.c > +++ b/src/hpet/hpet_check/hpet_check.c > @@ -106,8 +106,10 @@ static void hpet_check_base_acpi_table(fwts_framework *fw, > fwts_list *output; > fwts_list_link *item; > > - if (fwts_iasl_disassemble(fw, table, which, &output) != FWTS_OK) > + if (fwts_iasl_disassemble(fw, table, which, &output) != FWTS_OK) { > + fwts_iasl_deinit(); > return; > + } > if (output == NULL) > return; > > @@ -362,11 +364,19 @@ static int hpet_check_test3(fwts_framework *fw) > return FWTS_SKIP; > } > > + if (fwts_iasl_init(fw) != FWTS_OK) { > + fwts_warning(fw, "Failure to initialise iasl, aborting."); > + fwts_iasl_deinit(); > + return FWTS_ERROR; > + } > + > hpet_check_base_acpi_table(fw, "DSDT", 0); > > - for (i = 0; i< 11; i++) > + for (i = 0; i < 11; i++) > hpet_check_base_acpi_table(fw, "SSDT", i); > > + fwts_iasl_deinit(); > + > return FWTS_OK; > } > > diff --git a/src/lib/include/fwts_iasl.h b/src/lib/include/fwts_iasl.h > index 5efc95c..3e103da 100644 > --- a/src/lib/include/fwts_iasl.h > +++ b/src/lib/include/fwts_iasl.h > @@ -22,6 +22,11 @@ > > #include "fwts.h" > > +int fwts_iasl_aml_file_count(void); > +char *fwts_iasl_aml_name(const int nth); > +int fwts_iasl_init(fwts_framework *fw); > +void fwts_iasl_deinit(void); > + > int fwts_iasl_disassemble_all_to_file(fwts_framework *fw, > const char *path); > > @@ -31,8 +36,7 @@ int fwts_iasl_disassemble(fwts_framework *fw, > fwts_list **ias_output); > > int fwts_iasl_reassemble(fwts_framework *fw, > - const uint8_t *data, > - const int len, > + const int which, > fwts_list **iasl_disassembly, > fwts_list **iasl_stdout, > fwts_list **iasl_stderr); > diff --git a/src/lib/src/fwts_iasl.c b/src/lib/src/fwts_iasl.c > index 1800912..e4a8a68 100644 > --- a/src/lib/src/fwts_iasl.c > +++ b/src/lib/src/fwts_iasl.c > @@ -31,27 +31,59 @@ > #include "fwts_iasl_interface.h" > #include "fwts_acpica.h" > > +#define MAX_TABLES (128) > + > +static fwts_acpi_table_info *iasl_cached_table_info[MAX_TABLES]; > +static char *iasl_cached_table_files[MAX_TABLES]; > +static int iasl_cached_table_file_max = 0; > +static bool iasl_init = false; > + > +/* > + * fwts_iasl_aml_file_count() > + * return number of cached dumped amlfiles > + */ > +int fwts_iasl_aml_file_count(void) > +{ > + if (iasl_init) > + return iasl_cached_table_file_max; > + else > + return 0; > +} > + > +/* > + * fwts_iasl_aml_name() > + * return back nth iASL cached table name > + */ > +char *fwts_iasl_aml_name(const int nth) > +{ > + if (iasl_init && nth < iasl_cached_table_file_max) > + return iasl_cached_table_info[nth]->name; > + else > + return "<unknown>"; > +} > + > /* > * fwts_iasl_dump_aml_to_file() > * write AML data of given length to file amlfile. > */ > -static int fwts_iasl_dump_aml_to_file(fwts_framework *fw, > +static int fwts_iasl_dump_aml_to_file( > + fwts_framework *fw, > const uint8_t *data, > const int length, > - const char *amlfile) > + const char *filename) > { > int fd; > > /* Dump the AML bytecode into a tempoary file so we can disassemble it */ > - if ((fd = open(amlfile, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) { > - fwts_log_error(fw, "Cannot create temporary file %s", amlfile); > + if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) { > + fwts_log_error(fw, "Cannot create temporary file %s", filename); > return FWTS_ERROR; > } > > if (write(fd, data, length) != length) { > fwts_log_error(fw, "Cannot write all data to temporary file"); > close(fd); > - (void)unlink(amlfile); > + (void)unlink(filename); > return FWTS_ERROR; > } > close(fd); > @@ -60,42 +92,123 @@ static int fwts_iasl_dump_aml_to_file(fwts_framework *fw, > } > > /* > + * fwts_iasl_cache_table_to_file() > + * to disassemble an APCPI table we need to dump it > + * to file. To save effort in saving these to file > + * multiple times, we dump out all the DSDT and > + * SSDTs and cache the references to these. > + */ > +static int fwts_iasl_cache_table_to_file(fwts_framework *fw, char *tablename, int which) > +{ > + static pid_t pid = 0; > + char tmpname[PATH_MAX]; > + fwts_acpi_table_info *table; > + int ret; > + > + if (iasl_cached_table_file_max >= MAX_TABLES) { > + fwts_log_error(fw, "Temporary ACPI table lookup table full."); > + return FWTS_ERROR; > + } > + ret = fwts_acpi_find_table(fw, tablename, which, &table); > + if (ret != FWTS_OK) { > + fwts_log_error(fw, "Cannot load ACPI table %s.", tablename); > + return ret; > + } > + if (table == NULL) > + return FWTS_NO_TABLE; /* Table does not exist */ > + if (!pid) > + pid = getpid(); > + > + snprintf(tmpname, sizeof(tmpname), "/tmp/fwts_tmp_table_%d_%s_%d.dsl", pid, tablename, which); > + iasl_cached_table_files[iasl_cached_table_file_max] = strdup(tmpname); > + if (iasl_cached_table_files[iasl_cached_table_file_max] == NULL) { > + fwts_log_error(fw, "Cannot allocate cached table file name."); > + return FWTS_ERROR; > + } > + if (fwts_iasl_dump_aml_to_file(fw, table->data, table->length, tmpname) != FWTS_OK) { > + free(iasl_cached_table_files[iasl_cached_table_file_max]); > + iasl_cached_table_files[iasl_cached_table_file_max] = NULL; > + return FWTS_ERROR; > + } > + iasl_cached_table_info[iasl_cached_table_file_max] = table; > + iasl_cached_table_file_max++; > + return FWTS_OK; > +} > + > +/* > + * fwts_iasl_deinit() > + * clean up cached files and references > + */ > +void fwts_iasl_deinit(void) > +{ > + int i; > + > + for (i = 0; i < iasl_cached_table_file_max; i++) { > + if (iasl_cached_table_files[i]) > + (void)unlink(iasl_cached_table_files[i]); > + iasl_cached_table_files[i] = NULL; > + iasl_cached_table_info[i] = NULL; > + } > + iasl_cached_table_file_max = 0; > +} > + > +/* > + * fwts_iasl_init() > + * initialise iasl - cache DSDT and SSDT to file > + */ > +int fwts_iasl_init(fwts_framework *fw) > +{ > + int i; > + int ret; > + > + fwts_iasl_deinit(); /* Ensure it is clean */ > + > + ret = fwts_iasl_cache_table_to_file(fw, "DSDT", 0); > + if (ret != FWTS_OK) > + return ret; > + > + for (i = 0; i < MAX_TABLES; i++) { > + if (fwts_iasl_cache_table_to_file(fw, "SSDT", i) != FWTS_OK) > + break; > + } > + > + iasl_init = true; > + > + return FWTS_OK; > +} > + > +/* > * fwts_iasl_disassemble_to_file() > * Disassemble a given table and dump disassembly to a file. > * For tables where there are multiple matches, e.g. SSDT, we > * specify the Nth table with 'which'. > - * > */ > -int fwts_iasl_disassemble_to_file(fwts_framework *fw, > +static int fwts_iasl_disassemble_to_file(fwts_framework *fw, > const char *tablename, > const int which, > const char *filename) > { > - fwts_acpi_table_info *table; > - char amlfile[PATH_MAX]; > - int pid = getpid(); > - int ret; > - > - fwts_acpcia_set_fwts_framework(fw); > + int i, count, n = 0; > > - if ((ret = fwts_acpi_find_table(fw, tablename, which, &table)) != FWTS_OK) > - return ret; > + if (!iasl_init) > + return FWTS_ERROR; > > - if (table == NULL) > + /* Find Nth table of a given name */ > + count = fwts_iasl_aml_file_count(); > + for (i = 0; i < count; i++) { > + if (!strcmp(tablename, iasl_cached_table_info[i]->name)) { > + if (n == which) > + break; > + n++; > + } > + } > + if (i >= count) > return FWTS_NO_TABLE; > > - snprintf(amlfile, sizeof(amlfile), "/tmp/fwts_iasl_%d_%s.dat", pid, tablename); > - > - /* Dump the AML bytecode into a tempoary file so we can disassemble it */ > - if (fwts_iasl_dump_aml_to_file(fw, table->data, table->length, amlfile) != FWTS_OK) > - return FWTS_ERROR; > + fwts_acpcia_set_fwts_framework(fw); > > - if (fwts_iasl_disassemble_aml(amlfile, filename) < 0) { > - (void)unlink(amlfile); > + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, iasl_cached_table_file_max, i, filename) < 0) > return FWTS_ERROR; > - } > - > - (void)unlink(amlfile); > > return FWTS_OK; > } > @@ -116,12 +229,14 @@ int fwts_iasl_disassemble(fwts_framework *fw, > int pid = getpid(); > int ret; > > + if (!iasl_init) > + return FWTS_ERROR; > if (iasl_output == NULL) > return FWTS_ERROR; > > *iasl_output = NULL; > > - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d_%s.dsl", pid, tablename); > + snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_disassemble_%d_%s.dsl", pid, tablename); > > if ((ret = fwts_iasl_disassemble_to_file(fw, tablename, which, tmpfile)) != FWTS_OK) > return ret; > @@ -140,32 +255,36 @@ int fwts_iasl_disassemble(fwts_framework *fw, > int fwts_iasl_disassemble_all_to_file(fwts_framework *fw, > const char *path) > { > - int i; > + int i, n; > int ret; > char filename[PATH_MAX]; > char pathname[PATH_MAX]; > > - if (path == NULL) > - strncpy(pathname, "", sizeof(pathname)); > - else > - snprintf(pathname, sizeof(pathname), "%s/", path); > - > - snprintf(filename, sizeof(filename), "%sDSDT.dsl", pathname); > - > - ret = fwts_iasl_disassemble_to_file(fw, "DSDT", 0, filename); > + ret = fwts_iasl_init(fw); > if (ret == FWTS_ERROR_NO_PRIV) { > fprintf(stderr, "Need to have root privilege to read ACPI tables from memory! Re-run using sudo.\n"); > return FWTS_ERROR; > } > - if (ret == FWTS_OK) > - printf("Disassembled DSDT to %s\n", filename); > + if (ret != FWTS_OK) { > + fprintf(stderr, "Could not initialise disassembler.\n"); > + return FWTS_ERROR; > + } > > - for (i=0; ;i++) { > - snprintf(filename, sizeof(filename), "%sSSDT%d.dsl", pathname, i); > - if (fwts_iasl_disassemble_to_file(fw, "SSDT", i, filename) != FWTS_OK) > - break; > - printf("Disassembled SSDT %d to %s\n", i, filename); > + n = fwts_iasl_aml_file_count(); > + if (path == NULL) > + strncpy(pathname, "", sizeof(pathname)); > + else > + snprintf(pathname, sizeof(pathname), "%s/", path); > + > + for (i = 0; i < n; i++) { > + snprintf(filename, sizeof(filename), "%s%s%d.dsl", pathname, iasl_cached_table_info[i]->name, i); > + fwts_iasl_disassemble_to_file(fw, "DSDT", 0, filename); > + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, iasl_cached_table_file_max, i, filename) < 0) > + fprintf(stderr, "Could not disassemble %s\n", iasl_cached_table_info[i]->name); > + else > + printf("Disassembled %s to %s\n", iasl_cached_table_info[i]->name, filename); > } > + fwts_iasl_deinit(); > > return FWTS_OK; > } > @@ -177,47 +296,38 @@ int fwts_iasl_disassemble_all_to_file(fwts_framework *fw, > * any re-assembly errors into list iasl_errors. > */ > int fwts_iasl_reassemble(fwts_framework *fw, > - const uint8_t *data, > - const int len, > + const int which, > fwts_list **iasl_disassembly, > fwts_list **iasl_stdout, > fwts_list **iasl_stderr) > { > char tmpfile[PATH_MAX]; > - char amlfile[PATH_MAX]; > char *stdout_output = NULL, *stderr_output = NULL; > int pid = getpid(); > > - if ((iasl_disassembly == NULL) || > + if ((!iasl_init) || > + (iasl_disassembly == NULL) || > (iasl_stdout == NULL) || > - (iasl_stderr == NULL)) > + (iasl_stderr == NULL) || > + (which > iasl_cached_table_file_max)) > return FWTS_ERROR; > > fwts_acpcia_set_fwts_framework(fw); > > *iasl_disassembly = NULL; > > - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d.dsl", pid); > - snprintf(amlfile, sizeof(amlfile), "/tmp/fwts_iasl_%d.dat", pid); > - > - /* Dump the AML bytecode into a tempoary file so we can disassemble it */ > - if (fwts_iasl_dump_aml_to_file(fw, data, len, amlfile) != FWTS_OK) > - return FWTS_ERROR; > + snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_reassemble_%d.dsl", pid); > > - if (fwts_iasl_disassemble_aml(amlfile, tmpfile) < 0) { > + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, iasl_cached_table_file_max, which, tmpfile) < 0) { > (void)unlink(tmpfile); > - (void)unlink(amlfile); > return FWTS_ERROR; > } > - (void)unlink(amlfile); > > /* Read in the disassembled text to return later */ > *iasl_disassembly = fwts_file_open_and_read(tmpfile); > > /* Now we have a disassembled source in tmpfile, so let's assemble it */ > - > if (fwts_iasl_assemble_aml(tmpfile, &stdout_output, &stderr_output) < 0) { > - (void)unlink(amlfile); > (void)unlink(tmpfile); > free(stdout_output); > return FWTS_ERROR; > @@ -225,10 +335,9 @@ int fwts_iasl_reassemble(fwts_framework *fw, > > /* Remove these now we don't need them */ > (void)unlink(tmpfile); > - (void)unlink(amlfile); > > /* And remove aml file generated from ACPICA compiler */ > - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d.aml", pid); > + snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_reassemble_%d.aml", pid); > (void)unlink(tmpfile); > > *iasl_stdout = fwts_list_from_text(stdout_output); > @@ -237,4 +346,3 @@ int fwts_iasl_reassemble(fwts_framework *fw, > > return FWTS_OK; > } > - > Acked-by: Alex Hung <alex.hung@canonical.com>
On Mon, Jun 9, 2014 at 4:22 PM, Alex Hung <alex.hung@canonical.com> wrote: > On 05/29/2014 09:59 PM, Colin King wrote: >> >> From: Colin Ian King <colin.king@canonical.com> >> >> Reduce the number of false positives by including in all tables >> to help resolve external references. This requires a re-working >> of the two iASL interfaces and consumers of the API. >> >> Signed-off-by: Colin Ian King <colin.king@canonical.com> >> --- >> src/acpi/osilinux/osilinux.c | 7 + >> src/acpi/syntaxcheck/syntaxcheck.c | 46 ++--- >> src/acpica/source/compiler/fwts_iasl_interface.c | 31 ++- >> src/acpica/source/compiler/fwts_iasl_interface.h | 2 +- >> src/hpet/hpet_check/hpet_check.c | 14 +- >> src/lib/include/fwts_iasl.h | 8 +- >> src/lib/src/fwts_iasl.c | 232 >> +++++++++++++++++------ >> 7 files changed, 241 insertions(+), 99 deletions(-) >> >> diff --git a/src/acpi/osilinux/osilinux.c b/src/acpi/osilinux/osilinux.c >> index 04a731a..857d141 100644 >> --- a/src/acpi/osilinux/osilinux.c >> +++ b/src/acpi/osilinux/osilinux.c >> @@ -36,10 +36,17 @@ static int osilinux_test1(fwts_framework *fw) >> int dumpdepth = 0; >> int found = 0; >> >> + if (fwts_iasl_init(fw) != FWTS_OK) { >> + fwts_aborted(fw, "Failure to initialise iasl, aborting."); >> + fwts_iasl_deinit(); >> + return FWTS_ERROR; >> + } >> if (fwts_iasl_disassemble(fw, "DSDT", 0, &disassembly) != FWTS_OK) >> { >> fwts_aborted(fw, "Cannot disassemble DSDT with iasl."); >> + fwts_iasl_deinit(); >> return FWTS_ERROR; >> } >> + fwts_iasl_deinit(); >> >> if (disassembly == NULL) { >> fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoDSDT", >> diff --git a/src/acpi/syntaxcheck/syntaxcheck.c >> b/src/acpi/syntaxcheck/syntaxcheck.c >> index 5281031..5e4f7d4 100644 >> --- a/src/acpi/syntaxcheck/syntaxcheck.c >> +++ b/src/acpi/syntaxcheck/syntaxcheck.c >> @@ -28,6 +28,7 @@ >> #include <json/json.h> >> >> #define ASL_EXCEPTIONS /* so we can include AslErrorLevel in >> aslmessages.h */ >> +#define MAX_TABLES 128 >> >> #include "aslmessages.h" >> >> @@ -226,6 +227,10 @@ static int syntaxcheck_init(fwts_framework *fw) >> { >> (void)syntaxcheck_load_advice(fw); >> >> + if (fwts_iasl_init(fw) != FWTS_OK) { >> + fwts_aborted(fw, "Failure to initialise iasl, aborting."); >> + return FWTS_ERROR; >> + } >> return FWTS_OK; >> } >> >> @@ -233,6 +238,7 @@ static int syntaxcheck_deinit(fwts_framework *fw) >> { >> FWTS_UNUSED(fw); >> >> + fwts_iasl_deinit(); >> syntaxcheck_free_advice(); >> >> return FWTS_OK; >> @@ -456,27 +462,19 @@ static void syntaxcheck_give_advice(fwts_framework >> *fw, uint32_t error_code) >> /* >> * syntaxcheck_table() >> * disassemble and reassemble a table, check for errors. which >> indicates the Nth >> - * table, for example, SSDT may have tables 1..N >> + * table >> */ >> -static int syntaxcheck_table(fwts_framework *fw, char *tablename, int >> which) >> +static int syntaxcheck_table(fwts_framework *fw, const int which) >> { >> fwts_list_link *item; >> int errors = 0; >> int warnings = 0; >> int remarks = 0; >> - fwts_acpi_table_info *table; >> + char *tablename = fwts_iasl_aml_name(which); >> fwts_list *iasl_stdout, *iasl_stderr, *iasl_disassembly; >> >> - if (fwts_acpi_find_table(fw, tablename, which, &table) != FWTS_OK) >> { >> - fwts_aborted(fw, "Cannot load ACPI table %s.", tablename); >> - return FWTS_ERROR; >> - } >> - >> - if (table == NULL) >> - return FWTS_NO_TABLE; /* Table does not exist */ >> - >> - if (fwts_iasl_reassemble(fw, table->data, table->length, >> - &iasl_disassembly, &iasl_stdout, >> &iasl_stderr) != FWTS_OK) { >> + if (fwts_iasl_reassemble(fw, which, >> + &iasl_disassembly, &iasl_stdout, &iasl_stderr) != FWTS_OK) >> { >> fwts_aborted(fw, "Cannot re-assasemble with iasl."); >> return FWTS_ERROR; >> } >> @@ -611,34 +609,24 @@ static int syntaxcheck_table(fwts_framework *fw, >> char *tablename, int which) >> return FWTS_OK; >> } >> >> -static int syntaxcheck_DSDT(fwts_framework *fw) >> -{ >> - return syntaxcheck_table(fw, "DSDT", 0); >> -} >> - >> -static int syntaxcheck_SSDT(fwts_framework *fw) >> +static int syntaxcheck_tables(fwts_framework *fw) >> { >> int i; >> + const int n = fwts_iasl_aml_file_count(); >> >> - for (i=0; i < 100; i++) { >> - int ret = syntaxcheck_table(fw, "SSDT", i); >> - if (ret == FWTS_NO_TABLE) >> - return FWTS_OK; /* Hit the last table */ >> - if (ret != FWTS_OK) >> - return FWTS_ERROR; >> - } >> + for (i = 0; i < n; i++) >> + syntaxcheck_table(fw, i); >> >> return FWTS_OK; >> } >> >> static fwts_framework_minor_test syntaxcheck_tests[] = { >> - { syntaxcheck_DSDT, "Disassemble and reassemble DSDT" }, >> - { syntaxcheck_SSDT, "Disassemble and reassemble SSDT" }, >> + { syntaxcheck_tables, "Disassemble and reassemble DSDT and SSDTs." >> }, >> { NULL, NULL } >> }; >> >> static fwts_framework_ops syntaxcheck_ops = { >> - .description = "Re-assemble DSDT and find syntax errors and >> warnings.", >> + .description = "Re-assemble DSDT and SSDTs to find syntax errors >> and warnings.", >> .init = syntaxcheck_init, >> .deinit = syntaxcheck_deinit, >> .minor_tests = syntaxcheck_tests >> diff --git a/src/acpica/source/compiler/fwts_iasl_interface.c >> b/src/acpica/source/compiler/fwts_iasl_interface.c >> index 180dadd..f1498e5 100644 >> --- a/src/acpica/source/compiler/fwts_iasl_interface.c >> +++ b/src/acpica/source/compiler/fwts_iasl_interface.c >> @@ -27,6 +27,7 @@ >> #include "fwts_iasl_interface.h" >> >> #include "aslcompiler.h" >> +#include "acdisasm.h" >> #include "acapps.h" >> >> /* >> @@ -61,16 +62,21 @@ static void init_asl_core(void) >> * fwts_iasl_disassemble_aml() >> * invoke iasl to disassemble AML >> */ >> -int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile) >> +int fwts_iasl_disassemble_aml( >> + char *tables[], >> + const int table_entries, >> + const int which, >> + const char *outputfile) >> { >> pid_t pid; >> - int status; >> + int status, i; >> >> pid = fork(); >> switch (pid) { >> case -1: >> return -1; >> case 0: >> + >> /* Child */ >> init_asl_core(); >> >> @@ -83,9 +89,28 @@ int fwts_iasl_disassemble_aml(const char *aml, const >> char *outputfile) >> Gbl_UseDefaultAmlFilename = FALSE; >> UtConvertBackslashes (Gbl_OutputFilenamePrefix); >> >> + /* >> + * Add in external files and NOT the one we want >> + * disassemble >> + */ >> + for (i = 0; i < table_entries; i++) { >> + if (i != which) { >> + ACPI_STATUS acpi_status; >> + /* >> + * Add in external tables that are NOT >> the table >> + * we intent to disassemble >> + */ >> + acpi_status = >> AcpiDmAddToExternalFileList(tables[i]); >> + if (ACPI_FAILURE(acpi_status)) { >> + (void)unlink(outputfile); >> + _exit(1); >> + } >> + } >> + } >> + >> /* Throw away noisy errors */ >> if (freopen("/dev/null", "w", stderr) != NULL) >> - AslDoOneFile((char *)aml); >> + AslDoOneFile((char *)tables[which]); >> >> _exit(0); >> break; >> diff --git a/src/acpica/source/compiler/fwts_iasl_interface.h >> b/src/acpica/source/compiler/fwts_iasl_interface.h >> index 71675d3..5e2647b 100644 >> --- a/src/acpica/source/compiler/fwts_iasl_interface.h >> +++ b/src/acpica/source/compiler/fwts_iasl_interface.h >> @@ -20,7 +20,7 @@ >> #ifndef __FWTS_IASL_INTERFACE__ >> #define __FWTS_IASL_INTERFACE__ >> >> -int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile); >> +int fwts_iasl_disassemble_aml(char *tables[], const int table_entries, >> const int which, const char *outputfile); >> int fwts_iasl_assemble_aml(const char *source, char **stdout_output, >> char **stderr_output); >> >> #endif >> diff --git a/src/hpet/hpet_check/hpet_check.c >> b/src/hpet/hpet_check/hpet_check.c >> index 553dbc0..1a87a35 100644 >> --- a/src/hpet/hpet_check/hpet_check.c >> +++ b/src/hpet/hpet_check/hpet_check.c >> @@ -106,8 +106,10 @@ static void hpet_check_base_acpi_table(fwts_framework >> *fw, >> fwts_list *output; >> fwts_list_link *item; >> >> - if (fwts_iasl_disassemble(fw, table, which, &output) != FWTS_OK) >> + if (fwts_iasl_disassemble(fw, table, which, &output) != FWTS_OK) { >> + fwts_iasl_deinit(); >> return; >> + } >> if (output == NULL) >> return; >> >> @@ -362,11 +364,19 @@ static int hpet_check_test3(fwts_framework *fw) >> return FWTS_SKIP; >> } >> >> + if (fwts_iasl_init(fw) != FWTS_OK) { >> + fwts_warning(fw, "Failure to initialise iasl, aborting."); >> + fwts_iasl_deinit(); >> + return FWTS_ERROR; >> + } >> + >> hpet_check_base_acpi_table(fw, "DSDT", 0); >> >> - for (i = 0; i< 11; i++) >> + for (i = 0; i < 11; i++) >> hpet_check_base_acpi_table(fw, "SSDT", i); >> >> + fwts_iasl_deinit(); >> + >> return FWTS_OK; >> } >> >> diff --git a/src/lib/include/fwts_iasl.h b/src/lib/include/fwts_iasl.h >> index 5efc95c..3e103da 100644 >> --- a/src/lib/include/fwts_iasl.h >> +++ b/src/lib/include/fwts_iasl.h >> @@ -22,6 +22,11 @@ >> >> #include "fwts.h" >> >> +int fwts_iasl_aml_file_count(void); >> +char *fwts_iasl_aml_name(const int nth); >> +int fwts_iasl_init(fwts_framework *fw); >> +void fwts_iasl_deinit(void); >> + >> int fwts_iasl_disassemble_all_to_file(fwts_framework *fw, >> const char *path); >> >> @@ -31,8 +36,7 @@ int fwts_iasl_disassemble(fwts_framework *fw, >> fwts_list **ias_output); >> >> int fwts_iasl_reassemble(fwts_framework *fw, >> - const uint8_t *data, >> - const int len, >> + const int which, >> fwts_list **iasl_disassembly, >> fwts_list **iasl_stdout, >> fwts_list **iasl_stderr); >> diff --git a/src/lib/src/fwts_iasl.c b/src/lib/src/fwts_iasl.c >> index 1800912..e4a8a68 100644 >> --- a/src/lib/src/fwts_iasl.c >> +++ b/src/lib/src/fwts_iasl.c >> @@ -31,27 +31,59 @@ >> #include "fwts_iasl_interface.h" >> #include "fwts_acpica.h" >> >> +#define MAX_TABLES (128) >> + >> +static fwts_acpi_table_info *iasl_cached_table_info[MAX_TABLES]; >> +static char *iasl_cached_table_files[MAX_TABLES]; >> +static int iasl_cached_table_file_max = 0; >> +static bool iasl_init = false; >> + >> +/* >> + * fwts_iasl_aml_file_count() >> + * return number of cached dumped amlfiles >> + */ >> +int fwts_iasl_aml_file_count(void) >> +{ >> + if (iasl_init) >> + return iasl_cached_table_file_max; >> + else >> + return 0; >> +} >> + >> +/* >> + * fwts_iasl_aml_name() >> + * return back nth iASL cached table name >> + */ >> +char *fwts_iasl_aml_name(const int nth) >> +{ >> + if (iasl_init && nth < iasl_cached_table_file_max) >> + return iasl_cached_table_info[nth]->name; >> + else >> + return "<unknown>"; >> +} >> + >> /* >> * fwts_iasl_dump_aml_to_file() >> * write AML data of given length to file amlfile. >> */ >> -static int fwts_iasl_dump_aml_to_file(fwts_framework *fw, >> +static int fwts_iasl_dump_aml_to_file( >> + fwts_framework *fw, >> const uint8_t *data, >> const int length, >> - const char *amlfile) >> + const char *filename) >> { >> int fd; >> >> /* Dump the AML bytecode into a tempoary file so we can >> disassemble it */ >> - if ((fd = open(amlfile, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | >> S_IRUSR)) < 0) { >> - fwts_log_error(fw, "Cannot create temporary file %s", >> amlfile); >> + if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | >> S_IRUSR)) < 0) { >> + fwts_log_error(fw, "Cannot create temporary file %s", >> filename); >> return FWTS_ERROR; >> } >> >> if (write(fd, data, length) != length) { >> fwts_log_error(fw, "Cannot write all data to temporary >> file"); >> close(fd); >> - (void)unlink(amlfile); >> + (void)unlink(filename); >> return FWTS_ERROR; >> } >> close(fd); >> @@ -60,42 +92,123 @@ static int fwts_iasl_dump_aml_to_file(fwts_framework >> *fw, >> } >> >> /* >> + * fwts_iasl_cache_table_to_file() >> + * to disassemble an APCPI table we need to dump it >> + * to file. To save effort in saving these to file >> + * multiple times, we dump out all the DSDT and >> + * SSDTs and cache the references to these. >> + */ >> +static int fwts_iasl_cache_table_to_file(fwts_framework *fw, char >> *tablename, int which) >> +{ >> + static pid_t pid = 0; >> + char tmpname[PATH_MAX]; >> + fwts_acpi_table_info *table; >> + int ret; >> + >> + if (iasl_cached_table_file_max >= MAX_TABLES) { >> + fwts_log_error(fw, "Temporary ACPI table lookup table >> full."); >> + return FWTS_ERROR; >> + } >> + ret = fwts_acpi_find_table(fw, tablename, which, &table); >> + if (ret != FWTS_OK) { >> + fwts_log_error(fw, "Cannot load ACPI table %s.", >> tablename); >> + return ret; >> + } >> + if (table == NULL) >> + return FWTS_NO_TABLE; /* Table does not exist */ >> + if (!pid) >> + pid = getpid(); >> + >> + snprintf(tmpname, sizeof(tmpname), >> "/tmp/fwts_tmp_table_%d_%s_%d.dsl", pid, tablename, which); >> + iasl_cached_table_files[iasl_cached_table_file_max] = >> strdup(tmpname); >> + if (iasl_cached_table_files[iasl_cached_table_file_max] == NULL) { >> + fwts_log_error(fw, "Cannot allocate cached table file >> name."); >> + return FWTS_ERROR; >> + } >> + if (fwts_iasl_dump_aml_to_file(fw, table->data, table->length, >> tmpname) != FWTS_OK) { >> + free(iasl_cached_table_files[iasl_cached_table_file_max]); >> + iasl_cached_table_files[iasl_cached_table_file_max] = >> NULL; >> + return FWTS_ERROR; >> + } >> + iasl_cached_table_info[iasl_cached_table_file_max] = table; >> + iasl_cached_table_file_max++; >> + return FWTS_OK; >> +} >> + >> +/* >> + * fwts_iasl_deinit() >> + * clean up cached files and references >> + */ >> +void fwts_iasl_deinit(void) >> +{ >> + int i; >> + >> + for (i = 0; i < iasl_cached_table_file_max; i++) { >> + if (iasl_cached_table_files[i]) >> + (void)unlink(iasl_cached_table_files[i]); >> + iasl_cached_table_files[i] = NULL; >> + iasl_cached_table_info[i] = NULL; >> + } >> + iasl_cached_table_file_max = 0; >> +} >> + >> +/* >> + * fwts_iasl_init() >> + * initialise iasl - cache DSDT and SSDT to file >> + */ >> +int fwts_iasl_init(fwts_framework *fw) >> +{ >> + int i; >> + int ret; >> + >> + fwts_iasl_deinit(); /* Ensure it is clean */ >> + >> + ret = fwts_iasl_cache_table_to_file(fw, "DSDT", 0); >> + if (ret != FWTS_OK) >> + return ret; >> + >> + for (i = 0; i < MAX_TABLES; i++) { >> + if (fwts_iasl_cache_table_to_file(fw, "SSDT", i) != >> FWTS_OK) >> + break; >> + } >> + >> + iasl_init = true; >> + >> + return FWTS_OK; >> +} >> + >> +/* >> * fwts_iasl_disassemble_to_file() >> * Disassemble a given table and dump disassembly to a file. >> * For tables where there are multiple matches, e.g. SSDT, we >> * specify the Nth table with 'which'. >> - * >> */ >> -int fwts_iasl_disassemble_to_file(fwts_framework *fw, >> +static int fwts_iasl_disassemble_to_file(fwts_framework *fw, >> const char *tablename, >> const int which, >> const char *filename) >> { >> - fwts_acpi_table_info *table; >> - char amlfile[PATH_MAX]; >> - int pid = getpid(); >> - int ret; >> - >> - fwts_acpcia_set_fwts_framework(fw); >> + int i, count, n = 0; >> >> - if ((ret = fwts_acpi_find_table(fw, tablename, which, &table)) != >> FWTS_OK) >> - return ret; >> + if (!iasl_init) >> + return FWTS_ERROR; >> >> - if (table == NULL) >> + /* Find Nth table of a given name */ >> + count = fwts_iasl_aml_file_count(); >> + for (i = 0; i < count; i++) { >> + if (!strcmp(tablename, iasl_cached_table_info[i]->name)) { >> + if (n == which) >> + break; >> + n++; >> + } >> + } >> + if (i >= count) >> return FWTS_NO_TABLE; >> >> - snprintf(amlfile, sizeof(amlfile), "/tmp/fwts_iasl_%d_%s.dat", >> pid, tablename); >> - >> - /* Dump the AML bytecode into a tempoary file so we can >> disassemble it */ >> - if (fwts_iasl_dump_aml_to_file(fw, table->data, table->length, >> amlfile) != FWTS_OK) >> - return FWTS_ERROR; >> + fwts_acpcia_set_fwts_framework(fw); >> >> - if (fwts_iasl_disassemble_aml(amlfile, filename) < 0) { >> - (void)unlink(amlfile); >> + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, >> iasl_cached_table_file_max, i, filename) < 0) >> return FWTS_ERROR; >> - } >> - >> - (void)unlink(amlfile); >> >> return FWTS_OK; >> } >> @@ -116,12 +229,14 @@ int fwts_iasl_disassemble(fwts_framework *fw, >> int pid = getpid(); >> int ret; >> >> + if (!iasl_init) >> + return FWTS_ERROR; >> if (iasl_output == NULL) >> return FWTS_ERROR; >> >> *iasl_output = NULL; >> >> - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d_%s.dsl", >> pid, tablename); >> + snprintf(tmpfile, sizeof(tmpfile), >> "/tmp/fwts_iasl_disassemble_%d_%s.dsl", pid, tablename); >> >> if ((ret = fwts_iasl_disassemble_to_file(fw, tablename, which, >> tmpfile)) != FWTS_OK) >> return ret; >> @@ -140,32 +255,36 @@ int fwts_iasl_disassemble(fwts_framework *fw, >> int fwts_iasl_disassemble_all_to_file(fwts_framework *fw, >> const char *path) >> { >> - int i; >> + int i, n; >> int ret; >> char filename[PATH_MAX]; >> char pathname[PATH_MAX]; >> >> - if (path == NULL) >> - strncpy(pathname, "", sizeof(pathname)); >> - else >> - snprintf(pathname, sizeof(pathname), "%s/", path); >> - >> - snprintf(filename, sizeof(filename), "%sDSDT.dsl", pathname); >> - >> - ret = fwts_iasl_disassemble_to_file(fw, "DSDT", 0, filename); >> + ret = fwts_iasl_init(fw); >> if (ret == FWTS_ERROR_NO_PRIV) { >> fprintf(stderr, "Need to have root privilege to read ACPI >> tables from memory! Re-run using sudo.\n"); >> return FWTS_ERROR; >> } >> - if (ret == FWTS_OK) >> - printf("Disassembled DSDT to %s\n", filename); >> + if (ret != FWTS_OK) { >> + fprintf(stderr, "Could not initialise disassembler.\n"); >> + return FWTS_ERROR; >> + } >> >> - for (i=0; ;i++) { >> - snprintf(filename, sizeof(filename), "%sSSDT%d.dsl", >> pathname, i); >> - if (fwts_iasl_disassemble_to_file(fw, "SSDT", i, filename) >> != FWTS_OK) >> - break; >> - printf("Disassembled SSDT %d to %s\n", i, filename); >> + n = fwts_iasl_aml_file_count(); >> + if (path == NULL) >> + strncpy(pathname, "", sizeof(pathname)); >> + else >> + snprintf(pathname, sizeof(pathname), "%s/", path); >> + >> + for (i = 0; i < n; i++) { >> + snprintf(filename, sizeof(filename), "%s%s%d.dsl", >> pathname, iasl_cached_table_info[i]->name, i); >> + fwts_iasl_disassemble_to_file(fw, "DSDT", 0, filename); >> + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, >> iasl_cached_table_file_max, i, filename) < 0) >> + fprintf(stderr, "Could not disassemble %s\n", >> iasl_cached_table_info[i]->name); >> + else >> + printf("Disassembled %s to %s\n", >> iasl_cached_table_info[i]->name, filename); >> } >> + fwts_iasl_deinit(); >> >> return FWTS_OK; >> } >> @@ -177,47 +296,38 @@ int fwts_iasl_disassemble_all_to_file(fwts_framework >> *fw, >> * any re-assembly errors into list iasl_errors. >> */ >> int fwts_iasl_reassemble(fwts_framework *fw, >> - const uint8_t *data, >> - const int len, >> + const int which, >> fwts_list **iasl_disassembly, >> fwts_list **iasl_stdout, >> fwts_list **iasl_stderr) >> { >> char tmpfile[PATH_MAX]; >> - char amlfile[PATH_MAX]; >> char *stdout_output = NULL, *stderr_output = NULL; >> int pid = getpid(); >> >> - if ((iasl_disassembly == NULL) || >> + if ((!iasl_init) || >> + (iasl_disassembly == NULL) || >> (iasl_stdout == NULL) || >> - (iasl_stderr == NULL)) >> + (iasl_stderr == NULL) || >> + (which > iasl_cached_table_file_max)) >> return FWTS_ERROR; >> >> fwts_acpcia_set_fwts_framework(fw); >> >> *iasl_disassembly = NULL; >> >> - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d.dsl", pid); >> - snprintf(amlfile, sizeof(amlfile), "/tmp/fwts_iasl_%d.dat", pid); >> - >> - /* Dump the AML bytecode into a tempoary file so we can >> disassemble it */ >> - if (fwts_iasl_dump_aml_to_file(fw, data, len, amlfile) != FWTS_OK) >> - return FWTS_ERROR; >> + snprintf(tmpfile, sizeof(tmpfile), >> "/tmp/fwts_iasl_reassemble_%d.dsl", pid); >> >> - if (fwts_iasl_disassemble_aml(amlfile, tmpfile) < 0) { >> + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, >> iasl_cached_table_file_max, which, tmpfile) < 0) { >> (void)unlink(tmpfile); >> - (void)unlink(amlfile); >> return FWTS_ERROR; >> } >> - (void)unlink(amlfile); >> >> /* Read in the disassembled text to return later */ >> *iasl_disassembly = fwts_file_open_and_read(tmpfile); >> >> /* Now we have a disassembled source in tmpfile, so let's assemble >> it */ >> - >> if (fwts_iasl_assemble_aml(tmpfile, &stdout_output, >> &stderr_output) < 0) { >> - (void)unlink(amlfile); >> (void)unlink(tmpfile); >> free(stdout_output); >> return FWTS_ERROR; >> @@ -225,10 +335,9 @@ int fwts_iasl_reassemble(fwts_framework *fw, >> >> /* Remove these now we don't need them */ >> (void)unlink(tmpfile); >> - (void)unlink(amlfile); >> >> /* And remove aml file generated from ACPICA compiler */ >> - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d.aml", pid); >> + snprintf(tmpfile, sizeof(tmpfile), >> "/tmp/fwts_iasl_reassemble_%d.aml", pid); >> (void)unlink(tmpfile); >> >> *iasl_stdout = fwts_list_from_text(stdout_output); >> @@ -237,4 +346,3 @@ int fwts_iasl_reassemble(fwts_framework *fw, >> >> return FWTS_OK; >> } >> - >> > > Acked-by: Alex Hung <alex.hung@canonical.com> > > -- > Cheers, > Alex Hung > Acked-by: Keng-Yu Lin <kengyu@canonical.com>
diff --git a/src/acpi/osilinux/osilinux.c b/src/acpi/osilinux/osilinux.c index 04a731a..857d141 100644 --- a/src/acpi/osilinux/osilinux.c +++ b/src/acpi/osilinux/osilinux.c @@ -36,10 +36,17 @@ static int osilinux_test1(fwts_framework *fw) int dumpdepth = 0; int found = 0; + if (fwts_iasl_init(fw) != FWTS_OK) { + fwts_aborted(fw, "Failure to initialise iasl, aborting."); + fwts_iasl_deinit(); + return FWTS_ERROR; + } if (fwts_iasl_disassemble(fw, "DSDT", 0, &disassembly) != FWTS_OK) { fwts_aborted(fw, "Cannot disassemble DSDT with iasl."); + fwts_iasl_deinit(); return FWTS_ERROR; } + fwts_iasl_deinit(); if (disassembly == NULL) { fwts_failed(fw, LOG_LEVEL_MEDIUM, "NoDSDT", diff --git a/src/acpi/syntaxcheck/syntaxcheck.c b/src/acpi/syntaxcheck/syntaxcheck.c index 5281031..5e4f7d4 100644 --- a/src/acpi/syntaxcheck/syntaxcheck.c +++ b/src/acpi/syntaxcheck/syntaxcheck.c @@ -28,6 +28,7 @@ #include <json/json.h> #define ASL_EXCEPTIONS /* so we can include AslErrorLevel in aslmessages.h */ +#define MAX_TABLES 128 #include "aslmessages.h" @@ -226,6 +227,10 @@ static int syntaxcheck_init(fwts_framework *fw) { (void)syntaxcheck_load_advice(fw); + if (fwts_iasl_init(fw) != FWTS_OK) { + fwts_aborted(fw, "Failure to initialise iasl, aborting."); + return FWTS_ERROR; + } return FWTS_OK; } @@ -233,6 +238,7 @@ static int syntaxcheck_deinit(fwts_framework *fw) { FWTS_UNUSED(fw); + fwts_iasl_deinit(); syntaxcheck_free_advice(); return FWTS_OK; @@ -456,27 +462,19 @@ static void syntaxcheck_give_advice(fwts_framework *fw, uint32_t error_code) /* * syntaxcheck_table() * disassemble and reassemble a table, check for errors. which indicates the Nth - * table, for example, SSDT may have tables 1..N + * table */ -static int syntaxcheck_table(fwts_framework *fw, char *tablename, int which) +static int syntaxcheck_table(fwts_framework *fw, const int which) { fwts_list_link *item; int errors = 0; int warnings = 0; int remarks = 0; - fwts_acpi_table_info *table; + char *tablename = fwts_iasl_aml_name(which); fwts_list *iasl_stdout, *iasl_stderr, *iasl_disassembly; - if (fwts_acpi_find_table(fw, tablename, which, &table) != FWTS_OK) { - fwts_aborted(fw, "Cannot load ACPI table %s.", tablename); - return FWTS_ERROR; - } - - if (table == NULL) - return FWTS_NO_TABLE; /* Table does not exist */ - - if (fwts_iasl_reassemble(fw, table->data, table->length, - &iasl_disassembly, &iasl_stdout, &iasl_stderr) != FWTS_OK) { + if (fwts_iasl_reassemble(fw, which, + &iasl_disassembly, &iasl_stdout, &iasl_stderr) != FWTS_OK) { fwts_aborted(fw, "Cannot re-assasemble with iasl."); return FWTS_ERROR; } @@ -611,34 +609,24 @@ static int syntaxcheck_table(fwts_framework *fw, char *tablename, int which) return FWTS_OK; } -static int syntaxcheck_DSDT(fwts_framework *fw) -{ - return syntaxcheck_table(fw, "DSDT", 0); -} - -static int syntaxcheck_SSDT(fwts_framework *fw) +static int syntaxcheck_tables(fwts_framework *fw) { int i; + const int n = fwts_iasl_aml_file_count(); - for (i=0; i < 100; i++) { - int ret = syntaxcheck_table(fw, "SSDT", i); - if (ret == FWTS_NO_TABLE) - return FWTS_OK; /* Hit the last table */ - if (ret != FWTS_OK) - return FWTS_ERROR; - } + for (i = 0; i < n; i++) + syntaxcheck_table(fw, i); return FWTS_OK; } static fwts_framework_minor_test syntaxcheck_tests[] = { - { syntaxcheck_DSDT, "Disassemble and reassemble DSDT" }, - { syntaxcheck_SSDT, "Disassemble and reassemble SSDT" }, + { syntaxcheck_tables, "Disassemble and reassemble DSDT and SSDTs." }, { NULL, NULL } }; static fwts_framework_ops syntaxcheck_ops = { - .description = "Re-assemble DSDT and find syntax errors and warnings.", + .description = "Re-assemble DSDT and SSDTs to find syntax errors and warnings.", .init = syntaxcheck_init, .deinit = syntaxcheck_deinit, .minor_tests = syntaxcheck_tests diff --git a/src/acpica/source/compiler/fwts_iasl_interface.c b/src/acpica/source/compiler/fwts_iasl_interface.c index 180dadd..f1498e5 100644 --- a/src/acpica/source/compiler/fwts_iasl_interface.c +++ b/src/acpica/source/compiler/fwts_iasl_interface.c @@ -27,6 +27,7 @@ #include "fwts_iasl_interface.h" #include "aslcompiler.h" +#include "acdisasm.h" #include "acapps.h" /* @@ -61,16 +62,21 @@ static void init_asl_core(void) * fwts_iasl_disassemble_aml() * invoke iasl to disassemble AML */ -int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile) +int fwts_iasl_disassemble_aml( + char *tables[], + const int table_entries, + const int which, + const char *outputfile) { pid_t pid; - int status; + int status, i; pid = fork(); switch (pid) { case -1: return -1; case 0: + /* Child */ init_asl_core(); @@ -83,9 +89,28 @@ int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile) Gbl_UseDefaultAmlFilename = FALSE; UtConvertBackslashes (Gbl_OutputFilenamePrefix); + /* + * Add in external files and NOT the one we want + * disassemble + */ + for (i = 0; i < table_entries; i++) { + if (i != which) { + ACPI_STATUS acpi_status; + /* + * Add in external tables that are NOT the table + * we intent to disassemble + */ + acpi_status = AcpiDmAddToExternalFileList(tables[i]); + if (ACPI_FAILURE(acpi_status)) { + (void)unlink(outputfile); + _exit(1); + } + } + } + /* Throw away noisy errors */ if (freopen("/dev/null", "w", stderr) != NULL) - AslDoOneFile((char *)aml); + AslDoOneFile((char *)tables[which]); _exit(0); break; diff --git a/src/acpica/source/compiler/fwts_iasl_interface.h b/src/acpica/source/compiler/fwts_iasl_interface.h index 71675d3..5e2647b 100644 --- a/src/acpica/source/compiler/fwts_iasl_interface.h +++ b/src/acpica/source/compiler/fwts_iasl_interface.h @@ -20,7 +20,7 @@ #ifndef __FWTS_IASL_INTERFACE__ #define __FWTS_IASL_INTERFACE__ -int fwts_iasl_disassemble_aml(const char *aml, const char *outputfile); +int fwts_iasl_disassemble_aml(char *tables[], const int table_entries, const int which, const char *outputfile); int fwts_iasl_assemble_aml(const char *source, char **stdout_output, char **stderr_output); #endif diff --git a/src/hpet/hpet_check/hpet_check.c b/src/hpet/hpet_check/hpet_check.c index 553dbc0..1a87a35 100644 --- a/src/hpet/hpet_check/hpet_check.c +++ b/src/hpet/hpet_check/hpet_check.c @@ -106,8 +106,10 @@ static void hpet_check_base_acpi_table(fwts_framework *fw, fwts_list *output; fwts_list_link *item; - if (fwts_iasl_disassemble(fw, table, which, &output) != FWTS_OK) + if (fwts_iasl_disassemble(fw, table, which, &output) != FWTS_OK) { + fwts_iasl_deinit(); return; + } if (output == NULL) return; @@ -362,11 +364,19 @@ static int hpet_check_test3(fwts_framework *fw) return FWTS_SKIP; } + if (fwts_iasl_init(fw) != FWTS_OK) { + fwts_warning(fw, "Failure to initialise iasl, aborting."); + fwts_iasl_deinit(); + return FWTS_ERROR; + } + hpet_check_base_acpi_table(fw, "DSDT", 0); - for (i = 0; i< 11; i++) + for (i = 0; i < 11; i++) hpet_check_base_acpi_table(fw, "SSDT", i); + fwts_iasl_deinit(); + return FWTS_OK; } diff --git a/src/lib/include/fwts_iasl.h b/src/lib/include/fwts_iasl.h index 5efc95c..3e103da 100644 --- a/src/lib/include/fwts_iasl.h +++ b/src/lib/include/fwts_iasl.h @@ -22,6 +22,11 @@ #include "fwts.h" +int fwts_iasl_aml_file_count(void); +char *fwts_iasl_aml_name(const int nth); +int fwts_iasl_init(fwts_framework *fw); +void fwts_iasl_deinit(void); + int fwts_iasl_disassemble_all_to_file(fwts_framework *fw, const char *path); @@ -31,8 +36,7 @@ int fwts_iasl_disassemble(fwts_framework *fw, fwts_list **ias_output); int fwts_iasl_reassemble(fwts_framework *fw, - const uint8_t *data, - const int len, + const int which, fwts_list **iasl_disassembly, fwts_list **iasl_stdout, fwts_list **iasl_stderr); diff --git a/src/lib/src/fwts_iasl.c b/src/lib/src/fwts_iasl.c index 1800912..e4a8a68 100644 --- a/src/lib/src/fwts_iasl.c +++ b/src/lib/src/fwts_iasl.c @@ -31,27 +31,59 @@ #include "fwts_iasl_interface.h" #include "fwts_acpica.h" +#define MAX_TABLES (128) + +static fwts_acpi_table_info *iasl_cached_table_info[MAX_TABLES]; +static char *iasl_cached_table_files[MAX_TABLES]; +static int iasl_cached_table_file_max = 0; +static bool iasl_init = false; + +/* + * fwts_iasl_aml_file_count() + * return number of cached dumped amlfiles + */ +int fwts_iasl_aml_file_count(void) +{ + if (iasl_init) + return iasl_cached_table_file_max; + else + return 0; +} + +/* + * fwts_iasl_aml_name() + * return back nth iASL cached table name + */ +char *fwts_iasl_aml_name(const int nth) +{ + if (iasl_init && nth < iasl_cached_table_file_max) + return iasl_cached_table_info[nth]->name; + else + return "<unknown>"; +} + /* * fwts_iasl_dump_aml_to_file() * write AML data of given length to file amlfile. */ -static int fwts_iasl_dump_aml_to_file(fwts_framework *fw, +static int fwts_iasl_dump_aml_to_file( + fwts_framework *fw, const uint8_t *data, const int length, - const char *amlfile) + const char *filename) { int fd; /* Dump the AML bytecode into a tempoary file so we can disassemble it */ - if ((fd = open(amlfile, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) { - fwts_log_error(fw, "Cannot create temporary file %s", amlfile); + if ((fd = open(filename, O_WRONLY | O_CREAT | O_EXCL, S_IWUSR | S_IRUSR)) < 0) { + fwts_log_error(fw, "Cannot create temporary file %s", filename); return FWTS_ERROR; } if (write(fd, data, length) != length) { fwts_log_error(fw, "Cannot write all data to temporary file"); close(fd); - (void)unlink(amlfile); + (void)unlink(filename); return FWTS_ERROR; } close(fd); @@ -60,42 +92,123 @@ static int fwts_iasl_dump_aml_to_file(fwts_framework *fw, } /* + * fwts_iasl_cache_table_to_file() + * to disassemble an APCPI table we need to dump it + * to file. To save effort in saving these to file + * multiple times, we dump out all the DSDT and + * SSDTs and cache the references to these. + */ +static int fwts_iasl_cache_table_to_file(fwts_framework *fw, char *tablename, int which) +{ + static pid_t pid = 0; + char tmpname[PATH_MAX]; + fwts_acpi_table_info *table; + int ret; + + if (iasl_cached_table_file_max >= MAX_TABLES) { + fwts_log_error(fw, "Temporary ACPI table lookup table full."); + return FWTS_ERROR; + } + ret = fwts_acpi_find_table(fw, tablename, which, &table); + if (ret != FWTS_OK) { + fwts_log_error(fw, "Cannot load ACPI table %s.", tablename); + return ret; + } + if (table == NULL) + return FWTS_NO_TABLE; /* Table does not exist */ + if (!pid) + pid = getpid(); + + snprintf(tmpname, sizeof(tmpname), "/tmp/fwts_tmp_table_%d_%s_%d.dsl", pid, tablename, which); + iasl_cached_table_files[iasl_cached_table_file_max] = strdup(tmpname); + if (iasl_cached_table_files[iasl_cached_table_file_max] == NULL) { + fwts_log_error(fw, "Cannot allocate cached table file name."); + return FWTS_ERROR; + } + if (fwts_iasl_dump_aml_to_file(fw, table->data, table->length, tmpname) != FWTS_OK) { + free(iasl_cached_table_files[iasl_cached_table_file_max]); + iasl_cached_table_files[iasl_cached_table_file_max] = NULL; + return FWTS_ERROR; + } + iasl_cached_table_info[iasl_cached_table_file_max] = table; + iasl_cached_table_file_max++; + return FWTS_OK; +} + +/* + * fwts_iasl_deinit() + * clean up cached files and references + */ +void fwts_iasl_deinit(void) +{ + int i; + + for (i = 0; i < iasl_cached_table_file_max; i++) { + if (iasl_cached_table_files[i]) + (void)unlink(iasl_cached_table_files[i]); + iasl_cached_table_files[i] = NULL; + iasl_cached_table_info[i] = NULL; + } + iasl_cached_table_file_max = 0; +} + +/* + * fwts_iasl_init() + * initialise iasl - cache DSDT and SSDT to file + */ +int fwts_iasl_init(fwts_framework *fw) +{ + int i; + int ret; + + fwts_iasl_deinit(); /* Ensure it is clean */ + + ret = fwts_iasl_cache_table_to_file(fw, "DSDT", 0); + if (ret != FWTS_OK) + return ret; + + for (i = 0; i < MAX_TABLES; i++) { + if (fwts_iasl_cache_table_to_file(fw, "SSDT", i) != FWTS_OK) + break; + } + + iasl_init = true; + + return FWTS_OK; +} + +/* * fwts_iasl_disassemble_to_file() * Disassemble a given table and dump disassembly to a file. * For tables where there are multiple matches, e.g. SSDT, we * specify the Nth table with 'which'. - * */ -int fwts_iasl_disassemble_to_file(fwts_framework *fw, +static int fwts_iasl_disassemble_to_file(fwts_framework *fw, const char *tablename, const int which, const char *filename) { - fwts_acpi_table_info *table; - char amlfile[PATH_MAX]; - int pid = getpid(); - int ret; - - fwts_acpcia_set_fwts_framework(fw); + int i, count, n = 0; - if ((ret = fwts_acpi_find_table(fw, tablename, which, &table)) != FWTS_OK) - return ret; + if (!iasl_init) + return FWTS_ERROR; - if (table == NULL) + /* Find Nth table of a given name */ + count = fwts_iasl_aml_file_count(); + for (i = 0; i < count; i++) { + if (!strcmp(tablename, iasl_cached_table_info[i]->name)) { + if (n == which) + break; + n++; + } + } + if (i >= count) return FWTS_NO_TABLE; - snprintf(amlfile, sizeof(amlfile), "/tmp/fwts_iasl_%d_%s.dat", pid, tablename); - - /* Dump the AML bytecode into a tempoary file so we can disassemble it */ - if (fwts_iasl_dump_aml_to_file(fw, table->data, table->length, amlfile) != FWTS_OK) - return FWTS_ERROR; + fwts_acpcia_set_fwts_framework(fw); - if (fwts_iasl_disassemble_aml(amlfile, filename) < 0) { - (void)unlink(amlfile); + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, iasl_cached_table_file_max, i, filename) < 0) return FWTS_ERROR; - } - - (void)unlink(amlfile); return FWTS_OK; } @@ -116,12 +229,14 @@ int fwts_iasl_disassemble(fwts_framework *fw, int pid = getpid(); int ret; + if (!iasl_init) + return FWTS_ERROR; if (iasl_output == NULL) return FWTS_ERROR; *iasl_output = NULL; - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d_%s.dsl", pid, tablename); + snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_disassemble_%d_%s.dsl", pid, tablename); if ((ret = fwts_iasl_disassemble_to_file(fw, tablename, which, tmpfile)) != FWTS_OK) return ret; @@ -140,32 +255,36 @@ int fwts_iasl_disassemble(fwts_framework *fw, int fwts_iasl_disassemble_all_to_file(fwts_framework *fw, const char *path) { - int i; + int i, n; int ret; char filename[PATH_MAX]; char pathname[PATH_MAX]; - if (path == NULL) - strncpy(pathname, "", sizeof(pathname)); - else - snprintf(pathname, sizeof(pathname), "%s/", path); - - snprintf(filename, sizeof(filename), "%sDSDT.dsl", pathname); - - ret = fwts_iasl_disassemble_to_file(fw, "DSDT", 0, filename); + ret = fwts_iasl_init(fw); if (ret == FWTS_ERROR_NO_PRIV) { fprintf(stderr, "Need to have root privilege to read ACPI tables from memory! Re-run using sudo.\n"); return FWTS_ERROR; } - if (ret == FWTS_OK) - printf("Disassembled DSDT to %s\n", filename); + if (ret != FWTS_OK) { + fprintf(stderr, "Could not initialise disassembler.\n"); + return FWTS_ERROR; + } - for (i=0; ;i++) { - snprintf(filename, sizeof(filename), "%sSSDT%d.dsl", pathname, i); - if (fwts_iasl_disassemble_to_file(fw, "SSDT", i, filename) != FWTS_OK) - break; - printf("Disassembled SSDT %d to %s\n", i, filename); + n = fwts_iasl_aml_file_count(); + if (path == NULL) + strncpy(pathname, "", sizeof(pathname)); + else + snprintf(pathname, sizeof(pathname), "%s/", path); + + for (i = 0; i < n; i++) { + snprintf(filename, sizeof(filename), "%s%s%d.dsl", pathname, iasl_cached_table_info[i]->name, i); + fwts_iasl_disassemble_to_file(fw, "DSDT", 0, filename); + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, iasl_cached_table_file_max, i, filename) < 0) + fprintf(stderr, "Could not disassemble %s\n", iasl_cached_table_info[i]->name); + else + printf("Disassembled %s to %s\n", iasl_cached_table_info[i]->name, filename); } + fwts_iasl_deinit(); return FWTS_OK; } @@ -177,47 +296,38 @@ int fwts_iasl_disassemble_all_to_file(fwts_framework *fw, * any re-assembly errors into list iasl_errors. */ int fwts_iasl_reassemble(fwts_framework *fw, - const uint8_t *data, - const int len, + const int which, fwts_list **iasl_disassembly, fwts_list **iasl_stdout, fwts_list **iasl_stderr) { char tmpfile[PATH_MAX]; - char amlfile[PATH_MAX]; char *stdout_output = NULL, *stderr_output = NULL; int pid = getpid(); - if ((iasl_disassembly == NULL) || + if ((!iasl_init) || + (iasl_disassembly == NULL) || (iasl_stdout == NULL) || - (iasl_stderr == NULL)) + (iasl_stderr == NULL) || + (which > iasl_cached_table_file_max)) return FWTS_ERROR; fwts_acpcia_set_fwts_framework(fw); *iasl_disassembly = NULL; - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d.dsl", pid); - snprintf(amlfile, sizeof(amlfile), "/tmp/fwts_iasl_%d.dat", pid); - - /* Dump the AML bytecode into a tempoary file so we can disassemble it */ - if (fwts_iasl_dump_aml_to_file(fw, data, len, amlfile) != FWTS_OK) - return FWTS_ERROR; + snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_reassemble_%d.dsl", pid); - if (fwts_iasl_disassemble_aml(amlfile, tmpfile) < 0) { + if (fwts_iasl_disassemble_aml(iasl_cached_table_files, iasl_cached_table_file_max, which, tmpfile) < 0) { (void)unlink(tmpfile); - (void)unlink(amlfile); return FWTS_ERROR; } - (void)unlink(amlfile); /* Read in the disassembled text to return later */ *iasl_disassembly = fwts_file_open_and_read(tmpfile); /* Now we have a disassembled source in tmpfile, so let's assemble it */ - if (fwts_iasl_assemble_aml(tmpfile, &stdout_output, &stderr_output) < 0) { - (void)unlink(amlfile); (void)unlink(tmpfile); free(stdout_output); return FWTS_ERROR; @@ -225,10 +335,9 @@ int fwts_iasl_reassemble(fwts_framework *fw, /* Remove these now we don't need them */ (void)unlink(tmpfile); - (void)unlink(amlfile); /* And remove aml file generated from ACPICA compiler */ - snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_%d.aml", pid); + snprintf(tmpfile, sizeof(tmpfile), "/tmp/fwts_iasl_reassemble_%d.aml", pid); (void)unlink(tmpfile); *iasl_stdout = fwts_list_from_text(stdout_output); @@ -237,4 +346,3 @@ int fwts_iasl_reassemble(fwts_framework *fw, return FWTS_OK; } -