@@ -9,12 +9,21 @@
#define LOG_CATEOGRY LOGC_ACPI
#include <common.h>
+#include <malloc.h>
#include <dm.h>
#include <log.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,
@@ -24,6 +33,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);
@@ -43,6 +71,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;
@@ -61,7 +126,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;
@@ -69,6 +134,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);
@@ -77,9 +144,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);
}
@@ -92,7 +166,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;
@@ -103,7 +177,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;
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 v2: None Changes in v1: - Generalise the ACPI function recursion with acpi_recurse_method() drivers/core/acpi.c | 83 ++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 79 insertions(+), 4 deletions(-)