[PATCH] lib: fwts_acpi_tables: load tables from /sys (LP: #1437043)

Colin King colin.king at canonical.com
Fri Mar 27 00:57:31 UTC 2015


From: Colin Ian King <colin.king at canonical.com>

The /dev/mem interface is going to be deprecated, so if we can't
load directly from memory then try to load from the alternative
/sys/firmware/acpi/tables raw ACPI tables.

This will address issues on ARM first, and eventually x86 when
the /dev/mem interface gets removed. I discovered this fact
at the fw-summit today.

Signed-off-by: Colin Ian King <colin.king at canonical.com>
---
 src/lib/src/fwts_acpi_tables.c | 69 ++++++++++++++++++++++++++++++++++++------
 1 file changed, 60 insertions(+), 9 deletions(-)

diff --git a/src/lib/src/fwts_acpi_tables.c b/src/lib/src/fwts_acpi_tables.c
index 35d0414..d3ef6cd 100644
--- a/src/lib/src/fwts_acpi_tables.c
+++ b/src/lib/src/fwts_acpi_tables.c
@@ -677,10 +677,17 @@ static uint8_t *fwts_acpi_load_table_from_file(const int fd, size_t *length)
 	return ptr;
 }
 
-static int fwts_acpi_load_tables_from_file(fwts_framework *fw)
+/*
+ *  fwts_acpi_load_tables_from_file_generic()
+ *	load acpi tables from a given path with a given file extention
+ */
+static int fwts_acpi_load_tables_from_file_generic(
+	fwts_framework *fw,
+	char *acpi_table_path,
+	const char *extention,
+	int *count)
 {
 	struct dirent **dir_entries;
-	int count = 0;
 	int i;
 
 	/*
@@ -688,22 +695,38 @@ static int fwts_acpi_load_tables_from_file(fwts_framework *fw)
 	 * to ensure the tables are always loaded into memory
 	 * in some form of deterministic order
 	 */
-	if ((count = scandir(fw->acpi_table_path, &dir_entries, 0, alphasort)) < 0) {
+	if ((*count = scandir(acpi_table_path, &dir_entries, 0, alphasort)) < 0) {
 		fwts_log_error(fw, "Cannot open directory '%s' to read ACPI tables.",
 			fw->acpi_table_path);
 		return FWTS_ERROR;
 	}
 
-	for (i = 0; i < count; i++) {
-		if (strstr(dir_entries[i]->d_name, ".dat")) {
+	for (i = 0; i < *count; i++) {
+		/* Ignore . directories */
+		if (dir_entries[i]->d_name[0] == '.')
+			continue;
+
+		if (strstr(dir_entries[i]->d_name, extention)) {
 			char path[PATH_MAX];
 			int fd;
 
 			snprintf(path, sizeof(path), "%s/%s",
-				fw->acpi_table_path, dir_entries[i]->d_name);
+				acpi_table_path, dir_entries[i]->d_name);
 			if ((fd = open(path, O_RDONLY)) >= 0) {
 				uint8_t *table;
 				size_t length;
+				struct stat buf;
+
+				if (fstat(fd, &buf) < 0) {
+					fwts_log_error(fw, "Cannot stat file '%s'\n", path);
+					close(fd);
+					continue;
+				}
+				/* Must be a regular file */
+				if (!S_ISREG(buf.st_mode)) {
+					close(fd);
+					continue;
+				}
 
 				if ((table = fwts_acpi_load_table_from_file(fd, &length)) != NULL) {
 					char name[9];	/* "RSD PTR " or standard ACPI 4 letter name */
@@ -749,12 +772,22 @@ static int fwts_acpi_load_tables_from_file(fwts_framework *fw)
 		free(dir_entries[i]);
 	}
 	free(dir_entries);
+	return FWTS_OK;
+}
 
+/*
+ *  fwts_acpi_load_tables_from_file()
+ *	load raw acpi tables from a user given path, files must end in ".dat"
+ */
+static int fwts_acpi_load_tables_from_file(fwts_framework *fw)
+{
+	int count;
+
+	fwts_acpi_load_tables_from_file_generic(fw, fw->acpi_table_path, ".dat", &count);
 	if (count == 0) {
 		fwts_log_error(fw, "Could not find any APCI tables in directory '%s'.\n", fw->acpi_table_path);
 		return FWTS_ERROR;
 	}
-
 	return FWTS_OK;
 }
 
@@ -976,6 +1009,20 @@ static int fwts_acpi_load_tables_fixup(fwts_framework *fw)
 	return FWTS_OK;
 }
 
+
+static int fwts_acpi_load_tables_from_sysfs(fwts_framework *fw)
+{
+	int count, total;
+	fwts_acpi_load_tables_from_file_generic(fw, "/sys/firmware/acpi/tables", "", &total);
+	fwts_acpi_load_tables_from_file_generic(fw, "/sys/firmware/acpi/tables/dynamic", "", &count);
+	total += count;
+	if (total == 0) {
+		fwts_log_error(fw, "Could not find any APCI tables in directory '/sys/firmware/acpi/tables'.\n");
+		return FWTS_ERROR;
+	}
+	return FWTS_OK;
+}
+
 /*
  *  fwts_acpi_load_tables()
  *	Load from firmware or from files in a specified directory
@@ -988,9 +1035,13 @@ int fwts_acpi_load_tables(fwts_framework *fw)
 		ret = fwts_acpi_load_tables_from_file(fw);
 	else if (fw->acpi_table_acpidump_file != NULL)
 		ret = fwts_acpi_load_tables_from_acpidump(fw);
-	else if (fwts_check_root_euid(fw, true) == FWTS_OK)
+	else if (fwts_check_root_euid(fw, true) == FWTS_OK) {
 		ret = fwts_acpi_load_tables_from_firmware(fw);
-	else
+
+		/* Load from memory failed (e.g. no /dev/mem), so try sysfs */
+		if (ret != FWTS_OK)
+			ret = fwts_acpi_load_tables_from_sysfs(fw);
+	} else
 		ret = FWTS_ERROR_NO_PRIV;
 
 	if (ret == FWTS_OK) {
-- 
2.1.4




More information about the fwts-devel mailing list