blob: 3a9424e7ee5ad8deaa34eee78f8d069bb1dc4eaf [file] [log] [blame]
Simon Glassebb2e832020-07-07 13:11:39 -06001// SPDX-License-Identifier: GPL-2.0
2/*
3 * Generation of tables for particular device types
4 *
5 * Copyright 2019 Google LLC
6 * Mostly taken from coreboot file of the same name
7 */
8
9#include <common.h>
10#include <dm.h>
11#include <log.h>
12#include <acpi/acpi_device.h>
13#include <dm/acpi.h>
14
15/**
16 * acpi_device_path_fill() - Find the root device and build a path from there
17 *
18 * This recursively reaches back to the root device and progressively adds path
19 * elements until the device is reached.
20 *
21 * @dev: Device to return path of
22 * @buf: Buffer to hold the path
23 * @buf_len: Length of buffer
24 * @cur: Current position in the buffer
25 * @return new position in buffer after adding @dev, or -ve on error
26 */
27static int acpi_device_path_fill(const struct udevice *dev, char *buf,
28 size_t buf_len, int cur)
29{
30 char name[ACPI_NAME_MAX];
31 int next = 0;
32 int ret;
33
34 ret = acpi_get_name(dev, name);
35 if (ret)
36 return ret;
37
38 /*
39 * Make sure this name segment will fit, including the path segment
40 * separator and possible NULL terminator, if this is the last segment.
41 */
42 if (cur + strlen(name) + 2 > buf_len)
43 return -ENOSPC;
44
45 /* Walk up the tree to the root device */
46 if (dev_get_parent(dev)) {
47 next = acpi_device_path_fill(dev_get_parent(dev), buf, buf_len,
48 cur);
49 if (next < 0)
50 return next;
51 }
52
53 /* Fill in the path from the root device */
54 next += snprintf(buf + next, buf_len - next, "%s%s",
55 dev_get_parent(dev) && *name ? "." : "", name);
56
57 return next;
58}
59
60int acpi_device_path(const struct udevice *dev, char *buf, int maxlen)
61{
62 int ret;
63
64 ret = acpi_device_path_fill(dev, buf, maxlen, 0);
65 if (ret < 0)
66 return ret;
67
68 return 0;
69}
70
71int acpi_device_scope(const struct udevice *dev, char *scope, int maxlen)
72{
73 int ret;
74
75 if (!dev_get_parent(dev))
76 return log_msg_ret("noparent", -EINVAL);
77
78 ret = acpi_device_path_fill(dev_get_parent(dev), scope, maxlen, 0);
79 if (ret < 0)
80 return log_msg_ret("fill", ret);
81
82 return 0;
83}