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:
parent
41eae61c9f
commit
10ba4f7ad6
@ -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
|
||||
@ -698,6 +791,21 @@ func NewInvocation(tableHandle uint8, name string, args []interface{}) *Invocati
|
||||
}
|
||||
}
|
||||
|
||||
// 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
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user