From 65f7877216b5dbba657560bc51c1870a97b29e97 Mon Sep 17 00:00:00 2001 From: Gerd Hoffmann Date: Thu, 24 Sep 2020 09:48:38 +0200 Subject: 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 . --- src/fw/dsdt_parser.c | 19 +++++++++++++++---- src/util.h | 1 + 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; -- cgit