mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
acpi: implement minimal helper for reading AML operand values
The helper only supports reading a subset of the available AML operands: - constants (uint64, strings and bools; bools are auto-casted to uint64) - local and method args The implementation will recursively drill down into the operand values till it reaches a value that can be mapped to a Go uint64 or string type. For example, if arg0 contains a constant with the value "foo", vmRead will recurse into the arg0 value and return "foo"
This commit is contained in:
parent
fd2f4a72ad
commit
1a2d075aa2
@ -34,7 +34,8 @@ type execContext struct {
|
|||||||
ctrlFlow ctrlFlowType
|
ctrlFlow ctrlFlowType
|
||||||
|
|
||||||
// retVal holds the return value from a method if ctrlFlow is set to
|
// retVal holds the return value from a method if ctrlFlow is set to
|
||||||
// the value ctrlFlowTypeFnReturn.
|
// the value ctrlFlowTypeFnReturn or the intermediate value of an AML
|
||||||
|
// opcode execution.
|
||||||
retVal interface{}
|
retVal interface{}
|
||||||
|
|
||||||
vm *VM
|
vm *VM
|
||||||
|
35
src/gopheros/device/acpi/aml/vm_load_store.go
Normal file
35
src/gopheros/device/acpi/aml/vm_load_store.go
Normal file
@ -0,0 +1,35 @@
|
|||||||
|
package aml
|
||||||
|
|
||||||
|
// vmLoad returns the value contained inside arg. To obtain the actual stored
|
||||||
|
// value vmLoad will automatically peek into const entities and lookup
|
||||||
|
// local/global args.
|
||||||
|
func vmLoad(ctx *execContext, arg interface{}) (interface{}, *Error) {
|
||||||
|
// We need to keep evaluating types till we reach a type that can be
|
||||||
|
// returned. For example, a local arg may contain a const entity for
|
||||||
|
// which we want to fetch the contained value.
|
||||||
|
for {
|
||||||
|
switch typ := arg.(type) {
|
||||||
|
case *constEntity:
|
||||||
|
arg = typ.val
|
||||||
|
case Entity:
|
||||||
|
op := typ.getOpcode()
|
||||||
|
switch {
|
||||||
|
case opIsLocalArg(op):
|
||||||
|
arg = ctx.localArg[op-opLocal0]
|
||||||
|
case opIsMethodArg(op):
|
||||||
|
arg = ctx.methodArg[op-opArg0]
|
||||||
|
default:
|
||||||
|
return nil, &Error{message: "readArg: unsupported entity type: " + op.String()}
|
||||||
|
}
|
||||||
|
case bool:
|
||||||
|
// Convert boolean results to ints so they can be used
|
||||||
|
// by the ALU comparators.
|
||||||
|
if typ {
|
||||||
|
return uint64(1), nil
|
||||||
|
}
|
||||||
|
return uint64(0), nil
|
||||||
|
default:
|
||||||
|
return typ, nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
81
src/gopheros/device/acpi/aml/vm_load_store_test.go
Normal file
81
src/gopheros/device/acpi/aml/vm_load_store_test.go
Normal file
@ -0,0 +1,81 @@
|
|||||||
|
package aml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"reflect"
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestVMLoad(t *testing.T) {
|
||||||
|
specs := []struct {
|
||||||
|
ctx *execContext
|
||||||
|
argIn interface{}
|
||||||
|
valOut interface{}
|
||||||
|
err *Error
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&constEntity{val: uint64(123)},
|
||||||
|
uint64(123),
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&constEntity{val: "a string"},
|
||||||
|
"a string",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&constEntity{
|
||||||
|
val: &constEntity{val: true},
|
||||||
|
},
|
||||||
|
uint64(1),
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&constEntity{
|
||||||
|
val: &constEntity{val: false},
|
||||||
|
},
|
||||||
|
uint64(0),
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&execContext{
|
||||||
|
localArg: [maxLocalArgs]interface{}{"foo"},
|
||||||
|
},
|
||||||
|
&unnamedEntity{op: opLocal0},
|
||||||
|
"foo",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&execContext{
|
||||||
|
methodArg: [maxMethodArgs]interface{}{"bar", "foo"},
|
||||||
|
},
|
||||||
|
&unnamedEntity{op: opArg1},
|
||||||
|
"foo",
|
||||||
|
nil,
|
||||||
|
},
|
||||||
|
// Unsupported reads
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&unnamedEntity{op: opBuffer},
|
||||||
|
nil,
|
||||||
|
&Error{message: "readArg: unsupported entity type: Buffer"},
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for specIndex, spec := range specs {
|
||||||
|
got, err := vmLoad(spec.ctx, spec.argIn)
|
||||||
|
switch {
|
||||||
|
case !reflect.DeepEqual(spec.err, err):
|
||||||
|
t.Errorf("[spec %d] expected error: %v; got: %v", specIndex, spec.err, err)
|
||||||
|
case got != spec.valOut:
|
||||||
|
t.Errorf("[spec %d] expected to get value %v (type: %v); got %v (type %v)", specIndex,
|
||||||
|
spec.valOut, reflect.TypeOf(spec.valOut),
|
||||||
|
got, reflect.TypeOf(got),
|
||||||
|
)
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user