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