aboutsummaryrefslogtreecommitdiff
path: root/lib
diff options
context:
space:
mode:
Diffstat (limited to 'lib')
-rw-r--r--lib/acpi/Makefile1
-rw-r--r--lib/acpi/acpi_device.c83
2 files changed, 84 insertions, 0 deletions
diff --git a/lib/acpi/Makefile b/lib/acpi/Makefile
index 660491ef711..caae6c01bd9 100644
--- a/lib/acpi/Makefile
+++ b/lib/acpi/Makefile
@@ -1,4 +1,5 @@
# SPDX-License-Identifier: GPL-2.0+
#
+obj-y += acpi_device.o
obj-y += acpi_table.o
diff --git a/lib/acpi/acpi_device.c b/lib/acpi/acpi_device.c
new file mode 100644
index 00000000000..3a9424e7ee5
--- /dev/null
+++ b/lib/acpi/acpi_device.c
@@ -0,0 +1,83 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Generation of tables for particular device types
+ *
+ * Copyright 2019 Google LLC
+ * Mostly taken from coreboot file of the same name
+ */
+
+#include <common.h>
+#include <dm.h>
+#include <log.h>
+#include <acpi/acpi_device.h>
+#include <dm/acpi.h>
+
+/**
+ * acpi_device_path_fill() - Find the root device and build a path from there
+ *
+ * This recursively reaches back to the root device and progressively adds path
+ * elements until the device is reached.
+ *
+ * @dev: Device to return path of
+ * @buf: Buffer to hold the path
+ * @buf_len: Length of buffer
+ * @cur: Current position in the buffer
+ * @return new position in buffer after adding @dev, or -ve on error
+ */
+static int acpi_device_path_fill(const struct udevice *dev, char *buf,
+ size_t buf_len, int cur)
+{
+ char name[ACPI_NAME_MAX];
+ int next = 0;
+ int ret;
+
+ ret = acpi_get_name(dev, name);
+ if (ret)
+ return ret;
+
+ /*
+ * Make sure this name segment will fit, including the path segment
+ * separator and possible NULL terminator, if this is the last segment.
+ */
+ if (cur + strlen(name) + 2 > buf_len)
+ return -ENOSPC;
+
+ /* Walk up the tree to the root device */
+ if (dev_get_parent(dev)) {
+ next = acpi_device_path_fill(dev_get_parent(dev), buf, buf_len,
+ cur);
+ if (next < 0)
+ return next;
+ }
+
+ /* Fill in the path from the root device */
+ next += snprintf(buf + next, buf_len - next, "%s%s",
+ dev_get_parent(dev) && *name ? "." : "", name);
+
+ return next;
+}
+
+int acpi_device_path(const struct udevice *dev, char *buf, int maxlen)
+{
+ int ret;
+
+ ret = acpi_device_path_fill(dev, buf, maxlen, 0);
+ if (ret < 0)
+ return ret;
+
+ return 0;
+}
+
+int acpi_device_scope(const struct udevice *dev, char *scope, int maxlen)
+{
+ int ret;
+
+ if (!dev_get_parent(dev))
+ return log_msg_ret("noparent", -EINVAL);
+
+ ret = acpi_device_path_fill(dev_get_parent(dev), scope, maxlen, 0);
+ if (ret < 0)
+ return log_msg_ret("fill", ret);
+
+ return 0;
+}