diff options
Diffstat (limited to 'lib')
-rw-r--r-- | lib/acpi/Makefile | 1 | ||||
-rw-r--r-- | lib/acpi/acpi_device.c | 83 |
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; +} |