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 | 	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 | ||||||
| @ -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. | // 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