1
0
mirror of https://github.com/taigrr/gopher-os synced 2026-04-02 02:48:44 -07:00

acpi: provide more robust implementation for parsing AML method bodies

The previous implementation used brute-force approach where the parser
made an initial pass scanning the AML bytestream and looking for method
declaration opcodes. It then parsed out the method name and arg count
and populated a map which was used to detect the number of arguments to
be parsed upon encountering a method invocation. This approach proved to
be error-prone and would lead to an incorrect parse tree in the
following ASL example:

  Method (FOOF, 1, NotSerialized)
  {
    Return ("bar")
  }

  Method (TST0, 0, NotSerialized)
  {
    FOOF(0)
    \_SB.FOOF(2, 3)
  }

  Scope(\_SB){
    // Another FOOF method in \_SB which takes a different arg count
    Method (FOOF, 2, NotSerialized)
    {
      Return ("something")
    }
  }

In the above example the parser would correctly parse the first FOOF
call in TST0 but fail to parse the second invocation since the method
name contains a scope. The second invocation would actually yield the
following incorrect entity list (arguments appear as sibling entities):

Ref(\_SB.FOOF), Const(2), Const(3)

The new approach gets rid of the brute-force method and instead modifies
the initial parse of the tree not to parse the entities in the AML
method bodies but to instead track the start and end offset in the
AML stream for the body contents. In the second pass (where the parser
normally resolves symbol references), the parser can properly parse the
contents of method bodies since the entire AML tree is now known and the
parser can use the regular scope lookup rules to find the correct method
declaration for the invocation and figure out the argument count it
needs to parse.
This commit is contained in:
Achilleas Anagnostopoulos
2018-01-06 10:35:26 +00:00
parent 10ba4f7ad6
commit c09798622b
8 changed files with 155 additions and 188 deletions

View File

@@ -1,6 +1,8 @@
package entity
import "gopheros/kernel"
import (
"gopheros/kernel"
)
// Entity is an interface implemented by all AML entities.
type Entity interface {
@@ -731,6 +733,9 @@ type Method struct {
ArgCount uint8
Serialized bool
SyncLevel uint8
BodyStartOffset uint32
BodyEndOffset uint32
}
// NewMethod creats a new AML method entity.
@@ -775,37 +780,21 @@ func (ent *Method) SetArg(argIndex uint8, arg interface{}) bool {
type Invocation struct {
Generic
MethodName string
MethodDef *Method
Method *Method
}
// NewInvocation creates a new method invocation object.
func NewInvocation(tableHandle uint8, name string, args []interface{}) *Invocation {
func NewInvocation(tableHandle uint8, method *Method, args []interface{}) *Invocation {
return &Invocation{
Generic: Generic{
op: OpMethodInvocation,
tableHandle: tableHandle,
args: args,
},
MethodName: name,
Method: method,
}
}
// 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

View File

@@ -25,7 +25,7 @@ func TestEntityMethods(t *testing.T) {
{NewBankField(42), OpBankField, ""},
{NewReference(42, "TRG0"), OpName, ""},
{NewMethod(42, "FOO0"), OpMethod, "FOO0"},
{NewInvocation(42, "MTH0", nil), OpMethodInvocation, ""},
{NewInvocation(42, NewMethod(42, "MTH0"), nil), OpMethodInvocation, ""},
{NewMutex(42), OpMutex, ""},
{NewDevice(42, "DEV0"), OpDevice, "DEV0"},
{NewProcessor(42, "CPU0"), OpProcessor, "CPU0"},
@@ -283,14 +283,6 @@ func TestLazySymbolResolver(t *testing.T) {
&Reference{TargetName: "FLD0"},
"",
},
{
&Invocation{MethodName: "UNKNOWN"},
`could not resolve method invocation to: UNKNOWN; parent: \`,
},
{
&Invocation{MethodName: "MTH0"},
"",
},
}
for specIndex, spec := range specs {