[PATCH] dsddump: add utility to dump _DSDD (Device Specific Data)

Alex Hung alex.hung at canonical.com
Wed Jan 9 00:44:18 UTC 2019


Buglink: https://bugs.launchpad.net/bugs/1433643

In addition to ACPI spec, this patch also refers to two documents:

 - Device Properties UUID For _DSD
 - Hierarchical Data Extension UUID For _DSD

Both documents can be found @ http://uefi.org/acpi

Signed-off-by: Alex Hung <alex.hung at canonical.com>
---
 src/Makefile.am            |   1 +
 src/acpi/dsddump/dsddump.c | 196 +++++++++++++++++++++++++++++++++++++
 2 files changed, 197 insertions(+)
 create mode 100644 src/acpi/dsddump/dsddump.c

diff --git a/src/Makefile.am b/src/Makefile.am
index 52c637dd..8339f306 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -80,6 +80,7 @@ fwts_SOURCES = main.c 				\
 	acpi/dmar/dmar.c 			\
 	acpi/dppt/dppt.c 			\
 	acpi/drtm/drtm.c 			\
+	acpi/dsddump/dsddump.c			\
 	acpi/ecdt/ecdt.c			\
 	acpi/einj/einj.c			\
 	acpi/erst/erst.c			\
diff --git a/src/acpi/dsddump/dsddump.c b/src/acpi/dsddump/dsddump.c
new file mode 100644
index 00000000..611789b3
--- /dev/null
+++ b/src/acpi/dsddump/dsddump.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2019 Canonical
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+#include "fwts.h"
+
+#if defined(FWTS_HAS_ACPI)
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <unistd.h>
+#include <stdint.h>
+#include <inttypes.h>
+#include "fwts_acpi_object_eval.h"
+
+#define DEVICE_PROPERITY_UUID "DAFFD814-6EBA-4D8C-8A91-BC9BBF4AA301"
+#define HIERARCHICAL_DATA_EXTENSION "DBB8E3E6-5886-4BA6-8795-1319F52A966B"
+
+/*
+ *  dsddump_init()
+ *	initialize ACPI
+ */
+static int dsddump_init(fwts_framework *fw)
+{
+	if (fwts_acpi_init(fw) != FWTS_OK) {
+		fwts_log_error(fw, "Cannot initialise ACPI.");
+		return FWTS_ERROR;
+	}
+
+	return FWTS_OK;
+}
+
+/*
+ *  dsddump_deinit
+ *	de-intialize ACPI
+ */
+static int dsddump_deinit(fwts_framework *fw)
+{
+	return fwts_acpi_deinit(fw);
+}
+
+static void print_package_element(fwts_framework *fw, ACPI_OBJECT *obj)
+{
+	char full_name[128];
+	ACPI_STATUS status;
+	ACPI_BUFFER buffer;
+
+	switch (obj->Type) {
+		case ACPI_TYPE_INTEGER:
+			fwts_log_info_verbatim(fw, "    Value: 0x%8.8" PRIx64, obj->Integer.Value);
+			break;
+		case ACPI_TYPE_STRING:
+			fwts_log_info_verbatim(fw, "    Value: %s", obj->String.Pointer);
+			break;
+		case ACPI_TYPE_LOCAL_REFERENCE:
+			status = AcpiGetName(obj->Reference.Handle, ACPI_FULL_PATHNAME, &buffer);
+			if (ACPI_SUCCESS(status))
+				fwts_log_info_verbatim(fw, "    Value: %s", full_name);
+			break;
+		default:
+			fwts_log_info_verbatim(fw, "    Value: %s", "Unknown");
+			break;
+	}
+}
+
+static void parse_device_properity(fwts_framework *fw, ACPI_OBJECT *pkg)
+{
+	uint32_t i;
+
+	fwts_log_info_verbatim(fw, "  Package:");
+	for (i = 0; i < pkg->Package.Count; i++) {
+		ACPI_OBJECT *element = &pkg->Package.Elements[i];
+
+		fwts_log_info_verbatim(fw, "    Key: %s", element->Package.Elements[0].String.Pointer);
+
+		if (element->Package.Elements[1].Type == ACPI_TYPE_PACKAGE) {
+			ACPI_OBJECT *sub_pkg = &element->Package.Elements[1];
+			uint32_t j;
+
+			for (j = 0; i < sub_pkg->Package.Count; j++)
+				print_package_element(fw, &sub_pkg->Package.Elements[j]);
+		} else
+			print_package_element(fw, &element->Package.Elements[1]);
+	}
+}
+
+static void parse_hierarchical_data_ext(fwts_framework *fw, ACPI_OBJECT *pkg)
+{
+	uint32_t i;
+
+	fwts_log_info_verbatim(fw, "  Package:");
+	for (i = 0; i < pkg->Package.Count; i++) {
+		ACPI_OBJECT *element = &pkg->Package.Elements[i];
+		fwts_log_info_verbatim(fw, "    Key: %s", element->Package.Elements[0].String.Pointer);
+		print_package_element(fw, &element->Package.Elements[1]);
+	}
+}
+
+static void dsddump_package(
+	fwts_framework *fw,
+	ACPI_OBJECT *uuid,
+	ACPI_OBJECT *pkg)
+{
+	char guid[37];
+
+	fwts_guid_buf_to_str(uuid->Buffer.Pointer, guid, sizeof(guid));
+
+	if (!strncmp(guid, DEVICE_PROPERITY_UUID, sizeof(guid))) {
+		fwts_log_info_verbatim(fw, "  Device Properties UUID: %s", guid);
+		parse_device_properity(fw, pkg);
+	} else if (!strncmp(guid, HIERARCHICAL_DATA_EXTENSION, sizeof(guid))) {
+		fwts_log_info_verbatim(fw, "  Hierarchical Data Extension UUID: %s", guid);
+		parse_hierarchical_data_ext(fw, pkg);
+	}
+}
+
+static int dsddump_test1(fwts_framework *fw)
+{
+	const size_t name_len = 4;
+	fwts_list_link	*item;
+	fwts_list *objects;
+	bool found = false;
+
+	if ((objects = fwts_acpi_object_get_names()) == NULL) {
+		fwts_log_info(fw, "Cannot find any ACPI objects");
+		return FWTS_ERROR;
+	}
+
+	fwts_list_foreach(item, objects) {
+		char *name = fwts_list_data(char *, item);
+		const size_t len = strlen(name);
+
+		if (!strncmp("_DSD", name + len - name_len, name_len)) {
+			ACPI_OBJECT_LIST arg_list;
+			ACPI_OBJECT *obj;
+			ACPI_BUFFER buf;
+			uint32_t i;
+			int ret;
+
+			arg_list.Count   = 0;
+			arg_list.Pointer = NULL;
+
+			ret = fwts_acpi_object_evaluate(fw, name, &arg_list, &buf);
+			if ((ACPI_FAILURE(ret) != AE_OK) || (buf.Pointer == NULL))
+				continue;
+
+			/*  Do we have a valid buffer in the package to dump? */
+			obj = buf.Pointer;
+			if ((obj->Type == ACPI_TYPE_PACKAGE) &&
+			    (obj->Package.Count) &&
+			    (obj->Package.Elements[0].Type == ACPI_TYPE_BUFFER) &&
+			    (obj->Package.Elements[0].Buffer.Pointer != NULL) &&
+			    (obj->Package.Elements[0].Buffer.Length == 16)) {
+
+				fwts_log_info_verbatim(fw, "Name: %s", name);
+				for (i = 0; i < obj->Package.Count; i += 2)
+					dsddump_package(fw, &obj->Package.Elements[i], &obj->Package.Elements[i+1]);
+
+				fwts_log_nl(fw);
+				found = true;
+			}
+			free(buf.Pointer);
+		}
+	}
+
+	if (!found)
+		fwts_log_info_verbatim(fw, "No _DSD objects found.");
+
+	return FWTS_OK;
+}
+
+static fwts_framework_minor_test dsddump_tests[] = {
+	{ dsddump_test1, "Dump ACPI _DSD (Device Specific Data)." },
+	{ NULL, NULL }
+};
+
+static fwts_framework_ops dsddump_ops = {
+	.description = "Dump ACPI _DSD (Device Specific Data).",
+	.init        = dsddump_init,
+	.deinit      = dsddump_deinit,
+	.minor_tests = dsddump_tests
+};
+
+FWTS_REGISTER("dsddump", &dsddump_ops, FWTS_TEST_ANYTIME, FWTS_FLAG_UTILS)
+
+#endif
-- 
2.17.1




More information about the fwts-devel mailing list