diff --git a/src/gopheros/device/acpi/aml/entity.go b/src/gopheros/device/acpi/aml/entity.go index 0e0658b..6a70839 100644 --- a/src/gopheros/device/acpi/aml/entity.go +++ b/src/gopheros/device/acpi/aml/entity.go @@ -88,10 +88,12 @@ func (ent *namedEntity) setArg(argIndex uint8, arg interface{}) bool { func (ent *namedEntity) TableHandle() uint8 { return ent.tableHandle } func (ent *namedEntity) setTableHandle(h uint8) { ent.tableHandle = h } -// constEntity is an unnamedEntity which always evaluates to a constant value. -// Calls to setArg for argument index 0 will memoize the argument value that is +// constEntity is an optionally-named entity which always +// evaluates to a constant value. Calls to setArg for +// argument index 0 will memoize the argument value that is // stored inside this entity. type constEntity struct { + name string tableHandle uint8 op opcode args []interface{} @@ -114,7 +116,7 @@ func (ent *constEntity) setOpcode(op opcode) { ent.val = uint64(1<<64 - 1) } } -func (ent *constEntity) Name() string { return "" } +func (ent *constEntity) Name() string { return ent.name } func (ent *constEntity) Parent() ScopeEntity { return ent.parent } func (ent *constEntity) setParent(parent ScopeEntity) { ent.parent = parent } func (ent *constEntity) getArgs() []interface{} { return ent.args } @@ -406,21 +408,33 @@ type namedReference struct { func (ref *namedReference) Resolve(errWriter io.Writer, rootNs ScopeEntity) bool { if ref.target == nil { - ref.target = scopeFind(ref.parent, rootNs, ref.targetName) + if ref.target = scopeFind(ref.parent, rootNs, ref.targetName); ref.target == nil { + kfmt.Fprintf(errWriter, "could not resolve referenced symbol: %s (parent: %s)\n", ref.targetName, ref.parent.Name()) + return false + } } - if ref.target == nil { - kfmt.Fprintf(errWriter, "could not resolve referenced symbol: %s (parent: %s)\n", ref.targetName, ref.parent.Name()) - } - - return ref.target != nil + return true } // methodInvocationEntity describes an AML method invocation. type methodInvocationEntity struct { unnamedEntity - methodDef *Method + methodName string + method *Method +} + +func (m *methodInvocationEntity) Resolve(errWriter io.Writer, rootNs ScopeEntity) bool { + if m.method == nil { + var isMethod bool + if m.method, isMethod = scopeFind(m.parent, rootNs, m.methodName).(*Method); !isMethod { + kfmt.Fprintf(errWriter, "could not resolve merenced method: %s (parent: %s)\n", m.methodName, m.parent.Name()) + return false + } + } + + return true } // Method defines an invocable AML method. diff --git a/src/gopheros/device/acpi/aml/entity_test.go b/src/gopheros/device/acpi/aml/entity_test.go index 7e49e97..97ea402 100644 --- a/src/gopheros/device/acpi/aml/entity_test.go +++ b/src/gopheros/device/acpi/aml/entity_test.go @@ -133,6 +133,8 @@ func TestEntityResolveErrors(t *testing.T) { &indexFieldEntity{connectionName: `\`, indexRegName: `\`, dataRegName: "DAT0"}, // Unknown reference &namedReference{unnamedEntity: unnamedEntity{parent: scope}, targetName: "TRG0"}, + // Unknown method name + &methodInvocationEntity{unnamedEntity: unnamedEntity{parent: scope}, methodName: "MTH0"}, } for specIndex, spec := range specs { @@ -141,3 +143,31 @@ func TestEntityResolveErrors(t *testing.T) { } } } + +func TestMethodInvocationResolver(t *testing.T) { + scope := &scopeEntity{name: `\`} + scope.Append(&Method{ + scopeEntity: scopeEntity{ + name: "MTH0", + }, + }) + + validInv := &methodInvocationEntity{ + methodName: "MTH0", + } + + invalidInv := &methodInvocationEntity{ + methodName: "FOO0", + } + + scope.Append(validInv) + scope.Append(invalidInv) + + if !validInv.Resolve(ioutil.Discard, scope) { + t.Fatal("expected method invocation to resolve method", validInv.methodName) + } + + if invalidInv.Resolve(ioutil.Discard, scope) { + t.Fatal("expected method invocation NOT to resolve method", invalidInv.methodName) + } +}