1
0
mirror of https://github.com/taigrr/gopher-os synced 2026-03-30 03:35:24 -07:00

acpi: tag entities with the handle of the table that defines them

This allows us to implement the Unload opcode which given a handle,
removes all entities that are tagged by it.
This commit is contained in:
Achilleas Anagnostopoulos
2017-09-27 17:24:47 +01:00
parent 2a84c75d8e
commit d020045887
3 changed files with 139 additions and 44 deletions

View File

@@ -15,11 +15,12 @@ var (
// Parser implements an AML parser.
type Parser struct {
r amlStreamReader
errWriter io.Writer
root ScopeEntity
scopeStack []ScopeEntity
tableName string
r amlStreamReader
errWriter io.Writer
root ScopeEntity
scopeStack []ScopeEntity
tableName string
tableHandle uint8
}
// NewParser returns a new AML parser instance.
@@ -31,8 +32,10 @@ func NewParser(errWriter io.Writer, rootEntity ScopeEntity) *Parser {
}
// ParseAML attempts to parse the AML byte-code contained in the supplied ACPI
// table. The parser emits any encountered errors to the specified errWriter.
func (p *Parser) ParseAML(tableName string, header *table.SDTHeader) *kernel.Error {
// table tagging each scoped entity with the supplied table handle. The parser
// emits any encountered errors to the specified errWriter.
func (p *Parser) ParseAML(tableHandle uint8, tableName string, header *table.SDTHeader) *kernel.Error {
p.tableHandle = tableHandle
p.tableName = tableName
p.r.Init(
uintptr(unsafe.Pointer(header)),
@@ -137,13 +140,16 @@ func (p *Parser) parseObj() bool {
// finalizeObj applies post-parse logic for special object types.
func (p *Parser) finalizeObj(op opcode, obj Entity) bool {
obj.setTableHandle(p.tableHandle)
switch op {
case opElse:
// If this is an else block we need to append it as an argument to the
// If block
// Pop Else block of the current scope
p.scopeCurrent().removeLastChild()
prevObj := p.scopeCurrent().lastChild()
curScope := p.scopeCurrent()
curScope.removeChild(curScope.lastChild())
prevObj := curScope.lastChild()
if prevObj.getOpcode() != opIf {
kfmt.Fprintf(p.errWriter, "[table: %s, offset: %d] encountered else block without a matching if block\n", p.tableName, p.r.Offset())
return false
@@ -203,7 +209,7 @@ func (p *Parser) parseScope(maxReadOffset uint32) bool {
}
// parseNamespacedObj reads a scope target name from the AML bytestream,
// attaches the a device or method (depending on the opcode) object to the
// attaches the device or method (depending on the opcode) object to the
// correct parent scope, enters the device scope and parses the object list
// contained in the device definition.
func (p *Parser) parseNamespacedObj(op opcode, maxReadOffset uint32) bool {
@@ -312,7 +318,10 @@ func (p *Parser) parseArgObj() (Entity, bool) {
return nil, false
}
return p.scopeCurrent().removeLastChild(), true
curScope := p.scopeCurrent()
obj := curScope.lastChild()
curScope.removeChild(obj)
return obj, true
}
func (p *Parser) makeObjForOpcode(info *opcodeInfo) Entity {
@@ -385,7 +394,8 @@ func (p *Parser) parseMethodInvocationOrNameRef() bool {
// It may be a nested invocation or named ref
ok = p.parseMethodInvocationOrNameRef()
if ok {
arg = p.scopeCurrent().removeLastChild()
arg = p.scopeCurrent().lastChild()
p.scopeCurrent().removeChild(arg)
}
}
@@ -599,8 +609,9 @@ func (p *Parser) parseFieldList(op opcode, args []interface{}, maxReadOffset uin
p.scopeCurrent().Append(&fieldUnitEntity{
fieldEntity: fieldEntity{
namedEntity: namedEntity{
op: op,
name: unitName,
tableHandle: p.tableHandle,
op: op,
name: unitName,
},
bitOffset: curBitOffset,
bitWidth: bitWidth,
@@ -618,8 +629,9 @@ func (p *Parser) parseFieldList(op opcode, args []interface{}, maxReadOffset uin
p.scopeCurrent().Append(&indexFieldEntity{
fieldEntity: fieldEntity{
namedEntity: namedEntity{
op: op,
name: unitName,
tableHandle: p.tableHandle,
op: op,
name: unitName,
},
bitOffset: curBitOffset,
bitWidth: bitWidth,
@@ -822,7 +834,9 @@ func (p *Parser) parseTarget() (interface{}, bool) {
// In this case, this is either a NameString or a control method invocation.
if ok := p.parseMethodInvocationOrNameRef(); ok {
return p.scopeCurrent().removeLastChild(), ok
obj := p.scopeCurrent().lastChild()
p.scopeCurrent().removeChild(obj)
return obj, ok
}
return nil, false