From 1d5d1dc3ec6f13f7083365da198c04875c971cb6 Mon Sep 17 00:00:00 2001 From: Achilleas Anagnostopoulos Date: Fri, 13 Oct 2017 17:59:10 +0100 Subject: [PATCH] acpi: implement VM entity lookup and visit wrappers --- src/gopheros/device/acpi/aml/vm.go | 24 ++++++++++ src/gopheros/device/acpi/aml/vm_test.go | 63 +++++++++++++++++++++++++ 2 files changed, 87 insertions(+) diff --git a/src/gopheros/device/acpi/aml/vm.go b/src/gopheros/device/acpi/aml/vm.go index 3d482d4..9dae0d6 100644 --- a/src/gopheros/device/acpi/aml/vm.go +++ b/src/gopheros/device/acpi/aml/vm.go @@ -104,6 +104,30 @@ func (vm *VM) Init() *Error { return nil } +// Lookup traverses a potentially nested absolute AML path and returns the +// Entity reachable via that path or nil if the path does not point to a +// defined Entity. +func (vm *VM) Lookup(absPath string) Entity { + if absPath == "" || absPath[0] != '\\' { + return nil + } + + // If we just search for `\` return the root namespace + if len(absPath) == 1 { + return vm.rootNS + } + + return scopeFindRelative(vm.rootNS, absPath[1:]) +} + +// Visit performs a DFS on the AML namespace tree invoking the visitor for each +// encountered entity whose type matches entType. Namespace nodes are visited +// in parent to child order a property which allows the supplied visitor +// function to signal that it's children should not be visited. +func (vm *VM) Visit(entType EntityType, visitorFn Visitor) { + scopeVisit(0, vm.rootNS, entType, visitorFn) +} + // defaultACPIScopes constructs a tree of scoped entities that correspond to // the predefined scopes contained in the ACPI specification and returns back // its root node. diff --git a/src/gopheros/device/acpi/aml/vm_test.go b/src/gopheros/device/acpi/aml/vm_test.go index d71db1b..0e5fbbc 100644 --- a/src/gopheros/device/acpi/aml/vm_test.go +++ b/src/gopheros/device/acpi/aml/vm_test.go @@ -31,3 +31,66 @@ func TestVMInit(t *testing.T) { } }) } + +func TestVMObjectLookups(t *testing.T) { + resolver := &mockResolver{ + tableFiles: []string{"DSDT.aml"}, + } + vm := NewVM(os.Stderr, resolver) + if err := vm.Init(); err != nil { + t.Fatal(err) + } + + specs := []struct { + absPath string + match bool + }{ + { + ``, + false, + }, + { + `\`, + true, + }, + { + `\_SB_.PCI0.SBRG.PIC_`, + true, + }, + { + `\_SB_.PCI0.UNKNOWN_PATH`, + false, + }, + } + + for specIndex, spec := range specs { + foundMatch := vm.Lookup(spec.absPath) != nil + if foundMatch != spec.match { + t.Errorf("[spec %d] expected lookup match status to be %t", specIndex, spec.match) + } + } +} + +func TestVMVisit(t *testing.T) { + resolver := &mockResolver{ + tableFiles: []string{"parser-testsuite-DSDT.aml"}, + } + vm := NewVM(os.Stderr, resolver) + if err := vm.Init(); err != nil { + t.Fatal(err) + } + + var ( + methodCount int + expCount = 2 + ) + + vm.Visit(EntityTypeMethod, func(_ int, ent Entity) bool { + methodCount++ + return true + }) + + if methodCount != expCount { + t.Fatalf("expected visitor to be invoked for %d methods; got %d", expCount, methodCount) + } +}