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
b278ce626b
commit
3a3b980eaa
@ -451,6 +451,21 @@ func (ent *Field) SetArg(argIndex uint8, arg interface{}) bool {
|
|||||||
return ok
|
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
|
// 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
|
// index/data register pattern can be implemented. To write a value to an
|
||||||
// IndexField, the interpreter must first write the appropriate offset to
|
// 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
|
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
|
// BankField is a special field where a bank register must be used to select
|
||||||
// the appropriate bank region before accessing its contents.
|
// the appropriate bank region before accessing its contents.
|
||||||
type BankField struct {
|
type BankField struct {
|
||||||
@ -569,6 +607,29 @@ func (ent *BankField) SetArg(argIndex uint8, arg interface{}) bool {
|
|||||||
return ok
|
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.
|
// FieldUnit describes a sub-region inside a parent field.
|
||||||
type FieldUnit struct {
|
type FieldUnit struct {
|
||||||
GenericNamed
|
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
|
// 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
|
// 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
|
// 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.
|
// Method describes an invocable AML method.
|
||||||
type Method struct {
|
type Method struct {
|
||||||
Scope
|
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.
|
// Device defines an AML device entity.
|
||||||
type Device struct {
|
type Device struct {
|
||||||
Scope
|
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