1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00

acpi: implement LazyRefResolver for entities that use lazy symbol references

This commit is contained in:
Achilleas Anagnostopoulos 2017-12-29 09:11:09 +00:00
parent b278ce626b
commit 3a3b980eaa
2 changed files with 195 additions and 0 deletions

View File

@ -451,6 +451,21 @@ func (ent *Field) SetArg(argIndex uint8, arg interface{}) bool {
return ok
}
// ResolveSymbolRefs receives as input the root of the AML entity tree and
// attempts to resolve any symbol references using the scope searching rules
// defined by the ACPI spec.
func (ent *Field) ResolveSymbolRefs(rootNS Container) *kernel.Error {
var ok bool
if ent.Region, ok = FindInScope(ent.Parent(), rootNS, ent.RegionName).(*Region); !ok {
return &kernel.Error{
Module: "acpi_aml_resolver",
Message: "could not resolve referenced field region: " + ent.RegionName,
}
}
return nil
}
// IndexField is a special field that groups together two field units so a
// index/data register pattern can be implemented. To write a value to an
// IndexField, the interpreter must first write the appropriate offset to
@ -508,6 +523,29 @@ func (ent *IndexField) SetArg(argIndex uint8, arg interface{}) bool {
return ok
}
// ResolveSymbolRefs receives as input the root of the AML entity tree and
// attempts to resolve any symbol references using the scope searching rules
// defined by the ACPI spec.
func (ent *IndexField) ResolveSymbolRefs(rootNS Container) *kernel.Error {
var ok bool
if ent.IndexReg, ok = FindInScope(ent.Parent(), rootNS, ent.IndexRegName).(*FieldUnit); !ok {
return &kernel.Error{
Module: "acpi_aml_resolver",
Message: "could not resolve referenced index register: " + ent.IndexRegName,
}
}
if ent.DataReg, ok = FindInScope(ent.Parent(), rootNS, ent.DataRegName).(*FieldUnit); !ok {
return &kernel.Error{
Module: "acpi_aml_resolver",
Message: "could not resolve referenced data register: " + ent.DataRegName,
}
}
return nil
}
// BankField is a special field where a bank register must be used to select
// the appropriate bank region before accessing its contents.
type BankField struct {
@ -569,6 +607,29 @@ func (ent *BankField) SetArg(argIndex uint8, arg interface{}) bool {
return ok
}
// ResolveSymbolRefs receives as input the root of the AML entity tree and
// attempts to resolve any symbol references using the scope searching rules
// defined by the ACPI spec.
func (ent *BankField) ResolveSymbolRefs(rootNS Container) *kernel.Error {
var ok bool
if ent.Region, ok = FindInScope(ent.Parent(), rootNS, ent.RegionName).(*Region); !ok {
return &kernel.Error{
Module: "acpi_aml_resolver",
Message: "could not resolve referenced field region: " + ent.RegionName,
}
}
if ent.BankFieldUnit, ok = FindInScope(ent.Parent(), rootNS, ent.BankFieldUnitName).(*FieldUnit); !ok {
return &kernel.Error{
Module: "acpi_aml_resolver",
Message: "could not resolve referenced bank register field: " + ent.BankFieldUnitName,
}
}
return nil
}
// FieldUnit describes a sub-region inside a parent field.
type FieldUnit struct {
GenericNamed
@ -609,6 +670,24 @@ func NewFieldUnit(tableHandle uint8, name string) *FieldUnit {
}
}
// ResolveSymbolRefs receives as input the root of the AML entity tree and
// attempts to resolve any symbol references using the scope searching rules
// defined by the ACPI spec.
func (ent *FieldUnit) ResolveSymbolRefs(rootNS Container) *kernel.Error {
if ent.ConnectionName == "" {
return nil
}
if ent.Connection = FindInScope(ent.Parent(), rootNS, ent.ConnectionName); ent.Connection == nil {
return &kernel.Error{
Module: "acpi_aml_resolver",
Message: "[field unit: " + ent.Name() + "] could not resolve connection reference: " + ent.ConnectionName,
}
}
return nil
}
// Reference holds a named reference to an AML symbol. The spec allows the
// symbol not to be defined at the time when the reference is parsed. In such a
// case (forward reference) it will be resolved after the entire AML stream has
@ -631,6 +710,20 @@ func NewReference(tableHandle uint8, target string) *Reference {
}
}
// ResolveSymbolRefs receives as input the root of the AML entity tree and
// attempts to resolve any symbol references using the scope searching rules
// defined by the ACPI spec.
func (ent *Reference) ResolveSymbolRefs(rootNS Container) *kernel.Error {
if ent.Target = FindInScope(ent.Parent(), rootNS, ent.TargetName); ent.Target == nil {
return &kernel.Error{
Module: "acpi_aml_vm",
Message: "could not resolve referenced symbol: " + ent.TargetName + "; parent: " + ent.Parent().Name(),
}
}
return nil
}
// Method describes an invocable AML method.
type Method struct {
Scope
@ -697,6 +790,21 @@ func NewInvocation(tableHandle uint8, name string) *Invocation {
}
}
// ResolveSymbolRefs receives as input the root of the AML entity tree and
// attempts to resolve any symbol references using the scope searching rules
// defined by the ACPI spec.
func (ent *Invocation) ResolveSymbolRefs(rootNS Container) *kernel.Error {
var ok bool
if ent.MethodDef, ok = FindInScope(ent.Parent(), rootNS, ent.MethodName).(*Method); !ok {
return &kernel.Error{
Module: "acpi_aml_vm",
Message: "could not resolve method invocation to: " + ent.MethodName + "; parent: " + ent.Parent().Name(),
}
}
return nil
}
// Device defines an AML device entity.
type Device struct {
Scope

View File

@ -214,3 +214,90 @@ nextSpec:
}
}
}
func TestLazySymbolResolver(t *testing.T) {
root := NewScope(OpScope, 42, `\`)
reg0 := NewRegion(42)
reg0.SetArg(0, "REG0")
root.Append(reg0)
root.Append(NewFieldUnit(42, "FLD0"))
root.Append(NewMethod(42, "MTH0"))
specs := []struct {
ent Entity
expErr string
}{
{
&Field{RegionName: "MISSING"},
"could not resolve referenced field region: MISSING",
},
{
&Field{RegionName: "REG0"},
"",
},
{
&IndexField{IndexRegName: "UNKNOWN"},
"could not resolve referenced index register: UNKNOWN",
},
{
&IndexField{IndexRegName: "FLD0", DataRegName: "UNKNOWN"},
"could not resolve referenced data register: UNKNOWN",
},
{
&IndexField{IndexRegName: "FLD0", DataRegName: "FLD0"},
"",
},
{
&BankField{RegionName: "MISSING"},
"could not resolve referenced field region: MISSING",
},
{
&BankField{RegionName: "REG0", BankFieldUnitName: "UNKNOWN"},
"could not resolve referenced bank register field: UNKNOWN",
},
{
&BankField{RegionName: "REG0", BankFieldUnitName: "FLD0"},
"",
},
{
&FieldUnit{
GenericNamed: GenericNamed{name: "FLD0"},
ConnectionName: "MISSING",
},
"[field unit: FLD0] could not resolve connection reference: MISSING",
},
{
// No connection reference
&FieldUnit{},
"",
},
{
&FieldUnit{ConnectionName: "FLD0"},
"",
},
{
&Reference{TargetName: "MISSING"},
`could not resolve referenced symbol: MISSING; parent: \`,
},
{
&Reference{TargetName: "FLD0"},
"",
},
{
&Invocation{MethodName: "UNKNOWN"},
`could not resolve method invocation to: UNKNOWN; parent: \`,
},
{
&Invocation{MethodName: "MTH0"},
"",
},
}
for specIndex, spec := range specs {
root.Append(spec.ent)
err := spec.ent.(LazyRefResolver).ResolveSymbolRefs(root)
if spec.expErr != "" && (err == nil || err.Message != spec.expErr) {
t.Errorf("[spec %d] expected ResolveReferences to return error %q; got: %v", specIndex, spec.expErr, err)
}
}
}