diff mbox

[1/2] lib + tests: re-work iASL backand and API to handle externals (LP: #1317390)

Message ID 1401371962-32375-2-git-send-email-colin.king@canonical.com
State Rejected
Headers show

Commit Message

Colin Ian King May 29, 2014, 1:59 p.m. UTC
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(-)

Comments

Alex Hung June 9, 2014, 8:22 a.m. UTC | #1
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>
Keng-Yu Lin July 24, 2014, 5:23 a.m. UTC | #2
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 mbox

Patch

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;
 }
-