diff options
author | Gerd Hoffmann <kraxel@redhat.com> | 2020-09-24 09:48:38 +0200 |
---|---|---|
committer | Gerd Hoffmann <kraxel@redhat.com> | 2020-10-15 11:21:43 +0200 |
commit | 65f7877216b5dbba657560bc51c1870a97b29e97 (patch) | |
tree | a1330692b8a6cfc5213569979e2ae9dcfd991865 | |
parent | debe702fe679aa21d0670382a92767d7dd14a038 (diff) | |
download | seabios-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.c | 19 | ||||
-rw-r--r-- | 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); @@ -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; |