mirror of
https://github.com/taigrr/gopher-os
synced 2025-01-18 04:43:13 -08:00
acpi: implement AML helpers for detecting argument types
The list of AML types is described on $p. 876 of ACPI 6.2 standard
This commit is contained in:
parent
dfaf068735
commit
d6a825fc02
133
src/gopheros/device/acpi/aml/vm_convert.go
Normal file
133
src/gopheros/device/acpi/aml/vm_convert.go
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
package aml
|
||||||
|
|
||||||
|
// valueType represents the data types that the AML interpreter can process.
|
||||||
|
type valueType uint8
|
||||||
|
|
||||||
|
// The list of supporte AML value types (see p. 876 of ACPI 6.2 standard)
|
||||||
|
const (
|
||||||
|
valueTypeUninitialized valueType = iota
|
||||||
|
valueTypeBuffer
|
||||||
|
valueTypeBufferField
|
||||||
|
valueTypeDDBHandle
|
||||||
|
valueTypeDebugObject
|
||||||
|
valueTypeDevice
|
||||||
|
valueTypeEvent
|
||||||
|
valueTypeFieldUnit
|
||||||
|
valueTypeInteger // we also treat constants as integers
|
||||||
|
valueTypeMethod
|
||||||
|
valueTypeMutex
|
||||||
|
valueTypeObjectRef
|
||||||
|
valueTypeRegion
|
||||||
|
valueTypePackage
|
||||||
|
valueTypeString
|
||||||
|
valueTypePowerResource
|
||||||
|
valueTypeProcessor
|
||||||
|
valueTypeRawDataBuffer
|
||||||
|
valueTypeThermalZone
|
||||||
|
)
|
||||||
|
|
||||||
|
// String implements fmt.Stringer for valueType.
|
||||||
|
func (vt valueType) String() string {
|
||||||
|
switch vt {
|
||||||
|
case valueTypeBuffer:
|
||||||
|
return "Buffer"
|
||||||
|
case valueTypeBufferField:
|
||||||
|
return "BufferField"
|
||||||
|
case valueTypeDDBHandle:
|
||||||
|
return "DDBHandle"
|
||||||
|
case valueTypeDebugObject:
|
||||||
|
return "DebugObject"
|
||||||
|
case valueTypeDevice:
|
||||||
|
return "Device"
|
||||||
|
case valueTypeEvent:
|
||||||
|
return "Event"
|
||||||
|
case valueTypeFieldUnit:
|
||||||
|
return "FieldUnit"
|
||||||
|
case valueTypeInteger:
|
||||||
|
return "Integer"
|
||||||
|
case valueTypeMethod:
|
||||||
|
return "Method"
|
||||||
|
case valueTypeMutex:
|
||||||
|
return "Mutex"
|
||||||
|
case valueTypeObjectRef:
|
||||||
|
return "ObjectRef"
|
||||||
|
case valueTypeRegion:
|
||||||
|
return "Region"
|
||||||
|
case valueTypePackage:
|
||||||
|
return "Package"
|
||||||
|
case valueTypeString:
|
||||||
|
return "String"
|
||||||
|
case valueTypePowerResource:
|
||||||
|
return "PowerResource"
|
||||||
|
case valueTypeProcessor:
|
||||||
|
return "Processor"
|
||||||
|
case valueTypeRawDataBuffer:
|
||||||
|
return "RawDataBuffer"
|
||||||
|
case valueTypeThermalZone:
|
||||||
|
return "ThermalZone"
|
||||||
|
default:
|
||||||
|
return "Uninitialized"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// vmTypeOf returns the type of data stored inside the supplied argument.
|
||||||
|
func vmTypeOf(ctx *execContext, arg interface{}) valueType {
|
||||||
|
// Some objects (e.g args, constEntity contents) may require to perform
|
||||||
|
// more than one pass to figure out their type
|
||||||
|
for {
|
||||||
|
switch typ := arg.(type) {
|
||||||
|
case *constEntity:
|
||||||
|
// check the value stored inside
|
||||||
|
arg = typ.val
|
||||||
|
case *Device:
|
||||||
|
return valueTypeDevice
|
||||||
|
case *Method:
|
||||||
|
return valueTypeMethod
|
||||||
|
case *bufferEntity:
|
||||||
|
return valueTypeBuffer
|
||||||
|
case *bufferFieldEntity:
|
||||||
|
return valueTypeBufferField
|
||||||
|
case *fieldUnitEntity, *indexFieldEntity:
|
||||||
|
return valueTypeFieldUnit
|
||||||
|
case *regionEntity:
|
||||||
|
return valueTypeRegion
|
||||||
|
case *objRef:
|
||||||
|
return valueTypeObjectRef
|
||||||
|
case *eventEntity:
|
||||||
|
return valueTypeEvent
|
||||||
|
case *mutexEntity:
|
||||||
|
return valueTypeMutex
|
||||||
|
case Entity:
|
||||||
|
op := typ.getOpcode()
|
||||||
|
|
||||||
|
switch op {
|
||||||
|
case opPackage:
|
||||||
|
return valueTypePackage
|
||||||
|
case opPowerRes:
|
||||||
|
return valueTypePowerResource
|
||||||
|
case opProcessor:
|
||||||
|
return valueTypeProcessor
|
||||||
|
case opThermalZone:
|
||||||
|
return valueTypeThermalZone
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check if this a local or method arg; if so we need to
|
||||||
|
// fetch the arg and check its type
|
||||||
|
if op >= opLocal0 && op <= opLocal7 {
|
||||||
|
arg = ctx.localArg[op-opLocal0]
|
||||||
|
} else if op >= opArg0 && op <= opArg6 {
|
||||||
|
arg = ctx.methodArg[op-opArg0]
|
||||||
|
} else {
|
||||||
|
return valueTypeUninitialized
|
||||||
|
}
|
||||||
|
case string:
|
||||||
|
return valueTypeString
|
||||||
|
case uint64, bool:
|
||||||
|
return valueTypeInteger
|
||||||
|
case []byte:
|
||||||
|
return valueTypeRawDataBuffer
|
||||||
|
default:
|
||||||
|
return valueTypeUninitialized
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
174
src/gopheros/device/acpi/aml/vm_convert_test.go
Normal file
174
src/gopheros/device/acpi/aml/vm_convert_test.go
Normal file
@ -0,0 +1,174 @@
|
|||||||
|
package aml
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
)
|
||||||
|
|
||||||
|
func TestValueTypeToString(t *testing.T) {
|
||||||
|
specs := map[valueType]string{
|
||||||
|
valueTypeBuffer: "Buffer",
|
||||||
|
valueTypeBufferField: "BufferField",
|
||||||
|
valueTypeDDBHandle: "DDBHandle",
|
||||||
|
valueTypeDebugObject: "DebugObject",
|
||||||
|
valueTypeDevice: "Device",
|
||||||
|
valueTypeEvent: "Event",
|
||||||
|
valueTypeFieldUnit: "FieldUnit",
|
||||||
|
valueTypeInteger: "Integer",
|
||||||
|
valueTypeMethod: "Method",
|
||||||
|
valueTypeMutex: "Mutex",
|
||||||
|
valueTypeObjectRef: "ObjectRef",
|
||||||
|
valueTypeRegion: "Region",
|
||||||
|
valueTypePackage: "Package",
|
||||||
|
valueTypeString: "String",
|
||||||
|
valueTypePowerResource: "PowerResource",
|
||||||
|
valueTypeProcessor: "Processor",
|
||||||
|
valueTypeRawDataBuffer: "RawDataBuffer",
|
||||||
|
valueTypeThermalZone: "ThermalZone",
|
||||||
|
valueTypeUninitialized: "Uninitialized",
|
||||||
|
}
|
||||||
|
|
||||||
|
for vt, exp := range specs {
|
||||||
|
if got := vt.String(); got != exp {
|
||||||
|
t.Errorf("expected valueType %d string representation to be %q; got %q", vt, exp, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestVMTypeOf(t *testing.T) {
|
||||||
|
specs := []struct {
|
||||||
|
ctx *execContext
|
||||||
|
in interface{}
|
||||||
|
expType valueType
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&constEntity{val: uint64(42)},
|
||||||
|
valueTypeInteger,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&constEntity{val: "some string"},
|
||||||
|
valueTypeString,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&Device{},
|
||||||
|
valueTypeDevice,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&Method{},
|
||||||
|
valueTypeMethod,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&bufferEntity{},
|
||||||
|
valueTypeBuffer,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&bufferFieldEntity{},
|
||||||
|
valueTypeBufferField,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&fieldUnitEntity{},
|
||||||
|
valueTypeFieldUnit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&indexFieldEntity{},
|
||||||
|
valueTypeFieldUnit,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
®ionEntity{},
|
||||||
|
valueTypeRegion,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&objRef{},
|
||||||
|
valueTypeObjectRef,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&eventEntity{},
|
||||||
|
valueTypeEvent,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&mutexEntity{},
|
||||||
|
valueTypeMutex,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&unnamedEntity{op: opPackage},
|
||||||
|
valueTypePackage,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&unnamedEntity{op: opPowerRes},
|
||||||
|
valueTypePowerResource,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&unnamedEntity{op: opProcessor},
|
||||||
|
valueTypeProcessor,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&unnamedEntity{op: opThermalZone},
|
||||||
|
valueTypeThermalZone,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&execContext{
|
||||||
|
localArg: [maxLocalArgs]interface{}{
|
||||||
|
uint64(42),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&unnamedEntity{op: opLocal0},
|
||||||
|
valueTypeInteger,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
&execContext{
|
||||||
|
methodArg: [maxMethodArgs]interface{}{
|
||||||
|
uint64(42),
|
||||||
|
"foo",
|
||||||
|
},
|
||||||
|
},
|
||||||
|
&unnamedEntity{op: opArg1},
|
||||||
|
valueTypeString,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
"foo",
|
||||||
|
valueTypeString,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
uint64(42),
|
||||||
|
valueTypeInteger,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
[]byte("some data"),
|
||||||
|
valueTypeRawDataBuffer,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
&unnamedEntity{op: opAdd},
|
||||||
|
valueTypeUninitialized,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
nil,
|
||||||
|
int64(0xbadf00d),
|
||||||
|
valueTypeUninitialized,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for specIndex, spec := range specs {
|
||||||
|
if got := vmTypeOf(spec.ctx, spec.in); got != spec.expType {
|
||||||
|
t.Errorf("[spec %d] expected to get value type %s; got %s", specIndex, spec.expType, got)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
Loading…
x
Reference in New Issue
Block a user