diff mbox series

[v8,28/35] acpi: Record the items added to SSDT

Message ID 20200426092529.v8.28.I1f119e7a847da3e0b2b1791e6f48acaeaf25a223@changeid
State Superseded
Headers show
Series dm: Add programmatic generation of ACPI tables (part B) | expand

Commit Message

Simon Glass April 26, 2020, 3:26 p.m. UTC
It is useful to be able to control the order of data written to the SSDT
so that we can compare the output against known-good kernel dumps.

Add code to record each item that is added along with the device that
added it. That allows us to reorder things later if needed.

Signed-off-by: Simon Glass <sjg at chromium.org>
---

Changes in v8: None
Changes in v3: None
Changes in v2:
- Generalise the ACPI function recursion with acpi_recurse_method()

 drivers/core/acpi.c | 83 ++++++++++++++++++++++++++++++++++++++++++---
 1 file changed, 79 insertions(+), 4 deletions(-)
diff mbox series

Patch

diff --git a/drivers/core/acpi.c b/drivers/core/acpi.c
index 5014629ac1..e5474970a4 100644
--- a/drivers/core/acpi.c
+++ b/drivers/core/acpi.c
@@ -9,11 +9,20 @@ 
 #define LOG_CATEOGRY	LOGC_ACPI
 
 #include <common.h>
+#include <malloc.h>
 #include <dm.h>
 #include <dm/acpi.h>
 #include <dm/device-internal.h>
 #include <dm/root.h>
 
+#define MAX_ITEMS	100
+
+/* Type of table that we collected */
+enum gen_type_t {
+	TYPE_NONE,
+	TYPE_SSDT,
+};
+
 /* Type of method to call */
 enum method_t {
 	METHOD_WRITE_TABLES,
@@ -23,6 +32,25 @@  enum method_t {
 /* Prototype for all methods */
 typedef int (*acpi_method)(const struct udevice *dev, struct acpi_ctx *ctx);
 
+/**
+ * struct acpi_item - Holds info about ACPI data generated by a driver method
+ *
+ * @dev: Device that generated this data
+ * @type: Table type it refers to
+ * @buf: Buffer containing the data
+ * @size: Size of the data in bytes
+ */
+struct acpi_item {
+	struct udevice *dev;
+	enum gen_type_t type;
+	char *buf;
+	int size;
+};
+
+/* List of ACPI items collected */
+static struct acpi_item acpi_item[MAX_ITEMS];
+static int item_count;
+
 int acpi_copy_name(char *out_name, const char *name)
 {
 	strncpy(out_name, name, ACPI_NAME_LEN);
@@ -42,6 +70,43 @@  int acpi_get_name(const struct udevice *dev, char *out_name)
 	return -ENOSYS;
 }
 
+/**
+ * acpi_add_item() - Add a new item to the list of data collected
+ *
+ * @ctx: ACPI context
+ * @dev: Device that generated the data
+ * @type: Table type it refers to
+ * @start: The start of the data (the end is obtained from ctx->current)
+ * @return 0 if OK, -ENOSPC if too many items, -ENOMEM if out of memory
+ */
+static int acpi_add_item(struct acpi_ctx *ctx, struct udevice *dev,
+			 enum gen_type_t type, void *start)
+{
+	struct acpi_item *item;
+	void *end = ctx->current;
+
+	if (item_count == MAX_ITEMS) {
+		log_err("Too many items\n");
+		return log_msg_ret("mem", -ENOSPC);
+	}
+
+	item = &acpi_item[item_count];
+	item->dev = dev;
+	item->type = type;
+	item->size = end - start;
+	if (!item->size)
+		return 0;
+	item->buf = malloc(item->size);
+	if (!item->buf)
+		return log_msg_ret("mem", -ENOMEM);
+	memcpy(item->buf, start, item->size);
+	item_count++;
+	log_debug("* %s: Added type %d, %p, size %x\n", dev->name, type, start,
+		  item->size);
+
+	return 0;
+}
+
 acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
 {
 	struct acpi_ops *aops;
@@ -60,7 +125,7 @@  acpi_method acpi_get_method(struct udevice *dev, enum method_t method)
 }
 
 int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
-			enum method_t method)
+			enum method_t method, enum gen_type_t type)
 {
 	struct udevice *dev;
 	acpi_method func;
@@ -68,6 +133,8 @@  int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
 
 	func = acpi_get_method(parent, method);
 	if (func) {
+		void *start = ctx->current;
+
 		log_debug("\n");
 		log_debug("- %s %p\n", parent->name, func);
 		ret = device_ofdata_to_platdata(parent);
@@ -76,9 +143,16 @@  int acpi_recurse_method(struct acpi_ctx *ctx, struct udevice *parent,
 		ret = func(parent, ctx);
 		if (ret)
 			return log_msg_ret("func", ret);
+
+		/* Add the item to the internal list */
+		if (type != TYPE_NONE) {
+			ret = acpi_add_item(ctx, parent, type, start);
+			if (ret)
+				return log_msg_ret("add", ret);
+		}
 	}
 	device_foreach_child(dev, parent) {
-		ret = acpi_recurse_method(ctx, dev, method);
+		ret = acpi_recurse_method(ctx, dev, method, type);
 		if (ret)
 			return log_msg_ret("recurse", ret);
 	}
@@ -91,7 +165,7 @@  int acpi_fill_ssdt(struct acpi_ctx *ctx)
 	int ret;
 
 	log_debug("Writing SSDT tables\n");
-	ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT);
+	ret = acpi_recurse_method(ctx, dm_root(), METHOD_FILL_SSDT, TYPE_SSDT);
 	log_debug("Writing SSDT finished, err=%d\n", ret);
 
 	return ret;
@@ -102,7 +176,8 @@  int acpi_write_dev_tables(struct acpi_ctx *ctx)
 	int ret;
 
 	log_debug("Writing device tables\n");
-	ret = acpi_recurse_method(ctx, dm_root(), METHOD_WRITE_TABLES);
+	ret = acpi_recurse_method(ctx, dm_root(), METHOD_WRITE_TABLES,
+				  TYPE_NONE);
 	log_debug("Writing finished, err=%d\n", ret);
 
 	return ret;