aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorGerd Hoffmann <kraxel@redhat.com>2020-09-24 09:48:38 +0200
committerGerd Hoffmann <kraxel@redhat.com>2020-10-15 11:21:43 +0200
commit65f7877216b5dbba657560bc51c1870a97b29e97 (patch)
treea1330692b8a6cfc5213569979e2ae9dcfd991865
parentdebe702fe679aa21d0670382a92767d7dd14a038 (diff)
downloadseabios-65f7877216b5dbba657560bc51c1870a97b29e97.tar.gz
dsdt: track device hierarchy
Add parent entry to acpi_device struct, set it when parsing sub-devices, restore it when done. This allows to track and check for device relationships, for example the GSIn sub-devices of PCI0. Known limitation: Establishing relationship using Scope() does not work. This also makes the parser process data after sub-devices correctly, for example find _CRS in this case: Device (PCI0) { [ ... ] Device (GSI0) [ ... ] Name (_CRS, ResourceTemplate () { ... ] } Signed-off-by: Gerd Hoffmann <kraxel@redhat.com>.
-rw-r--r--src/fw/dsdt_parser.c19
-rw-r--r--src/util.h1
2 files changed, 16 insertions, 4 deletions
diff --git a/src/fw/dsdt_parser.c b/src/fw/dsdt_parser.c
index 61beeefd..fee3c090 100644
--- a/src/fw/dsdt_parser.c
+++ b/src/fw/dsdt_parser.c
@@ -18,6 +18,7 @@
struct acpi_device {
struct hlist_node node;
+ struct acpi_device *parent;
char name[16];
u8 *hid_aml;
u8 *sta_aml;
@@ -349,22 +350,25 @@ static int parse_pkg_scope(struct parse_state *s,
static int parse_pkg_device(struct parse_state *s,
u8 *ptr)
{
+ struct acpi_device *dev;
int offset, pkglength;
offset = parse_pkg_common(s, ptr, "device", &pkglength);
- s->dev = malloc_tmp(sizeof(struct acpi_device));
- if (!s->dev) {
+ dev = malloc_tmp(sizeof(struct acpi_device));
+ if (!dev) {
warn_noalloc();
s->error = 1;
return pkglength;
}
- memset(s->dev, 0, sizeof(struct acpi_device));
+ memset(dev, 0, sizeof(struct acpi_device));
+ dev->parent = s->dev;
+ s->dev = dev;
hlist_add_head(&s->dev->node, &acpi_devices);
strtcpy(s->dev->name, s->name, sizeof(s->name));
parse_termlist(s, ptr, offset, pkglength);
- s->dev = NULL;
+ s->dev = s->dev->parent;
return pkglength;
}
@@ -620,6 +624,11 @@ int acpi_dsdt_find_irq(struct acpi_device *dev, u64 *irq)
3 /* irq */, irq, &max);
}
+int acpi_dsdt_is_parent(struct acpi_device *dev, struct acpi_device *parent)
+{
+ return dev->parent == parent;
+}
+
int acpi_dsdt_present_eisaid(u16 eisaid)
{
if (!CONFIG_ACPI_PARSE)
@@ -666,6 +675,8 @@ void acpi_dsdt_parse(void)
dprintf(1, ", sta (0x%x)", dev->sta_aml[0]);
if (dev->crs_data)
dprintf(1, ", crs");
+ if (dev->parent)
+ dprintf(1, ", parent %s", acpi_dsdt_name(dev->parent));
dprintf(1, "\n");
if (dev->crs_data)
print_resources(" ", dev->crs_data, dev->crs_size);
diff --git a/src/util.h b/src/util.h
index 0de35229..d4071fc5 100644
--- a/src/util.h
+++ b/src/util.h
@@ -104,6 +104,7 @@ int acpi_dsdt_present_eisaid(u16 eisaid);
int acpi_dsdt_find_io(struct acpi_device *dev, u64 *min, u64 *max);
int acpi_dsdt_find_mem(struct acpi_device *dev, u64 *min, u64 *max);
int acpi_dsdt_find_irq(struct acpi_device *dev, u64 *irq);
+int acpi_dsdt_is_parent(struct acpi_device *dev, struct acpi_device *parent);
// fw/coreboot.c
extern const char *CBvendor, *CBpart;