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