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
|
||||
|
||||
// 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{}
|
||||
|
||||
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