1
0
mirror of https://github.com/taigrr/gopher-os synced 2025-01-18 04:43:13 -08:00

Merge pull request #63 from achilleasa/reimplement-aml-parser

Reimplement AML parser
This commit is contained in:
Achilleas Anagnostopoulos 2018-03-11 15:39:42 +00:00 committed by GitHub
commit b46598cb67
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
16 changed files with 12473 additions and 2 deletions

View File

@ -11,13 +11,18 @@ iso_target := $(BUILD_DIR)/kernel-$(ARCH).iso
# this: make run GO=go1.8
GO ?= go
# Prepend build path to GOPATH so the compiled packages and linter dependencies
# Prepend build path to GOPATH so the compiled packages and linter dependencies
# end up inside the build folder
GOPATH := $(BUILD_ABS_DIR):$(shell pwd):$(GOPATH)
FUZZ_PKG_LIST := src/gopheros/device/acpi/aml
# To append more entries to the above list use the following syntax
# FUZZ_PKG_LIST += path-to-pkg
ifeq ($(OS), Linux)
export SHELL := /bin/bash -o pipefail
LD := ld
AS := nasm
@ -143,7 +148,7 @@ run-vbox: iso
VBoxManage storageattach $(VBOX_VM_NAME) --storagectl "IDE Controller" --port 0 --device 0 --type dvddrive \
--medium $(iso_target) || true
VBoxManage startvm $(VBOX_VM_NAME)
# When building gdb target disable optimizations (-N) and inlining (l) of Go code
gdb: GC_FLAGS += -N -l
gdb: iso
@ -185,12 +190,28 @@ lint: lint-check-deps
src/...
lint-check-deps:
@echo [go get] installing linter dependencies
@GOPATH=$(GOPATH) $(GO) get -u -t gopkg.in/alecthomas/gometalinter.v1
@GOPATH=$(GOPATH) PATH=$(BUILD_ABS_DIR)/bin:$(PATH) gometalinter.v1 --install >/dev/null
test:
GOPATH=$(GOPATH) $(GO) test -cover gopheros/...
fuzz-deps:
@mkdir -p $(BUILD_DIR)/fuzz
@echo [go get] installing go-fuzz dependencies
@GOPATH=$(GOPATH) $(GO) get -u github.com/dvyukov/go-fuzz/...
%.fuzzpkg: %
@echo [go-fuzz] fuzzing: $<
@GOPATH=$(GOPATH) PATH=$(BUILD_ABS_DIR)/bin:$(PATH) go-fuzz-build -o $(BUILD_ABS_DIR)/fuzz/$(subst /,_,$<).zip $(subst src/,,$<)
@mkdir -p $(BUILD_ABS_DIR)/fuzz/corpus/$(subst /,_,$<)/corpus
@echo [go-fuzz] + grepping for corpus file hints in $<
@grep "go-fuzz-corpus+=" $</*fuzz.go | cut -d'=' -f2 | tr '\n' '\0' | xargs -0 -I@ sh -c 'export F="@"; cp $$F $(BUILD_ABS_DIR)/fuzz/corpus/$(subst /,_,$<)/corpus/ && echo "[go fuzz] + copy extra corpus file: $$F"'
@go-fuzz -bin=$(BUILD_ABS_DIR)/fuzz/$(subst /,_,$<).zip -workdir=$(BUILD_ABS_DIR)/fuzz/corpus/$(subst /,_,$<) 2>&1 | sed -e "s/^/ | /g"
test-fuzz: fuzz-deps $(addsuffix .fuzzpkg,$(FUZZ_PKG_LIST))
collect-coverage:
GOPATH=$(GOPATH) sh coverage.sh

View File

@ -0,0 +1,599 @@
package aml
import (
"bytes"
"gopheros/kernel/kfmt"
"io"
)
const (
// InvalidIndex is a sentinel value used by ObjectTree to indicate that
// a returned object index is not valid.
InvalidIndex uint32 = (1 << 32) - 1
// The size of AML name identifiers in bytes.
amlNameLen = 4
)
// fieldElement groups together information about a field element. This
// information can also be obtained by scanning a field element's siblings but
// it is summarized in this structure for convenience.
type fieldElement struct {
// The offset in the address space defined by parent field.
offset uint32
// The width of this field element in bits.
width uint32
accessLength uint8
_pad [3]uint8
accessType uint8
accessAttrib uint8
lockType uint8
updateType uint8
// The index of an Object to use as a connection target. Used only for
// GenericSerialBus and GeneralPurposeIO operation regions.
connectionIndex uint32
// The index of the Field (pOpField, pOpIndexField or pOpBankField) that this
// field element belongs to. According to the spec, named fields appear
// at the same scope as their parent.
fieldIndex uint32
}
// Object describes an entity encoded in the AML bytestream.
type Object struct {
// The AML ocode that describes this oBject.
opcode uint16
// The Index in the opcodeTable for this opcode
infoIndex uint8
// The table handle which contains this entity.
tableHandle uint8
// Named AML entities provide a fixed-width name which is padded by '_' chars.
name [amlNameLen]byte
// The following indices refer to other Objects in the ObjectTree
// that allocated this Object instance. Uninitialized indices are
// represented via a math.MaxUint32 value.
index uint32
parentIndex uint32
prevSiblingIndex uint32
nextSiblingIndex uint32
firstArgIndex uint32
lastArgIndex uint32
// The byte offset in the AML stream where this opcode is defined.
amlOffset uint32
// A non-zero value for pkgEnd indicates that this opcode requires deferred
// parsing due to its potentially ambiguous contents.
pkgEnd uint32
// A value placeholder for entites that contain values (e.g. int
// or string constants byte slices e.t.c)
value interface{}
}
// ObjectTree is a structure that contains a tree of AML entities where each
// entity is allocated from a contiguous Object pool. Index #0 of the pool
// contains the root scope ('\') of the AML tree.
type ObjectTree struct {
objPool []*Object
freeListHeadIndex uint32
}
// NewObjectTree returns a new ObjectTree instance.
func NewObjectTree() *ObjectTree {
return &ObjectTree{
freeListHeadIndex: InvalidIndex,
}
}
// CreateDefaultScopes populates the Object pool with the default scopes
// specified by the ACPI standard:
//
// +-[\] (Root scope)
// +- [_GPE] (General events in GPE register block)
// +- [_PR_] (ACPI 1.0 processor namespace)
// +- [_SB_] (System bus with all device objects)
// +- [_SI_] (System indicators)
// +- [_TZ_] (ACPI 1.0 thermal zone namespace)
func (tree *ObjectTree) CreateDefaultScopes(tableHandle uint8) {
root := tree.newNamedObject(pOpIntScopeBlock, tableHandle, [amlNameLen]byte{'\\'})
tree.append(root, tree.newNamedObject(pOpIntScopeBlock, tableHandle, [amlNameLen]byte{'_', 'G', 'P', 'E'})) // General events in GPE register block
tree.append(root, tree.newNamedObject(pOpIntScopeBlock, tableHandle, [amlNameLen]byte{'_', 'P', 'R', '_'})) // ACPI 1.0 processor namespace
tree.append(root, tree.newNamedObject(pOpIntScopeBlock, tableHandle, [amlNameLen]byte{'_', 'S', 'B', '_'})) // System bus with all device objects
tree.append(root, tree.newNamedObject(pOpIntScopeBlock, tableHandle, [amlNameLen]byte{'_', 'S', 'I', '_'})) // System indicators
tree.append(root, tree.newNamedObject(pOpIntScopeBlock, tableHandle, [amlNameLen]byte{'_', 'T', 'Z', '_'})) // ACPI 1.0 thermal zone namespace
}
// newObject allocates a new Object from the Object pool, populates its
// contents and returns back a pointer to it.
func (tree *ObjectTree) newObject(opcode uint16, tableHandle uint8) *Object {
var obj *Object
// Check the free list first
if tree.freeListHeadIndex != InvalidIndex {
obj = tree.objPool[tree.freeListHeadIndex]
tree.freeListHeadIndex = obj.nextSiblingIndex
} else {
// Allocate new object and attach it to the pool
obj = new(Object)
obj.index = uint32(len(tree.objPool))
tree.objPool = append(tree.objPool, obj)
}
obj.opcode = opcode
obj.infoIndex = pOpcodeTableIndex(opcode, true)
obj.tableHandle = tableHandle
obj.parentIndex = InvalidIndex
obj.prevSiblingIndex = InvalidIndex
obj.nextSiblingIndex = InvalidIndex
obj.firstArgIndex = InvalidIndex
obj.lastArgIndex = InvalidIndex
obj.value = nil
return obj
}
// newNamedObject allocates a new Object from the Object pool, populates its
// name and returns back a pointer to it.
func (tree *ObjectTree) newNamedObject(opcode uint16, tableHandle uint8, name [amlNameLen]byte) *Object {
obj := tree.newObject(opcode, tableHandle)
obj.name = name
return obj
}
// append appends arg to obj's argument list.
func (tree *ObjectTree) append(obj, arg *Object) {
arg.parentIndex = obj.index
if obj.lastArgIndex == InvalidIndex {
obj.firstArgIndex = arg.index
obj.lastArgIndex = arg.index
return
}
LastArg := tree.ObjectAt(obj.lastArgIndex)
LastArg.nextSiblingIndex = arg.index
arg.prevSiblingIndex = LastArg.index
arg.nextSiblingIndex = InvalidIndex
obj.lastArgIndex = arg.index
}
// appendAfter appends arg to obj's argument list after nextTo.
func (tree *ObjectTree) appendAfter(obj, arg, nextTo *Object) {
// nextTo is the last arg of obj; this is equivalent to a regular append
if nextTo.nextSiblingIndex == InvalidIndex {
tree.append(obj, arg)
return
}
arg.parentIndex = obj.index
arg.prevSiblingIndex = nextTo.index
arg.nextSiblingIndex = nextTo.nextSiblingIndex
tree.ObjectAt(arg.nextSiblingIndex).prevSiblingIndex = arg.index
nextTo.nextSiblingIndex = arg.index
}
// free appends obj to the tree's free object list allowing it to be re-used by
// future calls to NewObject and NewNamedObject. Callers must ensure that any
// held pointers to the object are not used after calling free.
func (tree *ObjectTree) free(obj *Object) {
if obj.parentIndex != InvalidIndex {
tree.detach(tree.ObjectAt(obj.parentIndex), obj)
}
if obj.firstArgIndex != InvalidIndex || obj.lastArgIndex != InvalidIndex {
panic("aml.ObjectTree: attempted to free object that still contains argument references")
}
// Push the object to the top of the free list and change its opcode to
// indicate this is a freed node
obj.opcode = pOpIntFreedObject
obj.nextSiblingIndex = tree.freeListHeadIndex
tree.freeListHeadIndex = obj.index
}
// detach detaches arg from obj's argument list.
func (tree *ObjectTree) detach(obj, arg *Object) {
if obj.firstArgIndex == arg.index {
obj.firstArgIndex = arg.nextSiblingIndex
}
if obj.lastArgIndex == arg.index {
obj.lastArgIndex = arg.prevSiblingIndex
}
if arg.nextSiblingIndex != InvalidIndex {
tree.ObjectAt(arg.nextSiblingIndex).prevSiblingIndex = arg.prevSiblingIndex
}
if arg.prevSiblingIndex != InvalidIndex {
tree.ObjectAt(arg.prevSiblingIndex).nextSiblingIndex = arg.nextSiblingIndex
}
arg.prevSiblingIndex = InvalidIndex
arg.nextSiblingIndex = InvalidIndex
arg.parentIndex = InvalidIndex
}
// ObjectAt returns a pointer to the Object at the specified index or nil if
// no object with this index exists inside the object tree.
func (tree *ObjectTree) ObjectAt(index uint32) *Object {
if index >= uint32(len(tree.objPool)) {
return nil
}
obj := tree.objPool[index]
if obj.opcode == pOpIntFreedObject {
return nil
}
return obj
}
// Find attempts to resolve the given expression into an Object using the rules
// specified in page 252 of the ACPI 6.2 spec:
//
// There are two types of namespace paths: an absolute namespace path (that is,
// one that starts with a \ prefix), and a relative namespace path (that is,
// one that is relative to the current namespace). The namespace search rules
// discussed above, only apply to single NameSeg paths, which is a relative
// namespace path. For those relative name paths that contain multiple NameSegs
// or Parent Prefixes, ^, the search rules do not apply. If the search rules
// do not apply to a relative namespace path, the namespace object is looked up
// relative to the current namespace
func (tree *ObjectTree) Find(scopeIndex uint32, expr []byte) uint32 {
exprLen := len(expr)
if exprLen == 0 || scopeIndex == InvalidIndex {
return InvalidIndex
}
switch {
case expr[0] == '\\': // relative to the root scope
// Name was just `\`; this matches the root namespace
if exprLen == 1 {
return 0
}
return tree.findRelative(0, expr[1:])
case expr[0] == '^': // relative to the parent scope(s)
for startIndex := 0; startIndex < exprLen; startIndex++ {
switch expr[startIndex] {
case '^':
// Mpve up one parent. If we were at the root scope
// then the lookup failed.
if scopeIndex = tree.ObjectAt(scopeIndex).parentIndex; scopeIndex == InvalidIndex {
return InvalidIndex
}
default:
// Found the start of the name. Look it up relative to current scope
return tree.findRelative(scopeIndex, expr[startIndex:])
}
}
// Name was just a sequence of '^'; this matches the last scopeIndex value
return scopeIndex
case exprLen > amlNameLen:
// The expression consists of multiple name segments joined together (e.g. FOOFBAR0)
// In this case we need to apply relative lookup rules for FOOF.BAR0
return tree.findRelative(scopeIndex, expr)
case exprLen == amlNameLen:
// expr is a simple name. According to the spec, we need to
// search for it in this scope and all its parent scopes till
// we reach the root.
for nextScopeIndex := scopeIndex; nextScopeIndex != InvalidIndex; nextScopeIndex = tree.ObjectAt(nextScopeIndex).parentIndex {
scopeObj := tree.ObjectAt(nextScopeIndex)
checkNextSibling:
for nextIndex := scopeObj.firstArgIndex; nextIndex != InvalidIndex; nextIndex = tree.ObjectAt(nextIndex).nextSiblingIndex {
obj := tree.ObjectAt(nextIndex)
for byteIndex := 0; byteIndex < amlNameLen; byteIndex++ {
if expr[byteIndex] != obj.name[byteIndex] {
continue checkNextSibling
}
}
// Found match
return obj.index
}
}
}
// Not found
return InvalidIndex
}
// findRelative attempts to resolve an object using relative scope lookup rules.
func (tree *ObjectTree) findRelative(scopeIndex uint32, expr []byte) uint32 {
exprLen := len(expr)
nextSegment:
for segIndex := 0; segIndex < exprLen; segIndex += amlNameLen {
// If expr contains a dual or multinamed path then we may encounter special
// prefix chars in the stream (the parser extracts the raw data). In this
// case skip over them.
for ; segIndex < exprLen && expr[segIndex] != '_' && (expr[segIndex] < 'A' || expr[segIndex] > 'Z'); segIndex++ {
}
if exprLen-segIndex < amlNameLen {
return InvalidIndex
}
// Search current scope for an entity matching the next name segment
scopeObj := tree.ObjectAt(scopeIndex)
checkNextSibling:
for nextIndex := scopeObj.firstArgIndex; nextIndex != InvalidIndex; nextIndex = tree.ObjectAt(nextIndex).nextSiblingIndex {
obj := tree.ObjectAt(nextIndex)
for byteIndex := 0; byteIndex < amlNameLen; byteIndex++ {
if expr[segIndex+byteIndex] != obj.name[byteIndex] {
continue checkNextSibling
}
}
// Found match; set match as the next scope index and
// try to match the next segment
scopeIndex = nextIndex
continue nextSegment
}
// Failed to match next segment. Lookup failed
return InvalidIndex
}
// scopeIndex contains the index of the last matched name in the expression
// which is the target we were looking for.
return scopeIndex
}
// ClosestNamedAncestor returns the index of the first named object that is an
// ancestor of obj. If any of obj's parents are unresolved scope directives
// then the call will return InvalidIndex.
func (tree *ObjectTree) ClosestNamedAncestor(obj *Object) uint32 {
if obj == nil {
return InvalidIndex
}
for ancestorIndex := obj.parentIndex; ancestorIndex != InvalidIndex; {
ancestor := tree.ObjectAt(ancestorIndex)
if ancestor.opcode == pOpScope {
break
}
if pOpcodeTable[ancestor.infoIndex].flags&pOpFlagNamed != 0 {
return ancestorIndex
}
ancestorIndex = ancestor.parentIndex
}
return InvalidIndex
}
// NumArgs returns the number of arguments contained in obj.
func (tree *ObjectTree) NumArgs(obj *Object) uint32 {
if obj == nil {
return 0
}
var argCount uint32
for siblingIndex := obj.firstArgIndex; siblingIndex != InvalidIndex; siblingIndex = tree.ObjectAt(siblingIndex).nextSiblingIndex {
argCount++
}
return argCount
}
// ArgAt returns a pointer to obj's arg located at index.
func (tree *ObjectTree) ArgAt(obj *Object, index uint32) *Object {
if obj == nil {
return nil
}
for argIndex, siblingIndex := uint32(0), obj.firstArgIndex; siblingIndex != InvalidIndex; argIndex, siblingIndex = argIndex+1, tree.ObjectAt(siblingIndex).nextSiblingIndex {
if argIndex == index {
return tree.ObjectAt(siblingIndex)
}
}
return nil
}
// PrettyPrint outputs a pretty-printed version of the AML tree to w.
func (tree *ObjectTree) PrettyPrint(w io.Writer) {
if len(tree.objPool) != 0 {
var padBuf bytes.Buffer
padBuf.WriteByte(' ')
tree.toString(w, &padBuf, 0)
}
}
func (tree *ObjectTree) toString(w io.Writer, padBuf *bytes.Buffer, index uint32) {
curObj := tree.ObjectAt(index)
_, _ = w.Write(padBuf.Bytes())
kfmt.Fprintf(w, "+- [%s", pOpcodeName(curObj.opcode))
if name := nameOf(curObj); len(name) != 0 {
kfmt.Fprintf(w, ", name: \"%s\"", name)
}
if curObj.opcode == pOpMethod {
kfmt.Fprintf(w, ", argCount: %d", uint8(tree.ArgAt(curObj, 1).value.(uint64)&0x7))
}
kfmt.Fprintf(w, ", table: %d, index: %d, offset: 0x%x", curObj.tableHandle, curObj.index, curObj.amlOffset)
kfmt.Fprintf(w, "]")
if curObj.opcode == pOpIntMethodCall {
methodObj := tree.ObjectAt(curObj.value.(uint32))
argCount := uint8(tree.ArgAt(methodObj, 1).value.(uint64) & 0x7)
kfmt.Fprintf(w, " -> [call to \"%s\", argCount: %d, table: %d, index: %d, offset: 0x%x]", methodObj.name[:], argCount, methodObj.tableHandle, methodObj.index, methodObj.amlOffset)
} else if curObj.opcode == pOpIntResolvedNamePath {
resolvedObj := tree.ObjectAt(curObj.value.(uint32))
kfmt.Fprintf(w, " -> [resolved to \"%s\", table: %d, index: %d, offset: 0x%x]", nameOf(resolvedObj), resolvedObj.tableHandle, resolvedObj.index, resolvedObj.amlOffset)
} else if curObj.opcode == pOpIntNamedField {
field := curObj.value.(*fieldElement)
kfmt.Fprintf(w, " -> [field index: %d, offset(bytes): 0x%x, width(bits): 0x%x, accType: ", field.fieldIndex, field.offset, field.width)
switch field.accessType {
case 0x00:
kfmt.Fprintf(w, "Any")
case 0x01:
kfmt.Fprintf(w, "Byte")
case 0x02:
kfmt.Fprintf(w, "Word")
case 0x03:
kfmt.Fprintf(w, "Dword")
case 0x04:
kfmt.Fprintf(w, "Qword")
case 0x05:
kfmt.Fprintf(w, "Buffer, accAttr: ")
switch field.accessAttrib {
case 0x02:
kfmt.Fprintf(w, "Quick")
case 0x04:
kfmt.Fprintf(w, "SendReceive")
case 0x06:
kfmt.Fprintf(w, "Byte")
case 0x08:
kfmt.Fprintf(w, "Word")
case 0x0a:
kfmt.Fprintf(w, "Block")
case 0x0b:
kfmt.Fprintf(w, "Bytes(0x%x)", field.accessLength)
case 0x0c:
kfmt.Fprintf(w, "ProcessCall")
case 0x0d:
kfmt.Fprintf(w, "BlockProcessCall")
case 0x0e:
kfmt.Fprintf(w, "RawBytes(0x%x)", field.accessLength)
case 0x0f:
kfmt.Fprintf(w, "RawProcessBytes(0x%x)", field.accessLength)
}
/*
case 0x40:
kfmt.Fprintf(w, "Bytes(0x%x)", field.AccessAttrib)
case 0x80:
kfmt.Fprintf(w, "RawBytes(0x%x)", field.AccessAttrib)
case 0xc0:
kfmt.Fprintf(w, "RawProcessBytes(0x%x)", field.AccessAttrib)
*/
}
kfmt.Fprintf(w, ", lockType: ")
switch field.lockType {
case 0x00:
kfmt.Fprintf(w, "NoLock")
case 0x01:
kfmt.Fprintf(w, "Lock")
}
kfmt.Fprintf(w, ", updateType: ")
switch field.updateType {
case 0x00:
kfmt.Fprintf(w, "Preserve")
case 0x01:
kfmt.Fprintf(w, "WriteAsOnes")
case 0x02:
kfmt.Fprintf(w, "WriteAsZeroes")
}
switch field.connectionIndex {
case InvalidIndex:
kfmt.Fprintf(w, ", connection: -]")
default:
kfmt.Fprintf(w, ", connection: index %d]", field.connectionIndex)
}
} else if curObj.opcode == pOpStringPrefix {
kfmt.Fprintf(w, " -> [string value: \"%s\"]", curObj.value.([]byte))
} else if curObj.opcode == pOpIntNamePath {
kfmt.Fprintf(w, " -> [namepath: \"%s\"]", curObj.value.([]byte))
} else if curObj.value != nil {
switch v := curObj.value.(type) {
case uint64:
kfmt.Fprintf(w, " -> [num value; dec: %d, hex: 0x%x]", v, v)
// If this is an encoded EISA id convert it back to a string
if curObj.opcode == pOpDwordPrefix && tree.ObjectAt(curObj.parentIndex).name == [amlNameLen]byte{'_', 'H', 'I', 'D'} {
// Poor-man's ntohl
id := uint32((v>>24)&0xff) |
uint32((v>>16)&0xff)<<8 |
uint32((v>>8)&0xff)<<16 |
uint32(v&0xff)<<24
var eisaID = [7]byte{
'@' + (byte)((id>>26)&0x1f),
'@' + (byte)((id>>21)&0x1f),
'@' + (byte)((id>>16)&0x1f),
hexToASCII(id >> 12),
hexToASCII(id >> 8),
hexToASCII(id >> 4),
hexToASCII(id),
}
kfmt.Fprintf(w, " [EISA: \"%s\"]", eisaID[:])
}
case []byte:
kfmt.Fprintf(w, " -> [bytelist value; len: %d; data: [", len(v))
for i, b := range v {
if i != 0 {
kfmt.Fprintf(w, ", ")
}
kfmt.Fprintf(w, "0x%x", uint8(b))
}
kfmt.Fprintf(w, "]]")
}
}
kfmt.Fprintf(w, "\n")
padLen := padBuf.Len()
if curObj.nextSiblingIndex == InvalidIndex {
padBuf.WriteByte(' ')
} else {
padBuf.WriteByte('|')
}
padBuf.WriteByte(' ')
padBuf.WriteByte(' ')
for argIndex := curObj.firstArgIndex; argIndex != InvalidIndex; argIndex = tree.ObjectAt(argIndex).nextSiblingIndex {
tree.toString(w, padBuf, argIndex)
}
padBuf.Truncate(padLen)
}
func hexToASCII(val uint32) byte {
v := byte(val & 0xf)
if v <= 9 {
return '0' + v
}
return 'A' + (v - 0xa)
}
func nameOf(obj *Object) []byte {
var nameStartIndex, nameEndIndex int
for ; nameStartIndex < amlNameLen; nameStartIndex++ {
if ch := obj.name[nameStartIndex]; (ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '\\' {
break
}
}
for nameEndIndex = nameStartIndex; nameEndIndex < amlNameLen; nameEndIndex++ {
if ch := obj.name[nameEndIndex]; !((ch >= 'A' && ch <= 'Z') || (ch >= '0' && ch <= '9') || ch == '_' || ch == '\\') {
break
}
}
if nameStartIndex != amlNameLen {
return obj.name[nameStartIndex:nameEndIndex]
}
return nil
}

View File

@ -0,0 +1,434 @@
package aml
import (
"fmt"
"testing"
)
func TestTreeObjectAt(t *testing.T) {
tree := NewObjectTree()
root := tree.newObject(pOpIntScopeBlock, 0)
obj1 := tree.newObject(pOpIntScopeBlock, 1)
tree.append(root, obj1)
if got := tree.ObjectAt(obj1.index); got != obj1 {
t.Fatalf("expected to get back obj1; got %#+v", got)
}
if got := tree.ObjectAt(obj1.index + 1); got != nil {
t.Fatalf("expected to get nil; got %#+v", got)
}
tree.free(obj1)
if got := tree.ObjectAt(obj1.index); got != nil {
t.Fatalf("expected to get back nil after freeing obj1; got %#+v", got)
}
}
func TestTreeFreelist(t *testing.T) {
tree := NewObjectTree()
root := tree.newObject(pOpIntScopeBlock, 0)
obj1 := tree.newObject(pOpIntScopeBlock, 1)
obj2 := tree.newObject(pOpIntScopeBlock, 2)
obj3 := tree.newObject(pOpIntScopeBlock, 3)
tree.append(root, obj1)
tree.append(root, obj2)
tree.append(root, obj3)
// By freeing these objects they will be re-used by the following NewObject
// calls in LIFO order.
obj2Index := obj2.index
obj3Index := obj3.index
tree.free(obj3)
tree.free(obj2)
newObj := tree.newObject(pOpIntScopeBlock, 4)
if newObj.index != obj2Index {
t.Errorf("expected object index to be %d; got %d", obj2Index, newObj.index)
}
newObj = tree.newObject(pOpIntScopeBlock, 4)
if newObj.index != obj3Index {
t.Errorf("expected object index to be %d; got %d", obj3Index, newObj.index)
}
if tree.freeListHeadIndex != InvalidIndex {
t.Errorf("expected free list head index to be InvalidIndex; got %d", tree.freeListHeadIndex)
}
}
func TestTreeFreelistPanic(t *testing.T) {
tree := NewObjectTree()
tree.CreateDefaultScopes(42)
defer func() {
expErr := "aml.ObjectTree: attempted to free object that still contains argument references"
if err := recover(); err != expErr {
t.Fatalf("expected call to Free to panic with: %s; got: %v", expErr, err)
}
}()
// Call should panic as root contains argument references
tree.free(tree.ObjectAt(0))
}
func TestTreeAppend(t *testing.T) {
tree := NewObjectTree()
root := tree.newObject(pOpIntScopeBlock, 0)
obj1 := tree.newObject(pOpIntScopeBlock, 1)
obj2 := tree.newObject(pOpIntScopeBlock, 2)
obj3 := tree.newObject(pOpIntScopeBlock, 3)
if root.firstArgIndex != InvalidIndex || root.lastArgIndex != InvalidIndex {
t.Fatal("expected root First/Last arg indices to be InvalidIndex")
}
tree.append(root, obj1)
if root.firstArgIndex != obj1.index || root.lastArgIndex != obj1.index {
t.Fatal("expected root First/Last arg indices to point to obj1")
}
if obj1.parentIndex != root.index {
t.Fatal("expected obj1 parent index to point to root")
}
if obj1.firstArgIndex != InvalidIndex || obj1.lastArgIndex != InvalidIndex {
t.Fatal("expected obj1 First/Last arg indices to be InvalidIndex")
}
// Attach the remaining pointers and follow the links both ways
tree.append(root, obj2)
tree.append(root, obj3)
visitedObjects := 0
for i := root.firstArgIndex; i != InvalidIndex; i = tree.ObjectAt(i).nextSiblingIndex {
visitedObjects++
}
if want := 3; visitedObjects != want {
t.Fatalf("expected to visit %d objects in left -> right traversal; visited %d", want, visitedObjects)
}
visitedObjects = 0
for i := root.lastArgIndex; i != InvalidIndex; i = tree.ObjectAt(i).prevSiblingIndex {
visitedObjects++
}
if want := 3; visitedObjects != want {
t.Fatalf("expected to visit %d objects in right -> left traversal; visited %d", want, visitedObjects)
}
}
func TestTreeAppendAfter(t *testing.T) {
tree := NewObjectTree()
root := tree.newObject(pOpIntScopeBlock, 0)
obj1 := tree.newObject(pOpIntScopeBlock, 1)
obj2 := tree.newObject(pOpIntScopeBlock, 2)
obj3 := tree.newObject(pOpIntScopeBlock, 3)
if root.firstArgIndex != InvalidIndex || root.lastArgIndex != InvalidIndex {
t.Fatal("expected root First/Last arg indices to be InvalidIndex")
}
tree.append(root, obj1)
tree.appendAfter(root, obj2, obj1)
tree.appendAfter(root, obj3, obj1)
expIndexList := []uint32{obj1.index, obj3.index, obj2.index}
visitedObjects := 0
for i := root.firstArgIndex; i != InvalidIndex; i = tree.ObjectAt(i).nextSiblingIndex {
if i != expIndexList[visitedObjects] {
t.Fatalf("expected arg %d to have index %d; got %d", visitedObjects, expIndexList[visitedObjects], i)
}
visitedObjects++
}
if want := 3; visitedObjects != want {
t.Fatalf("expected to visit %d objects in left -> right traversal; visited %d", want, visitedObjects)
}
}
func TestTreeDetach(t *testing.T) {
tree := NewObjectTree()
root := tree.newObject(pOpIntScopeBlock, 0)
obj1 := tree.newObject(pOpIntScopeBlock, 1)
obj2 := tree.newObject(pOpIntScopeBlock, 2)
obj3 := tree.newObject(pOpIntScopeBlock, 3)
t.Run("detach in reverse order", func(t *testing.T) {
tree.append(root, obj1)
tree.append(root, obj2)
tree.append(root, obj3)
tree.detach(root, obj3)
if root.firstArgIndex != obj1.index || root.lastArgIndex != obj2.index {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", obj1.index, obj2.index, root.firstArgIndex, root.lastArgIndex)
}
tree.detach(root, obj2)
if root.firstArgIndex != obj1.index || root.lastArgIndex != obj1.index {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", obj1.index, obj1.index, root.firstArgIndex, root.lastArgIndex)
}
tree.detach(root, obj1)
if root.firstArgIndex != InvalidIndex || root.lastArgIndex != InvalidIndex {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", InvalidIndex, InvalidIndex, root.firstArgIndex, root.lastArgIndex)
}
})
t.Run("detach in insertion order", func(t *testing.T) {
tree.append(root, obj1)
tree.append(root, obj2)
tree.append(root, obj3)
tree.detach(root, obj1)
if root.firstArgIndex != obj2.index || root.lastArgIndex != obj3.index {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", obj2.index, obj3.index, root.firstArgIndex, root.lastArgIndex)
}
tree.detach(root, obj2)
if root.firstArgIndex != obj3.index || root.lastArgIndex != obj3.index {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", obj3.index, obj3.index, root.firstArgIndex, root.lastArgIndex)
}
tree.detach(root, obj3)
if root.firstArgIndex != InvalidIndex || root.lastArgIndex != InvalidIndex {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", InvalidIndex, InvalidIndex, root.firstArgIndex, root.lastArgIndex)
}
})
t.Run("detach middle node and then edges", func(t *testing.T) {
tree.append(root, obj1)
tree.append(root, obj2)
tree.append(root, obj3)
tree.detach(root, obj2)
if root.firstArgIndex != obj1.index || root.lastArgIndex != obj3.index {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", obj1.index, obj3.index, root.firstArgIndex, root.lastArgIndex)
}
if obj1.nextSiblingIndex != obj3.index {
t.Fatalf("expected obj1 NextSiblingIndex to be %d; got %d", obj3.index, obj1.nextSiblingIndex)
}
if obj3.prevSiblingIndex != obj1.index {
t.Fatalf("expected obj3 PrevSiblingIndex to be %d; got %d", obj1.index, obj3.prevSiblingIndex)
}
tree.detach(root, obj1)
if root.firstArgIndex != obj3.index || root.lastArgIndex != obj3.index {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", obj3.index, obj3.index, root.firstArgIndex, root.lastArgIndex)
}
tree.detach(root, obj3)
if root.firstArgIndex != InvalidIndex || root.lastArgIndex != InvalidIndex {
t.Fatalf("unexpected first/last indices: want (%d, %d); got (%d, %d)", InvalidIndex, InvalidIndex, root.firstArgIndex, root.lastArgIndex)
}
})
}
func TestFind(t *testing.T) {
tree, scopeMap := genTestScopes()
specs := []struct {
curScope uint32
expr string
want uint32
}{
// Search rules do not apply for these cases
{
scopeMap["PCI0"],
`\`,
scopeMap[`\`],
},
{
scopeMap["PCI0"],
"IDE0_ADR",
scopeMap["_ADR"],
},
{
scopeMap["IDE0"],
"^^PCI0IDE0_ADR",
scopeMap["_ADR"],
},
{
scopeMap["IDE0"],
`\_SB_PCI0IDE0_ADR`,
scopeMap["_ADR"],
},
// Raw multi-segment path (prefix 0x2f, segCount: 3)
{
scopeMap["_ADR"],
fmt.Sprintf("\\%c%c_SB_PCI0IDE0", 0x2f, 0x03),
scopeMap["IDE0"],
},
{
scopeMap["IDE0"],
`\_SB_PCI0`,
scopeMap["PCI0"],
},
{
scopeMap["IDE0"],
`^`,
scopeMap["PCI0"],
},
// Bad queries
{
scopeMap["_SB_"],
"PCI0USB0_CRS",
InvalidIndex,
},
{
scopeMap["IDE0"],
"^^^^^^^^^^^^^^^^^^^",
InvalidIndex,
},
{
scopeMap["IDE0"],
`^^^^^^^^^^^FOO`,
InvalidIndex,
},
{
scopeMap["IDE0"],
"FOO",
InvalidIndex,
},
{
scopeMap["IDE0"],
"",
InvalidIndex,
},
// Incomplete multi-segment path (prefix 0x2f, segCount: 3)
{
scopeMap["_ADR"],
fmt.Sprintf("\\%c%c?", 0x2f, 0x03),
InvalidIndex,
},
// Search rules apply for these cases
{
scopeMap["IDE0"],
"_CRS",
scopeMap["_CRS"],
},
}
for specIndex, spec := range specs {
if got := tree.Find(spec.curScope, []byte(spec.expr)); got != spec.want {
t.Errorf("[spec %d] expected lookup to return index %d; got %d", specIndex, spec.want, got)
}
}
}
func TestNumArgs(t *testing.T) {
tree := NewObjectTree()
tree.CreateDefaultScopes(42)
if exp, got := uint32(5), tree.NumArgs(tree.ObjectAt(0)); got != exp {
t.Fatalf("expected NumArgs(root) to return %d; got %d", exp, got)
}
if got := tree.NumArgs(nil); got != 0 {
t.Fatalf("expected NumArgs(nil) to return 0; got %d", got)
}
}
func TestArgAt(t *testing.T) {
tree := NewObjectTree()
tree.CreateDefaultScopes(42)
root := tree.ObjectAt(0)
arg0 := tree.ArgAt(root, 0)
expName := [amlNameLen]byte{'_', 'G', 'P', 'E'}
if arg0.name != expName {
t.Errorf("expected ArgAt(root, 0) to return object with name: %s; got: %s", string(expName[:]), string(arg0.name[:]))
}
if got := tree.ArgAt(root, InvalidIndex); got != nil {
t.Errorf("expected ArgAt(root, InvalidIndex) to return nil; got: %v", got)
}
if got := tree.ArgAt(nil, 1); got != nil {
t.Fatalf("expected ArgAt(nil, x) to return nil; got %#+v", got)
}
}
func TestClosestNamedAncestor(t *testing.T) {
tree := NewObjectTree()
root := tree.newObject(pOpIntScopeBlock, 0)
obj1 := tree.newObject(pOpMethod, 1)
obj2 := tree.newObject(pOpIf, 2)
scope := tree.newObject(pOpScope, 3)
obj3 := tree.newObject(pOpIf, 4)
tree.append(root, obj1)
tree.append(obj1, obj2)
tree.append(obj2, scope)
tree.append(scope, obj3)
if got := tree.ClosestNamedAncestor(obj3); got != InvalidIndex {
t.Errorf("expected ClosestNamedAncestor to return InvalidIndex; got %d", got)
}
// No parent exists
if got := tree.ClosestNamedAncestor(root); got != InvalidIndex {
t.Errorf("expected ClosestNamedAncestor to return InvalidIndex; got %d", got)
}
// Make the root a non-named object and call ClosestNamedAncestor on its child
root.opcode = pOpAdd
root.infoIndex = pOpcodeTableIndex(root.opcode, false)
if got := tree.ClosestNamedAncestor(obj1); got != InvalidIndex {
t.Errorf("expected ClosestNamedAncestor to return InvalidIndex; got %d", got)
}
if got := tree.ClosestNamedAncestor(nil); got != InvalidIndex {
t.Fatalf("expected ClosestNamedAncestor(nil) to return InvalidIndex; got %d", got)
}
}
func genTestScopes() (*ObjectTree, map[string]uint32) {
// Setup the example tree from page 252 of the acpi 6.2 spec
// \
// SB
// \
// PCI0
// | _CRS
// \
// IDE0
// | _ADR
tree := NewObjectTree()
root := tree.newNamedObject(pOpIntScopeBlock, 0, [4]byte{'\\'})
pci := tree.newNamedObject(pOpIntScopeBlock, 0, [4]byte{'P', 'C', 'I', '0'})
ide := tree.newNamedObject(pOpIntScopeBlock, 0, [4]byte{'I', 'D', 'E', '0'})
sb := tree.newNamedObject(pOpIntScopeBlock, 0, [4]byte{'_', 'S', 'B', '_'})
crs := tree.newNamedObject(pOpIntScopeBlock, 0, [4]byte{'_', 'C', 'R', 'S'})
adr := tree.newNamedObject(pOpIntScopeBlock, 0, [4]byte{'_', 'A', 'D', 'R'})
// Setup tree
tree.append(root, sb)
tree.append(sb, pci)
tree.append(pci, crs)
tree.append(pci, ide)
tree.append(ide, adr)
return tree, map[string]uint32{
"IDE0": ide.index,
"PCI0": pci.index,
"_SB_": sb.index,
"\\": root.index,
"_ADR": adr.index,
"_CRS": crs.index,
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,40 @@
// +build gofuzz
//
// The following lines contain paths to interesting corpus data and will be
// automatically grepped and copied by the Makefile when fuzzing.
//
//go-fuzz-corpus+=src/gopheros/device/acpi/table/tabletest/DSDT.aml
//go-fuzz-corpus+=src/gopheros/device/acpi/table/tabletest/parser-testsuite-DSDT.aml
package aml
import (
"gopheros/device/acpi/table"
"io/ioutil"
"unsafe"
)
// Fuzz is the driver for go-fuzz. The function must return 1 if the fuzzer
// should increase priority of the given input during subsequent fuzzing (for
// example, the input is lexically correct and was parsed successfully); -1 if
// the input must not be added to corpus even if gives new coverage; and 0
// otherwise; other values are reserved for future use.
func Fuzz(data []byte) int {
// Setup SDT header pointing to data
headerLen := unsafe.Sizeof(table.SDTHeader{})
stream := make([]byte, int(headerLen)+len(data))
copy(stream[headerLen:], data)
header := (*table.SDTHeader)(unsafe.Pointer(&stream[0]))
header.Signature = [4]byte{'D', 'S', 'D', 'T'}
header.Length = uint32(len(stream))
header.Revision = 2
tree := NewObjectTree()
tree.CreateDefaultScopes(0)
if err := NewParser(ioutil.Discard, tree).ParseAML(uint8(1), "DSDT", header); err != nil {
return 0
}
return 1
}

View File

@ -0,0 +1,527 @@
package aml
// List of AML opcodes.
const (
// Regular opcode list
pOpZero = uint16(0x00)
pOpOne = uint16(0x01)
pOpAlias = uint16(0x06)
pOpName = uint16(0x08)
pOpBytePrefix = uint16(0x0a)
pOpWordPrefix = uint16(0x0b)
pOpDwordPrefix = uint16(0x0c)
pOpStringPrefix = uint16(0x0d)
pOpQwordPrefix = uint16(0x0e)
pOpScope = uint16(0x10)
pOpBuffer = uint16(0x11)
pOpPackage = uint16(0x12)
pOpVarPackage = uint16(0x13)
pOpMethod = uint16(0x14)
pOpExternal = uint16(0x15)
pOpLocal0 = uint16(0x60)
pOpLocal1 = uint16(0x61)
pOpLocal2 = uint16(0x62)
pOpLocal3 = uint16(0x63)
pOpLocal4 = uint16(0x64)
pOpLocal5 = uint16(0x65)
pOpLocal6 = uint16(0x66)
pOpLocal7 = uint16(0x67)
pOpArg0 = uint16(0x68)
pOpArg1 = uint16(0x69)
pOpArg2 = uint16(0x6a)
pOpArg3 = uint16(0x6b)
pOpArg4 = uint16(0x6c)
pOpArg5 = uint16(0x6d)
pOpArg6 = uint16(0x6e)
pOpStore = uint16(0x70)
pOpRefOf = uint16(0x71)
pOpAdd = uint16(0x72)
pOpConcat = uint16(0x73)
pOpSubtract = uint16(0x74)
pOpIncrement = uint16(0x75)
pOpDecrement = uint16(0x76)
pOpMultiply = uint16(0x77)
pOpDivide = uint16(0x78)
pOpShiftLeft = uint16(0x79)
pOpShiftRight = uint16(0x7a)
pOpAnd = uint16(0x7b)
pOpNand = uint16(0x7c)
pOpOr = uint16(0x7d)
pOpNor = uint16(0x7e)
pOpXor = uint16(0x7f)
pOpNot = uint16(0x80)
pOpFindSetLeftBit = uint16(0x81)
pOpFindSetRightBit = uint16(0x82)
pOpDerefOf = uint16(0x83)
pOpConcatRes = uint16(0x84)
pOpMod = uint16(0x85)
pOpNotify = uint16(0x86)
pOpSizeOf = uint16(0x87)
pOpIndex = uint16(0x88)
pOpMatch = uint16(0x89)
pOpCreateDWordField = uint16(0x8a)
pOpCreateWordField = uint16(0x8b)
pOpCreateByteField = uint16(0x8c)
pOpCreateBitField = uint16(0x8d)
pOpObjectType = uint16(0x8e)
pOpCreateQWordField = uint16(0x8f)
pOpLand = uint16(0x90)
pOpLor = uint16(0x91)
pOpLnot = uint16(0x92)
pOpLEqual = uint16(0x93)
pOpLGreater = uint16(0x94)
pOpLLess = uint16(0x95)
pOpToBuffer = uint16(0x96)
pOpToDecimalString = uint16(0x97)
pOpToHexString = uint16(0x98)
pOpToInteger = uint16(0x99)
pOpToString = uint16(0x9c)
pOpCopyObject = uint16(0x9d)
pOpMid = uint16(0x9e)
pOpContinue = uint16(0x9f)
pOpIf = uint16(0xa0)
pOpElse = uint16(0xa1)
pOpWhile = uint16(0xa2)
pOpNoop = uint16(0xa3)
pOpReturn = uint16(0xa4)
pOpBreak = uint16(0xa5)
pOpBreakPoint = uint16(0xcc)
pOpOnes = uint16(0xff)
// Extended opcodes
pOpMutex = uint16(0xff + 0x01)
pOpEvent = uint16(0xff + 0x02)
pOpCondRefOf = uint16(0xff + 0x12)
pOpCreateField = uint16(0xff + 0x13)
pOpLoadTable = uint16(0xff + 0x1f)
pOpLoad = uint16(0xff + 0x20)
pOpStall = uint16(0xff + 0x21)
pOpSleep = uint16(0xff + 0x22)
pOpAcquire = uint16(0xff + 0x23)
pOpSignal = uint16(0xff + 0x24)
pOpWait = uint16(0xff + 0x25)
pOpReset = uint16(0xff + 0x26)
pOpRelease = uint16(0xff + 0x27)
pOpFromBCD = uint16(0xff + 0x28)
pOpToBCD = uint16(0xff + 0x29)
pOpUnload = uint16(0xff + 0x2a)
pOpRevision = uint16(0xff + 0x30)
pOpDebug = uint16(0xff + 0x31)
pOpFatal = uint16(0xff + 0x32)
pOpTimer = uint16(0xff + 0x33)
pOpOpRegion = uint16(0xff + 0x80)
pOpField = uint16(0xff + 0x81)
pOpDevice = uint16(0xff + 0x82)
pOpProcessor = uint16(0xff + 0x83)
pOpPowerRes = uint16(0xff + 0x84)
pOpThermalZone = uint16(0xff + 0x85)
pOpIndexField = uint16(0xff + 0x86)
pOpBankField = uint16(0xff + 0x87)
pOpDataRegion = uint16(0xff + 0x88)
// Special internal opcodes which are not part of the spec; these are
// for internal use by the AML parser.
pOpIntScopeBlock = uint16(0xff + 0xf7)
pOpIntByteList = uint16(0xff + 0xf8)
pOpIntConnection = uint16(0xff + 0xf9)
pOpIntNamedField = uint16(0xff + 0xfa)
pOpIntResolvedNamePath = uint16(0xff + 0xfb)
pOpIntNamePath = uint16(0xff + 0xfc)
pOpIntNamePathOrMethodCall = uint16(0xff + 0xfd)
pOpIntMethodCall = uint16(0xff + 0xfe)
// Sentinel value to indicate freed objects
pOpIntFreedObject = uint16(0xff + 0xff)
)
// pOpIsLocalArg returns true if this opcode represents any of the supported local
// function args 0 to 7.
func pOpIsLocalArg(op uint16) bool {
return op >= pOpLocal0 && op <= pOpLocal7
}
// pOpIsMethodArg returns true if this opcode represents any of the supported
// input function args 0 to 6.
func pOpIsMethodArg(op uint16) bool {
return op >= pOpArg0 && op <= pOpArg6
}
// pOpIsArg returns true if this opcode is either a local or a method arg.
func pOpIsArg(op uint16) bool {
return pOpIsLocalArg(op) || pOpIsMethodArg(op)
}
// pOpIsType2 returns true if this is a Type2Opcode.
//
// Grammar:
// Type2Opcode := DefAcquire | DefAdd | DefAnd | DefBuffer | DefConcat |
// DefConcatRes | DefCondRefOf | DefCopyObject | DefDecrement |
// DefDerefOf | DefDivide | DefFindSetLeftBit | DefFindSetRightBit |
// DefFromBCD | DefIncrement | DefIndex | DefLAnd | DefLEqual |
// DefLGreater | DefLGreaterEqual | DefLLess | DefLLessEqual | DefMid |
// DefLNot | DefLNotEqual | DefLoadTable | DefLOr | DefMatch | DefMod |
// DefMultiply | DefNAnd | DefNOr | DefNot | DefObjectType | DefOr |
// DefPackage | DefVarPackage | DefRefOf | DefShiftLeft | DefShiftRight |
// DefSizeOf | DefStore | DefSubtract | DefTimer | DefToBCD | DefToBuffer |
// DefToDecimalString | DefToHexString | DefToInteger | DefToString |
// DefWait | DefXOr
func pOpIsType2(op uint16) bool {
switch op {
case pOpAcquire, pOpAdd, pOpAnd, pOpBuffer, pOpConcat,
pOpConcatRes, pOpCondRefOf, pOpCopyObject, pOpDecrement,
pOpDerefOf, pOpDivide, pOpFindSetLeftBit, pOpFindSetRightBit,
pOpFromBCD, pOpIncrement, pOpIndex, pOpLand, pOpLEqual,
pOpLGreater, pOpLLess, pOpMid,
pOpLnot, pOpLoadTable, pOpLor, pOpMatch, pOpMod,
pOpMultiply, pOpNand, pOpNor, pOpNot, pOpObjectType, pOpOr,
pOpPackage, pOpVarPackage, pOpRefOf, pOpShiftLeft, pOpShiftRight,
pOpSizeOf, pOpStore, pOpSubtract, pOpTimer, pOpToBCD, pOpToBuffer,
pOpToDecimalString, pOpToHexString, pOpToInteger, pOpToString,
pOpWait, pOpXor:
return true
default:
return false
}
}
// pOpIsDataObject returns true if this opcode is part of a DataObject definition
//
// Grammar:
// DataObject := ComputationalData | DefPackage | DefVarPackage
// ComputationalData := ByteConst | WordConst | DWordConst | QWordConst | String | ConstObj | RevisionOp | DefBuffer
// ConstObj := ZeroOp | OneOp | OnesOp
func pOpIsDataObject(op uint16) bool {
switch op {
case pOpBytePrefix, pOpWordPrefix, pOpDwordPrefix, pOpQwordPrefix, pOpStringPrefix,
pOpZero, pOpOne, pOpOnes, pOpRevision, pOpBuffer, pOpPackage, pOpVarPackage:
return true
default:
return false
}
}
const (
badOpcode = 0xff
extOpPrefix = 0x5b
)
// pOpFlag specifies a list of OR-able flags that describe the object
// type/attributes generated by a particular opcode.
type pOpFlag uint8
const (
pOpFlagNamed = 1 << iota
pOpFlagConstant
pOpFlagReference
pOpFlagCreate
pOpFlagExecutable
pOpFlagScoped
pOpFlagDeferParsing
)
// pOpArgTypeList encodes up to 7 opArgFlag values in a uint64 value.
type pOpArgTypeList uint64
// argCount returns the number of encoded args in the given arg type list.
func (fl pOpArgTypeList) argCount() (count uint8) {
// Each argument is specified using 8 bits with 0x0 indicating the end of the
// argument list
for ; fl&0xf != 0; fl, count = fl>>8, count+1 {
}
return count
}
// arg returns the arg type for argument "num" where num is the 0-based index
// of the argument to return. The allowed values for num are 0-6.
func (fl pOpArgTypeList) arg(num uint8) pArgType {
return pArgType((fl >> (num * 8)) & 0xf)
}
// pArgType represents the type of an argument expected by a particular opcode.
type pArgType uint8
// The list of supported opArgFlag values.
const (
_ pArgType = iota
pArgTypeTermList
pArgTypeTermArg
pArgTypeByteList
pArgTypeString
pArgTypeByteData
pArgTypeWordData
pArgTypeDwordData
pArgTypeQwordData
pArgTypeNameString
pArgTypeSuperName
pArgTypeSimpleName
pArgTypeDataRefObj
pArgTypeTarget
pArgTypeFieldList
pArgTypePkgLen
)
func makeArg0() pOpArgTypeList { return 0 }
func makeArg1(arg0 pArgType) pOpArgTypeList { return pOpArgTypeList(arg0) }
func makeArg2(arg0, arg1 pArgType) pOpArgTypeList {
return pOpArgTypeList(arg1)<<8 | pOpArgTypeList(arg0)
}
func makeArg3(arg0, arg1, arg2 pArgType) pOpArgTypeList {
return pOpArgTypeList(arg2)<<16 | pOpArgTypeList(arg1)<<8 | pOpArgTypeList(arg0)
}
func makeArg4(arg0, arg1, arg2, arg3 pArgType) pOpArgTypeList {
return pOpArgTypeList(arg3)<<24 | pOpArgTypeList(arg2)<<16 | pOpArgTypeList(arg1)<<8 | pOpArgTypeList(arg0)
}
func makeArg5(arg0, arg1, arg2, arg3, arg4 pArgType) pOpArgTypeList {
return pOpArgTypeList(arg4)<<32 | pOpArgTypeList(arg3)<<24 | pOpArgTypeList(arg2)<<16 | pOpArgTypeList(arg1)<<8 | pOpArgTypeList(arg0)
}
func makeArg6(arg0, arg1, arg2, arg3, arg4, arg5 pArgType) pOpArgTypeList {
return pOpArgTypeList(arg5)<<40 | pOpArgTypeList(arg4)<<32 | pOpArgTypeList(arg3)<<24 | pOpArgTypeList(arg2)<<16 | pOpArgTypeList(arg1)<<8 | pOpArgTypeList(arg0)
}
func makeArg7(arg0, arg1, arg2, arg3, arg4, arg5, arg6 pArgType) pOpArgTypeList {
return pOpArgTypeList(arg6)<<48 | pOpArgTypeList(arg5)<<40 | pOpArgTypeList(arg4)<<32 | pOpArgTypeList(arg3)<<24 | pOpArgTypeList(arg2)<<16 | pOpArgTypeList(arg1)<<8 | pOpArgTypeList(arg0)
}
// pOpcodeInfo contains all known information about an opcode,
// its argument count and types as well as the type of object
// represented by it.
type pOpcodeInfo struct {
op uint16
opName string
flags pOpFlag
argFlags pOpArgTypeList
}
// The opcode table contains all opcode-related information that the parser knows.
// This table is modeled after a similar table used in the acpica implementation.
var pOpcodeTable = []pOpcodeInfo{
/*0x00*/ {pOpZero, "Zero", pOpFlagConstant, makeArg0()},
/*0x01*/ {pOpOne, "One", pOpFlagConstant, makeArg0()},
/*0x02*/ {pOpAlias, "Alias", pOpFlagNamed, makeArg2(pArgTypeNameString, pArgTypeNameString)},
/*0x03*/ {pOpName, "Name", pOpFlagNamed, makeArg2(pArgTypeNameString, pArgTypeDataRefObj)},
/*0x04*/ {pOpBytePrefix, "BytePrefix", pOpFlagConstant, makeArg1(pArgTypeByteData)},
/*0x05*/ {pOpWordPrefix, "WordPrefix", pOpFlagConstant, makeArg1(pArgTypeWordData)},
/*0x06*/ {pOpDwordPrefix, "DwordPrefix", pOpFlagConstant, makeArg1(pArgTypeDwordData)},
/*0x07*/ {pOpStringPrefix, "StringPrefix", pOpFlagConstant, makeArg1(pArgTypeString)},
/*0x08*/ {pOpQwordPrefix, "QwordPrefix", pOpFlagConstant, makeArg1(pArgTypeQwordData)},
/*0x09*/ {pOpScope, "Scope", 0, makeArg3(pArgTypePkgLen, pArgTypeNameString, pArgTypeTermList)},
/*0x0a*/ {pOpBuffer, "Buffer", pOpFlagDeferParsing | pOpFlagCreate, makeArg3(pArgTypePkgLen, pArgTypeTermArg, pArgTypeByteList)},
/*0x0b*/ {pOpPackage, "Package", pOpFlagCreate, makeArg3(pArgTypePkgLen, pArgTypeByteData, pArgTypeTermList)},
/*0x0c*/ {pOpVarPackage, "VarPackage", pOpFlagCreate, makeArg3(pArgTypePkgLen, pArgTypeByteData, pArgTypeTermList)},
/*0x0d*/ {pOpMethod, "Method", pOpFlagNamed | pOpFlagScoped, makeArg4(pArgTypePkgLen, pArgTypeNameString, pArgTypeByteData, pArgTypeTermList)},
/*0x0e*/ {pOpExternal, "External", pOpFlagNamed, makeArg3(pArgTypeNameString, pArgTypeByteData, pArgTypeByteData)},
/*0x0f*/ {pOpLocal0, "Local0", pOpFlagExecutable, makeArg0()},
/*0x10*/ {pOpLocal1, "Local1", pOpFlagExecutable, makeArg0()},
/*0x11*/ {pOpLocal2, "Local2", pOpFlagExecutable, makeArg0()},
/*0x12*/ {pOpLocal3, "Local3", pOpFlagExecutable, makeArg0()},
/*0x13*/ {pOpLocal4, "Local4", pOpFlagExecutable, makeArg0()},
/*0120*/ {pOpLocal5, "Local5", pOpFlagExecutable, makeArg0()},
/*0x15*/ {pOpLocal6, "Local6", pOpFlagExecutable, makeArg0()},
/*0x16*/ {pOpLocal7, "Local7", pOpFlagExecutable, makeArg0()},
/*0x17*/ {pOpArg0, "Arg0", pOpFlagExecutable, makeArg0()},
/*0x18*/ {pOpArg1, "Arg1", pOpFlagExecutable, makeArg0()},
/*0x19*/ {pOpArg2, "Arg2", pOpFlagExecutable, makeArg0()},
/*0x1a*/ {pOpArg3, "Arg3", pOpFlagExecutable, makeArg0()},
/*0x1b*/ {pOpArg4, "Arg4", pOpFlagExecutable, makeArg0()},
/*0x1c*/ {pOpArg5, "Arg5", pOpFlagExecutable, makeArg0()},
/*0x1d*/ {pOpArg6, "Arg6", pOpFlagExecutable, makeArg0()},
/*0x1e*/ {pOpStore, "Store", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeSuperName)},
/*0x1f*/ {pOpRefOf, "RefOf", pOpFlagReference | pOpFlagExecutable, makeArg1(pArgTypeSuperName)},
/*0x20*/ {pOpAdd, "Add", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x21*/ {pOpConcat, "Concat", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x22*/ {pOpSubtract, "Subtract", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x23*/ {pOpIncrement, "Increment", pOpFlagExecutable, makeArg1(pArgTypeSuperName)},
/*0x24*/ {pOpDecrement, "Decrement", pOpFlagExecutable, makeArg1(pArgTypeSuperName)},
/*0x25*/ {pOpMultiply, "Multiply", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x26*/ {pOpDivide, "Divide", pOpFlagExecutable, makeArg4(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget, pArgTypeTarget)},
/*0x27*/ {pOpShiftLeft, "ShiftLeft", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x28*/ {pOpShiftRight, "ShiftRight", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x29*/ {pOpAnd, "And", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x2a*/ {pOpNand, "Nand", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x2b*/ {pOpOr, "Or", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x2c*/ {pOpNor, "Nor", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x2d*/ {pOpXor, "Xor", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x2e*/ {pOpNot, "Not", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x2f*/ {pOpFindSetLeftBit, "FindSetLeftBit", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x30*/ {pOpFindSetRightBit, "FindSetRightBit", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x31*/ {pOpDerefOf, "DerefOf", pOpFlagExecutable, makeArg1(pArgTypeTermArg)},
/*0x32*/ {pOpConcatRes, "ConcatRes", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x33*/ {pOpMod, "Mod", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x34*/ {pOpNotify, "Notify", pOpFlagExecutable, makeArg2(pArgTypeSuperName, pArgTypeTermArg)},
/*0x35*/ {pOpSizeOf, "SizeOf", pOpFlagExecutable, makeArg1(pArgTypeSuperName)},
/*0x36*/ {pOpIndex, "Index", pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x37*/ {pOpMatch, "Match", pOpFlagExecutable, makeArg6(pArgTypeTermArg, pArgTypeByteData, pArgTypeTermArg, pArgTypeByteData, pArgTypeTermArg, pArgTypeTermArg)},
/*0x38*/ {pOpCreateDWordField, "CreateDWordField", pOpFlagCreate | pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeNameString)},
/*0x39*/ {pOpCreateWordField, "CreateWordField", pOpFlagCreate | pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeNameString)},
/*0x3a*/ {pOpCreateByteField, "CreateByteField", pOpFlagCreate | pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeNameString)},
/*0x3b*/ {pOpCreateBitField, "CreateBitField", pOpFlagCreate | pOpFlagExecutable, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeNameString)},
/*0x3c*/ {pOpObjectType, "ObjectType", pOpFlagExecutable, makeArg1(pArgTypeSuperName)},
/*0x3d*/ {pOpCreateQWordField, "CreateQWordField", pOpFlagCreate, makeArg3(pArgTypeTermArg, pArgTypeTermArg, pArgTypeNameString)},
/*0x3e*/ {pOpLand, "Land", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTermArg)},
/*0x3f*/ {pOpLor, "Lor", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTermArg)},
/*0x40*/ {pOpLnot, "Lnot", pOpFlagExecutable, makeArg1(pArgTypeTermArg)},
/*0x41*/ {pOpLEqual, "LEqual", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTermArg)},
/*0x42*/ {pOpLGreater, "LGreater", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTermArg)},
/*0x43*/ {pOpLLess, "LLess", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTermArg)},
/*0x44*/ {pOpToBuffer, "ToBuffer", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x45*/ {pOpToDecimalString, "ToDecimalString", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x46*/ {pOpToHexString, "ToHexString", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x47*/ {pOpToInteger, "ToInteger", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x48*/ {pOpToString, "ToString", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x49*/ {pOpCopyObject, "CopyObject", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeSimpleName)},
/*0x4a*/ {pOpMid, "Mid", pOpFlagExecutable, makeArg4(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTermArg, pArgTypeTarget)},
/*0x4b*/ {pOpContinue, "Continue", pOpFlagExecutable, makeArg0()},
/*0x4c*/ {pOpIf, "If", pOpFlagExecutable | pOpFlagScoped, makeArg3(pArgTypePkgLen, pArgTypeTermArg, pArgTypeTermList)},
/*0x4d*/ {pOpElse, "Else", pOpFlagExecutable | pOpFlagScoped, makeArg2(pArgTypePkgLen, pArgTypeTermList)},
/*0x4e*/ {pOpWhile, "While", pOpFlagDeferParsing | pOpFlagExecutable | pOpFlagScoped, makeArg3(pArgTypePkgLen, pArgTypeTermArg, pArgTypeTermList)},
/*0x4f*/ {pOpNoop, "Noop", pOpFlagExecutable, makeArg0()},
/*0x50*/ {pOpReturn, "Return", pOpFlagExecutable, makeArg1(pArgTypeTermArg)},
/*0x51*/ {pOpBreak, "Break", pOpFlagExecutable, makeArg0()},
/*0x52*/ {pOpBreakPoint, "BreakPoint", pOpFlagExecutable, makeArg0()},
/*0x53*/ {pOpOnes, "Ones", pOpFlagConstant, makeArg0()},
/*0x54*/ {pOpMutex, "Mutex", pOpFlagNamed, makeArg2(pArgTypeNameString, pArgTypeByteData)},
/*0x55*/ {pOpEvent, "Event", pOpFlagNamed, makeArg1(pArgTypeNameString)},
/*0x56*/ {pOpCondRefOf, "CondRefOf", pOpFlagExecutable, makeArg2(pArgTypeSuperName, pArgTypeSuperName)},
/*0x57*/ {pOpCreateField, "CreateField", pOpFlagExecutable, makeArg4(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTermArg, pArgTypeNameString)},
/*0x58*/ {pOpLoadTable, "LoadTable", pOpFlagExecutable, makeArg7(pArgTypeTermArg, pArgTypeTermArg, pArgTypeTermArg, pArgTypeTermArg, pArgTypeTermArg, pArgTypeTermArg, pArgTypeTermArg)},
/*0x59*/ {pOpLoad, "Load", pOpFlagExecutable, makeArg2(pArgTypeNameString, pArgTypeSuperName)},
/*0x5a*/ {pOpStall, "Stall", pOpFlagExecutable, makeArg1(pArgTypeTermArg)},
/*0x5b*/ {pOpSleep, "Sleep", pOpFlagExecutable, makeArg1(pArgTypeTermArg)},
/*0x5c*/ {pOpAcquire, "Acquire", pOpFlagExecutable, makeArg2(pArgTypeSuperName, pArgTypeWordData)},
/*0x5d*/ {pOpSignal, "Signal", pOpFlagExecutable, makeArg1(pArgTypeTermArg)},
/*0x5e*/ {pOpWait, "Wait", pOpFlagExecutable, makeArg2(pArgTypeSuperName, pArgTypeTermArg)},
/*0x5f*/ {pOpReset, "Reset", pOpFlagExecutable, makeArg1(pArgTypeSuperName)},
/*0x60*/ {pOpRelease, "Release", pOpFlagExecutable, makeArg1(pArgTypeSuperName)},
/*0x61*/ {pOpFromBCD, "FromBCD", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x62*/ {pOpToBCD, "ToBCD", pOpFlagExecutable, makeArg2(pArgTypeTermArg, pArgTypeTarget)},
/*0x63*/ {pOpUnload, "Unload", pOpFlagExecutable, makeArg1(pArgTypeSuperName)},
/*0x64*/ {pOpRevision, "Revision", pOpFlagConstant | pOpFlagExecutable, makeArg0()},
/*0x65*/ {pOpDebug, "Debug", pOpFlagExecutable, makeArg0()},
/*0x66*/ {pOpFatal, "Fatal", pOpFlagExecutable, makeArg3(pArgTypeByteData, pArgTypeDwordData, pArgTypeTermArg)},
/*0x67*/ {pOpTimer, "Timer", pOpFlagExecutable, makeArg0()},
/*0x68*/ {pOpOpRegion, "OpRegion", pOpFlagNamed, makeArg4(pArgTypeNameString, pArgTypeByteData, pArgTypeTermArg, pArgTypeTermArg)},
/*0x69*/ {pOpField, "Field", pOpFlagCreate, makeArg4(pArgTypePkgLen, pArgTypeNameString, pArgTypeByteData, pArgTypeFieldList)},
/*0x6a*/ {pOpDevice, "Device", pOpFlagNamed | pOpFlagScoped, makeArg3(pArgTypePkgLen, pArgTypeNameString, pArgTypeTermList)},
/*0x6b*/ {pOpProcessor, "Processor", pOpFlagNamed | pOpFlagScoped, makeArg6(pArgTypePkgLen, pArgTypeNameString, pArgTypeByteData, pArgTypeDwordData, pArgTypeByteData, pArgTypeTermList)},
/*0x6c*/ {pOpPowerRes, "PowerRes", pOpFlagNamed | pOpFlagScoped, makeArg5(pArgTypePkgLen, pArgTypeNameString, pArgTypeByteData, pArgTypeWordData, pArgTypeTermList)},
/*0x6d*/ {pOpThermalZone, "ThermalZone", pOpFlagNamed | pOpFlagScoped, makeArg3(pArgTypePkgLen, pArgTypeNameString, pArgTypeTermList)},
/*0x6e*/ {pOpIndexField, "IndexField", pOpFlagCreate | pOpFlagNamed, makeArg5(pArgTypePkgLen, pArgTypeNameString, pArgTypeNameString, pArgTypeByteData, pArgTypeFieldList)},
/*0x6f*/ {pOpBankField, "BankField", pOpFlagDeferParsing | pOpFlagCreate | pOpFlagNamed, makeArg6(pArgTypePkgLen, pArgTypeNameString, pArgTypeNameString, pArgTypeTermArg, pArgTypeByteData, pArgTypeFieldList)},
/*0x70*/ {pOpDataRegion, "DataRegion", pOpFlagCreate | pOpFlagNamed, makeArg4(pArgTypeNameString, pArgTypeTermArg, pArgTypeTermArg, pArgTypeTermArg)},
// Special internal opcodes
/*0xf7*/ {pOpIntScopeBlock, "ScopeBlock", pOpFlagCreate | pOpFlagNamed, makeArg1(pArgTypeTermList)},
/*0xf8*/ {pOpIntByteList, "ByteList", pOpFlagCreate, makeArg0()},
/*0xf9*/ {pOpIntConnection, "Connection", pOpFlagCreate, makeArg0()},
/*0xfa*/ {pOpIntNamedField, "NamedField", pOpFlagCreate, makeArg0()},
/*0xfb*/ {pOpIntResolvedNamePath, "ResolvedNamePath", pOpFlagCreate, makeArg0()},
/*0xfc*/ {pOpIntNamePath, "NamePath", pOpFlagCreate, makeArg0()},
/*0xfd*/ {pOpIntNamePathOrMethodCall, "NamePath or MethodCall", pOpFlagCreate, makeArg0()},
/*0xfe*/ {pOpIntMethodCall, "MethodCall", pOpFlagCreate, makeArg0()},
}
// opcodeMap maps an AML opcode to an entry in the opcode table. Entries with
// the value 0xff indicate an invalid/unsupported opcode.
var opcodeMap = [256]uint8{
/* 0 1 2 3 4 5 6 7*/
/*0x00 - 0x07*/ 0x00, 0x01, 0xff, 0xff, 0xff, 0xff, 0x02, 0xff,
/*0x08 - 0x0f*/ 0x03, 0xff, 0x04, 0x05, 0x06, 0x07, 0x08, 0xff,
/*0x10 - 0x17*/ 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0xff, 0xff,
/*0x18 - 0x1f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x20 - 0x27*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x28 - 0x2f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x30 - 0x37*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x38 - 0x3f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x40 - 0x47*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x48 - 0x4f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x50 - 0x57*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x58 - 0x5f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x60 - 0x67*/ 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16,
/*0x68 - 0x6f*/ 0x17, 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d, 0xff,
/*0x70 - 0x77*/ 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25,
/*0x78 - 0x7f*/ 0x26, 0x27, 0x28, 0x29, 0x2a, 0x2b, 0x2c, 0x2d,
/*0x80 - 0x87*/ 0x2e, 0x2f, 0x30, 0x31, 0x32, 0x33, 0x34, 0x35,
/*0x88 - 0x8f*/ 0x36, 0x37, 0x38, 0x39, 0x3a, 0x3b, 0x3c, 0x3d,
/*0x90 - 0x97*/ 0x3e, 0x3f, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45,
/*0x98 - 0x9f*/ 0x46, 0x47, 0xff, 0xff, 0x48, 0x49, 0x4a, 0x4b,
/*0xa0 - 0xa7*/ 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0xff, 0xff,
/*0xa8 - 0xaf*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xb0 - 0xb7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xb8 - 0xbf*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xc0 - 0xc7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xc8 - 0xcf*/ 0xff, 0xff, 0xff, 0xff, 0x52, 0xff, 0xff, 0xff,
/*0xd0 - 0xd7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xd8 - 0xdf*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xe0 - 0xe7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xe8 - 0xef*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xf0 - 0xf7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xf8 - 0xff*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x53,
}
// extendedOpcodeMap maps an AML extended opcode (extOpPrefix + code) to an
// entry in the opcode table. Entries with the value 0xff indicate an
// invalid/unsupported opcode.
var extendedOpcodeMap = [256]uint8{
/* 0 1 2 3 4 5 6 7*/
/*0x00 - 0x07*/ 0xff, 0x54, 0x55, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x08 - 0x0f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x10 - 0x17*/ 0xff, 0xff, 0x56, 0x57, 0xff, 0xff, 0xff, 0xff,
/*0x18 - 0x1f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0x58,
/*0x20 - 0x27*/ 0x59, 0x5a, 0x5b, 0x5c, 0x5d, 0x5e, 0x5f, 0x60,
/*0x28 - 0x2f*/ 0x61, 0x62, 0x63, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x30 - 0x37*/ 0x64, 0x65, 0x66, 0x67, 0xff, 0xff, 0xff, 0xff,
/*0x38 - 0x3f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x40 - 0x47*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x48 - 0x4f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x50 - 0x57*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x58 - 0x5f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x60 - 0x67*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x68 - 0x6f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x70 - 0x77*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x78 - 0x7f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x80 - 0x87*/ 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f,
/*0x88 - 0x8f*/ 0x70, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x90 - 0x97*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0x98 - 0x9f*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xa0 - 0xa7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xa8 - 0xaf*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xb0 - 0xb7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xb8 - 0xbf*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xc0 - 0xc7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xc8 - 0xcf*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xd0 - 0xd7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xd8 - 0xdf*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xe0 - 0xe7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xe8 - 0xef*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xf0 - 0xf7*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
/*0xf8 - 0xff*/ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
}
// pOpcodeName returns the name of an opcode as a string.
func pOpcodeName(opcode uint16) string {
index := pOpcodeTableIndex(opcode, true)
if index == badOpcode {
return "unknown"
}
return pOpcodeTable[index].opName
}
// pOpcodeTableIndex returns the opcode table index for opcode or badOpcode(0xff)
// if opcode does not map to a valid opcode table entry.
func pOpcodeTableIndex(opcode uint16, allowInternalOp bool) uint8 {
if opcode <= 0xff {
return opcodeMap[opcode]
}
index := extendedOpcodeMap[opcode-0xff]
// internal opcodes do not have entries in the extendedOpcodeMap. They get
// allocated descending opcode values starting from (0xff + 0xfe). They do
// however have entries in the opcodeTable. To calculate their index we use
// the following formula: len(opcodeTable) - 1 - (0x1fd - intOpcode) or the
// equivalent: len(opcodeTable) + (intOpcode - 0x1fe)
// with
if index == badOpcode && allowInternalOp {
index = uint8(len(pOpcodeTable) + int(opcode) - 0x1fe)
}
return index
}

View File

@ -0,0 +1,143 @@
package aml
import "testing"
func TestOpcodeIsX(t *testing.T) {
specs := []struct {
op uint16
testFn func(uint16) bool
want bool
}{
// OpIsLocalArg
{pOpLocal0, pOpIsLocalArg, true},
{pOpLocal1, pOpIsLocalArg, true},
{pOpLocal2, pOpIsLocalArg, true},
{pOpLocal3, pOpIsLocalArg, true},
{pOpLocal4, pOpIsLocalArg, true},
{pOpLocal5, pOpIsLocalArg, true},
{pOpLocal6, pOpIsLocalArg, true},
{pOpLocal7, pOpIsLocalArg, true},
{pOpArg0, pOpIsLocalArg, false},
{pOpDivide, pOpIsLocalArg, false},
// OpIsMethodArg
{pOpArg0, pOpIsMethodArg, true},
{pOpArg1, pOpIsMethodArg, true},
{pOpArg2, pOpIsMethodArg, true},
{pOpArg3, pOpIsMethodArg, true},
{pOpArg4, pOpIsMethodArg, true},
{pOpArg5, pOpIsMethodArg, true},
{pOpArg6, pOpIsMethodArg, true},
{pOpLocal7, pOpIsMethodArg, false},
{pOpIf, pOpIsMethodArg, false},
// OpIsArg
{pOpLocal5, pOpIsArg, true},
{pOpArg1, pOpIsArg, true},
{pOpDivide, pOpIsArg, false},
// OpIsType2
{pOpAcquire, pOpIsType2, true},
{pOpAdd, pOpIsType2, true},
{pOpAnd, pOpIsType2, true},
{pOpBuffer, pOpIsType2, true},
{pOpConcat, pOpIsType2, true},
{pOpConcatRes, pOpIsType2, true},
{pOpCondRefOf, pOpIsType2, true},
{pOpCopyObject, pOpIsType2, true},
{pOpDecrement, pOpIsType2, true},
{pOpDerefOf, pOpIsType2, true},
{pOpDivide, pOpIsType2, true},
{pOpFindSetLeftBit, pOpIsType2, true},
{pOpFindSetRightBit, pOpIsType2, true},
{pOpFromBCD, pOpIsType2, true},
{pOpIncrement, pOpIsType2, true},
{pOpIndex, pOpIsType2, true},
{pOpLand, pOpIsType2, true},
{pOpLEqual, pOpIsType2, true},
{pOpLGreater, pOpIsType2, true},
{pOpLLess, pOpIsType2, true},
{pOpMid, pOpIsType2, true},
{pOpLnot, pOpIsType2, true},
{pOpLoadTable, pOpIsType2, true},
{pOpLor, pOpIsType2, true},
{pOpMatch, pOpIsType2, true},
{pOpMod, pOpIsType2, true},
{pOpMultiply, pOpIsType2, true},
{pOpNand, pOpIsType2, true},
{pOpNor, pOpIsType2, true},
{pOpNot, pOpIsType2, true},
{pOpObjectType, pOpIsType2, true},
{pOpOr, pOpIsType2, true},
{pOpPackage, pOpIsType2, true},
{pOpVarPackage, pOpIsType2, true},
{pOpRefOf, pOpIsType2, true},
{pOpShiftLeft, pOpIsType2, true},
{pOpShiftRight, pOpIsType2, true},
{pOpSizeOf, pOpIsType2, true},
{pOpStore, pOpIsType2, true},
{pOpSubtract, pOpIsType2, true},
{pOpTimer, pOpIsType2, true},
{pOpToBCD, pOpIsType2, true},
{pOpToBuffer, pOpIsType2, true},
{pOpToDecimalString, pOpIsType2, true},
{pOpToHexString, pOpIsType2, true},
{pOpToInteger, pOpIsType2, true},
{pOpToString, pOpIsType2, true},
{pOpWait, pOpIsType2, true},
{pOpXor, pOpIsType2, true},
{pOpBytePrefix, pOpIsType2, false},
// OpIsDataObject
{pOpBytePrefix, pOpIsDataObject, true},
{pOpWordPrefix, pOpIsDataObject, true},
{pOpDwordPrefix, pOpIsDataObject, true},
{pOpQwordPrefix, pOpIsDataObject, true},
{pOpStringPrefix, pOpIsDataObject, true},
{pOpZero, pOpIsDataObject, true},
{pOpOne, pOpIsDataObject, true},
{pOpOnes, pOpIsDataObject, true},
{pOpRevision, pOpIsDataObject, true},
{pOpBuffer, pOpIsDataObject, true},
{pOpPackage, pOpIsDataObject, true},
{pOpVarPackage, pOpIsDataObject, true},
{pOpLor, pOpIsDataObject, false},
}
for specIndex, spec := range specs {
if got := spec.testFn(spec.op); got != spec.want {
t.Errorf("[spec %d] opcode %q: expected to get %t; got %t", specIndex, spec.op, spec.want, got)
}
}
}
func TestOpcodeName(t *testing.T) {
for specIndex, spec := range pOpcodeTable {
if got := pOpcodeName(spec.op); got != spec.opName {
t.Errorf("[spec %d] expected OpcodeName(0x%x) to return %q; got %q", specIndex, spec.op, spec.opName, got)
}
}
if exp, got := "unknown", pOpcodeName(0xf8); got != exp {
t.Fatalf("expected OpcodeName to return %q for unknown opcode; got %q", exp, got)
}
}
func TestOpcodeMap(t *testing.T) {
freqs := make(map[uint8]int)
for _, tableIndex := range opcodeMap {
if tableIndex == badOpcode {
continue
}
freqs[tableIndex]++
}
for _, tableIndex := range extendedOpcodeMap {
if tableIndex == badOpcode {
continue
}
freqs[tableIndex]++
}
for tableIndex, freq := range freqs {
if freq > 1 {
t.Errorf("[index 0x%x] found %d duplicate entries in opcodeMap/extendedOpcodeMap for %s", tableIndex, freq, pOpcodeTable[tableIndex].opName)
}
}
}

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,107 @@
package aml
import (
"gopheros/kernel"
"reflect"
"unsafe"
)
var (
errInvalidUnreadByte = &kernel.Error{Module: "acpi_aml_parser", Message: "bad call to UnreadByte; stream offset is 0"}
errInvalidPkgEnd = &kernel.Error{Module: "acpi_aml_parser", Message: "attempted to set pkgEnd past the end of the stream"}
errReadPastPkgEnd = &kernel.Error{Module: "acpi_aml_parser", Message: "attempted to read past pkgEnd"}
)
type amlStreamReader struct {
offset uint32
data []byte
pkgEnd uint32
}
// Init sets up the reader so it can read up to dataLen bytes from the virtual
// memory address dataAddr. If a non-zero initialOffset is specified, it will
// be used as the current offset in the stream.
func (r *amlStreamReader) Init(dataAddr uintptr, dataLen, initialOffset uint32) {
// Overlay a byte slice on top of the memory block to be accessed.
r.data = *(*[]byte)(unsafe.Pointer(&reflect.SliceHeader{
Len: int(dataLen),
Cap: int(dataLen),
Data: dataAddr,
}))
r.SetPkgEnd(dataLen)
r.SetOffset(initialOffset)
}
// EOF returns true if the end of the pkg has been reached.
func (r *amlStreamReader) EOF() bool {
return r.offset >= r.pkgEnd
}
func (r *amlStreamReader) SetPkgEnd(pkgEnd uint32) error {
if pkgEnd > uint32(len(r.data)) {
return errInvalidPkgEnd
}
r.pkgEnd = pkgEnd
return nil
}
// ReadByte returns the next byte from the stream.
func (r *amlStreamReader) ReadByte() (byte, error) {
if r.EOF() {
return 0, errReadPastPkgEnd
}
r.offset++
return r.data[r.offset-1], nil
}
// PeekByte returns the next byte from the stream without advancing the read pointer.
func (r *amlStreamReader) PeekByte() (byte, error) {
if r.EOF() {
return 0, errReadPastPkgEnd
}
return r.data[r.offset], nil
}
// LastByte returns the last byte read off the stream
func (r *amlStreamReader) LastByte() (byte, error) {
if r.offset == 0 {
return 0, errReadPastPkgEnd
}
return r.data[r.offset-1], nil
}
// UnreadByte moves back the read pointer by one byte.
func (r *amlStreamReader) UnreadByte() error {
if r.offset == 0 {
return errInvalidUnreadByte
}
r.offset--
return nil
}
// Offset returns the current offset.
func (r *amlStreamReader) Offset() uint32 {
return r.offset
}
// DataPtr returns a pointer to the stream contents at the current stream offset.
func (r *amlStreamReader) DataPtr() uintptr {
if r.EOF() {
return 0
}
return uintptr(unsafe.Pointer(&r.data[r.offset]))
}
// SetOffset sets the reader offset to the supplied value.
func (r *amlStreamReader) SetOffset(off uint32) {
if max := uint32(len(r.data)); off > max {
off = max
}
r.offset = off
}

View File

@ -0,0 +1,131 @@
package aml
import (
"math"
"testing"
"unsafe"
)
func TestAMLStreamReader(t *testing.T) {
buf := make([]byte, 16)
for i := 0; i < len(buf); i++ {
buf[i] = byte(i)
}
t.Run("without offset", func(t *testing.T) {
var r amlStreamReader
r.Init(
uintptr(unsafe.Pointer(&buf[0])),
uint32(len(buf)),
0,
)
if err := r.SetPkgEnd(uint32(len(buf) + 1)); err != errInvalidPkgEnd {
t.Fatalf("expected to get errInvalidPkgEnd; got: %v", err)
}
if err := r.SetPkgEnd(uint32(len(buf))); err != nil {
t.Fatal(err)
}
if r.EOF() {
t.Fatal("unexpected EOF")
}
if err := r.UnreadByte(); err != errInvalidUnreadByte {
t.Fatalf("expected errInvalidUnreadByte; got %v", err)
}
if _, err := r.LastByte(); err != errReadPastPkgEnd {
t.Fatalf("unexpected error: %v", err)
}
for i := 0; i < len(buf); i++ {
exp := byte(i)
next, err := r.PeekByte()
if err != nil {
t.Fatal(err)
}
if next != exp {
t.Fatalf("expected PeekByte to return %d; got %d", exp, next)
}
next, err = r.ReadByte()
if err != nil {
t.Fatal(err)
}
if next != exp {
t.Fatalf("expected ReadByte to return %d; got %d", exp, next)
}
last, err := r.LastByte()
if err != nil {
t.Fatal(err)
}
if last != exp {
t.Fatalf("expected LastByte to return %d; got %d", exp, last)
}
}
if err := r.UnreadByte(); err != nil {
t.Fatalf("unexpected error: %v", err)
}
// Set offset past EOF; reader should cap the offset to len(buf)
r.SetOffset(math.MaxUint32)
if _, err := r.PeekByte(); err != errReadPastPkgEnd {
t.Fatalf("unexpected error: %v", err)
}
if _, err := r.ReadByte(); err != errReadPastPkgEnd {
t.Fatalf("unexpected error: %v", err)
}
exp := byte(len(buf) - 1)
if last, _ := r.LastByte(); last != exp {
t.Fatalf("expected LastByte to return %d; got %d", exp, last)
}
})
t.Run("with offset", func(t *testing.T) {
var r amlStreamReader
r.Init(
uintptr(unsafe.Pointer(&buf[0])),
uint32(len(buf)),
8,
)
if r.EOF() {
t.Fatal("unexpected EOF")
}
if exp, got := uint32(8), r.Offset(); got != exp {
t.Fatalf("expected Offset() to return %d; got %d", exp, got)
}
exp := byte(8)
if next, _ := r.ReadByte(); next != exp {
t.Fatalf("expected ReadByte to return %d; got %d", exp, next)
}
})
t.Run("ptr to data", func(t *testing.T) {
var r amlStreamReader
r.Init(
uintptr(unsafe.Pointer(&buf[0])),
uint32(len(buf)),
8,
)
if r.EOF() {
t.Fatal("unexpected EOF")
}
r.SetOffset(2)
ptr := r.DataPtr()
if got := *((*byte)(unsafe.Pointer(ptr))); got != buf[2] {
t.Fatal("expected DataPtr to return a pointer to buf[2]")
}
})
}

File diff suppressed because it is too large Load Diff

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,431 @@
/*
* Intel ACPI Component Architecture
* AML/ASL+ Disassembler version 20180105 (64-bit version)
* Copyright (c) 2000 - 2018 Intel Corporation
*
* Disassembling to symbolic ASL+ operators
*
* Disassembly of SSDT.aml, Tue Jan 30 08:22:57 2018
*
* Original Table Header:
* Signature "SSDT"
* Length 0x000001CC (460)
* Revision 0x01
* Checksum 0x9D
* OEM ID "VBOX "
* OEM Table ID "VBOXCPUT"
* OEM Revision 0x00000002 (2)
* Compiler ID "INTL"
* Compiler Version 0x20100528 (537920808)
*/
DefinitionBlock ("", "SSDT", 1, "VBOX ", "VBOXCPUT", 0x00000002)
{
Scope (\_PR)
{
Processor (CPU0, 0x00, 0x00000000, 0x00){}
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
Noop
}
}

View File

@ -0,0 +1,255 @@
// DSDT-parser-testsuite
//
// This file contains various ASL constructs to ensure that the AML parser
// properly handles all possible ASL opcodes it may encounter. This test file
// is used in addition to the DSDT.aml file obtained by running acpidump inside
// virtualbox.
DefinitionBlock ("parser-testsuite-DSDT.aml", "DSDT", 2, "GOPHER", "GOPHEROS", 0x00000002)
{
OperationRegion (DBG0, SystemIO, 0x3000, 0x04)
Field (DBG0, ByteAcc, NoLock, Preserve)
{
DHE1, 8
}
Device (DRV0)
{
Name (_ADR, Ones)
// named entity containing qword const
Name (H15F, 0xBADC0FEEDEADC0DE)
Method (_GTF, 0, NotSerialized) // _GTF: Get Task File
{
Return (H15F)
}
}
// example from p. 268 of ACPI 6.2 spec
Scope(\_SB){
OperationRegion(TOP1, GenericSerialBus, 0x00, 0x100) // GenericSerialBus device at command offset 0x00
Name (SDB0, ResourceTemplate() {})
Field(TOP1, BufferAcc, NoLock, Preserve){
Connection(SDB0), // Use the Resource Descriptor defined above
AccessAs(BufferAcc, AttribWord),
FLD0, 8,
FLD1, 8
}
Field(TOP1, BufferAcc, NoLock, Preserve){
Connection(I2cSerialBus(0x5b,,100000,, "\\_SB",,,,RawDataBuffer(){3,9})),
AccessAs(BufferAcc, AttribBytes(4)),
FLD2, 8,
AccessAs(BufferAcc, AttribRawBytes(3)),
FLD3, 8,
AccessAs(BufferAcc, AttribRawProcessBytes(2)),
FLD4, 8
}
}
// Buffer whose size is given by a nested method invocation which is
// evaluated at load-time
Method(BLE1, 1, Serialized)
{
Return(Arg0 + 1)
}
Name(BUFZ, Buffer(BLEN(BLE1(0xff), 0x0f)){0x48, 0x49, 0x21} )
Method(BLEN, 2, Serialized)
{
Return(Arg0 + Arg1 + 12)
}
// Load time assignment
FET0 = 1
// A buffer whose length is given by a named object
Name(BUFL, One)
Name(BUFF, Buffer(BUFL){})
// Other entity types
Event(HLO0)
Mutex(MUT0,1)
Signal(HLO0)
// Other executable bits
Method (EXE0, 1, Serialized)
{
// AML interpreter revision
Local0 = Revision
// NameString target
Local1 = SizeOf(GLB1)
Local0 = "my-handle"
Load(DBG0, Local0)
Unload(Local0)
// CreateXXXField
CreateBitField(Arg0, 0, WFL0)
if(Arg0==0){
Return(WFL0)
}
CreateByteField(Arg0, 0, WFL1)
if(Arg0==1){
Return(WFL1)
}
CreateWordField(Arg0, 0, WFL2)
if(Arg0==2){
Return(WFL2)
}
CreateDwordField(Arg0, 0, WFL3)
if(Arg0==3){
Return(WFL3)
}
CreateQwordField(Arg0, 0, WFL4)
if(Arg0==4){
Return(WFL4)
}
CreateField(Arg0, 0, 13, WFL5)
if(Arg0==5){
Return(WFL5)
}
// Example from p. 951 of the spec
Store (
LoadTable ("OEM1", "MYOEM", "TABLE1", "\\_SB.PCI0","MYD", Package () {0,"\\_SB.PCI0"}),
Local0
)
// Various Assignments
Local0 = 0xff
Local0 = 0xffff
Local0 = 0xffffffff
Local0 = 0xffffffffffffffff
Local0 = Zero
Local0 = One
Local0 = Ones
Local0 = "FOO"
// Conversions
FromBCD(9, Arg0)
ToBCD(Arg0, Local1)
// Debugging and error handling
Breakpoint
Debug = "test"
Fatal(0xf0, 0xdeadc0de, 1)
// Mutex support
Acquire(MUT0, 0xffff) // no timeout
Release(MUT0)
// Signal/Wait
Reset(HLO0)
Wait(HLO0, 0xffff)
// Get monotonic timer value
Local0 = Timer
CopyObject(Local0, Local1)
Return(ObjectType(Local1))
}
// BankField example from p. 910 of the spec
// Define a 256-byte operational region in SystemIO space and name it GIO0
OperationRegion (GIO0, SystemIO, 0x125, 0x100)
Field (GIO0, ByteAcc, NoLock, Preserve) {
GLB1, 1,
GLB2, 1,
Offset (1), // Move to offset for byte 1
BNK1, 4
}
BankField (GIO0, BNK1, 0, ByteAcc, Lock, WriteAsOnes) {
Offset (0x30),
FET0, 1,
FET1, 1,
}
// SMBus fields access types
OperationRegion(SMBD, SMBus, 0x4200, 0x100)
Field(SMBD, BufferAcc, NoLock, WriteAsZeros){
AccessAs(BufferAcc, SMBByte),
SFL0, 8,
AccessAs(BufferAcc, SMBWord),
SFL1, 8,
AccessAs(BufferAcc, SMBBlock),
SFL2, 8,
AccessAs(BufferAcc, SMBQuick),
SFL3, 8,
AccessAs(BufferAcc, SMBSendReceive),
SFL4, 8,
AccessAs(BufferAcc, SMBProcessCall),
SFL5, 8,
AccessAs(BufferAcc, SMBBlockProcessCall),
SFL6, 8,
AccessAs(BufferAcc, AttribBytes(0x12)),
SFL7, 8,
AccessAs(BufferAcc, AttribRawBytes(0x13)),
SFL8, 8,
AccessAs(BufferAcc, AttribRawProcessBytes(0x14)),
SFL9, 8,
//
AccessAs(AnyAcc),
SF10, 8,
AccessAs(ByteAcc),
SF11, 8,
AccessAs(WordAcc),
SF12, 8,
AccessAs(DwordAcc),
SF13, 8,
AccessAs(QwordAcc),
SF14, 8,
}
// Data Region
DataTableRegion (REG0, "FOOF", "BAR", "BAZ")
// Other resources
Processor(CPU0, 1, 0x120, 6){}
PowerResource(PWR0, 0, 0){}
ThermalZone(TZ0){}
// Method with various logic/flow changing opcodes
Method (FLOW, 2, NotSerialized)
{
While(Arg0 < Arg1)
{
Arg0++
If( Arg0 < 5 ) {
Continue
} Else {
If ( Arg1 == 0xff ) {
Break
} Else {
Arg0 = Arg0 + 1
}
}
}
Return(Arg0)
}
// Forward declaration to SCP0
Scope(\_SB) {
ThermalZone(^THRM){
Name(DEF0, Ones)
}
}
Scope(\THRM){
Name(DEF1, Zero)
}
Method(\THRM.MTH0, 0, NotSerialized){
Return(1)
}
}

View File

@ -0,0 +1,346 @@
+- [ScopeBlock, name: "\", table: 42, index: 0, offset: 0x0]
+- [ScopeBlock, name: "_GPE", table: 42, index: 1, offset: 0x0]
+- [ScopeBlock, name: "_PR_", table: 42, index: 2, offset: 0x0]
+- [ScopeBlock, name: "_SB_", table: 42, index: 3, offset: 0x0]
| +- [OpRegion, name: "TOP1", table: 0, index: 33, offset: 0x6c]
| | +- [NamePath, table: 0, index: 34, offset: 0x6e] -> [namepath: "TOP1"]
| | +- [BytePrefix, table: 0, index: 35, offset: 0x72] -> [num value; dec: 9, hex: 0x9]
| | +- [BytePrefix, table: 0, index: 36, offset: 0x73] -> [num value; dec: 0, hex: 0x0]
| | +- [WordPrefix, table: 0, index: 37, offset: 0x75] -> [num value; dec: 256, hex: 0x100]
| +- [Name, name: "SDB0", table: 0, index: 38, offset: 0x78]
| | +- [NamePath, table: 0, index: 39, offset: 0x79] -> [namepath: "SDB0"]
| | +- [Buffer, table: 0, index: 40, offset: 0x7d]
| | +- [BytePrefix, table: 0, index: 316, offset: 0x7f] -> [num value; dec: 2, hex: 0x2]
| | +- [ByteList, table: 0, index: 318, offset: 0x3cb] -> [bytelist value; len: 2; data: [0x79, 0x0]]
| +- [Field, table: 0, index: 41, offset: 0x83]
| | +- [NamePath, table: 0, index: 42, offset: 0x86] -> [namepath: "TOP1"]
| | +- [BytePrefix, table: 0, index: 43, offset: 0x8a] -> [num value; dec: 5, hex: 0x5]
| | +- [Connection, table: 0, index: 44, offset: 0x0]
| | +- [NamePath, table: 0, index: 45, offset: 0x8c] -> [namepath: "SDB0"]
| +- [NamedField, name: "FLD0", table: 0, index: 46, offset: 0x93] -> [field index: 41, offset(bytes): 0x0, width(bits): 0x8, accType: Buffer, accAttr: Word, lockType: NoLock, updateType: Preserve, connection: index 44]
| +- [NamedField, name: "FLD1", table: 0, index: 47, offset: 0x98] -> [field index: 41, offset(bytes): 0x8, width(bits): 0x8, accType: Buffer, accAttr: Word, lockType: NoLock, updateType: Preserve, connection: index 44]
| +- [Field, table: 0, index: 48, offset: 0x9d]
| | +- [NamePath, table: 0, index: 49, offset: 0xa0] -> [namepath: "TOP1"]
| | +- [BytePrefix, table: 0, index: 50, offset: 0xa4] -> [num value; dec: 5, hex: 0x5]
| | +- [Connection, table: 0, index: 51, offset: 0x0]
| | +- [ByteList, table: 0, index: 52, offset: 0xa7] -> [bytelist value; len: 25; data: [0x8e, 0x16, 0x0, 0x1, 0x0, 0x1, 0x2, 0x0, 0x0, 0x1, 0x8, 0x0, 0xa0, 0x86, 0x1, 0x0, 0x5b, 0x0, 0x3, 0x9, 0x5c, 0x5f, 0x53, 0x42, 0x0]]
| +- [NamedField, name: "FLD2", table: 0, index: 53, offset: 0xc7] -> [field index: 48, offset(bytes): 0x0, width(bits): 0x8, accType: Buffer, accAttr: Bytes(0x4), lockType: NoLock, updateType: Preserve, connection: index 51]
| +- [NamedField, name: "FLD3", table: 0, index: 54, offset: 0xd0] -> [field index: 48, offset(bytes): 0x8, width(bits): 0x8, accType: Buffer, accAttr: RawBytes(0x3), lockType: NoLock, updateType: Preserve, connection: index 51]
| +- [NamedField, name: "FLD4", table: 0, index: 55, offset: 0xd9] -> [field index: 48, offset(bytes): 0x10, width(bits): 0x8, accType: Buffer, accAttr: RawProcessBytes(0x2), lockType: NoLock, updateType: Preserve, connection: index 51]
+- [ScopeBlock, name: "_SI_", table: 42, index: 4, offset: 0x0]
+- [ScopeBlock, name: "_TZ_", table: 42, index: 5, offset: 0x0]
+- [OpRegion, name: "DBG0", table: 0, index: 6, offset: 0x24]
| +- [NamePath, table: 0, index: 7, offset: 0x26] -> [namepath: "DBG0"]
| +- [BytePrefix, table: 0, index: 8, offset: 0x2a] -> [num value; dec: 1, hex: 0x1]
| +- [WordPrefix, table: 0, index: 9, offset: 0x2b] -> [num value; dec: 12288, hex: 0x3000]
| +- [BytePrefix, table: 0, index: 10, offset: 0x2e] -> [num value; dec: 4, hex: 0x4]
+- [Field, table: 0, index: 11, offset: 0x30]
| +- [NamePath, table: 0, index: 12, offset: 0x33] -> [namepath: "DBG0"]
| +- [BytePrefix, table: 0, index: 13, offset: 0x37] -> [num value; dec: 1, hex: 0x1]
+- [NamedField, name: "DHE1", table: 0, index: 14, offset: 0x38] -> [field index: 11, offset(bytes): 0x0, width(bits): 0x8, accType: Byte, lockType: NoLock, updateType: Preserve, connection: -]
+- [Device, name: "DRV0", table: 0, index: 15, offset: 0x3d]
| +- [NamePath, table: 0, index: 16, offset: 0x40] -> [namepath: "DRV0"]
| +- [ScopeBlock, table: 0, index: 17, offset: 0x44]
| +- [Name, name: "_ADR", table: 0, index: 18, offset: 0x44]
| | +- [NamePath, table: 0, index: 19, offset: 0x45] -> [namepath: "_ADR"]
| | +- [Ones, table: 0, index: 20, offset: 0x49]
| +- [Name, name: "H15F", table: 0, index: 21, offset: 0x4a]
| | +- [NamePath, table: 0, index: 22, offset: 0x4b] -> [namepath: "H15F"]
| | +- [QwordPrefix, table: 0, index: 23, offset: 0x4f] -> [num value; dec: 13464654504543502558, hex: 0xbadc0feedeadc0de]
| +- [Method, name: "_GTF", argCount: 0, table: 0, index: 24, offset: 0x58]
| +- [NamePath, table: 0, index: 25, offset: 0x5a] -> [namepath: "_GTF"]
| +- [BytePrefix, table: 0, index: 26, offset: 0x5e] -> [num value; dec: 0, hex: 0x0]
| +- [ScopeBlock, table: 0, index: 27, offset: 0x5f]
| +- [Return, table: 0, index: 28, offset: 0x5f]
| +- [ResolvedNamePath, table: 0, index: 29, offset: 0x60] -> [resolved to "H15F", table: 0, index: 21, offset: 0x4a]
+- [Method, name: "BLE1", argCount: 1, table: 0, index: 56, offset: 0xde]
| +- [NamePath, table: 0, index: 57, offset: 0xe0] -> [namepath: "BLE1"]
| +- [BytePrefix, table: 0, index: 58, offset: 0xe4] -> [num value; dec: 9, hex: 0x9]
| +- [ScopeBlock, table: 0, index: 59, offset: 0xe5]
| +- [Return, table: 0, index: 60, offset: 0xe5]
| +- [Add, table: 0, index: 61, offset: 0xe6]
| +- [Arg0, table: 0, index: 62, offset: 0xe7]
| +- [BytePrefix, table: 0, index: 63, offset: 0xe8] -> [num value; dec: 1, hex: 0x1]
| +- [Zero, table: 0, index: 64, offset: 0xea]
+- [Name, name: "BUFZ", table: 0, index: 65, offset: 0xeb]
| +- [NamePath, table: 0, index: 66, offset: 0xec] -> [namepath: "BUFZ"]
| +- [Buffer, table: 0, index: 67, offset: 0xf0]
| +- [MethodCall, table: 0, index: 317, offset: 0xf2] -> [call to "BLEN", argCount: 2, table: 0, index: 68, offset: 0x101]
| | +- [MethodCall, table: 0, index: 307, offset: 0xf6] -> [call to "BLE1", argCount: 1, table: 0, index: 56, offset: 0xde]
| | | +- [BytePrefix, table: 0, index: 309, offset: 0xfa] -> [num value; dec: 255, hex: 0xff]
| | +- [BytePrefix, table: 0, index: 308, offset: 0xfc] -> [num value; dec: 15, hex: 0xf]
| +- [ByteList, table: 0, index: 30, offset: 0x64] -> [bytelist value; len: 3; data: [0x48, 0x49, 0x21]]
+- [Method, name: "BLEN", argCount: 2, table: 0, index: 68, offset: 0x101]
| +- [NamePath, table: 0, index: 69, offset: 0x103] -> [namepath: "BLEN"]
| +- [BytePrefix, table: 0, index: 70, offset: 0x107] -> [num value; dec: 10, hex: 0xa]
| +- [ScopeBlock, table: 0, index: 71, offset: 0x108]
| +- [Return, table: 0, index: 72, offset: 0x108]
| +- [Add, table: 0, index: 73, offset: 0x109]
| +- [Add, table: 0, index: 74, offset: 0x10a]
| | +- [Arg0, table: 0, index: 75, offset: 0x10b]
| | +- [Arg1, table: 0, index: 76, offset: 0x10c]
| | +- [Zero, table: 0, index: 77, offset: 0x10d]
| +- [BytePrefix, table: 0, index: 78, offset: 0x10e] -> [num value; dec: 12, hex: 0xc]
| +- [Zero, table: 0, index: 79, offset: 0x110]
+- [Store, table: 0, index: 80, offset: 0x111]
| +- [BytePrefix, table: 0, index: 81, offset: 0x112] -> [num value; dec: 1, hex: 0x1]
| +- [ResolvedNamePath, table: 0, index: 82, offset: 0x114] -> [resolved to "FET0", table: 0, index: 332, offset: 0x2b9]
+- [Name, name: "BUFL", table: 0, index: 83, offset: 0x118]
| +- [NamePath, table: 0, index: 84, offset: 0x119] -> [namepath: "BUFL"]
| +- [One, table: 0, index: 85, offset: 0x11d]
+- [Name, name: "BUFF", table: 0, index: 86, offset: 0x11e]
| +- [NamePath, table: 0, index: 87, offset: 0x11f] -> [namepath: "BUFF"]
| +- [Buffer, table: 0, index: 88, offset: 0x123]
| +- [ResolvedNamePath, table: 0, index: 32, offset: 0x125] -> [resolved to "BUFL", table: 0, index: 83, offset: 0x118]
| +- [ByteList, table: 0, index: 31, offset: 0x67] -> [bytelist value; len: 0; data: []]
+- [Event, name: "HLO0", table: 0, index: 89, offset: 0x129]
| +- [NamePath, table: 0, index: 90, offset: 0x12b] -> [namepath: "HLO0"]
+- [Mutex, name: "MUT0", table: 0, index: 91, offset: 0x12f]
| +- [NamePath, table: 0, index: 92, offset: 0x131] -> [namepath: "MUT0"]
| +- [BytePrefix, table: 0, index: 93, offset: 0x135] -> [num value; dec: 1, hex: 0x1]
+- [Signal, table: 0, index: 94, offset: 0x136]
| +- [ResolvedNamePath, table: 0, index: 95, offset: 0x138] -> [resolved to "HLO0", table: 0, index: 89, offset: 0x129]
+- [Method, name: "EXE0", argCount: 1, table: 0, index: 96, offset: 0x13c]
| +- [NamePath, table: 0, index: 97, offset: 0x13f] -> [namepath: "EXE0"]
| +- [BytePrefix, table: 0, index: 98, offset: 0x143] -> [num value; dec: 9, hex: 0x9]
| +- [ScopeBlock, table: 0, index: 99, offset: 0x144]
| +- [Store, table: 0, index: 100, offset: 0x144]
| | +- [Revision, table: 0, index: 101, offset: 0x145]
| | +- [Local0, table: 0, index: 102, offset: 0x147]
| +- [Store, table: 0, index: 103, offset: 0x148]
| | +- [SizeOf, table: 0, index: 104, offset: 0x149]
| | | +- [NamePath, table: 0, index: 105, offset: 0x14a] -> [namepath: "GLB1"]
| | +- [Local1, table: 0, index: 106, offset: 0x14e]
| +- [Store, table: 0, index: 107, offset: 0x14f]
| | +- [StringPrefix, table: 0, index: 108, offset: 0x150] -> [string value: "my-handle"]
| | +- [Local0, table: 0, index: 109, offset: 0x15b]
| +- [Load, table: 0, index: 110, offset: 0x15c]
| | +- [NamePath, table: 0, index: 111, offset: 0x15e] -> [namepath: "DBG0"]
| | +- [Local0, table: 0, index: 112, offset: 0x162]
| +- [Unload, table: 0, index: 113, offset: 0x163]
| | +- [Local0, table: 0, index: 114, offset: 0x165]
| +- [CreateBitField, table: 0, index: 115, offset: 0x166]
| | +- [Arg0, table: 0, index: 116, offset: 0x167]
| | +- [BytePrefix, table: 0, index: 117, offset: 0x168] -> [num value; dec: 0, hex: 0x0]
| | +- [NamePath, table: 0, index: 118, offset: 0x16a] -> [namepath: "WFL0"]
| +- [If, table: 0, index: 119, offset: 0x16e]
| | +- [LEqual, table: 0, index: 120, offset: 0x170]
| | | +- [Arg0, table: 0, index: 121, offset: 0x171]
| | | +- [BytePrefix, table: 0, index: 122, offset: 0x172] -> [num value; dec: 0, hex: 0x0]
| | +- [Return, table: 0, index: 123, offset: 0x174]
| | +- [NamePath, table: 0, index: 124, offset: 0x175] -> [namepath: "WFL0"]
| +- [CreateByteField, table: 0, index: 125, offset: 0x179]
| | +- [Arg0, table: 0, index: 126, offset: 0x17a]
| | +- [BytePrefix, table: 0, index: 127, offset: 0x17b] -> [num value; dec: 0, hex: 0x0]
| | +- [NamePath, table: 0, index: 128, offset: 0x17d] -> [namepath: "WFL1"]
| +- [If, table: 0, index: 129, offset: 0x181]
| | +- [LEqual, table: 0, index: 130, offset: 0x183]
| | | +- [Arg0, table: 0, index: 131, offset: 0x184]
| | | +- [BytePrefix, table: 0, index: 132, offset: 0x185] -> [num value; dec: 1, hex: 0x1]
| | +- [Return, table: 0, index: 133, offset: 0x187]
| | +- [NamePath, table: 0, index: 134, offset: 0x188] -> [namepath: "WFL1"]
| +- [CreateWordField, table: 0, index: 135, offset: 0x18c]
| | +- [Arg0, table: 0, index: 136, offset: 0x18d]
| | +- [BytePrefix, table: 0, index: 137, offset: 0x18e] -> [num value; dec: 0, hex: 0x0]
| | +- [NamePath, table: 0, index: 138, offset: 0x190] -> [namepath: "WFL2"]
| +- [If, table: 0, index: 139, offset: 0x194]
| | +- [LEqual, table: 0, index: 140, offset: 0x196]
| | | +- [Arg0, table: 0, index: 141, offset: 0x197]
| | | +- [BytePrefix, table: 0, index: 142, offset: 0x198] -> [num value; dec: 2, hex: 0x2]
| | +- [Return, table: 0, index: 143, offset: 0x19a]
| | +- [NamePath, table: 0, index: 144, offset: 0x19b] -> [namepath: "WFL2"]
| +- [CreateDWordField, table: 0, index: 145, offset: 0x19f]
| | +- [Arg0, table: 0, index: 146, offset: 0x1a0]
| | +- [BytePrefix, table: 0, index: 147, offset: 0x1a1] -> [num value; dec: 0, hex: 0x0]
| | +- [NamePath, table: 0, index: 148, offset: 0x1a3] -> [namepath: "WFL3"]
| +- [If, table: 0, index: 149, offset: 0x1a7]
| | +- [LEqual, table: 0, index: 150, offset: 0x1a9]
| | | +- [Arg0, table: 0, index: 151, offset: 0x1aa]
| | | +- [BytePrefix, table: 0, index: 152, offset: 0x1ab] -> [num value; dec: 3, hex: 0x3]
| | +- [Return, table: 0, index: 153, offset: 0x1ad]
| | +- [NamePath, table: 0, index: 154, offset: 0x1ae] -> [namepath: "WFL3"]
| +- [CreateQWordField, table: 0, index: 155, offset: 0x1b2]
| | +- [Arg0, table: 0, index: 156, offset: 0x1b3]
| | +- [BytePrefix, table: 0, index: 157, offset: 0x1b4] -> [num value; dec: 0, hex: 0x0]
| | +- [NamePath, table: 0, index: 158, offset: 0x1b6] -> [namepath: "WFL4"]
| +- [If, table: 0, index: 159, offset: 0x1ba]
| | +- [LEqual, table: 0, index: 160, offset: 0x1bc]
| | | +- [Arg0, table: 0, index: 161, offset: 0x1bd]
| | | +- [BytePrefix, table: 0, index: 162, offset: 0x1be] -> [num value; dec: 4, hex: 0x4]
| | +- [Return, table: 0, index: 163, offset: 0x1c0]
| | +- [NamePath, table: 0, index: 164, offset: 0x1c1] -> [namepath: "WFL4"]
| +- [CreateField, table: 0, index: 165, offset: 0x1c5]
| | +- [Arg0, table: 0, index: 166, offset: 0x1c7]
| | +- [BytePrefix, table: 0, index: 167, offset: 0x1c8] -> [num value; dec: 0, hex: 0x0]
| | +- [BytePrefix, table: 0, index: 168, offset: 0x1ca] -> [num value; dec: 13, hex: 0xd]
| | +- [NamePath, table: 0, index: 169, offset: 0x1cc] -> [namepath: "WFL5"]
| +- [If, table: 0, index: 170, offset: 0x1d0]
| | +- [LEqual, table: 0, index: 171, offset: 0x1d2]
| | | +- [Arg0, table: 0, index: 172, offset: 0x1d3]
| | | +- [BytePrefix, table: 0, index: 173, offset: 0x1d4] -> [num value; dec: 5, hex: 0x5]
| | +- [Return, table: 0, index: 174, offset: 0x1d6]
| | +- [NamePath, table: 0, index: 175, offset: 0x1d7] -> [namepath: "WFL5"]
| +- [Store, table: 0, index: 176, offset: 0x1db]
| | +- [LoadTable, table: 0, index: 177, offset: 0x1dc]
| | | +- [StringPrefix, table: 0, index: 178, offset: 0x1de] -> [string value: "OEM1"]
| | | +- [StringPrefix, table: 0, index: 179, offset: 0x1e4] -> [string value: "MYOEM"]
| | | +- [StringPrefix, table: 0, index: 180, offset: 0x1eb] -> [string value: "TABLE1"]
| | | +- [StringPrefix, table: 0, index: 181, offset: 0x1f3] -> [string value: "\_SB.PCI0"]
| | | +- [StringPrefix, table: 0, index: 182, offset: 0x1fe] -> [string value: "MYD"]
| | | +- [Package, table: 0, index: 183, offset: 0x203]
| | | | +- [BytePrefix, table: 0, index: 184, offset: 0x205] -> [num value; dec: 2, hex: 0x2]
| | | | +- [ScopeBlock, table: 0, index: 185, offset: 0x206]
| | | | +- [BytePrefix, table: 0, index: 186, offset: 0x206] -> [num value; dec: 0, hex: 0x0]
| | | | +- [StringPrefix, table: 0, index: 187, offset: 0x208] -> [string value: "\_SB.PCI0"]
| | | +- [Local0, table: 0, index: 188, offset: 0x213]
| | +- [Store, table: 0, index: 189, offset: 0x214]
| | +- [BytePrefix, table: 0, index: 190, offset: 0x215] -> [num value; dec: 255, hex: 0xff]
| | +- [Local0, table: 0, index: 191, offset: 0x217]
| +- [Store, table: 0, index: 192, offset: 0x218]
| | +- [WordPrefix, table: 0, index: 193, offset: 0x219] -> [num value; dec: 65535, hex: 0xffff]
| | +- [Local0, table: 0, index: 194, offset: 0x21c]
| +- [Store, table: 0, index: 195, offset: 0x21d]
| | +- [DwordPrefix, table: 0, index: 196, offset: 0x21e] -> [num value; dec: 4294967295, hex: 0xffffffff]
| | +- [Local0, table: 0, index: 197, offset: 0x223]
| +- [Store, table: 0, index: 198, offset: 0x224]
| | +- [QwordPrefix, table: 0, index: 199, offset: 0x225] -> [num value; dec: 18446744073709551615, hex: 0xffffffffffffffff]
| | +- [Local0, table: 0, index: 200, offset: 0x22e]
| +- [Store, table: 0, index: 201, offset: 0x22f]
| | +- [Zero, table: 0, index: 202, offset: 0x230]
| | +- [Local0, table: 0, index: 203, offset: 0x231]
| +- [Store, table: 0, index: 204, offset: 0x232]
| | +- [One, table: 0, index: 205, offset: 0x233]
| | +- [Local0, table: 0, index: 206, offset: 0x234]
| +- [Store, table: 0, index: 207, offset: 0x235]
| | +- [Ones, table: 0, index: 208, offset: 0x236]
| | +- [Local0, table: 0, index: 209, offset: 0x237]
| +- [Store, table: 0, index: 210, offset: 0x238]
| | +- [StringPrefix, table: 0, index: 211, offset: 0x239] -> [string value: "FOO"]
| | +- [Local0, table: 0, index: 212, offset: 0x23e]
| +- [FromBCD, table: 0, index: 213, offset: 0x23f]
| | +- [BytePrefix, table: 0, index: 214, offset: 0x241] -> [num value; dec: 9, hex: 0x9]
| | +- [Arg0, table: 0, index: 215, offset: 0x243]
| +- [ToBCD, table: 0, index: 216, offset: 0x244]
| | +- [Arg0, table: 0, index: 217, offset: 0x246]
| | +- [Local1, table: 0, index: 218, offset: 0x247]
| +- [BreakPoint, table: 0, index: 219, offset: 0x248]
| +- [Store, table: 0, index: 220, offset: 0x249]
| | +- [StringPrefix, table: 0, index: 221, offset: 0x24a] -> [string value: "test"]
| | +- [Debug, table: 0, index: 222, offset: 0x250]
| +- [Fatal, table: 0, index: 223, offset: 0x252]
| | +- [BytePrefix, table: 0, index: 224, offset: 0x254] -> [num value; dec: 240, hex: 0xf0]
| | +- [DwordPrefix, table: 0, index: 225, offset: 0x255] -> [num value; dec: 3735929054, hex: 0xdeadc0de]
| | +- [BytePrefix, table: 0, index: 226, offset: 0x259] -> [num value; dec: 1, hex: 0x1]
| +- [Acquire, table: 0, index: 227, offset: 0x25b]
| | +- [NamePath, table: 0, index: 228, offset: 0x25d] -> [namepath: "MUT0"]
| | +- [WordPrefix, table: 0, index: 229, offset: 0x261] -> [num value; dec: 65535, hex: 0xffff]
| +- [Release, table: 0, index: 230, offset: 0x263]
| | +- [NamePath, table: 0, index: 231, offset: 0x265] -> [namepath: "MUT0"]
| +- [Reset, table: 0, index: 232, offset: 0x269]
| | +- [NamePath, table: 0, index: 233, offset: 0x26b] -> [namepath: "HLO0"]
| +- [Wait, table: 0, index: 234, offset: 0x26f]
| | +- [NamePath, table: 0, index: 235, offset: 0x271] -> [namepath: "HLO0"]
| | +- [WordPrefix, table: 0, index: 236, offset: 0x275] -> [num value; dec: 65535, hex: 0xffff]
| +- [Store, table: 0, index: 237, offset: 0x278]
| | +- [Timer, table: 0, index: 238, offset: 0x279]
| | +- [Local0, table: 0, index: 239, offset: 0x27b]
| +- [CopyObject, table: 0, index: 240, offset: 0x27c]
| | +- [Local0, table: 0, index: 241, offset: 0x27d]
| | +- [Local1, table: 0, index: 242, offset: 0x27e]
| +- [Return, table: 0, index: 243, offset: 0x27f]
| +- [ObjectType, table: 0, index: 244, offset: 0x280]
| +- [Local1, table: 0, index: 245, offset: 0x281]
+- [OpRegion, name: "GIO0", table: 0, index: 246, offset: 0x282]
| +- [NamePath, table: 0, index: 247, offset: 0x284] -> [namepath: "GIO0"]
| +- [BytePrefix, table: 0, index: 248, offset: 0x288] -> [num value; dec: 1, hex: 0x1]
| +- [WordPrefix, table: 0, index: 249, offset: 0x289] -> [num value; dec: 293, hex: 0x125]
| +- [WordPrefix, table: 0, index: 250, offset: 0x28c] -> [num value; dec: 256, hex: 0x100]
+- [Field, table: 0, index: 251, offset: 0x28f]
| +- [NamePath, table: 0, index: 252, offset: 0x292] -> [namepath: "GIO0"]
| +- [BytePrefix, table: 0, index: 253, offset: 0x296] -> [num value; dec: 1, hex: 0x1]
+- [NamedField, name: "GLB1", table: 0, index: 254, offset: 0x297] -> [field index: 251, offset(bytes): 0x0, width(bits): 0x1, accType: Byte, lockType: NoLock, updateType: Preserve, connection: -]
+- [NamedField, name: "GLB2", table: 0, index: 255, offset: 0x29c] -> [field index: 251, offset(bytes): 0x1, width(bits): 0x1, accType: Byte, lockType: NoLock, updateType: Preserve, connection: -]
+- [NamedField, name: "BNK1", table: 0, index: 256, offset: 0x2a3] -> [field index: 251, offset(bytes): 0x8, width(bits): 0x4, accType: Byte, lockType: NoLock, updateType: Preserve, connection: -]
+- [BankField, table: 0, index: 257, offset: 0x2a8]
| +- [NamePath, table: 0, index: 328, offset: 0x2ab] -> [namepath: "GIO0"]
| +- [NamePath, table: 0, index: 329, offset: 0x2af] -> [namepath: "BNK1"]
| +- [BytePrefix, table: 0, index: 330, offset: 0x2b3] -> [num value; dec: 0, hex: 0x0]
| +- [BytePrefix, table: 0, index: 331, offset: 0x2b5] -> [num value; dec: 49, hex: 0x31]
+- [NamedField, name: "FET0", table: 0, index: 332, offset: 0x2b9] -> [field index: 257, offset(bytes): 0x180, width(bits): 0x1, accType: Byte, lockType: Lock, updateType: WriteAsOnes, connection: -]
+- [NamedField, name: "FET1", table: 0, index: 333, offset: 0x2be] -> [field index: 257, offset(bytes): 0x181, width(bits): 0x1, accType: Byte, lockType: Lock, updateType: WriteAsOnes, connection: -]
+- [OpRegion, name: "SMBD", table: 0, index: 258, offset: 0x2c3]
| +- [NamePath, table: 0, index: 259, offset: 0x2c5] -> [namepath: "SMBD"]
| +- [BytePrefix, table: 0, index: 260, offset: 0x2c9] -> [num value; dec: 4, hex: 0x4]
| +- [WordPrefix, table: 0, index: 261, offset: 0x2ca] -> [num value; dec: 16896, hex: 0x4200]
| +- [WordPrefix, table: 0, index: 262, offset: 0x2cd] -> [num value; dec: 256, hex: 0x100]
+- [Field, table: 0, index: 263, offset: 0x2d0]
| +- [NamePath, table: 0, index: 264, offset: 0x2d4] -> [namepath: "SMBD"]
| +- [BytePrefix, table: 0, index: 265, offset: 0x2d8] -> [num value; dec: 69, hex: 0x45]
+- [NamedField, name: "SFL0", table: 0, index: 266, offset: 0x2dc] -> [field index: 263, offset(bytes): 0x0, width(bits): 0x8, accType: Buffer, accAttr: Byte, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL1", table: 0, index: 267, offset: 0x2e4] -> [field index: 263, offset(bytes): 0x8, width(bits): 0x8, accType: Buffer, accAttr: Word, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL2", table: 0, index: 268, offset: 0x2ec] -> [field index: 263, offset(bytes): 0x10, width(bits): 0x8, accType: Buffer, accAttr: Block, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL3", table: 0, index: 269, offset: 0x2f4] -> [field index: 263, offset(bytes): 0x18, width(bits): 0x8, accType: Buffer, accAttr: Quick, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL4", table: 0, index: 270, offset: 0x2fc] -> [field index: 263, offset(bytes): 0x20, width(bits): 0x8, accType: Buffer, accAttr: SendReceive, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL5", table: 0, index: 271, offset: 0x304] -> [field index: 263, offset(bytes): 0x28, width(bits): 0x8, accType: Buffer, accAttr: ProcessCall, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL6", table: 0, index: 272, offset: 0x30c] -> [field index: 263, offset(bytes): 0x30, width(bits): 0x8, accType: Buffer, accAttr: BlockProcessCall, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL7", table: 0, index: 273, offset: 0x315] -> [field index: 263, offset(bytes): 0x38, width(bits): 0x8, accType: Buffer, accAttr: Bytes(0x12), lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL8", table: 0, index: 274, offset: 0x31e] -> [field index: 263, offset(bytes): 0x40, width(bits): 0x8, accType: Buffer, accAttr: RawBytes(0x13), lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SFL9", table: 0, index: 275, offset: 0x327] -> [field index: 263, offset(bytes): 0x48, width(bits): 0x8, accType: Buffer, accAttr: RawProcessBytes(0x14), lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SF10", table: 0, index: 276, offset: 0x32f] -> [field index: 263, offset(bytes): 0x50, width(bits): 0x8, accType: Any, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SF11", table: 0, index: 277, offset: 0x337] -> [field index: 263, offset(bytes): 0x58, width(bits): 0x8, accType: Byte, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SF12", table: 0, index: 278, offset: 0x33f] -> [field index: 263, offset(bytes): 0x60, width(bits): 0x8, accType: Word, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SF13", table: 0, index: 279, offset: 0x347] -> [field index: 263, offset(bytes): 0x68, width(bits): 0x8, accType: Dword, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [NamedField, name: "SF14", table: 0, index: 280, offset: 0x34f] -> [field index: 263, offset(bytes): 0x70, width(bits): 0x8, accType: Qword, lockType: NoLock, updateType: WriteAsZeroes, connection: -]
+- [DataRegion, name: "REG0", table: 0, index: 281, offset: 0x354]
| +- [NamePath, table: 0, index: 282, offset: 0x356] -> [namepath: "REG0"]
| +- [StringPrefix, table: 0, index: 283, offset: 0x35a] -> [string value: "FOOF"]
| +- [StringPrefix, table: 0, index: 284, offset: 0x360] -> [string value: "BAR"]
| +- [StringPrefix, table: 0, index: 285, offset: 0x365] -> [string value: "BAZ"]
+- [Processor, name: "CPU0", table: 0, index: 286, offset: 0x36a]
| +- [NamePath, table: 0, index: 287, offset: 0x36d] -> [namepath: "CPU0"]
| +- [BytePrefix, table: 0, index: 288, offset: 0x371] -> [num value; dec: 1, hex: 0x1]
| +- [DwordPrefix, table: 0, index: 289, offset: 0x372] -> [num value; dec: 288, hex: 0x120]
| +- [BytePrefix, table: 0, index: 290, offset: 0x376] -> [num value; dec: 6, hex: 0x6]
| +- [ScopeBlock, table: 0, index: 291, offset: 0x377]
+- [PowerRes, name: "PWR0", table: 0, index: 292, offset: 0x377]
| +- [NamePath, table: 0, index: 293, offset: 0x37a] -> [namepath: "PWR0"]
| +- [BytePrefix, table: 0, index: 294, offset: 0x37e] -> [num value; dec: 0, hex: 0x0]
| +- [WordPrefix, table: 0, index: 295, offset: 0x37f] -> [num value; dec: 0, hex: 0x0]
| +- [ScopeBlock, table: 0, index: 296, offset: 0x381]
+- [ThermalZone, name: "TZ0_", table: 0, index: 297, offset: 0x381]
| +- [NamePath, table: 0, index: 298, offset: 0x384] -> [namepath: "TZ0_"]
| +- [ScopeBlock, table: 0, index: 299, offset: 0x388]
+- [Method, name: "FLOW", argCount: 2, table: 0, index: 300, offset: 0x388]
| +- [NamePath, table: 0, index: 301, offset: 0x38a] -> [namepath: "FLOW"]
| +- [BytePrefix, table: 0, index: 302, offset: 0x38e] -> [num value; dec: 2, hex: 0x2]
| +- [ScopeBlock, table: 0, index: 303, offset: 0x38f]
| +- [While, table: 0, index: 304, offset: 0x38f]
| | +- [LLess, table: 0, index: 334, offset: 0x391]
| | | +- [Arg0, table: 0, index: 335, offset: 0x392]
| | | +- [Arg1, table: 0, index: 336, offset: 0x393]
| | +- [ScopeBlock, table: 0, index: 337, offset: 0x394]
| | +- [Increment, table: 0, index: 338, offset: 0x394]
| | | +- [Arg0, table: 0, index: 339, offset: 0x395]
| | +- [If, table: 0, index: 340, offset: 0x396]
| | +- [LLess, table: 0, index: 341, offset: 0x398]
| | | +- [Arg0, table: 0, index: 342, offset: 0x399]
| | | +- [BytePrefix, table: 0, index: 343, offset: 0x39a] -> [num value; dec: 5, hex: 0x5]
| | +- [ScopeBlock, table: 0, index: 344, offset: 0x39c]
| | +- [Continue, table: 0, index: 345, offset: 0x39c]
| +- [Return, table: 0, index: 305, offset: 0x3ad]
| +- [Arg0, table: 0, index: 306, offset: 0x3ae]
+- [ThermalZone, name: "THRM", table: 0, index: 310, offset: 0x3b6]
+- [NamePath, table: 0, index: 311, offset: 0x3b9] -> [namepath: "THRM"]
+- [ScopeBlock, table: 0, index: 312, offset: 0x3be]
+- [Name, name: "DEF0", table: 0, index: 313, offset: 0x3be]
| +- [NamePath, table: 0, index: 314, offset: 0x3bf] -> [namepath: "DEF0"]
| +- [Ones, table: 0, index: 315, offset: 0x3c3]
+- [Method, name: "MTH0", argCount: 0, table: 0, index: 322, offset: 0x3d1]
| +- [NamePath, table: 0, index: 323, offset: 0x3d3] -> [namepath: "MTH0"]
| +- [BytePrefix, table: 0, index: 324, offset: 0x3dd] -> [num value; dec: 0, hex: 0x0]
| +- [ScopeBlock, table: 0, index: 325, offset: 0x3de]
| +- [Return, table: 0, index: 326, offset: 0x3de]
| +- [BytePrefix, table: 0, index: 327, offset: 0x3df] -> [num value; dec: 1, hex: 0x1]
+- [Name, name: "DEF1", table: 0, index: 319, offset: 0x3cb]
+- [NamePath, table: 0, index: 320, offset: 0x3cc] -> [namepath: "DEF1"]
+- [Zero, table: 0, index: 321, offset: 0x3d0]